Reduce library size
This commit is contained in:
@@ -12,6 +12,6 @@
|
||||
/***
|
||||
* Enable/Disable debug logging
|
||||
*/
|
||||
#define DEBUG
|
||||
//#define DEBUG
|
||||
|
||||
#endif
|
||||
|
||||
@@ -187,7 +187,7 @@ void MyGateway::processRadioMessage() {
|
||||
if (process()) {
|
||||
// A new message was received from one of the sensors
|
||||
MyMessage message = getLastMessage();
|
||||
if (message.getCommand() == C_PRESENTATION && inclusionMode) {
|
||||
if (mGetCommand(message) == C_PRESENTATION && inclusionMode) {
|
||||
rxBlink(3);
|
||||
} else {
|
||||
rxBlink(1);
|
||||
@@ -213,7 +213,7 @@ void MyGateway::serial(const char *fmt, ... ) {
|
||||
}
|
||||
|
||||
void MyGateway::serial(MyMessage msg) {
|
||||
serial(PSTR("%d;%d;%d;%d;%s\n"),msg.getSender(), msg.getSensor(), msg.getCommand(), msg.getType(), msg.getString(convBuf));
|
||||
serial(PSTR("%d;%d;%d;%d;%s\n"),msg.sender, msg.sensor, mGetCommand(msg), msg.type, msg.getString(convBuf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,73 +4,8 @@
|
||||
|
||||
|
||||
MyMessage::MyMessage() {
|
||||
setVersion(PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
MyMessage::MyMessage(uint8_t _sensor, uint8_t _type, uint8_t _destination) {
|
||||
sensor = _sensor;
|
||||
type = _type;
|
||||
destination = _destination;
|
||||
setVersion(PROTOCOL_VERSION);
|
||||
setCommand(C_SET_VARIABLE);
|
||||
}
|
||||
|
||||
MyMessage MyMessage::build(uint8_t _sender, uint8_t _destination, uint8_t _sensor, uint8_t _command, uint8_t _type) {
|
||||
sender = _sender;
|
||||
destination = _destination;
|
||||
sensor = _sensor;
|
||||
type = _type;
|
||||
setCommand(_command);
|
||||
setLength(0);
|
||||
setPayloadType(P_STRING);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*MyMessage MyMessage::failed() {
|
||||
return getCommand() == C_FAILED
|
||||
}*/
|
||||
|
||||
// Header getters
|
||||
|
||||
uint8_t MyMessage::getCRC() {
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getVersion() {
|
||||
return BF_GET(version_length, 0, 3);
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getLength() {
|
||||
return BF_GET(version_length, 3, 5);
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getCommand() {
|
||||
return BF_GET(command_payload, 0, 4);
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getPayloadType() {
|
||||
return BF_GET(command_payload, 4, 4);
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getSensor() {
|
||||
return sensor;
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
||||
/* Getters for payload converted to desired form */
|
||||
@@ -80,10 +15,10 @@ void* MyMessage::getCustom() {
|
||||
|
||||
/* NOTE: Calling this method might affect the payload by converting it to its string representation */
|
||||
char* MyMessage::getString(char *buffer) {
|
||||
uint8_t payloadType = getPayloadType();
|
||||
uint8_t payloadType = miGetPayloadType();
|
||||
|
||||
if (payloadType == P_STRING) {
|
||||
data[getLength()] = '\0';
|
||||
data[miGetLength()] = '\0';
|
||||
return data;
|
||||
} else if (buffer != NULL) {
|
||||
switch(payloadType) {
|
||||
@@ -116,11 +51,14 @@ char* MyMessage::getString(char *buffer) {
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getByte() {
|
||||
if (getPayloadType() == P_BYTE)
|
||||
switch(miGetPayloadType()) {
|
||||
case P_BYTE:
|
||||
return data[0];
|
||||
if (getPayloadType() == P_STRING)
|
||||
case P_STRING:
|
||||
return atoi(data);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bool MyMessage::getBool() {
|
||||
return !(data[0]-'0'==0);
|
||||
@@ -131,90 +69,55 @@ double MyMessage::getDouble() {
|
||||
}
|
||||
|
||||
long MyMessage::getLong() {
|
||||
if (getPayloadType() == P_LONG32)
|
||||
switch(miGetPayloadType()) {
|
||||
case P_LONG32:
|
||||
return lValue;
|
||||
if (getPayloadType() == P_STRING)
|
||||
case P_STRING:
|
||||
return atol(data);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long MyMessage::getULong() {
|
||||
if (getPayloadType() == P_ULONG32)
|
||||
switch(miGetPayloadType()) {
|
||||
case P_ULONG32:
|
||||
return ulValue;
|
||||
if (getPayloadType() == P_STRING)
|
||||
case P_STRING:
|
||||
return atol(data);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int MyMessage::getInt() {
|
||||
if (getPayloadType() == P_INT16)
|
||||
switch(miGetPayloadType()) {
|
||||
case P_INT16:
|
||||
return iValue;
|
||||
if (getPayloadType() == P_STRING)
|
||||
case P_STRING:
|
||||
return atoi(data);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int MyMessage::getUInt() {
|
||||
if (getPayloadType() == P_UINT16)
|
||||
switch(miGetPayloadType()) {
|
||||
case P_UINT16:
|
||||
return uiValue;
|
||||
if (getPayloadType() == P_STRING)
|
||||
case P_STRING:
|
||||
return atoi(data);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Header setters
|
||||
MyMessage MyMessage::setCRC(uint8_t _crc) {
|
||||
crc = _crc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setVersion(uint8_t version) {
|
||||
BF_SET(version_length, version, 0, 3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setLength(uint8_t length) {
|
||||
BF_SET(version_length, length, 3, 5);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setCommand(uint8_t command) {
|
||||
BF_SET(command_payload, command, 0, 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setPayloadType(uint8_t pt) {
|
||||
BF_SET(command_payload, pt, 4, 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setType(uint8_t _type) {
|
||||
type = _type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setSensor(uint8_t _sensor) {
|
||||
sensor = _sensor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setSender(uint8_t _sender) {
|
||||
sender = _sender;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setLast(uint8_t _last) {
|
||||
last=_last;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::setDestination(uint8_t _destination) {
|
||||
destination = _destination;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Set payload
|
||||
MyMessage MyMessage::set(void* value, uint8_t length) {
|
||||
setPayloadType(P_CUSTOM);
|
||||
setLength(length);
|
||||
miSetPayloadType(P_CUSTOM);
|
||||
miSetLength(length);
|
||||
memcpy(data, value, min(length, MAX_PAYLOAD));
|
||||
return *this;
|
||||
}
|
||||
@@ -222,57 +125,57 @@ MyMessage MyMessage::set(void* value, uint8_t length) {
|
||||
|
||||
MyMessage MyMessage::set(const char* value) {
|
||||
uint8_t length = strlen(value);
|
||||
setLength(length);
|
||||
setPayloadType(P_STRING);
|
||||
miSetLength(length);
|
||||
miSetPayloadType(P_STRING);
|
||||
strncpy(data, value, min(length, MAX_PAYLOAD));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(uint8_t value) {
|
||||
setLength(1);
|
||||
setPayloadType(P_BYTE);
|
||||
miSetLength(1);
|
||||
miSetPayloadType(P_BYTE);
|
||||
data[0] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(bool value) {
|
||||
setLength(1);
|
||||
setPayloadType(P_STRING);
|
||||
miSetLength(1);
|
||||
miSetPayloadType(P_STRING);
|
||||
data[0] = value?'1':'0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(double value, uint8_t decimals) {
|
||||
dtostrf(value,2,decimals,data);
|
||||
setLength(strlen(data));
|
||||
setPayloadType(P_STRING);
|
||||
miSetLength(strlen(data));
|
||||
miSetPayloadType(P_STRING);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(unsigned long value) {
|
||||
setPayloadType(P_ULONG32);
|
||||
setLength(4);
|
||||
miSetPayloadType(P_ULONG32);
|
||||
miSetLength(4);
|
||||
ulValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(long value) {
|
||||
setPayloadType(P_LONG32);
|
||||
setLength(4);
|
||||
miSetPayloadType(P_LONG32);
|
||||
miSetLength(4);
|
||||
lValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(unsigned int value) {
|
||||
setPayloadType(P_INT16);
|
||||
setLength(2);
|
||||
miSetPayloadType(P_INT16);
|
||||
miSetLength(2);
|
||||
uiValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage MyMessage::set(int value) {
|
||||
setPayloadType(P_UINT16);
|
||||
setLength(2);
|
||||
miSetPayloadType(P_UINT16);
|
||||
miSetLength(2);
|
||||
iValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define MAX_MESSAGE_LENGTH 32
|
||||
#define HEADER_SIZE 8
|
||||
#define MAX_PAYLOAD (MAX_MESSAGE_LENGTH - HEADER_SIZE)
|
||||
#define GATEWAY_ADDRESS ((uint8_t)0)
|
||||
|
||||
// Message types
|
||||
typedef enum {
|
||||
@@ -27,8 +26,7 @@ typedef enum {
|
||||
C_REQ_VARIABLE = 2,
|
||||
C_SET_WITH_ACK = 3,
|
||||
C_INTERNAL = 4,
|
||||
C_STREAM = 5, // For Firmaware and other larger chunks of data that need to be divided into pieces.
|
||||
C_FAILED = 6
|
||||
C_STREAM = 5 // For Firmaware and other larger chunks of data that need to be divided into pieces.
|
||||
} command;
|
||||
|
||||
// Type of sensor data (for set/req/ack messages)
|
||||
@@ -44,7 +42,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
I_BATTERY_LEVEL, I_TIME, I_VERSION, I_REQUEST_ID,
|
||||
I_INCLUSION_MODE, I_RELAY_NODE, I_PING, I_PING_ACK,
|
||||
I_LOG_MESSAGE, I_CHILDREN, I_UNIT, I_SKETCH_NAME, I_SKETCH_VERSION
|
||||
I_LOG_MESSAGE, I_CHILDREN, I_CONFIG, I_SKETCH_NAME, I_SKETCH_VERSION
|
||||
} internal;
|
||||
|
||||
// Type of sensor (for presentation message)
|
||||
@@ -82,46 +80,44 @@ typedef enum {
|
||||
// Insert a new bitfield value x into y.
|
||||
#define BF_SET(y, x, start, len) ( y= ((y) &~ BF_MASK(start, len)) | BF_PREP(x, start, len) )
|
||||
|
||||
// Getters/setters for special fields in header
|
||||
#define mSetVersion(_msg,_version) BF_SET(_msg.version_length, _version, 0, 3)
|
||||
#define mSetLength(_msg,_length) BF_SET(_msg.version_length, _length, 3, 5)
|
||||
#define mSetCommand(_msg,_command) BF_SET(_msg.command_payload, _command, 0, 4)
|
||||
#define mSetPayloadType(_msg, _pt) BF_SET(_msg.command_payload, _pt, 4, 4)
|
||||
|
||||
#define mGetVersion(_msg) BF_GET(_msg.version_length, 0, 3)
|
||||
#define mGetLength(_msg) BF_GET(_msg.version_length, 3, 5)
|
||||
#define mGetCommand(_msg) BF_GET(_msg.command_payload, 0, 4)
|
||||
#define mGetPayloadType(_msg) BF_GET(_msg.command_payload, 4, 4)
|
||||
|
||||
// internal access for special fileds
|
||||
#define miGetPayloadType() BF_GET(command_payload, 4, 4)
|
||||
#define miGetLength() BF_GET(version_length, 3, 5)
|
||||
|
||||
#define miSetLength(_length) BF_SET(version_length, _length, 3, 5)
|
||||
#define miSetPayloadType(_pt) BF_SET(command_payload, _pt, 4, 4)
|
||||
|
||||
|
||||
// Check and fetch data from special messages
|
||||
#define isTimeResponse(_msg) (mGetCommand(_msg)==C_INTERN && _msg.type==I_TIME)
|
||||
#define isConfigResponse(_msg) (mGetCommand(_msg)==C_INTERN && _msg.type==I_CONFIG)
|
||||
#define mIsMetric(_msg) (_msg.getByte() == 'M')
|
||||
|
||||
|
||||
class MyMessage
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
MyMessage(uint8_t sensor, uint8_t type, uint8_t destination=GATEWAY_ADDRESS);
|
||||
MyMessage();
|
||||
|
||||
/* Check this after callback to see if request failed */
|
||||
// bool failed();
|
||||
|
||||
|
||||
// Getters for header
|
||||
uint8_t getCRC();
|
||||
uint8_t getVersion();
|
||||
uint8_t getLength();
|
||||
uint8_t getCommand();
|
||||
uint8_t getPayloadType();
|
||||
uint8_t getType();
|
||||
uint8_t getSensor();
|
||||
uint8_t getSender();
|
||||
uint8_t getLast();
|
||||
uint8_t getDestination();
|
||||
|
||||
// Getters for payload
|
||||
|
||||
|
||||
/**
|
||||
* If payload is something else than P_STRING you can have payload the value converted
|
||||
* to string representation by supplying a buffer with the minimum size of
|
||||
* 2*MAX_PAYLOAD+1. This is to be able to fit hex-conversion of a full binary payload.
|
||||
*/
|
||||
char* getString(char *buffer = NULL);
|
||||
|
||||
/**
|
||||
* Returns payload untouched
|
||||
*/
|
||||
void* getCustom();
|
||||
|
||||
uint8_t getByte();
|
||||
bool getBool();
|
||||
double getDouble();
|
||||
@@ -130,21 +126,6 @@ public:
|
||||
int getInt();
|
||||
unsigned int getUInt();
|
||||
|
||||
// Builder helper
|
||||
MyMessage build(uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type);
|
||||
|
||||
// Setters for header
|
||||
MyMessage setCRC(uint8_t crc);
|
||||
MyMessage setVersion(uint8_t version);
|
||||
MyMessage setLength(uint8_t length);
|
||||
MyMessage setCommand(uint8_t command);
|
||||
MyMessage setPayloadType(uint8_t pt);
|
||||
MyMessage setType(uint8_t type);
|
||||
MyMessage setSensor(uint8_t sensor);
|
||||
MyMessage setSender(uint8_t sender);
|
||||
MyMessage setLast(uint8_t last);
|
||||
MyMessage setDestination(uint8_t destination);
|
||||
|
||||
|
||||
// Setters for payload
|
||||
MyMessage set(void* payload, uint8_t length);
|
||||
@@ -166,6 +147,7 @@ public:
|
||||
uint8_t last; // 8 bit - Id of last node this message passed
|
||||
uint8_t destination; // 8 bit - Id of destination node
|
||||
uint8_t crc; // 8 bit - Message checksum
|
||||
|
||||
// Each message can transfer a payload. We add one extra byte for string
|
||||
// terminator \0 to be "printable" this is not transferred OTA
|
||||
// This union is used to simplify the construction of the binary transferred int/long values.
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
MySensor::MySensor(uint8_t _cepin, uint8_t _cspin) : RF24(_cepin, _cspin) {
|
||||
}
|
||||
|
||||
|
||||
void MySensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) {
|
||||
failedTransmissions = 0;
|
||||
|
||||
@@ -41,7 +40,7 @@ void MySensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_
|
||||
}
|
||||
|
||||
void MySensor::setupRelayMode(){
|
||||
s.childNodeTable = (uint8_t *) malloc(256);
|
||||
s.childNodeTable = new uint8_t[256];
|
||||
eeprom_read_block((void*)s.childNodeTable, (void*)EEPROM_ROUTES_ADDRESS, 256);
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ void MySensor::begin(void (*_msgCallback)(MyMessage), boolean _relayMode, uint8_
|
||||
present(NODE_CHILD_ID, relayMode? S_ARDUINO_RELAY : S_ARDUINO_NODE);
|
||||
|
||||
// Send parent information back to sensor net gateway.
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_RELAY_NODE).set(s.parentNodeId));
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_RELAY_NODE, s.parentNodeId);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +91,7 @@ uint8_t MySensor::getNodeId() {
|
||||
void MySensor::requestNodeId() {
|
||||
debug(PSTR("req node id\n"));
|
||||
RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(s.nodeId));
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_REQUEST_ID));
|
||||
buildSend(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_REQUEST_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +109,8 @@ void MySensor::findParentNode() {
|
||||
s.distance = 255;
|
||||
|
||||
// Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to)
|
||||
sendWrite(BROADCAST_ADDRESS, msg.build(s.nodeId, BROADCAST_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_PING));
|
||||
build(msg, s.nodeId, BROADCAST_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_PING)
|
||||
sendWrite(BROADCAST_ADDRESS, msg, true);
|
||||
// Wait for replies for max 10 seconds (or when buffer for all parent nodes have been filled up)
|
||||
|
||||
unsigned long enter = millis();
|
||||
@@ -121,32 +121,18 @@ void MySensor::findParentNode() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
boolean MySensor::sendAck(MyMessage message) {
|
||||
// Build ack message
|
||||
ack = message;
|
||||
ack.setCommand(C_SET_VARIABLE);
|
||||
ack.setSender(s.nodeId);
|
||||
ack.setDestination(message.getSender());
|
||||
return sendRoute(ack);
|
||||
}*/
|
||||
|
||||
|
||||
boolean MySensor::sendRoute(MyMessage message) {
|
||||
// Make sure to process any incoming messages before sending (could this end up in recursive loop?)
|
||||
process();
|
||||
|
||||
// If we still don't have any node id, re-request and skip this message.
|
||||
if (s.nodeId == AUTO && !(message.getCommand() == C_INTERNAL && message.getType() == I_REQUEST_ID)) {
|
||||
if (s.nodeId == AUTO && !(mGetCommand(message) == C_INTERNAL && message.type == I_REQUEST_ID)) {
|
||||
requestNodeId();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relayMode) {
|
||||
uint8_t dest = message.getDestination();
|
||||
uint8_t dest = message.destination;
|
||||
uint8_t route = getChildRoute(dest);
|
||||
if (route>0 && route<255 && dest != GATEWAY_ADDRESS) {
|
||||
debug(PSTR("route %d.\n"), route);
|
||||
@@ -176,16 +162,11 @@ boolean MySensor::sendRoute(MyMessage message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
boolean MySensor::sendWrite(uint8_t next, MyMessage message) {
|
||||
uint8_t length = message.getLength();
|
||||
message.setLast(s.nodeId);
|
||||
message.setCRC(crc8Message(message));
|
||||
|
||||
bool broadcast = message.getCommand() == C_INTERNAL && message.getType() == I_PING;
|
||||
boolean MySensor::sendWrite(uint8_t next, MyMessage message, bool broadcast) {
|
||||
uint8_t length = mGetLength(message);
|
||||
message.last = s.nodeId;
|
||||
mSetVersion(message, PROTOCOL_VERSION);
|
||||
message.crc = crc8Message(message);
|
||||
|
||||
// Make sure radio has powered up
|
||||
RF24::powerUp();
|
||||
@@ -196,115 +177,54 @@ boolean MySensor::sendWrite(uint8_t next, MyMessage message) {
|
||||
|
||||
// Only debug print payload if it is of string type
|
||||
debug(PSTR("tx: %d-%d-%d-%d s=%d,c=%d,t=%d, st=%s:%s\n"),
|
||||
message.getSender(),message.getLast(), next, message.getDestination(), message.getSensor(), message.getCommand(), message.getType(), ok?"ok":"fail", message.getString());
|
||||
message.sender,message.last, next, message.destination, message.sensor, mGetCommand(message), message.type, ok?"ok":"fail", message.getString());
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
bool MySensor::send(MyMessage message, bool enableAck) {
|
||||
message.setSender(s.nodeId);
|
||||
message.sender = s.nodeId;
|
||||
if (enableAck) {
|
||||
message.setCommand(C_SET_WITH_ACK);
|
||||
mSetCommand(message,C_SET_WITH_ACK);
|
||||
}
|
||||
return sendRoute(message);
|
||||
|
||||
/* return wait(message, C_SET_VARIABLE, retry).getCommand() != C_FAILED;
|
||||
} else {
|
||||
return ;
|
||||
}*/
|
||||
}
|
||||
|
||||
void MySensor::sendBatteryLevel(uint8_t value) {
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_BATTERY_LEVEL, value);
|
||||
}
|
||||
|
||||
void MySensor::present(uint8_t childSensorId, uint8_t sensorType) {
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType).set(LIBRARY_VERSION));
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, LIBRARY_VERSION);
|
||||
}
|
||||
|
||||
void MySensor::sketchInfo(const char *name, const char *version) {
|
||||
if (name != NULL)
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_SKETCH_NAME).set(name));
|
||||
if (version != NULL)
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_SKETCH_VERSION).set(version));
|
||||
if (name != NULL) {
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_SKETCH_NAME, name);
|
||||
}
|
||||
if (version != NULL) {
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_SKETCH_VERSION, version);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
MyMessage MySensor::get( uint8_t childSensorId, uint8_t variableType, uint8_t destination, uint8_t retry) {
|
||||
msg.build(s.nodeId, destination, childSensorId, C_REQ_VARIABLE, variableType);
|
||||
return wait(msg, C_SET_VARIABLE, retry);
|
||||
}*/
|
||||
|
||||
void MySensor::request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) {
|
||||
sendRoute(msg.build(s.nodeId, destination, childSensorId, C_REQ_VARIABLE, variableType));
|
||||
buildSend(msg, s.nodeId, destination, childSensorId, C_REQ_VARIABLE, variableType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MySensor::sendBatteryLevel(int value) {
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_BATTERY_LEVEL).set(value));
|
||||
}
|
||||
|
||||
/*
|
||||
MyMessage MySensor::wait(MyMessage message, uint8_t expectedResponseCommand, uint8_t retry) {
|
||||
while (retry>0) {
|
||||
|
||||
uint8_t sensor = message.getSensor();
|
||||
uint8_t type = message.getType();
|
||||
sendRoute(message);
|
||||
uint8_t i = 0;
|
||||
while (i < 100) { // 1 seconds timeout before re-sending status request
|
||||
while (process()) {
|
||||
// Check that it is right type of message and not a routing message
|
||||
if (msg.getCommand() == expectedResponseCommand &&
|
||||
msg.getType() == type &&
|
||||
msg.getSensor() == sensor) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
delay(10);
|
||||
i++;
|
||||
}
|
||||
retry--;
|
||||
}
|
||||
msg.setCommand(C_FAILED);
|
||||
return msg;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
MyMessage MySensor::getInternal(uint8_t variableType, uint8_t retry) {
|
||||
msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, variableType);
|
||||
return wait(msg, C_INTERNAL, retry);
|
||||
}*/
|
||||
|
||||
/*unsigned long MySensor::getTime(uint8_t retry) {
|
||||
MyMessage message = getInternal(I_TIME, retry);
|
||||
return message == NULL ? 0UL : message.getULong();
|
||||
}*/
|
||||
|
||||
void MySensor::requestTime() {
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_TIME));
|
||||
buildSend(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_TIME);
|
||||
}
|
||||
|
||||
|
||||
/*bool MySensor::isMetricSystem(uint8_t retry) {
|
||||
MyMessage message = getInternal(I_UNIT, retry);
|
||||
return (message == NULL)
|
||||
return true;
|
||||
else
|
||||
return message.getByte() == 'M';
|
||||
}*/
|
||||
|
||||
void MySensor::requestIsMetricSystem() {
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_UNIT));
|
||||
void MySensor::requestConfiguration() {
|
||||
buildSend(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CONFIG);
|
||||
}
|
||||
|
||||
|
||||
boolean MySensor::process() {
|
||||
uint8_t pipe;
|
||||
boolean available = RF24::available(&pipe);
|
||||
|
||||
|
||||
if (available && pipe<7) {
|
||||
uint8_t len = RF24::getDynamicPayloadSize();
|
||||
RF24::read(&msg, len);
|
||||
@@ -316,14 +236,14 @@ boolean MySensor::process() {
|
||||
// Make sure string gets terminated ok for full string messages.
|
||||
msg.data[len - HEADER_SIZE ] = '\0';
|
||||
debug(PSTR("rx: %d-%d-%d s=%d,c=%d,t=%d,cr=%s: %s\n"),
|
||||
msg.getSender(), msg.getLast(), msg.getDestination(), msg.getSensor(), msg.getCommand(), msg.getType(), valid==0?"ok":valid==1?"ec":"ev", msg.getString());
|
||||
msg.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, valid==0?"ok":valid==1?"ec":"ev", msg.getString());
|
||||
|
||||
if (ok) {
|
||||
uint8_t command = msg.getCommand();
|
||||
uint8_t type = msg.getType();
|
||||
uint8_t sender = msg.getSender();
|
||||
uint8_t last = msg.getLast();
|
||||
uint8_t destination = msg.getDestination();
|
||||
uint8_t command = mGetCommand(msg);
|
||||
uint8_t type = msg.type;
|
||||
uint8_t sender = msg.sender; //getSender();
|
||||
uint8_t last = msg.last;
|
||||
uint8_t destination = msg.destination;
|
||||
|
||||
if (relayMode && command == C_INTERNAL && type == I_PING && s.nodeId != AUTO) {
|
||||
// Relaying nodes should always answer ping messages
|
||||
@@ -331,8 +251,9 @@ boolean MySensor::process() {
|
||||
// between ping ack messages from other relaying nodes
|
||||
randomSeed(millis());
|
||||
delay(random(2000));
|
||||
uint8_t replyTo = msg.getSender();
|
||||
msg.build(s.nodeId, replyTo, NODE_CHILD_ID, C_INTERNAL, I_PING_ACK).set(s.distance);
|
||||
uint8_t replyTo = msg.sender;
|
||||
build(msg, s.nodeId, replyTo, NODE_CHILD_ID, C_INTERNAL, I_PING_ACK);
|
||||
msg.set(s.distance);
|
||||
sendWrite(replyTo, msg);
|
||||
return false;
|
||||
} else if (destination == s.nodeId) {
|
||||
@@ -349,7 +270,7 @@ boolean MySensor::process() {
|
||||
if (distance<s.distance-1) {
|
||||
// Found a neighbor closer to GW than previously found
|
||||
s.distance = distance + 1;
|
||||
s.parentNodeId = msg.getSender();
|
||||
s.parentNodeId = msg.sender;
|
||||
eeprom_write_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, s.parentNodeId);
|
||||
eeprom_write_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, s.distance);
|
||||
debug(PSTR("p=%d, d=%d\n"), s.parentNodeId, s.distance);
|
||||
@@ -374,15 +295,23 @@ boolean MySensor::process() {
|
||||
// Someone at sensor net gateway side wants this node to refresh its relay node
|
||||
findParentNode();
|
||||
// Send relay information back to sensor net gateway node device.
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_RELAY_NODE).set(s.parentNodeId));
|
||||
buildSendPayload(msg,s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_RELAY_NODE,s.parentNodeId);
|
||||
return false;
|
||||
} else if (type == I_CHILDREN) {
|
||||
if (msg.getByte() == 'F') {
|
||||
// Send in as many children we can fit in a message (binary)
|
||||
sendChildren();
|
||||
// TODO: We should send in as many children we can fit in a message (binary)
|
||||
// For now we only print routing table for this node.
|
||||
for (uint8_t i=0;i< 50; i++) {
|
||||
debug(PSTR("rd=%d, %d\n"), i, getChildRoute(i) );
|
||||
}
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CHILDREN, "n/a");
|
||||
} else if (msg.getByte() == 'C') {
|
||||
// Clears child relay data for this node
|
||||
clearChildRoutes();
|
||||
debug(PSTR("rd=clear\n"));
|
||||
for (uint8_t i=0;i< sizeof(s.childNodeTable); i++) {
|
||||
removeChildRoute(i);
|
||||
}
|
||||
buildSendPayload(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CHILDREN,"");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -391,12 +320,12 @@ boolean MySensor::process() {
|
||||
// Check if sender requests an ack back.
|
||||
if (command == C_SET_WITH_ACK) {
|
||||
ack = msg;
|
||||
ack.setCommand(C_SET_VARIABLE);
|
||||
ack.setSender(s.nodeId);
|
||||
ack.setDestination(msg.getSender());
|
||||
mSetCommand(ack,C_SET_VARIABLE);
|
||||
ack.sender = s.nodeId;
|
||||
ack.destination = msg.sender;
|
||||
sendRoute(ack);
|
||||
// The library user should not need to care about this ack request. Just treat it as a normal SET.
|
||||
msg.setCommand(C_SET_VARIABLE);
|
||||
mSetCommand(msg,C_SET_VARIABLE);
|
||||
}
|
||||
// Call incoming message callback if available
|
||||
if (msgCallback != NULL) {
|
||||
@@ -407,7 +336,7 @@ boolean MySensor::process() {
|
||||
} else if (relayMode) {
|
||||
// We should try to relay this message to another node
|
||||
|
||||
uint8_t route = getChildRoute(msg.getDestination());
|
||||
uint8_t route = getChildRoute(msg.destination);
|
||||
if (route>0 && route<255) {
|
||||
// This message should be forwarded to a child node. If we send message
|
||||
// to this nodes pipe then all children will receive it because the are
|
||||
@@ -482,7 +411,7 @@ MyMessage MySensor::getLastMessage() {
|
||||
* calculate CRC8 on MyMessage data taking care of data structure and protocol version
|
||||
*/
|
||||
uint8_t MySensor::crc8Message(MyMessage message) {
|
||||
uint8_t len = message.getLength();
|
||||
uint8_t len = mGetLength(message);
|
||||
uint8_t crc = 0x00;
|
||||
uint8_t loop_count;
|
||||
uint8_t bit_counter;
|
||||
@@ -491,7 +420,7 @@ uint8_t MySensor::crc8Message(MyMessage message) {
|
||||
uint8_t number_of_bytes_to_read = (uint8_t)sizeof(message);
|
||||
|
||||
// Must set crc to a constant value.
|
||||
message.setCRC(0);
|
||||
message.crc = 0;
|
||||
|
||||
// fill unused space by zeroes for string data only
|
||||
if(len>=0 && len < sizeof(message.data)-1) {
|
||||
@@ -525,16 +454,17 @@ uint8_t MySensor::crc8Message(MyMessage message) {
|
||||
|
||||
|
||||
uint8_t MySensor::validate(MyMessage message) {
|
||||
uint8_t oldCrc = message.getCRC();
|
||||
uint8_t oldCrc = message.crc;
|
||||
uint8_t newCrc = crc8Message(message);
|
||||
|
||||
if(!(message.getVersion() == PROTOCOL_VERSION)) return VALIDATE_BAD_VERSION;
|
||||
if(!(mGetVersion(message) == PROTOCOL_VERSION)) return VALIDATE_BAD_VERSION;
|
||||
|
||||
if(!(oldCrc == newCrc)) return VALIDATE_BAD_CRC;
|
||||
return VALIDATE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MySensor::addChildRoute(uint8_t childId, uint8_t route) {
|
||||
if (s.childNodeTable[childId] != route) {
|
||||
s.childNodeTable[childId] = route;
|
||||
@@ -553,34 +483,13 @@ uint8_t MySensor::getChildRoute(uint8_t childId) {
|
||||
return s.childNodeTable[childId];
|
||||
}
|
||||
|
||||
void MySensor::clearChildRoutes() {
|
||||
debug(PSTR("rd=clear\n"));
|
||||
for (unsigned int i=0;i< sizeof(s.childNodeTable); i++) {
|
||||
removeChildRoute(i);
|
||||
}
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CHILDREN).set(""));
|
||||
}
|
||||
|
||||
void MySensor::sendChildren() {
|
||||
// Send in which children that is using this node as parent.
|
||||
// TODO: Fix this
|
||||
for (int i=0;i< 50; i++) {
|
||||
// Serial.println(s.childNodeTable[i]);
|
||||
debug(PSTR("rd=%d, %d\n"), i, getChildRoute(i) );
|
||||
}
|
||||
sendRoute(msg.build(s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CHILDREN).set("n/a"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void MySensor::debugPrint(const char *fmt, ... ) {
|
||||
char fmtBuffer[300];
|
||||
if (s.nodeId == GATEWAY_ADDRESS) {
|
||||
// prepend debug message to be handled correctly by gw
|
||||
Serial.print("0;0;4;11;");
|
||||
Serial.write("0;0;4;11;");
|
||||
}
|
||||
va_list args;
|
||||
va_start (args, fmt );
|
||||
@@ -598,8 +507,8 @@ void MySensor::debugPrint(const char *fmt, ... ) {
|
||||
Serial.print(fmtBuffer);
|
||||
Serial.flush();
|
||||
|
||||
//Serial.print("0;0;4;11;Mem free:");
|
||||
//Serial.println(freeRam());
|
||||
//Serial.write("0;0;4;11;Mem free:");
|
||||
//Serial.write(freeRam());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -57,6 +57,22 @@
|
||||
#define SEND_RETRIES 3
|
||||
#define FIND_RELAY_AFTER_FAILED_TRANSMISSIONS 5
|
||||
|
||||
#define build(_msg, _sender, _destination, _sensor, _cmd, _type) \
|
||||
_msg.sender = _sender; \
|
||||
_msg.destination = _destination;\
|
||||
_msg.sensor = _sensor; \
|
||||
_msg.type = _type; \
|
||||
mSetCommand(_msg,_cmd); \
|
||||
|
||||
#define buildSend(_msg, _sender, _destination, _sensor, _cmd, _type) \
|
||||
build(_msg, _sender, _destination, _sensor, _cmd, _type) \
|
||||
sendRoute(_msg);
|
||||
|
||||
#define buildSendPayload(_msg, _sender, _destination, _sensor, _cmd, _type, _value) \
|
||||
build(_msg, _sender, _destination, _sensor, _cmd, _type) \
|
||||
_msg.set(_value); \
|
||||
sendRoute(_msg);
|
||||
|
||||
|
||||
class MySensor : public RF24
|
||||
{
|
||||
@@ -120,7 +136,7 @@ class MySensor : public RF24
|
||||
* Send this nodes battery level to gateway.
|
||||
* @param level Level between 0-100(%)
|
||||
*/
|
||||
void sendBatteryLevel(int level);
|
||||
void sendBatteryLevel(uint8_t level);
|
||||
|
||||
/**
|
||||
* Fetches a value from gateway or some other sensor in the radio network. Resends request and waits for response.
|
||||
@@ -144,26 +160,24 @@ class MySensor : public RF24
|
||||
* @param callback for result. This will be called when a message reply is received or request fails (see status of second argument).
|
||||
* @param destination The nodeId of other node in radio network. Default is gateway
|
||||
*/
|
||||
/*void (* msgCallback)(MyMessage, bool)=NULL, */
|
||||
void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS);
|
||||
|
||||
|
||||
/**
|
||||
* Fetches time from sensor net gateway.
|
||||
* Requests time from controller. Pick up response in callback.
|
||||
*
|
||||
* @return Seconds since 1970, 0 if failed.
|
||||
* @return Seconds since 1970.
|
||||
*/
|
||||
// unsigned long getTime(uint8_t retry=SEND_RETRIES);
|
||||
void requestTime();
|
||||
|
||||
/**
|
||||
* Fetches unit setting from sensor net gateway. Returns true if metric system has been selected which means
|
||||
* that sensor should report it's information in: celsius, meter, cm, gram, km/h, m/s etc..
|
||||
* Fetches configuration from controller. Returns true if metric system has been selected which means
|
||||
* that sensor should report it's information in:
|
||||
* celsius, meter, cm, gram, km/h, m/s etc..
|
||||
* If false is returned the sensor should report data in imperial system which means
|
||||
* fahrenheit, feet, gallon, mph etc...
|
||||
*/
|
||||
void requestIsMetricSystem();
|
||||
// bool isMetricSystem(uint8_t retry=SEND_RETRIES);
|
||||
void requestConfiguration();
|
||||
|
||||
|
||||
/**
|
||||
@@ -180,9 +194,6 @@ class MySensor : public RF24
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void debugPrint(const char *fmt, ... );
|
||||
int freeRam();
|
||||
@@ -199,44 +210,24 @@ class MySensor : public RF24
|
||||
MyMessage msg; // Buffer for incoming messages.
|
||||
uint8_t failedTransmissions;
|
||||
boolean relayMode;
|
||||
// char convBuffer[20];
|
||||
|
||||
void setupRelayMode();
|
||||
void setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate);
|
||||
void findParentNode();
|
||||
boolean sendRoute(MyMessage message);
|
||||
boolean sendWrite(uint8_t dest, MyMessage message);
|
||||
// void sendInternal(uint8_t variableType, const char *value);
|
||||
// boolean sendAck(MyMessage message);
|
||||
boolean sendData(uint8_t from, uint8_t to, uint8_t childId, uint8_t messageType, uint8_t type, const char *data, uint8_t length, boolean binaryMessage);
|
||||
boolean sendWrite(uint8_t dest, MyMessage message, bool broadcast=false);
|
||||
uint8_t validate(MyMessage message);
|
||||
void sendChildren();
|
||||
|
||||
|
||||
private:
|
||||
// Callbacks for reqeusts
|
||||
/* struct callback {
|
||||
bool active; // Deactivates callback after each reply
|
||||
uint8_t command; // Command type
|
||||
uint8_t sender;
|
||||
uint8_t sensor;
|
||||
uint8_t type;
|
||||
void (*msgCallback)(MyMessage, bool);
|
||||
};*/
|
||||
|
||||
|
||||
MyMessage ack; // Buffer for ack messages.
|
||||
void (*msgCallback)(MyMessage); // Callback for undefined incoming messages
|
||||
|
||||
void requestNodeId();
|
||||
uint8_t crc8Message(MyMessage);
|
||||
// MyMessage wait(MyMessage msg, uint8_t expectedReceiveType, uint8_t retry);
|
||||
// MyMessage getInternal(uint8_t variableType, uint8_t retry=SEND_RETRIES);
|
||||
|
||||
uint8_t getChildRoute(uint8_t childId);
|
||||
void addChildRoute(uint8_t childId, uint8_t route);
|
||||
void removeChildRoute(uint8_t childId);
|
||||
void clearChildRoutes();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <MyMessage.h>
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
#include <EEPROM.h>
|
||||
#include <RF24.h>
|
||||
|
||||
|
||||
@@ -48,18 +47,15 @@ void loop()
|
||||
|
||||
void incomingMessage(MyMessage message) {
|
||||
// We only expect one type of message from controller. But we better check anyway.
|
||||
Serial.println("hej");
|
||||
if (message.getType()==V_LIGHT) {
|
||||
bool status = message.getBool();
|
||||
|
||||
if (message.type==V_LIGHT) {
|
||||
// Change relay state
|
||||
digitalWrite(message.getSensor(), status?RELAY_ON:RELAY_OFF);
|
||||
digitalWrite(message.sensor, message.getBool()?RELAY_ON:RELAY_OFF);
|
||||
|
||||
// Write some debug info
|
||||
Serial.print("Incoming change for relay on pin:");
|
||||
Serial.print(message.getSensor());
|
||||
Serial.print("Incoming change for sensor:");
|
||||
Serial.print(message.sensor);
|
||||
Serial.print(", New status: ");
|
||||
Serial.println(status);
|
||||
}
|
||||
Serial.println(message.getBool());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user