268 lines
6.6 KiB
C++
268 lines
6.6 KiB
C++
#include "RelayBox.h"
|
|
#include "hardware.h"
|
|
#include <avr/wdt.h>
|
|
#include <SPI.h>
|
|
#include <Ethernet.h>
|
|
#include <Metro.h>
|
|
#include <Streaming.h>
|
|
#include <PubSubClient.h>
|
|
#include <PString.h>
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x07 };
|
|
|
|
EthernetClient ethClient;
|
|
|
|
void callback(char* topic, byte* payload, unsigned int length);
|
|
|
|
char server[] = "mqttbroker";
|
|
// char server[] = "192.168.75.1";
|
|
PubSubClient client(server, 1883, callback, ethClient);
|
|
uint8_t disconnectState = 0;
|
|
uint32_t disconnectTime = 0;
|
|
|
|
|
|
Metro minute = Metro(60000);
|
|
Metro second = Metro(1000);
|
|
uint32_t uptime;
|
|
|
|
|
|
|
|
|
|
Switch switches[NUM_OF_LINES];
|
|
|
|
|
|
void callback(char* topic, byte* payload, unsigned int length) {
|
|
const uint8_t BUFSIZE = 128;
|
|
if ((length + 1) >= BUFSIZE) { // 1 for terminating NUL
|
|
Serial << "Received message too long, ignore it" << endl;
|
|
} else {
|
|
char buffer[BUFSIZE];
|
|
memcpy(buffer, payload, length);
|
|
*(buffer + length) = 0;
|
|
Serial << "Received message: " << length << ", " << String(topic) << ", " << String(buffer) << endl;
|
|
|
|
char *paramPtr = buffer;
|
|
char *commandStr = 0;
|
|
char *indexStr = 0;
|
|
char *stateStr = 0;
|
|
if ((paramPtr != 0) && (*paramPtr != 0)){
|
|
// command
|
|
commandStr = strsep(¶mPtr, " ");
|
|
}
|
|
if ((paramPtr != 0) && (*paramPtr != 0)){
|
|
indexStr = strsep(¶mPtr, " ");
|
|
}
|
|
if ((paramPtr != 0) && (*paramPtr != 0)){
|
|
stateStr = strsep(¶mPtr, " ");
|
|
}
|
|
|
|
if ((commandStr != 0) && (*commandStr != 0) &&
|
|
(indexStr != 0) && (*indexStr != 0) &&
|
|
(stateStr != 0) && (*stateStr != 0)) {
|
|
String command = String(commandStr);
|
|
int index = 99;
|
|
if (! strcmp(indexStr, "all")) {
|
|
index = -1;
|
|
} else {
|
|
index = atoi(indexStr);
|
|
}
|
|
String state = String(stateStr);
|
|
bool validCommand = command.equals("switch");
|
|
bool validIndex = (! ((index < 0) || (index >= NUM_OF_LINES))) || (index == -1);
|
|
|
|
if (validCommand && validIndex) {
|
|
if (state.equalsIgnoreCase("on")) {
|
|
if (index == -1) {
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
switches[i].on();
|
|
}
|
|
} else {
|
|
switches[index].on();
|
|
}
|
|
} else if (state.equalsIgnoreCase("off")) {
|
|
if (index == -1) {
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
switches[i].off();
|
|
}
|
|
} else {
|
|
switches[index].off();
|
|
}
|
|
} else if (state.equalsIgnoreCase("toggle")) {
|
|
if (index == -1) {
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
switches[i].toggle();
|
|
}
|
|
} else {
|
|
switches[index].toggle();
|
|
}
|
|
} else {
|
|
Serial << "Invalid state " << state << endl;
|
|
}
|
|
} else {
|
|
if (! validCommand) {
|
|
Serial << "Invalid command " << commandStr << endl;
|
|
}
|
|
if (! validIndex) {
|
|
Serial << "Invalid index " << indexStr << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
// delay(5000);
|
|
Serial << "Starting ... " << endl;
|
|
|
|
configInit();
|
|
|
|
Ethernet.begin(mac);
|
|
Serial << "Got IP address: " << Ethernet.localIP() << endl;
|
|
|
|
disconnectState = 3;
|
|
disconnectTime = millis();
|
|
|
|
uptime = 0;
|
|
|
|
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
switches[i].begin(FEEDBACK_PIN[i], BUTTON_PIN[i], RELAY_PIN[i], LED_PIN[i], i);
|
|
}
|
|
|
|
wdt_enable(WDTO_8S);
|
|
}
|
|
|
|
void loop() {
|
|
wdt_reset();
|
|
|
|
#ifndef TEST_MODE
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
switches[i].exec();
|
|
}
|
|
|
|
if (minute.check() == 1) {
|
|
byte r = Ethernet.maintain();
|
|
Serial << "Ethernet.maintain: " << r << endl;
|
|
if ((r == DHCP_CHECK_REBIND_FAIL) || (r == DHCP_CHECK_RENEW_FAIL)) {
|
|
}
|
|
}
|
|
|
|
if ((disconnectState == 0) && (! client.loop())) {
|
|
disconnectState = 1;
|
|
}
|
|
|
|
switch (disconnectState) {
|
|
case 0:
|
|
// Serial.println("discState 0");
|
|
// everything fine
|
|
break;
|
|
case 1:
|
|
Serial.println("discState 1");
|
|
client.disconnect();
|
|
disconnectTime = millis();
|
|
disconnectState = 2;
|
|
break;
|
|
case 2:
|
|
Serial.println("discState 3");
|
|
if (disconnectTime + 2000 < millis()) {
|
|
disconnectState = 3;
|
|
}
|
|
break;
|
|
case 3:
|
|
Serial.println("discState 3");
|
|
if (client.connect("RelayBox")) {
|
|
client.subscribe("IoT/Command/RelayBox");
|
|
disconnectTime = millis();
|
|
disconnectState = 0;
|
|
} else {
|
|
disconnectState = 1;
|
|
}
|
|
break;
|
|
default:
|
|
disconnectState = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
if (second.check() == 1) {
|
|
uptime++;
|
|
|
|
// Serial.println("tick");
|
|
|
|
if (disconnectState == 0) {
|
|
String msg = String("{ \"metadata\": { \"device\": \"RelayBox\" }, \"data\": { \"uptime\": ") + uptime + String("}}");
|
|
client.publish("IoT/Heartbeat/RelayBox", (char*)msg.c_str());
|
|
|
|
char strbuf[768];
|
|
memset(strbuf, sizeof(strbuf), 0);
|
|
PString buf = PString(strbuf, sizeof(strbuf));
|
|
buf << "{ \"metadata\": { \"device\": \"RelayBox\" }, " <<
|
|
"\"data\": {" <<
|
|
"\"switchStates\": [";
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
if (i != 0) {
|
|
buf << ", ";
|
|
}
|
|
buf << "{ \"index\": " << i << ", " <<
|
|
"\"state\": " << switches[i].getState() << ", " <<
|
|
"\"feedbackState\": " << switches[i].getFeedback() << ", " <<
|
|
"\"stateConflict\": " << switches[i].getStateConflict() << " }";
|
|
if (switches[i].getStateConflict()) {
|
|
Serial << "State conflict on channel " << i << ", should be " << switches[i].getState() <<
|
|
", is " << switches[i].getFeedback() << endl;
|
|
}
|
|
}
|
|
buf << "], " <<
|
|
"\"uptime\": " << uptime <<
|
|
"}" <<
|
|
"}" << endl;
|
|
//Serial << strbuf << endl;
|
|
client.publish("IoT/Status/RelayBox", strbuf);
|
|
}
|
|
}
|
|
#else
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(RELAY_PIN[i], false);
|
|
digitalWrite(LED_PIN[i], false);
|
|
}
|
|
delay(500);
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(RELAY_PIN[i], true);
|
|
delay(100);
|
|
}
|
|
delay(500);
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(RELAY_PIN[i], false);
|
|
delay(100);
|
|
}
|
|
delay(500);
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(LED_PIN[i], true);
|
|
delay(100);
|
|
}
|
|
delay(500);
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(LED_PIN[i], false);
|
|
delay(100);
|
|
}
|
|
delay(100);
|
|
|
|
while (true) {
|
|
for (uint8_t i = 0; i < NUM_OF_LINES; i++) {
|
|
digitalWrite(LED_PIN[i], digitalRead(FEEDBACK_PIN[i]));
|
|
digitalWrite(RELAY_PIN[i], digitalRead(BUTTON_PIN[i]));
|
|
}
|
|
}
|
|
#endif
|
|
}
|