Merge pull request #377 from iranl/add-option-to-remove-non-json

Add option to remove some non-JSON MQTT topics
This commit is contained in:
Jan-Ole Schümann
2024-05-30 17:32:32 +07:00
committed by GitHub
11 changed files with 392 additions and 172 deletions

View File

@@ -48,6 +48,8 @@
#define mqtt_topic_battery_max_turn_current "/battery/maxTurnCurrent"
#define mqtt_topic_battery_lock_distance "/battery/lockDistance"
#define mqtt_topic_battery_keypad_critical "/battery/keypadCritical"
#define mqtt_topic_battery_basic_json "/battery/basicJson"
#define mqtt_topic_battery_advanced_json "/battery/advancedJson"
#define mqtt_topic_keypad "/keypad"
#define mqtt_topic_keypad_command_action "/keypad/command/action"

View File

@@ -264,13 +264,13 @@ void Network::initialize()
bool Network::update()
{
unsigned long ts = millis();
if(ts > 120000 && ts < 125000 && _preferences->getInt(preference_bootloop_counter, 0) > 0)
{
_preferences->putInt(preference_bootloop_counter, 0);
Log->println(F("Bootloop counter reset"));
}
_device->update();
if(!_mqttEnabled)
@@ -806,14 +806,15 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"Battery low",
name,
baseTopic,
String("~") + mqtt_topic_battery_critical,
String("~") + mqtt_topic_battery_basic_json,
deviceType,
"battery",
"",
"diagnostic",
"",
{{(char*)"pl_on", (char*)"1"},
{(char*)"pl_off", (char*)"0"}});
{(char*)"pl_off", (char*)"0"},
{(char*)"val_tpl", (char*)"{{value_json.critical}}" }});
// Battery voltage
publishHassTopic("sensor",
@@ -823,13 +824,14 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"Battery voltage",
name,
baseTopic,
String("~") + mqtt_topic_battery_voltage,
String("~") + mqtt_topic_battery_advanced_json,
deviceType,
"voltage",
"measurement",
"diagnostic",
"",
{ {(char*)"unit_of_meas", (char*)"V"} });
{ {(char*)"unit_of_meas", (char*)"V"},
{(char*)"val_tpl", (char*)"{{value_json.level}}" }});
// Trigger
publishHassTopic("sensor",
@@ -935,7 +937,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"",
{ { (char*)"en", (char*)"true" },
{(char*)"ic", (char*)"mdi:counter"}});
// Nuki Hub build
publishHassTopic("sensor",
"nuki_hub_build",
@@ -1333,13 +1335,14 @@ void Network::publishHASSConfigAdditionalLockEntities(char *deviceType, const ch
"Battery level",
name,
baseTopic,
String("~") + mqtt_topic_battery_level,
String("~") + mqtt_topic_battery_basic_json,
deviceType,
"battery",
"measurement",
"diagnostic",
"",
{ {(char*)"unit_of_meas", (char*)"%"} });
{ {(char*)"unit_of_meas", (char*)"%"},
{(char*)"val_tpl", (char*)"{{value_json.level}}" }});
if((int)basicLockConfigAclPrefs[7] == 1)
{
@@ -2298,7 +2301,7 @@ void Network::publishHASSConfigAdditionalOpenerEntities(char *deviceType, const
"",
{{(char*)"pl_on", (char*)"ring"},
{(char*)"pl_off", (char*)"standby"}});
JsonDocument json;
json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{(char*)"val_tpl", (char*)"{ \"event_type\": \"{{ value }}\" }"}});
json["event_types"][0] = "ring";
@@ -3032,14 +3035,15 @@ void Network::publishHASSConfigKeypad(char *deviceType, const char *baseTopic, c
"Keypad battery low",
name,
baseTopic,
String("~") + mqtt_topic_battery_keypad_critical,
String("~") + mqtt_topic_battery_basic_json,
deviceType,
"battery",
"",
"diagnostic",
"",
{{(char*)"pl_on", (char*)"1"},
{(char*)"pl_off", (char*)"0"}});
{(char*)"pl_off", (char*)"0"},
{(char*)"val_tpl", (char*)"{{value_json.keypadCritical}}" }});
// Query Keypad
publishHassTopic("button",
@@ -3152,6 +3156,18 @@ void Network::removeHassTopic(const String& mqttDeviceType, const String& mqttDe
}
}
void Network::removeTopic(const String& mqttPath, const String& mqttTopic)
{
String path = mqttPath;
path.concat(mqttTopic);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, "");
#ifdef DEBUG_NUKIHUB
Log->print(F("Removing MQTT topic: "));
Log->println(path.c_str());
#endif
}
void Network::removeHASSConfig(char* uidString)
{

View File

@@ -55,6 +55,7 @@ public:
void publishHASSWifiRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString);
void removeHASSConfig(char* uidString);
void removeHASSConfigTopic(char* deviceType, char* name, char* uidString);
void removeTopic(const String& mqttPath, const String& mqttTopic);
void batteryTypeToString(const Nuki::BatteryType battype, char* str);
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
void timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str);

