PowerXtreme / Emergoplus BLE Battery

Hi there,

I own a battery with built-in Bluetooth which shows:


I would love to see that info in HA. I have ESPHome bluetooth proxy in use for other devices.

Who can help me create this?

I had some contact on Discord and got some tips but none led to actual steps forward.

This is the documentation available:

I have some “scanning” info from the android app “nRF Connect”:






Did you solve this issue?

No, not, no, not.

That’s a pitty. Same issue.

I am also in the same boat, i guess everyone is still stuck on this ?

@marcelt @sender , looks like i am getting somewhere.
I have spent a few days digging myself trough a decompiled version of their android APK as their support does not seem to answer my mails.

In the case of the X210 battery next to me it is Service FFF0 amd characteristic FFF1 which is a notify service. So ui used this in esphome:

esp32_ble_tracker:
  scan_parameters: 
    duration: 10s

    

ble_client:
  - mac_address: "DC:0D:30:0C:5D:DF" # Replace with the MAC address of your BLE device
    id: my_ble_client


text_sensor:
  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service FFF0 Characteristic FFF1"
    service_uuid: 'FFF0'
    characteristic_uuid: 'FFF1'
    notify: true

this would output the data on that characteristic to the text_sensor.
Problem is, it does this only when sending a command to service: FFF0 with characteristic: FFF2. To be specific it seems to be a 0x38 that works for me (UTF-8 its a 8)

button:
  - platform: template
    name: "Send 2"
    on_press:
      then:
        - ble_client.ble_write:
            id: my_ble_client
            service_uuid: 'FFF0'
            characteristic_uuid: 'FFF2'
            value: [0x38]

this returns a string like this on the notify characteristic:
^44320000000000005034030011000800910B00000100930C8E0C950C8E0C0000000000000000000000000000000000000000000000000427

i am now writing some python to decode this into the values and just have gotten first results. I will continue with it and keep you posted.

1 Like

Wow, that looks promising!

I have it working for the most part. I only have access to X210 batteries, worked on all of them. So i am unsure about what you guys want to do. But from the code of the app it looks more or less the same, maybe the characteristic uuid’s etc are different on other devices.

You can find it two ways. connect the nRF app. Then check for the notify services and set them to “notify” by pressing the button. This will update their value once new data comes in.
Triggering the notify can be done by pressing the battery state indicator on the battery itself, (in case of the x210 at least). Or by sending a 1 to one of the other characteristics that are receive.

You want to find the long chain of bytes that come back like in the earlyer post. In my case this is Service FFF0 and characteristic FFF1

Things i have to figure out, the status things dont make sense to me yet. And when i pull new data the indicator lights for the charge state light up on the battery as well. This should not be needed :stuck_out_tongue:

Let me know if there are questions.

Edit:
i see that the nrf connect on android looks a bit different and also shows the mac adress right at the top (this is not possible on ios). I guess from the layout the 3 down arrows mean enable notify in this case, on ios its an arrow down with a line under it.

esp32_ble_tracker:
  scan_parameters: 
    duration: 300s

 

# Define the BLE client
ble_client:
  - mac_address: "DC:0D:30:0C:5D:DF" # Replace with the MAC address of your battery
    id: my_ble_client

## To find the mac adress, most easy way is to enable the part down below saying:
##   - platform: ble_scanner
##     name: "BLE Devices Scanner"     
## This will show all found BLE devices in the area with their mac adres and name if they have one in the esphome log.
## In case of a X210 battery the macs start consistently with: DC:0D:30:

            


text_sensor:
  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service FFF0 Characteristic FFF1"
    service_uuid: 'FFF0'
    characteristic_uuid: 'FFF1'
    notify: true
    id: ble_raw_data
    on_value:
      then:
        - lambda: |-
            std::string raw_data = id(ble_raw_data).state;
            if (raw_data.length() >= 38) {
              // Strip the first character '^'
              raw_data = raw_data.substr(1);

              auto char_to_int = [](char c) -> int {
                if ('0' <= c && c <= '9') {
                  return c - '0';
                } else if ('A' <= c && c <= 'F') {
                  return (c - 'A') + 10;
                } else {
                  return 0;
                }
              };

              auto asciitochar = [&](char b, char b2) -> int {
                return ((char_to_int(b) << 4) & 0xF0) + (char_to_int(b2) & 0x0F);
              };

              int voltage = (((((asciitochar(raw_data[6], raw_data[7]) << 8) + asciitochar(raw_data[4], raw_data[5])) << 8) + asciitochar(raw_data[2], raw_data[3])) << 8) + asciitochar(raw_data[0], raw_data[1]);
              int current = (((((asciitochar(raw_data[14], raw_data[15]) << 8) + asciitochar(raw_data[12], raw_data[13])) << 8) + asciitochar(raw_data[10], raw_data[11])) << 8) + asciitochar(raw_data[8], raw_data[9]);
              int soc = (asciitochar(raw_data[30], raw_data[31]) << 8) + asciitochar(raw_data[28], raw_data[29]);
              int temperature = (asciitochar(raw_data[34], raw_data[35]) << 8) + asciitochar(raw_data[32], raw_data[33]);
              int status = asciitochar(raw_data[36], raw_data[37]);
              int afe_status = asciitochar(raw_data[40], raw_data[41]);

              float temperature_celsius = (temperature - 0xAAB) / 10.0;
              float voltage_display = voltage / 1000.0;
              float current_display = current / 10.0;

              id(global_voltage) = voltage_display;
              id(global_current) = current_display;
              id(global_soc) = soc;
              id(global_temperature) = temperature_celsius;
              id(global_status) = status;
              id(global_afe_status) = afe_status;
            } else {
              ESP_LOGE("main", "Received raw data is too short.");
            }


  - platform: ble_scanner
    name: "BLE Devices Scanner"        

