Allow node to enter loop() if transport is NOK
This commit is contained in:
+8
-7
@@ -123,12 +123,6 @@
|
|||||||
*/
|
*/
|
||||||
//#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
|
//#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
|
||||||
|
|
||||||
/**
|
|
||||||
*@def MY_TRANSPORT_DONT_CARE_MODE
|
|
||||||
*@brief If set, transport traffic is unmonitored and GW connection is optional
|
|
||||||
*/
|
|
||||||
//#define MY_TRANSPORT_DONT_CARE_MODE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@def MY_TRANSPORT_MAX_TX_FAILURES
|
*@def MY_TRANSPORT_MAX_TX_FAILURES
|
||||||
*@brief Set to override max. consecutive TX failures until SNP is initiated
|
*@brief Set to override max. consecutive TX failures until SNP is initiated
|
||||||
@@ -167,6 +161,12 @@
|
|||||||
* @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data.
|
* @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data.
|
||||||
*/
|
*/
|
||||||
#define MY_CORE_COMPATIBILITY_CHECK
|
#define MY_CORE_COMPATIBILITY_CHECK
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def MY_TRANSPORT_RELAX
|
||||||
|
* @brief If enabled, node enters main loop() even if transport / connection to GW is not established
|
||||||
|
*/
|
||||||
|
//#define MY_TRANSPORT_RELAX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def MY_NODE_ID
|
* @def MY_NODE_ID
|
||||||
@@ -855,6 +855,8 @@
|
|||||||
#define MY_IS_RFM69HW
|
#define MY_IS_RFM69HW
|
||||||
#define MY_PARENT_NODE_IS_STATIC
|
#define MY_PARENT_NODE_IS_STATIC
|
||||||
#define MY_REGISTRATION_CONTROLLER
|
#define MY_REGISTRATION_CONTROLLER
|
||||||
|
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
|
||||||
|
#define MY_TRANSPORT_RELAX
|
||||||
#define MY_DEBUG_VERBOSE_RF24
|
#define MY_DEBUG_VERBOSE_RF24
|
||||||
#define MY_TRANSPORT_SANITY_CHECK
|
#define MY_TRANSPORT_SANITY_CHECK
|
||||||
#define MY_RF24_IRQ_PIN
|
#define MY_RF24_IRQ_PIN
|
||||||
@@ -862,7 +864,6 @@
|
|||||||
#define MY_RX_MESSAGE_BUFFER_SIZE
|
#define MY_RX_MESSAGE_BUFFER_SIZE
|
||||||
#define MY_NODE_LOCK_FEATURE
|
#define MY_NODE_LOCK_FEATURE
|
||||||
#define MY_REPEATER_FEATURE
|
#define MY_REPEATER_FEATURE
|
||||||
#define MY_TRANSPORT_DONT_CARE_MODE
|
|
||||||
#define MY_LINUX_SERIAL_GROUPNAME
|
#define MY_LINUX_SERIAL_GROUPNAME
|
||||||
#define MY_IS_SERIAL_PTY
|
#define MY_IS_SERIAL_PTY
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-20
@@ -239,26 +239,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_TRANSPORT_DONT_CARE_MODE) && !defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_TRANSPORT_DONT_CARE_MODE)
|
||||||
// enables transport don't care mode, i.e. transport link is not monitored and GW connection optional
|
#error This directive is deprecated, use MY_TRANSPORT_RELAX instead!
|
||||||
#if !defined(MY_PARENT_NODE_ID) || MY_PARENT_NODE_ID==255
|
|
||||||
#error MY_TRANSPORT_DONT_CARE_MODE requires MY_PARENT_NODE_ID set
|
|
||||||
#endif
|
|
||||||
#if !defined(MY_PARENT_NODE_IS_STATIC)
|
|
||||||
#define MY_PARENT_NODE_IS_STATIC
|
|
||||||
#endif
|
|
||||||
#ifdef MY_REGISTRATION_FEATURE
|
|
||||||
#undef MY_REGISTRATION_FEATURE
|
|
||||||
#endif
|
|
||||||
#ifdef MY_TRANSPORT_SANITY_CHECK
|
|
||||||
#undef MY_TRANSPORT_SANITY_CHECK
|
|
||||||
#endif
|
|
||||||
#ifndef MY_TRANSPORT_UPLINK_CHECK_DISABLED
|
|
||||||
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
|
|
||||||
#endif
|
|
||||||
#ifdef MY_REGISTRATION_FEATURE
|
|
||||||
#undef MY_REGISTRATION_FEATURE
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ extern bool transportSendRoute(MyMessage &message);
|
|||||||
// global variables
|
// global variables
|
||||||
extern MyMessage _msg;
|
extern MyMessage _msg;
|
||||||
extern MyMessage _msgTmp;
|
extern MyMessage _msgTmp;
|
||||||
extern NodeConfig _nc;
|
|
||||||
|
|
||||||
|
|
||||||
inline void gatewayTransportProcess() {
|
inline void gatewayTransportProcess() {
|
||||||
if (gatewayTransportAvailable()) {
|
if (gatewayTransportAvailable()) {
|
||||||
@@ -38,7 +36,7 @@ inline void gatewayTransportProcess() {
|
|||||||
_msgTmp = _msg;
|
_msgTmp = _msg;
|
||||||
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||||
mSetAck(_msgTmp, true);
|
mSetAck(_msgTmp, true);
|
||||||
_msgTmp.sender = _nc.nodeId;
|
_msgTmp.sender = getNodeId();
|
||||||
_msgTmp.destination = _msg.sender;
|
_msgTmp.destination = _msg.sender;
|
||||||
gatewayTransportSend(_msgTmp);
|
gatewayTransportSend(_msgTmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
// global variables
|
// global variables
|
||||||
extern MyMessage _msg;
|
extern MyMessage _msg;
|
||||||
extern MyMessage _msgTmp;
|
extern MyMessage _msgTmp;
|
||||||
extern NodeConfig _nc;
|
|
||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID);
|
SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID);
|
||||||
|
|||||||
+147
-94
@@ -6,7 +6,7 @@
|
|||||||
* network topology allowing messages to be routed to nodes.
|
* network topology allowing messages to be routed to nodes.
|
||||||
*
|
*
|
||||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
* Copyright (C) 2013-2015 Sensnology AB
|
* Copyright (C) 2013-2016 Sensnology AB
|
||||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
*
|
*
|
||||||
* Documentation: http://www.mysensors.org
|
* Documentation: http://www.mysensors.org
|
||||||
@@ -24,18 +24,34 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ControllerConfig _cc; // Configuration coming from controller
|
// message buffers
|
||||||
NodeConfig _nc; // Essential settings for node to work
|
|
||||||
MyMessage _msg; // Buffer for incoming messages
|
MyMessage _msg; // Buffer for incoming messages
|
||||||
MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others)
|
MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others)
|
||||||
|
|
||||||
bool _nodeRegistered = false;
|
// core configuration
|
||||||
|
coreConfig_t coreConfig;
|
||||||
|
|
||||||
#if defined(MY_DEBUG)
|
#if defined(MY_DEBUG)
|
||||||
char _convBuf[MAX_PAYLOAD*2+1];
|
char _convBuf[MAX_PAYLOAD*2+1];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void (*_timeCallback)(unsigned long); // Callback for requested time messages
|
// Callback for requested time messages
|
||||||
|
void (*_timeCallback)(unsigned long);
|
||||||
|
|
||||||
|
// Callback for transport=ok transition
|
||||||
|
void _callbackTransportOk()
|
||||||
|
{
|
||||||
|
if (!coreConfig.presentationSent) {
|
||||||
|
presentNode();
|
||||||
|
coreConfig.presentationSent = true;
|
||||||
|
}
|
||||||
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
|
if (!coreConfig.registrationRequested) {
|
||||||
|
_registerNode();
|
||||||
|
coreConfig.registrationRequested = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void _process(void) {
|
void _process(void) {
|
||||||
hwWatchdogReset();
|
hwWatchdogReset();
|
||||||
@@ -75,6 +91,7 @@ void _infiniteLoop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _begin(void) {
|
void _begin(void) {
|
||||||
|
// reset wdt
|
||||||
hwWatchdogReset();
|
hwWatchdogReset();
|
||||||
|
|
||||||
if (preHwInit) {
|
if (preHwInit) {
|
||||||
@@ -83,11 +100,15 @@ void _begin(void) {
|
|||||||
|
|
||||||
hwInit();
|
hwInit();
|
||||||
|
|
||||||
debug(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n"));
|
CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n"));
|
||||||
|
|
||||||
|
// set defaults
|
||||||
|
coreConfig.presentationSent = false;
|
||||||
|
coreConfig.registrationRequested = false;
|
||||||
|
|
||||||
// Call before() in sketch (if it exists)
|
// Call before() in sketch (if it exists)
|
||||||
if (before) {
|
if (before) {
|
||||||
debug(PSTR("MCO:BGN:BFR\n")); // before callback
|
CORE_DEBUG(PSTR("MCO:BGN:BFR\n")); // before callback
|
||||||
before();
|
before();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +120,7 @@ void _begin(void) {
|
|||||||
|
|
||||||
// Read latest received controller configuration from EEPROM
|
// Read latest received controller configuration from EEPROM
|
||||||
// Note: _cc.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default)
|
// Note: _cc.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default)
|
||||||
hwReadConfigBlock((void*)&_cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig));
|
hwReadConfigBlock((void*)&coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t));
|
||||||
|
|
||||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||||
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
|
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
|
||||||
@@ -109,42 +130,26 @@ void _begin(void) {
|
|||||||
#if defined(MY_SENSOR_NETWORK)
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
// Save static parent id in eeprom (used by bootloader)
|
// Save static parent id in eeprom (used by bootloader)
|
||||||
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID);
|
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID);
|
||||||
|
// Register for transport layer
|
||||||
|
transportRegisterTransportOkCallback(_callbackTransportOk);
|
||||||
|
|
||||||
|
// Initialise transport layer
|
||||||
transportInitialise();
|
transportInitialise();
|
||||||
while (!isTransportReady()) {
|
|
||||||
hwWatchdogReset();
|
#if !defined(MY_TRANSPORT_RELAX)
|
||||||
transportProcess();
|
// check if transport ready
|
||||||
yield();
|
while (!isTransportReady()) {
|
||||||
}
|
hwWatchdogReset();
|
||||||
#endif
|
transportProcess();
|
||||||
|
yield();
|
||||||
|
|
||||||
|
|
||||||
#ifdef MY_NODE_LOCK_FEATURE
|
|
||||||
// Check if node has been locked down
|
|
||||||
if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0) {
|
|
||||||
// Node is locked, check if unlock pin is asserted, else hang the node
|
|
||||||
pinMode(MY_NODE_UNLOCK_PIN, INPUT_PULLUP);
|
|
||||||
// Make a short delay so we are sure any large external nets are fully pulled
|
|
||||||
unsigned long enter = hwMillis();
|
|
||||||
while (hwMillis() - enter < 2) {}
|
|
||||||
if (digitalRead(MY_NODE_UNLOCK_PIN) == 0) {
|
|
||||||
// Pin is grounded, reset lock counter
|
|
||||||
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
|
||||||
// Disable pullup
|
|
||||||
pinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
|
||||||
setIndication(INDICATION_ERR_LOCKED);
|
|
||||||
debug(PSTR("MCO:BGN:NODE UNLOCKED\n"));
|
|
||||||
} else {
|
|
||||||
// Disable pullup
|
|
||||||
pinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
|
||||||
nodeLock("LDB"); //Locked during boot
|
|
||||||
}
|
}
|
||||||
} else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
|
#else
|
||||||
// Reset walue
|
CORE_DEBUG(PSTR("MCO:BGN:MTR\n"));
|
||||||
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
#endif
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
_checkNodeLock();
|
||||||
|
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
#if defined(MY_INCLUSION_BUTTON_FEATURE)
|
#if defined(MY_INCLUSION_BUTTON_FEATURE)
|
||||||
inclusionInit();
|
inclusionInit();
|
||||||
@@ -153,46 +158,40 @@ void _begin(void) {
|
|||||||
// initialise the transport driver
|
// initialise the transport driver
|
||||||
if (!gatewayTransportInit()) {
|
if (!gatewayTransportInit()) {
|
||||||
setIndication(INDICATION_ERR_INIT_GWTRANSPORT);
|
setIndication(INDICATION_ERR_INIT_GWTRANSPORT);
|
||||||
debug(PSTR("!MCO:BGN:TSP FAIL\n"));
|
CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n"));
|
||||||
// Nothing more we can do
|
// Nothing more we can do
|
||||||
_infiniteLoop();
|
_infiniteLoop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
|
||||||
presentNode();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// register node
|
|
||||||
_registerNode();
|
|
||||||
|
|
||||||
// Call sketch setup
|
// Call sketch setup
|
||||||
if (setup) {
|
if (setup) {
|
||||||
debug(PSTR("MCO:BGN:STP\n")); // setup callback
|
CORE_DEBUG(PSTR("MCO:BGN:STP\n")); // setup callback
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(PSTR("MCO:BGN:INIT OK,ID=%d,PAR=%d,DIS=%d,REG=%d\n"), _nc.nodeId, _nc.parentNodeId, _nc.distance, _nodeRegistered);
|
CORE_DEBUG(PSTR("MCO:BGN:INIT OK,TSP=%d\n"), isTransportReady());
|
||||||
|
|
||||||
|
// reset wdt before handing over to loop
|
||||||
hwWatchdogReset();
|
hwWatchdogReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _registerNode(void) {
|
void _registerNode(void)
|
||||||
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
{
|
||||||
debug(PSTR("MCO:REG:REQ\n")); // registration request
|
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
||||||
setIndication(INDICATION_REQ_REGISTRATION);
|
CORE_DEBUG(PSTR("MCO:REG:REQ\n")); // registration request
|
||||||
_nodeRegistered = MY_REGISTRATION_DEFAULT;
|
setIndication(INDICATION_REQ_REGISTRATION);
|
||||||
uint8_t counter = MY_REGISTRATION_RETRIES;
|
coreConfig.registered = MY_REGISTRATION_DEFAULT;
|
||||||
// only proceed if register response received or retries exceeded
|
uint8_t counter = MY_REGISTRATION_RETRIES;
|
||||||
do {
|
// only proceed if register response received or retries exceeded
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
|
do {
|
||||||
} while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--);
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
|
||||||
|
} while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--);
|
||||||
#else
|
#else
|
||||||
_nodeRegistered = true;
|
coreConfig.registered = true;
|
||||||
debug(PSTR("MCO:REG:NOT NEEDED\n"));
|
CORE_DEBUG(PSTR("MCO:REG:NOT NEEDED\n"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void presentNode(void) {
|
void presentNode(void) {
|
||||||
@@ -223,7 +222,7 @@ void presentNode(void) {
|
|||||||
|
|
||||||
// Send a configuration exchange request to controller
|
// Send a configuration exchange request to controller
|
||||||
// Node sends parent node. Controller answers with latest node configuration
|
// Node sends parent node. Controller answers with latest node configuration
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(_nc.parentNodeId));
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(getParentNodeId()));
|
||||||
|
|
||||||
// Wait configuration reply.
|
// Wait configuration reply.
|
||||||
(void)wait(2000, C_INTERNAL, I_CONFIG);
|
(void)wait(2000, C_INTERNAL, I_CONFIG);
|
||||||
@@ -236,16 +235,35 @@ void presentNode(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t getNodeId(void) {
|
uint8_t getNodeId(void)
|
||||||
return _nc.nodeId;
|
{
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
return transportGetNodeId();
|
||||||
|
#else
|
||||||
|
return 0xFF;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getParentNodeId(void) {
|
uint8_t getParentNodeId(void)
|
||||||
return _nc.parentNodeId;
|
{
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
return transportGetParentNodeId();
|
||||||
|
#else
|
||||||
|
return 0xFF;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerConfig getConfig(void) {
|
uint8_t getDistanceGW(void)
|
||||||
return _cc;
|
{
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
return transportGetDistanceGW();
|
||||||
|
#else
|
||||||
|
return 0xFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
controllerConfig_t getConfig(void) {
|
||||||
|
return coreConfig.controllerConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -254,7 +272,7 @@ bool _sendRoute(MyMessage &message) {
|
|||||||
(void)message;
|
(void)message;
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
if (message.destination == _nc.nodeId) {
|
if (message.destination == getNodeId()) {
|
||||||
// This is a message sent from a sensor attached on the gateway node.
|
// This is a message sent from a sensor attached on the gateway node.
|
||||||
// Pass it directly to the gateway transport layer.
|
// Pass it directly to the gateway transport layer.
|
||||||
return gatewayTransportSend(message);
|
return gatewayTransportSend(message);
|
||||||
@@ -268,16 +286,16 @@ bool _sendRoute(MyMessage &message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool send(MyMessage &message, const bool enableAck) {
|
bool send(MyMessage &message, const bool enableAck) {
|
||||||
message.sender = _nc.nodeId;
|
message.sender = getNodeId();
|
||||||
mSetCommand(message, C_SET);
|
mSetCommand(message, C_SET);
|
||||||
mSetRequestAck(message, enableAck);
|
mSetRequestAck(message, enableAck);
|
||||||
|
|
||||||
#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
||||||
if (_nodeRegistered) {
|
if (coreConfig.registered) {
|
||||||
return _sendRoute(message);
|
return _sendRoute(message);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
debug(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
|
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -308,7 +326,7 @@ bool sendSketchInfo(const char *name, const char *version, const bool ack) {
|
|||||||
if (name) {
|
if (name) {
|
||||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name));
|
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name));
|
||||||
}
|
}
|
||||||
if (version) {
|
if (version) {
|
||||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version));
|
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -336,15 +354,15 @@ bool _processInternalMessages(void) {
|
|||||||
}
|
}
|
||||||
else if (type == I_REGISTRATION_RESPONSE) {
|
else if (type == I_REGISTRATION_RESPONSE) {
|
||||||
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
||||||
_nodeRegistered = _msg.getBool();
|
coreConfig.registered = _msg.getBool();
|
||||||
setIndication(INDICATION_GOT_REGISTRATION);
|
setIndication(INDICATION_GOT_REGISTRATION);
|
||||||
debug(PSTR("MCO:PIM:NODE REG=%d\n"), _nodeRegistered); // node registration
|
CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), coreConfig.registered); // node registration
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (type == I_CONFIG) {
|
else if (type == I_CONFIG) {
|
||||||
// Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed
|
// Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed
|
||||||
_cc.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M
|
coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M
|
||||||
hwWriteConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, _cc.isMetric);
|
hwWriteConfigBlock((void*)&coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t));
|
||||||
}
|
}
|
||||||
else if (type == I_PRESENTATION) {
|
else if (type == I_PRESENTATION) {
|
||||||
// Re-send node presentation to controller
|
// Re-send node presentation to controller
|
||||||
@@ -377,7 +395,7 @@ bool _processInternalMessages(void) {
|
|||||||
for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) {
|
for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) {
|
||||||
const uint8_t route = transportGetRoute(cnt);
|
const uint8_t route = transportGetRoute(cnt);
|
||||||
if (route != BROADCAST_ADDRESS) {
|
if (route != BROADCAST_ADDRESS) {
|
||||||
debug(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
|
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
|
||||||
uint8_t outBuf[2] = { (uint8_t)cnt,route };
|
uint8_t outBuf[2] = { (uint8_t)cnt,route };
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2));
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2));
|
||||||
wait(200);
|
wait(200);
|
||||||
@@ -465,11 +483,11 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgtype) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) {
|
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) {
|
||||||
debug(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
|
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
|
||||||
// OTA FW feature: do not sleep if FW update ongoing
|
// OTA FW feature: do not sleep if FW update ongoing
|
||||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||||
if (_fwUpdateOngoing) {
|
if (_fwUpdateOngoing) {
|
||||||
debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing
|
CORE_DEBUG(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing
|
||||||
wait(sleepingMS);
|
wait(sleepingMS);
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
}
|
}
|
||||||
@@ -482,7 +500,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
|||||||
(void)interrupt2;
|
(void)interrupt2;
|
||||||
(void)mode2;
|
(void)mode2;
|
||||||
|
|
||||||
debug(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled
|
CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled
|
||||||
wait(sleepingMS);
|
wait(sleepingMS);
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
#else
|
#else
|
||||||
@@ -490,7 +508,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
|||||||
#if defined(MY_SENSOR_NETWORK)
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
// Do not sleep if transport not ready
|
// Do not sleep if transport not ready
|
||||||
if (!isTransportReady()) {
|
if (!isTransportReady()) {
|
||||||
debug(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
|
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
|
||||||
const uint32_t sleepEnterMS = hwMillis();
|
const uint32_t sleepEnterMS = hwMillis();
|
||||||
uint32_t sleepDeltaMS = 0;
|
uint32_t sleepDeltaMS = 0;
|
||||||
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
||||||
@@ -501,7 +519,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
|||||||
// sleep remainder
|
// sleep remainder
|
||||||
if (sleepDeltaMS < sleepingTimeMS) {
|
if (sleepDeltaMS < sleepingTimeMS) {
|
||||||
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
|
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
|
||||||
debug(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
|
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// no sleeping time left
|
// no sleeping time left
|
||||||
@@ -517,7 +535,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
debug(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport
|
CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport
|
||||||
transportPowerDown();
|
transportPowerDown();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -539,7 +557,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIndication(INDICATION_WAKEUP);
|
setIndication(INDICATION_WAKEUP);
|
||||||
debug(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up
|
CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -574,22 +592,57 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _nodeLock(const char* str)
|
||||||
|
{
|
||||||
#ifdef MY_NODE_LOCK_FEATURE
|
#ifdef MY_NODE_LOCK_FEATURE
|
||||||
void nodeLock(const char* str) {
|
|
||||||
// Make sure EEPROM is updated to locked status
|
// Make sure EEPROM is updated to locked status
|
||||||
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, 0);
|
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, 0);
|
||||||
while (1) {
|
while (1) {
|
||||||
setIndication(INDICATION_ERR_LOCKED);
|
setIndication(INDICATION_ERR_LOCKED);
|
||||||
debug(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %d AND RESET\n"), MY_NODE_UNLOCK_PIN);
|
CORE_DEBUG(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %d AND RESET\n"), MY_NODE_UNLOCK_PIN);
|
||||||
yield();
|
yield();
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str));
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str));
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
transportPowerDown();
|
transportPowerDown();
|
||||||
debug(PSTR("MCO:NLK:TPD\n")); // power down transport
|
CORE_DEBUG(PSTR("MCO:NLK:TPD\n")); // power down transport
|
||||||
#endif
|
#endif
|
||||||
setIndication(INDICATION_SLEEP);
|
setIndication(INDICATION_SLEEP);
|
||||||
(void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message
|
(void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message
|
||||||
setIndication(INDICATION_WAKEUP);
|
setIndication(INDICATION_WAKEUP);
|
||||||
}
|
}
|
||||||
}
|
#else
|
||||||
|
(void)str;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkNodeLock(void)
|
||||||
|
{
|
||||||
|
#ifdef MY_NODE_LOCK_FEATURE
|
||||||
|
// Check if node has been locked down
|
||||||
|
if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0) {
|
||||||
|
// Node is locked, check if unlock pin is asserted, else hang the node
|
||||||
|
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT_PULLUP);
|
||||||
|
// Make a short delay so we are sure any large external nets are fully pulled
|
||||||
|
unsigned long enter = hwMillis();
|
||||||
|
while (hwMillis() - enter < 2) {}
|
||||||
|
if (hwDigitalRead(MY_NODE_UNLOCK_PIN) == 0) {
|
||||||
|
// Pin is grounded, reset lock counter
|
||||||
|
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
||||||
|
// Disable pullup
|
||||||
|
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
||||||
|
setIndication(INDICATION_ERR_LOCKED);
|
||||||
|
CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Disable pullup
|
||||||
|
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
||||||
|
_nodeLock("LDB"); //Locked during boot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
|
||||||
|
// Reset walue
|
||||||
|
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
+32
-29
@@ -41,8 +41,9 @@
|
|||||||
* |-|------|-------|-----------------------------------------------|----------------------------------------------------------------------------
|
* |-|------|-------|-----------------------------------------------|----------------------------------------------------------------------------
|
||||||
* | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER)
|
* | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER)
|
||||||
* | | MCO | BGN | BFR | Callback before()
|
* | | MCO | BGN | BFR | Callback before()
|
||||||
|
* | | MCO | BGN | MTR | MY_TRANSPORT_RELAX enabled
|
||||||
* | | MCO | BGN | STP | Callback setup()
|
* | | MCO | BGN | STP | Callback setup()
|
||||||
* | | MCO | BGN | INIT OK,ID=%%d,PAR=%%d,DIS=%%d,REG=%%d | Core initialized, parent ID (PAR), distance to GW (DIS), registration (REG)
|
* | | MCO | BGN | INIT OK,TSP=%%d | Core initialised, transport status (TSP), 1=initialised, 0=not initialised
|
||||||
* | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter)
|
* | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter)
|
||||||
* |!| MCO | BGN | TSP FAIL | Transport initialization failed
|
* |!| MCO | BGN | TSP FAIL | Transport initialization failed
|
||||||
* | | MCO | REG | REQ | Registration request
|
* | | MCO | REG | REQ | Registration request
|
||||||
@@ -85,37 +86,36 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef MY_DEBUG
|
#ifdef MY_DEBUG
|
||||||
#define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
|
#define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug, to be removed (follow-up PR)
|
||||||
|
#define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
|
||||||
#else
|
#else
|
||||||
#define debug(x,...) //!< debug NULL
|
#define debug(x,...) //!< debug NULL, to be removed (follow-up PR)
|
||||||
|
#define CORE_DEBUG(x,...) //!< debug NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Node configuration
|
|
||||||
*
|
|
||||||
* This structure stores node-related configurations
|
|
||||||
*/
|
|
||||||
struct NodeConfig {
|
|
||||||
uint8_t nodeId; //!< Current node id
|
|
||||||
uint8_t parentNodeId; //!< Where this node sends its messages
|
|
||||||
uint8_t distance; //!< This nodes distance to sensor net gateway (number of hops)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Controller configuration
|
* @brief Controller configuration
|
||||||
*
|
*
|
||||||
* This structure stores controllerrelated configurations
|
* This structure stores controller-related configurations
|
||||||
*/
|
*/
|
||||||
struct ControllerConfig {
|
typedef struct {
|
||||||
uint8_t isMetric; //!< Flag indicating if metric or imperial measurements are used
|
uint8_t isMetric; //!< Flag indicating if metric or imperial measurements are used
|
||||||
};
|
} controllerConfig_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Node core configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
controllerConfig_t controllerConfig; //!< Controller config
|
||||||
|
// 8 bit
|
||||||
|
bool registered : 1; //!< Flag node registered
|
||||||
|
bool presentationSent : 1; //!< Flag presentation sent
|
||||||
|
bool registrationRequested : 1; //!< Flag registration requested
|
||||||
|
uint8_t reserved : 5; //!< reserved
|
||||||
|
} coreConfig_t;
|
||||||
|
|
||||||
extern NodeConfig _nc; //!< Node config
|
|
||||||
extern MyMessage _msg; //!< Buffer for incoming messages
|
|
||||||
extern MyMessage _msgTmp; //!< Buffer for temporary messages (acks and nonces among others)
|
|
||||||
#ifdef MY_DEBUG
|
|
||||||
extern char _convBuf[MAX_PAYLOAD * 2 + 1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// **** public functions ********
|
// **** public functions ********
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ bool requestTime(const bool ack = false);
|
|||||||
/**
|
/**
|
||||||
* Returns the most recent node configuration received from controller
|
* Returns the most recent node configuration received from controller
|
||||||
*/
|
*/
|
||||||
ControllerConfig getConfig(void);
|
controllerConfig_t getControllerConfig(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a state (in local EEPROM). Good for actuators to "remember" state between
|
* Save a state (in local EEPROM). Good for actuators to "remember" state between
|
||||||
@@ -328,20 +328,23 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i
|
|||||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
|
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
|
||||||
|
|
||||||
|
|
||||||
#ifdef MY_NODE_LOCK_FEATURE
|
|
||||||
/**
|
/**
|
||||||
* @ingroup MyLockgrp
|
* @ingroup MyLockgrp
|
||||||
* @ingroup internals
|
* @ingroup internals
|
||||||
* @brief Lock a node and transmit provided message with 30m intervals
|
* @brief Lock a node and transmit provided message with 30m intervals
|
||||||
*
|
*
|
||||||
* This function is called if suspicious activity has exceeded the threshold (see
|
* This function is called if suspicious activity has exceeded the threshold (see
|
||||||
* @ref ATTACK_COUNTER_MAX). Unlocking with a normal Arduino bootloader require erasing the EEPROM
|
* @ref MY_NODE_LOCK_COUNTER_MAX). Unlocking with a normal Arduino bootloader require erasing the EEPROM
|
||||||
* while unlocking with a custom bootloader require holding @ref UNLOCK_PIN low during power on/reset.
|
* while unlocking with a custom bootloader require holding @ref MY_NODE_UNLOCK_PIN low during power on/reset.
|
||||||
*
|
*
|
||||||
* @param str The string to transmit.
|
* @param str The string to transmit.
|
||||||
*/
|
*/
|
||||||
void nodeLock(const char* str);
|
void _nodeLock(const char* str);
|
||||||
#endif
|
|
||||||
|
/**
|
||||||
|
* @brief Check node lock status and prevent node execution if locked.
|
||||||
|
*/
|
||||||
|
void _checkNodeLock(void);
|
||||||
|
|
||||||
// **** private functions ********
|
// **** private functions ********
|
||||||
|
|
||||||
@@ -406,7 +409,7 @@ void loop(void) __attribute__((weak));
|
|||||||
|
|
||||||
// Inline function and macros
|
// Inline function and macros
|
||||||
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) {
|
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) {
|
||||||
msg.sender = _nc.nodeId;
|
msg.sender = getNodeId();
|
||||||
msg.destination = destination;
|
msg.destination = destination;
|
||||||
msg.sensor = sensor;
|
msg.sensor = sensor;
|
||||||
msg.type = type;
|
msg.type = type;
|
||||||
|
|||||||
+6
-6
@@ -185,7 +185,7 @@ bool signerProcessInternal(MyMessage &msg) {
|
|||||||
nof_nonce_requests++;
|
nof_nonce_requests++;
|
||||||
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
||||||
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
|
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
|
||||||
nodeLock("TMNR"); //Too many nonces requested
|
_nodeLock("TMNR"); //Too many nonces requested
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_SOFT)
|
#if defined(MY_SIGNING_SOFT)
|
||||||
@@ -317,7 +317,7 @@ bool signerSignMsg(MyMessage &msg) {
|
|||||||
#if defined(MY_SIGNING_FEATURE)
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
// If destination is known to require signed messages and we are the sender,
|
// If destination is known to require signed messages and we are the sender,
|
||||||
// sign this message unless it is a handshake message
|
// sign this message unless it is a handshake message
|
||||||
if (DO_SIGN(msg.destination) && msg.sender == _nc.nodeId) {
|
if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) {
|
||||||
if (skipSign(msg)) {
|
if (skipSign(msg)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -350,7 +350,7 @@ bool signerSignMsg(MyMessage &msg) {
|
|||||||
// After this point, only the 'last' member of the message structure is allowed to be altered if the
|
// After this point, only the 'last' member of the message structure is allowed to be altered if the
|
||||||
// message has been signed, or signature will become invalid and the message rejected by the receiver
|
// message has been signed, or signature will become invalid and the message rejected by the receiver
|
||||||
}
|
}
|
||||||
} else if (_nc.nodeId == msg.sender) {
|
} else if (getNodeId() == msg.sender) {
|
||||||
mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned
|
mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -368,9 +368,9 @@ bool signerVerifyMsg(MyMessage &msg) {
|
|||||||
// If we are a node, or we are a gateway and the sender require signatures (or just a strict gw)
|
// If we are a node, or we are a gateway and the sender require signatures (or just a strict gw)
|
||||||
// and we are the destination...
|
// and we are the destination...
|
||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||||
if (msg.destination == _nc.nodeId) {
|
if (msg.destination == getNodeId()) {
|
||||||
#else
|
#else
|
||||||
if ((!MY_IS_GATEWAY || DO_SIGN(msg.sender)) && msg.destination == _nc.nodeId) {
|
if ((!MY_IS_GATEWAY || DO_SIGN(msg.sender)) && msg.destination == getNodeId()) {
|
||||||
#endif
|
#endif
|
||||||
// Internal messages of certain types are not verified
|
// Internal messages of certain types are not verified
|
||||||
if (skipSign(msg)) {
|
if (skipSign(msg)) {
|
||||||
@@ -399,7 +399,7 @@ bool signerVerifyMsg(MyMessage &msg) {
|
|||||||
nof_failed_verifications++;
|
nof_failed_verifications++;
|
||||||
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
|
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
|
||||||
if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
|
if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
|
||||||
nodeLock("TMFV"); //Too many failed verifications
|
_nodeLock("TMFV"); //Too many failed verifications
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+80
-54
@@ -20,20 +20,25 @@
|
|||||||
#include "MyTransport.h"
|
#include "MyTransport.h"
|
||||||
|
|
||||||
// SM: transitions and update states
|
// SM: transitions and update states
|
||||||
static transportState stInit = { stInitTransition, stInitUpdate };
|
static transportState_t stInit = { stInitTransition, stInitUpdate };
|
||||||
static transportState stParent = { stParentTransition, stParentUpdate };
|
static transportState_t stParent = { stParentTransition, stParentUpdate };
|
||||||
static transportState stID = { stIDTransition, stIDUpdate };
|
static transportState_t stID = { stIDTransition, stIDUpdate };
|
||||||
static transportState stUplink = { stUplinkTransition, stUplinkUpdate };
|
static transportState_t stUplink = { stUplinkTransition, stUplinkUpdate };
|
||||||
static transportState stReady = { stReadyTransition, stReadyUpdate };
|
static transportState_t stReady = { stReadyTransition, stReadyUpdate };
|
||||||
static transportState stFailure = { stFailureTransition, stFailureUpdate };
|
static transportState_t stFailure = { stFailureTransition, stFailureUpdate };
|
||||||
|
|
||||||
// transport SM variables
|
// transport SM variables
|
||||||
static transportSM _transportSM;
|
static transportSM_t _transportSM;
|
||||||
|
|
||||||
|
// transport config
|
||||||
|
transportConfig_t transportConfig;
|
||||||
|
|
||||||
|
// callbacks
|
||||||
|
transportCallback_t transportOk_cb = NULL;
|
||||||
|
|
||||||
// global variables
|
// global variables
|
||||||
extern MyMessage _msg; // incoming message
|
extern MyMessage _msg; // incoming message
|
||||||
extern MyMessage _msgTmp; // outgoing message
|
extern MyMessage _msgTmp; // outgoing message
|
||||||
extern NodeConfig _nc; // node config
|
|
||||||
|
|
||||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||||
static routingTable _transportRoutingTable; //!< routing table
|
static routingTable _transportRoutingTable; //!< routing table
|
||||||
@@ -70,13 +75,10 @@ void stInitTransition(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Read node settings (ID, parent ID, GW distance) from EEPROM
|
// Read node settings (ID, parent ID, GW distance) from EEPROM
|
||||||
hwReadConfigBlock((void*)&_nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig));
|
hwReadConfigBlock((void*)&transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(transportConfig_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void stInitUpdate(void) {
|
void stInitUpdate(void) {
|
||||||
#if defined(MY_TRANSPORT_DONT_CARE_MODE)
|
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:TDC\n")); // transport don't care mode
|
|
||||||
#endif
|
|
||||||
// initialise radio
|
// initialise radio
|
||||||
if (!transportInit()) {
|
if (!transportInit()) {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n"));
|
TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n"));
|
||||||
@@ -89,9 +91,9 @@ void stInitUpdate(void) {
|
|||||||
#if defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
// Set configuration for gateway
|
// Set configuration for gateway
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n"));
|
TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n"));
|
||||||
_nc.parentNodeId = GATEWAY_ADDRESS;
|
transportConfig.parentNodeId = GATEWAY_ADDRESS;
|
||||||
_nc.distance = 0u;
|
transportConfig.distanceGW = 0u;
|
||||||
_nc.nodeId = GATEWAY_ADDRESS;
|
transportConfig.nodeId = GATEWAY_ADDRESS;
|
||||||
transportSetAddress(GATEWAY_ADDRESS);
|
transportSetAddress(GATEWAY_ADDRESS);
|
||||||
// GW mode: skip FPAR,ID,UPL states
|
// GW mode: skip FPAR,ID,UPL states
|
||||||
transportSwitchSM(stReady);
|
transportSwitchSM(stReady);
|
||||||
@@ -99,12 +101,12 @@ void stInitUpdate(void) {
|
|||||||
if ((uint8_t)MY_NODE_ID != AUTO) {
|
if ((uint8_t)MY_NODE_ID != AUTO) {
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%d\n"),(uint8_t)MY_NODE_ID);
|
TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%d\n"),(uint8_t)MY_NODE_ID);
|
||||||
// Set static ID
|
// Set static ID
|
||||||
_nc.nodeId = (uint8_t)MY_NODE_ID;
|
transportConfig.nodeId = (uint8_t)MY_NODE_ID;
|
||||||
// Save static ID to eeprom (for bootloader)
|
// Save static ID to eeprom (for bootloader)
|
||||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID);
|
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID);
|
||||||
}
|
}
|
||||||
// assign ID if set
|
// assign ID if set
|
||||||
if (_nc.nodeId == AUTO || transportAssignNodeID(_nc.nodeId)) {
|
if (transportConfig.nodeId == AUTO || transportAssignNodeID(transportConfig.nodeId)) {
|
||||||
// if node ID valid (>0 and <255), proceed to next state
|
// if node ID valid (>0 and <255), proceed to next state
|
||||||
transportSwitchSM(stParent);
|
transportSwitchSM(stParent);
|
||||||
}
|
}
|
||||||
@@ -125,14 +127,14 @@ void stParentTransition(void) {
|
|||||||
#if defined(MY_PARENT_NODE_IS_STATIC)
|
#if defined(MY_PARENT_NODE_IS_STATIC)
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%d\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent
|
TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%d\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent
|
||||||
_transportSM.findingParentNode = false;
|
_transportSM.findingParentNode = false;
|
||||||
_nc.distance = 1u; // assumption, CHKUPL:GWDC will update this variable
|
transportConfig.distanceGW = 1u; // assumption, CHKUPL:GWDC will update this variable
|
||||||
_nc.parentNodeId = (uint8_t)MY_PARENT_NODE_ID;
|
transportConfig.parentNodeId = (uint8_t)MY_PARENT_NODE_ID;
|
||||||
// save parent ID to eeprom (for bootloader)
|
// save parent ID to eeprom (for bootloader)
|
||||||
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID);
|
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID);
|
||||||
#else
|
#else
|
||||||
_transportSM.findingParentNode = true;
|
_transportSM.findingParentNode = true;
|
||||||
_nc.distance = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
|
transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
|
||||||
_nc.parentNodeId = AUTO;
|
transportConfig.parentNodeId = AUTO;
|
||||||
// Broadcast find parent request
|
// Broadcast find parent request
|
||||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set(""));
|
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set(""));
|
||||||
#endif
|
#endif
|
||||||
@@ -147,7 +149,7 @@ void stParentUpdate(void) {
|
|||||||
#else
|
#else
|
||||||
if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) {
|
if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) {
|
||||||
// timeout or preferred parent found
|
// timeout or preferred parent found
|
||||||
if (_nc.parentNodeId != AUTO) {
|
if (transportConfig.parentNodeId != AUTO) {
|
||||||
// parent assigned
|
// parent assigned
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok
|
TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok
|
||||||
_transportSM.findingParentNode = false;
|
_transportSM.findingParentNode = false;
|
||||||
@@ -177,7 +179,7 @@ void stParentUpdate(void) {
|
|||||||
// stID: verify and request ID if necessary
|
// stID: verify and request ID if necessary
|
||||||
void stIDTransition(void) {
|
void stIDTransition(void) {
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID
|
TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID
|
||||||
if (_nc.nodeId == AUTO) {
|
if (transportConfig.nodeId == AUTO) {
|
||||||
// send ID request
|
// send ID request
|
||||||
setIndication(INDICATION_REQ_NODEID);
|
setIndication(INDICATION_REQ_NODEID);
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID
|
TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID
|
||||||
@@ -186,7 +188,7 @@ void stIDTransition(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stIDUpdate(void) {
|
void stIDUpdate(void) {
|
||||||
if (_nc.nodeId != AUTO) {
|
if (transportConfig.nodeId != AUTO) {
|
||||||
// current node ID is valid
|
// current node ID is valid
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n"));
|
TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n"));
|
||||||
setIndication(INDICATION_GOT_NODEID);
|
setIndication(INDICATION_GOT_NODEID);
|
||||||
@@ -225,9 +227,9 @@ void stUplinkUpdate(void) {
|
|||||||
// uplink ok, i.e. GW replied
|
// uplink ok, i.e. GW replied
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok
|
TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok
|
||||||
//_transportSM.pingActive = false; ==> set false upon receiving I_PONG
|
//_transportSM.pingActive = false; ==> set false upon receiving I_PONG
|
||||||
if (_transportSM.pingResponse != _nc.distance) {
|
if (_transportSM.pingResponse != transportConfig.distanceGW) {
|
||||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _nc.distance, _transportSM.pingResponse); // distance to GW changed
|
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), transportConfig.distanceGW, _transportSM.pingResponse); // distance to GW changed
|
||||||
_nc.distance = _transportSM.pingResponse;
|
transportConfig.distanceGW = _transportSM.pingResponse;
|
||||||
}
|
}
|
||||||
transportSwitchSM(stReady); // proceed to next state
|
transportSwitchSM(stReady); // proceed to next state
|
||||||
}
|
}
|
||||||
@@ -257,6 +259,11 @@ void stReadyTransition(void) {
|
|||||||
_transportSM.uplinkOk = true;
|
_transportSM.uplinkOk = true;
|
||||||
_transportSM.failureCounter = 0u; // reset failure counter
|
_transportSM.failureCounter = 0u; // reset failure counter
|
||||||
_transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter
|
_transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter
|
||||||
|
// callback
|
||||||
|
if (transportOk_cb) {
|
||||||
|
transportOk_cb();
|
||||||
|
}
|
||||||
|
TRANSPORT_DEBUG(PSTR("TSM:READY:PARAM,ID=%d,PAR=%d,DIS=%d\n"), transportConfig.nodeId, transportConfig.parentNodeId, transportConfig.distanceGW);
|
||||||
}
|
}
|
||||||
|
|
||||||
// stReadyUpdate: monitors link
|
// stReadyUpdate: monitors link
|
||||||
@@ -311,7 +318,7 @@ void stFailureUpdate(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transportSwitchSM(transportState& newState) {
|
void transportSwitchSM(transportState_t& newState) {
|
||||||
if (_transportSM.currentState != &newState) {
|
if (_transportSM.currentState != &newState) {
|
||||||
_transportSM.stateRetries = 0u; // state change, reset retry counter
|
_transportSM.stateRetries = 0u; // state change, reset retry counter
|
||||||
_transportSM.currentState = &newState; // change state
|
_transportSM.currentState = &newState; // change state
|
||||||
@@ -386,9 +393,9 @@ bool transportCheckUplink(const bool force) {
|
|||||||
_transportSM.lastUplinkCheck = hwMillis();
|
_transportSM.lastUplinkCheck = hwMillis();
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n"));
|
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n"));
|
||||||
// did distance to GW change upstream, eg. re-routing of uplink nodes
|
// did distance to GW change upstream, eg. re-routing of uplink nodes
|
||||||
if (hopsCount != _nc.distance) {
|
if (hopsCount != transportConfig.distanceGW) {
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _nc.distance, hopsCount); // distance to GW changed
|
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), transportConfig.distanceGW, hopsCount); // distance to GW changed
|
||||||
_nc.distance = hopsCount;
|
transportConfig.distanceGW = hopsCount;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -401,7 +408,7 @@ bool transportCheckUplink(const bool force) {
|
|||||||
bool transportAssignNodeID(const uint8_t newNodeId) {
|
bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||||
// verify if ID valid
|
// verify if ID valid
|
||||||
if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) {
|
if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) {
|
||||||
_nc.nodeId = newNodeId;
|
transportConfig.nodeId = newNodeId;
|
||||||
transportSetAddress(newNodeId);
|
transportSetAddress(newNodeId);
|
||||||
// Write ID to EEPROM
|
// Write ID to EEPROM
|
||||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId);
|
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId);
|
||||||
@@ -411,14 +418,14 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
|
|||||||
else {
|
else {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID
|
TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID
|
||||||
setIndication(INDICATION_ERR_NET_FULL);
|
setIndication(INDICATION_ERR_NET_FULL);
|
||||||
_nc.nodeId = AUTO;
|
transportConfig.nodeId = AUTO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transportRouteMessage(MyMessage &message) {
|
bool transportRouteMessage(MyMessage &message) {
|
||||||
const uint8_t destination = message.destination;
|
const uint8_t destination = message.destination;
|
||||||
uint8_t route = _nc.parentNodeId; // by default, all traffic is routed via parent node
|
uint8_t route = transportConfig.parentNodeId; // by default, all traffic is routed via parent node
|
||||||
|
|
||||||
if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) {
|
if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent
|
TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent
|
||||||
@@ -427,7 +434,7 @@ bool transportRouteMessage(MyMessage &message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (destination == GATEWAY_ADDRESS) {
|
if (destination == GATEWAY_ADDRESS) {
|
||||||
route = _nc.parentNodeId; // message to GW always routes via parent
|
route = transportConfig.parentNodeId; // message to GW always routes via parent
|
||||||
}
|
}
|
||||||
else if (destination == BROADCAST_ADDRESS) {
|
else if (destination == BROADCAST_ADDRESS) {
|
||||||
route = BROADCAST_ADDRESS; // message to BC does not require routing
|
route = BROADCAST_ADDRESS; // message to BC does not require routing
|
||||||
@@ -439,9 +446,9 @@ bool transportRouteMessage(MyMessage &message) {
|
|||||||
if (route == AUTO) {
|
if (route == AUTO) {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:RTE:%d UNKNOWN\n"), destination); // route unknown
|
TRANSPORT_DEBUG(PSTR("!TSF:RTE:%d UNKNOWN\n"), destination); // route unknown
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
if (message.last != _nc.parentNodeId) {
|
if (message.last != transportConfig.parentNodeId) {
|
||||||
// message not from parent, i.e. child node - route it to parent
|
// message not from parent, i.e. child node - route it to parent
|
||||||
route = _nc.parentNodeId;
|
route = transportConfig.parentNodeId;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// route unknown and msg received from parent, send it to destination assuming in rx radius
|
// route unknown and msg received from parent, send it to destination assuming in rx radius
|
||||||
@@ -453,14 +460,14 @@ bool transportRouteMessage(MyMessage &message) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
route = _nc.parentNodeId; // not a repeater, all traffic routed via parent
|
route = transportConfig.parentNodeId; // not a repeater, all traffic routed via parent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// send message
|
// send message
|
||||||
const bool result = transportSendWrite(route, message);
|
const bool result = transportSendWrite(route, message);
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
// update counter
|
// update counter
|
||||||
if (route == _nc.parentNodeId) {
|
if (route == transportConfig.parentNodeId) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
setIndication(INDICATION_ERR_TX);
|
setIndication(INDICATION_ERR_TX);
|
||||||
_transportSM.failedUplinkTransmissions++;
|
_transportSM.failedUplinkTransmissions++;
|
||||||
@@ -506,7 +513,7 @@ bool transportWait(const uint32_t ms, const uint8_t cmd, const uint8_t msgtype){
|
|||||||
uint8_t transportPingNode(const uint8_t targetId) {
|
uint8_t transportPingNode(const uint8_t targetId) {
|
||||||
if(!_transportSM.pingActive){
|
if(!_transportSM.pingActive){
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId);
|
TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId);
|
||||||
if(targetId == _nc.nodeId) {
|
if(targetId == transportConfig.nodeId) {
|
||||||
// pinging self
|
// pinging self
|
||||||
_transportSM.pingResponse = 0u;
|
_transportSM.pingResponse = 0u;
|
||||||
}
|
}
|
||||||
@@ -574,7 +581,7 @@ void transportProcessMessage(void) {
|
|||||||
// update routing table if msg not from parent
|
// update routing table if msg not from parent
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
if (last != _nc.parentNodeId) {
|
if (last != transportConfig.parentNodeId) {
|
||||||
#else
|
#else
|
||||||
// GW doesn't have parent
|
// GW doesn't have parent
|
||||||
{
|
{
|
||||||
@@ -588,7 +595,7 @@ void transportProcessMessage(void) {
|
|||||||
_transportSM.msgReceived = true;
|
_transportSM.msgReceived = true;
|
||||||
|
|
||||||
// Is message addressed to this node?
|
// Is message addressed to this node?
|
||||||
if (destination == _nc.nodeId) {
|
if (destination == transportConfig.nodeId) {
|
||||||
// prevent buffer overflow by limiting max. possible message length (5 bits=31 bytes max) to MAX_PAYLOAD (25 bytes)
|
// prevent buffer overflow by limiting max. possible message length (5 bits=31 bytes max) to MAX_PAYLOAD (25 bytes)
|
||||||
mSetLength(_msg, min(mGetLength(_msg),(uint8_t)MAX_PAYLOAD));
|
mSetLength(_msg, min(mGetLength(_msg),(uint8_t)MAX_PAYLOAD));
|
||||||
// null terminate data
|
// null terminate data
|
||||||
@@ -599,7 +606,7 @@ void transportProcessMessage(void) {
|
|||||||
_msgTmp = _msg; // Copy message
|
_msgTmp = _msg; // Copy message
|
||||||
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||||
mSetAck(_msgTmp, true); // set ACK flag
|
mSetAck(_msgTmp, true); // set ACK flag
|
||||||
_msgTmp.sender = _nc.nodeId;
|
_msgTmp.sender = transportConfig.nodeId;
|
||||||
_msgTmp.destination = sender;
|
_msgTmp.destination = sender;
|
||||||
// send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
|
// send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
|
||||||
(void)transportSendRoute(_msgTmp);
|
(void)transportSendRoute(_msgTmp);
|
||||||
@@ -627,15 +634,15 @@ void transportProcessMessage(void) {
|
|||||||
if (isValidDistance(distance)) {
|
if (isValidDistance(distance)) {
|
||||||
distance++; // Distance to gateway is one more for us w.r.t. parent
|
distance++; // Distance to gateway is one more for us w.r.t. parent
|
||||||
// update settings if distance shorter or preferred parent found
|
// update settings if distance shorter or preferred parent found
|
||||||
if (((isValidDistance(distance) && distance < _nc.distance) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
if (((isValidDistance(distance) && distance < transportConfig.distanceGW) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
||||||
// Found a neighbor closer to GW than previously found
|
// Found a neighbor closer to GW than previously found
|
||||||
if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) {
|
if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) {
|
||||||
_transportSM.preferredParentFound = true;
|
_transportSM.preferredParentFound = true;
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found
|
||||||
}
|
}
|
||||||
_nc.distance = distance;
|
transportConfig.distanceGW = distance;
|
||||||
_nc.parentNodeId = sender;
|
transportConfig.parentNodeId = sender;
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _nc.parentNodeId, _nc.distance);
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), transportConfig.parentNodeId, transportConfig.distanceGW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,7 +704,7 @@ void transportProcessMessage(void) {
|
|||||||
// only reply if node is fully operational
|
// only reply if node is fully operational
|
||||||
if (type == I_FIND_PARENT_REQUEST) {
|
if (type == I_FIND_PARENT_REQUEST) {
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
if (sender != _nc.parentNodeId) { // no circular reference
|
if (sender != transportConfig.parentNodeId) { // no circular reference
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR REQ,ID=%d\n"), sender); // FPAR: find parent request
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR REQ,ID=%d\n"), sender); // FPAR: find parent request
|
||||||
// check if uplink functional - node can only be parent node if link to GW functional
|
// check if uplink functional - node can only be parent node if link to GW functional
|
||||||
// this also prevents circular references in case GW ooo
|
// this also prevents circular references in case GW ooo
|
||||||
@@ -706,7 +713,7 @@ void transportProcessMessage(void) {
|
|||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok
|
||||||
// random delay minimizes collisions
|
// random delay minimizes collisions
|
||||||
delay(hwMillis() & 0x3ff);
|
delay(hwMillis() & 0x3ff);
|
||||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(_nc.distance));
|
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(transportConfig.distanceGW));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request
|
TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request
|
||||||
@@ -721,10 +728,10 @@ void transportProcessMessage(void) {
|
|||||||
}
|
}
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
if (type == I_DISCOVER_REQUEST) {
|
if (type == I_DISCOVER_REQUEST) {
|
||||||
if (last == _nc.parentNodeId) {
|
if (last == transportConfig.parentNodeId) {
|
||||||
// random wait to minimize collisions
|
// random wait to minimize collisions
|
||||||
delay(hwMillis() & 0x3ff);
|
delay(hwMillis() & 0x3ff);
|
||||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(_nc.parentNodeId));
|
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(transportConfig.parentNodeId));
|
||||||
// no return here (for fwd if repeater)
|
// no return here (for fwd if repeater)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -733,7 +740,7 @@ void transportProcessMessage(void) {
|
|||||||
// controlled BC relay
|
// controlled BC relay
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
// controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds
|
// controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds
|
||||||
if(last == _nc.parentNodeId && sender != _nc.nodeId && isTransportReady()){
|
if(last == transportConfig.parentNodeId && sender != transportConfig.nodeId && isTransportReady()){
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding
|
||||||
(void)transportRouteMessage(_msg);
|
(void)transportRouteMessage(_msg);
|
||||||
}
|
}
|
||||||
@@ -743,7 +750,7 @@ void transportProcessMessage(void) {
|
|||||||
if (command != C_INTERNAL) {
|
if (command != C_INTERNAL) {
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
// only proceed if message received from parent
|
// only proceed if message received from parent
|
||||||
if (last != _nc.parentNodeId) {
|
if (last != transportConfig.parentNodeId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -818,7 +825,7 @@ void transportProcessFIFO(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||||
message.last = _nc.nodeId; // Update last
|
message.last = transportConfig.nodeId; // Update last
|
||||||
// sign message if required
|
// sign message if required
|
||||||
if (!signerSignMsg(message)) {
|
if (!signerSignMsg(message)) {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN FAIL\n"));
|
TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN FAIL\n"));
|
||||||
@@ -842,6 +849,25 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void transportRegisterTransportOkCallback(transportCallback_t cb)
|
||||||
|
{
|
||||||
|
transportOk_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t transportGetNodeId(void)
|
||||||
|
{
|
||||||
|
return transportConfig.nodeId;
|
||||||
|
}
|
||||||
|
uint8_t transportGetParentNodeId(void)
|
||||||
|
{
|
||||||
|
return transportConfig.parentNodeId;
|
||||||
|
}
|
||||||
|
uint8_t transportGetDistanceGW(void)
|
||||||
|
{
|
||||||
|
return transportConfig.distanceGW;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void transportClearRoutingTable(void) {
|
void transportClearRoutingTable(void) {
|
||||||
for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
|
for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
|
||||||
transportSetRoute((uint8_t)i, BROADCAST_ADDRESS);
|
transportSetRoute((uint8_t)i, BROADCAST_ADDRESS);
|
||||||
|
|||||||
+40
-7
@@ -55,7 +55,6 @@
|
|||||||
* |E| SYS | SUB | Message | Comment
|
* |E| SYS | SUB | Message | Comment
|
||||||
* |-|------|-----------|-----------------------|---------------------------------------------------------------------
|
* |-|------|-----------|-----------------------|---------------------------------------------------------------------
|
||||||
* | | TSM | INIT | | <b>Transition to stInit state</b>
|
* | | TSM | INIT | | <b>Transition to stInit state</b>
|
||||||
* | | TSM | INIT | TDC | Transport don't care mode
|
|
||||||
* | | TSM | INIT | STATID=%%d | Node ID is static
|
* | | TSM | INIT | STATID=%%d | Node ID is static
|
||||||
* | | TSM | INIT | TSP OK | Transport device configured and fully operational
|
* | | TSM | INIT | TSP OK | Transport device configured and fully operational
|
||||||
* | | TSM | INIT | GW MODE | Node is set up as GW, thus omitting ID and findParent states
|
* | | TSM | INIT | GW MODE | Node is set up as GW, thus omitting ID and findParent states
|
||||||
@@ -147,11 +146,13 @@
|
|||||||
|
|
||||||
// debug
|
// debug
|
||||||
#if defined(MY_DEBUG)
|
#if defined(MY_DEBUG)
|
||||||
#define TRANSPORT_DEBUG(x,...) debug(x, ##__VA_ARGS__) //!< debug
|
#define TRANSPORT_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
|
||||||
|
extern char _convBuf[MAX_PAYLOAD * 2 + 1];
|
||||||
#else
|
#else
|
||||||
#define TRANSPORT_DEBUG(x,...) //!< debug NULL
|
#define TRANSPORT_DEBUG(x,...) //!< debug NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
#define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes
|
#define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes
|
||||||
#else
|
#else
|
||||||
@@ -204,16 +205,32 @@
|
|||||||
#error Receive message buffering requires message buffering feature enabled!
|
#error Receive message buffering requires message buffering feature enabled!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void(*transportCallback_t)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Node configuration
|
||||||
|
*
|
||||||
|
* This structure stores node-related configurations
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t nodeId; //!< Current node id
|
||||||
|
uint8_t parentNodeId; //!< Where this node sends its messages
|
||||||
|
uint8_t distanceGW; //!< This nodes distance to sensor net gateway (number of hops)
|
||||||
|
} transportConfig_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SM state
|
* @brief SM state
|
||||||
*
|
*
|
||||||
* This structure stores SM state definitions
|
* This structure stores SM state definitions
|
||||||
*/
|
*/
|
||||||
struct transportState {
|
typedef struct {
|
||||||
void(*Transition)(); //!< state transition function
|
void(*Transition)(); //!< state transition function
|
||||||
void(*Update)(); //!< state update function
|
void(*Update)(); //!< state update function
|
||||||
};
|
} transportState_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Status variables and SM state
|
* @brief Status variables and SM state
|
||||||
@@ -222,7 +239,7 @@ struct transportState {
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// SM variables
|
// SM variables
|
||||||
transportState* currentState; //!< pointer to current fsm state
|
transportState_t* currentState; //!< pointer to current fsm state
|
||||||
uint32_t stateEnter; //!< state enter timepoint
|
uint32_t stateEnter; //!< state enter timepoint
|
||||||
// general transport variables
|
// general transport variables
|
||||||
uint32_t lastUplinkCheck; //!< last uplink check, required to prevent GW flooding
|
uint32_t lastUplinkCheck; //!< last uplink check, required to prevent GW flooding
|
||||||
@@ -239,7 +256,7 @@ typedef struct {
|
|||||||
bool msgReceived : 1; //!< flag message received
|
bool msgReceived : 1; //!< flag message received
|
||||||
// 8 bits
|
// 8 bits
|
||||||
uint8_t pingResponse; //!< stores I_PONG hops
|
uint8_t pingResponse; //!< stores I_PONG hops
|
||||||
} transportSM;
|
} transportSM_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief RAM routing table
|
* @brief RAM routing table
|
||||||
@@ -302,7 +319,7 @@ void stFailureUpdate(void);
|
|||||||
* @brief Switch SM state
|
* @brief Switch SM state
|
||||||
* @param newState New state to switch SM to
|
* @param newState New state to switch SM to
|
||||||
*/
|
*/
|
||||||
void transportSwitchSM(transportState& newState);
|
void transportSwitchSM(transportState_t& newState);
|
||||||
/**
|
/**
|
||||||
* @brief Update SM state
|
* @brief Update SM state
|
||||||
*/
|
*/
|
||||||
@@ -483,6 +500,22 @@ uint8_t transportReceive(void* data);
|
|||||||
*/
|
*/
|
||||||
void transportPowerDown();
|
void transportPowerDown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get node ID
|
||||||
|
* @return node ID
|
||||||
|
*/
|
||||||
|
uint8_t transportGetNodeId(void);
|
||||||
|
/**
|
||||||
|
* @brief Get parent node ID
|
||||||
|
* @return parent node ID
|
||||||
|
*/
|
||||||
|
uint8_t transportGetParentNodeId(void);
|
||||||
|
/**
|
||||||
|
* @brief Get distance to GW
|
||||||
|
* @return distance (=hops) to GW
|
||||||
|
*/
|
||||||
|
uint8_t transportGetDistanceGW(void);
|
||||||
|
|
||||||
|
|
||||||
#endif // MyTransport_h
|
#endif // MyTransport_h
|
||||||
/** @}*/
|
/** @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user