Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Additional Lock states in Home Assistant + Make Opener Continuous mode an option for lock/unlock #296

Merged
merged 15 commits into from
Feb 18, 2024
Merged
26 changes: 26 additions & 0 deletions Gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ void Gpio::init()
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrDeactivateRtoCm, FALLING);
break;
case PinRole::InputDeactivateRTO:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrDeactivateRTO, FALLING);
break;
case PinRole::InputDeactivateCM:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrDeactivateCM, FALLING);
break;
case PinRole::OutputHighLocked:
case PinRole::OutputHighUnlocked:
case PinRole::OutputHighMotorBlocked:
Expand Down Expand Up @@ -199,6 +207,10 @@ String Gpio::getRoleDescription(PinRole role) const
return "Input: Activate CM";
case PinRole::InputDeactivateRtoCm:
return "Input: Deactivate RTO/CM";
case PinRole::InputDeactivateRTO:
return "Input: Deactivate RTO";
case PinRole::InputDeactivateCM:
return "Input: Deactivate CM";
case PinRole::OutputHighLocked:
return "Output: High when locked";
case PinRole::OutputHighUnlocked:
Expand Down Expand Up @@ -327,6 +339,20 @@ void Gpio::isrDeactivateRtoCm()
_debounceTs = millis() + _debounceTime;
}

void Gpio::isrDeactivateRTO()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::DeactivateRTO, -1);
_debounceTs = millis() + _debounceTime;
}

void Gpio::isrDeactivateCM()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::DeactivateCM, -1);
_debounceTs = millis() + _debounceTime;
}

void Gpio::setPinOutput(const uint8_t& pin, const uint8_t& state)
{
digitalWrite(pin, state);
Expand Down
8 changes: 8 additions & 0 deletions Gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ enum class PinRole
InputActivateRTO,
InputActivateCM,
InputDeactivateRtoCm,
InputDeactivateRTO,
InputDeactivateCM,
OutputHighLocked,
OutputHighUnlocked,
OutputHighMotorBlocked,
Expand All @@ -38,6 +40,8 @@ enum class GpioAction
ActivateRTO,
ActivateCM,
DeactivateRtoCm,
DeactivateRTO,
DeactivateCM,
GeneralInput
};

Expand Down Expand Up @@ -88,6 +92,8 @@ class Gpio
PinRole::InputActivateRTO,
PinRole::InputActivateCM,
PinRole::InputDeactivateRtoCm,
PinRole::InputDeactivateRTO,
PinRole::InputDeactivateCM,
PinRole::OutputHighLocked,
PinRole::OutputHighUnlocked,
PinRole::OutputHighRtoActive,
Expand All @@ -110,6 +116,8 @@ class Gpio
static void IRAM_ATTR isrActivateRTO();
static void IRAM_ATTR isrActivateCM();
static void IRAM_ATTR isrDeactivateRtoCm();
static void IRAM_ATTR isrDeactivateRTO();
static void IRAM_ATTR isrDeactivateCM();

std::vector<std::function<void(const GpioAction&, const int&)>> _callbacks;

Expand Down
2 changes: 2 additions & 0 deletions MqttTopics.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
#define mqtt_topic_battery_keypad_critical "/battery/keypadCritical"

#define mqtt_topic_lock_state "/lock/state"
#define mqtt_topic_lock_ha_state "/lock/hastate"
#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"
#define mqtt_topic_query_battery "/lock/query/battery"
#define mqtt_topic_query_lockstate_command_result "/lock/query/lockstateCommandResult"
#define mqtt_topic_lock_binary_state "/lock/binaryState"
#define mqtt_topic_lock_continuous_mode "/lock/continuousMode"
#define mqtt_topic_lock_trigger "/lock/trigger"
#define mqtt_topic_lock_last_lock_action "/lock/lastLockAction"
#define mqtt_topic_lock_log "/lock/log"
Expand Down
64 changes: 55 additions & 9 deletions Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ bool Network::publishString(const char* prefix, const char *topic, const char *v
return _device->mqttPublish(path, MQTT_QOS_LEVEL, true, value) > 0;
}