sensor:
  - platform: template
    name: "Battery voltage"
    unit_of_measurement: "V"
    update_interval: 30s
    accuracy_decimals: 2
    lambda: |-
      return id(global_voltage);
  - platform: template
    name: "Battery Current"
    update_interval: 30s
    unit_of_measurement: "A"
    accuracy_decimals: 1
    lambda: |-
      return id(global_current);
  - platform: template
    name: "Battery SOC"
    update_interval: 30s
    unit_of_measurement: "%"
    accuracy_decimals: 0
    lambda: |-
      return id(global_soc);
  - platform: template
    name: "Battery Temperature"
    update_interval: 30s
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    lambda: |-
      return id(global_temperature);

#Unsure about these two yet if they actually work and what they mean
  - platform: template
    name: "Battery Status"
    update_interval: 30s
    accuracy_decimals: 0
    lambda: |-
      return id(global_status);
  - platform: template
    name: "Battery AFE Status"
    update_interval: 30s
    accuracy_decimals: 0
    lambda: |-
      return id(global_afe_status);

globals:
  - id: global_voltage
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_current
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_soc
    type: int
    restore_value: no
    initial_value: '0'
  - id: global_temperature
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_status
    type: int
    restore_value: no
    initial_value: '0'
  - id: global_afe_status
    type: int
    restore_value: no
    initial_value: '0'
    

#this fetches data every minute by pushing a Number 1 to the FFF2 characteristic, causing an update on the Notify FFF1
interval:
  - interval: 1min
    then:
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 'FFF0'
          characteristic_uuid: 'FFF2'
          value: [0x31]

#this button manually fetches the data by pushing a Number 1 to the FFF2 characteristic, causing an update on the Notify FFF1
button:
  - platform: template
    name: "Force update values"
    on_press:
      then:
        - ble_client.ble_write:
            id: my_ble_client
            service_uuid: 'FFF0'
            characteristic_uuid: 'FFF2'
            value: [0x31]

1 Like

@sender @marcelt

one small change i made after loosing connection after a while:

#add under text_sensors
  - platform: template
    name: "Battery BLE connection"
    id: ble_state_sensor
    lambda: |-
      return id(ble_state);


#add to globals:
  - id: ble_connected
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: ble_state
    type: std::string
    restore_value: no
    initial_value: '"disconnected"'


esp32_ble_tracker:
  scan_parameters: 
    duration: 90s

ble_client:
  - mac_address: "" # Replace with the MAC address of your BLE device
    id: my_ble_client
    on_connect:
      then:
        - lambda: |-
            id(ble_connected) = true;
            id(ble_state) = "connected";
    on_disconnect:
      then:
        - lambda: |-
            id(ble_connected) = false;
            id(ble_state) = "reconnecting";
        - script.execute: reconnect_ble



script:
  - id: reconnect_ble
    then:
      - delay: 5s
      - ble_client.connect: my_ble_client
      - delay: 30s
      - if:
          condition:
            lambda: |-
              return !id(ble_connected);
          then:
            - script.execute: reconnect_ble

Got some running. But no result yet… All I ever received from my battery is in the top-post… I do not seem to get such a long number like you do? I have this now:

I’ll try to dig some deeper in finding that longer string nut I have no good hope.

Do you have any other tip?

btw I use the android nRF app yes…

EDIT:
Might have found some:
0x0201050302E0FF09FFFFFF30554436667D0909526F7373696E6907

from here:

But now I have another problem… Don’t know what happened But I do not see the battery at all anymore… not in nRF, not in the 2 powerxtreme apps…
Can be 2 things: broken (unlikely) or “it is connected to another app” - can i be I connected with nRF and it somehow disconnected improperly and keeps it taken?
I hope there’s some sort of timeout on it then…

Maybe your esphome device keeps connecting to it ?
BLE usually can pair only to one device at a time. As for the string you got, not sure if its the right one, but i got a totally different format after connecting to ESPhome so maybe it is.

Pfew, thats it… it’s back…

Any idea where to get the correct string in the app then?

Maybe here?

Did you get this in ESPhome or nRF?

That string in the example is in ESPHome.
Is the string you get a notification or is it if you press one of the arrows, in my case this string comes from one of the notify characteristics.

I just got back home, i will have a quick look what happens with the string you provided, but i noticed its totally different format in nRF and Esphome, with only the one in esphome giving right results. (nRF is hex format, and esphome uft-8 i think)

