I have a hex string like “010203”
I need to treat that string as bunch of hex bytes (0x01, 0x02, 0x03), not an ACSII string.
If I use "{{ '010203' | base64_encode }}"
I get MDEwMjAz
which decodes to 303130323033
which is the ASCII
How to I do a ‘binary’ base64_encode?
Hellis81
(Hellis81)
May 19, 2025, 9:08am
2
robClark56:
‘binary’ base64_encode?
Maybe I’m just not following.
But binary is 0 and 1.
base64 means there are 64 characters in the to represent the numbers.
So what is binary base64?
Yeah - I agree. Maybe binary was not the best word.
Maybe ‘bytes’ → Base64 is a better term
petro
(Petro)
May 19, 2025, 10:53am
4
it decodes to “010203” if you use base64_decode. I think you need to come back with the correct terminology or provide the expected answer so we can reverse engineer what you really want.
EDIT: Are you saying you want 010203
to change to 0x01
0x02
0x03
?
Let me clarify again
I have a string “010203”, that represents a 3-byte array = [1,2,3]
I want to convert that to this string “AQID”
For an online equivalent:
Enter 010203 in the HEX input
yes
for another example:
Input: “0F010003” = [0x0F, 0x01, 0x00,0x03]
Output “DwEAAw==”
petro
(Petro)
May 19, 2025, 1:02pm
8
{{ (int('0F010003', base=16) | pack(">I")).decode('utf-8') | base64_encode }}
EDIT: I Had to “jump through hoops” to get this to work because the jinja functions don’t work with bytes. Kinda annoying. Might put in a PR to address that.
EDIT2: Added 2 PRs to make this easier, will be a couple months before they are merged though.
dev
← Petro31:add-fromhex-filter
opened 02:19PM - 19 May 25 UTC
## Breaking change
## Proposed change
Add fromhex filter to support … converting hex strings to bytes. Currently there is a gap in HA when converting HEX strings (common) to base64. This is typically need for remotes like broadlink and other aspects of HA that require base64 strings.
If a user attempts to convert a hex string to base64, they have to know quite a bit about encoding. [Which isn't easy](https://community.home-assistant.io/t/convert-hex-string-to-base64/892265/8).
This PR is phase2 of a 2 updates. This update specifically just allows base64_encode to accept bytes as an input.
Phase 1 -> https://github.com/home-assistant/core/pull/145227
This proposal changes this template:
```
{{ (int('0F010003', base=16) | pack(">I")).decode('utf-8') | base64_encode }}
```
To this:
```
{{ '0F010003' | fromhex | base64_encode }}
```
Which will easily work with hex strings.
## Type of change
- [ ] Dependency upgrade
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New integration (thank you!)
- [x] New feature (which adds functionality to an existing integration)
- [ ] Deprecation (breaking change to happen in the future)
- [ ] Breaking change (fix/feature causing existing functionality to break)
- [ ] Code quality improvements to existing code or addition of tests
## Additional information
- This PR fixes or closes issue: fixes #
- This PR is related to issue:
- Link to documentation pull request: https://github.com/home-assistant/home-assistant.io/pull/39096
- Link to developer documentation pull request:
- Link to frontend pull request:
## Checklist
- [x] The code change is tested and works locally.
- [x] Local tests pass. **Your PR cannot be merged unless tests pass**
- [x] There is no commented out code in this PR.
- [x] I have followed the [development checklist][dev-checklist]
- [x] I have followed the [perfect PR recommendations][perfect-pr]
- [x] The code has been formatted using Ruff (`ruff format homeassistant tests`)
- [x] Tests have been added to verify that the new code works.
If user exposed functionality or configuration variables are added/changed:
- [x] Documentation added/updated for [www.home-assistant.io][docs-repository]
If the code communicates with devices, web services, or third-party tools:
- [ ] The [manifest file][manifest-docs] has all fields filled out correctly.
Updated and included derived files by running: `python3 -m script.hassfest`.
- [ ] New or updated dependencies have been added to `requirements_all.txt`.
Updated by running `python3 -m script.gen_requirements_all`.
- [ ] For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
To help with the load of incoming pull requests:
- [ ] I have reviewed two other [open pull requests][prs] in this repository.
[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-desc+review%3Anone+-status%3Afailure
[dev-checklist]: https://developers.home-assistant.io/docs/development_checklist/
[manifest-docs]: https://developers.home-assistant.io/docs/creating_integration_manifest/
[quality-scale]: https://developers.home-assistant.io/docs/integration_quality_scale_index/
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr
dev
← Petro31:update-base64-encode-bytes
opened 02:05PM - 19 May 25 UTC
## Breaking change
## Proposed change
Allow base64_encode to support… bytes. Currently there is a gap in HA when converting HEX strings (common) to base64. This is typically need for remotes like broadlink and other aspects of HA that require base64 strings.
If a user attempts to convert a hex string to base64, they have to know quite a bit about encoding. [Which isn't easy.](https://community.home-assistant.io/t/convert-hex-string-to-base64/892265/8)
This PR is phase1 of a 2 updates. This update specifically just allows base64_encode to accept bytes as an input.
Phase 2 -> https://github.com/home-assistant/core/pull/145229
This proposal changes this template:
```
{{ (int('0F010003', base=16) | pack(">I")).decode('utf-8') | base64_encode }}
```
To this:
```
{{ '0F010003' | fromhex | base64_encode }}
```
Which will easily work with hex strings.
## Type of change
- [ ] Dependency upgrade
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New integration (thank you!)
- [x] New feature (which adds functionality to an existing integration)
- [ ] Deprecation (breaking change to happen in the future)
- [ ] Breaking change (fix/feature causing existing functionality to break)
- [ ] Code quality improvements to existing code or addition of tests
## Additional information
- This PR fixes or closes issue: fixes #
- This PR is related to issue:
- Link to documentation pull request: https://github.com/home-assistant/home-assistant.io/pull/39097
- Link to developer documentation pull request:
- Link to frontend pull request:
## Checklist
- [x] The code change is tested and works locally.
- [x] Local tests pass. **Your PR cannot be merged unless tests pass**
- [x] There is no commented out code in this PR.
- [x] I have followed the [development checklist][dev-checklist]
- [x] I have followed the [perfect PR recommendations][perfect-pr]
- [x] The code has been formatted using Ruff (`ruff format homeassistant tests`)
- [x] Tests have been added to verify that the new code works.
If user exposed functionality or configuration variables are added/changed:
- [x] Documentation added/updated for [www.home-assistant.io][docs-repository]
If the code communicates with devices, web services, or third-party tools:
- [ ] The [manifest file][manifest-docs] has all fields filled out correctly.
Updated and included derived files by running: `python3 -m script.hassfest`.
- [ ] New or updated dependencies have been added to `requirements_all.txt`.
Updated by running `python3 -m script.gen_requirements_all`.
- [ ] For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
To help with the load of incoming pull requests:
- [ ] I have reviewed two other [open pull requests][prs] in this repository.
[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-desc+review%3Anone+-status%3Afailure
[dev-checklist]: https://developers.home-assistant.io/docs/development_checklist/
[manifest-docs]: https://developers.home-assistant.io/docs/creating_integration_manifest/
[quality-scale]: https://developers.home-assistant.io/docs/integration_quality_scale_index/
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr
which will result in a “simple” template: {{ '0F010003' | fromhex | base64_encode }}
1 Like
Oh!
Thanks. Will give it a try tomorrow. Getting late here.
How do I use your answer to encode a hex string that is an input field to a script
Assume {{ command }} is a string like '0F010003'
sequence:
- variables:
command64: >-
"{{ (int( "{{ command }}", base=16) | pack('>I')).decode('utf-8') |
base64_encode }}"
Thats is not working - I think because I have nested {{ {{ }} }}
petro
(Petro)
May 19, 2025, 3:41pm
11
sequence:
- variables:
command64: >-
{{ (int(command, base=16) | pack('>I')).decode('utf-8') | base64_encode }}
I am having problems when running this script.
Here is the full script.
The error is: failed to perform the action script/settempalarm. UndefinedError: 'None' has no attribute 'decode'
sequence:
- variables:
command64: >-
{{ (int(command, base=16) | pack('>I')).decode('utf-8') |
base64_encode }}
- action: mqtt.publish
metadata: {}
data:
qos: "0"
retain: false
topic: application/{{ applicationID }}/device/{{ device }}/command/down
payload: >-
{ "devEui":"{{ device }}","confirmed": false,"fPort": 1,"data":"{{
command64 }}" }
fields:
device:
selector:
text: null
name: device
description: DevEUI
required: true
applicationID:
selector:
text: null
name: applicationID
description: Chirpstack Application ID
required: true
command:
selector:
text: {}
name: Command
description: Hex String
required: true
alias: SendCommand
description: Sends MQTT message to the Gateway with a downlink command
petro
(Petro)
May 19, 2025, 3:58pm
13
Are you putting in a command when you test it? That error tells me you aren’t.
Yes: command is set (and is “AA01000200150020”)
If I edit the code as below, all runs fine and I get an MQTT Publish
sequence:
- variables:
command64: "{{ command }}"
- action: mqtt.publish
metadata: {}
data:
qos: "0"
retain: false
topic: application/{{ applicationID }}/device/{{ device }}/command/down
payload: >-
{ "devEui":"{{ device }}","confirmed": false,"fPort": 1,"data":"{{
command64 }}" }
fields:
device:
selector:
text: null
name: device
description: DevEUI
required: true
applicationID:
selector:
text: null
name: applicationID
description: Chirpstack Application ID
required: true
command:
selector:
text: {}
name: Command
description: Hex String
required: true
alias: SendCommand
description: Sends MQTT message to the Gateway with a downlink command
MQTT:
{
"devEui": "a840414e4f5cae3d",
"confirmed": false,
"fPort": 1,
"data": "AA01000200150020"
}
petro
(Petro)
May 19, 2025, 4:19pm
15
Try this then, FYI you swapped the struct from 4 bytes to 8, which is why it was failing. I.e. Your original question used 3 bytes (010203
), your example had 4 ( 0F010003
). Now you’re trying to pass 8 (AA01000200150020
)in your last post.
sequence:
- variables:
command64: >
{{ (int(command, base=16) | pack('>Q')).decode('utf-16') | base64_encode }}
- action: mqtt.publish
metadata: {}
data:
qos: "0"
retain: false
topic: application/{{ applicationID }}/device/{{ device }}/command/down
payload: >-
{ "devEui":"{{ device }}","confirmed": false,"fPort": 1,"data":"{{
command64 }}" }
fields:
device:
selector:
text: null
name: device
description: DevEUI
required: true
applicationID:
selector:
text: null
name: applicationID
description: Chirpstack Application ID
required: true
command:
selector:
text: {}
name: Command
description: Hex String
required: true
alias: SendCommand
description: Sends MQTT message to the Gateway with a downlink command
EDIT: If that isn’t right, then changes need to happen.
I will not know in advance how long the input hex string is.
I will try with your change … but what if I have an even longer string (say 20 hex bytes?)
petro
(Petro)
May 19, 2025, 4:36pm
17
Do you have a link to the documentation for whatever device we are dealing with here?
petro
(Petro)
May 19, 2025, 6:34pm
18
HA is not currently equipped with the ability to do this. You’ll have to wait until my 2 PRs above are in the software.
Thanks for all your help so far.
Regarding the longer input strings: When encoding HEX → base64, I might try chunking the input into 3-byte chunks (which will always give 4 base64 chars) and then join the chunks together.
Question: I have the option of NOT using a string that represents the input bytes; I could use a byte array instead. I wonder if that makes the code easier to handle. I will do some checks.
You asked what equipment I am dealing with and a link to the docs.
The project is LoRaWAN. I have this common LoRaWAN gateway .
This device uses MQTT to:
report remote sensor data (that part is easy)
receive commands to be forwarded to the remote sensor
The sending commands
documentation is here
This is the important part of that MQTT message:
"data": "...." // base64 encoded data (plaintext, will be encrypted by ChirpStack)
And the ‘data’ is a bunch of bytes that is a command. For example the command to
turn on alarm mode
Check temp every 2 mins
set the alarm temp range as being outside 16C and 32 C is AA01000200100020
Another command is Reset
= 04FF
I will experiment with these possible solutions:
Converting byte-array instead of string
3-byte chunking
Just realised a problem with your suggested code:
{{ (int('AA010003', base=16) | pack(">I")).decode('utf-8') | base64_encode }}
Results in
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 0: invalid start byte
Indeed 0xAA is not a valid utf-8 character.
Is there a different .decode(xx)
option?
I seached but had trouble finding the documentation on the decode filter