Pool Monitor Device Yieryi BLE-YC01

Thanks all, works like a charm.
Only problem seems to be te range. Anyone inhere has any idea how to extend the BT range of my esp32wroom ?
It doesnt connect to the ble-yc01 though its only 5 meters away.

Correct, I’ve choose to create a PLA box to put my ESP outside near the pool. As the ESP is using Wifi, no range problem after.
PS : I’ve tried just behind the window in the living but the BLE signal is stop but the window (same behevior with my smartphone). If I open the window, then it connect to.

thxn for sharing your code, my esp32 is ready, just need to change the MAC, just ordered the BLE-YC01 from aliexpress :slight_smile:

Thanks for the code.
It works perfect.

Just one thing:
Is it possible to make something that the sonsors go to „unknow“ when the esp can not connect to the device? For one houre or something?
At the moment the value is still displaying also when the sensor when the device is not in the range of the esp.

Thanks for your help.

For those using this code on esphome 2023.6.x with

bluetooth_proxy:
  active: true

And who are having connection problems, while waiting for the patch on esphome to be pushed,
Just add:

external_components:
  - source: github://pr#5073
    components: [ esp32_ble_tracker ]

https://github.com/esphome/esphome/pull/5073

1 Like

Thanks, this code works quite well!

I made a few changes:

  • added the chlorine as reported by the meter like in another post, but note the value is in mg/L and not ppm, and it requires 1 decimal, otherwise it will often just report 0
  • my device reports °C, and that’s what I need
  • pH seems to be reported with 1 decimal only, so I set that
  • I removed the “start scanning” and “stop scanning” buttons - they don’t do anything since continuous scanning is the default anyway for the ble_tracker. If you don’t want that, you have to set “continuous: false”, but if you use the esp32 as bluetooth proxy as well, this won’t work anymore. Setting “active: false” is just to avoid asking passive devices for additional data after receiving a packet, it’s irrelevant for the YC01, which requires an active connection. So the comment in the code “stop active scanning” is actually incorrect to my knowledge.
  • in the code in the referenced post, the active time was 25min instead of 2min. I correct that, but at home, I have removed the timer entirely. Let’s see how long battery will last…
  • EDIT: I also changed the platform type from the default arduino to esp-idf, as that is recommended for bluetooth proxies, so I guess it is better here as well (this is not shown in my code). This change has to be done via usb connection, not OTA.

Hope that helps…


esp32_ble_tracker:
  scan_parameters:
    active: false

binary_sensor:
- platform: status
  name: "ESP32 Status"
- platform: template
  id: ble_yc01_ble_connected
  icon: mdi:bluetooth-connect
  name: "BLE Connected"

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      # Turn on BLE client every 30 minutes for 2 minutes
      - seconds: 0
        minutes: /30
        then:
          - switch.turn_on: ble_switch
          - delay: 2min
          - switch.turn_off: ble_switch


######################################################
##                                                  ##
##   To initiate to connection with the BLE device  ##
##                                                  ##
######################################################

ble_client: 
  - mac_address: C0:00:00:0x:xx:xx #Use the MAC address of your BLE device
    id: ble_yc01
    on_connect: #### Actions to perform when connecting to the BLE device ####
      then:
      #### Wait until characteristic is discovered ####
        - wait_until:   
            lambda: |-
              esphome::ble_client::BLEClient* client = id(ble_yc01);
            
              auto service_uuid = 0xFF01;
              auto char_uuid = 0xFF02;
              
              //#### When waiting for connection, we extract the available characteristics ####
              esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid);
              
              return chr != nullptr;
              
        #### Official connection to the BLE device with the desired characteristic ####
        - lambda: |- 
            ESP_LOGD("ble_client_lambda", "Connected to BLE-YC01");
            id(ble_yc01_ble_connected).publish_state(true);

            esphome::ble_client::BLEClient* client = id(ble_yc01);
            
            auto service_uuid = 0xFF01; 
            auto char_uuid = 0xFF02;
            
            esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid);
            
            if (chr == nullptr) {
                ESP_LOGW("ble_client", "[0xFF01] Characteristic not found.  State update can not be written.");
            }
        
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client", "Disconnected from BLE-YC01");
            id(ble_yc01_ble_connected).publish_state(false);
            
######################################################
##                                                  ##
##     Sensors associated with the BLE device       ##
##                                                  ##
######################################################
            