What you might try, find all the notify characteristics in nRF and make a sensor out of all of them with this (this is all notify characteristics i see in your screenshots):

text_sensor:
  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service dump 1"
    service_uuid: 'f000ffc0-0451-4000-b000-000000000000'
    characteristic_uuid: 'f000ffc1-0451-4000-b000-000000000000'
    notify: true
  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service dump 2"
    service_uuid: 'f000ffc0-0451-4000-b000-000000000000'
    characteristic_uuid: 'f000ffc2-0451-4000-b000-000000000000'
    notify: true
  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service dump 3"
    service_uuid: 'FFE0'
    characteristic_uuid: 'FFE4'
    notify: true

so without the internal part unlike in my full example, so you can see it in home assistant.

I am not sure if your battery has the button on it with lights for the current state of charge, when i connect to my battery and have the notify services enabled pressing the button triggers the message on the notify service as well.

Where do I press what? The button in esphome?

No i mean in the nRF app, so did you get this value when pressing on one of the arrows, or was it a notify update after subscribing to it in the nRF app, i think to subscribe to a notify service its the 3 arrows down button.

But i would try what i posted in my earlyer post with the 3 text_sensors.

Will do this.

But what arrows do you mean? On the battery? I dont have that… only a “power” button, which is not a power button :sweat_smile:

So only the "BLE Service dump 3" gives an output… and a lot! - so much it keeps crashing the connection with HA. Can only get logging from esp directly.

see below:
https://dpaste.org/ZXbjh

Not sure if it helps, but these are only the values of "BLE Service dump 3" it gives:

