Skip to content

Fix Prime 250w charger. - #57

Merged
flip-dots merged 3 commits into
mainfrom
prime_250w_fixes
Aug 4, 2026
Merged

Fix Prime 250w charger.#57
flip-dots merged 3 commits into
mainfrom
prime_250w_fixes

Conversation

@flip-dots

Copy link
Copy Markdown
Owner

Issues were found in #51 to do with the Prime 250w charger needing a keep-alive command to be sent every 10~ seconds in order to receive telemetry. I have now obtained this device and have tested it myself and have been able to confirm that it does need this command to be sent, however the other changes to negotiation were not needed for this specific device.

This PR fixes support for this device by adding a new _keep_alive() function to the base SolixBLEDevice class which is called periodically when connected and negotiated, with this automatically stopping when disconnected.

This is currently experimental and I might end up changing things before merging (I am not sure about the interface or if it should be merged with _post_connect), but I am mostly happy with this as a solution.

@thomluther

Copy link
Copy Markdown

Hi @flip-dots

With MQTT, the A2345 has not only the realtime trigger that runs only about 8-10 seconds with a subset of telemetry, there is also a status request command that triggers only a single but full telemetry message, containing also the live power values (more than the realtime trigger message).

If you want to automate telemetry for A2345, I suggest to investigate and use the status request rather than the realtime data, since it gives you control about the message frequency and you receive also the device settings, which are not included in the real time messages.

Example of status request 0200:

ff:09:14:00:03:00:0f:02:00:a1:01:22:fe:05:03:64:67:4e:6a:b1
15:06:12 INFO: ----------------------- Charger / A2345 / 0200 / Header ------------------------
ff 09   : 2 Byte Anker Solix message marker (supposed 'ff 09')
14 00   : 2 Byte total message length (20) in Bytes (Little Endian format)
03 00 0f: 3 Byte fixed message pattern (supposed `03 00/01 0f` for send/receive)
02 00   : 2 Byte message type pattern (varies per device model and message type)
        : 1 Byte optional message increment (  0)
-> b1 <-: XOR Checksum Byte (last message byte), Crosscheck: 00 => OK
-- Fields --|- Value (Hex/Decode Options)---------------------------------------
Fld Len Type       uIntLe/var          sIntLe         floatLe      dblLe/4int
a1   01 --    22
└->   1 unk   b'"' --> pattern_22
fe   05 03    64:67:4e:6a
└->   5 var       26468;27214      1783523172 62381741815689138600411136.000  100;103;78;106 --> msg_timestamp (2026-07-08 15:06:12)
--------------------------------------------------------------------------------

The A2345 will respond with message 0a00, example including the known decoding of the fields