sensor: #### Template sensor as their values are publish from a lambda or the BLE client ####

  - platform: template    
    name: "BLE-YC01 EC"
    id: ble_yc01_ec_sensor
    unit_of_measurement: "µS/cm"
    accuracy_decimals: 0
    state_class: measurement
    icon: mdi:water-opacity
    
  - platform: template
    name: "BLE-YC01 TDS"
    id: ble_yc01_tds_sensor
    unit_of_measurement: "ppm"
    accuracy_decimals: 0
    state_class: measurement
    icon: mdi:water-opacity
    
  - platform: template
    name: "BLE-YC01 Temperature"
    id: ble_yc01_temperature_sensor
    unit_of_measurement: "C"
    accuracy_decimals: 1
    state_class: measurement
    device_class: temperature
    
  - platform: template
    name: "BLE-YC01 ORP"
    id: ble_yc01_orp_sensor
    unit_of_measurement: "mV"
    accuracy_decimals: 0
    state_class: measurement
    device_class: voltage
    
  - platform: template
    name: "BLE-YC01 pH"
    id: ble_yc01_ph_sensor
    unit_of_measurement: "pH"
    accuracy_decimals: 1
    state_class: measurement
    icon: mdi:ph

  - platform: template
    name: "BLE-YC01 battery"
    id: ble_yc01_battery
    unit_of_measurement: "%"
    accuracy_decimals: 0
    state_class: measurement
    device_class: battery
    icon: mdi:battery

  - platform: template
    name: "BLE-YC01 CL"
    id: ble_yc01_cloro
    unit_of_measurement: "mg/L"
    accuracy_decimals: 1
    state_class: measurement
    icon: mdi:water-opacity  
    
  - platform: ble_client ####  Sensor required to manage values coming from the BLE device ####
    ble_client_id: ble_yc01
    type: characteristic
    id: ble_yc01_sensor
    update_interval: 30s
    internal: true
    service_uuid: FF01
    characteristic_uuid: FF02
    notify: true
    #### Lambda to decode values and push to the associated sensors ####
    lambda: |-
    
      if (x.size() == 0) return NAN;
      
      //ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); // ####  Useful for debugging ####
 
 
      // ### DECODING ###
      uint8_t tmp = 0;
      uint8_t hibit = 0;
      uint8_t lobit = 0;
      uint8_t hibit1 = 0;
      uint8_t lobit1 = 0;
      auto message = x;
      
      for (int i = x.size() -1 ; i > 0; i--) {
        tmp=message[i];
        hibit1=(tmp&0x55)<<1;
        lobit1=(tmp&0xAA)>>1;
        tmp=message[i-1];	
        hibit=(tmp&0x55)<<1;
        lobit=(tmp&0xAA)>>1;
        
        message[i]=~(hibit1|lobit);
        message[i-1]=~(hibit|lobit1);

      }
      
      //ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", message.size(), message.size(), &message[0]); // #### For debug ####


      // #### Extraction of individual values ####
      auto temp = ((message[13]<<8) + message[14]);
      auto ph = ((message[3]<<8) + message[4]);
      auto orp = ((message[20]<<8) + message[21]);
      auto battery = ((message[15]<<8) + message[16]);
      auto ec = ((message[5]<<8) + message[6]);
      auto tds = ((message[7]<<8) + message[8]);
      auto cloro = ((message[11]<<8) + message[12]);
      
      // #### Sensors updated with new values
      id(ble_yc01_temperature_sensor).publish_state(temp/10.0);
      id(ble_yc01_ph_sensor).publish_state(ph/100.0);
      id(ble_yc01_orp_sensor).publish_state(orp);
      id(ble_yc01_battery).publish_state(battery/31.9);
      id(ble_yc01_ec_sensor).publish_state(ec);
      id(ble_yc01_tds_sensor).publish_state(tds);
      id(ble_yc01_cloro).publish_state(cloro/10.0);
       
      return 0.0; // this sensor isn't actually used other than to hook into raw value and publish to template sensors


switch:  #### To switch on and off the communication with the BLE device ####
  - platform: ble_client
    id: ble_switch
    ble_client_id: ble_yc01
    name: "Enable BLE-YC01"
2 Likes

Thnx for sharing this!

Thx for this sharing. I’ve just updated my ESP with your code as I’ve noticed some problem and those seems to be solved with your explanation.

It’s running now for 15 minutes (not so long), but I can see 2 things corrected for me :

  1. battery level is now correct
  2. disconnection is done after 2 minutes. I hope it should use less battery on the YC01 !

I was thinking about something, but i’m not good enought yet in ESPHome. During the disconnected period, is there a method to tell the ESP to no trying to read value as it’s not connected ? It should stop writing warning in the log and unstress the ESP to try to do something it can’t ?

Well, you could try to experiment with setting “continuous: false” in scan_parameters. I’m not sure though whether then the scan will be activated by activating ble_client, I simply haven’t experimented with that…

So I haven’t found a way to restart the YC01 once it loses connection, e.g., when my homeassistant instance crashes for longer time. The automation listed above is unlikely to work, as the log says the esp32 is starting scans anyway, but the YC01 just doesn’t respond. In that case, I have to go and press the on button on the device…

Great project thanks guys, just received mine. Trying codes above!

1 Like

Receive mine this week, does someone have a dashboard yaml, with like gauge sensors? Would be nice if someone can share

Did you find a way to turn on/off the backlight?

Would be nice to figure out how to keep the device ON all the time, also I paid attention that if ESP32 kept on for long time it freezes without connecting to the device even if device turned ON manually. Only reset helps to regain connection.
That’s sad

Guys , i have the BLE-YC01 for a few days, but dont get any cloro readins? I have for test some chloor tablets in bottle, but still no readins? also in HA i get strange values… what am i missing here?

image

pH has to be btween a range to get chloro readings. its around 7-8pH. You won’t get a chloro reading with pH4

Ahh, makes sense…

I also need to calibrate the device, maybe that’s the issue indeed, thnx for this feedback

How did you know this?

Hmm I think it was in the manual. It has been a really long time since I looked. It may mention it in the app.

Ok, have to read again then :slight_smile:

1 Like