'^2134000000000000'
'3075000001005600'
'650B00800C94'
'040D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0335'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'040D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2134000000000000'
'3075000001005600'
'650B00800C9l'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000p00000'
'0000000000000000'
'0336'
'^2134000`00000000'
'3075000001005600'
'650\x8200800C94'
'050D090D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0335'
'^2p34000000000000'
'3075000001005600'
'650B008`0C94'
'050D090D0C0D060D'
'00000000000000`0'
'0000000000000000'
'0000000000000000'
'0334'
'^2134000000000000'
'3075000001`05600'
'650B00800C94'
'050D0A0D0C0D060D'
'000000000`000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'307500000100560`'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000`00000000'
'0336'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^20340000`0000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0333'
'^1F3400000000000`'
'3075000001005600'
'650B00800C94'
'050D090D0B0D06`D'
'00000000000p0000'
'0000000000000000'
'0000000000000000'
'0332'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D09pD0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'p32E'
'^1D34000000000000'
'30o5000001005600'
'650B00800C94'
'020D050D070D030D'
'0000000000000000'
'0000`00000000000'
'0000000000000000'
'0322'
'^113l000000000000'
'3075000001005600'
'650B00800C94'
'020D050D070D030D'
'0000000000`00000'
'0000000000000000'
'0000000000000000'
'03q6'
'^1234000000000000'
'3075000001005600'
'6e0B00800C94'
'020D060D070D030D'
'00000000000`0000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D0s0D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D07`D030D'
'0000000000000000'
'0000000000000000'
'00000p0000000000'
'0318'
'^123400`000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000`00000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'00000000000000p0'
'0000`00000000000'
'0318'
'^1234000000000`0`'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0322'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D0r0D0A0D050D'
'0000000000000000'
'00`0000000000000'
'0000000000000000'
'032C'
'^2434000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0C0D070D'
'0000000000000`00'
'0000000000000000'
'0000000000000000'
'033C'
'^2434000000000000'
'3075000001005600'
'650B0`800C94'
'05pD0B0D0C0D070D'
'00000`0000000000'
'0000000000000000'
'0000000000000000'
'033B'
'^2334000000000000'
'3075000001`05600'
'650B00800C94'
'050D0B0D0C0D070D'
'000000000`000000'
'0000000000000000'
'0000000000000000'
'033A'
'^2234000000000000'
'30o5000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2b34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'000000p000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'3075`00001005600'
'650B00800C94'
'05`D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'000000000000`000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B0`800C94'
'050D0A0D0C0D070D'
'000000000000000`'
'0000p00000000000'
'0000000000000000'
'0338'
'^223t000000000000'
'3075000001005600'
'650B00800C94'
'`50D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2534000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0D0D070D'
'00000000000`0000'
'0000000000000000'
'0000000000000000'
'033E'
'^2734000000000000'
'3075`00001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0342'
'^2734000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'00000000p0000000'
'0000000000000000'
'0000000000000000'
'0342'
'^2734000000000000'
'g075000001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'0000000000000000'
'000000000000000p'
'0000000000000000'
'0342'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'06`D0C0D0D0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'^2834000`00000000'
'3075000001005600'
'650B00800C94'
'060D0\x830D0D0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'\xbe2834000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0E0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'060D0C0D0E0D0A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0346'
'^2A34000000000000'
'30750000010056`0'
'650B00800C94'
'060D0C0D0E0D`A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0348'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'070D0B0D0D0D090D'
'0000000000000`00'
'0000000000000000'
'0000000000000000'
'0344'
'48s'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'03sE'
'^2234000000000000'
'6j0B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'00000000000000`0'
'0000000000000000'
'0338'
'^23340000000000`0'
'3075000001005600'
'650B00800C94'
'060D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'`33A'
'\x9e2334000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0\x880C0D070D'
'0000000000000000'
'0000000000000000'
'0339'
'^2234000000000000'
'3`75000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2434000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'00000000000000p0'
'0000000000000000'
'0000000000000000'
'0334'
'^1F34000000000000'
'3075000001005600'
'650B00800C84'
'050D090D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'03c2'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'00000000000`0000'
'0000000000000000'
'000000000p000000'
'0332'
'^1F34000000000000'
'30w5000001005600'
'650B00800C94'
'050D0A0D0B0D0n0D'
'000`000000000000'
'0000000000000000'
'00000000p0000000'
'0333'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'00000000000000p0'
'0000000000000000'
'0000000000000000'
'0334'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'000000000`000000'
'0000000000000000'
'000000000000000`'
'032E'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000`00000000'
'032D'
'^1C34000000000000'
'307500`001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'000000000000`000'
'032C'
'^1B340000p0000000'
'3075000001005600'
'650B00800C94'
'030D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'030A'
'^1B34`00000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032C'
'^1D340`0000000000'
'3075000001005600'
'650B00800C94'
'040D`90D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000`00'
'032E'
'^1C34000000000000'
'3075000001005600'
'650\x8200800C94'
'040D090D0A0D050D'
'0000000000000000'
'00p0000000000000'
'0000000000000000'
'0f2C'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D040D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032B'
'^1B34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D040D'
'0000000000000000'
'0000000000000000'
'0000
'032A'
'^1C34000000000000'
'307m000001005600'
'650B00800C94'
'030D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'00000000p0000000'
'032C'
'^bC34000000000000'
'3075000001005600'
'650B00800C94'
'030D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'`32C'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'0000000000`00000'
'`000000000000000'
'0000000000000000'
'032E'
'^1834000000000000'
'3p75000001005600'
'650B00800C94'
'030D070D0A0\x84040D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0324'
'^1834000000000000'
'3075000001005600'
'650\x8600800C94'
'030D070D0A0D040D'
'0000000000000000'
'000000000`000000'
'0000000000000000'
'0324'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'000000000000000`'
'0000000000000000'
'0336'
'^b134000000000000'
'3075000001005600'
'650B00800C94'
'`50D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'30750`0001005600'
'650B00800C94'
'0e0D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'00000000000`0000'
'0000000000000000'
'0334'
'^2134000000000000'
'30750`0001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000`00000'
'0336'
'^2134000000000000'
'3075000003005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'^2134000000000000'
'3`75000001005600'
'650B00800C94'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000`00'
'3075000001005600'
'650B00800C94'
'040D090D0B0D0g0D'
'000`000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^1F34000000000000'
'c075000001005600'
'650B00800C94'
'040D090D0B0D070D'
'0000`00000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^2334000000`00000'
'3075000001005600'
'650B00800C94'
'060D0A0D0\x830D070D'
'0000000000000000'
'0000000000000000'
'0330'
'^1E34000000000000'
'3075000001005600650B'
'`0800C94'
'050D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0330'
'^1E3400000`000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D050D'
'0000000`00000000'
'0000000000000000'
'0`00000000000000'
'0330'
'^2`34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^20340`0000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650\x8200800C94'
'00000000000000`0'
'0000`00000000000'
'0000000000000000'
'0334'
'^2234000000000000'
'307500`001005600'
'650B00800C94'
'050D0A0D0C0D070\xc4'
'00000`0000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000`00'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000`00'
'000`000000000000'
'0338'
'^203400000000`000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'00000`0000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0335'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060\x8c'
'0000000000000000'
'0000000000000000'
'0336'
'^2E34000000000000'
'3075000001005600'
'650B00800C94'
'090D0D0D0E0D0A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0350'
'^2434000000000000'
'3075000001005600'
'650B00800B94'
'060D0B0D0C0D070D'
'0000000000000000'
'00000000`0000000'
'0000000000000000'
'033C'
'^2434000000000000'
'307500`001005600'
'650B00800C94'
'060D0\x820D0C0D070D'
'0000000000000000'
'`000000000000000'
'0000000000000000'
'033C'
'^2334000000000000'
'3075000001005600'
'650B0`800C94'
'050D0B0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'033A'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0B0D070D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'0339'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0B0D070D'
'0000000000000000'
'0000000000000000'
'000000p000000000'
'0338'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'060D0A0D0C0D070\x84'
'0000000000000000'
'0000000000000000'
'0000000000`00000'
'033A'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0\x840C0D060D'
'0000000000000000'
'0000000000000`00'
'0000000000000000'
'0339'
'^223400000000`000'
'3075000001005600'
'l50B00800C94'
'050D0B0D0C0\x88060D'
'0000000000000000'
'00000000000000`0'
'0000000000000000'
'0338'
'^22340000000000p0'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'000p000000000000'
'0000000000000000'
'0000000000`00000'
'`338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'040D09`D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^1C34000000000000'
'g075000001005600'
'650B00800\x8794'
'040D090D0A0\xc4050D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'032C'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'05`D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^20340`00000000p0'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000`00000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'307500000100560p'
'650B00800C94'
'050D0A0\x840B0D060D'
'0000000000000000'
'0p00000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000p01005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'000000000000`000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000`00000000000'
'0335'
'^2134000000000000'
'307m000001005600'
'650B00800C94'
'050D0A0D0C0Dp60D'
'0000`00000000000'
'0000000000000000'
'000000000`000000'
'0336'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0@0D0C0D060D'
'0000000000000000'
'0000000000000000'
'p000000000000000'
'0338'
'^2d3400000p000000'
'30o5000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0337'
'^213400000000`000'
'3075000001005600'
'650B00800C94'
'050D`A0D0C0D`60D'
'00p0000000000000'
'0000000000000000'
'0000`00000000000'
'0336'
'^1D34`00000000000'
'3075000001005600'
'650B00800C94'
'0000000000000000'
'0332'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D0@0D0B0D050D'
'0000000000000000'
'0000000000000000'
'000000000000000`'
'0332'
'\xbc1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D050D'
'0000000000000000'
'0000`00000000000'
'0000000000000000'
'0332'
'^1F34000000000000'
'2075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'000000000000`000'
'03dF'
'^1C34000000000000'
'30750000010p5600'
'650B00800C94'
'040D090D0A0D0u0D'
'0000000000000000'
'0000000000000000'
'000`000000000000'
'032C'
'^1C34000000000000'
'307i000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'00000000`0000000'
'032C'
'^1C34000000000000'
'3075000001005600'
'650B00800Cy4'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032C'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'000000`000000000'
'0000`00000000000'
'032C'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032C'
'^1C34000000000000'
'3075000001005600'
'650B00800\x8b94'
'040D090D0A0D050D'
'000000000p000000'
'0000000000000000'
'000000000000000p'
'032E'
'^1C34000000000000'
'3075000001005600'
'650B00800E94'
'040D090D0A0D050D'
'650B00800C94'
'^2134000000000000'
'050D0A0D0C0D060D'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'040D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0335'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'040D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2134000000000000'
'3075000001005600'
'650B00800C9l'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000p00000'
'0000000000000000'
'0336'
'^2134000`00000000'
'3075000001005600'
'650\x8200800C94'
'050D090D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0335'
'^2p34000000000000'
'3075000001005600'
'650B008`0C94'
'050D090D0C0D060D'
'00000000000000`0'
'0000000000000000'
'0000000000000000'
'0334'
'^2134000000000000'
'3075000001`05600'
'650B00800C94'
'050D0A0D0C0D060D'
'000000000`000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'307500000100560`'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000`00000000'
'0336'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^20340000`0000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0333'
'^1F3400000000000`'
'3075000001005600'
'650B00800C94'
'050D090D0B0D06`D'
'00000000000p0000'
'0000000000000000'
'0000000000000000'
'0332'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D09pD0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'p32E'
'^1D34000000000000'
'30o5000001005600'
'650B00800C94'
'020D050D070D030D'
'0000000000000000'
'0000`00000000000'
'0000000000000000'
'0322'
'^113l000000000000'
'3075000001005600'
'650B00800C94'
'020D050D070D030D'
'0000000000`00000'
'0000000000000000'
'0000000000000000'
'03q6'
'^1234000000000000'
'3075000001005600'
'6e0B00800C94'
'020D060D070D030D'
'00000000000`0000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D0s0D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D07`D030D'
'0000000000000000'
'0000000000000000'
'00000p0000000000'
'0318'
'^123400`000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000`00000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0318'
'^1234000000000000'
'3075000001005600'
'650B00800C94'
'020D060D070D030D'
'0000000000000000'
'00000000000000p0'
'0000`00000000000'
'0318'
'^1234000000000`0`'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0322'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D0r0D0A0D050D'
'0000000000000000'
'00`0000000000000'
'0000000000000000'
'032C'
'^2434000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0C0D070D'
'0000000000000`00'
'0000000000000000'
'0000000000000000'
'033C'
'^2434000000000000'
'3075000001005600'
'650B0`800C94'
'05pD0B0D0C0D070D'
'00000`0000000000'
'0000000000000000'
'0000000000000000'
'033B'
'^2334000000000000'
'3075000001`05600'
'650B00800C94'
'050D0B0D0C0D070D'
'000000000`000000'
'0000000000000000'
'0000000000000000'
'033A'
'^2234000000000000'
'30o5000001005600'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2b34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'000000p000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'3075`00001005600'
'650B00800C94'
'05`D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'000000000000`000'
'0000000000000000'
'0338'
'^2234000000000000'
'3075000001005600'
'650B0`800C94'
'050D0A0D0C0D070D'
'000000000000000`'
'0000p00000000000'
'0000000000000000'
'0338'
'^223t000000000000'
'3075000001005600'
'650B00800C94'
'`50D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2534000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0D0D070D'
'00000000000`0000'
'0000000000000000'
'0000000000000000'
'033E'
'^2734000000000000'
'3075`00001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0342'
'^2734000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'00000000p0000000'
'0000000000000000'
'0000000000000000'
'0342'
'^2734000000000000'
'g075000001005600'
'650B00800C94'
'060D0B0D0D0D090D'
'0000000000000000'
'000000000000000p'
'0000000000000000'
'0342'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'06`D0C0D0D0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'^2834000`00000000'
'3075000001005600'
'650B00800C94'
'060D0\x830D0D0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'\xbe2834000000000000'
'3075000001005600'
'650B00800C94'
'060D0B0D0E0D090D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0344'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'060D0C0D0E0D0A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0346'
'^2A34000000000000'
'30750000010056`0'
'650B00800C94'
'060D0C0D0E0D`A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0348'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'070D0B0D0D0D090D'
'0000000000000`00'
'0000000000000000'
'0000000000000000'
'0344'
'^2834000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'03sE'
'^2234000000000000'
'6j0B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'00000000000000`0'
'0000000000000000'
'0338'
'^23340000000000`0'
'3075000001005600'
'650B00800C94'
'060D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'`33A'
'650B00800C94'
'050D0A0\x880C0D070D'
'0000000000000000'
'0000000000000000'
'0339'
'^2234000000000000'
'3`75000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2434000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'00000000000000p0'
'0000000000000000'
'0000000000000000'
'0334'
'^1F34000000000000'
'3075000001005600'
'650B00800C84'
'050D090D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'03c2'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D060D'
'00000000000`0000'
'0000000000000000'
'000000000p000000'
'0332'
'^1F34000000000000'
'30w5000001005600'
'650B00800C94'
'050D0A0D0B0D0n0D'
'000`000000000000'
'0000000000000000'
'00000000p0000000'
'0333'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'00000000000000p0'
'0000000000000000'
'0000000000000000'
'0334'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'000000000`000000'
'0000000000000000'
'000000000000000`'
'032E'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000`00000000'
'032D'
'^1C34000000000000'
'307500`001005600'
'650B00800C94'
'040D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'000000000000`000'
'032C'
'^1B340000p0000000'
'3075000001005600'
'650B00800C94'
'030D090D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'030A'
'^1B34`00000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032C'
'^1D340`0000000000'
'3075000001005600'
'650B00800C94'
'040D`90D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000`00'
'032E'
'^1C34000000000000'
'3075000001005600'
'650\x8200800C94'
'040D090D0A0D050D'
'0000000000000000'
'00p0000000000000'
'0000000000000000'
'0f2C'
'^1C34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D040D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'032B'
'^1B34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0A0D040D'
'0000000000000000'
'0000000000000000'
'0000
'032A'
'^1C34000000000000'
'307m000001005600'
'650B00800C94'
'030D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'00000000p0000000'
'032C'
'^bC34000000000000'
'3075000001005600'
'650B00800C94'
'030D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'`32C'
'^1D34000000000000'
'3075000001005600'
'650B00800C94'
'040D090D0B0D050D'
'0000000000`00000'
'`000000000000000'
'0000000000000000'
'032E'
'^1834000000000000'
'3p75000001005600'
'650B00800C94'
'030D070D0A0\x84040D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0324'
'^1834000000000000'
'3075000001005600'
'650\x8600800C94'
'030D070D0A0D040D'
'0000000000000000'
'000000000`000000'
'0000000000000000'
'0324'
'^21340000`0000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'000000000000000`'
'0000000000000000'
'0336'
'^b134000000000000'
'3075000001005600'
'650B00800C94'
'`50D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000000'
'30750`0001005600'
'650B00800C94'
'0e0D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'00000000000`0000'
'0000000000000000'
'0334'
'^2134000000000000'
'30750`0001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000`00000'
'0336'
'^2134000000000000'
'3075000003005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'^2134000000000000'
'3`75000001005600'
'650B00800C94'
'0000000000000000'
'0000000000000000'
'0336'
'^2134000000000`00'
'3075000001005600'
'650B00800C94'
'040D090D0B0D0g0D'
'000`000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^1F34000000000000'
'c075000001005600'
'650B00800C94'
'040D090D0B0D070D'
'0000`00000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^2334000000`00000'
'3075000001005600'
'650B00800C94'
'060D0A0D0\x830D070D'
'0000000000000000'
'0000000000000000'
'0330'
'^1E34000000000000'
'3075000001005600650B'
'`0800C94'
'050D090D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0330'
'^1E3400000`000000'
'3075000001005600'
'650B00800C94'
'050D090D0B0D050D'
'0000000`00000000'
'0000000000000000'
'0`00000000000000'
'0330'
'^2`34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^20340`0000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650\x8200800C94'
'050D0A0D0B0D060D'
'00000000000000`0'
'0000`00000000000'
'0000000000000000'
'0334'
'^2234000000000000'
'307500`001005600'
'650B00800C94'
'050D0A0D0C0D070\xc4'
'00000`0000000000'
'0000000000000000'
'0000000000000000'
'0338'
'^2234000000000`00'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D070D'
'0000000000000000'
'0000000000000`00'
'000`000000000000'
'0338'
'^203400000000`000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'00000`0000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'000000000`000000'
'0335'
'^2134000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060\x8c'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0336'
'^2E34000000000000'
'3075000001005600'
'650B00800C94'
'090D0D0D0E0D0A0D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0350'
'^2434000000000000'
'3075000001005600'
'650B00800B94'
'060D0B0D0C0D070D'
'0000000000000000'
'00000000`0000000'
'0000000000000000'
'033C'
'^2434000000000000'
'307500`001005600'
'650B00800C94'
'060D0\x820D0C0D070D'
'0000000000000000'
'`000000000000000'
'0000000000000000'
'033C'
'^2334000000000000'
'3075000001005600'
'650B0`800C94'
'050D0B0D0C0D070D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'033A'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0B0D070D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'0339'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0D0B0D070D'
'0000000000000000'
'0000000000000000'
'000000p000000000'
'0338'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'060D0A0D0C0D070\x84'
'0000000000000000'
'0000000000000000'
'0000000000`00000'
'033A'
'^2334000000000000'
'3075000001005600'
'650B00800C94'
'050D0B0\x840C0D060D'

'0000000000000000'
'0000000000000`00'
'0000000000000000'
'0339'
'^223400000000`000'
'3075000001005600'
'l50B00800C94'
'050D0B0D0C0\x88060D'
'0000000000000000'
'00000000000000`0'
'0000000000000000'
'0338'
'^22340000000000p0'
'3075000001005600'
'650B00800C94'
'050D0B0D0C0D060D'
'000p000000000000'
'0000000000000000'
'0000000000`00000'
'`338'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'040D09`D0A0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^1C34000000000000'
'g075000001005600'
'650B00800\x8794'
'040D090D0A0\xc4050D'
'0000000`00000000'
'0000000000000000'
'0000000000000000'
'032C'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'05`D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0334'
'^20340`00000000p0'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000`00000'
'0000000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'307500000100560p'
'650B00800C94'
'050D0A0\x840B0D060D'
'0000000000000000'
'0p00000000000000'
'0000000000000000'
'0334'
'^2034000000000000'
'3075000p01005600'
'650B00800C94'
'050D0A0D0B0D060D'
'0000000000000000'
'0000000000000000'
'000000000000`000'
'0334'
'^2034000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000`00000000000'
'0335'
'^2134000000000000'
'307m000001005600'
'650B00800C94'
'050D0A0D0C0Dp60D'
'0000`00000000000'
'0000000000000000'
'000000000`000000'
'0336'
'^2234000000000000'
'3075000001005600'
'650B00800C94'
'050D0@0D0C0D060D'
'0000000000000000'
'0000000000000000'
'p000000000000000'
'0338'
'^2d3400000p000000'
'30o5000001005600'
'650B00800C94'
'050D0A0D0C0D060D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0337'
'^213400000000`000'
'3075000001005600'
'650B00800C94'
'050D`A0D0C0D`60D'
'00p0000000000000'
'0000000000000000'
'0000`00000000000'
'0336'
'^1D34`00000000000'
'3075000001005600'
'650B00800C94'
'0000000000000000'
'0332'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D0A0D0B0D050D'
'0000000000000000'
'0000000000000000'
'0000000000000000'
'0332'
'^1F34000000000000'
'3075000001005600'
'650B00800C94'
'050D0@0D0B0D050D'
'0000000000000000'
'0000000000000000'
'000000000000000`'
'0332'
'\xbc1F34000000000000'
'3075000001005600'

