Pool Monitor Device Yieryi BLE-YC01

Hi,

Here is a functional code for an ESP32 with Esphome associated with Home Assistant. Every 30 minutes, the BLE device is polled for new datas.

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


esp32_ble_tracker: #### Stop the active scan ####
  scan_parameters: 
    active: false

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

ble_client: 
  - mac_address: YO:UR:_A:DD:RE:SS #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");
            
            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");
            
######################################################
##                                                  ##
##     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: "F"
    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: 2
    state_class: measurement
    icon: mdi:ph

  - platform: template
    name: "BLE-YC01 batterie"
    id: ble_yc01_battery
    unit_of_measurement: "%"
    accuracy_decimals: 0
    state_class: measurement
    device_class: battery
    icon: mdi:battery
    
  - platform: ble_client ####  Sensor required to manage values coming from the BLE device ####
    ble_client_id: ble_yc01
    id: ble_yc01_sensor
    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]);
      
      // #### Sensors updated with new values
      id(ble_yc01_temperature_sensor).publish_state(((temp/10.0) * (9.0/5.0)) + 32.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/45);
      id(ble_yc01_ec_sensor).publish_state(ec);
      id(ble_yc01_tds_sensor).publish_state(tds);
       
      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"

Here is a way to calculate free chlorine in HA. For now, I canā€™t figure out how to integrate it directly in Esphome.

The formula comes from raspipool github: https://github.com/segalion/raspipool

sensors:
  - platform: template
    sensors:
      chlore_libre_spa:
        value_template: "{{ ( 0.23 * (1 + 0 / 100 ) * ( 14 - states('sensor.ble_yc01_ph')|float(0.0)) ** ( 1 / (400 - states('sensor.ble_yc01_orp')|float(0.0)) ) * ( states('sensor.ble_yc01_ph')|float(0.0) -4.1) ** ( ( states('sensor.ble_yc01_orp')|float(0.0) - 516)/145) + 10.0 ** ( (states('sensor.ble_yc01_orp')|float(0.0) + states('sensor.ble_yc01_ph')|float(0.0) * 70 -1282) / 40 ) ) |round(1) }}"
        unit_of_measurement: ppm
        icon_template: mdi:react
        friendly_name: "Chlore libre estimƩ spa"
5 Likes

Be careful to switch off the comm with the BLE device before uploading in the ESP32. The BLE device seems to freeze sometimes if the connection isnā€™t properly disconnected. You will have to remove the batteries to restart the deviceā€¦ A little bit annoying.

2 Likes

Thank you bro. It Work for me.

1 Like

Great!!!
Iā€™m looking for a orp and ph sensor for my swimming pool, Iā€™m automating everything. do you recomend it? It looks so good but in amazon there are terrible descriptions.
Please let me know.
Thanks

I would personally take a look to the Blueriiot products. I bought the BLE-YC01 just for testing given its price and can see massive differences in the measures even enough I made the calibration (which I am pending of repeating just in case). The Blueriiiot is perfectly integrated with HA too although it is far more expensive. Take a look to the integration and forum and make your own decision. I have been running the Blueriiot for +2y and my pool have never been better. I have a full automation of the pumps for filtering and chemicalā€™s (bleach, etc).

Thanks, Iā€™ve built an automated system with injectors of ph and chrorine,pumps with vvd and also ph sensor but with orp sensor I have some problems and after checking 2 orp electrodes nothing works, i used drobot kit but after several hours working, values get crazy.
This is why iā€™m looking for something different without invest too much money.
Iā€™ve taked a look blueriot devices but they are quite expensive and the probe need to be changed every 2 years with more than 100ā‚¬ for this part.

If the values of ble-yc01 are correct and it works at least 1 year it deserves it.

Thanks

So the code that was posted by kymote125 also works for my BLE enabled yinmik branded pH/ec handheld tester. Everything worked with essentially no modification required.

The model I have is BLE-9908, though there are several other BLE models with slightly different features that may also work.

There is potential in modifying these handheld testers to function as part of a hydroponics system or possibly an aquarium. I may make a new thread if Iā€™m able to reliably have mine return 24/7 pH, EC, and temp readings from my hydroponic system into HA.

1 Like

Iā€™ve also received my BLE-YC01, and Iā€™ve integrated it in my swimming-pool.
Iā€™ve calibrated PH and also ORP, but I donā€™t know why the ORP value doesnā€™t match with the expected, with the stripes the value of free chlorine is 1 and here is 0,1, PH is ok but orp is lower than normal.

Any idea what can I do?

image

Wow, sorry for not response, I was not able to watch the forum from my last post. I have my unit now on pool using with his app. I try to test the code with EspHome, thanks so much for your work. By now, seems that my unit power on button is not working very properly after two weeks on pool.

Do you know how much last battery using a regular BTLE pooling? Because is seems that is not very much time as I read on some coments.

Thanks!
Ruben

In my case 1% every 12h so 2% each day.

