diff --git a/.cproject b/.cproject
index 5ad54d7..236f73a 100644
--- a/.cproject
+++ b/.cproject
@@ -28,12 +28,14 @@
+
diff --git a/MqttClient.cpp b/MqttClient.cpp
index 206158f..95780c2 100644
--- a/MqttClient.cpp
+++ b/MqttClient.cpp
@@ -11,12 +11,94 @@
#include
#include
#include
+#include
+#include
+#include "cmd.h"
+#include "config.h"
-byte MQTT_BROKER[] = { 172, 16, 2, 16 };
+char MQTT_BROKER_DEFAULT[] = "192.168.75.1";
const uint16_t MQTT_PORT = 1883;
+
+
+String MqttConfig::exec(String params) {
+ String res = "failed";
+
+ Print *out = m_server;
+ MqttClient *mc = (MqttClient*)m_mqttClient;
+ if (params.equalsIgnoreCase("help")) {
+ *out << "help ..... this help page" << endl;
+ *out << "show ..... shows the whole configuration" << endl;
+ *out << "broker ... set the broker's address" << endl;
+ *out << " followed by a restart, you need to" << endl;
+ *out << " about a minute" << endl;
+ *out << "add ...... add an mbus client, params: token address period" << endl;
+ *out << "del ...... delete an mbus client, params: index" << endl;
+ *out << "reset .... reset configuration" << endl;
+ *out << " followed by a restart, you need to" << endl;
+ *out << " about a minute" << endl;
+ *out << endl;
+ res = "done";
+ } else if (params.equalsIgnoreCase("show")) {
+ // show the whole configuration
+ *out << "Clients:" << endl;
+ *out << "(index, token, address, period)" << endl;
+ for (uint8_t i = 0; i < NUM_OF_DEVICES; i++) {
+ *out << i << ": " << mc->m_mbusDevTuple[i].token << ", " <<
+ mc->m_mbusDevTuple[i].address << ", " <<
+ mc->m_mbusDevTuple[i].queryPeriod << endl;
+ }
+ *out << "Broker: " << mc->m_mqttBroker << endl;
+ *out << "Watchdog resets: " << WDOG_RSTCNT << endl;
+ res = "done";
+ } else if (params.startsWith("broker ")) {
+ // set the broker's address
+ int space = params.indexOf(' ');
+ if (space == -1) {
+ res = "missing argument";
+ } else {
+ String broker = params.substring(space+1);
+ strcpy(mc->m_mqttBroker, broker.c_str());
+ configWrite(CONFIG_BROKER, sizeof(mc->m_mqttBroker), (char*)mc->m_mqttBroker);
+ *out << "Stopping gateway, wait for reset" << endl;
+ while (true);
+ res = "done";
+ }
+ } else if (params.startsWith("add ")) {
+ // add an mbus client, params: token address period
+
+ configWrite(CONFIG_DEVICES, sizeof(mc->m_mbusDevTuple), (char*)mc->m_mbusDevTuple);
+ res = "done";
+ } else if (params.startsWith("del ")) {
+ // delete an mbus client, params: index
+ int space = params.indexOf(' ');
+ if (space == -1) {
+ res = "missing argument";
+ } else {
+ String arg0 = params.substring(space);
+ int idx = atoi(arg0.c_str());
+ if (idx < 0 || idx >= NUM_OF_DEVICES) {
+ res = "illegal index";
+ } else {
+ *out << "Index " << arg0 << " (" << idx << ") to be deleted" << endl;
+ mc->m_mbusDevTuple[idx] = {0, 0, 0, 0};
+ configWrite(CONFIG_DEVICES, sizeof(mc->m_mbusDevTuple), (char*)mc->m_mbusDevTuple);
+ res = "done";
+ }
+ }
+ } else if (params.equalsIgnoreCase("reset")) {
+ configReset();
+ *out << "Stopping gateway, wait for reset" << endl;
+ while (true);
+ res = "done";
+ }
+ return res;
+}
+
+
+
void callback(char* topic, byte* payload, unsigned int length) {
}
@@ -24,16 +106,10 @@ void callback(char* topic, byte* payload, unsigned int length) {
Metro secondTick = Metro(1000);
-MqttClient::MqttClient(RequestSender *meterBusMaster) :
- m_client(), m_meterBusMaster(meterBusMaster), m_mqttClient(MQTT_BROKER, MQTT_PORT, callback, m_client),
+MqttClient::MqttClient(RequestSender *meterBusMaster) : m_mqttConfig(this),
+ m_client(), m_meterBusMaster(meterBusMaster), m_mqttClient(m_client),
m_disconnectState(3), m_disconnectTime(millis()), m_uptime(0), m_deviceIdx(0)
{
- for (uint8_t i = 0; i < NUM_OF_DEVICES; i++) {
- m_mbusDevTuple[i] = { 0, 0, 0, 0 };
- }
-
- m_mbusDevTuple[0] = { 1, 0x53, 10, 0 }; // light meter
- m_mbusDevTuple[1] = { 2, 32, 10, 0 }; // electrity
}
void MqttClient::sendResponse(uint8_t *responseBuffer, uint16_t responseBufferLength, uint8_t token) {
@@ -67,7 +143,7 @@ void MqttClient::sendResponse(uint8_t *responseBuffer, uint16_t responseBufferLe
if (m_disconnectState == 0) {
//Serial << "publishing " << strbuf << endl;
//Serial << "length: " << buf.length() << endl;
- m_mqttClient.publish("MeterbusHub/Measurement", strbuf);
+ m_mqttClient.publish("IoT/MeterbusHub/Measurement", strbuf);
} else {
Serial << "no MQTT connection, message lost: " << endl <<
strbuf << endl;
@@ -80,13 +156,34 @@ void MqttClient::sendError(uint8_t code, uint8_t token) {
if (m_disconnectState == 0) {
//Serial << "publishing " << msg << endl;
//Serial << "length: " << msg.length() << endl;
- m_mqttClient.publish("MeterbusHub/Measurement", (char*)msg.c_str());
+ m_mqttClient.publish("IoT/MeterbusHub/Measurement", (char*)msg.c_str());
} else {
Serial << "no MQTT connection, message lost: " << msg << endl;
}
}
-void MqttClient::begin() {
+void MqttClient::begin(CmdServer *cmdServer) {
+ m_mqttConfig.registerYourself(cmdServer);
+
+ if (! configIsValid()) {
+ for (uint8_t i = 0; i < NUM_OF_DEVICES; i++) {
+ m_mbusDevTuple[i] = { 0, 0, 0, 0 };
+ }
+ m_mbusDevTuple[0] = { 1, 0x53, 10, 0 }; // light meter
+ m_mbusDevTuple[1] = { 2, 32, 10, 0 }; // electrity
+ configWrite(CONFIG_DEVICES, sizeof(m_mbusDevTuple), (char*)m_mbusDevTuple);
+
+ strcpy(m_mqttBroker, MQTT_BROKER_DEFAULT);
+ configWrite(CONFIG_BROKER, sizeof(m_mqttBroker), (char*)m_mqttBroker);
+ }
+
+
+ configRead(CONFIG_DEVICES, sizeof(m_mbusDevTuple), (char*)m_mbusDevTuple);
+ configRead(CONFIG_BROKER, sizeof(m_mqttBroker), (char*)m_mqttBroker);
+
+
+
+ m_mqttClient = PubSubClient(m_mqttBroker, MQTT_PORT, callback, m_client);
}
void MqttClient::exec() {
@@ -133,9 +230,10 @@ void MqttClient::exec() {
m_uptime++;
//Serial << "Tick " << m_uptime << endl;
- String msg = String("{ \"metadata\": { \"device\": \"MeterbusHub\" }, \"data\": { \"uptime\": ") + m_uptime + String("}}");
+ byte wdogCnt = WDOG_RSTCNT;
+ String msg = String("{ \"metadata\": { \"device\": \"MeterbusHub\" }, \"data\": { \"uptime\": ") + m_uptime + String(", \"watchdogCnt\": ") + wdogCnt + String("}}");
if (m_disconnectState == 0) {
- m_mqttClient.publish("MeterbusHub/Heartbeat", (char*)msg.c_str());
+ m_mqttClient.publish("IoT/MeterbusHub/Heartbeat", (char*)msg.c_str());
} else {
Serial << "no MQTT connection, message lost: " << msg << endl;
}
diff --git a/MqttClient.h b/MqttClient.h
index bf5053f..f2b8029 100644
--- a/MqttClient.h
+++ b/MqttClient.h
@@ -12,6 +12,7 @@
#include
#include "mBusDialog.h"
#include
+#include "cmd.h"
#define NUM_OF_DEVICES 10
@@ -23,14 +24,31 @@ typedef struct {
uint16_t timer;
} mbusDevTuple_t;
+
+class MqttClient;
+
+class MqttConfig : public Cmd {
+public:
+ MqttConfig(MqttClient *mqttClient) : m_mqttClient(mqttClient) {};
+ virtual String getCmdName() { return "MQ"; }
+ virtual String getHelp() { return "MQTT Client Config"; }
+ virtual String exec(String params);
+private:
+ MqttClient *m_mqttClient;
+};
+
+
class MqttClient : public ResponseCallback {
public:
MqttClient(RequestSender *meterBusMaster);
- void begin();
+ void begin(CmdServer *cmdServer);
void exec();
virtual void sendResponse(uint8_t *responseBuffer, uint16_t responseBufferLength, uint8_t token);
virtual void sendError(uint8_t code, uint8_t token);
+ friend class MqttConfig;
private:
+ MqttConfig m_mqttConfig;
+ char m_mqttBroker[64];
EthernetClient m_client;
RequestSender *m_meterBusMaster;
PubSubClient m_mqttClient;
diff --git a/NetMeterBusMaster2.cpp b/NetMeterBusMaster2.cpp
index cfb5ae1..0699d25 100644
--- a/NetMeterBusMaster2.cpp
+++ b/NetMeterBusMaster2.cpp
@@ -12,6 +12,8 @@
#include
#include "MqttClient.h"
#include
+#include
+#include "config.h"
const uint8_t POWER_LED = 4;
@@ -29,15 +31,37 @@ static MqttClient mqttClient(&meterBusMaster);
// static MeterBusServer meterBusServer(2001, &meterBusMaster);
static OverCurrentProt overCurrentProt;
+Metro wdogTick = Metro(1000);
+Metro dhcpTick = Metro(5* 60 * 1000);
+
+extern "C" {
+ void startup_early_hook( ) __attribute__ ((weak));
+ void startup_early_hook() {
+ // enable watchdog
+ WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
+ WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
+
+ // one minute
+ WDOG_TOVALL = 0xea60;
+ WDOG_TOVALH = 0;
+ WDOG_PRESC = 0;
+
+ WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN | WDOG_STCTRLH_ALLOWUPDATE | WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_WAITEN;
+ }
+} // extern "C"
void setup() {
+ pinMode(POWER_LED, OUTPUT);
+ digitalWrite(POWER_LED, HIGH);
+
Serial.begin(115200);
delay(100);
Serial.println("Starting up ...");
- pinMode(POWER_LED, OUTPUT);
digitalWrite(POWER_LED, LOW);
+ configInit();
+
pinMode(ETHERNET_RESET, OUTPUT);
digitalWrite(ETHERNET_RESET, LOW);
delay(100);
@@ -53,12 +77,33 @@ void setup() {
overCurrentProt.begin(&cmdServer);
meterBusMaster.begin(&cmdServer);
// meterBusServer.begin();
- mqttClient.begin();
+ mqttClient.begin(&cmdServer);
digitalWrite(POWER_LED, HIGH);
+
}
void loop() {
+ // watchdog refresh
+ cli();
+ WDOG_REFRESH = 0xa602;
+ WDOG_REFRESH = 0xb480;
+ sei();
+
+
+ if (wdogTick.check() == 1) {
+ uint16_t h = WDOG_TMROUTH;
+ uint16_t l = WDOG_TMROUTL;
+ uint16_t c = WDOG_RSTCNT;
+
+ Serial << "WDog, h: " << _HEX(h) << ", l: " << _HEX(l) << ", c: " << _HEX(c) << endl;
+ }
+
+ if (dhcpTick.check() == 1) {
+ byte r = Ethernet.maintain();
+ Serial << "Ethernet.maintain: " << r << endl;
+ }
+
//Serial << "*** 1" << endl;
cmdServer.exec();
//Serial << "*** 2" << endl;
diff --git a/config.cpp b/config.cpp
new file mode 100644
index 0000000..c136775
--- /dev/null
+++ b/config.cpp
@@ -0,0 +1,50 @@
+/*
+ * config.cpp
+ *
+ * Created on: 11.05.2015
+ * Author: wn
+ */
+
+#include
+#include
+#include "config.h"
+
+static bool __configIsValid = false;
+
+void configInit() {
+ uint32_t magic;
+ configRead(CONFIG_MAGIC, 4, (char*)&magic);
+ __configIsValid = (magic != 0xdeadbeef);
+
+ if (! __configIsValid) {
+ Serial << "Initialize config" << endl;
+ uint32_t setMagic = 0xdeadbeef;
+ configWrite(CONFIG_MAGIC, 4, (char*)&setMagic);
+ } else {
+ Serial << "Config valid" << endl;
+ }
+}
+
+bool configIsValid() {
+ return __configIsValid;
+}
+
+void configReset() {
+ Serial << "Reset config" << endl;
+ uint32_t setMagic = 0xa5a5a5a5;
+ configWrite(CONFIG_MAGIC, 4, (char*)&setMagic);
+}
+
+void configRead(int addr, uint8_t len, char *buffer) {
+ for (uint8_t i = 0; i < len; i++) {
+ *(buffer + i) = EEPROM.read(addr + i);
+ //Serial << "Read " << *(buffer + i) << " from " << addr + i << endl;
+ }
+}
+
+void configWrite(int addr, uint8_t len, char *buffer) {
+ for (uint8_t i = 0; i < len; i++) {
+ //Serial << "Write " << _HEX(*(buffer + i)) << " to " << addr + i << endl;
+ EEPROM.write(addr + i, *(buffer + i));
+ }
+}
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..744f90a
--- /dev/null
+++ b/config.h
@@ -0,0 +1,24 @@
+/*
+ * config.h
+ *
+ * Created on: 11.05.2015
+ * Author: wn
+ */
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+
+void configInit();
+bool configIsValid();
+void configReset();
+
+void configRead(int addr, uint8_t len, char *buffer);
+void configWrite(int addr, uint8_t len, char *buffer);
+
+#define CONFIG_MAGIC 0 // 4
+#define CONFIG_DEVICES 4 // 64
+#define CONFIG_BROKER 68 // 64
+#define CONFIG_NEXT 132
+
+#endif /* CONFIG_H_ */