This commit is contained in:
2021-01-12 12:26:58 +01:00
parent 2d67aceba0
commit 0031f92c54
190 changed files with 25835 additions and 1 deletions

View File

@@ -0,0 +1,16 @@
#include <LightMqttSettingsService.h>
LightMqttSettingsService::LightMqttSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
_httpEndpoint(LightMqttSettings::read,
LightMqttSettings::update,
this,
server,
LIGHT_BROKER_SETTINGS_PATH,
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED),
_fsPersistence(LightMqttSettings::read, LightMqttSettings::update, this, fs, LIGHT_BROKER_SETTINGS_FILE) {
}
void LightMqttSettingsService::begin() {
_fsPersistence.readFromFS();
}

View File

@@ -0,0 +1,41 @@
#ifndef LightMqttSettingsService_h
#define LightMqttSettingsService_h
#include <HttpEndpoint.h>
#include <FSPersistence.h>
#include <SettingValue.h>
#define LIGHT_BROKER_SETTINGS_FILE "/config/brokerSettings.json"
#define LIGHT_BROKER_SETTINGS_PATH "/rest/brokerSettings"
class LightMqttSettings {
public:
String mqttPath;
String name;
String uniqueId;
static void read(LightMqttSettings& settings, JsonObject& root) {
root["mqtt_path"] = settings.mqttPath;
root["name"] = settings.name;
root["unique_id"] = settings.uniqueId;
}
static StateUpdateResult update(JsonObject& root, LightMqttSettings& settings) {
settings.mqttPath = root["mqtt_path"] | SettingValue::format("homeassistant/light/#{unique_id}");
settings.name = root["name"] | SettingValue::format("light-#{unique_id}");
settings.uniqueId = root["unique_id"] | SettingValue::format("light-#{unique_id}");
return StateUpdateResult::CHANGED;
}
};
class LightMqttSettingsService : public StatefulService<LightMqttSettings> {
public:
LightMqttSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
void begin();
private:
HttpEndpoint<LightMqttSettings> _httpEndpoint;
FSPersistence<LightMqttSettings> _fsPersistence;
};
#endif // end LightMqttSettingsService_h

73
src/LightStateService.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include <LightStateService.h>
LightStateService::LightStateService(AsyncWebServer* server,
SecurityManager* securityManager,
AsyncMqttClient* mqttClient,
LightMqttSettingsService* lightMqttSettingsService) :
_httpEndpoint(LightState::read,
LightState::update,
this,
server,
LIGHT_SETTINGS_ENDPOINT_PATH,
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED),
_mqttPubSub(LightState::haRead, LightState::haUpdate, this, mqttClient),
_webSocket(LightState::read,
LightState::update,
this,
server,
LIGHT_SETTINGS_SOCKET_PATH,
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED),
_mqttClient(mqttClient),
_lightMqttSettingsService(lightMqttSettingsService) {
// configure led to be output
pinMode(LED_PIN, OUTPUT);
// configure MQTT callback
_mqttClient->onConnect(std::bind(&LightStateService::registerConfig, this));
// configure update handler for when the light settings change
_lightMqttSettingsService->addUpdateHandler([&](const String& originId) { registerConfig(); }, false);
// configure settings service update handler to update LED state
addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false);
}
void LightStateService::begin() {
_state.ledOn = DEFAULT_LED_STATE;
onConfigUpdated();
}
void LightStateService::onConfigUpdated() {
digitalWrite(LED_PIN, _state.ledOn ? LED_ON : LED_OFF);
}
void LightStateService::registerConfig() {
if (!_mqttClient->connected()) {
return;
}
String configTopic;
String subTopic;
String pubTopic;
DynamicJsonDocument doc(256);
_lightMqttSettingsService->read([&](LightMqttSettings& settings) {
configTopic = settings.mqttPath + "/config";
subTopic = settings.mqttPath + "/set";
pubTopic = settings.mqttPath + "/state";
doc["~"] = settings.mqttPath;
doc["name"] = settings.name;
doc["unique_id"] = settings.uniqueId;
});
doc["cmd_t"] = "~/set";
doc["stat_t"] = "~/state";
doc["schema"] = "json";
doc["brightness"] = false;
String payload;
serializeJson(doc, payload);
_mqttClient->publish(configTopic.c_str(), 0, false, payload.c_str());
_mqttPubSub.configureTopics(pubTopic, subTopic);
}

