Skip to content

Commit

Permalink
Merge pull request #301 from iranl/mqtt-json-keyturner
Browse files Browse the repository at this point in the history
MQTT JSON Lock/Opener and keypad
  • Loading branch information
technyon committed Feb 17, 2024
2 parents 8d7256a + fc767dd commit 1c9366f
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 57 deletions.
2 changes: 2 additions & 0 deletions MqttTopics.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define mqtt_topic_battery_keypad_critical "/battery/keypadCritical"

#define mqtt_topic_lock_state "/lock/state"
#define mqtt_topic_lock_json "/lock/json"
#define mqtt_topic_query_config "/lock/query/config"
#define mqtt_topic_query_lockstate "/lock/query/lockstate"
#define mqtt_topic_query_keypad "/lock/query/keypad"
Expand Down Expand Up @@ -51,6 +52,7 @@
#define mqtt_topic_keypad_command_code "/keypad/command/code"
#define mqtt_topic_keypad_command_enabled "/keypad/command/enabled"
#define mqtt_topic_keypad_command_result "/keypad/command/commandResult"
#define mqtt_topic_keypad_json "/keypad/json"

#define mqtt_topic_presence "/presence/devices"

Expand Down
52 changes: 26 additions & 26 deletions Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,13 @@ bool Network::update()
}
_lastMaintenanceTs = ts;
}

if(_preferences->getBool(preference_check_updates))
{
if(_lastUpdateCheckTs == 0 || (ts - _lastUpdateCheckTs) > 86400000)
{
_lastUpdateCheckTs = ts;

https.useHTTP10(true);
https.begin(GITHUB_LATEST_RELEASE_API_URL);

Expand All @@ -373,16 +373,16 @@ bool Network::update()
DynamicJsonDocument doc(6144);
DeserializationError jsonError = deserializeJson(doc, https.getStream());

if (!jsonError) {
if (!jsonError) {
_latestVersion = doc["tag_name"];
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_latest, _latestVersion);
}
}
}

https.end();
}
}

for(const auto& gpioTs : _gpioTs)
{
uint8_t pin = gpioTs.first;
Expand Down Expand Up @@ -750,7 +750,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
json["dev"]["mf"] = "Nuki";
json["dev"]["mdl"] = deviceType;
json["dev"]["name"] = name;

String cuUrl = _preferences->getString(preference_mqtt_hass_cu_url);

if (cuUrl != "")
Expand All @@ -761,7 +761,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
{
json["dev"]["cu"] = "http://" + _device->localIP();
}

json["~"] = baseTopic;
json["name"] = nullptr;
json["unique_id"] = String(uidString) + "_lock";
Expand Down Expand Up @@ -945,11 +945,11 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"",
{ { "enabled_by_default", "true" },
{"ic", "mdi:counter"}});

if(_preferences->getBool(preference_check_updates))
{
// NUKI Hub latest
publishHassTopic("sensor",
publishHassTopic("sensor",
"nuki_hub_latest",
uidString,
"_nuki_hub_latest",
Expand All @@ -964,13 +964,13 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"",
{ { "enabled_by_default", "true" },
{"ic", "mdi:counter"}});

// NUKI Hub update
char latest_version_topic[250];
_lockPath.toCharArray(latest_version_topic,_lockPath.length() + 1);
strcat(latest_version_topic, mqtt_topic_info_nuki_hub_latest);

publishHassTopic("update",
publishHassTopic("update",
"nuki_hub_update",
uidString,
"_nuki_hub_update",
Expand All @@ -986,7 +986,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
{ { "enabled_by_default", "true" },
{ "entity_picture", "https://raw.githubusercontent.com/technyon/nuki_hub/master/icon/favicon-32x32.png" },
{ "release_url", GITHUB_LATEST_RELEASE_URL },
{ "latest_version_topic", latest_version_topic }});
{ "latest_version_topic", latest_version_topic }});
}
else
{
Expand Down Expand Up @@ -1050,7 +1050,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
{ "pl_off", "0" },
{ "state_on", "1" },
{ "state_off", "0" }});

