diff --git a/openBeken_win32_mvsc2017.vcxproj b/openBeken_win32_mvsc2017.vcxproj
index 75fab3a68..7624e724e 100644
--- a/openBeken_win32_mvsc2017.vcxproj
+++ b/openBeken_win32_mvsc2017.vcxproj
@@ -951,6 +951,8 @@
+
+
diff --git a/openBeken_win32_mvsc2017.vcxproj.filters b/openBeken_win32_mvsc2017.vcxproj.filters
index 26578fcd0..6d5b03e8e 100644
--- a/openBeken_win32_mvsc2017.vcxproj.filters
+++ b/openBeken_win32_mvsc2017.vcxproj.filters
@@ -857,6 +857,12 @@
Simulator
+
+ SelfTest
+
+
+ SelfTest
+
diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c
index 9a34475ec..2965a272b 100644
--- a/src/httpserver/hass.c
+++ b/src/httpserver/hass.c
@@ -65,9 +65,16 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
case BATTERY_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "battery", index);
break;
+ case VOLTAGE_SENSOR:
case BATTERY_VOLTAGE_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "voltage", index);
break;
+ case CURRENT_SENSOR:
+ sprintf(uniq_id, "%s_%s_%d", longDeviceName, "current", index);
+ break;
+ default:
+ sprintf(uniq_id, "%s_%s_%d", longDeviceName, "sensor", index);
+ break;
}
}
@@ -95,11 +102,12 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe
case LIGHT_RGBCW:
sprintf(info->channel, "light/%s/config", uniq_id);
break;
-
case RELAY:
sprintf(info->channel, "switch/%s/config", uniq_id);
break;
-
+ case BINARY_SENSOR:
+ sprintf(info->channel, "binary_sensor/%s/config", uniq_id);
+ break;
case CO2_SENSOR:
case TVOC_SENSOR:
case POWER_SENSOR:
@@ -109,9 +117,9 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe
case HUMIDITY_SENSOR:
sprintf(info->channel, "sensor/%s/config", uniq_id);
break;
-
- case BINARY_SENSOR:
- sprintf(info->channel, "binary_sensor/%s/config", uniq_id);
+ default:
+ sprintf(info->channel, "sensor/%s/config", uniq_id);
+ break;
}
}
@@ -323,8 +331,17 @@ HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type) {
/// @brief Initializes HomeAssistant binary sensor device discovery storage.
/// @param index
/// @return
-HassDeviceInfo* hass_init_binary_sensor_device_info(int index) {
- HassDeviceInfo* info = hass_init_device_info(BINARY_SENSOR, index, "1", "0");
+HassDeviceInfo* hass_init_binary_sensor_device_info(int index, bool bInverse) {
+ const char *payload_on;
+ const char *payload_off;
+ if (bInverse) {
+ payload_on = "1";
+ payload_off = "0";
+ } else {
+ payload_off = "1";
+ payload_on = "0";
+ }
+ HassDeviceInfo* info = hass_init_device_info(BINARY_SENSOR, index, payload_on, payload_off);
sprintf(g_hassBuffer, "~/%i/get", index);
cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); //state_topic
diff --git a/src/httpserver/hass.h b/src/httpserver/hass.h
index 8891ad9f4..01bfe3115 100644
--- a/src/httpserver/hass.h
+++ b/src/httpserver/hass.h
@@ -84,7 +84,7 @@ void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE
HassDeviceInfo* hass_init_relay_device_info(int index, ENTITY_TYPE type);
HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type);
HassDeviceInfo* hass_init_power_sensor_device_info(int index);
-HassDeviceInfo* hass_init_binary_sensor_device_info(int index);
+HassDeviceInfo* hass_init_binary_sensor_device_info(int index, bool bInverse);
HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int decPlaces, int decOffset);
const char* hass_build_discovery_json(HassDeviceInfo* info);
void hass_free_device_info(HassDeviceInfo* info);
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index 08f725266..1cd4477ec 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -1601,9 +1601,9 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
hooks.free_fn = os_free;
cJSON_InitHooks(&hooks);
- if (relayCount > 0) {
+ //if (relayCount > 0) {
for (i = 0; i < CHANNEL_MAX; i++) {
- if (h_isChannelRelay(i)) {
+ if (h_isChannelRelay(i) || g_cfg.pins.channelTypes[i] == ChType_Toggle) {
// TODO: flags are 32 bit and there are 64 max channels
BIT_SET(flagsChannelPublished, i);
if (CFG_HasFlag(OBK_FLAG_MQTT_HASS_ADD_RELAYS_AS_LIGHTS)) {
@@ -1618,14 +1618,14 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
discoveryQueued = true;
}
}
- }
+ //}
if (dInputCount > 0) {
for (i = 0; i < CHANNEL_MAX; i++) {
if (h_isChannelDigitalInput(i)) {
// TODO: flags are 32 bit and there are 64 max channels
BIT_SET(flagsChannelPublished, i);
- dev_info = hass_init_binary_sensor_device_info(i);
+ dev_info = hass_init_binary_sensor_device_info(i, false);
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
hass_free_device_info(dev_info);
dev_info = NULL;
@@ -1739,7 +1739,16 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
{
case ChType_OpenClosed:
{
- dev_info = hass_init_binary_sensor_device_info(i);
+ dev_info = hass_init_binary_sensor_device_info(i, false);
+ MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
+ hass_free_device_info(dev_info);
+
+ discoveryQueued = true;
+ }
+ break;
+ case ChType_OpenClosed_Inv:
+ {
+ dev_info = hass_init_binary_sensor_device_info(i, true);
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
hass_free_device_info(dev_info);
@@ -1800,6 +1809,15 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
discoveryQueued = true;
}
break;
+ case ChType_Current_div1000:
+ {
+ dev_info = hass_init_sensor_device_info(CURRENT_SENSOR, i, 3, 3);
+ MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
+ hass_free_device_info(dev_info);
+
+ discoveryQueued = true;
+ }
+ break;
case ChType_Power:
{
dev_info = hass_init_sensor_device_info(POWER_SENSOR, i, -1, -1);
diff --git a/src/selftest/selftest_hass_discovery_ext.c b/src/selftest/selftest_hass_discovery_ext.c
index c55fb7d99..fcfdea26e 100644
--- a/src/selftest/selftest_hass_discovery_ext.c
+++ b/src/selftest/selftest_hass_discovery_ext.c
@@ -61,6 +61,70 @@ void Test_HassDiscovery_Channel_Humidity() {
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/15/get");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_cla", "measurement");
}
+void Test_HassDiscovery_Channel_Current_div100() {
+ const char *shortName = "WinCurTest";
+ const char *fullName = "Windows Fake Cur";
+ const char *mqttName = "testCur";
+ SIM_ClearOBK(shortName);
+ SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
+
+ CFG_SetShortDeviceName(shortName);
+ CFG_SetDeviceName(fullName);
+
+ // in this example, i am using channel 4
+ CHANNEL_SetType(4, ChType_Current_div100);
+
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
+ Sim_RunSeconds(5, false);
+
+ // OBK device should publish JSON on MQTT topic "homeassistant"
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
+ //SELFTEST_ASSERT_JSON_VALUE_STRING(0, "name", "WinCurTest Current");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "current");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "A");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "val_tpl", "{{ float(value)*0.01|round(3) }}");
+ // in this example, i am using channel 4
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/4/get");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_cla", "measurement");
+}
+void Test_HassDiscovery_Channel_Current_div1000() {
+ const char *shortName = "WinCurTest";
+ const char *fullName = "Windows Fake Cur";
+ const char *mqttName = "testCur";
+ SIM_ClearOBK(shortName);
+ SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
+
+ CFG_SetShortDeviceName(shortName);
+ CFG_SetDeviceName(fullName);
+
+ // in this example, i am using channel 14
+ CHANNEL_SetType(14, ChType_Current_div1000);
+
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
+ Sim_RunSeconds(5, false);
+
+ // OBK device should publish JSON on MQTT topic "homeassistant"
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
+ //SELFTEST_ASSERT_JSON_VALUE_STRING(0, "name", "WinCurTest Current");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "current");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "A");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "val_tpl", "{{ float(value)*0.001|round(3) }}");
+ // in this example, i am using channel 14
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/14/get");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_cla", "measurement");
+}
void Test_HassDiscovery_Channel_Voltage_div10() {
const char *shortName = "WinVolTest";
const char *fullName = "Windows Fake Vol";
@@ -86,7 +150,7 @@ void Test_HassDiscovery_Channel_Voltage_div10() {
SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "name", "WinVolTest Voltage");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
- SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "voltge");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "voltage");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "V");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "val_tpl", "{{ float(value)*0.1|round(2) }}");
// in this example, i am using channel 23
@@ -122,11 +186,109 @@ void Test_HassDiscovery_Channel_Temperature() {
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/0/get");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_cla", "measurement");
}
+void Test_HassDiscovery_Channel_Temperature_div10() {
+ const char *shortName = "WinTempTest";
+ const char *fullName = "Windows Fake Temp";
+ const char *mqttName = "testTemp";
+ SIM_ClearOBK(shortName);
+ SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
+
+ CFG_SetShortDeviceName(shortName);
+ CFG_SetDeviceName(fullName);
+
+ CHANNEL_SetType(3, ChType_Temperature_div10);
+
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
+ Sim_RunSeconds(5, false);
+
+ // OBK device should publish JSON on MQTT topic "homeassistant"
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "name", "WinTempTest Temperature");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "temperature");
+ //SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "C");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/3/get");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "val_tpl", "{{ float(value)*0.1|round(2) }}");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_cla", "measurement");
+}
+void Test_HassDiscovery_Channel_Toggle() {
+ const char *shortName = "WinToggleTest";
+ const char *fullName = "Windows Fake Toggle";
+ const char *mqttName = "testToggle";
+ SIM_ClearOBK(shortName);
+ SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
+
+ CFG_SetShortDeviceName(shortName);
+ CFG_SetDeviceName(fullName);
+
+ CHANNEL_SetType(4, ChType_Toggle);
+
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
+ Sim_RunSeconds(5, false);
+
+ // OBK device should publish JSON on MQTT topic "homeassistant"
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
+ //SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "C");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/4/get");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "cmd_t", "~/4/set");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "pl_on", "1");
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "pl_off", "0");
+}
+void Test_HassDiscovery_Channel_Toggle_2x() {
+ const char *shortName = "WinToggleTest";
+ const char *fullName = "Windows Fake Toggle";
+ const char *mqttName = "testToggle";
+ SIM_ClearOBK(shortName);
+ SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
+
+ CFG_SetShortDeviceName(shortName);
+ CFG_SetDeviceName(fullName);
+
+ CHANNEL_SetType(4, ChType_Toggle);
+ CHANNEL_SetType(5, ChType_Toggle);
+
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
+ Sim_RunSeconds(5, false);
+
+ // OBK device should publish JSON on MQTT topic "homeassistant"
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "~", mqttName);
+ //SELFTEST_ASSERT_JSON_VALUE_STRING(0, "unit_of_meas", "C");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "pl_on", "1");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "pl_off", "0");
+ // we have used channel index 4
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "stat_t", "~/4/get");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "cmd_t", "~/4/set");
+ // AND we have used channel index 5
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "stat_t", "~/5/get");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY("homeassistant", true, 0, 0, "cmd_t", "~/5/set");
+}
void Test_HassDiscovery_Ext() {
Test_HassDiscovery_TuyaMCU_VoltageCurrentPower();
Test_HassDiscovery_Channel_Humidity();
Test_HassDiscovery_Channel_Temperature();
+ Test_HassDiscovery_Channel_Temperature_div10();
Test_HassDiscovery_Channel_Voltage_div10();
+ Test_HassDiscovery_Channel_Current_div100();
+ Test_HassDiscovery_Channel_Current_div1000();
+ Test_HassDiscovery_Channel_Toggle();
+ Test_HassDiscovery_Channel_Toggle_2x();
}