How can I get readings from a SensorPush more frequently?

Hi all -
I would like to explore ways to get data from a SensorPush sensor more frequently.

Here’s my setup:
Home Assistant 2023.2.0 on a Raspberry Pi 4
Supervisor 2023.01.1
Operating System 9.5
Frontend 20230201.0 - latest

ESPHome running a generic ESP32 Core Board from Inland (The ESP is currently configured to only monitor/control a BedJet device).

According to SensorPush, the hardware records and presents data once a minute.

Searching around the net, I found that I could use the SensorPush BLE API and SensorPushBleak to get data from the device on demand. I made a little python script to run on a separate Raspberry pi 3 and get sensor data on demand - works pretty good.

Hopefully, without adding more hardware to my whole setup, I’d like to be able to run the above functionality to poll the SensorPush device from within Home Assistant. Here’s what I’ve tried:

Official

  1. Investigated the official Home Assistant Integration for SensorPush. Did not see a way to increase the frequency of incoming data.

  2. Installed Python Scripts. Could not run my script because it not possible to use Python imports (need to import BleakClient referenced above)

  3. Installed HACS and Passive BLE Monitor. Again stuck with the one reading per minute constraint of the hardware.

  4. As of today, I’m investigating using the ESPHome BLE Client Sensor to query the SenorPush device - looks promising (?)

I’m only about 3 days into working with Home Assistant and this issue, but thought I’d reach out to this excellent community for comments on attacking this goal of getting data on demand from a SensorPush sensor.

Thanks in advance for your consideration and comments.
John

Found a solution, thought I’d post it. Created the ble_client, and a sensor for it. Sensor has 3 characteristics - Temp, humidity and voltage. Values are polled every 15 seconds for temp and humidity, the voltage polls at a minute as shown in the yaml below. I also created a Switch (named
Initiate SensorPush Write) to write to the temperature characteristic, which triggers a sensor reading internally on the SensorPush device - according to this link.

In HomeAssistant, I set up an automation to “Turn On” the "Initiate SensorPush Write " switch every 15 seconds - BAM! fresh sensor reading every 15 seconds or so… Kind of clunky, but it works. Currently investigating a better way of doing the ble_client.ble_write - getting rid of the switch would be nice, but also would like an easy way of adjusting the timing.

Also have a switch to turn off the ble_client. This is nice so that I can disconnect the ESP and connect to the SensorPush with the iOS or android app to double check values that I’m getting from the ESP.

Will update if I have a more elegant solution as I really wanted to:

  1. Connect to the SensorPush

  2. Write to the temp characteristic

  3. Read temp, humidity, and volts

  4. Disconnect

  5. 15 seconds later, do it all over again.

The YAML:

esp32_ble_tracker:

ble_client:

  - mac_address: xx:xx:xx:xx:xx:xx
    id: sensorpush_ble_id1
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to SensorPush device");
    on_disconnect:                                                                 
      then:                                                                        
        - lambda: |-                                                               
            ESP_LOGD("ble_client_lambda", "Disconnected from SensorPush device");

sensor:
  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Temp"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090080-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:thermometer'
    unit_of_measurement: '°F'
    update_interval: 15s
    notify: YES
    device_class: "temperature"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0])/100;
    filters:
      - lambda: return x * (9.0/5.0) + 32.0;



  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Humidity"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090081-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:water-percent'
    unit_of_measurement: '%'
    update_interval: 15s
    notify: YES
    device_class: "humidity"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0])/100;
  
  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Battery Voltage"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090007-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:battery-bluetooth-variant'
    unit_of_measurement: 'mV'
    update_interval: 120s
    notify: YES
    device_class: "voltage"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0]);

switch:
  - platform: ble_client
    ble_client_id: sensorpush_ble_id1
    name: "Enable SensorPush Reads"
  - platform: template
    name: "Initiate SensorPush Write"
    turn_on_action:
      - ble_client.ble_write:
          id: sensorpush_ble_id1
          service_uuid: EF090000-11D6-42BA-93B8-9DD7EC090AB0
          characteristic_uuid: EF090081-11D6-42BA-93B8-9DD7EC090AA9
          # List of bytes to write.
          value: [0x01,0x00, 0x00, 0x00]

Yo - got a better solution.

It’s now setup to Write to the Temp characteristic after any raw value comes in from a read. Fresh data is then ready for the next read:

ble_client:
  - mac_address: XX:XX:XX:XX:XX:XX
    id: sensorpush_ble_id1

sensor:
  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Temp"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090080-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:thermometer'
    unit_of_measurement: '°F'
    update_interval: 120s
    notify: YES
    device_class: "temperature"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0])/100;
    filters:
      - lambda: return x * (9.0/5.0) + 32.0;



  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Humidity"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090081-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:water-percent'
    unit_of_measurement: '%'
    update_interval: 5s
    notify: YES
    device_class: "humidity"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0])/100;
    on_raw_value:
      - ble_client.ble_write:
          id: sensorpush_ble_id1
          service_uuid: EF090000-11D6-42BA-93B8-9DD7EC090AB0
          characteristic_uuid: EF090081-11D6-42BA-93B8-9DD7EC090AA9
          # List of bytes to write.
          value: [0x01,0x00, 0x00, 0x00]
  
  - platform: ble_client
    type: characteristic
    ble_client_id: sensorpush_ble_id1
    name: "SensorPush Battery Voltage"
    service_uuid: 'EF090000-11D6-42BA-93B8-9DD7EC090AB0'
    characteristic_uuid: 'EF090007-11D6-42BA-93B8-9DD7EC090AA9'
    icon: 'mdi:battery-bluetooth-variant'
    unit_of_measurement: 'mV'
    update_interval: 120s
    notify: YES
    device_class: "voltage"
    state_class: "measurement"
    accuracy_decimals: 2
    lambda: |-
      return (float)((int16_t)(x[1]<< 8) + x[0]);

Where is this located? In your esphome yaml?

Yes, that is a snippet from the yaml.

Hi!

Could you solve the ble_client connection only for the time of read/write values? How much the permanent connection affects the battery?
I would like to just read the battery once a day, and send alert to my device trackers if needed, but don’t want to keep a client connection alive to eat the battery.
Thx!