// Unlatch
publishHassTopic("button",
"unlatch",
Expand All @@ -1066,8 +1066,8 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"",
String("~") + mqtt_topic_lock_action,
{ { "enabled_by_default", "false" },
{ "pl_prs", "unlatch" }});
{ "pl_prs", "unlatch" }});

}
}

Expand Down Expand Up @@ -1362,7 +1362,7 @@ String Network::createHassTopicPath(const String& mqttDeviceType, const String&
path.concat("/");
path.concat(mqttDeviceName);
path.concat("/config");

return path;
}

Expand All @@ -1387,26 +1387,26 @@ void Network::removeHASSConfig(char* uidString)
removeHassTopic("lock", "smartlock", uidString);
removeHassTopic("binary_sensor", "battery_low", uidString);
removeHassTopic("binary_sensor", "keypad_battery_low", uidString);
removeHassTopic("sensor", "battery_voltage", uidString);
removeHassTopic("sensor", "battery_voltage", uidString);
removeHassTopic("sensor", "trigger", uidString);
removeHassTopic("binary_sensor", "mqtt_connected", uidString);
removeHassTopic("switch", "reset", uidString);
removeHassTopic("switch", "reset", uidString);
removeHassTopic("sensor", "firmware_version", uidString);
removeHassTopic("sensor", "hardware_version", uidString);
removeHassTopic("sensor", "nuki_hub_version", uidString);
removeHassTopic("sensor", "nuki_hub_latest", uidString);
removeHassTopic("update", "nuki_hub_update", uidString);
removeHassTopic("sensor", "nuki_hub_ip", uidString);
removeHassTopic("switch", "led_enabled", uidString);
removeHassTopic("switch", "button_enabled", uidString);
removeHassTopic("switch", "led_enabled", uidString);
removeHassTopic("switch", "button_enabled", uidString);
removeHassTopic("button", "unlatch", uidString);
removeHassTopic("button", "lockngo", uidString);
removeHassTopic("button", "lockngounlatch", uidString);
removeHassTopic("sensor", "battery_level", uidString);
removeHassTopic("binary_sensor", "door_sensor", uidString);
removeHassTopic("binary_sensor", "ring", uidString);
removeHassTopic("number", "led_brightness", uidString);
removeHassTopic("sensor", "sound_level", uidString);
removeHassTopic("sensor", "sound_level", uidString);
removeHassTopic("number", "sound_level", uidString);
removeHassTopic("sensor", "last_action_authorization", uidString);
removeHassTopic("sensor", "keypad_status", uidString);
Expand Down Expand Up @@ -1451,17 +1451,17 @@ DynamicJsonDocument Network::createHassJson(const String& uidString,
{
json["dev_cla"] = deviceClass;
}

if(stateTopic != "")
{
json["stat_t"] = stateTopic;
}

if(stateClass != "")
{
json["stat_cla"] = stateClass;
}

if(entityCat != "")
{
json["ent_cat"] = entityCat;
Expand All @@ -1471,7 +1471,7 @@ DynamicJsonDocument Network::createHassJson(const String& uidString,
{
json["cmd_t"] = commandTopic;
}

json["avty"]["t"] = _lockPath + mqtt_topic_mqtt_connection_state;

for(const auto& entry : additionalEntries)
Expand All @@ -1489,7 +1489,7 @@ DynamicJsonDocument Network::createHassJson(const String& uidString,
json[entry.first] = entry.second;
}
}

return json;
}

Expand Down
68 changes: 55 additions & 13 deletions NetworkLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,15 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState)
{
char str[50];
memset(&str, 0, sizeof(str));

DynamicJsonDocument json(_bufferSize);

lockstateToString(keyTurnerState.lockState, str);

if((_firstTunerStatePublish || keyTurnerState.lockState != lastKeyTurnerState.lockState) && keyTurnerState.lockState != NukiLock::LockState::Undefined)
{
memset(&str, 0, sizeof(str));
lockstateToString(keyTurnerState.lockState, str);

publishString(mqtt_topic_lock_state, str);

if(_haEnabled)
Expand All @@ -222,34 +226,48 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
}
}

