Configuration possible through mqtt

This commit is contained in:
Philip Johansson 2020-06-09 16:56:50 +02:00
parent 9359c72234
commit 4ee892531a
5 changed files with 92 additions and 52 deletions

View File

@ -18,7 +18,7 @@ PenaltyReturnTypeOnItsOwnLine: 1000000
BreakConstructorInitializers: BeforeComma
ConstructorInitializerIndentWidth: 0
BraceWrapping:
AfterEnum: true
AfterEnum: false
AfterStruct: false
SplitEmptyFunction: false
AfterCaseLabel: false

View File

@ -6,6 +6,8 @@ An esp8266 powered **IKEA Tvärfot** with a Neopixel ring and a proximity sensor
## Writing a configuration
Open a Serial Monitor at baudrate 9600 and paste the following json configuration adapted to your needs.
Before sending press the on board button "flash" or connect a button to D0. You will now have 10s to send the configuration. The onboard LED will light up as long as the board reads Serial input. If successful the new configuration should be shown in the terminal.
It is also possible to send the same json configuration on mqtt using topic *light/bedlamp/relay/0/config*. This of course demands that the ESP is connected to your wifi, logged in and registered on the mqtt service so this cannot be used for initial configuration.
```
{
"hostname": "your_hostname",
@ -22,8 +24,9 @@ Before sending press the on board button "flash" or connect a button to D0. You
Configured in vscode, inside of *platformio.ini* change the board name to what you've set in the configuration. Then upload sketch updates via WiFi by clicking the *Upload* button in *platformIO* under the *evn:esp8266 OTA* configuration
## MQTT
Topics....
Example payload:
### State and Command topics
An identical json package is both sent and received to set and get the status of the light. The command topic is *light/bedlamp/relay/0/set* and the state topic is *light/bedlamp/relay/0*.
```
{
"brightness": 255,
@ -35,6 +38,10 @@ Example payload:
"state": "ON"
}
```
### Configuration topic
See *Writing a configuration*. This can also be done using mqtt at topic *light/bedlamp/relay/0/config*
## Home Assistant
Adjust the name and topics to suite your configuration
```

View File

@ -17,6 +17,12 @@ public:
std::array<uint8_t, 3> color;
} Data;
enum MqttTopic {
OutTopic,
InTopic,
ConfigTopic,
};
static Config& Instance();
Config(Config&) = delete;
@ -28,6 +34,8 @@ public:
void write();
void write(Data data);
String getMqttTopic(MqttTopic);
Data data;
private:

View File

@ -47,8 +47,26 @@ void Config::write()
Serial.println("Saving config");
printConfig(data);
}
void Config::write(Data data)
{
this->data = data;
write();
}
String Config::getMqttTopic(MqttTopic topic)
{
switch (topic)
{
case (MqttTopic::OutTopic):
return String("light/" + String(data.hostname) + "/relay/0");
break;
case (MqttTopic::InTopic):
return String("light/" + String(data.hostname) + "/relay/0/set");
break;
case (MqttTopic::ConfigTopic):
return String("light/" + String(data.hostname) + "/relay/0/config");
break;
}
return {};
}

View File