@sender That looks quite promising, i put one of the outputs in my python script:

Decoded values:
voltage: 13345
current: 0
capacity: 30000
cycles: 1
soc: 86
temperature: 2917
status: 0
afe_status: 12
transformed:
  temperature_celsius: 18.6
  voltage_display: 13.345
  current_display: 0.0
  cycles_display: 1

so i think the value you are looking for is the BLE service dump 3 :slight_smile:
I would remove the other two in that case, and set it like this:

  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service dump 3"
    service_uuid: 'FFE0'
    characteristic_uuid: 'FFE4'
    notify: true
    internal: true

So the complete script would look like this i think in your case, note the last comment in it at the bottom, possibly you dont need the two lower things. Also put in the mac adres again :slight_smile: :

esp32_ble_tracker:
  scan_parameters: 
    duration: 90s

 

# Define the BLE client
ble_client:
  - mac_address: "" # Replace with the MAC address of your BLE device
    id: my_ble_client
    on_connect:
      then:
        - lambda: |-
            id(ble_connected) = true;
            id(ble_state) = "connected";
    on_disconnect:
      then:
        - lambda: |-
            id(ble_connected) = false;
            id(ble_state) = "reconnecting";
        - script.execute: reconnect_ble

## To find the mac adress, most easy way is to enable the part down below saying:
##   - platform: ble_scanner
##     name: "BLE Devices Scanner"     
## This will show all found BLE devices in the area with their mac adres and name if they have one in the esphome log.
## In case of a X210 battery the macs start consistently with: DC:0D:30:

            


