Skip to content

Instantly share code, notes, and snippets.

@Tmbao
Created October 3, 2023 22:27
Show Gist options
  • Select an option

  • Save Tmbao/5e45203a6b9cf560f48842c2623baba7 to your computer and use it in GitHub Desktop.

Select an option

Save Tmbao/5e45203a6b9cf560f48842c2623baba7 to your computer and use it in GitHub Desktop.
Holman BX1 ESP Adapter
esphome:
name: irrigation-controller
friendly_name: Irrigation Controller
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "<TODO>"
services:
- service: start_garden_tap
variables:
running_time_mins: int
then:
- if:
condition:
lambda: return running_time_mins <= 0 || running_time_mins >= 60;
then:
- logger.log:
level: ERROR
format: "Invalid running time minutes: %d"
args: [running_time_mins]
else:
- lambda: id(watering_triggered_min) = running_time_mins;
- esp32_ble_tracker.start_scan:
- service: stop_garden_tap
then:
- lambda: id(watering_triggered_min) = -1;
- esp32_ble_tracker.start_scan:
ota:
password: "<TODO>"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Irrigation-Controller"
password: "<TODO>"
globals:
# -1 for OFF, 0 for NO_ACTION, 1 for ON
- id: watering_triggered_min
type: int
restore_value: no
initial_value: '0'
captive_portal:
esp32_ble:
io_capability: keyboard_display
esp32_ble_tracker:
scan_parameters:
interval: 5s
window: 2s
active: false
ble_client:
- mac_address: "<TODO> - Find this in the holman app"
id: garden_bx1_tap
on_passkey_request:
then:
- ble_client.passkey_reply:
id: garden_bx1_tap
passkey: 174142
on_numeric_comparison_request:
then:
- logger.log:
format: "Compare this passkey with the one on your BLE device: %06d"
args: [ passkey ]
- ble_client.numeric_comparison_reply:
id: garden_bx1_tap
accept: True
on_connect:
then:
- wait_until: # wait until characteristic is discovered
condition:
lambda: |-
esphome::ble_client::BLEClient* client = id(garden_bx1_tap);
esphome::ble_client::BLECharacteristic* chr_passcode = client->get_characteristic(0x21);
esphome::ble_client::BLECharacteristic* chr_watering = client->get_characteristic(0x18);
return chr_passcode != nullptr && chr_watering != nullptr;
timeout: 5s
- lambda: |-
ESP_LOGD("ble_client_lambda", "Connected to Garden-BX1");
esphome::ble_client::BLEClient* client = id(garden_bx1_tap);
if (id(watering_triggered_min) == 0) {
ESP_LOGI("main", "Setting up passcode to stop advertising!");
esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(0x21);
if (chr == nullptr) {
ESP_LOGW("main", "[0x21] Characteristic not found. State update can not be written.");
} else {
unsigned char val[2] = {
0xae, 0x8e
};
int status = esp_ble_gattc_write_char(
client->get_gattc_if(),
client->get_conn_id(),
chr->handle,
sizeof(val),
val,
ESP_GATT_WRITE_TYPE_NO_RSP,
ESP_GATT_AUTH_REQ_NONE
);
if (status) {
ESP_LOGW("main", "Error settting up passcode, status=%d", status);
} else {
ESP_LOGI("main", "Passcode setup successfully");
}
}
} else if (id(watering_triggered_min) > 0) {
ESP_LOGI("main", "Starting tap!");
esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(0x18);
if (chr == nullptr) {
ESP_LOGW("main", "[0x18] Characteristic not found. State update can not be written.");
} else {
unsigned char val[10] = {
0x01, 0x00, 0x00, (char) id(watering_triggered_min), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int status = esp_ble_gattc_write_char(
client->get_gattc_if(),
client->get_conn_id(),
chr->handle,
sizeof(val),
val,
ESP_GATT_WRITE_TYPE_NO_RSP,
ESP_GATT_AUTH_REQ_NONE
);
if (status) {
ESP_LOGW("main", "Error sending write value to BLE gattc server, status=%d", status);
} else {
ESP_LOGI("main", "Tap started successfully!");
}
}
id(watering_triggered_min) = 0;
} else {
ESP_LOGI("main", "Stopping tap!");
esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(0x18);
if (chr == nullptr) {
ESP_LOGW("main", "[0x18] Characteristic not found. State update can not be written.");
} else {
unsigned char val[10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int status = esp_ble_gattc_write_char(
client->get_gattc_if(),
client->get_conn_id(),
chr->handle,
sizeof(val),
val,
ESP_GATT_WRITE_TYPE_NO_RSP,
ESP_GATT_AUTH_REQ_NONE
);
if (status) {
ESP_LOGW("main", "Error sending write value to BLE gattc server, status=%d", status);
} else {
ESP_LOGI("main", "Tap stopped successfully!");
}
}
id(watering_triggered_min) = 0;
}
- esp32_ble_tracker.stop_scan:
sensor:
- platform: internal_temperature
name: "Irrigation Controller Internal Temperature"
@ModLogNet
Copy link

Hi I'm adapting this to work with the BX4's as well, I noticed that you have this listed as private, would you prefer I not release my changes?

@Tmbao
Copy link
Author

Tmbao commented May 6, 2024

Hi @ModLogNet I think this script is not well polished enough, and people should take extra precautious when using, so I'm reluctant to make this a proper repository, maybe you can create your own gist for BX4 and we can link each other's gist so that other people can find them :). But I've made it public just in case your BX4 change is also compatible with BX1, then you're welcome to update this :)

@PBMikeW
Copy link

PBMikeW commented Jan 12, 2025

@Tmbao You are a legend, I had my device running in 5 minutes with this. Spent ages trying to get it running with Tuya ble to no avail.

@nickw444
Copy link

Interestingly the MAC address reported in the Holman app for me wasn't the true peripheral BLE Mac Address - I managed to sniff it with a Nordic sniffer to find a slightly different address. App reported C7:34:2C:92:10:38 but the working MAC for this was f8:10:92:2c:34:c7 (reversed order and different start byte)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment