Skip to content

Commit 8754ea5

Browse files
committed
Minor update
1 parent 5538615 commit 8754ea5

File tree

6 files changed

+81
-57
lines changed

6 files changed

+81
-57
lines changed

html/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ <h1>Device Info - {device_id}</h1>
5454
<div class="col-md-4">
5555
<div class="panel panel-info">
5656
<div class="panel-heading"><strong>{name}</strong></div>
57-
<div class="panel-body" data-ajaxurl="{name}" style="font-size: 24px;">
57+
<div class="panel-body" data-ajaxurl="{path}" style="font-size: 24px;">
5858
{value}
5959
</div>
6060
</div>

src/ConfigEntry.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class ConfigEntry : public MqttEntry {
88
public:
9-
ConfigEntry(PubSubClient& mqttClient, MqttEntry& parent) : MqttEntry("config", mqttClient, parent) {
9+
ConfigEntry(PubSubClient& mqttClient, MqttEntry& parent) : MqttEntry("config", mqttClient, parent, true) {
1010
SPIFFS.begin();
1111
load();
1212
setPublishFunction([this](MqttEntry* entry, String message){
@@ -15,25 +15,19 @@ class ConfigEntry : public MqttEntry {
1515
}
1616

1717
String getString(String key, String defaultValue) {
18-
key.replace(".", "/");
1918
String value = get(key).getValue();
20-
if(value == "") {
19+
if(value == NULL) {
2120
return defaultValue;
2221
} else {
2322
return value;
2423
}
2524
}
2625

27-
const char* getCString(String key, String defaultValue) {
28-
return getString(key, defaultValue).c_str();
29-
}
30-
3126
int getInt(String key, int defaultValue) {
3227
return getString(key, String(defaultValue)).toInt();
3328
}
3429

3530
void set(String key, String value) {
36-
key.replace(".", "/");
3731
get(key).setValue(value);
3832
}
3933

@@ -45,7 +39,6 @@ class ConfigEntry : public MqttEntry {
4539
String getKey(MqttEntry* entry) {
4640
String key = entry->getTopic();
4741
key.replace(getTopic() + "/", "");
48-
key.replace("/", ".");
4942
return key;
5043
}
5144

src/EasyMqtt.h

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ class EasyMqtt : public MqttEntry {
1616
ConfigEntry* configEntry;
1717

1818
String deviceId = "deviceId";
19+
long mqttDelay = 0;
1920

2021
protected:
2122
/**
2223
Handle connections to mqtt
2324
*/
24-
void connect() {
25+
void connectWiFi() {
2526
if(WiFi.status() == WL_DISCONNECTED) {
2627
debug("Connecting to wifi: " + config().getString("wifi.ssid", ""));
2728
WiFi.mode(WIFI_STA);
@@ -33,10 +34,9 @@ class EasyMqtt : public MqttEntry {
3334

3435
int timer = 0;
3536
while ((WiFi.status() == WL_DISCONNECTED) && timer < 50) {
36-
Serial.println(WiFi.status());
37+
debug("Wifi Status", String(WiFi.status()));
3738
delay(500);
3839
timer++;
39-
// ToDo: handle timeout, and create AP
4040
}
4141
if(timer < 50 && WiFi.status() == WL_CONNECTED) {
4242
debug("WiFi connected");
@@ -50,7 +50,10 @@ class EasyMqtt : public MqttEntry {
5050
debug("devideId", deviceId);
5151
webPortal.setup(*this);
5252
}
53-
if(mqttClient.state() == MQTT_DISCONNECTED) {
53+
}
54+
55+
void connectMqtt() {
56+
if (!mqttClient.connected() && mqttDelay < millis()) {
5457
debug("Configure MQTT");
5558
mqttClient.setClient(wifiClient);
5659
mqttClient.setCallback([&](const char* topic, uint8_t* payload, unsigned int length) {
@@ -59,8 +62,7 @@ class EasyMqtt : public MqttEntry {
5962
});
6063
});
6164
mqttClient.setServer(config().getString("mqtt.host", "").c_str(), config().getInt("mqtt.port", 1883));
62-
}
63-
if (!mqttClient.connected()) {
65+
6466
debug("Connecting to MQTT");
6567
if (mqttClient.connect(deviceId.c_str(), config().getString("mqtt.username", "").c_str(), config().getString("mqtt.password", "").c_str())) {
6668
debug("Connected to MQTT");
@@ -70,18 +72,34 @@ class EasyMqtt : public MqttEntry {
7072
});
7173

7274
debug("Topic", getTopic());
75+
7376
each([&](MqttEntry* entry){
7477
if (entry->isOut()) {
7578
mqttClient.subscribe(entry->getTopic().c_str());
7679
}
7780
});
81+
mqttDelay = 0;
7882
} else {
7983
debug("Connection to MQTT failed, rc", String(mqttClient.state()));
80-
delay(500);
84+
85+
mqttDelay = millis() + 1000;
8186
}
8287
}
8388
}
8489

90+
void debug(String msg) {
91+
#ifdef DEBUG
92+
Serial.println(msg);
93+
#endif
94+
if(mqttClient.connected()) {
95+
get("system/debug").publish(msg);
96+
}
97+
}
98+
99+
void debug(String key, String value) {
100+
debug(key + " = " + value);
101+
}
102+
85103
public:
86104
EasyMqtt() : MqttEntry("easyMqtt", mqttClient) {
87105
deviceId = String(ESP.getChipId());
@@ -129,19 +147,6 @@ class EasyMqtt : public MqttEntry {
129147
return *configEntry;
130148
}
131149

132-
void debug(String msg) {
133-
#ifdef DEBUG
134-
Serial.println(msg);
135-
#endif
136-
if(mqttClient.connected()) {
137-
get("system")["debug"].publish(msg);
138-
}
139-
}
140-
141-
void debug(String key, String value) {
142-
debug(key + " = " + value);
143-
}
144-
145150
String getDeviceId() {
146151
return deviceId;
147152
}
@@ -151,15 +156,17 @@ class EasyMqtt : public MqttEntry {
151156
}
152157

153158
/**
154-
Setup connection to wifi
159+
Configure wifi
160+
Deprecated
155161
*/
156162
void wifi(const char* ssid, const char* password) {
157163
config().set("wifi.ssid", ssid);
158164
config().set("wifi.password", password);
159165
}
160166

161167
/**
162-
Setup connection to mqtt
168+
Configure mqtt
169+
Deprecated
163170
*/
164171
void mqtt(const char* host, int port, const char* username, const char* password) {
165172
config().set("mqtt.host", host);
@@ -172,7 +179,8 @@ class EasyMqtt : public MqttEntry {
172179
Handle the normal loop
173180
*/
174181
void loop() {
175-
connect();
182+
connectWiFi();
183+
connectMqtt();
176184
mqttClient.loop();
177185
webPortal.loop();
178186
each([](MqttEntry* entry){

src/MqttEntry.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class MqttEntry {
1515
int force = 0;
1616
int interval = -1;
1717
int forceUpdate = -1;
18-
unsigned long lastUpdate = 0; // Last read of data
18+
bool internal = false;
19+
unsigned long lastUpdate = 0;
1920
String lastValue = "";
2021

2122
PubSubClient* client = NULL;
@@ -37,6 +38,13 @@ class MqttEntry {
3738
}
3839

3940
protected:
41+
MqttEntry(const char* name, PubSubClient& mqttClient, MqttEntry& parent, bool internal) {
42+
setParent(parent);
43+
client = &mqttClient;
44+
setName(name);
45+
MqttEntry::internal = internal;
46+
}
47+
4048
MqttEntry(const char* name, PubSubClient& mqttClient, MqttEntry& parent) {
4149
setParent(parent);
4250
client = &mqttClient;
@@ -65,7 +73,7 @@ class MqttEntry {
6573
void setPublishFunction(std::function<void(MqttEntry*, String)> function) {
6674
publishFunction = function;
6775
}
68-
76+
6977
public:
7078
void callback(const char* topic, uint8_t* payload, unsigned int length) {
7179
if (strcmp(getTopic().c_str(), topic) == 0) {
@@ -117,6 +125,14 @@ class MqttEntry {
117125
return parent == NULL;
118126
}
119127

128+
bool isInternal() {
129+
if (parent) {
130+
return parent->isInternal() || internal;
131+
} else {
132+
return internal;
133+
}
134+
}
135+
120136
virtual String getTopic() {
121137
if (parent) {
122138
return parent->getTopic() + "/" + name;
@@ -155,6 +171,7 @@ class MqttEntry {
155171
}
156172

157173
void setValue(String value) {
174+
lastUpdate = millis();
158175
lastValue = value;
159176
publish(value);
160177
}
@@ -192,6 +209,7 @@ class MqttEntry {
192209
* Create or get the sub topic with the name {name}
193210
*/
194211
MqttEntry & get(String name) {
212+
name.replace('.', '/');
195213
int pos = name.indexOf('/');
196214
if(pos < 0) {
197215
return operator[](name.c_str());

src/WebPortal.h

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class WebPortal {
1717
return path;
1818
}
1919

20+
String getRestPath(MqttEntry* entry) {
21+
return "/rest" + getName(entry);
22+
}
23+
2024
public:
2125
WebPortal() {
2226
}
@@ -31,7 +35,7 @@ class WebPortal {
3135
webServer->on("/save", std::bind(&WebPortal::handleSaveConfig, this));
3236
mqtt->each([&](MqttEntry* entry) {
3337
if(entry->isIn() || entry->isOut()) {
34-
webServer->on(getName(entry).c_str(), std::bind(&WebPortal::handleRest, this));
38+
webServer->on(getRestPath(entry).c_str(), std::bind(&WebPortal::handleRest, this));
3539
}
3640
});
3741
webServer->onNotFound(std::bind(&WebPortal::handleNotFound, this));
@@ -43,30 +47,32 @@ class WebPortal {
4347
page += FPSTR(HTML_MAIN1);
4448
// Sensors
4549
mqtt->each([&](MqttEntry* entry) {
46-
if(entry->isIn()) {
47-
50+
if(!entry->isInternal()) {
4851
String value = entry->getValue();
49-
value.toLowerCase();
50-
if(value == "on" || value == "open" || value == "true") {
51-
value = FPSTR(HTML_VALUE_ON);
52-
} else if (value == "off" || value == "closed" || value == "false") {
53-
value = FPSTR(HTML_VALUE_OFF);
54-
} else {
55-
value = entry->getValue();
52+
if(value != NULL) {
53+
value.toLowerCase();
54+
if(value == "on" || value == "open" || value == "true") {
55+
value = FPSTR(HTML_VALUE_ON);
56+
} else if (value == "off" || value == "closed" || value == "false") {
57+
value = FPSTR(HTML_VALUE_OFF);
58+
} else {
59+
value = "{value}";
60+
}
61+
value.replace("{value}", entry->getValue());
62+
63+
page += FPSTR(HTML_SENSOR);
64+
page.replace("{name}", getName(entry));
65+
page.replace("{path}", getRestPath(entry));
66+
page.replace("{value}", value);
67+
page.replace("{last_updated}", String(entry->getLastUpdate() / 1000));
5668
}
57-
value.replace("{value}", entry->getValue());
58-
59-
page += FPSTR(HTML_SENSOR);
60-
page.replace("{name}", getName(entry));
61-
page.replace("{value}", value);
62-
page.replace("{last_updated}", String(entry->getLastUpdate() / 1000));
6369
}
6470
});
6571

6672
page += FPSTR(HTML_MAIN2);
6773
// Inputs
6874
mqtt->each([&](MqttEntry* entry) {
69-
if(entry->isOut()) {
75+
if(entry->isOut() && !entry->isInternal()) {
7076
page += FPSTR(HTML_INPUT);
7177
page.replace("{name}", getName(entry));
7278
}
@@ -77,8 +83,7 @@ class WebPortal {
7783
mqtt->get("config").each([&](MqttEntry* entry) {
7884
page += FPSTR(HTML_CONFIG_ENTRY);
7985
String name = getName(entry);
80-
name = name.substring(7);
81-
name.replace("/", ".");
86+
name = name.substring(8);
8287
if(name.endsWith("password")) {
8388
page.replace("{type}", "password");
8489
} else {
@@ -125,7 +130,7 @@ class WebPortal {
125130
}
126131

127132
void handleRest() {
128-
MqttEntry* entry = &mqtt->get(webServer->uri().substring(1));
133+
MqttEntry* entry = &mqtt->get(webServer->uri().substring(5));
129134
if(webServer->method() == HTTP_GET && entry->isIn()) {
130135
webServer->send(200, "text/plain", entry->getValue());
131136
} else if(webServer->method() == HTTP_POST && entry->isOut()) {

src/html.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
#define html_h
33

44
const char HTML_MAIN1[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Device Info - {device_id}</title><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css\" integrity=\"sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp\" crossorigin=\"anonymous\"></head><body><script type=\"application/javascript\">function sendValue(input) {$.ajax({url: input.dataset.url, method: \"POST\", data: $(input).closest(\"form\").find(\"input\").val()}).complete(function (data, textStatus, jqXHR) {alert(textStatus);});}setInterval(function() {$(\"[data-ajaxurl]\").each(function(index) {var ele = $(this);$.ajax(ele.data(\"ajaxurl\")).complete(function (data, textStatus, jqXHR) {ele.html(data);});});}, 1000);</script><div class=\"container\"><h1>Device Info - {device_id}</h1><ul class=\"nav nav-tabs\" role=\"tablist\"><li role=\"presentation\" class=\"active\"><a href=\"#devices\" aria-controls=\"devices\" role=\"tab\" data-toggle=\"tab\"><span class=\"glyphicon glyphicon-dashboard\" aria-hidden=\"true\"></span> Devices</a></li><li role=\"presentation\"><a href=\"#input\" aria-controls=\"input\" role=\"tab\" data-toggle=\"tab\"><span class=\"glyphicon glyphicon-pencil\" aria-hidden=\"true\"></span> Input</a></li><li role=\"presentation\"><a href=\"#config\" aria-controls=\"config\" role=\"tab\" data-toggle=\"tab\"><span class=\"glyphicon glyphicon-cog\" aria-hidden=\"true\"></span> Config</a></li><li role=\"presentation\"><a href=\"#about\" aria-controls=\"about\" role=\"tab\" data-toggle=\"tab\"><span class=\"glyphicon glyphicon-book\" aria-hidden=\"true\"></span> About</a></li></ul><div class=\"tab-content\" style=\"border-style: solid; border-color: #ddd; border-width: 0px 1px 1px 1px\"><div role=\"tabpanel\" class=\"tab-pane active\" id=\"devices\"><br /><div class=\"container-fluid\"><div class=\"row\">";
5-
const char HTML_SENSOR[] PROGMEM = "<div class=\"col-md-4\"><div class=\"panel panel-info\"><div class=\"panel-heading\"><strong>{name}</strong></div><div class=\"panel-body\" data-ajaxurl=\"{name}\" style=\"font-size: 24px;\">{value}</div></div></div>";
5+
const char HTML_SENSOR[] PROGMEM = "<div class=\"col-md-4\"><div class=\"panel panel-info\"><div class=\"panel-heading\"><strong>{name}</strong></div><div class=\"panel-body\" data-ajaxurl=\"{path}\" style=\"font-size: 24px;\">{value}</div></div></div>";
66
const char HTML_VALUE_ON[] PROGMEM = "<span class=\"label label-success\">{value}</span>";
77
const char HTML_VALUE_OFF[] PROGMEM = "<span class=\"label label-danger\">{value}</span>";
88
const char HTML_MAIN2[] PROGMEM = "</div></div></div><div role=\"tabpanel\" class=\"tab-pane\" id=\"input\"><br /><div class=\"container-fluid\"><div class=\"row\">";
99
const char HTML_INPUT[] PROGMEM = "<div class=\"col-md-4\"><div class=\"panel panel-success\"><div class=\"panel-heading\"><strong>{name}</strong></div><div class=\"panel-body\" style=\"font-size: 24px;\"><form><div class=\"input-group\"><input type=\"text\" class=\"form-control\" placeholder=\"value\"><span class=\"input-group-btn\"><button class=\"btn btn-default\" type=\"button\" data-url=\"{name}\" onclick=\"sendValue(this);\">Send</button></span></div></form></div></div></div>";
1010
const char HTML_MAIN3[] PROGMEM = "</div></div></div><div role=\"tabpanel\" class=\"tab-pane\" id=\"config\"><div class=\"container-fluid\"><div class=\"row\"><div class=\"col-md-12\"><form class=\"form-horizontal\" action=\"/save\" method=\"POST\">";
1111
const char HTML_CONFIG_HEADER[] PROGMEM = "<br /><h3>{title}</h3><hr/>";
1212
const char HTML_CONFIG_ENTRY[] PROGMEM = "<div class=\"form-group\"><label for=\"{key}\" class=\"col-sm-2 control-label\">{key}</label><div class=\"col-sm-8\"><input type=\"{type}\" class=\"form-control\" id=\"{key}\" placeholder=\"\" value=\"{value}\"></div></div>";
13-
const char HTML_MAIN4[] PROGMEM = "<hr/><div class=\"form-group\"><div class=\"col-sm-offset-9 col-sm-2\"><button type=\"submit\" class=\"btn btn-default\">Save</button></div></div></form></div></div></div></div><div role=\"tabpanel\" class=\"tab-pane\" id=\"about\"><br /><div class=\"container-fluid\"><div class=\"row\"><div class=\"col-md-12\"><h1>About</h1><p>Device is using EasyMqtt version 0.0.1</p>Device Id: {device_id}<br />Topic: {topic}<br /><hr /><h3>MQTT API:</h3><ul class=\"list-group\">";
13+
const char HTML_MAIN4[] PROGMEM = "<hr/><div class=\"form-group\"><div class=\"col-sm-offset-9 col-sm-2\"><button type=\"submit\" class=\"btn btn-default\">Save</button></div></div></form></div></div></div></div><div role=\"tabpanel\" class=\"tab-pane\" id=\"about\"><br /><div class=\"container-fluid\"><div class=\"row\"><div class=\"col-md-12\"><h1>About</h1><p>Device is using EasyMqtt version 0.0.1</p><dl class=\"dl-horizontal\"><dt>Device Id</dt><dd>{device_id}</dd><dt>Topic</dt><dd>{topic}</dd></dl><hr /><h3>MQTT API:</h3><ul class=\"list-group\">";
1414
const char HTML_MAIN5[] PROGMEM = "</ul><hr /><h3>Rest API:</h3><ul class=\"list-group\">";
1515
const char HTML_API_DOC[] PROGMEM = "<li class=\"list-group-item\">{path}</li>";
1616
const char HTML_MAIN6[] PROGMEM = "</ul></div></div></div></div></div></div><script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\"></script><script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\" integrity=\"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa\" crossorigin=\"anonymous\"></script></body></html>";

0 commit comments

Comments
 (0)