From 67f4ca1fb4149cfebeaf4d73c7527d4a8d8a51d9 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Mon, 19 May 2014 20:08:12 +0200 Subject: [PATCH] latest test sketches and working request for id --- EthernetGateway/EthernetGateway.ino | 1 - libraries/MySensors/MyMessage.cpp | 5 + libraries/MySensors/MyMessage.h | 3 +- libraries/MySensors/MySensor.cpp | 174 +++++++++--------- libraries/MySensors/MySensor.h | 20 +- .../DallasTemperatureSensor.ino | 8 +- .../examples/MotionSensor/MotionSensor.ino | 21 ++- .../examples/RelayActuator/RelayActuator.ino | 5 +- libraries/RF24/RF24.cpp | 4 +- 9 files changed, 129 insertions(+), 112 deletions(-) diff --git a/EthernetGateway/EthernetGateway.ino b/EthernetGateway/EthernetGateway.ino index 7a4b363..f6c2481 100644 --- a/EthernetGateway/EthernetGateway.ino +++ b/EthernetGateway/EthernetGateway.ino @@ -54,7 +54,6 @@ #include #include #include -//#include #include // Use this if you have attached a Ethernet ENC28J60 shields //#include // Use this fo WizNET module and Arduino Ethernet Shield diff --git a/libraries/MySensors/MyMessage.cpp b/libraries/MySensors/MyMessage.cpp index 941dc06..7d34eb2 100644 --- a/libraries/MySensors/MyMessage.cpp +++ b/libraries/MySensors/MyMessage.cpp @@ -7,6 +7,11 @@ MyMessage::MyMessage() { destination = 0; // Gateway is default destination } +MyMessage::MyMessage(uint8_t _sensor, uint8_t _type) { + destination = 0; // Gateway is default destination + sensor = _sensor; + type = _type; +} /* Getters for payload converted to desired form */ diff --git a/libraries/MySensors/MyMessage.h b/libraries/MySensors/MyMessage.h index 0039b0d..ab6da6b 100644 --- a/libraries/MySensors/MyMessage.h +++ b/libraries/MySensors/MyMessage.h @@ -40,7 +40,7 @@ typedef enum { // Type of internal messages (for internal messages) typedef enum { - I_BATTERY_LEVEL, I_TIME, I_VERSION, I_REQUEST_ID, + I_BATTERY_LEVEL, I_TIME, I_VERSION, I_ID_REQUEST, I_ID_RESPONSE, I_INCLUSION_MODE, I_CONFIG, I_PING, I_PING_ACK, I_LOG_MESSAGE, I_CHILDREN, I_SKETCH_NAME, I_SKETCH_VERSION } internal; @@ -114,6 +114,7 @@ public: // Constructors MyMessage(); + MyMessage(uint8_t sensor, uint8_t type); char* getString(); /** diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index 6921fcd..5174777 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -25,37 +25,8 @@ inline MyMessage* build (MyMessage* msg, uint8_t sender, uint8_t destination, ui 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; - // Start up the radio library - RF24::begin(); - - if (!RF24::isPVariant()) { - debug(PSTR("check wires\n")); - while(1); - } - RF24::setAutoAck(1); - RF24::enableAckPayload(); - RF24::setChannel(channel); - RF24::setPALevel(paLevel); - RF24::setDataRate(dataRate); - RF24::setRetries(5,15); - RF24::setCRCLength(RF24_CRC_16); - RF24::enableDynamicPayloads(); - - // All repeater nodes and gateway listen to broadcast pipe (for PING messages) - if (relayMode) { - RF24::openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); - } -} - -void MySensor::setupRelayMode(){ - childNodeTable = new uint8_t[256]; - eeprom_read_block((void*)childNodeTable, (void*)EEPROM_ROUTES_ADDRESS, 256); -} - -void MySensor::begin(void (*_msgCallback)(MyMessage), boolean _relayMode, uint8_t _nodeId, rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) { +void MySensor::begin(void (*_msgCallback)(MyMessage), uint8_t _nodeId, boolean _relayMode, rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) { Serial.begin(BAUD_RATE); relayMode = _relayMode; msgCallback = _msgCallback; @@ -86,7 +57,7 @@ void MySensor::begin(void (*_msgCallback)(MyMessage), boolean _relayMode, uint8_ requestNodeId(); } - debug(PSTR("%s started\n"), relayMode?"relay":"sensor"); + debug(PSTR("%s started, id %d\n"), relayMode?"relay":"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)); @@ -99,8 +70,38 @@ void MySensor::begin(void (*_msgCallback)(MyMessage), boolean _relayMode, uint8_ // 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)); - Serial.print("XX"); - Serial.println(nc.parentNodeId); + + // Wait configuration reply. + waitForReply(); +} + +void MySensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) { + failedTransmissions = 0; + + // Start up the radio library + RF24::begin(); + + if (!RF24::isPVariant()) { + debug(PSTR("check wires\n")); + while(1); + } + RF24::setAutoAck(1); + RF24::setAutoAck(BROADCAST_PIPE,false); // Turn off auto ack for broadcast + RF24::enableAckPayload(); + RF24::setChannel(channel); + RF24::setPALevel(paLevel); + RF24::setDataRate(dataRate); + RF24::setRetries(5,15); + RF24::setCRCLength(RF24_CRC_16); + RF24::enableDynamicPayloads(); + + // All nodes listen to broadcast pipe (for PING-ACK messages) + RF24::openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); +} + +void MySensor::setupRelayMode(){ + childNodeTable = new uint8_t[256]; + eeprom_read_block((void*)childNodeTable, (void*)EEPROM_ROUTES_ADDRESS, 256); } @@ -115,7 +116,8 @@ 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_REQUEST_ID)); + sendRoute(build(&msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST)->set("")); + waitForReply(); } @@ -125,31 +127,33 @@ void MySensor::findParentNode() { failedTransmissions = 0; - // Open a reading pipe for current nodeId (if it differs from broadcast) - if (nc.nodeId != BROADCAST_PIPE) { - RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId)); - } // Set distance to max 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); + build(&msg, nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING)->set(""); sendWrite(BROADCAST_ADDRESS, &msg, true); + // Wait for ping response. + waitForReply(); +} + +void MySensor::waitForReply() { unsigned long enter = millis(); - // Wait for ack responses slightly more than 1 second - while (millis() - enter < 1200) { + // Wait a couple of seconds for response + while (millis() - enter < 2000) { process(); } - } boolean MySensor::sendRoute(MyMessage *message) { // Make sure to process any incoming messages before sending (could this end up in recursive loop?) // process(); + bool requestId = (mGetCommandP(message) == C_INTERNAL && message->type == I_ID_REQUEST); + bool responseId = (mGetCommandP(message) == C_INTERNAL && message->type == I_ID_RESPONSE); // If we still don't have any node id, re-request and skip this message. - if (nc.nodeId == AUTO && !(mGetCommandP(message) == C_INTERNAL && message->type == I_REQUEST_ID)) { + if (nc.nodeId == AUTO && !requestId) { requestNodeId(); return false; } @@ -157,16 +161,20 @@ boolean MySensor::sendRoute(MyMessage *message) { if (relayMode) { uint8_t dest = message->destination; uint8_t route = getChildRoute(dest); - if (route>0 && route<255 && dest != GATEWAY_ADDRESS) { - debug(PSTR("route %d.\n"), route); + if (route>GATEWAY_ADDRESS && routelast = nc.nodeId; mSetVersionP(message, PROTOCOL_VERSION); message->crc = crc8Message(message); - // Make sure radio has powered up RF24::powerUp(); RF24::stopListening(); @@ -199,8 +206,8 @@ boolean MySensor::sendWrite(uint8_t next, MyMessage *message, bool broadcast) { RF24::startListening(); // 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->sender,message->last, next, message->destination, message->sensor, mGetCommandP(message), message->type, ok?"ok":"fail", message->getString()); + 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)); return ok; } @@ -259,8 +266,8 @@ 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.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, valid==0?"ok":valid==1?"ec":"ev", msg.getString()); + debug(PSTR("read: %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(convBuf)); if (!ok) return false; @@ -276,7 +283,7 @@ boolean MySensor::process() { // 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)); + sendWrite(sender, build(&msg, nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_PING_ACK)->set(nc.distance), true); return false; } else if (destination == nc.nodeId) { // This message is addressed to this node @@ -286,8 +293,9 @@ boolean MySensor::process() { } if (command == C_INTERNAL) { - if (type == I_PING_ACK) { - // We've received a reply to our PING message looking for parent. + if (type == I_PING_ACK && nc.nodeId != GATEWAY_ADDRESS) { + // We've received a reply to a PING message. Check if the distance is + // shorter than we already have. uint8_t distance = msg.getByte(); if (distanceset(temperature,1)); + gw.send(msg.setSensor(i)->set(temperature,1)); lastTemperature[i]=temperature; } } diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index 194aaa4..3bb8777 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -1,20 +1,22 @@ +#include #include #include -#include #include -#include #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) -#define CHILD_ID 0 // Id of the sensor child +#define CHILD_ID 1 // Id of the sensor child -Sensor gw; +MySensor gw; Sleep sleep; +// Initialize motion message +MyMessage msg(CHILD_ID, V_TRIPPED); void setup() { - EEPROM.write(EEPROM_RELAY_ID_ADDRESS, 0); - + //eeprom_write_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, 1); + //eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, 255); + //delay(2000); gw.begin(); // Send the sketch version information to the gateway and Controller @@ -22,7 +24,10 @@ void setup() pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input // Register all sensors to gw (they will be created as child devices) - gw.sendSensorPresentation(CHILD_ID, S_MOTION); + delay(500); + gw.present(CHILD_ID, S_MOTION); + delay(1000); + } void loop() @@ -31,7 +36,7 @@ void loop() boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; Serial.println(tripped); - gw.sendVariable(CHILD_ID, V_TRIPPED, tripped?"1":"0"); // Send tripped value to gw + gw.send(msg.set(tripped?"1":"0")); // Send tripped value to gw // Power down the radio. Note that the radio will get powered back up // on the next write() call. diff --git a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino index e57ad78..f04b602 100644 --- a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino +++ b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino @@ -16,7 +16,7 @@ MySensor gw; void setup() { // Initialize library and add callback for incoming messages - gw.begin(incomingMessage, false); + gw.begin(incomingMessage, AUTO, true); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Relay", "1.0"); @@ -42,10 +42,9 @@ void incomingMessage(MyMessage message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { // Change relay state - digitalWrite(message.sensor, message.getBool()?RELAY_ON:RELAY_OFF); + digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom gw.saveState(message.sensor, message.getBool()); - // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); diff --git a/libraries/RF24/RF24.cpp b/libraries/RF24/RF24.cpp index 000cfed..2efb7bb 100644 --- a/libraries/RF24/RF24.cpp +++ b/libraries/RF24/RF24.cpp @@ -680,10 +680,10 @@ void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){ // Send the payload //write_payload( buf, len ); - write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; + write_payload( buf, len, multicast?static_cast(W_TX_PAYLOAD_NO_ACK):static_cast(W_TX_PAYLOAD)) ; ce(HIGH); - ce(LOW); + ce(LOW); }