----------------------- Charger / A2345 / 0a00 / Header ------------------------
ff 09   : 2 Byte Anker Solix message marker (supposed 'ff 09')
2f 01   : 2 Byte total message length (303) in Bytes (Little Endian format)
03 01 0f: 3 Byte fixed message pattern (supposed `03 00/01 0f` for send/receive)
0a 00   : 2 Byte message type pattern (varies per device model and message type)
00      : 1 Byte optional message increment (  0)
-> 96 <-: XOR Checksum Byte (last message byte), Crosscheck: 00 => OK
-- Fields --|- Value (Hex/Decode Options)---------------------------------------
Fld Len Type       uIntLe/var          sIntLe         floatLe      dblLe/4int
a1   01 --    64
└->   1 unk   b'd'
a2   03 02    7a:07
└->   3 sile             1914            1914                           122;7 --> sw_version
a3   03 02    00:00
└->   3 sile                0               0                             0;0
a4   08 04    01:20:4d:64:00:c5:00
└->   8 bin   b'\x01 Md\x00\xc5\x00' --> {'00': {'name': 'usbc_1_status', 'type': b'\x01'}, '01': {'name': 'usbc_1_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_1_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_1_power', 'type': b'\x02', 'factor': 0.01}}
a5   08 04    01:40:3a:00:00:00:00
└->   8 bin   b'\x01@:\x00\x00\x00\x00' --> {'00': {'name': 'usbc_2_status', 'type': b'\x01'}, '01': {'name': 'usbc_2_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_2_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_2_power', 'type': b'\x02', 'factor': 0.01}}
a6   08 04    01:90:13:9c:00:32:00
└->   8 bin   b'\x01\x90\x13\x9c\x002\x00' --> {'00': {'name': 'usbc_3_status', 'type': b'\x01'}, '01': {'name': 'usbc_3_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_3_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_3_power', 'type': b'\x02', 'factor': 0.01}}
a7   08 04    01:70:13:64:00:31:00
└->   8 bin   b'\x01p\x13d\x001\x00' --> {'00': {'name': 'usbc_4_status', 'type': b'\x01'}, '01': {'name': 'usbc_4_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_4_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_4_power', 'type': b'\x02', 'factor': 0.01}}
a8   08 04    00:00:00:00:00:00:00
└->   8 bin   b'\x00\x00\x00\x00\x00\x00\x00' --> {'00': {'name': 'usba_1_status', 'type': b'\x01'}, '01': {'name': 'usba_1_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usba_1_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usba_1_power', 'type': b'\x02', 'factor': 0.01}}
a9   08 04    01:70:13:00:00:00:00
└->   8 bin   b'\x01p\x13\x00\x00\x00\x00' --> {'00': {'name': 'usba_2_status', 'type': b'\x01'}, '01': {'name': 'usba_2_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usba_2_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usba_2_power', 'type': b'\x02', 'factor': 0.01}}
aa   14 04    01:00:0c:00:00:00:0c:00:00:00:58:02:00:00:00:00:00:00:02
└->  20 bin   b'\x01\x00\x0c\x00\x00\x00\x0c\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x02' --> {'00': {'name': 'usbc_1_switch', 'type': b'\x01'}, '01': {'name': 'usbc_1_start_switch', 'type': b'\x01'}, '02': {'name': 'usbc_1_start_hour', 'type': b'\x01'}, '03': {'name': 'usbc_1_start_minute', 'type': b'\x01'}, '04': {'name': 'usbc_1_start_weekdays', 'type': b'\x01'}, '05': {'name': 'usbc_1_end_switch', 'type': b'\x01'}, '06': {'name': 'usbc_1_end_hour', 'type': b'\x01'}, '07': {'name': 'usbc_1_end_minute', 'type': b'\x01'}, '08': {'name': 'usbc_1_end_weekdays', 'type': b'\x01'}, '09': {'name': 'usbc_1_timer_switch', 'type': b'\x01'}, '10': {'name': 'usbc_1_timer_seconds', 'type': b'\x03'}, '14': {'name': 'usbc_1_timer_remaining_seconds', 'type': b'\x03'}, '18': {'name': 'usbc_1_priority', 'type': b'\x01'}}
ab   14 04    01:ff:0c:00:00:ff:0c:00:00:00:58:02:00:00:00:00:00:00:02
└->  20 bin   b'\x01\xff\x0c\x00\x00\xff\x0c\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x02' --> {'00': {'name': 'usbc_2_switch', 'type': b'\x01'}, '01': {'name': 'usbc_2_start_switch', 'type': b'\x01'}, '02': {'name': 'usbc_2_start_hour', 'type': b'\x01'}, '03': {'name': 'usbc_2_start_minute', 'type': b'\x01'}, '04': {'name': 'usbc_2_start_weekdays', 'type': b'\x01'}, '05': {'name': 'usbc_2_end_switch', 'type': b'\x01'}, '06': {'name': 'usbc_2_end_hour', 'type': b'\x01'}, '07': {'name': 'usbc_2_end_minute', 'type': b'\x01'}, '08': {'name': 'usbc_2_end_weekdays', 'type': b'\x01'}, '09': {'name': 'usbc_2_timer_switch', 'type': b'\x01'}, '10': {'name': 'usbc_2_timer_seconds', 'type': b'\x03'}, '14': {'name': 'usbc_2_timer_remaining_seconds', 'type': b'\x03'}, '18': {'name': 'usbc_2_priority', 'type': b'\x01'}}
ac   14 04    01:ff:0c:00:00:ff:0c:00:00:00:58:02:00:00:00:00:00:00:01
└->  20 bin   b'\x01\xff\x0c\x00\x00\xff\x0c\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x01' --> {'00': {'name': 'usbc_3_switch', 'type': b'\x01'}, '01': {'name': 'usbc_3_start_switch', 'type': b'\x01'}, '02': {'name': 'usbc_3_start_hour', 'type': b'\x01'}, '03': {'name': 'usbc_3_start_minute', 'type': b'\x01'}, '04': {'name': 'usbc_3_start_weekdays', 'type': b'\x01'}, '05': {'name': 'usbc_3_end_switch', 'type': b'\x01'}, '06': {'name': 'usbc_3_end_hour', 'type': b'\x01'}, '07': {'name': 'usbc_3_end_minute', 'type': b'\x01'}, '08': {'name': 'usbc_3_end_weekdays', 'type': b'\x01'}, '09': {'name': 'usbc_3_timer_switch', 'type': b'\x01'}, '10': {'name': 'usbc_3_timer_seconds', 'type': b'\x03'}, '14': {'name': 'usbc_3_timer_remaining_seconds', 'type': b'\x03'}, '18': {'name': 'usbc_3_priority', 'type': b'\x01'}}
ad   14 04    01:ff:0c:00:00:ff:0c:00:00:00:58:02:00:00:00:00:00:00:01
└->  20 bin   b'\x01\xff\x0c\x00\x00\xff\x0c\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x01' --> {'00': {'name': 'usbc_4_switch', 'type': b'\x01'}, '01': {'name': 'usbc_4_start_switch', 'type': b'\x01'}, '02': {'name': 'usbc_4_start_hour', 'type': b'\x01'}, '03': {'name': 'usbc_4_start_minute', 'type': b'\x01'}, '04': {'name': 'usbc_4_start_weekdays', 'type': b'\x01'}, '05': {'name': 'usbc_4_end_switch', 'type': b'\x01'}, '06': {'name': 'usbc_4_end_hour', 'type': b'\x01'}, '07': {'name': 'usbc_4_end_minute', 'type': b'\x01'}, '08': {'name': 'usbc_4_end_weekdays', 'type': b'\x01'}, '09': {'name': 'usbc_4_timer_switch', 'type': b'\x01'}, '10': {'name': 'usbc_4_timer_seconds', 'type': b'\x03'}, '14': {'name': 'usbc_4_timer_remaining_seconds', 'type': b'\x03'}, '18': {'name': 'usbc_4_priority', 'type': b'\x01'}}
ae   14 04    01:ff:0c:00:00:ff:0c:00:00:00:58:02:00:00:00:00:00:00:00
└->  20 bin   b'\x01\xff\x0c\x00\x00\xff\x0c\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x00' --> {'00': {'name': 'usba_switch', 'type': b'\x01'}, '01': {'name': 'usba_start_switch', 'type': b'\x01'}, '02': {'name': 'usba_start_hour', 'type': b'\x01'}, '03': {'name': 'usba_start_minute', 'type': b'\x01'}, '04': {'name': 'usba_start_weekdays', 'type': b'\x01'}, '05': {'name': 'usba_end_switch', 'type': b'\x01'}, '06': {'name': 'usba_end_hour', 'type': b'\x01'}, '07': {'name': 'usba_end_minute', 'type': b'\x01'}, '08': {'name': 'usba_end_weekdays', 'type': b'\x01'}, '09': {'name': 'usba_timer_switch', 'type': b'\x01'}, '10': {'name': 'usba_timer_seconds', 'type': b'\x03'}, '14': {'name': 'usba_timer_remaining_seconds', 'type': b'\x03'}, '18': {'name': 'usba_priority', 'type': b'\x01'}}
af   06 04    03:7c:14:ae:05
└->   6 bin   b'\x03|\x14\xae\x05' --> {'00': [{'name': 'clock_settings', 'mask': 255}, {'name': 'clock_switch', 'mask': 128}, {'name': 'holiday_switch', 'mask': 64}], '01': {'name': 'theme_id', 'type': b'\x03', 'signed': False}}
b0   02 01    01
└->   2 ui                  1               1 --> display_timeout_mode
b1   02 01    02
└->   2 ui                  2               2 --> usage_mode
b2   03 04    00:00
└->   3 bin   b'\x00\x00'
b3   02 01    55
└->   2 ui                 85              85 --> display_brightness
b4   02 01    00
└->   2 ui                  0               0 --> knob_mode
b5   02 01    01
└->   2 ui                  1               1 --> clock_mode
b6   02 01    01
└->   2 ui                  1               1 --> unknown_b6
b7   03 02    ff:02
└->   3 sile              767             767                           255;2
b8   08 04    00:00:00:00:00:00:ff
└->   8 bin   b'\x00\x00\x00\x00\x00\x00\xff' --> {'00': {'name': 'custom_profile_number', 'type': b'\x01'}, '01': {'name': 'auto_exit_switch', 'type': b'\x01'}, '02': {'name': 'custom_usb_c1_power_limit', 'type': b'\x01'}, '03': {'name': 'custom_usb_c2_power_limit', 'type': b'\x01'}, '04': {'name': 'custom_usb_c3_power_limit', 'type': b'\x01'}, '05': {'name': 'custom_usb_c4_power_limit', 'type': b'\x01'}, '06': {'name': 'custom_usb_a_power_limit', 'type': b'\x01'}}
b9   06 04    08:00:17:01:7f
└->   6 bin   b'\x08\x00\x17\x01\x7f' --> {'00': {'name': 'clock_display_start_hour', 'type': b'\x01'}, '01': {'name': 'clock_display_start_minute', 'type': b'\x01'}, '02': {'name': 'clock_display_end_hour', 'type': b'\x01'}, '03': {'name': 'clock_display_end_minute', 'type': b'\x01'}, '04': {'name': 'clock_display_weekdays', 'type': b'\x01'}}
ba   0d 04    3b:00:00:3b:00:00:3b:00:00:3b:00:00
└->  13 bin   b';\x00\x00;\x00\x00;\x00\x00;\x00\x00' --> {'00': {'name': 'custom_usb_c1_protocols', 'type': b'\x04', 'length': 1, 'state_converter': <function <lambda> at 0x7b88bf2b1fe0>}, '03': {'name': 'custom_usb_c2_protocols', 'type': b'\x04', 'length': 1, 'state_converter': <function <lambda> at 0x7b88bf2b2090>}, '06': {'name': 'custom_usb_c3_protocols', 'type': b'\x04', 'length': 1, 'state_converter': <function <lambda> at 0x7b88bf2b2140>}, '09': {'name': 'custom_usb_c4_protocols', 'type': b'\x04', 'length': 1, 'state_converter': <function <lambda> at 0x7b88bf2b21f0>}}
bb   02 01    01
└->   2 ui                  1               1
bc   02 01    01
└->   2 ui                  1               1
bd   11 04    00:00:00:00:fa:ff:fb:ff:00:00:00:00:00:00:00:00
└->  17 bin   b'\x00\x00\x00\x00\xfa\xff\xfb\xff\x00\x00\x00\x00\x00\x00\x00\x00'
fe   05 03    0a:5b:56:69
└->   5 var       23306;26966      1767267082 16196252825932032387317760.000    10;91;86;105 --> msg_timestamp (2026-01-01 11:31:22)
--------------------------------------------------------------------------------