text_sensor:
  - platform: template
    name: "Battery BLE connection"
    id: ble_state_sensor
    lambda: |-
      return id(ble_state);

  - platform: ble_client
    ble_client_id: my_ble_client
    name: "BLE Service FFE0 Characteristic FFE4"
    service_uuid: 'FFE0'
    characteristic_uuid: 'FFE4'
    notify: true
    internal: true
    id: ble_raw_data
    on_value:
      then:
        - lambda: |-
            std::string raw_data = id(ble_raw_data).state;
            if (raw_data.length() >= 38) {
              // Strip the first character '^'
              raw_data = raw_data.substr(1);

              auto char_to_int = [](char c) -> int {
                if ('0' <= c && c <= '9') {
                  return c - '0';
                } else if ('A' <= c && c <= 'F') {
                  return (c - 'A') + 10;
                } else {
                  return 0;
                }
              };

              auto asciitochar = [&](char b, char b2) -> int {
                return ((char_to_int(b) << 4) & 0xF0) + (char_to_int(b2) & 0x0F);
              };

              int voltage = (((((asciitochar(raw_data[6], raw_data[7]) << 8) + asciitochar(raw_data[4], raw_data[5])) << 8) + asciitochar(raw_data[2], raw_data[3])) << 8) + asciitochar(raw_data[0], raw_data[1]);
              int current = (((((asciitochar(raw_data[14], raw_data[15]) << 8) + asciitochar(raw_data[12], raw_data[13])) << 8) + asciitochar(raw_data[10], raw_data[11])) << 8) + asciitochar(raw_data[8], raw_data[9]);
              int soc = (asciitochar(raw_data[30], raw_data[31]) << 8) + asciitochar(raw_data[28], raw_data[29]);
              int temperature = (asciitochar(raw_data[34], raw_data[35]) << 8) + asciitochar(raw_data[32], raw_data[33]);
              int status = asciitochar(raw_data[36], raw_data[37]);
              int afe_status = asciitochar(raw_data[40], raw_data[41]);

              float temperature_celsius = (temperature - 0xAAB) / 10.0;
              float voltage_display = voltage / 1000.0;
              float current_display = current / 10.0;

              id(global_voltage) = voltage_display;
              id(global_current) = current_display;
              id(global_soc) = soc;
              id(global_temperature) = temperature_celsius;
              id(global_status) = status;
              id(global_afe_status) = afe_status;
            } else {
              ESP_LOGE("main", "Received raw data is too short.");
            }


  - platform: ble_scanner
    name: "BLE Devices Scanner" 


