[DISC] Add runtime configuration for OpenHAB (#1658)

* [DISC] Add runtime configuration for OpenHAB

Add an MQTT configurable system key "ohdiscovery" for OpenHAB auto discovery

* Docs and environments update
This commit is contained in:
Florian authored and GitHub committed 2023-05-31 11:35:35 -05:00
1 parent 4a28f491f5
commit 6e23ca029b
11 files changed
+83 -128

No files matched your search

-2
View File
@@ -19,7 +19,6 @@ jobs:
- "esp32dev-gf-sun-inverter" - "esp32dev-gf-sun-inverter"
- "esp32dev-ir" - "esp32dev-ir"
- "esp32dev-ble" - "esp32dev-ble"
- "esp32dev-ble-openhab"
- "esp32dev-ble-mqtt-undecoded" - "esp32dev-ble-mqtt-undecoded"
- "esp32dev-ble-aws" - "esp32dev-ble-aws"
- "esp32feather-ble" - "esp32feather-ble"
@@ -60,7 +59,6 @@ jobs:
- "nodemcuv2-rf-cc1101" - "nodemcuv2-rf-cc1101"
- "nodemcuv2-somfy-cc1101" - "nodemcuv2-somfy-cc1101"
- "manual-wifi-test" - "manual-wifi-test"
- "openhab-test"
- "nodemcuv2-mqtt-fw-test" - "nodemcuv2-mqtt-fw-test"
- "rf-wifi-gateway" - "rf-wifi-gateway"
- "nodemcuv2-rf2" - "nodemcuv2-rf2"
-3
View File
@@ -7,9 +7,6 @@ So as to use the autodiscovery function you need to have:
* The Jinga transformation addon installed * The Jinga transformation addon installed
* The Json transformation addon installed * The Json transformation addon installed
You need to set `OpenHABAutoDiscovery` to true into `config_mqttDiscovery.h`
`#define OpenHABDiscovery true`
::: tip ::: tip
If you are connecting to BLE devices it is highly recommended to set `filterConnectable` to `true` in [BT configuration](../use/ble.md#advanced-filter-out-connectable-devices). Otherwise you may encounter incomplete data. If you are connecting to BLE devices it is highly recommended to set `filterConnectable` to `true` in [BT configuration](../use/ble.md#advanced-filter-out-connectable-devices). Otherwise you may encounter incomplete data.
::: :::
+5 -1
View File
@@ -64,7 +64,7 @@ Bravo👏, second step done! Now let's add the Jinja transformation service.
Second step done! Second step done!
## Upload OpenMQTTGateway to an ESP32 ## Upload OpenMQTTGateway to an ESP32
[Upload OpenMQTTGateway from the web](../upload/web-install.md) by selecting `esp32dev-ble-openhab` [Upload OpenMQTTGateway from the web](../upload/web-install.md) by selecting the environment corresponding to your need.
Or use another upload method from the Upload section. Or use another upload method from the Upload section.
@@ -75,6 +75,10 @@ Or use another upload method from the Upload section that requires credentials b
You should see the gateway connected to your broker by checking with an MQTT client like MQTT Explorer. You should see the gateway connected to your broker by checking with an MQTT client like MQTT Explorer.
To make the auto discovery compatible with OpenHAB you have to send the following command with a retain flag.
`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"ohdiscovery":true}'`
## Adding the things ## Adding the things
1. From the Administration click on "Things" under "Settings", you should see a number in the INBOX button 1. From the Administration click on "Things" under "Settings", you should see a number in the INBOX button
+9
View File
@@ -33,6 +33,15 @@ If you want the settings to be kept upon gateway restart, you can publish the co
Auto discovery is enable by default on release binaries, on platformio (except for UNO). With Arduino IDE please read the [advanced configuration section](../upload/advanced-configuration#auto-discovery) of the documentation. Auto discovery is enable by default on release binaries, on platformio (except for UNO). With Arduino IDE please read the [advanced configuration section](../upload/advanced-configuration#auto-discovery) of the documentation.
::: :::
## AutoDiscovery compatible with OpenHAB (default: false)
OpenHAB does not support the key `is_defined` in the json template, to remove it at runtime and make the auto discovery compatible you can use the following command with a retain flag.
`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"ohdiscovery":true}'`
::: tip
This command can also be used with other controllers that does not support the is_defined key.
:::
## Change the WiFi credentials ## Change the WiFi credentials
`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"wifi_ssid":"ssid", "wifi_pass":"password"}'` `mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"wifi_ssid":"ssid", "wifi_pass":"password"}'`
-29
View File
@@ -239,23 +239,6 @@ build_flags =
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
custom_description = Regular BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices custom_description = Regular BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices
[env:esp32dev-ble-openhab]
platform = ${com.esp32_platform}
board = esp32dev
board_build.partitions = min_spiffs.csv
lib_deps =
${com-esp32.lib_deps}
${libraries.ble}
${libraries.decoder}
build_flags =
${com-esp32.build_flags}
'-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2'
'-DLED_SEND_RECEIVE_ON=0'
'-DOpenHABDiscovery=true'
'-DGateway_Name="OMG_ESP32_BLE_OH"'
custom_description = BLE gateway with OpenHAB discovery and adaptive scanning activated, automatically adapts the scan parameters depending on your devices
[env:esp32dev-ble-mqtt-undecoded] [env:esp32dev-ble-mqtt-undecoded]
platform = ${com.esp32_platform} platform = ${com.esp32_platform}
board = esp32dev board = esp32dev
@@ -1222,18 +1205,6 @@ build_flags =
'-DGateway_Name="OMG_TEST_MANUAL_WIFI"' '-DGateway_Name="OMG_TEST_MANUAL_WIFI"'
board_build.flash_mode = dout board_build.flash_mode = dout
[env:openhab-test]
platform = ${com.esp8266_platform}
board = nodemcuv2
lib_deps =
${com-esp.lib_deps}
${libraries.wifimanager8266}
build_flags =
${com-esp.build_flags}
'-DOpenHABDiscovery=true'
'-DGateway_Name="OMG_TEST_OPENHAB"'
board_build.flash_mode = dout
[env:nodemcuv2-mqtt-fw-test] [env:nodemcuv2-mqtt-fw-test]
platform = ${com.esp8266_platform} platform = ${com.esp8266_platform}
board = nodemcuv2 board = nodemcuv2
-4
View File
@@ -1102,11 +1102,7 @@ void launchBTDiscovery(bool overrideDiscovery) {
Log.trace(F("Name: %s"), prop.value()["name"].as<const char*>()); Log.trace(F("Name: %s"), prop.value()["name"].as<const char*>());
String entity_name = String(model_id.c_str()) + "-" + String(prop.key().c_str()); String entity_name = String(model_id.c_str()) + "-" + String(prop.key().c_str());
String unique_id = macWOdots + "-" + String(prop.key().c_str()); String unique_id = macWOdots + "-" + String(prop.key().c_str());
# if OpenHABDiscovery
String value_template = "{{ value_json." + String(prop.key().c_str()) + "}}";
# else
String value_template = "{{ value_json." + String(prop.key().c_str()) + " | is_defined }}"; String value_template = "{{ value_json." + String(prop.key().c_str()) + " | is_defined }}";
# endif
if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::SBS1 && strcmp(prop.key().c_str(), "state") != 0) { if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::SBS1 && strcmp(prop.key().c_str(), "state") != 0) {
String payload_on = "{\"SBS1\":\"on\",\"mac\":\"" + String(p->macAdr) + "\"}"; String payload_on = "{\"SBS1\":\"on\",\"mac\":\"" + String(p->macAdr) + "\"}";
String payload_off = "{\"SBS1\":\"off\",\"mac\":\"" + String(p->macAdr) + "\"}"; String payload_off = "{\"SBS1\":\"off\",\"mac\":\"" + String(p->macAdr) + "\"}";
-7
View File
@@ -127,17 +127,10 @@ void launchRTL_433Discovery(bool overrideDiscovery) {
String idWoKey = pdevice->uniqueId; String idWoKey = pdevice->uniqueId;
idWoKey.remove(idWoKey.length() - (strlen(parameters[i][0]) + 1)); idWoKey.remove(idWoKey.length() - (strlen(parameters[i][0]) + 1));
DISCOVERY_TRACE_LOG(F("idWoKey %s" CR), idWoKey.c_str()); DISCOVERY_TRACE_LOG(F("idWoKey %s" CR), idWoKey.c_str());
# if OpenHABDiscovery
String value_template = "{{ value_json." + String(parameters[i][0]) + "}}";
if (strcmp(parameters[i][0], "battery_ok") == 0)) {
value_template = "{{ float(value_json." + String(parameters[i][0]) + ") * 99 + 1 }}"; // https://github.com/merbanan/rtl_433/blob/93f0f30c28cfb6b82b8cc3753415b01a85bee91d/examples/rtl_433_mqtt_hass.py#L187
}
# else
String value_template = "{{ value_json." + String(parameters[i][0]) + " | is_defined }}"; String value_template = "{{ value_json." + String(parameters[i][0]) + " | is_defined }}";
if (strcmp(parameters[i][0], "battery_ok") == 0) { if (strcmp(parameters[i][0], "battery_ok") == 0) {
value_template = "{{ float(value_json." + String(parameters[i][0]) + ") * 99 + 1 | is_defined }}"; // https://github.com/merbanan/rtl_433/blob/93f0f30c28cfb6b82b8cc3753415b01a85bee91d/examples/rtl_433_mqtt_hass.py#L187 value_template = "{{ float(value_json." + String(parameters[i][0]) + ") * 99 + 1 | is_defined }}"; // https://github.com/merbanan/rtl_433/blob/93f0f30c28cfb6b82b8cc3753415b01a85bee91d/examples/rtl_433_mqtt_hass.py#L187
} }
# endif
String topic = subjectRTL_433toMQTT; String topic = subjectRTL_433toMQTT;
# if valueAsATopic # if valueAsATopic
// Remove the key from the unique id to extract the device id // Remove the key from the unique id to extract the device id
+21 -2
View File
@@ -192,6 +192,20 @@ void announceDeviceTrigger(bool use_gateway_info, char* topic, char* type, char*
pub_custom_topic((char*)topic_to_publish.c_str(), sensor, true); pub_custom_topic((char*)topic_to_publish.c_str(), sensor, true);
} }
/*
* Remove a substring p from a given string s
*/
std::string remove_substring(std::string s, const std::string& p) {
std::string::size_type n = p.length();
for (std::string::size_type i = s.find(p);
i != std::string::npos;
i = s.find(p))
s.erase(i, n);
return s;
}
/** /**
* @brief Generate message and publish it on an MQTT discovery explorer. For HA @see https://www.home-assistant.io/docs/mqtt/discovery/ * @brief Generate message and publish it on an MQTT discovery explorer. For HA @see https://www.home-assistant.io/docs/mqtt/discovery/
* *
@@ -280,8 +294,13 @@ void createDiscovery(const char* sensor_type,
sensor["uniq_id"] = unique_id; //unique_id sensor["uniq_id"] = unique_id; //unique_id
if (retainCmd) if (retainCmd)
sensor["retain"] = retainCmd; // Retain command sensor["retain"] = retainCmd; // Retain command
if (value_template[0]) if (value_template[0]) {
sensor["val_tpl"] = value_template; //value_template if (strstr(value_template, " | is_defined") != NULL && OpenHABDisc) {
sensor["val_tpl"] = remove_substring(value_template, " | is_defined"); //OpenHAB compatible HA auto discovery
} else {
sensor["val_tpl"] = value_template; //HA Auto discovery
}
}
if (payload_on[0]) { if (payload_on[0]) {
if (strcmp(sensor_type, "button") == 0) { if (strcmp(sensor_type, "button") == 0) {
sensor["pl_prs"] = payload_on; // payload_press for a button press sensor["pl_prs"] = payload_on; // payload_press for a button press
+40 -77
View File
@@ -135,83 +135,46 @@ void announceDeviceTrigger(bool use_gateway_info,
# define OpenHABDiscovery false # define OpenHABDiscovery false
#endif #endif
#if OpenHABDiscovery // OpenHAB autodiscovery value key definition (is defined command is not supported by OpenHAB) boolean OpenHABDisc = OpenHABDiscovery;
# define jsonBatt "{{ value_json.batt }}"
# define jsonLux "{{ value_json.lux }}" // Home assistant autodiscovery value key definition
# define jsonPres "{{ value_json.pres }}" #define jsonBatt "{{ value_json.batt | is_defined }}"
# define jsonFer "{{ value_json.fer }}" #define jsonLux "{{ value_json.lux | is_defined }}"
# define jsonFor "{{ value_json.for }}" #define jsonPres "{{ value_json.pres | is_defined }}"
# define jsonMoi "{{ value_json.moi }}" #define jsonFer "{{ value_json.fer | is_defined }}"
# define jsonHum "{{ value_json.hum }}" #define jsonFor "{{ value_json.for | is_defined }}"
# define jsonStep "{{ value_json.steps }}" #define jsonMoi "{{ value_json.moi | is_defined }}"
# define jsonWeight "{{ value_json.weight }}" #define jsonHum "{{ value_json.hum | is_defined }}"
# define jsonPresence "{{ value_json.presence }}" #define jsonStep "{{ value_json.steps | is_defined }}"
# define jsonAltim "{{ value_json.altim }}" #define jsonWeight "{{ value_json.weight | is_defined }}"
# define jsonAltif "{{ value_json.altift }}" #define jsonPresence "{{ value_json.presence | is_defined }}"
# define jsonTempc "{{ value_json.tempc }}" #define jsonAltim "{{ value_json.altim | is_defined }}"
# define jsonTempc2 "{{ value_json.tempc2 }}" #define jsonAltif "{{ value_json.altift | is_defined }}"
# define jsonTempc3 "{{ value_json.tempc3 }}" #define jsonTempc "{{ value_json.tempc | is_defined }}"
# define jsonTempc4 "{{ value_json.tempc4 }}" #define jsonTempc2 "{{ value_json.tempc2 | is_defined }}"
# define jsonTempf "{{ value_json.tempf }}" #define jsonTempc3 "{{ value_json.tempc3 | is_defined }}"
# define jsonMsg "{{ value_json.message }}" #define jsonTempc4 "{{ value_json.tempc4 | is_defined }}"
# define jsonVal "{{ value_json.value }}" #define jsonTempf "{{ value_json.tempf | is_defined }}"
# define jsonVolt "{{ value_json.volt }}" #define jsonMsg "{{ value_json.message | is_defined }}"
# define jsonCurrent "{{ value_json.current }}" #define jsonVal "{{ value_json.value | is_defined }}"
# define jsonPower "{{ value_json.power }}" #define jsonVolt "{{ value_json.volt | is_defined }}"
# define jsonEnergy "{{ value_json.energy }}" #define jsonCurrent "{{ value_json.current | is_defined }}"
# define jsonGpio "{{ value_json.gpio }}" #define jsonPower "{{ value_json.power | is_defined }}"
# define jsonFtcd "{{ value_json.ftcd }}" #define jsonEnergy "{{ value_json.energy | is_defined }}"
# define jsonWm2 "{{ value_json.wattsm2 }}" #define jsonGpio "{{ value_json.gpio | is_defined }}"
# define jsonAdc "{{ value_json.adc }}" #define jsonFtcd "{{ value_json.ftcd | is_defined }}"
# define jsonPa "{{ float(value_json.pa) * 0.01 }}" #define jsonWm2 "{{ value_json.wattsm2 | is_defined }}"
# define jsonId "{{ value_json.id }}" #define jsonAdc "{{ value_json.adc | is_defined }}"
# define jsonAddress "{{ value_json.address }}" #define jsonPa "{{ float(value_json.pa) * 0.01 | is_defined }}"
# define jsonOpen "{{ value_json.open }}" #define jsonId "{{ value_json.id | is_defined }}"
# define jsonTime "{{ value_json.time }}" #define jsonAddress "{{ value_json.address | is_defined }}"
# define jsonCount "{{ value_json.count }}" #define jsonOpen "{{ value_json.open | is_defined }}"
# define jsonAlarm "{{ value_json.alarm }}" #define jsonTime "{{ value_json.time | is_defined }}"
# define jsonInuse "{{ value_json.power | float > 0 }}" #define jsonCount "{{ value_json.count | is_defined }}"
# define jsonInuseRN8209 "{% if value_json.power > 0.02 -%} on {% else %} off {%- endif %}" #define jsonAlarm "{{ value_json.alarm | is_defined }}"
# define jsonVoltBM2 "{% if value_json.uuid is not defined -%} {{value_json.volt}} {%- endif %}" #define jsonInuse "{{ value_json.power | is_defined | float > 0 }}"
#else // Home assistant autodiscovery value key definition #define jsonInuseRN8209 "{% if value_json.power > 0.02 -%} on {% else %} off {%- endif %}"
# define jsonBatt "{{ value_json.batt | is_defined }}" #define jsonVoltBM2 "{% if value_json.uuid is not defined and value_json.volt is defined -%} {{value_json.volt}} {%- endif %}"
# define jsonLux "{{ value_json.lux | is_defined }}"
# define jsonPres "{{ value_json.pres | is_defined }}"
# define jsonFer "{{ value_json.fer | is_defined }}"
# define jsonFor "{{ value_json.for | is_defined }}"
# define jsonMoi "{{ value_json.moi | is_defined }}"
# define jsonHum "{{ value_json.hum | is_defined }}"
# define jsonStep "{{ value_json.steps | is_defined }}"
# define jsonWeight "{{ value_json.weight | is_defined }}"
# define jsonPresence "{{ value_json.presence | is_defined }}"
# define jsonAltim "{{ value_json.altim | is_defined }}"
# define jsonAltif "{{ value_json.altift | is_defined }}"
# define jsonTempc "{{ value_json.tempc | is_defined }}"
# define jsonTempc2 "{{ value_json.tempc2 | is_defined }}"
# define jsonTempc3 "{{ value_json.tempc3 | is_defined }}"
# define jsonTempc4 "{{ value_json.tempc4 | is_defined }}"
# define jsonTempf "{{ value_json.tempf | is_defined }}"
# define jsonMsg "{{ value_json.message | is_defined }}"
# define jsonVal "{{ value_json.value | is_defined }}"
# define jsonVolt "{{ value_json.volt | is_defined }}"
# define jsonCurrent "{{ value_json.current | is_defined }}"
# define jsonPower "{{ value_json.power | is_defined }}"
# define jsonEnergy "{{ value_json.energy | is_defined }}"
# define jsonGpio "{{ value_json.gpio | is_defined }}"
# define jsonFtcd "{{ value_json.ftcd | is_defined }}"
# define jsonWm2 "{{ value_json.wattsm2 | is_defined }}"
# define jsonAdc "{{ value_json.adc | is_defined }}"
# define jsonPa "{{ float(value_json.pa) * 0.01 | is_defined }}"
# define jsonId "{{ value_json.id | is_defined }}"
# define jsonAddress "{{ value_json.address | is_defined }}"
# define jsonOpen "{{ value_json.open | is_defined }}"
# define jsonTime "{{ value_json.time | is_defined }}"
# define jsonCount "{{ value_json.count | is_defined }}"
# define jsonAlarm "{{ value_json.alarm | is_defined }}"
# define jsonInuse "{{ value_json.power | is_defined | float > 0 }}"
# define jsonInuseRN8209 "{% if value_json.power > 0.02 -%} on {% else %} off {%- endif %}"
# define jsonVoltBM2 "{% if value_json.uuid is not defined and value_json.volt is defined -%} {{value_json.volt}} {%- endif %}"
#endif
#define stateClassNone "" #define stateClassNone ""
#define stateClassMeasurement "measurement" #define stateClassMeasurement "measurement"
+8 -1
View File
@@ -1972,6 +1972,7 @@ String stateMeasures() {
SYSdata["version"] = OMG_VERSION; SYSdata["version"] = OMG_VERSION;
# ifdef ZmqttDiscovery # ifdef ZmqttDiscovery
SYSdata["discovery"] = disc; SYSdata["discovery"] = disc;
SYSdata["ohdiscovery"] = OpenHABDisc;
# endif # endif
# if defined(ESP8266) || defined(ESP32) # if defined(ESP8266) || defined(ESP32)
SYSdata["env"] = ENV_NAME; SYSdata["env"] = ENV_NAME;
@@ -2445,7 +2446,13 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
stateMeasures(); stateMeasures();
} }
} }
# ifdef ZmqttDiscovery
if (SYSdata.containsKey("ohdiscovery") && SYSdata["ohdiscovery"].is<bool>()) {
OpenHABDisc = SYSdata["ohdiscovery"];
Log.notice(F("OpenHAB discovery: %T" CR), OpenHABDisc);
stateMeasures();
}
# endif
if (SYSdata.containsKey("wifi_ssid") && SYSdata.containsKey("wifi_pass")) { if (SYSdata.containsKey("wifi_ssid") && SYSdata.containsKey("wifi_pass")) {
# if defined(ZgatewayBT) && defined(ESP32) # if defined(ZgatewayBT) && defined(ESP32)
stopProcessing(); stopProcessing();
-2
View File
@@ -41,7 +41,6 @@ extra_configs =
;default_envs = esp32dev-gf-sun-inverter ;default_envs = esp32dev-gf-sun-inverter
;default_envs = esp32dev-ir ;default_envs = esp32dev-ir
;default_envs = esp32dev-ble ;default_envs = esp32dev-ble
;default_envs = esp32dev-ble-openhab
;default_envs = esp32dev-ble-mqtt-undecoded ;default_envs = esp32dev-ble-mqtt-undecoded
;default_envs = esp32dev-ble-aws ;default_envs = esp32dev-ble-aws
;default_envs = esp32feather-ble ;default_envs = esp32feather-ble
@@ -82,7 +81,6 @@ extra_configs =
;default_envs = nodemcuv2-rf-cc1101 ;default_envs = nodemcuv2-rf-cc1101
;default_envs = nodemcuv2-somfy-cc1101 ;default_envs = nodemcuv2-somfy-cc1101
;default_envs = manual-wifi-test ;default_envs = manual-wifi-test
;default_envs = openhab-test
;default_envs = nodemcuv2-mqtt-fw-test ;default_envs = nodemcuv2-mqtt-fw-test
;default_envs = rf-wifi-gateway ;default_envs = rf-wifi-gateway
;default_envs = nodemcuv2-rf2 ;default_envs = nodemcuv2-rf2