Example of 0303 real time message, only showing a subset of fields (including decoding):

----------------------- Charger / A2345 / 0303 / Header ------------------------
ff 09   : 2 Byte Anker Solix message marker (supposed 'ff 09')
63 00   : 2 Byte total message length (99) in Bytes (Little Endian format)
03 01 0f: 3 Byte fixed message pattern (supposed `03 00/01 0f` for send/receive)
03 03   : 2 Byte message type pattern (varies per device model and message type)
        : 1 Byte optional message increment (  0)
-> 50 <-: XOR Checksum Byte (last message byte), Crosscheck: 00 => OK
-- Fields --|- Value (Hex/Decode Options)---------------------------------------
Fld Len Type       uIntLe/var          sIntLe         floatLe      dblLe/4int
a1   01 --    34
└->   1 unk   b'4'
a2   08 04    01:30:4d:64:00:c5:00
└->   8 bin   b'\x010Md\x00\xc5\x00' --> {'00': {'name': 'usbc_1_status', 'type': b'\x01'}, '01': {'name': 'usbc_1_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_1_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_1_power', 'type': b'\x02', 'factor': 0.01}}
a3   08 04    01:40:3a:00:00:00:00
└->   8 bin   b'\x01@:\x00\x00\x00\x00' --> {'00': {'name': 'usbc_2_status', 'type': b'\x01'}, '01': {'name': 'usbc_2_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_2_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_2_power', 'type': b'\x02', 'factor': 0.01}}
a4   08 04    01:90:13:00:00:00:00
└->   8 bin   b'\x01\x90\x13\x00\x00\x00\x00' --> {'00': {'name': 'usbc_3_status', 'type': b'\x01'}, '01': {'name': 'usbc_3_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_3_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_3_power', 'type': b'\x02', 'factor': 0.01}}
a5   08 04    01:78:13:00:00:00:00
└->   8 bin   b'\x01x\x13\x00\x00\x00\x00' --> {'00': {'name': 'usbc_4_status', 'type': b'\x01'}, '01': {'name': 'usbc_4_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usbc_4_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usbc_4_power', 'type': b'\x02', 'factor': 0.01}}
a6   08 04    00:00:00:00:00:00:00
└->   8 bin   b'\x00\x00\x00\x00\x00\x00\x00' --> {'00': {'name': 'usba_1_status', 'type': b'\x01'}, '01': {'name': 'usba_1_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usba_1_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usba_1_power', 'type': b'\x02', 'factor': 0.01}}
a7   08 04    00:00:00:00:00:00:00
└->   8 bin   b'\x00\x00\x00\x00\x00\x00\x00' --> {'00': {'name': 'usba_2_status', 'type': b'\x01'}, '01': {'name': 'usba_2_voltage', 'type': b'\x02', 'factor': 0.001}, '03': {'name': 'usba_2_current', 'type': b'\x02', 'factor': 0.001}, '05': {'name': 'usba_2_power', 'type': b'\x02', 'factor': 0.01}}
a8   11 04    00:00:00:00:fa:ff:fb:ff:00:00:00:00:00:00:00:00
└->  17 bin   b'\x00\x00\x00\x00\xfa\xff\xfb\xff\x00\x00\x00\x00\x00\x00\x00\x00' --> {'00': {'name': 'unknown_a8_00_01', 'type': b'\x02'}, '01': {'name': 'unknown_a8_01_02', 'type': b'\x02'}, '02': {'name': 'unknown_a8_02_03', 'type': b'\x02'}, '03': {'name': 'unknown_a8_03', 'type': b'\x01'}}
fe   05 03    32:5a:56:69
└->   5 var       23090;26966      1767266866 16196003794887037308370944.000    50;90;86;105 --> msg_timestamp (2026-01-01 11:27:46)
--------------------------------------------------------------------------------

@flip-dots

Copy link
Copy Markdown
Owner Author

@thomluther good to know, I might end up implementing that in future but at the moment its not easily possible due to the issues of decoding telemetry above a certain size that are split across payloads as the newer prime style devices are a bit wacky in that department (they only sometimes encode information about if a packet is fragmented rather than always with the Solix style), but after that’s sorted out it should be possible.

@pkolbus

pkolbus commented Aug 3, 2026

Copy link
Copy Markdown

This PR is working for mine as well. (A2345 firmware 2.1.1.6, for the record)

(Edit to add): Although I am seeing sensor updates, I am also seeing log messages that are not raised with the #51 stack, including...

2026-08-03 19:57:48.103 ERROR (MainThread) [SolixBLE.prime_device] Failed to validate authenticity of payload, decoding anyway...
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/SolixBLE/prime_device.py", line 153, in _decrypt_payload
    return cipher.decrypt_and_verify(encrypted_payload, mac)
           ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/Crypto/Cipher/_mode_gcm.py", line 567, in decrypt_and_verify
    self.verify(received_mac_tag)
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/Crypto/Cipher/_mode_gcm.py", line 508, in verify
    raise ValueError("MAC check failed")
ValueError: MAC check failed
2026-08-03 19:57:48.104 ERROR (MainThread) [SolixBLE.device] Error extracting param_data (id=5b) (len=182) from '1f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8' (len=173) at index 173. We extracted: '1f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8' but expected 9 more bytes!
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/SolixBLE/device.py", line 443, in _verbose_pop
    new_bytes = new_bytes + bytes([data.pop(0)])
                                   ~~~~~~~~^^^
