Skip to content

BLE Water Level Sensor Communication

Overview

The SMARTA L v2 base station communicates with a separate, external BLE-enabled water level sensor to obtain tank level readings. The base station acts as a BLE client (or central device) that actively scans for and processes advertising data from the designated BLE sensor.

BLE Sensor Interaction Model

  1. Sensor Advertising: The external water level sensor periodically broadcasts its data within BLE advertising packets. This data typically includes the raw sensor reading (e.g., pressure value) and potentially other status information.
  2. Base Station Scanning: The base station (main.ino - initialize_ble_client()) continuously or periodically performs BLE scans (pBLEScan->start()) to discover nearby BLE devices.
  3. Sensor Identification (Pairing/Targeting):
    • The base station is configured with the MAC address of the specific water level sensor it should listen to. This MAC address is stored in preferences as adv_id (getSettingValues() in main.ino).
    • The adv_id can be set/updated via the Sensor MAC Characteristic (f3b5a8d4-2b6e-4a1b-8b1e-3c4d5e6f7a96). Writing a new MAC address to this characteristic updates the preference and typically triggers a device restart to apply the change (SensorMacCallbacks::onWrite() in main.ino).
  4. Data Reception and Processing:
    • During a scan, if the base station detects an advertising packet from the configured sensor's MAC address (adv_id), it extracts the service data from the advertisement (scanCompleteCallback() in main.ino).
    • The scanCompleteCallback() function is triggered when a scan is complete or when a device matching certain criteria is found (if filters were applied, though in this case, it seems to iterate through all results).
    • It specifically checks if (device_id == adv_id) to process data only from the paired sensor.
    • The raw service data (ble_service_data = device.getServiceData()) is then parsed. The current implementation appears to take the first few bytes of the service data, subtracts one from each byte's decimal value, and concatenates them to form blePayloadString. It also creates a binary string representation in blePayloadBytes.
    • The RSSI of the sensor's advertisement is also captured (lastSensorRSSI = device.getRSSI()).
  5. Data Utilization:
    • The parsed blePayloadString (representing the raw sensor value) is then used in conjunction with calibration values (e.g., raw_zero, height, sensorType - also configurable via BLE, see PumpControlCallbacks::onWrite() in main.ino for cal: command) to calculate the actual tank level (tank_level_condition_get() in main.ino).
    • This calculated tank level and other sensor-related data (like raw_known, level_known) are then made available via the Pump Data Characteristic and transmitted via MQTT.

Key Code References

  • BLE Scanning Initialization: initialize_ble_client() in main.ino sets up the BLE scanner and callbacks.
  • Scan Completion and Data Parsing: scanCompleteCallback(BLEScanResults results) in main.ino handles the results of a BLE scan, identifies the target sensor by its MAC address (adv_id), and extracts/parses the advertising service data.
  • Sensor MAC Configuration: The adv_id is retrieved from preferences (getSettingValues() in main.ino) and can be updated via the SENSOR_MAC_UUID characteristic (SensorMacCallbacks in main.ino).
  • Sensor Data Storage: Variables like ble_service_data, blePayloadString, lastSensorRSSI store the incoming data from the sensor.
  • Calibration Data: sensorType, raw_zero, height are used to convert raw sensor readings to meaningful levels. These are configurable.
  • Tank Level Calculation: tank_level_condition_get() in main.ino likely uses the parsed sensor data and calibration parameters.

Pairing and Sensor Management

  • The "pairing" is essentially the act of configuring the base station with the correct MAC address (adv_id) of the BLE sensor.
  • If the sensor needs to be replaced or changed, its new MAC address must be written to the base station via the Sensor MAC Characteristic.
  • The OLED display might show "NO SENSOR DETECTED" (noSensorDetectedDisplay() in OLED.ino) if no valid data is received from the configured sensor after a certain period or if sensorValid is false.
  • A successful pairing/update of the sensor MAC is usually indicated on the OLED (sensorPairedDisplay() in OLED.ino).

Data Flow Summary

  1. External BLE Sensor advertises its readings.
  2. Base Station scans for BLE advertisements.
  3. Base Station identifies the target sensor using the stored adv_id (MAC address).
  4. Base Station extracts and parses the service data from the sensor's advertisement.
  5. The raw data is converted to a tank level using calibration parameters.
  6. The tank level and other system data are then exposed via the base station's own BLE services (e.g., Pump Data Characteristic) and sent to the cloud via Wi-Fi/LTE.

Borehole Sensor Support (Secondary BLE Sensor)

Overview

SMARTA L v2 firmware supports a second BLE water level sensor, referred to as the Borehole Sensor. This sensor is handled in parallel with the main tank sensor, allowing the system to monitor and report borehole water levels independently.

Configuration and Activation

  • The borehole sensor is identified by its own MAC address (bh_adv_id), stored in preferences and configurable similarly to the main sensor.
  • Borehole sensor calibration parameters are independent and default to 10 bar operation (bh_sensorType, bh_raw_zero, bh_height, bh_level_known, bh_raw_known).
  • The borehole sensor is only active if the borehole_active boolean (stored in preferences) is set to true.

BLE Scanning and Data Processing

  • During BLE scans, the base station checks for both the main tank sensor (adv_id) and the borehole sensor (bh_adv_id).
  • If a device with the borehole sensor's MAC address is found and borehole_active is true, its service data is extracted and parsed similarly to the main sensor.
  • The borehole sensor's raw data is processed using its own calibration parameters via the bh_pressure_process() function.

MQTT Publishing

  • When a new reading is received from the borehole sensor, the following MQTT topics are published (if borehole_active is true):
    • bh_ble_data: Parsed borehole sensor value (string)
    • bh_ble_data_raw: Raw binary string representation
    • borehole_level: The calculated borehole water level (integer, in centimeters or as configured)
  • The borehole_level is published immediately upon receiving a new reading, without any additional validity or time-gap checks.

Code References

  • BLE Scan Callback: scanCompleteCallback() in main.ino processes both main and borehole sensors.
  • Borehole Sensor Variables: bh_adv_id, bh_ble_service_data, bh_sensorType, bh_raw_zero, bh_height, bh_level_known, bh_raw_known, bh_tank_level, etc.
  • Activation Flag: borehole_active boolean, loaded from preferences.
  • Pressure Processing: bh_pressure_process() in main.ino converts borehole sensor data to a level.
  • MQTT Publishing: Borehole sensor data is published to MQTT topics directly in the BLE scan callback.

Data Flow for Borehole Sensor

  1. Borehole BLE Sensor advertises its readings.
  2. Base Station scans for BLE advertisements.
  3. If borehole_active is true and the borehole sensor is detected, its service data is parsed.
  4. The raw data is converted to a borehole level using borehole calibration parameters.
  5. The borehole level and raw data are published to MQTT topics (bh_ble_data, bh_ble_data_raw, borehole_level) immediately.