@ -22,10 +22,10 @@ const int sensorPin = A0;
const int ledPin = D8;
const int ledCount = 4;
EasyButton button(buttonPin);
Config& config = Config::Instance();
EasyButton button(buttonPin);
MyLed myLed(ledPin, ledCount);
WiFiClient wifiClient;
@ -41,46 +41,51 @@ typedef struct {
bool validReading; // In within sensor range
} SensorData;
void setConfig(String jsonConfig)
{
DynamicJsonDocument doc(512);
deserializeJson(doc, jsonConfig);
JsonObject obj = doc.as<JsonObject>();
String hostname = obj["hostname"];
String ssid = obj["ssid"];
String wifiPass = obj["pass"];
String mqttServer = obj["mqttserver"];
String mqttUser = obj["mqttuser"];
String mqttPass = obj["mqttpass"];
int mqttPort = obj["mqttport"];
Serial.printf("Parsed hostname: %s, ssid: %s, pass: %s\n",
hostname.c_str(),
ssid.c_str(),
String(wifiPass).c_str());
if (hostname != "null" && ssid != "null" && wifiPass != "null")
{
hostname.toCharArray(config.data.hostname,
sizeof(config.data.hostname));
ssid.toCharArray(config.data.ssid, sizeof(config.data.ssid));
wifiPass.toCharArray(config.data.pass, sizeof(config.data.pass));
mqttServer.toCharArray(config.data.mqttServer,
sizeof(config.data.mqttServer));
mqttUser.toCharArray(config.data.mqttUser,
sizeof(config.data.mqttUser));
mqttPass.toCharArray(config.data.mqttPass,
sizeof(config.data.mqttPass));
config.data.mqttPort = mqttPort;
config.write();
Serial.println("rebooting...");
ESP.restart();
}
}
void checkSerial()
{
String s = Serial.readString();
if (!s.isEmpty())
{
Serial.println(s.c_str());
DynamicJsonDocument doc(512);
deserializeJson(doc, s);
JsonObject obj = doc.as<JsonObject>();
String hostname = obj["hostname"];
String ssid = obj["ssid"];
String wifiPass = obj["pass"];
String mqttServer = obj["mqttserver"];
String mqttUser = obj["mqttuser"];
String mqttPass = obj["mqttpass"];
int mqttPort = obj["mqttport"];
Serial.printf("Parsed hostname: %s, ssid: %s, pass: %s\n",
hostname.c_str(),
ssid.c_str(),
String(wifiPass).c_str());
if (hostname != "null" && ssid != "null" && wifiPass != "null")
{
hostname.toCharArray(config.data.hostname,
sizeof(config.data.hostname));
ssid.toCharArray(config.data.ssid, sizeof(config.data.ssid));
wifiPass.toCharArray(config.data.pass, sizeof(config.data.pass));
mqttServer.toCharArray(config.data.mqttServer,
sizeof(config.data.mqttServer));
mqttUser.toCharArray(config.data.mqttUser,
sizeof(config.data.mqttUser));
mqttPass.toCharArray(config.data.mqttPass,
sizeof(config.data.mqttPass));
config.data.mqttPort = mqttPort;
config.write();
Serial.println("rebooting...");
ESP.restart();
}
setConfig(s);
}
}
@ -104,10 +109,10 @@ void onPressed()
void mqttPublishState()
{
const String outTopic =
"light/" + String(config.data.hostname) + "/relay/0";
if (mqttClient.connected())
mqttClient.publish(outTopic.c_str(), myLed.get().c_str());
mqttClient.publish(
config.getMqttTopic(Config::MqttTopic::OutTopic).c_str(),
myLed.get().c_str());
}
void mqttReconnect()
@ -121,9 +126,10 @@ void mqttReconnect()
{
Serial.println("connected");
mqttPublishState();
const String inTopic =
"light/" + String(config.data.hostname) + "/relay/0/set";
mqttClient.subscribe(inTopic.c_str());
mqttClient.subscribe(
config.getMqttTopic(Config::MqttTopic::InTopic).c_str());
mqttClient.subscribe(
config.getMqttTopic(Config::MqttTopic::ConfigTopic).c_str());
} else
{
Serial.print("failed, rc=");
@ -138,12 +144,17 @@ void mqttReconnect()
void mqttCallback(char* topic, byte* payload, unsigned int length)
{
String msg(reinterpret_cast<char const*>(payload));
Serial.printf("Message arrived [%s] \n", topic);
Serial.println(msg.c_str());
myLed.set(msg);
mqttPublishState();
if (String(topic) == config.getMqttTopic(Config::InTopic))
{
myLed.set(msg);
mqttPublishState();
} else if (String(topic) == config.getMqttTopic(Config::ConfigTopic))
{
setConfig(msg);
}
}
void setup()
@ -182,10 +193,6 @@ void setup()
mqttReconnect();
webOTA.setup(&WiFi);
// TEST
// myLed.set("{\"brightness\": 233, \"color\": { \"r\": 211, \"g\": 200, "
// "\"b\": 199 }, \"state\": \"OFF\"}");
}
float filter(float input)