Blue connect Go - Pool Analyzer

Hello,

this is my first topic.

I have openhab installed for long time and in the community, I ever found information to make working all my devices.

Today is my day to help someone to integrate The blue connect pool analyzer.

My setup:

Openhab 3.4.4

Mqtt Mosquito

ESP32 with ESPhome firmware

Blue connect GO device ==> Blue Connect Go

Before to start, you must have a MQTT broker correctly working.

The idea is to use an ESP32 with BLE to communicate with the blue connect device and publish the measurements on MQTT.
I was able to make working my setup thanks a discussion here: Blue Connect pool measurements - Third party integrations - Home Assistant Community

this is my thing setup for esp32 module:

UID: mqtt:topic:mosquitto:792b246d34
label: MQTT esphome blueconnect
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:mosquitto
channels:
  - id: esphome_blueconnect_switch
    channelTypeUID: mqtt:switch
    label: esphome_blueconnect_switch
    description: null
    configuration:
      commandTopic: blueconnect/switch/blueconnect_enable/command
      stateTopic: blueconnect/switch/blueconnect_enable/state
  - id: esphome_blueconnect_temperature
    channelTypeUID: mqtt:number
    label: esphome_blueconnect_temperature
    description: null
    configuration:
      stateTopic: blueconnect/sensor/blueconnect_temperature/state
  - id: esphome_blueconnect_pH
    channelTypeUID: mqtt:number
    label: esphome_blueconnect_pH
    description: null
    configuration:
      stateTopic: blueconnect/sensor/blueconnect_ph/state
  - id: esphome_blueconnect_ORP
    channelTypeUID: mqtt:number
    label: esphome_blueconnect_ORP
    description: null
    configuration:
      stateTopic: blueconnect/sensor/blueconnect_orp/state
  - id: esphome_blueconnect_battery
    channelTypeUID: mqtt:number
    label: esphome_blueconnect_battery
    description: null
    configuration:
      stateTopic: blueconnect/sensor/blueconnect_battery/state
  - id: esphome_blueconnect_status
    channelTypeUID: mqtt:number
    label: esphome_blueconnect_status
    description: null
    configuration:
      stateTopic: blueconnect/sensor/blueconnect_status/state

this is the esphome configuration file for ESP32 BLE gateway

substitutions:
  blueriiot_mac: *********************
  blueriiot_name_prefix: blue_connect
  blueriiot_id_prefix: bc
  
  # send true 0x01 to this service ID
  blueriiot_send_service_uuid: 'F3300001-F0A2-9B06-0C59-1BC4763B5C00'
  blueriiot_send_characteristic_uuid: 'F3300002-F0A2-9B06-0C59-1BC4763B5C00'
  
  # notification is received on this Service ID                  
  blueriiot_receive_service_uuid: 'F3300001-F0A2-9B06-0C59-1BC4763B5C00'
  blueriiot_receive_characteristic_uuid: 'F3300003-F0A2-9B06-0C59-1BC4763B5C00'
  
esphome:
  name: blueconnect

esp32:
  board: nodemcu-32s
  framework:
    type: arduino

wifi:
  ssid: *******************
  password: ******************
  ap:
    ssid: "BlueConnect Hotspot"
    password: qwertyuiop

web_server:
  port: 80
  
# Enable logging
logger:
  #level: VERY_VERBOSE
  #level: INFO
  level: VERBOSE
  
# Enable Home Assistant API
#api:
mqtt:
  topic_prefix: esphome
  broker: 192.168.0.4
  id: "mqttClient"
  port: 1883
  name: "Blue Connect GO"
  discovery : false
  birth_message:
    topic: "blueconnect/status"
    payload: 'online'
  will_message:
    topic: "blueconnect/status"
    payload: 'offline'

ota:
  password: ********************

esp32_ble_tracker:
  scan_parameters:
    active: false
    interval: 1000ms
    window: 700ms
  on_ble_advertise:
    - mac_address: ${blueriiot_mac}
      then:
        - logger.log: 
            format: "Found Blueriiot sensor"
            level: "INFO"

