Work in progress

This commit is contained in:
Henrik Ekblad
2015-05-12 00:36:22 +02:00
parent 0b1f0dcbe0
commit 9469188e32
17 changed files with 477 additions and 85 deletions
+4 -4
View File
@@ -56,13 +56,13 @@
// #define WITH_LEDS_BLINKING
// default LEDs blinking period in milliseconds
#define DEFAULT_LED_BLINK_PERIOD 300
#define MY_DEFAULT_LED_BLINK_PERIOD 300
// The RX LED default pin
#define DEFAULT_RX_LED_PIN 8
#define MY_DEFAULT_RX_LED_PIN 8
// The TX LED default pin
#define DEFAULT_TX_LED_PIN 9
#define MY_DEFAULT_TX_LED_PIN 9
// The Error LED default pin
#define DEFAULT_ERR_LED_PIN 7
#define MY_DEFAULT_ERR_LED_PIN 7
/**********************************
+99
View File
@@ -0,0 +1,99 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 "MyGateway.h"
// Inline function and macros
static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
msg.sender = sender;
msg.destination = destination;
msg.sensor = sensor;
msg.type = type;
mSetCommand(msg,command);
mSetRequestAck(msg,enableAck);
mSetAck(msg,false);
return msg;
}
MyGateway::MyGateway(MyGatewayTransport &_transport,MyTransport &_radio, MyHw &_hw
#ifdef MY_SIGNING_FEATURE
, MySigning &_signer
#endif
#ifdef WITH_LEDS_BLINKING
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
#endif
) : transport(_transport),MySensor(_radio, _hw
#ifdef MY_SIGNING_FEATURE
, _signer
#endif
#ifdef WITH_LEDS_BLINKING
, _rx, _tx, _er, _blink_period
#endif
)
{
}
boolean MyGateway::sendRoute(MyMessage &message) {
if (message.destination == GATEWAY_ADDRESS) {
// This is a message sent from a sensor attached on the gateway node.
// Pass it directly to the gateway transport layer.
transport.send(message);
} else {
MySensor::sendRoute(message);
}
}
boolean MyGateway::process() {
bool newMessage = false;
if (transport.available()) {
MyMessage &gmsg = transport.receive();
if (msg.destination == GATEWAY_ADDRESS) {
// Check if sender requests an ack back.
if (mGetRequestAck(gmsg)) {
// Copy message
tmpMsg = gmsg;
mSetRequestAck(tmpMsg,false); // Reply without ack flag (otherwise we would end up in an eternal loop)
mSetAck(tmpMsg,true);
tmpMsg.sender = nc.nodeId;
tmpMsg.destination = msg.sender;
transport.send(tmpMsg);
}
if (mGetCommand(gmsg) == C_INTERNAL) {
if (msg.type == I_VERSION) {
// Request for version. Create the response
transport.send(build(msg, GATEWAY_ADDRESS, GATEWAY_ADDRESS, GATEWAY_ADDRESS, C_INTERNAL, I_VERSION, false).set(LIBRARY_VERSION));
} else if (msg.type == I_INCLUSION_MODE) {
// Request to change inclusion mode
//setInclusionMode(atoi(msg.data) == 1);
} else {
processInternalMessages(gmsg);
}
} else {
// Call incoming message callback if available
if (msgCallback != NULL) {
msgCallback(msg);
}
newMessage = true;
}
}
}
return MySensor::process() || newMessage;
}
+83
View File
@@ -0,0 +1,83 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 MyGateway_h
#define MyGateway_h
#include "MyConfig.h"
#include "MySensor.h"
#include "MyHw.h"
#include "MyTransport.h"
#include "MyTransportNRF24.h"
#ifdef MY_SIGNING_FEATURE
#include "MySigning.h"
#include "MySigningNone.h"
#endif
#include "MyMessage.h"
#ifdef MY_OTA_FIRMWARE_FEATURE
#include "utility/SPIFlash.h"
#endif
#include "MyProtocol.h"
#include "MyGatewayTransport.h"
#include "MyGatewayTransportSerial.h"
#include <stddef.h>
#include <stdarg.h>
class MyGateway : public MySensor
{
public:
// MyProtocolSerial constructor
MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver()
#ifdef MY_SIGNING_FEATURE
, MySigning &signer=*new MySigningNone()
#endif
#ifdef WITH_LEDS_BLINKING
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN
, uint8_t _tx=MY_DEFAULT_TX_LED_PIN
, uint8_t _er=MY_DEFAULT_ERR_LED_PIN
, unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD
#endif
);
void enableInclusionModeFeature(uint8_t inclusionModeButtonPin, uint8_t inclusionModeDuration);
/**
* See MySensor.h
*
* Overloaded to handle local sensor data sent to controller.
*/
boolean sendRoute(MyMessage &message);
/**
* Processes incoming messages to this node.
* Returns true if there is a message addressed for this node was received.
* Preferred way of handling incoming messages is to use the callback defined in begin().
*/
boolean process();
private:
MyGatewayTransport &transport;
};
#endif
@@ -17,18 +17,9 @@
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyParserSerial_h
#define MyParserSerial_h
#include "MyGatewayTransport.h"
#include "MyConfig.h"
#include "MyParser.h"
class MyParserSerial : public MyParser
{
public:
MyParserSerial();
bool parse(MyMessage &message, char *inputString);
private:
uint8_t h2i(char c);
};
#endif
MyGatewayTransport::MyGatewayTransport(MyProtocol &_protocol) : protocol(_protocol) {
}
+44
View File
@@ -0,0 +1,44 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 MyGatewayTransport_h
#define MyGatewayTransport_h
#include "MyMessage.h"
#include "MyProtocol.h"
#include "MyProtocolDefault.h"
class MyGatewayTransport
{
public:
// MyProtocol constructor
MyGatewayTransport(MyProtocol &protocol = *new MyProtocolDefault());
// Send message to controller
virtual bool send(MyMessage &message) = 0;
// Check if a new message is available from controller
virtual bool available() = 0;
// Pick up last message received from controller
virtual MyMessage& receive() = 0;
protected:
MyProtocol& protocol;
};
#endif
@@ -0,0 +1,66 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 "MyGatewayTransportSerial.h"
MyGatewayTransportSerial::MyGatewayTransportSerial(MyProtocol &_protocol) : MyGatewayTransport(_protocol),inputPos(0)
{
}
bool MyGatewayTransportSerial::send(MyMessage &message) {
Serial.print(protocol.format(message));
// Serial print is always successful
return true;
}
bool MyGatewayTransportSerial::available() {
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 (inputPos < MAX_RECEIVE_LENGTH - 1 && !available) {
if (inChar == '\n') {
inputString[inputPos] = 0;
available = true;
} else {
// add it to the inputString:
inputString[inputPos] = inChar;
inputPos++;
}
} else {
// Incoming message too long. Throw away
inputPos = 0;
}
}
if (available) {
// Parse message and return parse result
available = protocol.parse(msg, inputString);
inputPos = 0;
}
return available;
}
MyMessage & MyGatewayTransportSerial::receive() {
// Return the last parsed message
return msg;
}
@@ -0,0 +1,50 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 MyGatewayTransportSerial_h
#define MyGatewayTransportSerial_h
#include "MyMessage.h"
#include "MyProtocol.h"
#include "MyGatewayTransport.h"
#include "MyProtocolDefault.h"
#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller
class MyGatewayTransportSerial : public MyGatewayTransport
{
public:
// MyGateway constructor
MyGatewayTransportSerial(MyProtocol &protocol = *new MyProtocolDefault());
// 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();
private:
char inputString[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface
int inputPos;
MyMessage msg;
};
#endif
@@ -17,7 +17,7 @@
* version 2 as published by the Free Software Foundation.
*/
#include "MyParser.h"
#include "MyProtocol.h"
MyParser::MyParser() {
MyProtocol::MyProtocol() {
}
@@ -17,19 +17,23 @@
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyParser_h
#define MyParser_h
#ifndef MyProtocol_h
#define MyProtocol_h
#include "MyMessage.h"
class MyParser
class MyProtocol
{
public:
// MyParser constructor
MyParser();
// MyProtocol constructor
MyProtocol();
// parse(message, inputString)
// parse a string into a message element
// returns true if successfully parsed the input string
virtual bool parse(MyMessage &message, char *inputString) = 0;
// Format MyMessage to the protocol represenataion
virtual char *format(MyMessage &message) = 0;
};
#endif
@@ -17,13 +17,13 @@
* version 2 as published by the Free Software Foundation.
*/
#include "MyParser.h"
#include "MyParserSerial.h"
#include "MyProtocol.h"
#include "MyProtocolDefault.h"
#include "MyTransport.h"
MyParserSerial::MyParserSerial() : MyParser() {}
MyProtocolDefault::MyProtocolDefault() : MyProtocol() {}
bool MyParserSerial::parse(MyMessage &message, char *inputString) {
bool MyProtocolDefault::parse(MyMessage &message, char *inputString) {
char *str, *p, *value=NULL;
uint8_t bvalue[MAX_PAYLOAD];
uint8_t blen = 0;
@@ -89,7 +89,13 @@ bool MyParserSerial::parse(MyMessage &message, char *inputString) {
return true;
}
uint8_t MyParserSerial::h2i(char c) {
char * MyProtocolDefault::format(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));
return fmtBuffer;
}
uint8_t MyProtocolDefault::h2i(char c) {
uint8_t i = 0;
if (c <= '9')
i += c - '0';
+42
View File
@@ -0,0 +1,42 @@
/**
* 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 Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* 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 MyProtocolDefault_h
#define MyProtocolDefault_h
#include "MyConfig.h"
#include "MyProtocol.h"
#include "MyTransport.h"
#define MAX_FORMAT_BUFFER_LENGTH 120 // Max buffersize when formatting messages
class MyProtocolDefault : public MyProtocol
{
public:
MyProtocolDefault();
bool parse(MyMessage &message, char *inputString);
char *format(MyMessage &message);
private:
char fmtBuffer[MAX_FORMAT_BUFFER_LENGTH];
char convBuffer[MAX_PAYLOAD*2+1];
uint8_t h2i(char c);
};
#endif
+49 -42
View File
@@ -667,50 +667,19 @@ boolean MySensor::process() {
return true; // Just pass along nonce silently (no need to call callback for these)
#endif
} else if (sender == GATEWAY_ADDRESS) {
bool isMetric;
if (type == I_REBOOT) {
// Requires MySensors or other bootloader with watchdogs enabled
hw_reboot();
} else if (type == I_ID_RESPONSE) {
if (type == I_ID_RESPONSE && nc.nodeId == AUTO) {
nc.nodeId = msg.getByte();
if (nc.nodeId == AUTO) {
nc.nodeId = msg.getByte();
if (nc.nodeId == AUTO) {
// sensor net gateway will return max id if all sensor id are taken
debug(PSTR("full\n"));
while (1); // Wait here. Nothing else we can do...
}
setupNode();
// Write id to EEPROM
hw_writeConfig(EEPROM_NODE_ID_ADDRESS, nc.nodeId);
debug(PSTR("id=%d\n"), nc.nodeId);
}
} else if (type == I_CONFIG) {
// Pick up configuration from controller (currently only metric/imperial)
// and store it in eeprom if changed
isMetric = msg.getString()[0] == 'M' ;
cc.isMetric = isMetric;
hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric);
} else if (type == I_CHILDREN) {
if (repeaterMode && msg.getString()[0] == 'C') {
// Clears child relay data for this node
debug(PSTR("clear\n"));
uint8_t i = 255;
do {
hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff);
} while (i--);
// Clear parent node id & distance to gw
hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF);
hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF);
// Find parent node
findParentNode();
sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set(""));
}
} else if (type == I_TIME) {
if (timeCallback != NULL) {
// Deliver time to callback
timeCallback(msg.getULong());
// sensor net gateway will return max id if all sensor id are taken
debug(PSTR("full\n"));
while (1); // Wait here. Nothing else we can do...
}
setupNode();
// Write id to EEPROM
hw_writeConfig(EEPROM_NODE_ID_ADDRESS, nc.nodeId);
debug(PSTR("id=%d\n"), nc.nodeId);
} else {
processInternalMessages(msg);
}
return false;
}
@@ -791,6 +760,44 @@ boolean MySensor::process() {
return false;
}
void MySensor::processInternalMessages(MyMessage &msg) {
bool isMetric;
uint8_t type = msg.type;
if (type == I_REBOOT) {
// Requires MySensors or other bootloader with watchdogs enabled
hw_reboot();
} else if (type == I_CONFIG) {
// Pick up configuration from controller (currently only metric/imperial)
// and store it in eeprom if changed
isMetric = msg.getString()[0] == 'M' ;
cc.isMetric = isMetric;
hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric);
} else if (type == I_CHILDREN) {
if (repeaterMode && msg.getString()[0] == 'C') {
// Clears child relay data for this node
debug(PSTR("clear\n"));
uint8_t i = 255;
do {
hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff);
} while (i--);
// Clear parent node id & distance to gw
hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF);
hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF);
// Find parent node
findParentNode();
sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set(""));
}
} else if (type == I_TIME) {
if (timeCallback != NULL) {
// Deliver time to callback
timeCallback(msg.getULong());
}
}
}
MyMessage& MySensor::getLastMessage() {
return msg;
}
+8 -8
View File
@@ -26,7 +26,6 @@
#include "MyHw.h"
#include "MyTransport.h"
#include "MyTransportNRF24.h"
#include "MyParser.h"
#ifdef MY_SIGNING_FEATURE
#include "MySigning.h"
#include "MySigningNone.h"
@@ -147,10 +146,10 @@ class MySensor
, MySigning &signer=*new MySigningNone()
#endif
#ifdef WITH_LEDS_BLINKING
, uint8_t _rx=DEFAULT_RX_LED_PIN,
uint8_t _tx=DEFAULT_TX_LED_PIN,
uint8_t _er=DEFAULT_ERR_LED_PIN,
unsigned long _blink_period=DEFAULT_LED_BLINK_PERIOD
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN,
uint8_t _tx=MY_DEFAULT_TX_LED_PIN,
uint8_t _er=MY_DEFAULT_ERR_LED_PIN,
unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD
#endif
);
@@ -199,7 +198,6 @@ class MySensor
*/
bool send(MyMessage &msg, bool ack=false);
boolean sendRoute(MyMessage &message);
/**
* Send this nodes battery level to gateway.
@@ -315,6 +313,8 @@ class MySensor
void errBlink(uint8_t cnt);
#endif
boolean sendRoute(MyMessage &message);
protected:
NodeConfig nc; // Essential settings for node to work
ControllerConfig cc; // Configuration coming from controller
@@ -357,8 +357,7 @@ class MySensor
MyHw& hw;
boolean sendWrite(uint8_t dest, MyMessage &message);
private:
void processInternalMessages(MyMessage &msg);
#ifdef DEBUG
char convBuf[MAX_PAYLOAD*2+1];
#endif
@@ -371,6 +370,7 @@ class MySensor
bool isValidFirmware();
#endif
private:
void requestNodeId();
void setupNode();
@@ -66,7 +66,7 @@
#include <MySigningAtsha204Soft.h>
#include <MySigningAtsha204.h>
#include <MyParserSerial.h>
#include <MyProtocolDefault.h>
#include <MySensor.h>
#include <stdarg.h>
#include <PinChangeInt.h>
@@ -17,7 +17,7 @@ volatile boolean buttonTriggeredInclusion;
boolean inclusionMode; // Keeps track on inclusion mode
void (*serial)(const char *fmt, ... );
MyParserSerial parser;
MyProtocolDefault protocol;
void setInclusionMode(boolean newMode);
@@ -79,7 +79,7 @@ void parseAndSend(MySensor &gw, char *commandBuffer) {
boolean ok;
MyMessage &msg = gw.getLastMessage();
if (parser.parse(msg, commandBuffer)) {
if (protocol.parse(msg, commandBuffer)) {
uint8_t command = mGetCommand(msg);
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
@@ -37,7 +37,7 @@ volatile boolean buttonTriggeredInclusion;
boolean inclusionMode; // Keeps track on inclusion mode
void (*serial)(const char *fmt, ... );
MyParserSerial parser;
MyProtocolDefault protocol;
void setInclusionMode(boolean newMode);
@@ -99,7 +99,7 @@ void parseAndSend(MySensor &gw, char *commandBuffer) {
boolean ok;
MyMessage &msg = gw.getLastMessage();
if (parser.parse(msg, commandBuffer)) {
if (protocol.parse(msg, commandBuffer)) {
uint8_t command = mGetCommand(msg);
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
@@ -46,7 +46,7 @@
#include <MySigningAtsha204.h>
#include <SPI.h>
#include <MyParserSerial.h>
#include <MyProtocolDefault.h>
#include <MySensor.h>
#include <stdarg.h>
#include <PinChangeInt.h>