void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState)
void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);

Expand Down Expand Up @@ -770,9 +770,12 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
json["pl_lock"] = lockAction;
json["pl_unlk"] = unlockAction;
json["pl_open"] = openAction;
json["stat_t"] = String("~") + mqtt_topic_lock_binary_state;
json["stat_locked"] = lockedState;
json["stat_unlocked"] = unlockedState;
json["stat_t"] = String("~") + mqtt_topic_lock_ha_state;
json["stat_jammed"] = "jammed";
json["stat_locked"] = "locked";
json["stat_locking"] = "locking";
json["stat_unlocked"] = "unlocked";
json["stat_unlocking"] = "unlocking";
json["opt"] = "false";

serializeJson(json, _buffer, _bufferSize);
Expand Down Expand Up @@ -1072,7 +1075,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
}


void Network::publishHASSConfigAdditionalButtons(char *deviceType, const char *baseTopic, char *name, char *uidString, const char *availabilityTopic, const bool &hasKeypad, char *lockAction, char *unlockAction, char *openAction, char *lockedState, char *unlockedState)
void Network::publishHASSConfigAdditionalButtons(char *deviceType, const char *baseTopic, char *name, char *uidString)
{
// Lock 'n' Go
publishHassTopic("button",
Expand Down Expand Up @@ -1132,9 +1135,7 @@ void Network::publishHASSConfigBatLevel(char *deviceType, const char *baseTopic,
}
}

void Network::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString,
char *lockAction, char *unlockAction, char *openAction, char *lockedState,
char *unlockedState)
void Network::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);

Expand All @@ -1159,6 +1160,50 @@ void Network::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopi
}
}

void Network::publishHASSConfigContinuousMode(char *deviceType, const char *baseTopic, char *name, char *uidString)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);

if (discoveryTopic != "")
{

publishHassTopic("binary_sensor",
"continuous_mode",
uidString,
"_continuous_mode",
"Continuous mode",
name,
baseTopic,
String("~") + mqtt_topic_lock_continuous_mode,
deviceType,
"lock",
"",
"",
"",
{{"pl_on", "on"},
{"pl_off", "off"}});

publishHassTopic("switch",
"continuous_mode",
uidString,
"_continuous_mode",
"Continuous mode",
name,
baseTopic,
String("~") + mqtt_topic_lock_continuous_mode,
deviceType,
"lock",
"",
"",
String("~") + mqtt_topic_lock_action,
{{ "enabled_by_default", "false" },
{"state_on", "on"},
{"state_on", "off"},
{"pl_on", "activateCM"},
{"pl_off", "deactivateCM"}});
}
}

void Network::publishHASSConfigRingDetect(char *deviceType, const char *baseTopic, char *name, char *uidString)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
Expand Down Expand Up @@ -1190,7 +1235,6 @@ void Network::publishHASSConfigRingDetect(char *deviceType, const char *baseTopi
}
}


void Network::publishHASSConfigLedBrightness(char *deviceType, const char *baseTopic, char *name, char *uidString)
{
publishHassTopic("number",
Expand Down Expand Up @@ -1412,6 +1456,8 @@ void Network::removeHASSConfig(char* uidString)
removeHassTopic("sensor", "keypad_status", uidString);
removeHassTopic("sensor", "wifi_signal_strength", uidString);
removeHassTopic("sensor", "bluetooth_signal_strength", uidString);
removeHassTopic("binary_sensor", "continuous_mode", uidString);
removeHassTopic("switch", "continuous_mode", uidString);
}
}

Expand Down
7 changes: 4 additions & 3 deletions Network.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ class Network
void publishBool(const char* prefix, const char* topic, const bool value);
bool publishString(const char* prefix, const char* topic, const char* value);