Hello RubenKona,
Iā€™m interested by all the information you could have from the brands of the device, can you share an archive of all the documents you have ?

Thanks

How do you calculate free chlorine ?

Do you mean manual and box of the product?

Hi, I was looking for something like that all summer ! do you think it will work on this model :

1 Like

You have talked about excel files : "I donā€™t know how to share the information, as canā€™t attach the excel with the information. Probably better to send to interested people? "
does they result from reverse engineering or direct from manufacturer ?

I search some of the probably ā€œbuildersā€ of the device, and ask to him. Surprisingly they send to me that Excel, that only have the information that I posted on the two posts before with this, no more information on that Excel, for that is not useful to post it. Only two sheets with the two codes that I have posted.

PD: The seller that send me the information arenā€™t ā€œexactlyā€ the same as the device that I have, but in Aliexpress there are some clone devices probably made by same manufacturer.

Ruben
PD: I have just compiled the code, I try to connect to my device. It is true that no clorine information :frowning:

Well; I finally connect to the device using the sample above from @kymote125 (thanks a lot).

I also have tried (unsuccesfully) to calculate clorine using the given formula.
All values seem to match, except battery that tell me 70% as app tell me 100%.
Also doesnā€™t seem to work the 30 minutes pool (I am not using HA as clock origin, but SNTP as I am not using HA. It seems that is pooling all time (or 60 seconds more or less). Also have to convert temp to C as it seems that default is F.

This is my MQTT posted by Esp32:
image

This is the formula I put inside Lambda, but it gives me nan:

        auto cloro = pow (  0.23 * (1.0 + 0.0 / 100.0 ) * ( 14.0 - ph) ,
                  1.0 / (400.0 - orp) ) * 
                 pow ( ( ph - 4.1 ) , ( ( orp - 516.0) / 145.0 ) ) +
                 pow ( 10.0 , ( ( orp + ph * 70.0 - 1282.0) / 40.0 ) );

        id(ble_yc01_cloro).publish_state(cloro);

I have created other sensor:

  - platform: template
    name: "BLE-YC01 CL"
    id: ble_yc01_cloro
    unit_of_measurement: "ppm"
    accuracy_decimals: 0
    state_class: measurement
    icon: mdi:water-opacity

Any suggestion for clorine calculation?

I have read also that device will go to sleep if not pool in, I think 5 minutes, but you say that your pool is every 30 minutes. Is that working?

Thanks in advance.
Ruben
Edit: I didnā€™t realized on the formula to transform to F :man_facepalming:

1 Like

Hi again, I was debbuging the information send by my BLE-YC01 comparing to the vaules that App show on screen, and seems to be some error on the values readed by before code based on possitions of the received data. Also seems that the device sends the calculated chlorine, so doesnā€™t need to calculate with a formula (that in any case, seems very inacurate as I have read on other places posts).

This is the information I received. Later post my corrected ā€œlambda codeā€:

[10:22:19][D][ble_client.receive:204]: value received at 3: 750 [2, 238]   -> ORP mV 
[10:22:19][D][ble_client.receive:204]: value received at 5: 661 [2, 149]   -> EC uS/cm
[10:22:19][D][ble_client.receive:204]: value received at 7: 330 [1, 74]    -> TDS ppm
[10:22:19][D][ble_client.receive:204]: value received at 9: 762 [2, 250]   -> pH / 100
[10:22:19][D][ble_client.receive:204]: value received at 11: 18 [0, 18]    -> 11, 12 Cloro / 10 mg/L
[10:22:19][D][ble_client.receive:204]: value received at 13: 260 [1, 4]    -> 13, 14 Temperatura / 10 ĀŗC
[10:22:19][D][ble_client.receive:204]: value received at 15: 3151 [12, 79] -> Battery
[10:22:19][D][ble_client.receive:208]: value received at 18: 999 [3, 231]  -> ??
[10:22:19][D][ble_client.receive:208]: value received at 20: 762 [2, 250]  -> pH again?

This is corrected code (only ORP/pH was incorrect based on app readings), and also added CL:

        auto temp = ((message[13]<<8) + message[14]);
        auto ph = ((message[3]<<8) + message[4]);
        auto orp = ((message[9]<<8) + message[10]);
        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.51); //Por prueba y error
        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);

I am doing more testsā€¦ not sure of all values :frowning:

Edited again, initial values seems to be ok, only added Chlorine.

Edited 2: With this final version all seems to work correctly including Chlorine calculated by device.The only thing that I donā€™t know how to do, is not asking for values every little time instead of suposed 30 minutes interrogation.

1 Like

I use this :

The formula comes from raspipool github: https://github.com/segalion/raspipool

Hiya all, I just received my BLE-YC01 and managed to connect it to my ESP32. However, my BLE-YC01 keeps turning off after a couple of minutes which kinda defeats the purpose. Has anyone figured out how to keep it on?
Thanks a bunch!

1 Like