#include "RelayBox.h" #include "hardware.h" #include #include #include #include #include #include #include #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 }