diff --git a/data/routes/misc.html b/data/routes/misc.html index eca4b9c..9a4b431 100644 --- a/data/routes/misc.html +++ b/data/routes/misc.html @@ -14,18 +14,16 @@

-
+
- -
+
-
+
+ + +
+
+ + +
HomeKey Card Finish:
@@ -170,6 +179,7 @@

MQTT Topics

+
+ + +
diff --git a/src/config.h b/src/config.h index ba3aa07..4ef3153 100644 --- a/src/config.h +++ b/src/config.h @@ -60,6 +60,7 @@ enum class gpioMomentaryStateStatus : uint8_t #define MQTT_SET_TARGET_STATE_TOPIC "homekit/set_target_state" // MQTT Control Topic for the HomeKit lock target state #define MQTT_SET_CURRENT_STATE_TOPIC "homekit/set_current_state" // MQTT Control Topic for the HomeKit lock current state #define MQTT_STATE_TOPIC "homekit/state" // MQTT Topic for publishing the HomeKit lock target state +#define MQTT_PROX_BAT_TOPIC "homekit/set_battery_lvl" // MQTT Topic for publishing the HomeKit lock target state // Miscellaneous #define HOMEKEY_COLOR TAN diff --git a/src/main.cpp b/src/main.cpp index 108cc34..333a846 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,6 +71,7 @@ namespace espConfig lockTStateCmd.append(id).append("/" MQTT_SET_TARGET_STATE_TOPIC); lockCustomStateTopic.append(id).append("/" MQTT_CUSTOM_STATE_TOPIC); lockCustomStateCmd.append(id).append("/" MQTT_CUSTOM_STATE_CTRL_TOPIC); + btrLvlCmdTopic.append(id).append("/" MQTT_PROX_BAT_TOPIC); } /* MQTT Broker */ std::string mqttBroker = MQTT_HOST; @@ -85,6 +86,7 @@ namespace espConfig std::string lockStateCmd; std::string lockCStateCmd; std::string lockTStateCmd; + std::string btrLvlCmdTopic; /* MQTT Custom State */ std::string lockCustomStateTopic; std::string lockCustomStateCmd; @@ -94,7 +96,7 @@ namespace espConfig bool nfcTagNoPublish = false; std::map customLockStates = { {"C_LOCKED", C_LOCKED}, {"C_UNLOCKING", C_UNLOCKING}, {"C_UNLOCKED", C_UNLOCKED}, {"C_LOCKING", C_LOCKING}, {"C_JAMMED", C_JAMMED}, {"C_UNKNOWN", C_UNKNOWN} }; std::map customLockActions = { {"UNLOCK", UNLOCK}, {"LOCK", LOCK} }; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(espConfig::mqttConfig_t, mqttBroker, mqttPort, mqttUsername, mqttPassword, mqttClientId, lwtTopic, hkTopic, lockStateTopic, lockStateCmd, lockCStateCmd, lockTStateCmd, lockCustomStateTopic, lockCustomStateCmd, lockEnableCustomState, hassMqttDiscoveryEnabled, customLockStates, customLockActions, nfcTagNoPublish) + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(espConfig::mqttConfig_t, mqttBroker, mqttPort, mqttUsername, mqttPassword, mqttClientId, lwtTopic, hkTopic, lockStateTopic, lockStateCmd, lockCStateCmd, lockTStateCmd, lockCustomStateTopic, lockCustomStateCmd, lockEnableCustomState, hassMqttDiscoveryEnabled, customLockStates, customLockActions, nfcTagNoPublish, btrLvlCmdTopic) } mqttData; struct misc_config_t @@ -135,13 +137,17 @@ namespace espConfig std::string webUsername = WEB_AUTH_USERNAME; std::string webPassword = WEB_AUTH_PASSWORD; std::array nfcGpioPins{SS, SCK, MISO, MOSI}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(misc_config_t, deviceName, otaPasswd, hk_key_color, setupCode, lockAlwaysUnlock, lockAlwaysLock, controlPin, hsStatusPin, nfcSuccessPin, nfcSuccessTime, nfcNeopixelPin, neopixelSuccessColor, neopixelFailureColor, neopixelSuccessTime, neopixelFailTime, nfcSuccessHL, nfcFailPin, nfcFailTime, nfcFailHL, gpioActionPin, gpioActionLockState, gpioActionUnlockState, gpioActionMomentaryEnabled, gpioActionMomentaryTimeout, webAuthEnabled, webUsername, webPassword, nfcGpioPins) + uint8_t btrLowStatusThreshold = 10; + bool proxBatEnabled = false; + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(misc_config_t, deviceName, otaPasswd, hk_key_color, setupCode, lockAlwaysUnlock, lockAlwaysLock, controlPin, hsStatusPin, nfcSuccessPin, nfcSuccessTime, nfcNeopixelPin, neopixelSuccessColor, neopixelFailureColor, neopixelSuccessTime, neopixelFailTime, nfcSuccessHL, nfcFailPin, nfcFailTime, nfcFailHL, gpioActionPin, gpioActionLockState, gpioActionUnlockState, gpioActionMomentaryEnabled, gpioActionMomentaryTimeout, webAuthEnabled, webUsername, webPassword, nfcGpioPins, btrLowStatusThreshold, proxBatEnabled) } miscConfig; }; KeyFlow hkFlow = KeyFlow::kFlowFAST; SpanCharacteristic* lockCurrentState; SpanCharacteristic* lockTargetState; +SpanCharacteristic* statusLowBtr; +SpanCharacteristic* btrLevel; esp_mqtt_client_handle_t client = nullptr; std::unique_ptr pixel; @@ -155,6 +161,15 @@ bool save_to_nvs() { return !set_nvs && !commit_nvs; } +struct PhysicalLockBattery : Service::BatteryService +{ + PhysicalLockBattery() { + LOG(D, "Configuring PhysicalLockBattery"); + statusLowBtr = new Characteristic::StatusLowBattery(0, true); + btrLevel = new Characteristic::BatteryLevel(100, true); + } +}; + struct LockManagement : Service::LockManagement { SpanCharacteristic* lockControlPoint; @@ -682,6 +697,9 @@ void mqtt_connected_event(void* event_handler_arg, esp_event_base_t event_base, if (espConfig::mqttData.lockEnableCustomState) { esp_mqtt_client_subscribe(client, espConfig::mqttData.lockCustomStateCmd.c_str(), 0); } + if (espConfig::miscConfig.proxBatEnabled) { + esp_mqtt_client_subscribe(client, espConfig::mqttData.btrLvlCmdTopic.c_str(), 0); + } esp_mqtt_client_subscribe(client, espConfig::mqttData.lockStateCmd.c_str(), 0); esp_mqtt_client_subscribe(client, espConfig::mqttData.lockCStateCmd.c_str(), 0); esp_mqtt_client_subscribe(client, espConfig::mqttData.lockTStateCmd.c_str(), 0); @@ -709,6 +727,13 @@ void mqtt_data_handler(void* event_handler_arg, esp_event_base_t event_base, int lockCurrentState->setVal(state); esp_mqtt_client_publish(client, espConfig::mqttData.lockStateTopic.c_str(), std::to_string(lockCurrentState->getVal()).c_str(), 0, 1, true); } + } else if (!strcmp(espConfig::mqttData.btrLvlCmdTopic.c_str(), topic.c_str())) { + btrLevel->setVal(state); + if (state <= espConfig::miscConfig.btrLowStatusThreshold) { + statusLowBtr->setVal(1); + } else { + statusLowBtr->setVal(0); + } } } @@ -800,6 +825,10 @@ String miscHtmlProcess(const String& var) { return String(espConfig::miscConfig.nfcGpioPins[2]); } else if (var == "NFCMOSIGPIOPIN") { return String(espConfig::miscConfig.nfcGpioPins[3]); + } else if (var == "BTRLOWTHRESHOLD") { + return String(espConfig::miscConfig.btrLowStatusThreshold); + } else if (var == "PROXBATENABLE") { + return String(espConfig::miscConfig.proxBatEnabled); } return String(); } @@ -883,6 +912,8 @@ String mqttHtmlProcess(const String& var) { return String(espConfig::mqttData.customLockStates["C_UNKNOWN"]); } else if (var == "NFCTAGSNOPUBLISH") { return String(espConfig::mqttData.nfcTagNoPublish); + } else if (var == "BTRLEVELCMD") { + return String(espConfig::mqttData.btrLvlCmdTopic.c_str()); } return ""; } @@ -1122,6 +1153,17 @@ void setupWeb() { return; } espConfig::miscConfig.nfcGpioPins[3] = p->value().toInt(); + } else if (!strcmp(p->name().c_str(), "prox-bat-enable")) { + espConfig::miscConfig.proxBatEnabled = p->value().toInt(); + } else if (!strcmp(p->name().c_str(), "btr-low-threshold")) { + espConfig::miscConfig.btrLowStatusThreshold = p->value().toInt(); + if (statusLowBtr && btrLevel) { + if (btrLevel->getVal() <= espConfig::miscConfig.btrLowStatusThreshold) { + statusLowBtr->setVal(1); + } else { + statusLowBtr->setVal(0); + } + } } } json json_misc_config = espConfig::miscConfig; @@ -1614,7 +1656,20 @@ void setup() { } save_to_nvs(); }); - + new SpanUserCommand('N', "Btr status low", [](const char* arg) { + const char* TAG = "BTR_LOW"; + if (strncmp(arg + 1, "0", 1) == 0) { + statusLowBtr->setVal(0); + LOG(I, "Low status set to NORMAL"); + } else if (strncmp(arg + 1, "1", 1) == 0) { + statusLowBtr->setVal(1); + LOG(I, "Low status set to LOW"); + } + }); + new SpanUserCommand('B', "Btr level", [](const char* arg) { + uint8_t level = atoi(static_cast(arg + 1)); + btrLevel->setVal(level); + }); new SpanAccessory(); new Service::AccessoryInformation(); @@ -1640,6 +1695,9 @@ void setup() { new NFCAccess(); new Service::HAPProtocolInformation(); new Characteristic::Version(); + if (espConfig::miscConfig.proxBatEnabled) { + new PhysicalLockBattery(); + } homeSpan.setControllerCallback(pairCallback); homeSpan.setWifiCallback(wifiCallback); if (espConfig::miscConfig.nfcNeopixelPin != 255) {