void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState);
void publishHASSConfigAdditionalButtons(char* deviceType, const char* baseTopic, char* name, char* uidString, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState);
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
void publishHASSConfigAdditionalButtons(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigBatLevel(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState);
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigRingDetect(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigContinuousMode(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigLedBrightness(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigSoundLevel(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString);
Expand Down
28 changes: 21 additions & 7 deletions NetworkLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne

if(_haEnabled)
{
publishBinaryState(keyTurnerState.lockState);
publishState(keyTurnerState.lockState);
}
}

Expand Down Expand Up @@ -300,21 +300,35 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
_firstTunerStatePublish = false;
}

void NetworkLock::publishBinaryState(NukiLock::LockState lockState)
void NetworkLock::publishState(NukiLock::LockState lockState)
{
switch(lockState)
{
case NukiLock::LockState::Locked:
publishString(mqtt_topic_lock_ha_state, "locked");
publishString(mqtt_topic_lock_binary_state, "locked");
break;
case NukiLock::LockState::Locking:
publishString(mqtt_topic_lock_ha_state, "locking");
publishString(mqtt_topic_lock_binary_state, "locked");
break;
case NukiLock::LockState::Unlocked:
case NukiLock::LockState::Unlocking:
publishString(mqtt_topic_lock_ha_state, "unlocking");
publishString(mqtt_topic_lock_binary_state, "unlocked");
break;
case NukiLock::LockState::Unlocked:
case NukiLock::LockState::Unlatched:
case NukiLock::LockState::Unlatching:
case NukiLock::LockState::UnlockedLnga:
publishString(mqtt_topic_lock_ha_state, "unlocked");
publishString(mqtt_topic_lock_binary_state, "unlocked");
break;
case NukiLock::LockState::Uncalibrated:
case NukiLock::LockState::Calibration:
case NukiLock::LockState::BootRun:
case NukiLock::LockState::MotorBlocked:
publishString(mqtt_topic_lock_ha_state, "jammed");
break;
default:
break;
}
Expand Down Expand Up @@ -571,15 +585,15 @@ bool NetworkLock::comparePrefixedPath(const char *fullPath, const char *subPath)
}

void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char *lockAction,
char *unlockAction, char *openAction, char *lockedState, char *unlockedState)
char *unlockAction, char *openAction)
{
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, "~/maintenance/mqttConnectionState", hasKeypad, lockAction, unlockAction, openAction, lockedState, unlockedState);
_network->publishHASSConfigAdditionalButtons(deviceType, baseTopic, name, uidString, "~/maintenance/mqttConnectionState", hasKeypad, lockAction, unlockAction, openAction, lockedState, unlockedState);
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, "~/maintenance/mqttConnectionState", hasKeypad, lockAction, unlockAction, openAction);
_network->publishHASSConfigAdditionalButtons(deviceType, baseTopic, name, uidString);
_network->publishHASSConfigBatLevel(deviceType, baseTopic, name, uidString);
_network->publishHASSConfigLedBrightness(deviceType, baseTopic, name, uidString);
if(hasDoorSensor)
{
_network->publishHASSConfigDoorSensor(deviceType, baseTopic, name, uidString, lockAction, unlockAction, openAction, lockedState, unlockedState);
_network->publishHASSConfigDoorSensor(deviceType, baseTopic, name, uidString);
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions NetworkLock.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class NetworkLock : public MqttReceiver
void initialize();

void publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState);
void publishBinaryState(NukiLock::LockState lockState);
void publishState(NukiLock::LockState lockState);
void publishAuthorizationInfo(const std::list<NukiLock::LogEntry>& logEntries);
void clearAuthorizationInfo();
void publishCommandResult(const char* resultStr);
Expand All @@ -34,7 +34,7 @@ class NetworkLock : public MqttReceiver
void publishRssi(const int& rssi);
void publishRetry(const std::string& message);
void publishBleAddress(const std::string& address);
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState);
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
void removeHASSConfig(char* uidString);
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
void publishKeypadCommandResult(const char* result);
Expand Down
Loading
Loading