View File

@@ -63,20 +63,49 @@ void NetworkLock::initialize()
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
if(_preferences->getBool(preference_disable_non_json, false))
{
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_action);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_id);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_name);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_code);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_result);
_network->removeTopic(_mqttPath, mqtt_topic_config_button_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_config_led_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_config_led_brightness);
_network->removeTopic(_mqttPath, mqtt_topic_config_auto_unlock);
_network->removeTopic(_mqttPath, mqtt_topic_config_auto_lock);
_network->removeTopic(_mqttPath, mqtt_topic_config_single_lock);
_network->removeTopic(_mqttPath, mqtt_topic_battery_level);
_network->removeTopic(_mqttPath, mqtt_topic_battery_critical);
_network->removeTopic(_mqttPath, mqtt_topic_battery_charging);
_network->removeTopic(_mqttPath, mqtt_topic_battery_voltage);
_network->removeTopic(_mqttPath, mqtt_topic_battery_drain);
_network->removeTopic(_mqttPath, mqtt_topic_battery_max_turn_current);
_network->removeTopic(_mqttPath, mqtt_topic_battery_lock_distance);
_network->removeTopic(_mqttPath, mqtt_topic_battery_keypad_critical);
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
}
if(_preferences->getBool(preference_keypad_control_enabled))
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
if(!_preferences->getBool(preference_disable_non_json, false))
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
}
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
_network->initTopic(_mqttPath, mqtt_topic_query_keypad, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--");
}
@@ -104,8 +133,7 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
delay(200);
restartEsp(RestartReason::RequestedViaMqtt);
}
if(comparePrefixedPath(topic, mqtt_topic_webserver_action))
else if(comparePrefixedPath(topic, mqtt_topic_webserver_action))
{
if(strcmp(value, "") == 0 ||
strcmp(value, "--") == 0) return;
@@ -164,46 +192,50 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
}
}
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
if(!_preferences->getBool(preference_disable_non_json, false))
{
if(_keypadCommandReceivedReceivedCallback != nullptr)
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
{
if(strcmp(value, "--") == 0) return;
_keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled);
_keypadCommandId = 0;
_keypadCommandName = "--";
_keypadCommandCode = "000000";
_keypadCommandEnabled = 1;
if(strcmp(value, "--") != 0)
if(_keypadCommandReceivedReceivedCallback != nullptr)
{
publishString(mqtt_topic_keypad_command_action, "--");
if(strcmp(value, "--") == 0) return;
_keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled);
_keypadCommandId = 0;
_keypadCommandName = "--";
_keypadCommandCode = "000000";
_keypadCommandEnabled = 1;
if(strcmp(value, "--") != 0)
{
publishString(mqtt_topic_keypad_command_action, "--");
}
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
}
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
{
_keypadCommandId = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name))
{
_keypadCommandName = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code))
{
_keypadCommandCode = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled))
{
_keypadCommandEnabled = atoi(value);
}
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
{
_keypadCommandId = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name))
{
_keypadCommandName = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code))
{
_keypadCommandCode = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled))
{
_keypadCommandEnabled = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
{
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
publishString(mqtt_topic_query_config, "0");
@@ -267,6 +299,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
memset(&str, 0, sizeof(str));
JsonDocument json;
JsonDocument jsonBattery;
lockstateToString(keyTurnerState.lockState, str);
@@ -334,27 +367,26 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
json["door_sensor_state"] = str;
if(_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState)
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0;
uint8_t level = (keyTurnerState.criticalBatteryState & 0b11111100) >> 1;
bool keypadCritical = (keyTurnerState.accessoryBatteryState & (1 << 7)) != 0 ? (keyTurnerState.accessoryBatteryState & (1 << 6)) != 0 : false;
jsonBattery["critical"] = critical ? "1" : "0";
jsonBattery["charging"] = charging ? "1" : "0";
jsonBattery["level"] = level;
jsonBattery["keypadCritical"] = keypadCritical ? "1" : "0";
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
{
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
publishBool(mqtt_topic_battery_critical, critical);
bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0;
publishBool(mqtt_topic_battery_charging, charging);
uint8_t level = (keyTurnerState.criticalBatteryState & 0b11111100) >> 1;
publishInt(mqtt_topic_battery_level, level);
}
if(_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState)
if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
{
if((keyTurnerState.accessoryBatteryState & (1 << 7)) != 0) {
publishBool(mqtt_topic_battery_keypad_critical, (keyTurnerState.accessoryBatteryState & (1 << 6)) != 0);
}
else
{
publishBool(mqtt_topic_battery_keypad_critical, false);
}
publishBool(mqtt_topic_battery_keypad_critical, keypadCritical);
}
json["auth_id"] = _authId;
@@ -362,6 +394,9 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_lock_json, _buffer);
serializeJson(jsonBattery, _buffer, _bufferSize);
publishString(mqtt_topic_battery_basic_json, _buffer);
_firstTunerStatePublish = false;
}
@@ -528,10 +563,33 @@ void NetworkLock::publishLockstateCommandResult(const char *resultStr)
void NetworkLock::publishBatteryReport(const NukiLock::BatteryReport& batteryReport)
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds
publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0);
publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds
publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0);
publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees
}
char str[50];
memset(&str, 0, sizeof(str));
JsonDocument json;
json["batteryDrain"] = batteryReport.batteryDrain;
json["batteryVoltage"] = (float)batteryReport.batteryVoltage / 1000.0;
json["critical"] = batteryReport.criticalBatteryState;
lockactionToString(batteryReport.lockAction, str);
json["lockAction"] = str;
json["startVoltage"] = (float)batteryReport.startVoltage / 1000.0;
json["lowestVoltage"] = (float)batteryReport.lowestVoltage / 1000.0;
json["lockDistance"] = (float)batteryReport.lockDistance / 1000.0;
json["startTemperature"] = batteryReport.startTemperature;
json["maxTurnCurrent"] = (float)batteryReport.maxTurnCurrent / 1000.0;
json["batteryResistance"] = (float)batteryReport.batteryResistance / 1000.0;
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_battery_advanced_json, _buffer);
}
void NetworkLock::publishConfig(const NukiLock::Config &config)
@@ -583,10 +641,15 @@ void NetworkLock::publishConfig(const NukiLock::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer);
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1);
publishInt(mqtt_topic_config_led_brightness, config.ledBrightness);
publishBool(mqtt_topic_config_single_lock, config.singleLock == 1);
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1);
publishInt(mqtt_topic_config_led_brightness, config.ledBrightness);
publishBool(mqtt_topic_config_single_lock, config.singleLock == 1);
}
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]));
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]));
}
@@ -633,8 +696,12 @@ void NetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer);
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0);
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1);
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0);
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1);
}
}
void NetworkLock::publishRssi(const int& rssi)
@@ -746,16 +813,42 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_keypad_json, _buffer);
while(index < maxKeypadCodeCount)
if(!_preferences->getBool(preference_disable_non_json, false))
{
NukiLock::KeypadEntry entry;
memset(&entry, 0, sizeof(entry));
String basePath = mqtt_topic_keypad;
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
while(index < maxKeypadCodeCount)
{
NukiLock::KeypadEntry entry;
memset(&entry, 0, sizeof(entry));
String basePath = mqtt_topic_keypad;
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
++index;
++index;
}
}
else if (maxKeypadCodeCount > 0)
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
String codeTopic = _mqttPath;
codeTopic.concat(mqtt_topic_keypad);
codeTopic.concat("/code_");
codeTopic.concat(std::to_string(i).c_str());
codeTopic.concat("/");
_network->removeTopic(codeTopic, "id");
_network->removeTopic(codeTopic, "enabled");
_network->removeTopic(codeTopic, "name");
_network->removeTopic(codeTopic, "createdYear");
_network->removeTopic(codeTopic, "createdMonth");
_network->removeTopic(codeTopic, "createdDay");
_network->removeTopic(codeTopic, "createdHour");
_network->removeTopic(codeTopic, "createdMin");
_network->removeTopic(codeTopic, "createdSec");
_network->removeTopic(codeTopic, "lockCount");
}
_preferences->putUInt(preference_lock_max_keypad_code_count, 0);
}
}
@@ -838,6 +931,7 @@ void NetworkLock::publishConfigCommandResult(const char* result)
void NetworkLock::publishKeypadCommandResult(const char* result)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
publishString(mqtt_topic_keypad_command_result, result);
}
@@ -868,6 +962,7 @@ void NetworkLock::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCal
void NetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
}
@@ -994,6 +1089,8 @@ bool NetworkLock::publishString(const char *topic, const char *value)
void NetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
char codeName[sizeof(entry.name) + 1];
memset(codeName, 0, sizeof(codeName));
memcpy(codeName, entry.name, sizeof(entry.name));