ble_client:
  - mac_address: ${blueriiot_mac}
    id: ble_client_${blueriiot_id_prefix}
    on_connect: 
      then:
        - logger.log: 
            format: "Connected to Blueriiot sensor"
            level: "INFO"
        - lambda: "id(binary_sensor_${blueriiot_id_prefix}_connected).publish_state(true);"
        - delay: 2s
        - button.press: button_${blueriiot_id_prefix}_doreading
    on_disconnect: [lambda: "id(binary_sensor_${blueriiot_id_prefix}_connected).publish_state(false);"]

switch:
  - platform: ble_client
    ble_client_id: ble_client_${blueriiot_id_prefix}
    name: "${blueriiot_name_prefix} Enable"
    id: switch_${blueriiot_id_prefix}_enable

sensor:
  - platform: template
    id: binary_sensor_${blueriiot_id_prefix}_connected
    name: ${blueriiot_name_prefix} Status
    device_class: signal_strength
    entity_category: diagnostic
  
  - platform: template 
    id: sensor_${blueriiot_id_prefix}_temperature
    name: ${blueriiot_name_prefix} Temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 1
  
  - platform: template 
    id: sensor_${blueriiot_id_prefix}_ph
    name: ${blueriiot_name_prefix} pH
    unit_of_measurement: "pH"
    accuracy_decimals: 1

  - platform: template 
    id: sensor_${blueriiot_id_prefix}_orp
    name: ${blueriiot_name_prefix} ORP
    unit_of_measurement: "mV"
    accuracy_decimals: 0
    
  - platform: template 
    id: sensor_${blueriiot_id_prefix}_bat
    name: ${blueriiot_name_prefix} Battery
    unit_of_measurement: "%"
    accuracy_decimals: 0
                
## Blue Connect
button:
  - platform: template
    id: button_${blueriiot_id_prefix}_doreading
    name: ${blueriiot_name_prefix} do reading
    internal: true
    on_press:
      then:
        - ble_client.ble_write:
            id: ble_client_${blueriiot_id_prefix}
            service_uuid: ${blueriiot_send_service_uuid}
            characteristic_uuid: ${blueriiot_send_characteristic_uuid}
            value: !lambda |-
              return {0x01};

text_sensor:
  - platform: ble_client
    id: ${blueriiot_id_prefix}_reading_data
    name: ${blueriiot_name_prefix} reading data
    internal: true
    ble_client_id: ble_client_${blueriiot_id_prefix}
    service_uuid: ${blueriiot_receive_service_uuid}
    characteristic_uuid: ${blueriiot_receive_characteristic_uuid}
    notify: true
    update_interval: never
    on_notify:
      then:
        lambda: |-
          std::string rawhex = format_hex_pretty((uint8_t *) x.c_str(), x.size()).c_str();
          ESP_LOGD("raw_hex", "%s", rawhex.c_str());

          float temperature = (float)((int16_t)(x[2]<< 8) + x[1])/100;
          ESP_LOGD("temp", "%f", temperature);
          id(sensor_${blueriiot_id_prefix}_temperature).publish_state(temperature);
              
          float raw_ph = (float)( (int16_t) (x[4]<< 8) + x[3]) ;
          float ph = (float)( (int16_t) (2048 - raw_ph))  ; 
          ESP_LOGD("ph", "%f", ph);
          id(sensor_${blueriiot_id_prefix}_ph).publish_state(ph);
          
          float orp = (float)( (int16_t) (x[6]<< 8) + x[5]) / 3.86 ;
          ESP_LOGD("orp", "%f", orp);
          id(sensor_${blueriiot_id_prefix}_orp).publish_state(orp);
          
          float bat = (float)( (int16_t) x[11]) ;
          ESP_LOGD("bat", "%f", bat);
          id(sensor_${blueriiot_id_prefix}_bat).publish_state(bat);
          
          id(switch_${blueriiot_id_prefix}_enable).turn_off();

Theoretically the only rules that you need to read the data from blue connect is teh rules called “piscina lettura” and “piscina graph” :slight_smile:
There is also a rule to controll a dosing pump, i shared maybe you have some improvements

