Fix comment. Pseudo random.

This commit is contained in:
Henrik Ekblad
2014-05-16 07:24:24 +02:00
parent a31d9d1074
commit 7080520a3f
4 changed files with 184 additions and 195 deletions
+4 -4
View File
@@ -26,16 +26,16 @@ char* MyMessage::getString(char *buffer) {
itoa(bValue, buffer, MAX_PAYLOAD);
break;
case P_INT16:
itoa(iValue, data, MAX_PAYLOAD);
itoa(iValue, buffer, MAX_PAYLOAD);
break;
case P_UINT16:
ltoa(uiValue, data, MAX_PAYLOAD);
ltoa(uiValue, buffer, MAX_PAYLOAD);
break;
case P_LONG32:
ltoa(lValue, data, MAX_PAYLOAD);
ltoa(lValue, buffer, MAX_PAYLOAD);
break;
case P_ULONG32:
ltoa(ulValue, data, MAX_PAYLOAD);
ltoa(ulValue, buffer, MAX_PAYLOAD);
break;
case P_CUSTOM:
// TODO: Ok, what do we do here? We should probably convert this to hex
+2 -2
View File
@@ -22,8 +22,8 @@
// Message types
typedef enum {
C_PRESENTATION = 0,
C_SET_VARIABLE = 1,
C_REQ_VARIABLE = 2,
C_SET = 1,
C_REQ = 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.
+174 -169
View File
@@ -111,11 +111,10 @@ void MySensor::findParentNode() {
// Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to)
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();
// Wait for ack responses 5 seconds
while (millis() - enter < 5000) {
// Wait for ack responses slightly more than 1 second
while (millis() - enter < 1200) {
process();
}
@@ -187,6 +186,8 @@ bool MySensor::send(MyMessage message, bool enableAck) {
message.sender = s.nodeId;
if (enableAck) {
mSetCommand(message,C_SET_WITH_ACK);
} else {
mSetCommand(message,C_SET);
}
return sendRoute(message);
}
@@ -209,15 +210,14 @@ void MySensor::sketchInfo(const char *name, const char *version) {
}
void MySensor::request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) {
buildSend(msg, s.nodeId, destination, childSensorId, C_REQ_VARIABLE, variableType);
buildSend(msg, s.nodeId, destination, childSensorId, C_REQ, variableType);
}
void MySensor::requestTime() {
buildSend(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_TIME);
}
void MySensor::requestConfiguration() {
void MySensor::requestConfig() {
buildSend(msg, s.nodeId, GATEWAY_ADDRESS, NODE_CHILD_ID, C_INTERNAL, I_CONFIG);
}
@@ -225,179 +225,184 @@ boolean MySensor::process() {
uint8_t pipe;
boolean available = RF24::available(&pipe);
if (available && pipe<7) {
uint8_t len = RF24::getDynamicPayloadSize();
RF24::read(&msg, len);
RF24::writeAckPayload(pipe,&pipe, 1 );
if (!available || pipe>6)
return false;
uint8_t valid = validate(msg);
boolean ok = valid == VALIDATE_OK;
uint8_t len = RF24::getDynamicPayloadSize();
RF24::read(&msg, len);
RF24::writeAckPayload(pipe,&pipe, 1 );
// 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.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, valid==0?"ok":valid==1?"ec":"ev", msg.getString());
uint8_t valid = validate(msg);
boolean ok = valid == VALIDATE_OK;
if (ok) {
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;
// 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.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, valid==0?"ok":valid==1?"ec":"ev", msg.getString());
if (relayMode && command == C_INTERNAL && type == I_PING && s.nodeId != AUTO) {
// Relaying nodes should always answer ping messages
// Wait a random delay of 0-2 seconds to minimize collision
// between ping ack messages from other relaying nodes
randomSeed(millis());
delay(random(2000));
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);
if (!ok)
return false;
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) {
// Relaying nodes should always answer ping messages
// Wait a random delay of 0-2 seconds to minimize collision
// between ping ack messages from other relaying nodes
delay(millis() & 0x3ff);
build(msg, s.nodeId, sender, NODE_CHILD_ID, C_INTERNAL, I_PING_ACK);
msg.set(s.distance);
sendWrite(sender, msg);
return false;
} else if (destination == s.nodeId) {
// This message is addressed to this node
if (relayMode && last != s.parentNodeId) {
// Message is from one of the child nodes. Add it to routing table.
addChildRoute(sender, last);
}
if (command == C_INTERNAL) {
if (type == I_PING_ACK) {
// We've received a reply to our PING message looking for parent.
uint8_t distance = msg.getByte();
if (distance<s.distance-1) {
// Found a neighbor closer to GW than previously found
s.distance = distance + 1;
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);
}
return false;
} else if (destination == s.nodeId) {
// This message is addressed to this node
if (relayMode && last != s.parentNodeId) {
// Message is from one of the child nodes. Add it to routing table.
addChildRoute(sender, last);
}
if (command == C_INTERNAL) {
if (type == I_PING_ACK) {
uint8_t distance = msg.getByte();
if (distance<s.distance-1) {
// Found a neighbor closer to GW than previously found
s.distance = distance + 1;
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);
}
} else if (type == I_REQUEST_ID && sender == GATEWAY_ADDRESS) {
if (s.nodeId == AUTO) {
s.nodeId = msg.getByte();
// Write id to EEPROM
if (s.nodeId == AUTO) {
// sensor net gateway will return max id if all sensor id are taken
debug(PSTR("full\n"));
while (1); // Wait here. Nothing else we can do...
} else {
RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(s.nodeId));
eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, s.nodeId);
}
debug(PSTR("id=%d\n"), s.nodeId);
}
return false;
} else if (relayMode && sender == GATEWAY_ADDRESS) {
if (type == I_RELAY_NODE && destination != GATEWAY_ADDRESS) {
// 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.
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') {
// 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
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;
}
}
}
// Check if sender requests an ack back.
if (command == C_SET_WITH_ACK) {
ack = msg;
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.
mSetCommand(msg,C_SET_VARIABLE);
}
// Call incoming message callback if available
if (msgCallback != NULL) {
msgCallback(msg);
}
// Return true if message was addressed for this node...
return true;
} else if (relayMode) {
// We should try to relay this message to another node
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
// all listening to this nodes pipe.
//
// +----B
// -A
// +----C------D
//
// We're node C, Message comes from A and has destination D
//
// lookup route in table and send message there
sendWrite(route, msg);
} else if (pipe == CURRENT_NODE_PIPE) {
// A message comes from a child node and we have no
// route for it.
//
// +----B
// -A
// +----C------D <-- Message comes from D
//
// We're node C
//
// Message should be passed to node A (this nodes relay)
// This message should be routed back towards sensor net gateway
sendWrite(s.parentNodeId, msg);
// Add this child to our "routing table" if it not already exist
addChildRoute(sender, last);
} else {
// We're snooped a message directed to gateway from another branch
// Make sure to remove the sender node from our routing table.
//
// +-----B <-- Message comes from here
// -A
// +-----C <-- We're here
//
// So the sender of message should never be in our
// routing table.
//
// We could also end up in this else-statement if message
// destination has no route.
// This can happen if a node never has sent any message to
// sensor net gateway (which will build up routing information in all nodes
// that gets passed).
// THIS SHOULD NOT HAPPEN ANY MORE
/*if (s.nodeId == GATEWAY_ADDRESS) {
// We should perhaps inform gateway about the no-route situation?!
debug(PSTR("ro=?\n"));
} else if (type == I_REQUEST_ID && sender == GATEWAY_ADDRESS) {
if (s.nodeId == AUTO) {
s.nodeId = msg.getByte();
// Write id to EEPROM
if (s.nodeId == AUTO) {
// sensor net gateway will return max id if all sensor id are taken
debug(PSTR("full\n"));
while (1); // Wait here. Nothing else we can do...
} else {
//debug(PSTR("Remove child node from routing table.\n"));
removeChildRoute(sender);
}*/
RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(s.nodeId));
eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, s.nodeId);
}
debug(PSTR("id=%d\n"), s.nodeId);
}
return false;
} else if (relayMode && sender == GATEWAY_ADDRESS) {
if (type == I_RELAY_NODE && destination != GATEWAY_ADDRESS) {
// Gatewa/controller wants this node to refresh its parent node
findParentNode();
// Send relay information back to sensor net gateway node device.
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') {
// 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
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;
}
}
}
// Check if sender requests an ack back.
if (command == C_SET_WITH_ACK) {
ack = msg;
mSetCommand(ack,C_SET);
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.
mSetCommand(msg,C_SET);
}
// Call incoming message callback if available
if (msgCallback != NULL) {
msgCallback(msg);
}
// Return true if message was addressed for this node...
return true;
} else if (relayMode) {
// We should try to relay this message to another node
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
// all listening to this nodes pipe.
//
// +----B
// -A
// +----C------D
//
// We're node C, Message comes from A and has destination D
//
// lookup route in table and send message there
sendWrite(route, msg);
} else if (pipe == CURRENT_NODE_PIPE) {
// A message comes from a child node and we have no
// route for it.
//
// +----B
// -A
// +----C------D <-- Message comes from D
//
// We're node C
//
// Message should be passed to node A (this nodes relay)
// This message should be routed back towards sensor net gateway
sendWrite(s.parentNodeId, msg);
// Add this child to our "routing table" if it not already exist
addChildRoute(sender, last);
} else {
// We're snooped a message directed to gateway from another branch
// Make sure to remove the sender node from our routing table.
//
// +-----B <-- Message comes from here
// -A
// +-----C <-- We're here
//
// So the sender of message should never be in our
// routing table.
//
// We could also end up in this else-statement if message
// destination has no route.
// This can happen if a node never has sent any message to
// sensor net gateway (which will build up routing information in all nodes
// that gets passed).
// THIS SHOULD NOT HAPPEN ANY MORE
/*if (s.nodeId == GATEWAY_ADDRESS) {
// We should perhaps inform gateway about the no-route situation?!
debug(PSTR("ro=?\n"));
} else {
//debug(PSTR("Remove child node from routing table.\n"));
removeChildRoute(sender);
}*/
}
}
return false;
}
+4 -20
View File
@@ -54,7 +54,6 @@
#define CURRENT_NODE_PIPE ((uint8_t)1)
#define BROADCAST_PIPE ((uint8_t)2)
#define SEND_RETRIES 3
#define FIND_RELAY_AFTER_FAILED_TRANSMISSIONS 5
#define build(_msg, _sender, _destination, _sensor, _cmd, _type) \
@@ -127,10 +126,9 @@ class MySensor : public RF24
*
* @param msg Message to send
* @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack.
* @param retry Number of attempts before giving up. Default is SEND_RETRIES
* @return true Retuns false if ack is enabled and no ack came back
* @return true Returns true if message reached the first stop on its way to destination.
*/
bool send(MyMessage msg, bool ack=false/*, uint8_t retry=SEND_RETRIES*/);
bool send(MyMessage msg, bool ack=false);
/**
* Send this nodes battery level to gateway.
@@ -138,19 +136,6 @@ class MySensor : public RF24
*/
void sendBatteryLevel(uint8_t level);
/**
* Fetches a value from gateway or some other sensor in the radio network. Resends request and waits for response.
* Note that if you have registered a callback in begin() it will also be called before message is returned
* by get()
*
* @param childSensorId The unique child id for the different sensors connected to this arduino. 0-254.
* @param variableType The variableType to fetch
* @param destination The nodeId of other node in radio network. Default is gateway
* @param number of attempts to fetch
* @return Message response
*/
// MyMessage get(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS, uint8_t retry=SEND_RETRIES);
/**
* Requests a value from gateway or some other sensor in the radio network.
* Make sure to add callback in begin() to handle request response.
@@ -162,7 +147,6 @@ class MySensor : public RF24
*/
void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS);
/**
* Requests time from controller. Pick up response in callback.
*
@@ -171,13 +155,13 @@ class MySensor : public RF24
void requestTime();
/**
* Fetches configuration from controller. Returns true if metric system has been selected which means
* Requests 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 requestConfiguration();
void requestConfig();
/**