From ceb8f5969fbe97b20ffe5fa9a7cbc264ead7a1e2 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Sat, 23 May 2015 23:15:03 +0200 Subject: [PATCH] Add tested draft of MyGatewayTransportEthernet working as client Signed-off-by: Tomas Hozza --- libraries/MySensors/MyConfig.h | 12 ++ .../MySensors/MyGatewayTransportEthernet.cpp | 189 ++++++++++++++++++ .../MySensors/MyGatewayTransportEthernet.h | 100 +++++++++ 3 files changed, 301 insertions(+) create mode 100644 libraries/MySensors/MyGatewayTransportEthernet.cpp create mode 100644 libraries/MySensors/MyGatewayTransportEthernet.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 0e07a5a..871e269 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -74,6 +74,11 @@ // Enables inclusion-mode button feature on the gateway device #define MY_INCLUSION_BUTTON_FEATURE +// Disable inclusion mode button if inclusion mode feature is not enabled +#ifndef MY_INCLUSION_MODE_FEATURE +#undef MY_INCLUSION_BUTTON_FEATURE +#endif + // The default input pin used for the inclusion mode button #define MY_INCLUSION_MODE_BUTTON_PIN 3 // Number of seconds (default one minute) inclusion mode should be enabled @@ -152,6 +157,13 @@ #define RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! +/************************************** +* Gateway Transport Ethernet Defaults +***************************************/ +// Enable to use DHCP for getting IP address. If not defined, static IP is expected +//#define IP_ADDRESS_DHCP +// Enable to use UDP instead of plain Ethernet +#define USE_UDP #endif diff --git a/libraries/MySensors/MyGatewayTransportEthernet.cpp b/libraries/MySensors/MyGatewayTransportEthernet.cpp new file mode 100644 index 0000000..7d5e948 --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportEthernet.cpp @@ -0,0 +1,189 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyGatewayTransportEthernet.h" + +MyGatewayTransportEthernet::MyGatewayTransportEthernet( + MyProtocol &protocol, + uint8_t *gw_mac +#ifndef IP_ADDRESS_DHCP + , IPAddress gw_ip +#endif /* not IP_ADDRESS_DHCP */ + , uint16_t gw_port +#ifdef IP_ADDRESS_DHCP + , unsigned long ip_renew_interval +#endif /* IP_ADDRESS_DHCP */ + , IPAddress controller_IP + , uint16_t controller_port) : + MyGatewayTransport(protocol), + gatewayMAC(gw_mac), +#ifndef IP_ADDRESS_DHCP + gatewayIP(gw_ip), +#endif /* not IP_ADDRESS_DHCP */ + gatewayPort(gw_port), +#ifdef IP_ADDRESS_DHCP + ip_renewal_period(ip_renew_interval), +#endif /* IP_ADDRESS_DHCP */ + controllerIP(controller_IP), + controllerPort(controller_port) +{ + ; +} + +bool MyGatewayTransportEthernet::begin() { +#ifdef IP_ADDRESS_DHCP + // Get IP address from DHCP + Ethernet.begin(gatewayMAC); +#else + Ethernet.begin(gatewayMAC, gatewayIP); +#endif /* IP_ADDRESS_DHCP */ + + // give the Ethernet interface a second to initialize + // TODO: use HW delay + delay(1000); + +#ifdef USE_UDP + server = new EthernetUDP(); + server->begin(gatewayPort); +#else + // we have to use pointers due to the constructor of EthernetServer + server = new EthernetServer(gatewayPort); + server->begin(); +#endif /* USE_UDP */ +} + +bool MyGatewayTransportEthernet::send(MyMessage &message) +{ + char *msg = NULL; + + if (controllerIP == INADDR_NONE) { + // no controller IP address set! + return false; + } + else { + msg = protocol.format(message); +#ifdef USE_UDP + server->beginPacket(controllerIP, controllerPort); + server->write(msg, strlen(msg)); + // returns 1 if the packet was sent successfully + return server->endPacket(); +#else + EthernetClient client; + if (client.connect(controllerIP, controllerPort)) { + client.write(msg, strlen(msg)); + client.stop(); + return true; + } + else { + // connecting to the server failed! + return false; + } +#endif /* USE_UDP */ + } +} + +bool MyGatewayTransportEthernet::available() +{ + bool available = false; + +#ifdef IP_ADDRESS_DHCP + // renew IP address using DHCP + renewIP(); +#endif + +#ifdef USE_UDP + int packet_size = server->parsePacket(); + + if (server->available()) { + server->read(inputBuffer, MAX_RECEIVE_LENGTH); + available = true; + } +#else + // if an incoming client connects, there will be + // bytes available to read via the client object + EthernetClient client = server->available(); + + if (client) { + while (client.available()) { + // read the bytes incoming from the client + char inChar = client.read(); + + if (inputPos < MAX_RECEIVE_LENGTH - 1) { + // if newline then command is complete + if (inChar == '\n') { + inputBuffer[inputPos] = 0; + available = true; + } else { + inputBuffer[inputPos] = inChar; + inputPos++; + } + } + } + } + inputPos = 0; +#endif + + if (available) { + // Parse message and return parse result + available = protocol.parse(msg, inputBuffer); + } + + return available; +} + +MyMessage& MyGatewayTransportEthernet::receive() +{ + // Return the last parsed message + return msg; +} + +void MyGatewayTransportEthernet::setControllerIPPort(const IPAddress& addr, const uint16_t port) { + controllerIP = addr; + + /* set the port if some legal value passed */ + if (port > 0) + controllerPort = port; +} + +#ifdef IP_ADDRESS_DHCP +void MyGatewayTransportEthernet::renewIP() +{ + /* renew/rebind IP address + 0 - nothing happened + 1 - renew failed + 2 - renew success + 3 - rebinf failed + 4 - rebind success + */ + // TODO: Use millis from MyHw ?? + static unsigned long next_time = millis() + ip_renewal_period; + unsigned long now = millis(); + + // http://playground.arduino.cc/Code/TimingRollover + if ((long)(now - next_time) < 0) + return; + + if (Ethernet.maintain() & ~(0x06)) { + /* Error occured -> IP was not renewed */ + return; + } + + next_time = now + ip_renewal_period; +} +#endif /* IP_ADDRESS_DHCP */ diff --git a/libraries/MySensors/MyGatewayTransportEthernet.h b/libraries/MySensors/MyGatewayTransportEthernet.h new file mode 100644 index 0000000..fefda1c --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportEthernet.h @@ -0,0 +1,100 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyGatewayTransportEthernet_h +#define MyGatewayTransportEthernet_h + +#include "MyConfig.h" +#include "MyMessage.h" +#include "MyProtocol.h" +#include "MyGatewayTransport.h" +#include "MyProtocolDefault.h" + +#include + +// Use this if you have attached a Ethernet ENC28J60 shields +//#include + +// Use this fo WizNET W5100 module and Arduino Ethernet Shield +#include + +#ifdef USE_UDP +#include +#endif /* USE_UDP */ + +#define CONTROLLER_PORT 5003 +#define IP_RENEWAL_INTERVAL 60000 // in milliseconds +#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller + + +class MyGatewayTransportEthernet : public MyGatewayTransport +{ + public: + MyGatewayTransportEthernet(MyProtocol &protocol, + uint8_t *gw_mac +#ifndef IP_ADDRESS_DHCP + , IPAddress gw_ip +#endif /* not IP_ADDRESS_DHCP */ + , uint16_t gw_port +#ifdef IP_ADDRESS_DHCP + , unsigned long ip_renew_interval +#endif /* IP_ADDRESS_DHCP */ + , IPAddress controller_IP + , uint16_t controller_port + ); + + // initialize the driver + bool begin(); + + // Send message to controller + bool send(MyMessage &message); + + // Check if a new message is available from controller + bool available(); + + // Pick up last message received from controller + MyMessage& receive(); + + // Set the controller IP and Port + void setControllerIPPort(const IPAddress& addr, const uint16_t port); + +protected: + IPAddress controllerIP; + uint16_t controllerPort; + +#ifdef IP_ADDRESS_DHCP + void renewIP(); + unsigned long ip_renewal_period; +#endif /* IP_ADDRESS_DHCP */ + uint8_t *gatewayMAC; + IPAddress gatewayIP; + uint16_t gatewayPort; + +#ifndef USE_UDP + EthernetServer *server; + uint8_t inputPos; +#else + EthernetUDP *server; +#endif + + char inputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface + MyMessage msg; +}; + +#endif /* MyGatewayTransportEthernet_h */