Serial Gateway in a working state
This commit is contained in:
@@ -49,22 +49,36 @@
|
|||||||
* Information LEDs blinking
|
* Information LEDs blinking
|
||||||
***********************************/
|
***********************************/
|
||||||
// This feature enables LEDs blinking on message receive, transmit
|
// This feature enables LEDs blinking on message receive, transmit
|
||||||
// or if some error occured. This was commonly used only in gateways,
|
// or if some error occurred. This was commonly used only in gateways,
|
||||||
// but now can be used in any sensor node. Also the LEDs can now be
|
// but now can be used in any sensor node. Also the LEDs can now be
|
||||||
// disabled in the gateway.
|
// disabled in the gateway.
|
||||||
|
|
||||||
// #define WITH_LEDS_BLINKING
|
// #define MY_LEDS_BLINKING_FEATURE
|
||||||
|
|
||||||
// default LEDs blinking period in milliseconds
|
// default LEDs blinking period in milliseconds
|
||||||
#define MY_DEFAULT_LED_BLINK_PERIOD 300
|
#define MY_DEFAULT_LED_BLINK_PERIOD 300
|
||||||
// The RX LED default pin
|
// The RX LED default pin
|
||||||
#define MY_DEFAULT_RX_LED_PIN 8
|
#define MY_DEFAULT_RX_LED_PIN 6
|
||||||
// The TX LED default pin
|
// The TX LED default pin
|
||||||
#define MY_DEFAULT_TX_LED_PIN 9
|
#define MY_DEFAULT_TX_LED_PIN 5
|
||||||
// The Error LED default pin
|
// The Error LED default pin
|
||||||
#define MY_DEFAULT_ERR_LED_PIN 7
|
#define MY_DEFAULT_ERR_LED_PIN 4
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************
|
||||||
|
* Gateway inclusion button/mode configuration
|
||||||
|
**********************************************/
|
||||||
|
// Enabled inclusion mode feature
|
||||||
|
#define MY_INCLUSION_MODE_FEATURE
|
||||||
|
|
||||||
|
// Enables inclusion-mode button feature on the gateway device
|
||||||
|
#define MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
|
||||||
|
// 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
|
||||||
|
#define MY_INCLUSION_MODE_DURATION 60
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* Message Signing Settings
|
* Message Signing Settings
|
||||||
***********************************/
|
***********************************/
|
||||||
|
|||||||
@@ -20,33 +20,64 @@
|
|||||||
#include "MyGateway.h"
|
#include "MyGateway.h"
|
||||||
|
|
||||||
// Inline function and macros
|
// 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) {
|
static inline MyMessage& build(MyMessage &msg, uint8_t type) {
|
||||||
msg.sender = sender;
|
msg.sender = GATEWAY_ADDRESS;
|
||||||
msg.destination = destination;
|
msg.destination = GATEWAY_ADDRESS;
|
||||||
msg.sensor = sensor;
|
msg.sensor = 0;
|
||||||
msg.type = type;
|
msg.type = type;
|
||||||
mSetCommand(msg,command);
|
mSetCommand(msg, C_INTERNAL);
|
||||||
mSetRequestAck(msg,enableAck);
|
mSetRequestAck(msg, false);
|
||||||
mSetAck(msg,false);
|
mSetAck(msg, false);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGateway::MyGateway(MyGatewayTransport &_transport,MyTransport &_radio, MyHw &_hw
|
MyGateway::MyGateway(MyGatewayTransport &_transport, MyTransport &_radio,
|
||||||
|
MyHw &_hw
|
||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
, MySigning &_signer
|
, MySigning &_signer
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
|
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
|
||||||
#endif
|
#endif
|
||||||
) : transport(_transport),MySensor(_radio, _hw
|
) :
|
||||||
|
transport(_transport), MySensor(_radio, _hw
|
||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
, _signer
|
, _signer
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
, _rx, _tx, _er, _blink_period
|
, _rx, _tx, _er, _blink_period
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
inclusionMode = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGateway::begin(void (*_msgCallback)(const MyMessage &)
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
, int _inclusionModeDuration
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
, uint8_t _inclusionModeButtonPin
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
) {
|
||||||
|
// Setup digital in that triggers inclusion mode
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
inclusionDuration = _inclusionModeDuration*1000;
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
inclusionButtonPin = _inclusionModeButtonPin;
|
||||||
|
pinMode(inclusionButtonPin, INPUT);
|
||||||
|
digitalWrite(inclusionButtonPin, HIGH);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start MySensors in repeater mode
|
||||||
|
MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS);
|
||||||
|
|
||||||
|
// Startup complete
|
||||||
|
transport.send(build(msg, I_GATEWAY_READY).set("Gateway startup complete."));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +91,8 @@ boolean MyGateway::sendRoute(MyMessage &message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean MyGateway::process() {
|
boolean MyGateway::process() {
|
||||||
|
checkInclusionMode();
|
||||||
bool newMessage = false;
|
bool newMessage = false;
|
||||||
if (transport.available()) {
|
if (transport.available()) {
|
||||||
MyMessage &gmsg = transport.receive();
|
MyMessage &gmsg = transport.receive();
|
||||||
@@ -70,8 +101,8 @@ boolean MyGateway::process() {
|
|||||||
if (mGetRequestAck(gmsg)) {
|
if (mGetRequestAck(gmsg)) {
|
||||||
// Copy message
|
// Copy message
|
||||||
tmpMsg = gmsg;
|
tmpMsg = gmsg;
|
||||||
mSetRequestAck(tmpMsg,false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
mSetRequestAck(tmpMsg, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||||
mSetAck(tmpMsg,true);
|
mSetAck(tmpMsg, true);
|
||||||
tmpMsg.sender = nc.nodeId;
|
tmpMsg.sender = nc.nodeId;
|
||||||
tmpMsg.destination = msg.sender;
|
tmpMsg.destination = msg.sender;
|
||||||
transport.send(tmpMsg);
|
transport.send(tmpMsg);
|
||||||
@@ -79,10 +110,12 @@ boolean MyGateway::process() {
|
|||||||
if (mGetCommand(gmsg) == C_INTERNAL) {
|
if (mGetCommand(gmsg) == C_INTERNAL) {
|
||||||
if (msg.type == I_VERSION) {
|
if (msg.type == I_VERSION) {
|
||||||
// Request for version. Create the response
|
// Request for version. Create the response
|
||||||
transport.send(build(msg, GATEWAY_ADDRESS, GATEWAY_ADDRESS, GATEWAY_ADDRESS, C_INTERNAL, I_VERSION, false).set(LIBRARY_VERSION));
|
transport.send(build(msg, I_VERSION).set(LIBRARY_VERSION));
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
} else if (msg.type == I_INCLUSION_MODE) {
|
} else if (msg.type == I_INCLUSION_MODE) {
|
||||||
// Request to change inclusion mode
|
// Request to change inclusion mode
|
||||||
//setInclusionMode(atoi(msg.data) == 1);
|
setInclusionMode(atoi(msg.data) == 1);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
processInternalMessages(gmsg);
|
processInternalMessages(gmsg);
|
||||||
}
|
}
|
||||||
@@ -97,3 +130,39 @@ boolean MyGateway::process() {
|
|||||||
}
|
}
|
||||||
return MySensor::process() || newMessage;
|
return MySensor::process() || newMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
void MyGateway::setInclusionMode(boolean newMode) {
|
||||||
|
if (newMode != inclusionMode) {
|
||||||
|
inclusionMode = newMode;
|
||||||
|
// Send back mode change to controller
|
||||||
|
transport.send(build(msg, I_INCLUSION_MODE).set(inclusionMode?1:0));
|
||||||
|
if (inclusionMode) {
|
||||||
|
|
||||||
|
inclusionStartTime = hw_millis();
|
||||||
|
Serial.println(inclusionStartTime);
|
||||||
|
Serial.println(inclusionDuration);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGateway::checkInclusionMode() {
|
||||||
|
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
if (!inclusionMode && digitalRead(inclusionButtonPin) == LOW) {
|
||||||
|
// Start inclusion mode
|
||||||
|
setInclusionMode(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (inclusionMode && hw_millis()-inclusionStartTime>inclusionDuration) {
|
||||||
|
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode
|
||||||
|
setInclusionMode(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
, MySigning &signer=*new MySigningNone()
|
, MySigning &signer=*new MySigningNone()
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN
|
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN
|
||||||
, uint8_t _tx=MY_DEFAULT_TX_LED_PIN
|
, uint8_t _tx=MY_DEFAULT_TX_LED_PIN
|
||||||
, uint8_t _er=MY_DEFAULT_ERR_LED_PIN
|
, uint8_t _er=MY_DEFAULT_ERR_LED_PIN
|
||||||
@@ -60,7 +60,24 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
void enableInclusionModeFeature(uint8_t inclusionModeButtonPin, uint8_t inclusionModeDuration);
|
/**
|
||||||
|
* Begin operation of the MySensors library
|
||||||
|
*
|
||||||
|
* Call this in setup(), before calling any other sensor net library methods.
|
||||||
|
* @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL.
|
||||||
|
* @param inclusionModeDuration Number of milliseconds inclusion mode should be enabled
|
||||||
|
* @param inclusionModeButtonPin Button pin used for enabling inclusion mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
void begin(void (* msgCallback)(const MyMessage &)=NULL
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
, int inclusionModeDuration=MY_INCLUSION_MODE_DURATION
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
, uint8_t inclusionModeButtonPin=MY_INCLUSION_MODE_BUTTON_PIN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See MySensor.h
|
* See MySensor.h
|
||||||
@@ -77,7 +94,21 @@ public:
|
|||||||
boolean process();
|
boolean process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MyGatewayTransport &transport;
|
MyGatewayTransport &transport;
|
||||||
|
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
|
||||||
|
void setInclusionMode(bool newMode);
|
||||||
|
void checkInclusionMode();
|
||||||
|
unsigned long inclusionStartTime;
|
||||||
|
bool inclusionMode;
|
||||||
|
unsigned long inclusionDuration;
|
||||||
|
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
uint8_t inclusionButtonPin;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ MySensor::MySensor(MyTransport &_radio, MyHw &_hw
|
|||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
, MySigning &_signer
|
, MySigning &_signer
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
|
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
@@ -62,7 +62,7 @@ MySensor::MySensor(MyTransport &_radio, MyHw &_hw
|
|||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
signer(_signer),
|
signer(_signer),
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
pinRx(_rx), pinTx(_tx), pinEr(_er), ledBlinkPeriod(_blink_period),
|
pinRx(_rx), pinTx(_tx), pinEr(_er), ledBlinkPeriod(_blink_period),
|
||||||
#endif
|
#endif
|
||||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||||
@@ -96,7 +96,7 @@ bool MySensor::isValidFirmware() {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
void MySensor::handleLedsBlinking() {
|
void MySensor::handleLedsBlinking() {
|
||||||
static unsigned long next_time = hw_millis() + ledBlinkPeriod;
|
static unsigned long next_time = hw_millis() + ledBlinkPeriod;
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
|
|||||||
hw_readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign));
|
hw_readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
// Setup led pins
|
// Setup led pins
|
||||||
pinMode(pinRx, OUTPUT);
|
pinMode(pinRx, OUTPUT);
|
||||||
pinMode(pinTx, OUTPUT);
|
pinMode(pinTx, OUTPUT);
|
||||||
@@ -327,7 +327,7 @@ boolean MySensor::sendRoute(MyMessage &message) {
|
|||||||
// If we still don't have any parent id, re-request and skip this message.
|
// If we still don't have any parent id, re-request and skip this message.
|
||||||
if (nc.parentNodeId == AUTO) {
|
if (nc.parentNodeId == AUTO) {
|
||||||
findParentNode();
|
findParentNode();
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@@ -336,7 +336,7 @@ boolean MySensor::sendRoute(MyMessage &message) {
|
|||||||
// If we still don't have any node id, re-request and skip this message.
|
// If we still don't have any node id, re-request and skip this message.
|
||||||
if (nc.nodeId == AUTO) {
|
if (nc.nodeId == AUTO) {
|
||||||
requestNodeId();
|
requestNodeId();
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@@ -375,14 +375,14 @@ boolean MySensor::sendRoute(MyMessage &message) {
|
|||||||
}
|
}
|
||||||
if (hw_millis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
|
if (hw_millis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
|
||||||
debug(PSTR("nonce tmo\n"));
|
debug(PSTR("nonce tmo\n"));
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!signOk) {
|
if (!signOk) {
|
||||||
debug(PSTR("sign fail\n"));
|
debug(PSTR("sign fail\n"));
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@@ -443,7 +443,7 @@ boolean MySensor::sendRoute(MyMessage &message) {
|
|||||||
if (!ok) {
|
if (!ok) {
|
||||||
// Failure when sending to parent node. The parent node might be down and we
|
// Failure when sending to parent node. The parent node might be down and we
|
||||||
// need to find another route to gateway.
|
// need to find another route to gateway.
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
failedTransmissions++;
|
failedTransmissions++;
|
||||||
@@ -460,7 +460,7 @@ boolean MySensor::sendWrite(uint8_t to, MyMessage &message) {
|
|||||||
mSetVersion(message, PROTOCOL_VERSION);
|
mSetVersion(message, PROTOCOL_VERSION);
|
||||||
uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message);
|
uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message);
|
||||||
message.last = nc.nodeId;
|
message.last = nc.nodeId;
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
txBlink(1);
|
txBlink(1);
|
||||||
#endif
|
#endif
|
||||||
bool ok = radio.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length));
|
bool ok = radio.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length));
|
||||||
@@ -508,7 +508,7 @@ void MySensor::requestTime(void (* _timeCallback)(unsigned long)) {
|
|||||||
boolean MySensor::process() {
|
boolean MySensor::process() {
|
||||||
hw_watchdogReset();
|
hw_watchdogReset();
|
||||||
|
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
handleLedsBlinking();
|
handleLedsBlinking();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -522,7 +522,7 @@ boolean MySensor::process() {
|
|||||||
debug(PSTR("fw upd fail\n"));
|
debug(PSTR("fw upd fail\n"));
|
||||||
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
||||||
fwUpdateOngoing = false;
|
fwUpdateOngoing = false;
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@@ -546,7 +546,7 @@ boolean MySensor::process() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t len = radio.receive((uint8_t *)&msg);
|
uint8_t len = radio.receive((uint8_t *)&msg);
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
rxBlink(1);
|
rxBlink(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -561,14 +561,14 @@ boolean MySensor::process() {
|
|||||||
if (!mGetSigned(msg)) {
|
if (!mGetSigned(msg)) {
|
||||||
// Got unsigned message that should have been signed
|
// Got unsigned message that should have been signed
|
||||||
debug(PSTR("no sign\n"));
|
debug(PSTR("no sign\n"));
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!signer.verifyMsg(msg)) {
|
else if (!signer.verifyMsg(msg)) {
|
||||||
debug(PSTR("verify fail\n"));
|
debug(PSTR("verify fail\n"));
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false; // This signed message has been tampered with!
|
return false; // This signed message has been tampered with!
|
||||||
@@ -584,7 +584,7 @@ boolean MySensor::process() {
|
|||||||
|
|
||||||
if(!(mGetVersion(msg) == PROTOCOL_VERSION)) {
|
if(!(mGetVersion(msg) == PROTOCOL_VERSION)) {
|
||||||
debug(PSTR("ver mismatch\n"));
|
debug(PSTR("ver mismatch\n"));
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
errBlink(1);
|
errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ class MySensor
|
|||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
, MySigning &signer=*new MySigningNone()
|
, MySigning &signer=*new MySigningNone()
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN,
|
, uint8_t _rx=MY_DEFAULT_RX_LED_PIN,
|
||||||
uint8_t _tx=MY_DEFAULT_TX_LED_PIN,
|
uint8_t _tx=MY_DEFAULT_TX_LED_PIN,
|
||||||
uint8_t _er=MY_DEFAULT_ERR_LED_PIN,
|
uint8_t _er=MY_DEFAULT_ERR_LED_PIN,
|
||||||
@@ -303,7 +303,7 @@ class MySensor
|
|||||||
*/
|
*/
|
||||||
int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
|
int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
|
||||||
|
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
/**
|
/**
|
||||||
* Blink with LEDs
|
* Blink with LEDs
|
||||||
* @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms
|
* @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms
|
||||||
@@ -339,7 +339,7 @@ class MySensor
|
|||||||
MySigning& signer;
|
MySigning& signer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
uint8_t pinRx; // Rx led pin
|
uint8_t pinRx; // Rx led pin
|
||||||
uint8_t pinTx; // Tx led pin
|
uint8_t pinTx; // Tx led pin
|
||||||
uint8_t pinEr; // Err led pin
|
uint8_t pinEr; // Err led pin
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
|||||||
MyHwATMega328 hw;
|
MyHwATMega328 hw;
|
||||||
|
|
||||||
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||||
// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_WITH_LEDS_BLINKING
|
||||||
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||||
#else
|
#else
|
||||||
MySensor gw(transport, hw /*, signer*/);
|
MySensor gw(transport, hw /*, signer*/);
|
||||||
|
|||||||
@@ -92,12 +92,12 @@ void parseAndSend(MySensor &gw, char *commandBuffer) {
|
|||||||
setInclusionMode(atoi(msg.data) == 1);
|
setInclusionMode(atoi(msg.data) == 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
gw.txBlink(1);
|
gw.txBlink(1);
|
||||||
#endif
|
#endif
|
||||||
ok = gw.sendRoute(msg);
|
ok = gw.sendRoute(msg);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
gw.errBlink(1);
|
gw.errBlink(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 __GATEWAYUTIL_H__
|
|
||||||
#define __GATEWAYUTIL_H__
|
|
||||||
|
|
||||||
#include <MyTransport.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ARDUINO
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled
|
|
||||||
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
|
|
||||||
|
|
||||||
volatile boolean buttonTriggeredInclusion;
|
|
||||||
boolean inclusionMode; // Keeps track on inclusion mode
|
|
||||||
void (*serial)(const char *fmt, ... );
|
|
||||||
|
|
||||||
MyProtocolDefault protocol;
|
|
||||||
|
|
||||||
void setInclusionMode(boolean newMode);
|
|
||||||
|
|
||||||
char convBuf[MAX_PAYLOAD*2+1];
|
|
||||||
char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera
|
|
||||||
unsigned long inclusionStartTime;
|
|
||||||
|
|
||||||
void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) {
|
|
||||||
inclusionMode = 0;
|
|
||||||
buttonTriggeredInclusion = false;
|
|
||||||
serial = _serial;
|
|
||||||
|
|
||||||
pinInclusion = _inc;
|
|
||||||
inclusionTime = _incTime;
|
|
||||||
|
|
||||||
// Setup digital in that triggers inclusion mode
|
|
||||||
pinMode(pinInclusion, INPUT);
|
|
||||||
digitalWrite(pinInclusion, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void startInclusionInterrupt() {
|
|
||||||
buttonTriggeredInclusion = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (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 (protocol.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
|
|
||||||
|
|
||||||
@@ -29,15 +29,13 @@
|
|||||||
* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
|
* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
|
||||||
*
|
*
|
||||||
* LEDs (OPTIONAL):
|
* LEDs (OPTIONAL):
|
||||||
* - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
* - To use the feature, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h
|
||||||
* - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
|
* - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
|
||||||
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
|
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
|
||||||
* - ERR (red) - fast blink on error during transmission error or recieve crc error
|
* - ERR (red) - fast blink on error during transmission error or recieve crc error
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NO_PORTB_PINCHANGES
|
|
||||||
|
|
||||||
#include <MySigningNone.h>
|
#include <MySigningNone.h>
|
||||||
#include <MyTransportRFM69.h>
|
#include <MyTransportRFM69.h>
|
||||||
#include <MyTransportNRF24.h>
|
#include <MyTransportNRF24.h>
|
||||||
@@ -46,13 +44,11 @@
|
|||||||
#include <MySigningAtsha204.h>
|
#include <MySigningAtsha204.h>
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <MyGatewayTransportSerial.h>
|
||||||
#include <MyProtocolDefault.h>
|
#include <MyProtocolDefault.h>
|
||||||
#include <MySensor.h>
|
#include <MyGateway.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <PinChangeInt.h>
|
|
||||||
#include "GatewayUtil.h"
|
|
||||||
|
|
||||||
#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
|
#define INCLUSION_MODE_TIME 60 // Number of seconds inclusion mode is enabled
|
||||||
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
|
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
|
||||||
#define RADIO_ERROR_LED_PIN 4 // Error led pin
|
#define RADIO_ERROR_LED_PIN 4 // Error led pin
|
||||||
#define RADIO_RX_LED_PIN 6 // Receive led pin
|
#define RADIO_RX_LED_PIN 6 // Receive led pin
|
||||||
@@ -70,88 +66,37 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
|||||||
// Hardware profile
|
// Hardware profile
|
||||||
MyHwATMega328 hw;
|
MyHwATMega328 hw;
|
||||||
|
|
||||||
|
// Controller Transport profile
|
||||||
|
MyProtocolDefault protocol;
|
||||||
|
MyGatewayTransportSerial ctrlTransport(protocol);
|
||||||
|
|
||||||
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||||
// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h
|
||||||
#ifdef WITH_LEDS_BLINKING
|
#ifdef MY_LEDS_BLINKING_FEATURE
|
||||||
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
MyGateway gw(ctrlTransport, transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||||
#else
|
#else
|
||||||
MySensor gw(transport, hw /*, signer*/);
|
MyGateway gw(ctrlTransport, transport, hw /*, signer*/);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface
|
|
||||||
int inputPos = 0;
|
|
||||||
boolean commandComplete = false; // whether the string is complete
|
|
||||||
|
|
||||||
void parseAndSend(char *commandBuffer);
|
|
||||||
|
|
||||||
void output(const char *fmt, ... ) {
|
|
||||||
va_list args;
|
|
||||||
va_start (args, fmt );
|
|
||||||
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
|
||||||
va_end (args);
|
|
||||||
Serial.print(serialBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
gw.begin(incomingMessage, 0, true, 0);
|
gw.begin(NULL
|
||||||
|
#ifdef MY_INCLUSION_MODE_FEATURE
|
||||||
|
, INCLUSION_MODE_TIME
|
||||||
|
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||||
|
, INCLUSION_MODE_PIN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output);
|
|
||||||
|
|
||||||
// Add interrupt for inclusion button to pin
|
|
||||||
PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING);
|
|
||||||
|
|
||||||
|
|
||||||
// Send startup log message on serial
|
|
||||||
serial(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
gw.process();
|
gw.process();
|
||||||
|
|
||||||
checkButtonTriggeredInclusion();
|
|
||||||
checkInclusionFinished();
|
|
||||||
|
|
||||||
if (commandComplete) {
|
|
||||||
// A command wass issued from serial interface
|
|
||||||
// We will now try to send it to the actuator
|
|
||||||
parseAndSend(gw, inputString);
|
|
||||||
commandComplete = false;
|
|
||||||
inputPos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
SerialEvent occurs whenever a new data comes in the
|
|
||||||
hardware serial RX. This routine is run between each
|
|
||||||
time loop() runs, so using delay inside loop can delay
|
|
||||||
response. Multiple bytes of data may be available.
|
|
||||||
*/
|
|
||||||
void serialEvent() {
|
|
||||||
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 && !commandComplete) {
|
|
||||||
if (inChar == '\n') {
|
|
||||||
inputString[inputPos] = 0;
|
|
||||||
commandComplete = true;
|
|
||||||
} else {
|
|
||||||
// add it to the inputString:
|
|
||||||
inputString[inputPos] = inChar;
|
|
||||||
inputPos++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Incoming message too long. Throw away
|
|
||||||
inputPos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user