Automatically convert hex code to tex via python scrip and automation

Hi everyone! I want to apologize right away, I am not a programmer, I am a radio-electronic engineer. And my native language is not English =(

The situation is like this - I have a TTGO SIM800L (it is an ESP32 module + GSM modem that can receive/send SMS, calls and USSD requests) connected via ESPHome, fully configured and working, among all sensors I have “Ussd Code”, I want to use it to get the balance of the personal account, but I get hex code. And here I experienced difficulties in converting this code to text. I have a programmer friend who doesn’t know what HA is at all, but he wrote me a little code in python to convert it to text and it works fine if I run it in my terminal.

Here it is:

def ucs2_to_utf8(s):
    result = ""
    i = 0
    while i < len(s) - 3:
        code = ((int(s[i:i+2], 16) << 8) +
                int(s[i+2:i+4], 16))
        result += chr(code)
        i += 4
    return result

hex_string = "hex code from operator"
decoded_string = ucs2_to_utf8(hex_string)
print(decoded_string)

But then I am faced with the problem of automating this code, so that the state of the original sensor is run through this code and shown in a new specially created text sensor.

I realize that I need to use Python Scripts and call this code through it, but I don’t know the syntax and how it all works. =(

Maybe I’m wrong and there are easier ways to do this, but I’m hanging on to this code because at the very least it works!

I will be grateful for any help and advice. Thanks!

P.S. I can share a working code for TTGO SIM800L if anyone is interested.

I’m familiar with the encodings used.

I’m not in front of a PC now, but I think we can do this with some Jinja and a template sensor. Bit shifts at the same as multiplying by powers of 2.

What is your source sensor entity ID) with an example value?

I can try to write you a template tomorrow, unless someone else comes ong before that.

I actually have no Python scripts in my HA setup. If you want to pursue that route, you will need to access the raw sensor value via the hass object and your script will need to return a value (response_data). You can then call your script from an automation in HA, extract the response data and set an input_text helper.

Or you can make a trigger-based sensor like here for the weather service: Template - Home Assistant.

Oh, thank you very much for the response!

I don’t care at all how it will be done, I just proceeded from the fact that I already have some properly working code.

Source sensor ID “sensor.ttgo_sim800_ussd_code”
Example of sensor hex code: “041204300448002004310430043B0430043D0441003A00200033003500300020044004430431002E”
The correct decoded value of this code is "Ваш баланс: 350 руб. " (This is Cyrillic)
THX!

Bugger, I wrote the whole Jinja template, but then realised there’s no way to decode the new “byte” sequence (in Python you can call .decode, but that’s not available/allowed in Jinja).

Thus, your script is then first prize.

I’ll provide mostly an outline. I haven’t used py scripts, but this should get you going. None of this has been tested.

First, make sure you put python_script: in your configuration.yaml (I don’t think it’s enabled by default if you have default_config in there). The steps are detailed here too.

Start by enabling the Python Scripts integration and create the first script.

  • Add to configuration.yaml: python_script:
  • Create the folder <config>/python_scripts
  • Create a file <config>/python_scripts/hello_world.py in the folder and give it this content:

Choose a name for your script and put this content in it. Let’s call it decode_balance.py:

def ucs2_to_utf8(s):
    result = ""
    i = 0
    while i < len(s) - 3:
        code = ((int(s[i:i+2], 16) << 8) +
                int(s[i+2:i+4], 16))
        result += chr(code)
        i += 4
    return result

hex_string = hass.states.get("sensor.ttgo_sim800_ussd_code")
output["decoded_string"] = ucs2_to_utf8(hex_string)

You can call it like this:

- service: python_script.decode_balance
  response_variable: decoded_string

You can use this in a trigger-based template sensor:

  - trigger:
    - platform: time_pattern
      # every 5 minutes past the hour
      hours: "*"
      minutes: "5"
    action:
      - service: python_script.decode_balance
        response_variable: decoded_string
    sensor:
      - name: SMS Balance
        unique_id: "<provide your own>"
        state: "{{ decoded_string }}"

PS: A somewhat denser version using built-ins is this, but your friend clearly understands the encodings involved.

ucs2_string = "041204300448002004310430043B0430043D0441003A00200033003500300020044004430431002E"
bytes_object = bytes.fromhex(ucs2_string)
unicode_string = bytes_object.decode('utf-16-be')  # UCS-2 is essentially UTF-16 Big Endian
utf8_string = unicode_string.encode('utf-8')