Field notes · battery-powered BLE irrigation controllers

Your irrigation timer already talks. It just doesn't talk Wi-Fi.

Battery tap timers and valve controllers speak Bluetooth LE to a phone app and nothing else. A small bridge puts them on Wi-Fi, into Home Assistant, and under real automation. Here is the working software, the protocol detail you'll need, and the parts.

Galcon 6100 series Home Assistant / MQTT Battery decoding published here first
A watered garden on the left, a solar array being rinsed on the right, joined by a light arc
One controller, two jobs: the garden and the panels.

Start with the software

You do not need to write any of this yourself. There is a maintained open-source project that already does the hard part: it connects to the controller, reads live status, edits schedules, and publishes everything to MQTT with Home Assistant auto-discovery.

Open source · Python

py-galcon-bt-control

Desktop GUI with live status and schedule editing, command-line tools, and an MQTT bridge with Home Assistant auto-discovery. Windows installer for x64 and ARM64; runs fine headless on a Raspberry Pi. Not affiliated with the manufacturer.

Get it on GitHub →

Install that first and confirm you can see your controller. Everything below assumes it is running and talking.

What this page adds

The project above documents the service, the characteristics, the active-zone byte and the open/close commands. Those are settled and this page does not restate them as new. What follows is the part that was still open — most of the status frame, and the battery.

FieldWhereStatus
Service & characteristicsalready documented
Active zones, remaining timestatus[0], [2–3]already documented
Valve open / closecmd[0], [1]already documented
Battery level and low thresholdstatus[10–11]new here
Input voltage, power ratingstatus[1]new here
Sensor wet, master, fertilizer, ACstatus[9]new here
Rain-off days remainingstatus[12]new here
Valve count, DC/AC typestatus[13]new here
Firmware, signal, water budgetstatus[14–16]new here
Duration as h / m / scmd[3–5]refined
Rain-off and water-budget commandscmd[2], [6], [7]new here

The battery reading

This is the field everyone gets wrong, and there is a good reason for it. Byte 10 on its own looks like nonsense — it climbs and wraps and never behaves like a percentage. It is not a percentage. It is the low half of a 16-bit value.

batteryLevel = status[11] << 8 | status[10]     # little-endian, raw ADC counts

lowBattery   = batteryLevel <= 3123    when input is  9 V
             = batteryLevel <= 2947    when input is 18 V

The number is a raw converter count, not millivolts and not a percentage. Do not render it as volts — a fabricated unit is worse than an honest raw figure. What makes it useful is that the thresholds above are the same ones the controller's own app uses to decide when to warn you, so an integration can raise "battery low" at exactly the right moment instead of at a guessed number.

Once you can read the level9V alkaline, multipackWith a real battery reading you can stock replacements before a zone silently stops watering.

Which threshold applies

Bit 6 of status[1] tells you the controller's input voltage: set means 18 V, clear means 9 V. Read it per frame rather than assuming — the same protocol covers both.

inputVolts = (status[1] >> 6) & 1 ? 18 : 9

A worked example. A resting frame of ff 00 … 08 a6 0e 00 db 2f b1 64 gives byte 10 = 0xa6 (166) and byte 11 = 0x0e (14), so the level is 14×256 + 166 = 3750. Byte 1 is zero, so the input is 9 V and the threshold is 3123. The pack is healthy.

The rest of the status frame

Twenty bytes, read from the status characteristic. Offsets not listed here are either already covered by the project above or have no established meaning.

ByteMeaningHow to read it
1Input voltage, power ratingbit6 → 18 V / 9 V  ·  bit7 → rating
9Device flagsbit0 sensor wet · bit1 master open · bit2 fertilizer · bit3 AC present
10–11Battery levelLE16, raw counts
12Rain-off days remaining0 = not in rain-off
13Valve count and supply typebits0–2 → lookup below  ·  bit3 set = DC
14Firmware versioninteger
15Signal strengthunsigned — subtract 256 for dBm
16Water budgetpercent

Valve count lookup

Bits 0–2 of byte 13, read least-significant first and concatenated, index a table rather than encoding the count directly:

{ 000: 0,  100: 1,  010: 2,  110: 4,
  001: 6,  101: 9,  011: 12, 111: 12 }

So a controller reporting 110 has four valves. Worth checking against what your own bridge enumerates — if the two disagree, trust the bridge and tell me.

Commands beyond open and close

The command frame is twenty bytes, all zero except the fields you set. Byte 2 acts as an opcode for the device-wide settings; the valve commands leave it at zero.

ByteFieldEncoding
0Close valvezone number
1Open valve0x80 | zone number
2Opcode1 = rain-off   2 = water budget
3–5Durationhours, minutes, seconds
6Rain-off days0 clears it
7Water budgetpercent

Duration is a full h/m/s triple, not a single minutes byte. That matters for the short cycles these controllers are good at — ten-second bursts for propagation misting, or the sub-minute pulses a panel rinse wants.