json["lock_state"] = str;

memset(&str, 0, sizeof(str));
triggerToString(keyTurnerState.trigger, str);

if(_firstTunerStatePublish || keyTurnerState.trigger != lastKeyTurnerState.trigger)
{
memset(&str, 0, sizeof(str));
triggerToString(keyTurnerState.trigger, str);
publishString(mqtt_topic_lock_trigger, str);
}

json["trigger"] = str;

memset(&str, 0, sizeof(str));
lockactionToString(keyTurnerState.lastLockAction, str);

if(_firstTunerStatePublish || keyTurnerState.lastLockAction != lastKeyTurnerState.lastLockAction)
{
memset(&str, 0, sizeof(str));
lockactionToString(keyTurnerState.lastLockAction, str);
publishString(mqtt_topic_lock_last_lock_action, str);
}

json["last_lock_action"] = str;

memset(&str, 0, sizeof(str));
NukiLock::completionStatusToString(keyTurnerState.lastLockActionCompletionStatus, str);

if(_firstTunerStatePublish || keyTurnerState.lastLockActionCompletionStatus != lastKeyTurnerState.lastLockActionCompletionStatus)
{
memset(&str, 0, sizeof(str));
NukiLock::completionStatusToString(keyTurnerState.lastLockActionCompletionStatus, str);
publishString(mqtt_topic_lock_completionStatus, str);
}

json["lock_completion_status"] = str;

memset(&str, 0, sizeof(str));
NukiLock::doorSensorStateToString(keyTurnerState.doorSensorState, str);

if(_firstTunerStatePublish || keyTurnerState.doorSensorState != lastKeyTurnerState.doorSensorState)
{
memset(&str, 0, sizeof(str));
NukiLock::doorSensorStateToString(keyTurnerState.doorSensorState, str);
publishString(mqtt_topic_lock_door_sensor_state, str);
}

json["door_sensor_state"] = str;

if(_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState)
{
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
Expand All @@ -273,6 +291,12 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
}
}

json["auth_id"] = authId;
json["auth_name"] = authName;

serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_lock_json, _buffer);

_firstTunerStatePublish = false;
}

Expand Down Expand Up @@ -301,8 +325,6 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
char str[50];

bool authFound = false;
uint32_t authId = 0;
char authName[33];
memset(authName, 0, sizeof(authName));

DynamicJsonDocument json(_bufferSize);
Expand Down Expand Up @@ -457,15 +479,35 @@ void NetworkLock::publishBleAddress(const std::string &address)
void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
{
uint index = 0;

DynamicJsonDocument json(_bufferSize);

for(const auto& entry : entries)
{
String basePath = mqtt_topic_keypad;
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);


auto jsonEntry = json.add();

jsonEntry["id"] = entry.codeId;
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
jsonEntry["createdYear"] = entry.dateCreatedYear;
jsonEntry["createdMonth"] = entry.dateCreatedMonth;
jsonEntry["createdDay"] = entry.dateCreatedDay;
jsonEntry["createdHour"] = entry.dateCreatedHour;
jsonEntry["createdMin"] = entry.dateCreatedMin;
jsonEntry["createdSec"] = entry.dateCreatedSec;
jsonEntry["lockCount"] = entry.lockCount;

++index;
}

serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_keypad_json, _buffer);

while(index < maxKeypadCodeCount)
{
NukiLock::KeypadEntry entry;
Expand Down
6 changes: 4 additions & 2 deletions NetworkLock.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,16 @@ class NetworkLock : public MqttReceiver

bool _firstTunerStatePublish = true;
unsigned long _lastMaintenanceTs = 0;
bool _haEnabled= false;
bool _haEnabled = false;
bool _reconnected = false;

String _keypadCommandName = "";
String _keypadCommandCode = "";
uint _keypadCommandId = 0;
int _keypadCommandEnabled = 1;
uint8_t _queryCommands = 0;
uint8_t _queryCommands = 0;
uint32_t authId = 0;
char authName[33];

char* _buffer;
size_t _bufferSize;
Expand Down
Loading

0 comments on commit 1c9366f

Please sign in to comment.