IndexError: pop from empty bytearray
2026-08-03 19:57:48.104 ERROR (MainThread) [SolixBLE.device] Unexpected end of packet! Data may be missing or invalid! Extracted so far: '{'ed': 'e9d073b65d927d1352adf1944ea588a91899aa76ea472a7083e971d75662562ba6ea9a8f294f5dbe6058928b69ae81359c59'}'. Payload: 'ed32e9d073b65d927d1352adf1944ea588a91899aa76ea472a7083e971d75662562ba6ea9a8f294f5dbe6058928b69ae81359c595bb61f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8'

@flip-dots

Copy link
Copy Markdown
Owner Author

This PR is working for mine as well. (A2345 firmware 2.1.1.6, for the record)

(Edit to add): Although I am seeing sensor updates, I am also seeing log messages that are not raised with the #51 stack, including...

2026-08-03 19:57:48.103 ERROR (MainThread) [SolixBLE.prime_device] Failed to validate authenticity of payload, decoding anyway...
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/SolixBLE/prime_device.py", line 153, in _decrypt_payload
    return cipher.decrypt_and_verify(encrypted_payload, mac)
           ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/Crypto/Cipher/_mode_gcm.py", line 567, in decrypt_and_verify
    self.verify(received_mac_tag)
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/Crypto/Cipher/_mode_gcm.py", line 508, in verify
    raise ValueError("MAC check failed")