var Number pump_calibration = 50	// [ml al minuto] valore di calibrazione della pompa peristaltica  *******da tarare*********
var Number concentrazione = 150		// [ml per ogni m3 per abbassare 1 di PH]  [Aggiungere 3 lt. di prodotto ogni 100 m3 d'acqua per abbassare di 0,2 unità il valore di pH]
var Timer pump = null				// timer
var Timer ble = null				// timer
var Number cap = 14 				// [mc] volume piscina
var Number hyst = 0					// valore di isteresi sul setpoint impostato
var Number ble_on = 180				// [secondi] di attivazione bluetooth
var Number pump_off = 6.8			// valore pump grafico
var Number pump_on = 8				// valore pump grafico
var Number max_time = 15			// [minuti] - valore massimo dosabile per proteggere il sistema
var Number ph_offset = -0.07		// [pH] offset misura ph

/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

rule "piscina"
when
	Time cron "0 0 10,12,14,16 * * ?"
then
	var Number ph = esphome_blueconnect_pH.state as Number
	var Number level = ph_level.state as Number
	var Number level_h = level + hyst
	if (ph > level_h){
		pump_dosing_controll.sendCommand(ON)	
	}else{
		if(pump !== null) {
			pump.cancel
			pump = null
		}
		dosing_pump_status.postUpdate("Livello ph corretto " + (esphome_blueconnect_pH.state).format("%.2f pH"))
	}
end

rule "piscina 1"
when
	Item pump_dosing_controll received command ON
then
	var Number ph = esphome_blueconnect_pH.state as Number
	var Number level = ph_level.state as Number
	var Number ml = concentrazione*cap*(ph - level)	
	var time = (ml/pump_calibration).intValue
	ph_minu_dosaggio.postUpdate(ml)
	if (time >= max_time) {
		pump_dosing_time.postUpdate(max_time)
		dosing_pump_status.postUpdate("Livello pH Troppo Alto - Controllo Sonde")	
		pump = createTimer(now.plusMinutes(max_time), [ |
			pump_dosing_controll.sendCommand(OFF)
		])
	} else {
		pump_dosing_time.postUpdate(time)
		dosing_pump_status.postUpdate("Livello pH Alto - Pompa Dosaggio Accesa")	
		pump = createTimer(now.plusMinutes(time), [ |
			pump_dosing_controll.sendCommand(OFF)
		])
	}
end

rule "piscina 2"
when
	Item pump_dosing_controll received command OFF
then
	dosing_pump_status.postUpdate("Pompa Dosaggio Spenta")
	pump_dosing_time.postUpdate(0) 
	ph_minu_dosaggio.postUpdate(0)
	if(pump !== null) {
		pump.cancel
		pump = null
	}
end

rule "piscina graph"
when
	Item pump_dosing_controll received command or
	Item ph_level received update or
	Item esphome_blueconnect_pH_raw received update or
	Item esphome_blueconnect_temperature received update
then
	if(receivedCommand == ON) g_pump.postUpdate(pump_on)
	else g_pump.postUpdate(pump_off)	
	g_set.postUpdate(ph_level.state)
	var Number ph_raw = esphome_blueconnect_pH_raw.state as Number
	var Number temp = esphome_blueconnect_temperature.state as Number
	var Number slope = 54.2 + temp * 0.1984
	var Number ph_calc = ph_raw / (slope * 4) + 7 + ph_offset
	g_ph.postUpdate(ph_calc) 
	ph_ave.postUpdate(ph_calc)
	esphome_blueconnect_pH.postUpdate(ph_calc)
end

rule "piscina lettura"
when
    Time cron "0 50 * * * ?"
then
	esphome_blueconnect_switch.sendCommand(ON)
	ble = createTimer(now.plusSeconds(ble_on), [ |
      esphome_blueconnect_switch.sendCommand(OFF)
	])	
end

items and sitemap i just share some images:

1 Like

image

the raw data for the battery status is still in debugging :slight_smile:

Great, Love it!

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.