It’s been a long while since I wrote something interesting in this blog. Well, since I’m no copywriter, have no ads and don’t use any dumbass neural nets and write everything by hand – it does take a while. And today I got an interesting thing to write about. I got my hands on a weird thing – ujin aqua leak sensors. In some countries they are provided by the developer along with a newly built house/apartment. Just that like ‘first free doze’. So I decided to have a look if it’s possible to ‘decloud’ and hook it to Home Assistant and also check what’s inside.

Enclosure
Just a small rectangle. The top surface is a regular push button that can be used to check connectivity and pair it with leak controller. No weird stuff here. Pogo pins on the bottom that actually ‘sense’ water.

First thing you notice – it’s not waterproof! The case is easy to pry open, no rubber detected (!)

The PCB has no anti-corrosive coating, no immersion gold plating (just regular HASL), so corrosion in wet areas is most likely. Here’s the PCB itself. The battery looks huge, just like the caps all around the place. Seems like we have something very tricky going on there, but more about that later.

Now let’s compare with a cheaper alternative – Aqara Water Leak sensor.


That one has a sealed enclosure and the battery holder has a rubber ring protecting the inner parts from any water. The screws on bottom also allow to easily hook a sensor cable, so that one device can cover bigger area.
So far the biggest drawback is:
The sensor lacks proper waterproofing and is very likely to die from corrosion pretty soon!
The hardware
After finishing my rant about the enclosure and lack of waterproofing, I disassembled the device, noted the huge battery and put under my microscope for detailed analysis.





That was a huge surprise for me. It’s just “good old” nrf, right? I had a long story working with those modules and even wrote about some of my struggles with crappy modules here and here. Even before that I wrote a bootloader for it now almost 11 years ago, in 2014.
Even I, despite having a ton of nRF24L01 boards for my smarthome (some dating back as fat as 2012) first moved them from a homebrew solution to mysensors in 2020, and now moving on to WiFi or Zigbee. And crappy signal quality was one of the reasons to do that.

In any case, this is definetely not what I expected to see in serious ‘production’.
nRF24L01 clone called SI24R1 is different from original. It is capable of higher transmission power and that hints that the developers stumbled on the same problems as me: signal quality was trash. So how did they solve that? Here’s what SI24R1 datasheet writes about TX power.

Still, seems that was NOT sufficient, so after SI24R1 there’s another chip to solve issues in the most brutal way.. CB2401 from some company called chipbetter. Google found a datasheet in the very first link.
From that I learned that the whole thing can broadcast as loud as +22dBm. (With +20dBm being the upper legal limit in my country). It also consumes about 100mA during TX (peak current is even bigger – 350mA).
Here’s the reason why we need those huge caps. Since the tablet cells can’t provide big current they’ve put a ton of caps for make sure it works. Even more than needed since some places were not populated. Unfortunately, electrolytic caps tend to have some leakage current (that pretty much depends on the quality, though).
PCB antennas tend to be not even in their emission direction, so the’ve hooked up a huge antenna module. Why not ceramic? No idea, but it really doesn’t really matter.
So, if it’s a 4 layer pcb, they might’ve even done impedance control, so the RF paths might be nice after all and not providing a lot of noise. If only they didn’t cheap out on immersion gold plating – perhaps that could’ve improved device survivability in wet environment. Although with the whole battery to corrode that wouldn’t be a really big issue.
So, to sum up: it works, it’s brutal and looks like somebody was looking for adventures during development. Single-chip solutions are available for everything: bluetooth, zigbee and even those MCUs with built-in nRF24L01 and I have no idea why the developers didn’t use any of those.
The software stack
nRF24L01 as well as SI24R01 is NOT bluetooth. So either the sticker lies, or… Somebody read about an old hack how you can use nRF24L01 to send bluetooth LE advertisement messages with a little bit of vendor data bundled. And next that hack solution goes into production. Per rectum ad astra, as one of my friends would call it.
That basically tells us 2 things: The link between controller and leak sensor is unencrypted, unidirectional and all the data is to be found in the vendor section of le broadcast message.
So I powered up BT on my phone, shorted the pogo pins of the sensor. New devices appeared. It’s named as LD-S. No clue how ofter advertisement messages are sent out when there’s no leak. I bet the BLE spec is not really followed here. Basically this is really the thing that determines the battery life in the end since a LOT of power is consumed during TX.
Checking the concept
I dived into my closet and picked up one of my esp32 boards. Threw a silly configuration that would dump all the vendor data bytes. It looked like this:
esphome:
name: $devicename
build_path: build/$devicename
esp32:
# framework:
# type: esp-idf
# version: recommended
board: esp32doit-devkit-v1
api:
substitutions:
devicename: "leaktest"
logger:
level: DEBUG
baud_rate: 0
wifi:
networks:
- ssid: !secret wifi_ssid
password: !secret wifi_pwd
ota:
- platform: esphome
password: updateme
esp32_ble_tracker:
on_ble_advertise:
- mac_address:
- XX:XX:XX:XX:XX:XX
then:
- lambda: |-
ESP_LOGD("ble_adv", "New BLE device");
ESP_LOGD("ble_adv", " address: %s", x.address_str().c_str());
ESP_LOGD("ble_adv", " name: %s", x.get_name().c_str());
ESP_LOGD("ble_adv", " Advertised service UUIDs:");
for (auto uuid : x.get_service_uuids()) {
ESP_LOGD("ble_adv", " - %s", uuid.to_string().c_str());
}
ESP_LOGD("ble_adv", " Advertised service data:");
for (auto data : x.get_service_datas()) {
ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
}
ESP_LOGD("ble_adv", " Advertised manufacturer data:");
for (auto data : x.get_manufacturer_datas()) {
ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
ESP_LOGD("ble_adv", " %x %x %x %x %x ", data.data[0], data.data[1], data.data[2], data.data[3], data.data[4]);
}
web_server:
Next I tried shorting the sensor and pressing the button. That’s what I saw in the log.
[22:50:07][D][ble_adv:040]: New BLE device
[22:50:07][D][ble_adv:041]: address: XXXXXXXXXXXXXXXX
[22:50:07][D][ble_adv:042]: name: LD-S
[22:50:07][D][ble_adv:043]: Advertised service UUIDs:
[22:50:07][D][ble_adv:047]: Advertised service data:
[22:50:07][D][ble_adv:051]: Advertised manufacturer data:
[22:50:07][D][ble_adv:053]: - 0xFFFF: (length 5)
[22:50:07][D][ble_adv:054]: 3 7 64 0 4c
First 3 bytes of the vendor data didn’t seem to change. Remained constant at 3 7 64. The last byte looked like the report number. It always incremented whenever any of the data changed. And the third byte was the one holding interesting data. It looked like a bitfield with encoded leak detection, button short and long press and other things.
theoretically there should also be the battery state, but without hooking it to lab supply to imitate discharged battery that wouldn’t be possible to find out. At this point I stopped the experiment to same time.
Writing a component and hooking it to, say, esphome is now mostly mechanical job. These sensors will work with no issues. The big question is: is it worth it? Buying more of them is not worth the coin: they cost more and are less durable than other vendors.
The summary
The sensor will likely last a year or two, depending on the environment. Pogo pins will stop working if any water touches them (steel springs in the pogo pins I had were very quick to catch rust). May not be critical, but who knows?
You can protect it from corrosion by applying sealant on the edges, preferably in a way it can be later removed and use it anyway. But as for me – I decided to just abandon these. They were just not worth the effort.
Next on my list is a little review of their leak controller. People I know told me it was prone to overheat and even sent me this nice picture from a thermal cam. But that post would be at least maybe several months from now on.
