diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp index 25800f5..cf6abd4 100644 --- a/libraries/MySensors/MyGateway.cpp +++ b/libraries/MySensors/MyGateway.cpp @@ -28,9 +28,9 @@ MyGateway::MyGateway(uint8_t _cepin, uint8_t _cspin, uint8_t _inclusion_time, ui void MyGateway::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate, void (*inDataCallback)(char *)) { Serial.begin(BAUD_RATE); - relayMode = true; + repeaterMode = true; isGateway = true; - setupRelayMode(); + setupRepeaterMode(); if (inDataCallback != NULL) { useWriteCallback = true; @@ -157,7 +157,7 @@ void MyGateway::parseAndSend(char *commandBuffer) { msg.type = type; mSetCommand(msg,command); msg.set(value); - ok = sendRoute(&msg); + ok = sendRoute(msg); if (!ok) { errBlink(1); } @@ -178,7 +178,7 @@ void MyGateway::setInclusionMode(boolean newMode) { // Override normal validate to add error blink if crc check fails -uint8_t MyGateway::validate(MyMessage *message) { +uint8_t MyGateway::validate(MyMessage &message) { uint8_t res = MySensor::validate(message); if (res == VALIDATE_BAD_CRC) { errBlink(1); @@ -189,8 +189,8 @@ uint8_t MyGateway::validate(MyMessage *message) { void MyGateway::processRadioMessage() { if (process()) { // A new message was received from one of the sensors - MyMessage *message = getLastMessage(); - if (mGetCommandP(message) == C_PRESENTATION && inclusionMode) { + MyMessage message = getLastMessage(); + if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { rxBlink(3); } else { rxBlink(1); @@ -215,8 +215,8 @@ void MyGateway::serial(const char *fmt, ... ) { } } -void MyGateway::serial(MyMessage *msg) { - serial(PSTR("%d;%d;%d;%d;%s\n"),msg->sender, msg->sensor, mGetCommandP(msg), msg->type, msg->getString(convBuf)); +void MyGateway::serial(MyMessage &msg) { + serial(PSTR("%d;%d;%d;%d;%s\n"),msg.sender, msg.sensor, mGetCommand(msg), msg.type, msg.getString(convBuf)); } diff --git a/libraries/MySensors/MyGateway.h b/libraries/MySensors/MyGateway.h index e02b8e2..8b520e5 100644 --- a/libraries/MySensors/MyGateway.h +++ b/libraries/MySensors/MyGateway.h @@ -69,8 +69,8 @@ class MyGateway : public MySensor uint8_t pinEr; void serial(const char *fmt, ... ); - void serial(MyMessage *msg); - uint8_t validate(MyMessage *message); + void serial(MyMessage &msg); + uint8_t validate(MyMessage &message); void interruptStartInclusion(); void checkButtonTriggeredInclusion(); void setInclusionMode(boolean newMode); diff --git a/libraries/MySensors/MyMessage.cpp b/libraries/MySensors/MyMessage.cpp index d11c703..2ac6006 100644 --- a/libraries/MySensors/MyMessage.cpp +++ b/libraries/MySensors/MyMessage.cpp @@ -15,26 +15,26 @@ MyMessage::MyMessage(uint8_t _sensor, uint8_t _type) { /* Getters for payload converted to desired form */ -void* MyMessage::getCustom() { +void* MyMessage::getCustom() const { return (void *)data; } -char* MyMessage::getString() { +const char* MyMessage::getString() const { uint8_t payloadType = miGetPayloadType(); if (payloadType == P_STRING) { - data[miGetLength()] = '\0'; return data; } else { return NULL; } } -char* MyMessage::getString(char *buffer) { +char* MyMessage::getString(char *buffer) const { uint8_t payloadType = miGetPayloadType(); if (payloadType == P_STRING) { - data[miGetLength()] = '\0'; - return data; + strncpy(buffer, data, miGetLength()); + buffer[miGetLength()] = '\0'; + return buffer; } else if (buffer != NULL) { switch(payloadType) { case P_BYTE: @@ -65,7 +65,7 @@ char* MyMessage::getString(char *buffer) { } } -uint8_t MyMessage::getByte() { +uint8_t MyMessage::getByte() const { switch(miGetPayloadType()) { case P_BYTE: return data[0]; @@ -76,15 +76,15 @@ uint8_t MyMessage::getByte() { } } -bool MyMessage::getBool() { +bool MyMessage::getBool() const { return !(data[0]-'0'==0); } -double MyMessage::getDouble() { +double MyMessage::getDouble() const { return strtod(data, NULL); } -long MyMessage::getLong() { +long MyMessage::getLong() const { switch(miGetPayloadType()) { case P_LONG32: return lValue; @@ -95,7 +95,7 @@ long MyMessage::getLong() { } } -unsigned long MyMessage::getULong() { +unsigned long MyMessage::getULong() const { switch(miGetPayloadType()) { case P_ULONG32: return ulValue; @@ -106,7 +106,7 @@ unsigned long MyMessage::getULong() { } } -int MyMessage::getInt() { +int MyMessage::getInt() const { switch(miGetPayloadType()) { case P_INT16: return iValue; @@ -117,7 +117,7 @@ int MyMessage::getInt() { } } -unsigned int MyMessage::getUInt() { +unsigned int MyMessage::getUInt() const { switch(miGetPayloadType()) { case P_UINT16: return uiValue; @@ -130,85 +130,85 @@ unsigned int MyMessage::getUInt() { } -MyMessage* MyMessage::setType(uint8_t _type) { +MyMessage& MyMessage::setType(uint8_t _type) { type = _type; - return this; + return *this; } -MyMessage* MyMessage::setSensor(uint8_t _sensor) { +MyMessage& MyMessage::setSensor(uint8_t _sensor) { sensor = _sensor; - return this; + return *this; } -MyMessage* MyMessage::setDestination(uint8_t _destination) { +MyMessage& MyMessage::setDestination(uint8_t _destination) { destination = _destination; - return this; + return *this; } // Set payload -MyMessage* MyMessage::set(void* value, uint8_t length) { +MyMessage& MyMessage::set(void* value, uint8_t length) { miSetPayloadType(P_CUSTOM); miSetLength(length); memcpy(data, value, min(length, MAX_PAYLOAD)); - return this; + return *this; } -MyMessage* MyMessage::set(const char* value) { +MyMessage& MyMessage::set(const char* value) { uint8_t length = strlen(value); miSetLength(length); miSetPayloadType(P_STRING); strncpy(data, value, min(length, MAX_PAYLOAD)); - return this; + return *this; } -MyMessage* MyMessage::set(uint8_t value) { +MyMessage& MyMessage::set(uint8_t value) { miSetLength(1); miSetPayloadType(P_BYTE); data[0] = value; - return this; + return *this; } -MyMessage* MyMessage::set(bool value) { +MyMessage& MyMessage::set(bool value) { miSetLength(1); miSetPayloadType(P_STRING); data[0] = value?'1':'0'; - return this; + return *this; } -MyMessage* MyMessage::set(double value, uint8_t decimals) { +MyMessage& MyMessage::set(double value, uint8_t decimals) { dtostrf(value,2,decimals,data); miSetLength(strlen(data)); miSetPayloadType(P_STRING); - return this; + return *this; } -MyMessage* MyMessage::set(unsigned long value) { +MyMessage& MyMessage::set(unsigned long value) { miSetPayloadType(P_ULONG32); miSetLength(4); ulValue = value; - return this; + return *this; } -MyMessage* MyMessage::set(long value) { +MyMessage& MyMessage::set(long value) { miSetPayloadType(P_LONG32); miSetLength(4); lValue = value; - return this; + return *this; } -MyMessage* MyMessage::set(unsigned int value) { +MyMessage& MyMessage::set(unsigned int value) { miSetPayloadType(P_UINT16); miSetLength(2); uiValue = value; - return this; + return *this; } -MyMessage* MyMessage::set(int value) { +MyMessage& MyMessage::set(int value) { miSetPayloadType(P_INT16); miSetLength(2); iValue = value; - return this; + return *this; } diff --git a/libraries/MySensors/MyMessage.h b/libraries/MySensors/MyMessage.h index ab6da6b..6bebda3 100644 --- a/libraries/MySensors/MyMessage.h +++ b/libraries/MySensors/MyMessage.h @@ -24,9 +24,8 @@ typedef enum { C_PRESENTATION = 0, 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. + C_INTERNAL = 3, + C_STREAM = 4 // For Firmware and other larger chunks of data that need to be divided into pieces. } command; // Type of sensor data (for set/req/ack messages) @@ -49,7 +48,7 @@ typedef enum { typedef enum { S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND, S_RAIN, S_UV, S_WEIGHT, S_POWER, S_HEATER, S_DISTANCE, S_LIGHT_LEVEL, S_ARDUINO_NODE, - S_ARDUINO_RELAY, S_LOCK, S_IR, S_WATER + S_ARDUINO_REPEATER_NODE, S_LOCK, S_IR, S_WATER } sensor; // Type of data stream (for streamed message) @@ -83,29 +82,23 @@ typedef enum { // 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 mSetVersionP(_msg,_version) BF_SET(_msg->version_length, _version, 0, 3) -#define mSetLengthP(_msg,_length) BF_SET(_msg->version_length, _length, 3, 5) -#define mSetCommandP(_msg,_command) BF_SET(_msg->command_payload, _command, 0, 4) -#define mSetPayloadTypeP(_msg, _pt) BF_SET(_msg->command_payload, _pt, 4, 4) +#define mSetCommand(_msg,_command) BF_SET(_msg.command_ack_payload, _command, 0, 3) +#define mSetAck(_msg,_command) BF_SET(_msg.command_ack_payload, _command, 3, 1) +#define mSetPayloadType(_msg, _pt) BF_SET(_msg.command_ack_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) -#define mGetVersionP(_msg) BF_GET(_msg->version_length, 0, 3) -#define mGetLengthP(_msg) BF_GET(_msg->version_length, 3, 5) -#define mGetCommandP(_msg) BF_GET(_msg->command_payload, 0, 4) -#define mGetPayloadTypeP(_msg) BF_GET(_msg->command_payload, 4, 4) +#define mGetCommand(_msg) BF_GET(_msg.command_ack_payload, 0, 3) +#define mGetAck(_msg) BF_GET(_msg.command_ack_payload, 3, 1) +#define mGetPayloadType(_msg) BF_GET(_msg.command_ack_payload, 4, 4) -// internal access for special fileds -#define miGetPayloadType() BF_GET(command_payload, 4, 4) +// internal access for special fields +#define miGetPayloadType() BF_GET(command_ack_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) +#define miSetPayloadType(_pt) BF_SET(command_ack_payload, _pt, 4, 4) class MyMessage @@ -116,47 +109,50 @@ public: MyMessage(uint8_t sensor, uint8_t type); - char* getString(); /** * If payload is something else than P_STRING you can have the payload value converted * into 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); - void* getCustom(); - uint8_t getByte(); - bool getBool(); - double getDouble(); - long getLong(); - unsigned long getULong(); - int getInt(); - unsigned int getUInt(); + char* getString(char *buffer) const; + const char* getString() const; + void* getCustom() const; + uint8_t getByte() const; + bool getBool() const; + double getDouble() const; + long getLong() const; + unsigned long getULong() const; + int getInt() const; + unsigned int getUInt() const; // Setters for building message "on the fly" - MyMessage* setType(uint8_t type); - MyMessage* setSensor(uint8_t sensor); - MyMessage* setDestination(uint8_t destination); + MyMessage& setType(uint8_t type); + MyMessage& setSensor(uint8_t sensor); + MyMessage& setDestination(uint8_t destination); // Setters for payload - MyMessage* set(void* payload, uint8_t length); - MyMessage* set(const char* value); - MyMessage* set(uint8_t value); - MyMessage* set(bool value); - MyMessage* set(double value, uint8_t decimals); - MyMessage* set(unsigned long value); - MyMessage* set(long value); - MyMessage* set(unsigned int value); - MyMessage* set(int value); + MyMessage& set(void* payload, uint8_t length); + MyMessage& set(const char* value); + MyMessage& set(uint8_t value); + MyMessage& set(bool value); + MyMessage& set(double value, uint8_t decimals); + MyMessage& set(unsigned long value); + MyMessage& set(long value); + MyMessage& set(unsigned int value); + MyMessage& set(int value); - uint8_t version_length; // 3 bit - Protocol version + 5 bit - Length of payload - uint8_t command_payload; // 4 bit - Command type + 4 bit - Payload data type - uint8_t type; // 8 bit - Type varies depending on command - uint8_t sensor; // 8 bit - Id of sensor that this message concerns. - uint8_t sender; // 8 bit - Id of sender node - 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 + uint8_t version_length; // 3 bit - Protocol version + // 5 bit - Length of payload + uint8_t command_ack_payload; // 3 bit - Command type + // 1 bit - Indicator that receiver should send an ack back. + // 4 bit - Payload data type + uint8_t type; // 8 bit - Type varies depending on command + uint8_t sensor; // 8 bit - Id of sensor that this message concerns. + uint8_t sender; // 8 bit - Id of sender node + 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 diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index fb02828..44901a2 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -14,12 +14,13 @@ // Inline function and macros -inline MyMessage* build (MyMessage* msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type) { - msg->sender = sender; - msg->destination = destination; - msg->sensor = sensor; - msg->type = type; - mSetCommandP(msg,command); +inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { + msg.sender = sender; + msg.destination = destination; + msg.sensor = sensor; + msg.type = type; + mSetCommand(msg,command); + mSetAck(msg,enableAck); return msg; } @@ -28,14 +29,14 @@ MySensor::MySensor(uint8_t _cepin, uint8_t _cspin) : RF24(_cepin, _cspin) { } -void MySensor::begin(void (*_msgCallback)(MyMessage), uint8_t _nodeId, boolean _relayMode, rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) { +void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) { Serial.begin(BAUD_RATE); isGateway = false; - relayMode = _relayMode; + repeaterMode = _repeaterMode; msgCallback = _msgCallback; - if (relayMode) { - setupRelayMode(); + if (repeaterMode) { + setupRepeaterMode(); } setupRadio(paLevel, channel, dataRate); @@ -60,19 +61,19 @@ void MySensor::begin(void (*_msgCallback)(MyMessage), uint8_t _nodeId, boolean _ requestNodeId(); } - debug(PSTR("%s started, id %d\n"), relayMode?"relay":"sensor", nc.nodeId); + debug(PSTR("%s started, id %d\n"), repeaterMode?"repeater":"sensor", nc.nodeId); // Open reading pipe for messages directed to this node (set write pipe to same) RF24::openReadingPipe(WRITE_PIPE, TO_ADDR(nc.nodeId)); RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId)); // Send presentation for this radio node (attach - present(NODE_SENSOR_ID, relayMode? S_ARDUINO_RELAY : S_ARDUINO_NODE); + present(NODE_SENSOR_ID, repeaterMode? S_ARDUINO_REPEATER_NODE : S_ARDUINO_NODE); // Send a configuration exchange request to controller // Node sends parent node. Controller answers with latest node configuration // which is picked up in process() - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG)->set(nc.parentNodeId)); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(nc.parentNodeId)); // Wait configuration reply. waitForReply(); @@ -102,7 +103,7 @@ void MySensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_ RF24::openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); } -void MySensor::setupRelayMode(){ +void MySensor::setupRepeaterMode(){ childNodeTable = new uint8_t[256]; eeprom_read_block((void*)childNodeTable, (void*)EEPROM_ROUTES_ADDRESS, 256); } @@ -119,7 +120,7 @@ ControllerConfig MySensor::getConfig() { void MySensor::requestNodeId() { debug(PSTR("req node id\n")); RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId)); - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST)->set("")); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set("")); waitForReply(); } @@ -131,8 +132,8 @@ void MySensor::findParentNode() { nc.distance = 255; // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to) - build(&msg, nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING)->set(""); - sendWrite(BROADCAST_ADDRESS, &msg, true); + build(msg, nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING, false).set(""); + sendWrite(BROADCAST_ADDRESS, msg, true); // Wait for ping response. waitForReply(); @@ -146,26 +147,26 @@ void MySensor::waitForReply() { } } -boolean MySensor::sendRoute(MyMessage *message) { +boolean MySensor::sendRoute(MyMessage &message) { // Make sure to process any incoming messages before sending (could this end up in recursive loop?) // process(); - bool isInternal = mGetCommandP(message) == C_INTERNAL; + bool isInternal = mGetCommand(message) == C_INTERNAL; // If we still don't have any node id, re-request and skip this message. - if (nc.nodeId == AUTO && !(isInternal && message->type == I_ID_REQUEST)) { + if (nc.nodeId == AUTO && !(isInternal && message.type == I_ID_REQUEST)) { requestNodeId(); return false; } - if (relayMode) { - uint8_t dest = message->destination; + if (repeaterMode) { + uint8_t dest = message.destination; uint8_t route = getChildRoute(dest); if (route>GATEWAY_ADDRESS && routetype == I_ID_RESPONSE && dest==BROADCAST_ADDRESS) { + } else if (isInternal && message.type == I_ID_RESPONSE && dest==BROADCAST_ADDRESS) { // Node has not yet received any id. We need to send it // by doing a broadcast sending, return sendWrite(BROADCAST_ADDRESS, message, true); @@ -192,59 +193,56 @@ boolean MySensor::sendRoute(MyMessage *message) { return false; } -boolean MySensor::sendWrite(uint8_t next, MyMessage *message, bool broadcast) { - uint8_t length = mGetLengthP(message); - message->last = nc.nodeId; - mSetVersionP(message, PROTOCOL_VERSION); - message->crc = crc8Message(message); +boolean MySensor::sendWrite(uint8_t next, MyMessage &message, bool broadcast) { + uint8_t length = mGetLength(message); + message.last = nc.nodeId; + mSetVersion(message, PROTOCOL_VERSION); + message.crc = crc8Message(message); // Make sure radio has powered up RF24::powerUp(); RF24::stopListening(); RF24::openWritingPipe(TO_ADDR(next)); - bool ok = RF24::write(message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length), broadcast); + bool ok = RF24::write(&message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length), broadcast); RF24::startListening(); debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d, st=%s:%s\n"), - message->sender,message->last, next, message->destination, message->sensor, mGetCommandP(message), message->type, ok?"ok":"fail", message->getString(convBuf)); + message.sender,message.last, next, message.destination, message.sensor, mGetCommand(message), message.type, ok?"ok":"fail", message.getString(convBuf)); return ok; } -bool MySensor::send(MyMessage *message, bool enableAck) { - message->sender = nc.nodeId; - if (enableAck) { - mSetCommandP(message,C_SET_WITH_ACK); - } else { - mSetCommandP(message,C_SET); - } +bool MySensor::send(MyMessage &message, bool enableAck) { + message.sender = nc.nodeId; + mSetCommand(message,C_SET); + mSetAck(message,enableAck); return sendRoute(message); } -void MySensor::sendBatteryLevel(uint8_t value) { - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL)->set(value)); +void MySensor::sendBatteryLevel(uint8_t value, bool enableAck) { + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value)); } -void MySensor::present(uint8_t childSensorId, uint8_t sensorType) { - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType)->set(LIBRARY_VERSION)); +void MySensor::present(uint8_t childSensorId, uint8_t sensorType, bool enableAck) { + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(LIBRARY_VERSION)); } -void MySensor::sendSketchInfo(const char *name, const char *version) { +void MySensor::sendSketchInfo(const char *name, const char *version, bool enableAck) { if (name != NULL) { - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME)->set(name)); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name)); } if (version != NULL) { - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION)->set(version)); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version)); } } void MySensor::request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) { - sendRoute(build(&msg, nc.nodeId, destination, childSensorId, C_REQ, variableType)); + sendRoute(build(msg, nc.nodeId, destination, childSensorId, C_REQ, variableType, false)); } void MySensor::requestTime(void (* _timeCallback)(unsigned long)) { timeCallback = _timeCallback; - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME)); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false)); } @@ -259,7 +257,7 @@ boolean MySensor::process() { RF24::read(&msg, len); RF24::writeAckPayload(pipe,&pipe, 1 ); - uint8_t valid = validate(&msg); + uint8_t valid = validate(msg); boolean ok = valid == VALIDATE_OK; // Make sure string gets terminated ok for full string messages. @@ -276,16 +274,26 @@ boolean MySensor::process() { uint8_t last = msg.last; uint8_t destination = msg.destination; - if (relayMode && command == C_INTERNAL && type == I_PING) { + if (repeaterMode && 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); - sendWrite(sender, build(&msg, nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_PING_ACK)->set(nc.distance), true); + sendWrite(sender, build(msg, nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_PING_ACK, false).set(nc.distance), true); return false; } else if (destination == nc.nodeId) { + // Check if sender requests an ack back. + if (mGetAck(msg)) { + // Copy message + ack = msg; + mSetAck(ack,false); // Reply without ack flag (otherwise we would end up in an eternal loop) + ack.sender = nc.nodeId; + ack.destination = msg.sender; + sendRoute(ack); + } + // This message is addressed to this node - if (relayMode && last != nc.parentNodeId) { + if (repeaterMode && last != nc.parentNodeId) { // Message is from one of the child nodes. Add it to routing table. addChildRoute(sender, last); } @@ -334,13 +342,13 @@ boolean MySensor::process() { } break; case I_CHILDREN: - if (relayMode && msg.getByte() == 'C') { + if (repeaterMode && msg.getByte() == 'C') { // Clears child relay data for this node debug(PSTR("rd=clear\n")); for (uint8_t i=0;i< sizeof(childNodeTable); i++) { removeChildRoute(i); } - sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN)->set("")); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); } break; case I_TIME: @@ -352,24 +360,13 @@ boolean MySensor::process() { return false; } } - // Check if sender requests an ack back. - if (command == C_SET_WITH_ACK) { - // Copy message - ack = msg; - mSetCommand(ack,C_SET); - ack.sender = nc.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 && pipe == CURRENT_NODE_PIPE) { + } else if (repeaterMode && pipe == CURRENT_NODE_PIPE) { // We should try to relay this message to another node uint8_t route = getChildRoute(msg.destination); @@ -385,7 +382,7 @@ boolean MySensor::process() { // We're node C, Message comes from A and has destination D // // lookup route in table and send message there - sendWrite(route, &msg); + sendWrite(route, msg); } else { // A message comes from a child node and we have no // route for it. @@ -399,7 +396,7 @@ boolean MySensor::process() { // Message should be passed to node A (this nodes relay) // This message should be routed back towards sensor net gateway - sendWrite(nc.parentNodeId, &msg); + sendWrite(nc.parentNodeId, msg); // Add this child to our "routing table" if it not already exist addChildRoute(sender, last); } @@ -411,16 +408,16 @@ boolean MySensor::process() { } -MyMessage* MySensor::getLastMessage() { - return &msg; +MyMessage& MySensor::getLastMessage() { + return msg; } /* * calculate CRC8 on MyMessage data taking care of data structure and protocol version */ -uint8_t MySensor::crc8Message(MyMessage *message) { - uint8_t len = mGetLengthP(message); +uint8_t MySensor::crc8Message(MyMessage &message) { + uint8_t len = mGetLength(message); uint8_t crc = 0x00; uint8_t loop_count; uint8_t bit_counter; @@ -429,16 +426,16 @@ uint8_t MySensor::crc8Message(MyMessage *message) { uint8_t number_of_bytes_to_read = (uint8_t)sizeof(MyMessage); // Must set crc to a constant value. - message->crc = 0; + message.crc = 0; // fill unused space by zeroes for string data only - if(len>=0 && len < sizeof(message->data)) { - memset(&message->data[len], 0, sizeof(message->data) - len); + if(len>=0 && len < sizeof(message.data)) { + memset(&message.data[len], 0, sizeof(message.data) - len); } for (loop_count = 0; loop_count != number_of_bytes_to_read; loop_count++) { - data = ((uint8_t*)message)[loop_count]; + data = ((uint8_t*)&message)[loop_count]; bit_counter = 8; do { @@ -461,11 +458,11 @@ uint8_t MySensor::crc8Message(MyMessage *message) { } -uint8_t MySensor::validate(MyMessage *message) { - uint8_t oldCrc = message->crc; +uint8_t MySensor::validate(MyMessage &message) { + uint8_t oldCrc = message.crc; uint8_t newCrc = crc8Message(message); - if(!(mGetVersionP(message) == 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; diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 2c1a025..15d8e62 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -95,13 +95,13 @@ class MySensor : public RF24 * Call this in setup(), before calling any other sensor net library methods. * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. * @param nodeId The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller. - * @param relayMode Activate relay mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false + * @param repeaterMode Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false * @param paLevel Radio PA Level for this sensor. Default RF24_PA_MAX * @param channel Radio channel. Default is channel 76 * @param dataRate Radio transmission speed. Default RF24_1MBPS */ - void begin(void (* msgCallback)(MyMessage)=NULL, uint8_t nodeId=AUTO, boolean relayMode=false, rf24_pa_dbm_e paLevel=RF24_PA_LEVEL, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE); + void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, rf24_pa_dbm_e paLevel=RF24_PA_LEVEL, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE); /** * Return the nodes nodeId. @@ -113,16 +113,19 @@ class MySensor : public RF24 * It is usually good to present all attached sensors after power-up in setup(). * * @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. - * @param sensorType The sensor type. See sensor typedef in Message.h. + * @param sensorType The sensor type. See sensor typedef in MyMessage.h. + * @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. */ - void present(uint8_t sensorId, uint8_t sensorType); + void present(uint8_t sensorId, uint8_t sensorType, bool ack=false); /** * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. * @param name String containing a short Sketch name or NULL if not applicable * @param version String containing a short Sketch version or NULL if not applicable + * @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. + * */ - void sendSketchInfo(const char *name, const char *version); + void sendSketchInfo(const char *name, const char *version, bool ack=false); /** * Sends a message to gateway or one of the other nodes in the radio network @@ -131,19 +134,21 @@ class MySensor : public RF24 * @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. * @return true Returns true if message reached the first stop on its way to destination. */ - bool send(MyMessage *msg, bool ack=false); + bool send(MyMessage &msg, bool ack=false); /** * Send this nodes battery level to gateway. * @param level Level between 0-100(%) + * @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. + * */ - void sendBatteryLevel(uint8_t level); + void sendBatteryLevel(uint8_t level, bool ack=false); /** * Requests a value from gateway or some other sensor in the radio network. * Make sure to add callback-method in begin-method to handle request responses. * - * @param childSensorId The unique child id for the different sensors connected to this arduino. 0-254. + * @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 */ @@ -192,7 +197,7 @@ class MySensor : public RF24 /** * Returns the last received message */ - MyMessage* getLastMessage(void); + MyMessage& getLastMessage(void); /** * Sleep (PowerDownMode) the Arduino and radio. Wake up on timer. @@ -229,16 +234,16 @@ class MySensor : public RF24 protected: NodeConfig nc; // Essential settings for node to work ControllerConfig cc; // Configuration coming from controller - bool relayMode; + bool repeaterMode; bool isGateway; MyMessage msg; // Buffer for incoming messages. MyMessage ack; // Buffer for ack messages. - void setupRelayMode(); + void setupRepeaterMode(); void setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate); - boolean sendRoute(MyMessage *message); - boolean sendWrite(uint8_t dest, MyMessage *message, bool broadcast=false); - uint8_t validate(MyMessage *message); + boolean sendRoute(MyMessage &message); + boolean sendWrite(uint8_t dest, MyMessage &message, bool broadcast=false); + uint8_t validate(MyMessage &message); private: #ifdef DEBUG @@ -247,12 +252,12 @@ class MySensor : public RF24 uint8_t failedTransmissions; uint8_t *childNodeTable; // In memory buffer for routing information to other nodes. also stored in EEPROM void (*timeCallback)(unsigned long); // Callback for requested time messages - void (*msgCallback)(MyMessage); // Callback for incoming messages from other nodes and gateway. + void (*msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. void waitForReply(); void requestNodeId(); void findParentNode(); - uint8_t crc8Message(MyMessage *message); + uint8_t crc8Message(MyMessage &message); uint8_t getChildRoute(uint8_t childId); void addChildRoute(uint8_t childId, uint8_t route); void removeChildRoute(uint8_t childId); diff --git a/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino index 9a0282c..047068e 100644 --- a/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino +++ b/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -57,7 +57,7 @@ void loop() if (lastTemperature[i] != temperature && temperature != -127.00) { // Send in the new temperature - gw.send(msg.setSensor(i)->set(temperature,1)); + gw.send(msg.setSensor(i).set(temperature,1)); lastTemperature[i]=temperature; } } diff --git a/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino b/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino index 2c17df6..f8836ff 100644 --- a/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino +++ b/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino @@ -93,7 +93,7 @@ void loop() } } -void incomingMessage(MyMessage message) { +void incomingMessage(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw:"); diff --git a/libraries/MySensors/examples/IrSensor/IrSensor.ino b/libraries/MySensors/examples/IrSensor/IrSensor.ino index a34e024..4505d48 100644 --- a/libraries/MySensors/examples/IrSensor/IrSensor.ino +++ b/libraries/MySensors/examples/IrSensor/IrSensor.ino @@ -54,7 +54,7 @@ void loop() -void incomingMessage(MyMessage message) { +void incomingMessage(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { int incomingRelayStatus = message.getInt(); diff --git a/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino index f834f0c..d74a9d7 100644 --- a/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino +++ b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino @@ -29,7 +29,7 @@ unsigned long SLEEP_TIME = 30; // Sleep time between reads (in seconds) BH1750 lightSensor; MySensor gw; MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); -int lastlux; +uint16_t lastlux; void setup() { diff --git a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino index f04b602..0e4994d 100644 --- a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino +++ b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino @@ -38,7 +38,7 @@ void loop() gw.process(); } -void incomingMessage(MyMessage message) { +void incomingMessage(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { // Change relay state diff --git a/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino b/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino index 9aed1b4..d242988 100644 --- a/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino +++ b/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino @@ -71,8 +71,7 @@ void loop() -void incomingMessage(MyMessage message) { - Serial.println(gw.getInternalTemp()); +void incomingMessage(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { // Change relay state diff --git a/libraries/MySensors/examples/RelayingNode/RelayingNode.ino b/libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino similarity index 53% rename from libraries/MySensors/examples/RelayingNode/RelayingNode.ino rename to libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino index 95975b6..e023176 100644 --- a/libraries/MySensors/examples/RelayingNode/RelayingNode.ino +++ b/libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino @@ -1,8 +1,7 @@ -// Example sketch showing how to create a node thay relays messages +// Example sketch showing how to create a node thay repeates messages // from nodes far from gateway back to gateway. -// Important here is that node uses Relay-class and calls -// gw.messageAvailable() frequently. This sketch should not -// sleep. +// It is important that nodes that has enabled repeater mode calls +// gw.preocess() frequently. This node should never sleep. #include #include @@ -12,11 +11,11 @@ MySensor gw; void setup() { - // The third argument enables relaying mode. + // The third argument enables repeater mode. gw.begin(NULL, AUTO, true); //Send the sensor node sketch version information to the gateway - gw.sendSketchInfo("Relaying Node", "1.0"); + gw.sendSketchInfo("Repeater Node", "1.0"); } void loop() diff --git a/libraries/MySensors/examples/ServoActuator/ServoActuator.ino b/libraries/MySensors/examples/ServoActuator/ServoActuator.ino index b54aed2..a0b8853 100644 --- a/libraries/MySensors/examples/ServoActuator/ServoActuator.ino +++ b/libraries/MySensors/examples/ServoActuator/ServoActuator.ino @@ -49,7 +49,7 @@ void loop() } } -void incomingMessage(MyMessage message) { +void incomingMessage(const MyMessage &message) { myservo.attach(SERVO_DIGITAL_OUT_PIN); attachedServo = true; if (message.type==V_DIMMER) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE diff --git a/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino index 26265ff..352900c 100644 --- a/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino +++ b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino @@ -109,7 +109,7 @@ void loop() } } -void incomingMessage(MyMessage message) { +void incomingMessage(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw:");