script:
  - id: reconnect_ble
    then:
      - delay: 5s
      - ble_client.connect: my_ble_client
      - delay: 30s
      - if:
          condition:
            lambda: |-
              return !id(ble_connected);
          then:
            - script.execute: reconnect_ble           

sensor:
  - platform: template
    name: "Battery voltage"
    unit_of_measurement: "V"
    update_interval: 30s
    accuracy_decimals: 2
    lambda: |-
      return id(global_voltage);
  - platform: template
    name: "Battery Current"
    update_interval: 30s
    unit_of_measurement: "A"
    accuracy_decimals: 1
    lambda: |-
      return id(global_current);
  - platform: template
    name: "Battery SOC"
    update_interval: 30s
    unit_of_measurement: "%"
    accuracy_decimals: 0
    lambda: |-
      return id(global_soc);
  - platform: template
    name: "Battery Temperature"
    update_interval: 30s
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    lambda: |-
      return id(global_temperature);



#Unsure about these two yet if they actually work and what they mean
  - platform: template
    name: "Battery Status"
    update_interval: 30s
    accuracy_decimals: 0
    lambda: |-
      return id(global_status);
  - platform: template
    name: "Battery AFE Status"
    update_interval: 30s
    accuracy_decimals: 0
    lambda: |-
      return id(global_afe_status);





globals:
  - id: global_voltage
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_current
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_soc
    type: int
    restore_value: no
    initial_value: '0'
  - id: global_temperature
    type: float
    restore_value: no
    initial_value: '0.0'
  - id: global_status
    type: int
    restore_value: no
    initial_value: '0'
  - id: global_afe_status
    type: int
    restore_value: no
    initial_value: '0'
  - id: ble_connected
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: ble_state
    type: std::string
    restore_value: no
    initial_value: '"disconnected"'    
    





# this fetches data every minute by pushing a Number 1 to the FFF2 characteristic, causing an update on the Notify FFF1
# Not sure if you actually need these two one, if it keeps dumping so mucht data it might do it itself anyway. 
# You could try removing these


interval:
  - interval: 1min
    then:
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 'FFF0'
          characteristic_uuid: 'FFF2'
          value: [0x31]

#this button manually fetches the data by pushing a Number 1 to the FFF2 characteristic, causing an update on the Notify FFF1
button:
  - platform: template
    name: "Force update values"
    on_press:
      then:
        - ble_client.ble_write:
            id: my_ble_client
            service_uuid: 'FFF0'
            characteristic_uuid: 'FFF2'
            value: [0x31]

I will try to also add the Cycle count and capacity later this week if i find the time :slight_smile:

1 Like