Give the capacitor time

Battery models drive a latching solenoid from a capacitor, and the capacitor needs to charge before it can throw the valve. The app waits a full six seconds after connecting before it sends any valve command. If your writes are accepted but the valve never moves, this is almost always why — shorter empirical waits work most of the time, which is exactly what makes the failure so confusing.

The bridge boardESP32-C3 SuperMiniWi-Fi and BLE on one chip. Sits within radio reach of the controller and relays to your network.

What you need to build the bridge

The controller only speaks Bluetooth LE, and BLE range is short. The bridge is a small board that sits within radio reach of the controller, holds a Wi-Fi link back to your network, and relays between the two.

Affiliate disclosure. The product links below are affiliate links. If you buy through them the price is unchanged for you and this page earns a small commission. Prices were correct when the page was built and will drift.

The bridge itself

Bridge boardESP32-C3 SuperMiniWi-Fi and BLE on one chip, thumbnail-sized, runs on USB power. The cheapest thing that does the whole job.$3.73View on AliExpress
AlternativeESP32-S3 / C3 ZeroMore memory and IO if you want the bridge to drive anything else — a relay, a flow meter, a moisture probe.$4.38View on AliExpress
EnclosureIP67 clear project boxThe bridge lives outdoors near the valves. A clear lid lets the status LED through without opening it.$4.80View on AliExpress
EnclosureIP67 box with haspLarger, hinged, easier to open in the field if you expect to touch the hardware more than once.$8.51View on AliExpress

For the controller

Power9V alkaline, multipackNow that you can read the real battery level, you can stock replacements before a zone silently stops watering.$7.06View on AliExpress
Power9V 1100mAh alkalineHigher capacity cells for controllers driving several valves through a full season.$11.52View on AliExpress
ValveDC latching solenoidThe valve type these controllers drive. Useful as a spare, or to add a zone the controller already supports.$18.20View on AliExpress

Application: washing solar panels on a schedule

Solar array with a sprinkler manifold misting the panel glass at sunrise
A row of nozzles along the array turns an expensive call-out into a schedule.

This is the use that justified the whole exercise, and it is not what these controllers are sold for.

Rooftop panels lose output to dust. The usual answer is to book a cleaner a few times a year, which is expensive and badly timed — you pay whether the panels needed it or not. A few irrigation valves plumbed to sprayers along the array turn that into a scheduled rinse, and once the controller is on Wi-Fi the schedule can respond to conditions instead of a calendar.

Two things make this work properly, and both need the controller to be readable rather than just writable:

Short cycles matter here, which is why the h/m/s duration encoding above is worth having — a panel rinse is a couple of minutes per zone, staggered, not a garden soak.

Manual backupWater-fed pole brush kit, 12–15ftFor the twice-a-year deep clean the sprayers won't do, and for reaching panels the fixed nozzles miss.$45.95View on AliExpress

Use mains or filtered water if you can. Hard water dries to a mineral film that costs you more output than the dust did.

Application: the garden it was built for

The ordinary use, done properly once the controller is no longer a black box.

Out of the box these timers run a fixed weekly schedule that you edit by crouching in front of the unit with your phone. On Wi-Fi, the same hardware becomes something you can drive from conditions: skip a cycle after rain, shorten everything in a cool week with the water-budget command, extend it in a heatwave, and get a notification when a battery is genuinely low rather than when a zone has already failed silently.

The water budget is the underused one. It scales every programmed duration by a percentage in a single write — opcode 2 with a percent in byte 7 — so seasonal adjustment does not mean rewriting every schedule record.

DistributionDIY drip irrigation kit, 10–30mDrippers, tubing and connectors to get from the valve to the plants. The controller handles timing; this handles delivery.$10.34View on AliExpress
DistributionMicro drip system, 20m adjustableAdjustable emitters for pots and balconies, where per-plant flow varies more than in a bed.$7.16View on AliExpress

What else opens up

Once status is readable and commands are writable from your own code, the controller stops being an appliance and becomes a component.

Other Bluetooth irrigation controllers

This page is about one family. Several other BLE timers have community work behind them, at varying depth. Rather than restate any of it, here is where to look.

ControllerWhere the work is
Galcon 9001BT / 11000suborb/GalconController — Python, documents a shorter 7-byte frame format used by that generation
Galcon 9001BT on ESP32sr01/gl9001-esphome — an ESPHome component, the closest thing to a drop-in Wi-Fi bridge
Generic BLE deviceszewelor/bt-mqtt-gateway and devbis/ble2mqtt — extensible BLE-to-MQTT gateways worth starting from for an unsupported timer

The two Galcon generations are not compatible: the newer one uses 20-byte frames and a different service, the older one 7-byte frames. Code written for one will connect to the other and then quietly do nothing useful.

Also on this site