diff --git a/lightbar.cpp b/lightbar.cpp index 0330ec0..85c105d 100644 --- a/lightbar.cpp +++ b/lightbar.cpp @@ -13,6 +13,16 @@ Lightbar::~Lightbar() { } +void Lightbar::toggleInternalState() +{ + onState = !onState; +} + +bool Lightbar::getOnState() +{ + return onState; +} + uint32_t Lightbar::getSerial() { return this->serial; @@ -44,12 +54,6 @@ void Lightbar::onOff() onState = !onState; } -void Lightbar::setOnOff(bool on) -{ - if (onState != on) - this->onOff(); -} - void Lightbar::brighter() { this->sendRawCommand(Lightbar::Command::BRIGHTER); diff --git a/lightbar.h b/lightbar.h index 4ea7eba..b928bba 100644 --- a/lightbar.h +++ b/lightbar.h @@ -31,14 +31,15 @@ class Lightbar void cooler(); void reset(); void pair(); - void setOnOff(bool on); void setTemperature(uint8_t value); void setMiredTemperature(uint mireds); void setBrightness(uint8_t value); + void toggleInternalState(); + bool getOnState(); private: Radio *radio; - bool onState = false; + bool onState = true; uint32_t serial; String serialString; const char *name; diff --git a/mqtt.cpp b/mqtt.cpp index a27d785..a6bc1fc 100644 --- a/mqtt.cpp +++ b/mqtt.cpp @@ -67,6 +67,13 @@ void MQTT::onMessage(char *topic, byte *payload, unsigned int length) return; } + if (!strcmp(topic, String(this->getCombinedRootTopic() + "/" + lightbar->getSerialString() + "/toggle_internal").c_str())) + { + lightbar->toggleInternalState(); + this->publishLightbarState(lightbar); + return; + } + if (strcmp(topic, String(this->getCombinedRootTopic() + "/" + lightbar->getSerialString() + "/command").c_str())) continue; @@ -75,8 +82,8 @@ void MQTT::onMessage(char *topic, byte *payload, unsigned int length) if (command.hasOwnProperty("state")) { - const char *state = command["state"]; - lightbar->setOnOff(strcmp(state, "ON")); + lightbar->onOff(); + this->publishLightbarState(lightbar); } if (command.hasOwnProperty("brightness")) @@ -91,6 +98,25 @@ void MQTT::onMessage(char *topic, byte *payload, unsigned int length) } } +Lightbar *MQTT::get_lightbar_by_serial(uint32_t serial){ + for (int i = 0; i < this->lightbarCount; i++){ + if (this->lightbars[i]->getSerial() == serial){ + return this->lightbars[i]; + } + } +} + +void MQTT::publishLightbarState(Lightbar *lightbar){ + JSONVar stateJson; + stateJson["state"] = lightbar->getOnState() ? "ON" : "OFF"; + + String payload = JSON.stringify(stateJson); + String stateTopic = this->getCombinedRootTopic() + "/" + lightbar->getSerialString() + "/state"; + + // Publish with retain flag set to true + this->client->publish(stateTopic.c_str(), payload.c_str(), true); +} + void MQTT::setup() { Serial.print("[MQTT] Device ID: "); @@ -121,8 +147,15 @@ void MQTT::setup() this->client->publish(String(this->getCombinedRootTopic() + "/availability").c_str(), "online", true); this->client->subscribe(String(this->getCombinedRootTopic() + "/+/command").c_str()); this->client->subscribe(String(this->getCombinedRootTopic() + "/+/pair").c_str()); + this->client->subscribe(String(this->getCombinedRootTopic() + "/+/toggle_internal").c_str()); this->sendAllHomeAssistantDiscoveryMessages(); + + //send your current state after init, should be on by default + for (int i = 0; i < this->lightbarCount; i++){ + this->publishLightbarState(this->lightbars[i]); + } + } bool MQTT::addLightbar(Lightbar *lightbar) @@ -179,7 +212,7 @@ bool MQTT::removeRemote(Remote *remote) { if (this->remotes[i] == remote) { - this->remotes[i]->registerCommandListener(this->remoteCommandHandler); + this->remotes[i]->unregisterCommandListener(this->remoteCommandHandler); for (int j = i; j < this->remoteCount - 1; j++) { this->remotes[j] = this->remotes[j + 1]; @@ -256,6 +289,7 @@ void MQTT::sendHomeAssistantLightbarDiscoveryMessages(Lightbar *lightbar) "brightness_scale": 15, "name": "Light bar", "cmd_t": "~/command", + "stat_t": "~/state", "uniq_id": ")json" + topicClient + R"json(_lightbar", "max_mireds": 370, @@ -280,6 +314,19 @@ void MQTT::sendHomeAssistantLightbarDiscoveryMessages(Lightbar *lightbar) this->client->beginPublish(String(homeAssistantDiscoveryPrefix + "/button/" + topicClient + "/pair/config").c_str(), rendevous_str.length(), true); this->client->print(rendevous_str); this->client->endPublish(); + + rendevous_str = "{" + + baseConfig + + R"json( + "name": "Toggle Internal State", + "cmd_t": "~/toggle_internal", + "uniq_id": ")json" + + topicClient + R"json(_toggle_internal", + "p": "button" + )json" + "}"; + this->client->beginPublish(String(homeAssistantDiscoveryPrefix + "/button/" + topicClient + "/toggle_internal/config").c_str(), rendevous_str.length(), true); + this->client->print(rendevous_str); + this->client->endPublish(); } void MQTT::sendHomeAssistantRemoteDiscoveryMessages(Remote *remote) @@ -382,9 +429,13 @@ void MQTT::sendAction(Remote *remote, byte command, byte options) String action; switch ((uint8_t)command) { - case Lightbar::Command::ON_OFF: + case Lightbar::Command::ON_OFF:{ action = "press"; + Lightbar *lightbar = this->get_lightbar_by_serial(remote->getSerial()); + lightbar->toggleInternalState(); + this->publishLightbarState(lightbar); break; + } case Lightbar::Command::BRIGHTER: action = "turn_clockwise"; diff --git a/mqtt.h b/mqtt.h index e52fd62..184d2d2 100644 --- a/mqtt.h +++ b/mqtt.h @@ -26,6 +26,9 @@ class MQTT void sendAction(Remote *remote, byte command, byte options); const String getCombinedRootTopic(); const String getClientId(); + boolean get_MQTT_connection_failed(); + void publishLightbarState(Lightbar *lightbar); + Lightbar *get_lightbar_by_serial(uint32_t serial); private: WiFiClient *wifiClient; diff --git a/radio.cpp b/radio.cpp index be9c589..234c16b 100644 --- a/radio.cpp +++ b/radio.cpp @@ -156,7 +156,7 @@ void Radio::setup() Serial.println("[Radio] Setting up radio..."); this->radio.failureDetected = false; - this->radio.openReadingPipe(0, Radio::address); + this->radio.openReadingPipe(0, Radio::receive_address); this->radio.setChannel(68); this->radio.setDataRate(RF24_2MBPS); @@ -166,7 +166,7 @@ void Radio::setup() this->radio.setAutoAck(false); this->radio.setRetries(15, 15); - this->radio.openWritingPipe(Radio::address); + this->radio.openWritingPipe(Radio::send_address); this->radio.startListening(); Serial.println("[Radio] done!"); @@ -261,6 +261,14 @@ void Radio::handlePackage() Serial.println("[Radio] Ignoring package with too low package number!"); return; } + + if (package_id_for_serial->never_read) { + package_id_for_serial->never_read = false; + } + else if (package_id_for_serial->package_id == package_id){ + return; + } + package_id_for_serial->package_id = package_id; Serial.println("[Radio] Package received!"); diff --git a/radio.h b/radio.h index c9a6e2a..e8f411c 100644 --- a/radio.h +++ b/radio.h @@ -12,6 +12,7 @@ class Remote; struct PackageIdForSerial { uint32_t serial; + boolean never_read = true; uint8_t package_id; }; @@ -35,7 +36,8 @@ class Radio Remote *remotes[constants::MAX_REMOTES]; uint8_t num_remotes = 0; - static const uint64_t address = 0xAAAAAAAAAAAA; + static const uint64_t send_address = 0x5555555555; + static const uint64_t receive_address = 0xAAAAAAAAAA; static constexpr byte preamble[8] = {0x53, 0x39, 0x14, 0xDD, 0x1C, 0x49, 0x34, 0x12}; // For details on how these parameters were chosen, see