88
src/LightStateService.h Normal file
View File

@@ -0,0 +1,88 @@
#ifndef LightStateService_h
#define LightStateService_h
#include <LightMqttSettingsService.h>
#include <HttpEndpoint.h>
#include <MqttPubSub.h>
#include <WebSocketTxRx.h>
#define LED_PIN 2
#define PRINT_DELAY 5000
#define DEFAULT_LED_STATE false
#define OFF_STATE "OFF"
#define ON_STATE "ON"
// Note that the built-in LED is on when the pin is low on most NodeMCU boards.
// This is because the anode is tied to VCC and the cathode to the GPIO 4 (Arduino pin 2).
#ifdef ESP32
#define LED_ON 0x1
#define LED_OFF 0x0
#elif defined(ESP8266)
#define LED_ON 0x0
#define LED_OFF 0x1
#endif
#define LIGHT_SETTINGS_ENDPOINT_PATH "/rest/lightState"
#define LIGHT_SETTINGS_SOCKET_PATH "/ws/lightState"
class LightState {
public:
bool ledOn;
static void read(LightState& settings, JsonObject& root) {
root["led_on"] = settings.ledOn;
}
static StateUpdateResult update(JsonObject& root, LightState& lightState) {
boolean newState = root["led_on"] | DEFAULT_LED_STATE;
if (lightState.ledOn != newState) {
lightState.ledOn = newState;
return StateUpdateResult::CHANGED;
}
return StateUpdateResult::UNCHANGED;
}
static void haRead(LightState& settings, JsonObject& root) {
root["state"] = settings.ledOn ? ON_STATE : OFF_STATE;
}
static StateUpdateResult haUpdate(JsonObject& root, LightState& lightState) {
String state = root["state"];
// parse new led state
boolean newState = false;
if (state.equals(ON_STATE)) {
newState = true;
} else if (!state.equals(OFF_STATE)) {
return StateUpdateResult::ERROR;
}
// change the new state, if required
if (lightState.ledOn != newState) {
lightState.ledOn = newState;
return StateUpdateResult::CHANGED;
}
return StateUpdateResult::UNCHANGED;
}
};
class LightStateService : public StatefulService<LightState> {
public:
LightStateService(AsyncWebServer* server,
SecurityManager* securityManager,
AsyncMqttClient* mqttClient,
LightMqttSettingsService* lightMqttSettingsService);
void begin();
private:
HttpEndpoint<LightState> _httpEndpoint;
MqttPubSub<LightState> _mqttPubSub;
WebSocketTxRx<LightState> _webSocket;
AsyncMqttClient* _mqttClient;
LightMqttSettingsService* _lightMqttSettingsService;
void registerConfig();
void onConfigUpdated();
};
#endif

36
src/main.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include <ESP8266React.h>
#include <LightMqttSettingsService.h>
#include <LightStateService.h>
#define SERIAL_BAUD_RATE 115200
AsyncWebServer server(80);
ESP8266React esp8266React(&server);
LightMqttSettingsService lightMqttSettingsService =
LightMqttSettingsService(&server, esp8266React.getFS(), esp8266React.getSecurityManager());
LightStateService lightStateService = LightStateService(&server,
esp8266React.getSecurityManager(),
esp8266React.getMqttClient(),
&lightMqttSettingsService);
void setup() {
// start serial and filesystem
Serial.begin(SERIAL_BAUD_RATE);
// start the framework and demo project
esp8266React.begin();
// load the initial light settings
lightStateService.begin();
// start the light service
lightMqttSettingsService.begin();
// start the server
server.begin();
}
void loop() {
// run the framework's loop function
esp8266React.loop();
}