ValueError: MAC check failed
2026-08-03 19:57:48.104 ERROR (MainThread) [SolixBLE.device] Error extracting param_data (id=5b) (len=182) from '1f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8' (len=173) at index 173. We extracted: '1f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8' but expected 9 more bytes!
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/SolixBLE/device.py", line 443, in _verbose_pop
    new_bytes = new_bytes + bytes([data.pop(0)])
                                   ~~~~~~~~^^^
IndexError: pop from empty bytearray
2026-08-03 19:57:48.104 ERROR (MainThread) [SolixBLE.device] Unexpected end of packet! Data may be missing or invalid! Extracted so far: '{'ed': 'e9d073b65d927d1352adf1944ea588a91899aa76ea472a7083e971d75662562ba6ea9a8f294f5dbe6058928b69ae81359c59'}'. Payload: 'ed32e9d073b65d927d1352adf1944ea588a91899aa76ea472a7083e971d75662562ba6ea9a8f294f5dbe6058928b69ae81359c595bb61f40ee48dae879932135fb2ac30e5a2c10af4a0e6fbbb34d9aac8c4639efdd1a2206a94fe8480c94cf72ce46aa89890a86ee4048dddd3d4a41439476ff0bb57ddb265225d54c93acf401259301d38543a4c8cb0652e1189bbfdb79500f2bef2cee6a7345878ac6b78e8be7c5013e30763673ee8fe2df4d2b39255335b14ad87e7961d3fa93d82d03038af26d191d9e6896fe24cf7d511809569a6058012ed34318983645089f2a16a30ebf8ac8'

I am seeing the same thing during the negotiation phase, my guess is its the pesky fragmentation causing issues again, but since that part of the negotiation is not needed to receive telemetry it can be safely ignored for now and with any luck will go away when fragmentation is fully figured out.

@flip-dots

Copy link
Copy Markdown
Owner Author

I have also been able to add support for controlling the USB outputs and setting timers. The only issues that remain are the incorrect clock/time zone, which will need to be fixed in another PR, the issues with occasionally un-parseable packets, which will also need to be fixed in another PR, and a weird issue where the USB C ports report 0.02A of current with nothing plugged in, which I think is fine for now.

@flip-dots
flip-dots merged commit dcaa318 into main Aug 4, 2026
3 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants