From adc3f664fc7ab89106c03e3141c2af0ec80ae3af Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Wed, 30 Sep 2015 22:30:32 +0200 Subject: [PATCH] SerialGateway fixed and verified --- libraries/MySensors/MyConfig.h | 25 +- libraries/MySensors/MySensor.h | 21 +- .../MySensors/core/MyGatewayTransport.cpp | 7 + .../core/MyGatewayTransportEthernet.cpp | 234 +++++++++++------- .../core/MyGatewayTransportSerial.cpp | 17 +- libraries/MySensors/core/MyProtocol.h | 2 + .../MySensors/core/MyProtocolMySensors.cpp | 6 +- libraries/MySensors/core/MySensorCore.cpp | 1 - libraries/MySensors/core/MyTransport.cpp | 8 +- .../Esp8266Gateway/Esp8266Gateway.ino | 195 ++------------- .../examples/Esp8266Gateway/GatewayUtil.h | 136 ---------- libraries/MySensors/keywords.txt | 10 +- 12 files changed, 252 insertions(+), 410 deletions(-) delete mode 100644 libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index f4a99d8..9886789 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -44,6 +44,7 @@ #define MY_BAUD_RATE 115200 #endif + /********************************** * Radio selection and node config ***********************************/ @@ -87,6 +88,28 @@ #define MY_OTA_FLASH_JDECID 0x1F65 #endif + +/********************************** +* Gateway config +***********************************/ + +// Max buffersize needed for messages coming from controller +#ifndef MY_GATEWAY_MAX_RECEIVE_LENGTH +#define MY_GATEWAY_MAX_RECEIVE_LENGTH 100 +#endif + +// Max buffer size when sending messages +#ifndef MY_GATEWAY_MAX_SEND_LENGTH +#define MY_GATEWAY_MAX_SEND_LENGTH 120 +#endif + +// Max number of parallel clients (sever mode) +#ifndef MY_GATEWAY_MAX_CLIENTS +#define MY_GATEWAY_MAX_CLIENTS 1 +#endif + + + /********************************** * Information LEDs blinking ***********************************/ @@ -98,7 +121,7 @@ //#define MY_LEDS_BLINKING_FEATURE // The following setting allows you to inverse the blinking feature MY_LEDS_BLINKING_FEATURE -// When WITH_LEDS_BLINKING_INVERSE is enabled LEDSs are normally turned on and switches +// When MY_WITH_LEDS_BLINKING_INVERSE is enabled LEDSs are normally turned on and switches // off when blinking //#define MY_WITH_LEDS_BLINKING_INVERSE diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 98d493e..0f315d9 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -26,6 +26,7 @@ #include "MyConfig.h" #include "core/MySensorCore.h" +// Detect node type #if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) || defined(ARDUINO_ARCH_ESP8266) #define MY_GATEWAY_FEATURE #define MY_IS_GATEWAY (true) @@ -36,13 +37,18 @@ #define MY_NODE_TYPE "sensor" #endif +// Enable radio "feature" if one of the radio types was enabled +#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) + #define MY_RADIO_FEATURE +#endif // HARDWARE #if defined(ARDUINO_ARCH_ESP8266) - #include "drivers/ESP8266/SPI/SPI.cpp" + #undef PSTR + #define PSTR(x) (x) #include "drivers/ESP8266/EEPROM/EEPROM.cpp" + #include "drivers/ESP8266/SPI/SPI.cpp" #include "core/MyHwESP8266.cpp" - // For ESP8266, we always enable gateway feature #define MY_GATEWAY_ESP8266 #elif defined(ARDUINO_ARCH_AVR) @@ -118,14 +124,20 @@ // #include "drivers/ESP8266/ESP8266WiFi/src/WifiClient.cpp" // #include "drivers/ESP8266/ESP8266WiFi/src/WifiServer.cpp" // #include "drivers/ESP8266/ESP8266WiFi/src/WifiUdp.cpp" + #if !defined(USE_UDP) + + #endif + + #include "core/MyGatewayTransportEthernet.cpp" + #elif defined(MY_GATEWAY_W5100) // GATEWAY - W5100 - #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" + /*#include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" #include "drivers/AVR/Ethernet_W5100/DNS.cpp" #include "drivers/AVR/Ethernet_W5100/Ethernet.cpp" #include "drivers/AVR/Ethernet_W5100/EthernetUdp.cpp" - #include "drivers/AVR/Ethernet_W5100/IPAddress.cpp" + #include "drivers/AVR/Ethernet_W5100/IPAddress.cpp"*/ #if !defined(USE_UDP) #include "drivers/AVR/Ethernet_W5100/EthernetServer.cpp" @@ -166,7 +178,6 @@ // RADIO #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) - #define MY_RADIO_FEATURE // SOFTSPI #ifdef MY_SOFTSPI #if defined(ARDUINO_ARCH_ESP8266) diff --git a/libraries/MySensors/core/MyGatewayTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.cpp index 79ece44..abd0879 100644 --- a/libraries/MySensors/core/MyGatewayTransport.cpp +++ b/libraries/MySensors/core/MyGatewayTransport.cpp @@ -19,8 +19,11 @@ #include "MyGatewayTransport.h" +extern boolean transportSendRoute(MyMessage &message); + inline void gatewayTransportProcess() { if (gatewayTransportAvailable()) { + MyMessage &_msg = gatewayTransportReceive(); if (_msg.destination == GATEWAY_ADDRESS) { // Check if sender requests an ack back. @@ -51,6 +54,10 @@ inline void gatewayTransportProcess() { receive(_msg); } } + } else { + #if defined(MY_RADIO_FEATURE) + transportSendRoute(_msg); + #endif } } } diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index cebf6cc..2ec8123 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -17,25 +17,59 @@ * version 2 as published by the Free Software Foundation. */ -#include "MyGatewayTransportEthernet.h" +#include "MyGatewayTransport.h" -IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); -IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); +#if defined(MY_CONTROLLER_IP_ADDRESS) + IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); +#endif + +#if defined(MY_IP_ADDRESS) + IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); +#endif byte _ethernetGatewayMAC[] = { MY_MAC_ADDRESS }; uint16_t _ethernetGatewayPort = MY_PORT; -char _ethernetInputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface MyMessage _ethernetMsg; -#ifdef MY_USE_UDP - EthernetUDP _ethernetServer; +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +// gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); + +typedef struct +{ + char string[MY_GATEWAY_MAX_RECEIVE_LENGTH]; + uint8_t idx; +} inputBuffer; + +#if defined(MY_GATEWAY_ESP8266) + // Some re-defines to make code more readable below + #define EthernetServer WiFiServer + #define EthernetClient WiFiClient + + #if defined(MY_IP_ADDRESS) + IPAddress gateway(MY_IP_GATEWAY_ADDRESS); + IPAddress subnet(MY_IP_SUBNET_ADDRESS); + #endif + +#endif + + + +#if defined(MY_USE_UDP) + #if defined(MY_GATEWAY_ESP8266) + WiFiUDP _ethernetServer; + #else + EthernetUDP _ethernetServer; + #endif #else - // we have to use pointers due to the constructor of EthernetServer EthernetServer _ethernetServer(_ethernetGatewayPort); uint8_t _ethernetInputPos; #endif /* USE_UDP */ -#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller +static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS]; +static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS]; +static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS]; + #ifndef MY_IP_ADDRESS void gatewayTransportRenewIP(); @@ -43,102 +77,136 @@ MyMessage _ethernetMsg; bool gatewayTransportInit() { -#ifdef MY_IP_ADDRESS - Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); -#else - // Get IP address from DHCP - Ethernet.begin(_ethernetGatewayMAC); -#endif /* IP_ADDRESS_DHCP */ + #if defined(MY_GATEWAY_ESP8266) + (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); + #ifdef MY_IP_ADDRESS + WiFi.config(_ethernetGatewayIP, gateway, subnet); + #endif + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println(PSTR("Connected to AP!")); + Serial.print(PSTR("IP: ")); + Serial.println(WiFi.localIP()); - // give the Ethernet interface a second to initialize - // TODO: use HW delay - delay(1000); + #else + #ifdef MY_IP_ADDRESS + Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); + #else + // Get IP address from DHCP + Ethernet.begin(_ethernetGatewayMAC); + #endif /* IP_ADDRESS_DHCP */ + // give the Ethernet interface a second to initialize + // TODO: use HW delay + delay(1000); + #endif -#ifdef MY_USE_UDP - _ethernetServer.begin(_ethernetGatewayPort); -#else - // we have to use pointers due to the constructor of EthernetServer - _ethernetServer.begin(); -#endif /* USE_UDP */ + #ifdef MY_USE_UDP + _ethernetServer.begin(_ethernetGatewayPort); + #else + // we have to use pointers due to the constructor of EthernetServer + _ethernetServer.begin(); + #if defined(MY_GATEWAY_ESP8266) + _ethernetServer.setNoDelay(true); + #endif + #endif /* USE_UDP */ } bool gatewayTransportSend(MyMessage &message) { - char *_ethernetMsg = NULL; + char *_ethernetMsg = protocolFormat(message); - if (_ethernetControllerIP == INADDR_NONE) { - // no controller IP address set! - return false; - } - else { - _ethernetMsg = protocolFormat(message); -#ifdef MY_USE_UDP - _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); - _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); - // returns 1 if the packet was sent successfully - return _ethernetServer.endPacket(); -#else - EthernetClient client; - if (client.connect(_ethernetControllerIP, MY_PORT)) { - client.write(_ethernetMsg, strlen(_ethernetMsg)); - client.stop(); - return true; - } - else { - // connecting to the server failed! - return false; - } -#endif /* USE_UDP */ - } + #if defined(MY_CONTROLLER_IP_ADDRESS) + #if defined(MY_USE_UDP) + _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); + _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); + // returns 1 if the packet was sent successfully + return _ethernetServer.endPacket(); + #else + EthernetClient client; + if (client.connect(_ethernetControllerIP, MY_PORT)) { + client.write(_ethernetMsg, strlen(_ethernetMsg)); + client.stop(); + return true; + } + else { + // connecting to the server failed! + return false; + } + + #endif + #else + // Send to connected clients + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + if (clients[i] && clients[i].connected()) + { + clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg)); + } + } + // TODO: What do we return here? + return true; + #endif } bool gatewayTransportAvailable() { bool available = false; -#ifndef MY_IP_ADDRESS - // renew IP address using DHCP - gatewayTransportRenewIP(); -#endif + #if !defined(MY_IP_ADDRESS) && !defined(MY_GATEWAY_ESP8266) + // renew IP address using DHCP + gatewayTransportRenewIP(); + #endif -#ifdef MY_USE_UDP - int packet_size = _ethernetServer.parsePacket(); + #ifdef MY_USE_UDP + int packet_size = _ethernetServer.parsePacket(); - if (_ethernetServer.available()) { - _ethernetServer.read(_ethernetInputBuffer, MAX_RECEIVE_LENGTH); - available = true; - } -#else - // if an incoming client connects, there will be - // bytes available to read via the client object - EthernetClient client = _ethernetServer.available(); + if (_ethernetServer.available()) { + _ethernetServer.read(inputString[0], MY_GATEWAY_MAX_RECEIVE_LENGTH); + return protocolParse(_ethernetMsg, inputString[0]); + } + #else + // Loop over clients connect and read available data + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { + while (clients[i].connected() && clients[i].available()) { + char inChar = clients[i].read(); + if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { + // if newline then command is complete + if (inChar == '\n') { + // a command was issued by the client + // we will now try to send it to the actuator + inputString[i].string[inputString[i].idx] = 0; - if (client) { - while (client.available()) { - // read the bytes incoming from the client - char inChar = client.read(); + // echo the string to the serial port + Serial.print(PSTR("Client ")); + Serial.print(i); + Serial.print(": "); + Serial.println(inputString[i].string); - if (_ethernetInputPos < MAX_RECEIVE_LENGTH - 1) { - // if newline then command is complete - if (inChar == '\n') { - _ethernetInputBuffer[_ethernetInputPos] = 0; - available = true; + // clear the string: + inputString[i].idx = 0; + + return protocolParse(_ethernetMsg, inputString[i].string); + } else { + // add it to the inputString: + inputString[i].string[inputString[i].idx++] = inChar; + } } else { - _ethernetInputBuffer[_ethernetInputPos] = inChar; - _ethernetInputPos++; + // Incoming message too long. Throw away + Serial.print(PSTR("Client ")); + Serial.print(i); + Serial.println(PSTR(": Message too long")); + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; } } } - } - _ethernetInputPos = 0; -#endif - if (available) { - // Parse message and return parse result - available = protocolParse(_ethernetMsg, _ethernetInputBuffer); - } - - return available; + #endif + return false; } MyMessage& gatewayTransportReceive() @@ -148,7 +216,7 @@ MyMessage& gatewayTransportReceive() } -#ifndef MY_IP_ADDRES +#if !defined(MY_IP_ADDRESS) && !defined(MY_GATEWAY_ESP8266) void gatewayTransportRenewIP() { /* renew/rebind IP address diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.cpp b/libraries/MySensors/core/MyGatewayTransportSerial.cpp index ed6b5ce..b292f7b 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.cpp +++ b/libraries/MySensors/core/MyGatewayTransportSerial.cpp @@ -19,20 +19,16 @@ #include "MyConfig.h" -#include "MyProtocolMySensors.h" +#include "MyProtocol.h" #include "MyGatewayTransport.h" #include "MyMessage.h" #include "MyProtocol.h" -#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller -char _serialInputString[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface +char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface int _serialInputPos; MyMessage _serialMsg; -bool gatewayTransportInit() { - return true; -} bool gatewayTransportSend(MyMessage &message) { Serial.print(protocolFormat(message)); @@ -40,14 +36,21 @@ bool gatewayTransportSend(MyMessage &message) { return true; } +bool gatewayTransportInit() { + gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); + return true; +} + + bool gatewayTransportAvailable() { bool available = false; + while (Serial.available()) { // get the new byte: char inChar = (char) Serial.read(); // if the incoming character is a newline, set a flag // so the main loop can do something about it: - if (_serialInputPos < MAX_RECEIVE_LENGTH - 1 && !available) { + if (_serialInputPos < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1 && !available) { if (inChar == '\n') { _serialInputString[_serialInputPos] = 0; available = true; diff --git a/libraries/MySensors/core/MyProtocol.h b/libraries/MySensors/core/MyProtocol.h index c425809..324759a 100644 --- a/libraries/MySensors/core/MyProtocol.h +++ b/libraries/MySensors/core/MyProtocol.h @@ -20,8 +20,10 @@ #ifndef MyProtocol_h #define MyProtocol_h +#include "MyConfig.h" #include "MyMessage.h" + // parse(message, inputString) // parse a string into a message element // returns true if successfully parsed the input string diff --git a/libraries/MySensors/core/MyProtocolMySensors.cpp b/libraries/MySensors/core/MyProtocolMySensors.cpp index f231cd9..a74d8aa 100644 --- a/libraries/MySensors/core/MyProtocolMySensors.cpp +++ b/libraries/MySensors/core/MyProtocolMySensors.cpp @@ -21,11 +21,9 @@ #include "MyTransport.h" #include "MyProtocol.h" -#define MAX_FORMAT_BUFFER_LENGTH 120 // Max buffersize when formatting messages - uint8_t protocolH2i(char c); -char _fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; +char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH]; char _convBuffer[MAX_PAYLOAD*2+1]; bool protocolParse(MyMessage &message, char *inputString) { @@ -95,7 +93,7 @@ bool protocolParse(MyMessage &message, char *inputString) { } char * protocolFormat(MyMessage &message) { - snprintf_P(_fmtBuffer, MAX_FORMAT_BUFFER_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(_convBuffer)); + snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(_convBuffer)); return _fmtBuffer; } diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index 65e7199..bda6917 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -86,7 +86,6 @@ void _begin() { while(1); // Nothing more we can do } - gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); #endif diff --git a/libraries/MySensors/core/MyTransport.cpp b/libraries/MySensors/core/MyTransport.cpp index f9f19ec..788786b 100644 --- a/libraries/MySensors/core/MyTransport.cpp +++ b/libraries/MySensors/core/MyTransport.cpp @@ -122,7 +122,6 @@ inline void transportProcess() { uint8_t sender = _msg.sender; uint8_t last = _msg.last; uint8_t destination = _msg.destination; - if (destination == _nc.nodeId) { // This message is addressed to this node @@ -285,6 +284,10 @@ inline void transportProcess() { } #endif + #if defined(MY_GATEWAY_FEATURE) + // Hand over message to controller + gatewayTransportSend(_msg); + #endif // Call incoming message callback if available if (receive) { receive(_msg); @@ -356,6 +359,7 @@ boolean transportSendRoute(MyMessage &message) { uint8_t last = message.last; bool ok; + // If we still don't have any parent id, re-request and skip this message. if (_nc.parentNodeId == AUTO) { transportFindParentNode(); @@ -412,7 +416,6 @@ boolean transportSendRoute(MyMessage &message) { } #endif - #if !defined(MY_REPEATER_FEATURE) // None repeating node... We can only send to our parent ok = transportSendWrite(_nc.parentNodeId, message); @@ -448,6 +451,7 @@ boolean transportSendRoute(MyMessage &message) { #if defined (MY_GATEWAY_FEATURE) // Destination isn't in our routing table and isn't a broadcast address // Nothing to do here + debug(PSTR("Destination %d unknown\n"), dest); return false; # else // A message comes from a child node and we have no diff --git a/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino index 41a28f4..d7b5510 100644 --- a/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino +++ b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino @@ -64,8 +64,8 @@ * * Make sure to fill in your ssid and WiFi password below for ssid & pass. */ + #include -#include // Enable debug prints to serial monitor #define MY_DEBUG @@ -74,26 +74,27 @@ #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -// Gateway always enabled for ESP8266 by default -//#define MY_GATEWAY_ESP8266 +// Gateway mode always enabled for ESP8266 +#define MY_GATEWAY_ESP8266 -// Enable to use UDP -#define MY_USE_UDP +#define MY_ESP8266_SSID "MySSID" +#define MY_ESP8266_PASSWORD "MyVerySecretPassword" -#define MY_IP_ADDRESS 192,168,178,66 // If this is disabled, DHCP is used to retrieve address -// Renewal period if using DHCP -//#define MY_IP_RENEWAL_INTERVAL 60000 -// The port to keep open on node server mode / or port to contact in client mode +// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) +// #define MY_IP_ADDRESS 192,168,178,66 +// If using static ip you need to define Gateway and Subnet address as well +#define MY_IP_GATEWAY_ADDRESS 192,168,0,1 +#define MY_IP_SUBNET_ADDRESS 255,255,255,0 + +// The port to keep open on node server mode #define MY_PORT 5003 -// Controller ip address (enables client mode). Undefine this to act as sever. -#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 - -// The MAC address can be anything you want but should be unique on your network. -// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. -// Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. -#define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +// How many clients should be able to connect to this gateway (default 1) +#define MY_GATEWAY_MAX_CLIENTS 5 +// Controller ip address (enables client mode). Undefine this to act as sever. +//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 + // Flash leds on rx/tx/err #define MY_LEDS_BLINKING_FEATURE // Set blinking period @@ -108,170 +109,24 @@ // Digital pin used for inclusion mode button #define MY_INCLUSION_MODE_BUTTON_PIN 3 -#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin -#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin -#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED +#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin +#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED -// NEW -#define MY_ESP8266_MAX_CLIENTS 5 // how many clients should be able to telnet to this ESP8266 -#define MY_ESP8266_SSID "MySSID" -#define MY_ESP8266_PASSWORD "MyVerySecretPassword" +#include - - -#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller -#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller - -typedef struct -{ - char string[MAX_RECEIVE_LENGTH]; - uint8_t idx; -} inputBuffer; - - -#include -//#include - -const char *ssid = "MySSID"; // cannot be longer than 32 characters! -const char *pass = "MyVerySecretPassword"; // - - -#define IP_PORT 5003 // The port you want to open -#define MAX_SRV_CLIENTS 5 // how many clients should be able to telnet to this ESP8266 - -// a R/W server on the port -static WiFiServer server(IP_PORT); -static WiFiClient clients[MAX_SRV_CLIENTS]; -static bool clientsConnected[MAX_SRV_CLIENTS]; -static inputBuffer inputString[MAX_SRV_CLIENTS]; - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - - -void output(const char *fmt, ... ) -{ - char serialBuffer[MAX_SEND_LENGTH]; - va_list args; - va_start (args, fmt ); - vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args); - va_end (args); - Serial.print(serialBuffer); - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) - { - if (clients[i] && clients[i].connected()) - { -// Serial.print("Client "); Serial.print(i); Serial.println(" write"); - clients[i].write((uint8_t*)serialBuffer, strlen(serialBuffer)); - } - } +void setup() { + } -void setup() -{ -/* // Setup console - hw_init(); - - Serial.println(); Serial.println(); - Serial.println("ESP8266 MySensors Gateway"); - Serial.print("Connecting to "); Serial.println(ssid); - - (void)WiFi.begin(ssid, pass); - while (WiFi.status() != WL_CONNECTED) - { - delay(500); - Serial.print("."); - } - Serial.println("Connected!"); - Serial.print("IP: "); Serial.println(WiFi.localIP()); - Serial.flush(); - - setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output); - - // Initialize gateway at maximum PA level, channel 70 and callback for write operations - begin(incomingMessage, 0, true, 0); - - // start listening for clients - server.begin(); - server.setNoDelay(true); */ +void presentation() { + // Present locally attached sensors here } void loop() { -/* - checkButtonTriggeredInclusion(); - checkInclusionFinished(); - // Go over list of clients and stop any that are no longer connected. - // If the server has a new client connection it will be assigned to a free slot. - bool allSlotsOccupied = true; - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) - { - if (!clients[i].connected()) - { - if (clientsConnected[i]) - { - Serial.print("Client "); Serial.print(i); Serial.println(" disconnected"); - clients[i].stop(); - } - //check if there are any new clients - if (server.hasClient()) - { - clients[i] = server.available(); - inputString[i].idx = 0; - Serial.print("Client "); Serial.print(i); Serial.println(" connected"); - output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY); - } - } - bool connected = clients[i].connected(); - clientsConnected[i] = connected; - allSlotsOccupied &= connected; - } - if (allSlotsOccupied && server.hasClient()) - { - //no free/disconnected spot so reject - Serial.println("No free slot available"); - WiFiClient c = server.available(); - c.stop(); - } - - // Loop over clients connect and read available data - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) - { - while(clients[i].connected() && clients[i].available()) - { - char inChar = clients[i].read(); - if ( inputString[i].idx < MAX_RECEIVE_LENGTH - 1 ) - { - // if newline then command is complete - if (inChar == '\n') - { - // a command was issued by the client - // we will now try to send it to the actuator - inputString[i].string[inputString[i].idx] = 0; - - // echo the string to the serial port - Serial.print("Client "); Serial.print(i); Serial.print(": "); Serial.println(inputString[i].string); - - parseAndSend(gw, inputString[i].string); - - // clear the string: - inputString[i].idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; - } else { - // add it to the inputString: - inputString[i].string[inputString[i].idx++] = inChar; - } - } else { - // Incoming message too long. Throw away - Serial.print("Client "); Serial.print(i); Serial.println(": Message too long"); - inputString[i].idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; - } - } - }*/ } diff --git a/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h b/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h deleted file mode 100644 index fa814b3..0000000 --- a/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef __GATEWAYUTIL_H__ -#define __GATEWAYUTIL_H__ - -#ifdef ARDUINO - -static uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled -static uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode - -#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller -#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller - - -typedef struct -{ - char string[MAX_RECEIVE_LENGTH]; - uint8_t idx; -} inputBuffer; - -static volatile boolean buttonTriggeredInclusion; -static boolean inclusionMode; // Keeps track on inclusion mode -bool inclusionButtonSupported = false; -void (*serial)(const char *fmt, ... ); - -MyParserSerial parser; - -void setInclusionMode(boolean newMode); - -char convBuf[MAX_PAYLOAD*2+1]; -unsigned long inclusionStartTime; - - -void startInclusionInterrupt() { - buttonTriggeredInclusion = true; -} - -void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) { - inclusionMode = 0; - buttonTriggeredInclusion = false; - serial = _serial; - - inclusionTime = _incTime; - inclusionButtonSupported = (_inc != 255); - if (inclusionButtonSupported) - { - pinInclusion = _inc; - - // Setup digital in that triggers inclusion mode - pinMode(pinInclusion, INPUT_PULLUP); - - // Add interrupt for inclusion button to pin - attachInterrupt(pinInclusion, startInclusionInterrupt, FALLING); - } -} - -void incomingMessage(const MyMessage &message) { -// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { -// gw.rxBlink(3); -// } else { -// gw.rxBlink(1); -// } - // Pass along the message from sensors to serial line - serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf)); -} - - - -void checkButtonTriggeredInclusion() { - if (inclusionButtonSupported) - { - if (buttonTriggeredInclusion) { - // Ok, someone pressed the inclusion button on the gateway - // start inclusion mode for 1 munute. - #ifdef DEBUG - serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE); - #endif - buttonTriggeredInclusion = false; - setInclusionMode(true); - } - } -} - -void checkInclusionFinished() { - if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - setInclusionMode(false); - } -} - -void parseAndSend(MySensor &gw, char *commandBuffer) { - boolean ok; - MyMessage &msg = gw.getLastMessage(); - - if (parser.parse(msg, commandBuffer)) { - uint8_t command = mGetCommand(msg); - - if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { - // Handle messages directed to gateway - if (msg.type == I_VERSION) { - // Request for version - serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); - } else if (msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(msg.data) == 1); - } - } else { - #ifdef WITH_LEDS_BLINKING - gw.txBlink(1); - #endif - ok = gw.sendRoute(msg); - if (!ok) { - #ifdef WITH_LEDS_BLINKING - gw.errBlink(1); - #endif - } - } - } -} - -void setInclusionMode(boolean newMode) { - if (newMode != inclusionMode) { - inclusionMode = newMode; - // Send back mode change on serial line to ack command - serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0); - - if (inclusionMode) { - inclusionStartTime = millis(); - } - } -} - - -#else -#error This example is only for use on Arduino. -#endif // ARDUINO - -#endif diff --git a/libraries/MySensors/keywords.txt b/libraries/MySensors/keywords.txt index 643dc01..e9c95ce 100644 --- a/libraries/MySensors/keywords.txt +++ b/libraries/MySensors/keywords.txt @@ -40,7 +40,7 @@ MY_OTA_FIRMWARE_FEATURE LITERAL1 MY_OTA_FLASH_SS LITERAL1 MY_OTA_FLASH_JDECID LITERAL1 MY_LEDS_BLINKING_FEATURE LITERAL1 -WITH_LEDS_BLINKING_INVERSE LITERAL1 +MY_WITH_LEDS_BLINKING_INVERSE LITERAL1 MY_DEFAULT_LED_BLINK_PERIOD LITERAL1 MY_WITH_LEDS_BLINKING_INVERSE LITERAL1 MY_DEFAULT_RX_LED_PIN LITERAL1 @@ -78,6 +78,7 @@ MY_RF69_IRQ_PIN LITERAL1 MY_RF69_SPI_CS LITERAL1 MY_RF69_IRQ_NUM LITERAL1 MY_RFM69_ENCRYPTKEY LITERAL1 +MY_GATEWAY_SERIAL LITERAL1 MY_GATEWAY_W5100 LITERAL1 MY_GATEWAY_ENC28J60 LITERAL1 MY_GATEWAY_ESP8266 LITERAL1 @@ -87,3 +88,10 @@ MY_USE_UDP LITERAL1 MY_IP_RENEWAL_INTERVAL LITERAL1 MY_MAC_ADDRESS LITERAL1 MY_CONTROLLER_IP_ADDRESS LITERAL1 +MY_GATEWAY_MAX_CLIENTS LITERAL1 +MY_GATEWAY_MAX_SEND_LENGTH LITERAL1 +MY_GATEWAY_MAX_RECEIVE_LENGTH LITERAL1 +MY_ESP8266_SSID LITERAL1 +MY_ESP8266_PASSWORD LITERAL1 +MY_IP_GATEWAY_ADDRESS LITERAL1 +MY_IP_SUBNET_ADDRESS LITERAL1