Reduce library size

This commit is contained in:
Henrik Ekblad
2014-05-15 07:40:07 +02:00
parent 710d445815
commit a31d9d1074
7 changed files with 176 additions and 395 deletions
+1 -1
View File
@@ -12,6 +12,6 @@
/***
* Enable/Disable debug logging
*/
#define DEBUG
//#define DEBUG
#endif
+2 -2
View File
@@ -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));
}
+53 -150
View File
@@ -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;
}
+26 -44
View File
@@ -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.
+64 -155
View File
@@ -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
+24 -33
View File
@@ -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());
}
}