View File

@@ -50,20 +50,43 @@ void NetworkOpener::initialize()
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
if(_preferences->getBool(preference_disable_non_json, false))
{
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_action);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_id);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_name);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_code);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_config_button_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_config_led_enabled);
_network->removeTopic(_mqttPath, mqtt_topic_config_sound_level);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_result);
_network->removeTopic(_mqttPath, mqtt_topic_battery_level);
_network->removeTopic(_mqttPath, mqtt_topic_battery_critical);
_network->removeTopic(_mqttPath, mqtt_topic_battery_charging);
_network->removeTopic(_mqttPath, mqtt_topic_battery_voltage);
_network->removeTopic(_mqttPath, mqtt_topic_battery_keypad_critical);
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
}
if(_preferences->getBool(preference_keypad_control_enabled))
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
if(!_preferences->getBool(preference_disable_non_json, false))
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
}
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
_network->initTopic(_mqttPath, mqtt_topic_query_keypad, "0");
_network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--");
}
@@ -127,46 +150,50 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
}
}
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
if(!_preferences->getBool(preference_disable_non_json, false))
{
if(_keypadCommandReceivedReceivedCallback != nullptr)
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
{
if(strcmp(value, "--") == 0) return;
_keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled);
_keypadCommandId = 0;
_keypadCommandName = "--";
_keypadCommandCode = "000000";
_keypadCommandEnabled = 1;
if(strcmp(value, "--") != 0)
if(_keypadCommandReceivedReceivedCallback != nullptr)
{
publishString(mqtt_topic_keypad_command_action, "--");
if(strcmp(value, "--") == 0) return;
_keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled);
_keypadCommandId = 0;
_keypadCommandName = "--";
_keypadCommandCode = "000000";
_keypadCommandEnabled = 1;
if(strcmp(value, "--") != 0)
{
publishString(mqtt_topic_keypad_command_action, "--");
}
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
}
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
{
_keypadCommandId = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name))
{
_keypadCommandName = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code))
{
_keypadCommandCode = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled))
{
_keypadCommandEnabled = atoi(value);
}
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
{
_keypadCommandId = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name))
{
_keypadCommandName = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code))
{
_keypadCommandCode = value;
}
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled))
{
_keypadCommandEnabled = atoi(value);
}
else if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
{
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
publishString(mqtt_topic_query_config, "0");
@@ -232,6 +259,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
memset(&str, 0, sizeof(str));
JsonDocument json;
JsonDocument jsonBattery;
lockstateToString(keyTurnerState.lockState, str);
@@ -305,9 +333,11 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
json["door_sensor_state"] = str;
if(_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState)
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
jsonBattery["critical"] = critical ? "1" : "0";
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
{
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
publishBool(mqtt_topic_battery_critical, critical);
}
@@ -317,6 +347,9 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_lock_json, _buffer);
serializeJson(jsonBattery, _buffer, _bufferSize);
publishString(mqtt_topic_battery_basic_json, _buffer);
_firstTunerStatePublish = false;
}
@@ -494,7 +527,7 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
else publishString(mqtt_topic_lock_log, _buffer);
if(authFound)
{
publishUInt(mqtt_topic_lock_auth_id, _authId);
@@ -521,7 +554,25 @@ void NetworkOpener::publishLockstateCommandResult(const char *resultStr)
void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport)
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
}
char str[50];
memset(&str, 0, sizeof(str));
JsonDocument json;
json["batteryVoltage"] = (float)batteryReport.batteryVoltage / 1000.0;
json["critical"] = batteryReport.criticalBatteryState;
lockactionToString(batteryReport.lockAction, str);
json["lockAction"] = str;
json["startVoltage"] = (float)batteryReport.startVoltage / 1000.0;
json["lowestVoltage"] = (float)batteryReport.lowestVoltage / 1000.0;
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_battery_advanced_json, _buffer);
}
void NetworkOpener::publishConfig(const NukiOpener::Config &config)
@@ -573,8 +624,13 @@ void NetworkOpener::publishConfig(const NukiOpener::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer);
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1);
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1);
}
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]));
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]));
}
@@ -624,7 +680,11 @@ void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &conf
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer);
publishUInt(mqtt_topic_config_sound_level, config.soundLevel);
if(!_preferences->getBool(preference_disable_non_json, false))
{
publishUInt(mqtt_topic_config_sound_level, config.soundLevel);
}
}
void NetworkOpener::publishRssi(const int &rssi)
@@ -668,7 +728,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
auto jsonEntry = json.add<JsonVariant>();
jsonEntry["codeId"] = entry.codeId;
@@ -750,16 +810,42 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_keypad_json, _buffer);
while(index < maxKeypadCodeCount)
if(!_preferences->getBool(preference_disable_non_json, false))
{
NukiLock::KeypadEntry entry;
memset(&entry, 0, sizeof(entry));
String basePath = mqtt_topic_keypad;
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
while(index < maxKeypadCodeCount)
{
NukiLock::KeypadEntry entry;
memset(&entry, 0, sizeof(entry));
String basePath = mqtt_topic_keypad;
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
++index;
++index;
}
}
else if (maxKeypadCodeCount > 0)
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
String codeTopic = _mqttPath;
codeTopic.concat(mqtt_topic_keypad);
codeTopic.concat("/code_");
codeTopic.concat(std::to_string(i).c_str());
codeTopic.concat("/");
_network->removeTopic(codeTopic, "id");
_network->removeTopic(codeTopic, "enabled");
_network->removeTopic(codeTopic, "name");
_network->removeTopic(codeTopic, "createdYear");
_network->removeTopic(codeTopic, "createdMonth");
_network->removeTopic(codeTopic, "createdDay");
_network->removeTopic(codeTopic, "createdHour");
_network->removeTopic(codeTopic, "createdMin");
_network->removeTopic(codeTopic, "createdSec");
_network->removeTopic(codeTopic, "lockCount");
}
_preferences->putUInt(preference_lock_max_keypad_code_count, 0);
}
}
@@ -842,6 +928,7 @@ void NetworkOpener::publishConfigCommandResult(const char* result)
void NetworkOpener::publishKeypadCommandResult(const char* result)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
publishString(mqtt_topic_keypad_command_result, result);
}
@@ -872,6 +959,7 @@ void NetworkOpener::setConfigUpdateReceivedCallback(void (*configUpdateReceivedC
void NetworkOpener::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
}
@@ -928,6 +1016,8 @@ void NetworkOpener::publishString(const char* topic, const char* value)
void NetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
char codeName[sizeof(entry.name) + 1];
memset(codeName, 0, sizeof(codeName));
memcpy(codeName, entry.name, sizeof(entry.name));

View File

@@ -32,7 +32,7 @@ NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId
network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiOpenerInst->onConfigUpdateReceivedCallback);
network->setKeypadCommandReceivedCallback(nukiOpenerInst->onKeypadCommandReceivedCallback);
if(_preferences->getBool(preference_disable_non_json, false)) network->setKeypadCommandReceivedCallback(nukiOpenerInst->onKeypadCommandReceivedCallback);
network->setKeypadJsonCommandReceivedCallback(nukiOpenerInst->onKeypadJsonCommandReceivedCallback);
_gpio->addCallback(NukiOpenerWrapper::gpioActionCallback);
@@ -520,7 +520,7 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
{
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
@@ -571,7 +571,7 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
}
uint keypadCount = entries.size();
if(keypadCount > _maxKeypadCodeCount)
if(keypadCount > _maxKeypadCodeCount && !_preferences->getBool(preference_disable_non_json, false))
{
_maxKeypadCodeCount = keypadCount;
_preferences->putUInt(preference_lock_max_keypad_code_count, _maxKeypadCodeCount);
@@ -1358,6 +1358,8 @@ void NukiOpenerWrapper::gpioActionCallback(const GpioAction &action, const int&
void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(!_preferences->getBool(preference_keypad_control_enabled))
{
_network->publishKeypadCommandResult("KeypadControlDisabled");

View File

@@ -32,7 +32,7 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback);
network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
if(_preferences->getBool(preference_disable_non_json, false)) network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
network->setKeypadJsonCommandReceivedCallback(nukiInst->onKeypadJsonCommandReceivedCallback);
network->setTimeControlCommandReceivedCallback(nukiInst->onTimeControlCommandReceivedCallback);
@@ -202,7 +202,7 @@ void NukiWrapper::update()
{
_waitKeypadUpdateTs = 0;
updateKeypad(true);
}
}
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
{
_waitTimeControlUpdateTs = 0;
@@ -496,12 +496,12 @@ void NukiWrapper::updateAuthData(bool retrieved)
std::list<NukiLock::LogEntry> log;
_nukiLock.getLogEntries(&log);
if(log.size() > _preferences->getInt(preference_authlog_max_entries, 3))
{
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
@@ -512,7 +512,7 @@ void NukiWrapper::updateAuthData(bool retrieved)
{
std::list<NukiLock::LogEntry> log;
_nukiLock.getLogEntries(&log);
if(log.size() > _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG))
{
log.resize(_preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG));
@@ -526,14 +526,14 @@ void NukiWrapper::updateAuthData(bool retrieved)
_network->publishAuthorizationInfo(log, false);
}
}
postponeBleWatchdog();
}
void NukiWrapper::updateKeypad(bool retrieved)
{
if(!_preferences->getBool(preference_keypad_info_enabled)) return;
if(!retrieved)
{
Log->print(F("Querying lock keypad: "));
@@ -553,14 +553,14 @@ void NukiWrapper::updateKeypad(bool retrieved)
Log->println(entries.size());
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
if(entries.size() > _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD))
{
entries.resize(_preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
}
uint keypadCount = entries.size();
if(keypadCount > _maxKeypadCodeCount)
if(keypadCount > _maxKeypadCodeCount && !_preferences->getBool(preference_disable_non_json, false))
{
_maxKeypadCodeCount = keypadCount;
_preferences->putUInt(preference_lock_max_keypad_code_count, _maxKeypadCodeCount);
@@ -605,12 +605,12 @@ void NukiWrapper::updateTimeControl(bool retrieved)
Log->println(timeControlEntries.size());
timeControlEntries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; });
if(timeControlEntries.size() > _preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL))
{
timeControlEntries.resize(_preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL));
}
_network->publishTimeControl(timeControlEntries);
_timeControlIds.clear();
@@ -1352,6 +1352,8 @@ void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(!_preferences->getBool(preference_keypad_control_enabled))
{
_network->publishKeypadCommandResult("KeypadControlDisabled");
@@ -1744,7 +1746,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
entry.codeId = codeId;
size_t nameLen = strlen(name);
memcpy(&entry.name, name, nameLen > 20 ? 20 : nameLen);
if(code) entry.code = code;
else
{
@@ -1855,7 +1857,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
const char *time = json["time"].as<const char*>();
const char *lockAct = json["lockAction"].as<const char*>();
NukiLock::LockAction timeControlLockAction;
if(lockAct)
{
timeControlLockAction = nukiInst->lockActionToEnum(lockAct);

View File

@@ -82,6 +82,7 @@
#define preference_bootloop_counter (char*)"btlpcounter"
#define preference_enable_bootloop_reset (char*)"enabtlprst"
#define preference_buffer_size (char*)"buffsize"
#define preference_disable_non_json (char*)"disnonjson"
class DebugPreferences
{
@@ -99,7 +100,7 @@ private:
preference_keypad_info_enabled, preference_acl, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled,
preference_conf_lock_basic_acl, preference_conf_lock_advanced_acl, preference_conf_opener_basic_acl, preference_conf_opener_advanced_acl,
preference_access_level, preference_register_as_app, preference_command_nr_of_retries, preference_command_retry_delay, preference_cred_user,
preference_cred_password, preference_publish_authdata, preference_publish_debug_info, preference_presence_detection_timeout,
preference_cred_password, preference_publish_authdata, preference_publish_debug_info, preference_presence_detection_timeout, preference_disable_non_json,
preference_has_mac_saved, preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2, preference_latest_version,
preference_task_size_network, preference_task_size_nuki, preference_task_size_pd, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries
};
@@ -115,7 +116,7 @@ private:
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
preference_enable_bootloop_reset, preference_webserver_enabled, preference_find_best_rssi, preference_restart_on_disconnect, preference_keypad_control_enabled,
preference_keypad_info_enabled, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_ip_dhcp_enabled,
preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled
preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled, preference_disable_non_json
};
const bool isRedacted(const char* key) const

View File

@@ -421,6 +421,11 @@ bool WebCfgServer::processArgs(String& message)
_preferences->putBool(preference_check_updates, (value == "1"));
configChanged = true;
}
else if(key == "DISNONJSON")
{
_preferences->putBool(preference_disable_non_json, (value == "1"));
configChanged = true;
}
else if(key == "DHCPENA")
{
_preferences->putBool(preference_ip_dhcp_enabled, (value == "1"));
@@ -1339,6 +1344,7 @@ void WebCfgServer::buildMqttConfigHtml(String &response)
printCheckBox(response, "RSTDISC", "Restart on disconnect", _preferences->getBool(preference_restart_on_disconnect), "");
printCheckBox(response, "MQTTLOG", "Enable MQTT logging", _preferences->getBool(preference_mqtt_log_enabled), "");
printCheckBox(response, "CHECKUPDATE", "Check for Firmware Updates every 24h", _preferences->getBool(preference_check_updates), "");
printCheckBox(response, "DISNONJSON", "Disable some extraneous non-JSON topics", _preferences->getBool(preference_disable_non_json), "");
response.concat("</table>");
response.concat("* If no encryption is configured for the MQTT broker, leave empty. Only supported for Wi-Fi connections.<br><br>");