From b0917af27e415f4c45b6e1e7e6c610dd393b610d Mon Sep 17 00:00:00 2001 From: Daniel Wiegert Date: Sun, 17 Aug 2014 20:51:52 +0200 Subject: [PATCH 1/3] Changed from Switch/case to if/elseif to save some runtime ram --- libraries/MySensors/MyMessage.cpp | 79 +++++++++++++------------------ libraries/MySensors/MySensor.cpp | 15 ++---- 2 files changed, 38 insertions(+), 56 deletions(-) mode change 100644 => 100755 libraries/MySensors/MyMessage.cpp mode change 100644 => 100755 libraries/MySensors/MySensor.cpp diff --git a/libraries/MySensors/MyMessage.cpp b/libraries/MySensors/MyMessage.cpp old mode 100644 new mode 100755 index 8c5492a..286b111 --- a/libraries/MySensors/MyMessage.cpp +++ b/libraries/MySensors/MyMessage.cpp @@ -64,28 +64,21 @@ char* MyMessage::getString(char *buffer) const { buffer[miGetLength()] = 0; return buffer; } else if (buffer != NULL) { - switch(payloadType) { - case P_BYTE: - itoa(bValue, buffer, 10); - break; - case P_INT16: - itoa(iValue, buffer, 10); - break; - case P_UINT16: - utoa(uiValue, buffer, 10); - break; - case P_LONG32: - ltoa(lValue, buffer, 10); - break; - case P_ULONG32: - ultoa(ulValue, buffer, 10); - break; - case P_FLOAT32: - dtostrf(fValue,2,fPrecision,buffer); - break; - case P_CUSTOM: - return getStream(buffer); - break; + if (payloadType == P_BYTE) { + itoa(bValue, buffer, 10); + } else if (payloadType == P_INT16) { + itoa(iValue, buffer, 10); + } else if (payloadType == P_UINT16) { + utoa(uiValue, buffer, 10); + } else if (payloadType == P_LONG32) { + ltoa(lValue, buffer, 10); + } else if (payloadType == P_ULONG32) { + + ultoa(ulValue, buffer, 10); + } else if (payloadType == P_FLOAT32) { + dtostrf(fValue,2,fPrecision,buffer); + } else if (payloadType == P_CUSTOM) { + return getStream(buffer); } return buffer; } else { @@ -94,12 +87,11 @@ char* MyMessage::getString(char *buffer) const { } uint8_t MyMessage::getByte() const { - switch(miGetPayloadType()) { - case P_BYTE: + if (miGetPayloadType() == P_BYTE) { return data[0]; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atoi(data); - default: + } else { return 0; } } @@ -109,56 +101,51 @@ bool MyMessage::getBool() const { } float MyMessage::getFloat() const { - switch(miGetPayloadType()) { - case P_FLOAT32: + if (miGetPayloadType() == P_FLOAT32) { return fValue; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atof(data); - default: + } else { return 0; } } long MyMessage::getLong() const { - switch(miGetPayloadType()) { - case P_LONG32: + if (miGetPayloadType() == P_LONG32) { return lValue; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atol(data); - default: + } else { return 0; } } unsigned long MyMessage::getULong() const { - switch(miGetPayloadType()) { - case P_ULONG32: + if (miGetPayloadType() == P_ULONG32) { return ulValue; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atol(data); - default: + } else { return 0; } } int MyMessage::getInt() const { - switch(miGetPayloadType()) { - case P_INT16: + if (miGetPayloadType() == P_INT16) { return iValue; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atoi(data); - default: + } else { return 0; } } unsigned int MyMessage::getUInt() const { - switch(miGetPayloadType()) { - case P_UINT16: + if (miGetPayloadType() == P_UINT16) { return uiValue; - case P_STRING: + } else if (miGetPayloadType() == P_STRING) { return atoi(data); - default: + } else { return 0; } diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp old mode 100644 new mode 100755 index 11fcf18..b43a46a --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -327,12 +327,10 @@ boolean MySensor::process() { } else if (sender == GATEWAY_ADDRESS) { bool isMetric; - switch (type) { - case I_REBOOT: + if (type == I_REBOOT) { wdt_enable(WDTO_15MS); for (;;); - break; - case I_ID_RESPONSE: + } else if (type == I_ID_RESPONSE) { if (nc.nodeId == AUTO) { nc.nodeId = msg.getByte(); // Write id to EEPROM @@ -346,8 +344,7 @@ boolean MySensor::process() { } debug(PSTR("id=%d\n"), nc.nodeId); } - break; - case I_CONFIG: + } else if (type == I_CONFIG) { // Pick up configuration from controller (currently only metric/imperial) // and store it in eeprom if changed isMetric = msg.getByte() == 'M' ; @@ -356,8 +353,7 @@ boolean MySensor::process() { eeprom_write_byte((uint8_t*)EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); //eeprom_write_block((const void*)&cc, (uint8_t*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); } - break; - case I_CHILDREN: + } else if (type == I_CHILDREN) { if (repeaterMode && msg.getByte() == 'C') { // Clears child relay data for this node debug(PSTR("rd=clear\n")); @@ -366,8 +362,7 @@ boolean MySensor::process() { } sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); } - break; - case I_TIME: + } else if (type == I_TIME) { if (timeCallback != NULL) { // Deliver time to callback timeCallback(msg.getULong()); From 3af3014178d85a31d9a5ea92b677982926f07334 Mon Sep 17 00:00:00 2001 From: Daniel Wiegert Date: Sun, 17 Aug 2014 21:23:18 +0200 Subject: [PATCH 2/3] New comments and minor fixes --- MQTTGateway/MQTTGateway.ino | 181 ++++++++++++++++------------ libraries/MySensors/MyMQTT.cpp | 209 ++++++++++++++++----------------- libraries/MySensors/MyMQTT.h | 12 +- 3 files changed, 216 insertions(+), 186 deletions(-) diff --git a/MQTTGateway/MQTTGateway.ino b/MQTTGateway/MQTTGateway.ino index 9cbc641..467ac44 100755 --- a/MQTTGateway/MQTTGateway.ino +++ b/MQTTGateway/MQTTGateway.ino @@ -1,36 +1,77 @@ -/* MyMQTT Gateway 0.1b +/* MyMQTT Broker Gateway 0.1b Created by Daniel Wiegert - Based on Mysensors Ethernet Gateway by Henrik Ekblad + Based on MySensors Ethernet Gateway by Henrik Ekblad + http://www.mysensors.org + Requires MySensors lib 1.4b - http://www.mysensors.org - * Don't forget to look at the definitions in MyMQTT.h! - * Don't forget to configure Radio pins, IP and MAC-address! + * Change below; TCP_IP, TCP_PORT, TCP_MAC + This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. + *1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. - * Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/Light - NodeID and SensorID is number (0-255). - Last segment is translation of the sensor type, look inside MyMQTT.cpp for - the definitions. User can change this to their needs. + *2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change + the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. + http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 -Example openhab setup: http://www.openhab.org/ + * Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h! -* openhab.cfg + define TCPDUMP and connect serial interface if you have problems, please write on + http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to + turn on DEBUG in libraries\MySensors\MyConfig.h also. + + MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition. + If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20. + To disable: set MQTT_FIRST_SENSORID to 255. + + MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like. + + MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes. + This can be useful if you want to send latest state back to the MQTT client. Just check if incoming + message has any length or not. + + * Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/[SensorType] + NodeID and SensorID is uint8 (0-255) number. + Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions. + User can change this to their needs. We have also left some space for custom types. + +Special: (sensor 255 reserved for special commands) +You can receive a node sketch name with MyMQTT/20/255/Sketch_name (or version with _version) + +To-do: + Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself. + Be able to send ACK so client returns the data being sent. + ... Please come with ideas! + + Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation) + - http://www.openhab.org/ + - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en + ... Please notify me if you use this broker with other software. + + + * Example Openhab configuration: +openhab.cfg --- mqtt:mysensor.url=tcp://192.168.0.234:1883 mqtt:mysensor.clientId=MQTT --- -* items/test.items +items/test.items --- Group test -Number Temp_test "Temp [%.1f °C]" (test) {mqtt="<[mysensor:MyMQTT/20/#/Temperature:state:default]"} -Number Hum_test "Hum [%.1f %%]" (test) {mqtt="<[mysensor:MyMQTT/20/#/Humidity:state:default]"} -Number test_test "test [%s]" (test) {mqtt="<[mysensor:MyMQTT/20/3/#:state:default]"} -Switch sw1 "sw 1" (test) {<[mysensor:MyMQTT/21/1/Light:command:MAP(1.map)]"} +Number Temp_test "Temp [%.1f °C]" (test) {mqtt="<[mysensor:MyMQTT/20/#/Temperature:state:default]"} +Number Hum_test "Hum [%.1f %%]" (test) {mqtt="<[mysensor:MyMQTT/20/#/Humidity:state:default]"} +Number test_test "test [%s]" (test) {mqtt="<[mysensor:MyMQTT/20/3/#:state:default]"} +Switch sw1 "sw 1" (test) {mqtt="<[mysensor:MyMQTT/21/1/Light:command:MAP(1on0off.map)]"} +Switch sw2 "sw2 recieve example" (test) {mqtt=">[mysensor:MyMQTT/21/2/Light:command:ON:1], + >[mysensor:MyMQTT/21/2/Light:command:OFF:0]"} +Switch sw3 "sw2 send + recieve example" (test) {mqtt=">[mysensor:MyMQTT/21/2/Light:command:ON:1], + >[mysensor:MyMQTT/21/2/Light:command:OFF:0],<[mysensor:MyMQTT/21/2/Light:command:MAP(1on0off.map)]"} +String sketch20 "Node 20 Sketch name [%s]" (test) {mqtt="<[mysensor:MyMQTT/20/255/Sketch_name:state:default]"} +String sketch21 "Node 21 Sketch name [%s]" (test) {mqtt="<[mysensor:MyMQTT/21/255/Sketch_name:state:default]"} --- (Note; # = Wildcard character) -* sitemap/test.site +sitemap/test.site --- sitemap demo label="Menu" Frame label="Openhab" { @@ -38,96 +79,84 @@ Frame label="Openhab" { } --- -* transform/1.map +transform/1on0off.map --- 1=ON 0=OFF --- -* Features: - - Supports automatic nodeID delegation - - Recieve sketchname and version Example: (openhab item) -String sketch20 "Node 20 Sketch name [%s]" (sketch,name,a) {mqtt="<[mysensor:MyMQTT/20/255/Sketch_name:state:default]"} -String sketch21 "Node 21 Sketch name [%s]" (sketch,name,a) {mqtt="<[mysensor:MyMQTT/21/255/Sketch_name:state:default]"} -[...] - -* Todo: - - DOCUMENTATION... - - Special commands - Read and set EEPROM Values - Send Reboot, And reboot gateway itself. -... - -Sketch uses 23,666 bytes (77%) of program storage space. Maximum is 30,720 bytes. -Global variables use 766 bytes (37%) of dynamic memory, leaving 1,282 bytes for local variables. Maximum is 2,048 bytes. */ + #include #include #include #include -// Use this for IBOARD modded to use standard MISO/MOSI/SCK More information see; -// http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 -//#define RADIO_CE_PIN 3 // radio chip enable -//#define RADIO_SPI_SS_PIN 8 // radio SPI serial select -//#define RADIO_ERROR_LED_PIN A2 // Error led pin -//#define RADIO_RX_LED_PIN A1 // Receive led pin -//#define RADIO_TX_LED_PIN A0 // the PCB, on board LED +// Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above! +/* +#define RADIO_CE_PIN 3 // radio chip enable +#define RADIO_SPI_SS_PIN 8 // radio SPI serial select +#define RADIO_ERROR_LED_PIN A2 // Error led pin +#define RADIO_RX_LED_PIN A1 // Receive led pin +#define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/ //Use this for default configured pro mini / nano etc : +///* #define RADIO_CE_PIN 5 // radio chip enable #define RADIO_SPI_SS_PIN 6 // radio SPI serial select #define RADIO_ERROR_LED_PIN 7 // Error led pin #define RADIO_RX_LED_PIN 8 // Receive led pin -#define RADIO_TX_LED_PIN 9 // the PCB, on board LED +#define RADIO_TX_LED_PIN 9 // the PCB, on board LED*/ -#define IP_PORT 1883 // MQTT Listening port -IPAddress myIp ( 192, 168, 0, 234 ); // Configure your static ip-address here -byte mac[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - Change this! -// * NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Locally Administered Address Ranges. +#define TCP_PORT 1883 // Set your MQTT Broker Listening port. +IPAddress TCP_IP ( 192, 168, 0, 234 ); // Configure your static ip-address here +byte TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - You should change this! see note *2 above! -EthernetServer server = EthernetServer(IP_PORT); +EthernetServer server = EthernetServer(TCP_PORT); MyMQTT gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN); -// Uncomment this constructor if you have leds and include button attached to your gateway -// MyMQTT gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); + +// -- Uncomment this constructor if you have leds and include button attached to your gateway +//MyMQTT gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); void processEthernetMessages() { - char inputString[MQTT_MAX_PACKET_SIZE] = ""; - int inputSize = 0; - EthernetClient client = server.available(); - if (client) { - while (client.available()) { - char inChar = client.read(); - inputString[inputSize] = inChar; - inputSize++; - } - gw.processMQTTMessage(inputString, inputSize); - } + char inputString[MQTT_MAX_PACKET_SIZE] = ""; + int inputSize = 0; + EthernetClient client = server.available(); + if (client) { + while (client.available()) { + char inChar = client.read(); + inputString[inputSize] = inChar; + inputSize++; + } + gw.processMQTTMessage(inputString, inputSize); + } } void writeEthernet(char *writeBuffer, int *writeSize) { - server.write(writeBuffer, *writeSize); // Should this really be *writeSize? + server.write(writeBuffer, *writeSize); // Todo: Should this really be *writeSize? } void ledTimersInterrupt() { - gw.ledTimersInterrupt(); + gw.ledTimersInterrupt(); } int main(void) { - init(); - Ethernet.begin(mac, myIp); - delay(1000); // Wait for Ethernet to get configured. - gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet); - server.begin(); - if (gw.isLedMode()) { - // Add led timer interrupt - MsTimer2::set(300, ledTimersInterrupt); - MsTimer2::start(); - } - while (1) { - processEthernetMessages(); - gw.processRadioMessage(); - } + init(); + Ethernet.begin(TCP_MAC, TCP_IP); + delay(1000); // Wait for Ethernet to get configured. + gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet); + server.begin(); +// Add led timer interrupt + if (gw.isLedMode()) { + MsTimer2::set(200, ledTimersInterrupt); + MsTimer2::start(); + } + while (1) { + processEthernetMessages(); + gw.processRadioMessage(); + } } + + diff --git a/libraries/MySensors/MyMQTT.cpp b/libraries/MySensors/MyMQTT.cpp index 7d8c9a3..2e1d49e 100755 --- a/libraries/MySensors/MyMQTT.cpp +++ b/libraries/MySensors/MyMQTT.cpp @@ -12,44 +12,45 @@ version 2 as published by the Free Software Foundation. #include "MyMQTT.h" char broker[] PROGMEM = MQTT_BROKER_PREFIX; -char S_0[] PROGMEM = "Temperature"; -char S_1[] PROGMEM = "Humidity"; -char S_2[] PROGMEM = "Light"; -char S_3[] PROGMEM = "Dimmer"; -char S_4[] PROGMEM = "Pressure"; -char S_5[] PROGMEM = "Forecast"; -char S_6[] PROGMEM = "Rain"; -char S_7[] PROGMEM = "Rainrate"; -char S_8[] PROGMEM = "Wind"; -char S_9[] PROGMEM = "Gust"; -char S_10[] PROGMEM = "Direction"; -char S_11[] PROGMEM = "UV"; -char S_12[] PROGMEM = "Weight"; -char S_13[] PROGMEM = "Distance"; -char S_14[] PROGMEM = "Impedance"; -char S_15[] PROGMEM = "Armed"; -char S_16[] PROGMEM = "Tripped"; -char S_17[] PROGMEM = "Watt"; -char S_18[] PROGMEM = "KWH"; -char S_19[] PROGMEM = "Scene_ON"; -char S_20[] PROGMEM = "Scene_OFF"; -char S_21[] PROGMEM = "Heater"; -char S_22[] PROGMEM = "Heater_SW"; -char S_23[] PROGMEM = "LightLVL"; -char S_24[] PROGMEM = "Var1"; -char S_25[] PROGMEM = "Var2"; -char S_26[] PROGMEM = "Var3"; -char S_27[] PROGMEM = "Var4"; -char S_28[] PROGMEM = "Var5,"; -char S_29[] PROGMEM = "Up"; -char S_30[] PROGMEM = "Down"; -char S_31[] PROGMEM = "Stop"; -char S_32[] PROGMEM = "IR_Send"; -char S_33[] PROGMEM = "IR_Receive"; -char S_34[] PROGMEM = "Flow"; -char S_35[] PROGMEM = "Volume"; -char S_36[] PROGMEM = "Lock_Status"; -char S_37[] PROGMEM = "Volt_Batt"; // Does not exist in mysensors lib! + +char S_0[] PROGMEM = "Temperature"; //V_TEMP +char S_1[] PROGMEM = "Humidity"; //V_HUM +char S_2[] PROGMEM = "Light"; //V_LIGHT +char S_3[] PROGMEM = "Dimmer"; //V_DIMMER +char S_4[] PROGMEM = "Pressure"; //V_PRESSURE +char S_5[] PROGMEM = "Forecast"; //V_FORECAST +char S_6[] PROGMEM = "Rain"; //V_RAIN +char S_7[] PROGMEM = "Rainrate"; //V_RAINRATE +char S_8[] PROGMEM = "Wind"; //V_WIND +char S_9[] PROGMEM = "Gust"; //V_GUST +char S_10[] PROGMEM = "Direction"; //V_DIRECTION +char S_11[] PROGMEM = "UV"; //V_UV +char S_12[] PROGMEM = "Weight"; //V_WEIGHT +char S_13[] PROGMEM = "Distance"; //V_DISTANCE +char S_14[] PROGMEM = "Impedance"; //V_IMPEDANCE +char S_15[] PROGMEM = "Armed"; //V_ARMED +char S_16[] PROGMEM = "Tripped"; //V_TRIPPED +char S_17[] PROGMEM = "Watt"; //V_WATT +char S_18[] PROGMEM = "KWH"; //V_KWH +char S_19[] PROGMEM = "Scene_ON"; //V_SCENE_ON +char S_20[] PROGMEM = "Scene_OFF"; //V_SCENE_OFF +char S_21[] PROGMEM = "Heater"; //V_HEATER +char S_22[] PROGMEM = "Heater_SW"; //V_HEATER_SW +char S_23[] PROGMEM = "LightLevel"; //V_LIGHT_LEVEL +char S_24[] PROGMEM = "Var1"; //V_VAR1 +char S_25[] PROGMEM = "Var2"; //V_VAR2 +char S_26[] PROGMEM = "Var3"; //V_VAR3 +char S_27[] PROGMEM = "Var4"; //V_VAR4 +char S_28[] PROGMEM = "Var5,"; //V_VAR5 +char S_29[] PROGMEM = "Up"; //V_UP +char S_30[] PROGMEM = "Down"; //V_DOWN +char S_31[] PROGMEM = "Stop"; //V_STOP +char S_32[] PROGMEM = "IR_Send"; //V_IR_SEND +char S_33[] PROGMEM = "IR_Receive"; //V_IR_RECEIVE +char S_34[] PROGMEM = "Flow"; //V_FLOW +char S_35[] PROGMEM = "Volume"; //V_VOLUME +char S_36[] PROGMEM = "Lock_Status";//V_LOCK_STATUS +char S_37[] PROGMEM = "DustLevel"; //V_DUST_LEVEL char S_38[] PROGMEM = ""; char S_39[] PROGMEM = ""; char S_40[] PROGMEM = ""; @@ -57,23 +58,24 @@ char S_41[] PROGMEM = ""; char S_42[] PROGMEM = ""; char S_43[] PROGMEM = ""; char S_44[] PROGMEM = ""; -char S_45[] PROGMEM = ""; +char S_45[] PROGMEM = "Volt_Batt"; // Does not exist in MyMessage.h! char S_46[] PROGMEM = ""; char S_47[] PROGMEM = ""; char S_48[] PROGMEM = ""; -char S_49[] PROGMEM = "Sketch_name"; // Does not exist in mysensors lib! -char S_50[] PROGMEM = "Sketch_version"; // Does not exist in mysensors lib! +char S_49[] PROGMEM = "Sketch_name"; // Does not exist in MyMessage.h! +char S_50[] PROGMEM = "Sketch_version"; // Does not exist in MyMessage.h! -PROGMEM const char *sType[] = -{ S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, S_8, S_9, S_10, +PROGMEM const char *sType[] = { + S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, S_8, S_9, S_10, S_11, S_12, S_13, S_14, S_15, S_16, S_17, S_18, S_19, S_20, - S_21, S_22, S_23, S_24, S_25, S_26, S_27, S_28, S_29, S_30, + S_21, S_22, S_23, S_24, S_25, S_26, S_27, S_28, S_29, S_30, S_31, S_32, S_33, S_34, S_35, S_36, S_37, S_38, S_39, S_40, - S_41, S_42, S_43, S_44, S_45, S_46, S_47, S_48, S_49, S_50}; + S_41, S_42, S_43, S_44, S_45, S_46, S_47, S_48, S_49, S_50 +}; -MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin, uint8_t _rx, uint8_t _tx, uint8_t _er) : +MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin, uint8_t _rx, uint8_t _tx, uint8_t _er) : MySensor(_cepin, _cspin) { if (_rx != NULL) { pinRx = _rx; @@ -83,7 +85,7 @@ MySensor(_cepin, _cspin) { if (_tx != NULL) { pinTx = _tx; pinMode(pinTx, OUTPUT); - ledMode = true; + ledMode = true; } if (_er != NULL) { pinEr = _er; @@ -118,7 +120,7 @@ void MyMQTT::processRadioMessage() { // A new message was received from one of the sensors MyMessage message = getLastMessage(); // Pass along the message from sensors to serial line - rxBlink(3); + rxBlink(1); SendMQTT(message); } @@ -130,7 +132,7 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { buffer[0]= 0; buffsize = 0; #ifdef TCPDUMP - Serial.print("<<"); + Serial.print("<<"); char buf[4]; for (int a=0; a 0) { #ifdef TCPDUMP - Serial.print(">>"); + Serial.print(">>"); char buf[4]; - for (int a=0; a> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { + if ((byte)inputString[0] >> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { buffer[0]= 0; buffsize = 0; if ((byte)inputString[0] >> 4 == MQTTSUBSCRIBE) { @@ -179,38 +181,32 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { strncat(buffer,inputString+4,inputString[3]); } msg.sender = GATEWAY_ADDRESS; - for (str = strtok_r(buffer, "/", &p); // split using semicolon - str && i < 4; str = strtok_r(NULL, "/", &p) //get subsequent tokens (?) - ) { - switch (i) { - case 0: // Radioid (destination) + for (str = strtok_r(buffer,"/",&p) ; str && i<4 ; str = strtok_r(NULL,"/",&p)) { //split using semicolon + // TODO: Check if we should send ack or not. + if (i == 0) { if (strcmp_P(str,broker)!=0) { return; //Message not for us or malformatted! } - break; - case 1: + } else if (i==1) { msg.destination = atoi(str); - break; - case 2: + } else if (i==2) { msg.sensor = atoi(str); - break; - case 3: + } else if (i==3) { char match=0; for (int j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(sType[j]))) ; j++) { - if (strcmp(str,convBuf)==0) { - match=j; + if (strcmp(str,convBuf)==0) { + match=j; break; } - } + } msg.type = match; - break; } i++; } if ((char)inputString[1] > (char)(inputString[3]+2) && !((byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { strcpy(convBuf,inputString+(inputString[3]+4)); msg.set(convBuf); - } else { + } else { msg.set(""); } msg.sender = GATEWAY_ADDRESS; @@ -225,13 +221,13 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { void MyMQTT::SendMQTT(MyMessage &msg) { -//serial(PSTR("%d;%d;%d;%d;%s\n"),msg.sender, msg.sensor, mGetCommand(msg), msg.type, msg.getString(convBuf)); + //serial(PSTR("%d;%d;%d;%d;%s\n"),msg.sender, msg.sensor, mGetCommand(msg), msg.type, msg.getString(convBuf)); buffsize = 0; if (!MQTTClientConnected) return; if (msg.isAck()) { -Serial.println("msg is ack!"); + Serial.println("msg is ack!"); if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) { - // TODO: sending ACK request on id_response fucks node up. doesn't work. + // TODO: sending ACK request on id_response fucks node up. doesn't work. // The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. } } else { @@ -243,17 +239,17 @@ Serial.println("msg is ack!"); saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); } if (mGetCommand(msg)==C_INTERNAL && msg.type==I_CONFIG) { // CONFIG - // As for now there is only one 'config' request. + // As for now there is only one 'config' request. // We force SI! Resistance is futile! // - // Todo : Support for more config types, Maybe just read from own EEPROM? - // Use internal EEPROM_CONTROLLER_CONFIG_ADDRESS and special MQTT address to write to + // Todo : Support for more config types, Maybe just read from own EEPROM? + // Use internal EEPROM_CONTROLLER_CONFIG_ADDRESS and special MQTT address to write to // EEPROM_CONTROLLER_CONFIG_ADDRESS & EEPROM_LOCAL_CONFIG_ADDRESS msg.destination = msg.sender; //NodeID msg.sender = GATEWAY_ADDRESS; msg.sensor = 255; //SensorID msg.type = I_CONFIG; //msgType - mSetCommand(msg,C_INTERNAL); //Subtype + mSetCommand(msg,C_INTERNAL);//Subtype mSetRequestAck(msg,false); mSetAck(msg,false); msg.set("M"); @@ -280,7 +276,7 @@ Serial.println("msg is ack!"); // if (sendRoute(msg)) saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); // If send OK save to eeprom. DOES NOT ALWAYS RETURN 'OK'!? } else if (mGetCommand(msg)!=0) { if (mGetCommand(msg)==3) msg.type=msg.type+38; - buffer[buffsize++] = MQTTPUBLISH << 4; // 0: + buffer[buffsize++] = MQTTPUBLISH << 4; // 0: buffer[buffsize++] = 0x09; // 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2 buffer[buffsize++] = 0x00; // 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!) buffer[buffsize++] = 0x08; // 3: Length LSB (ADDR), We'll set this later @@ -301,11 +297,11 @@ Serial.println("msg is ack!"); #ifdef TCPDUMP Serial.print(">>"); char buf[4]; - for (int a=0; a Date: Sun, 17 Aug 2014 22:04:42 +0200 Subject: [PATCH 3/3] moved comment and minor ops --- MQTTGateway/MQTTGateway.ino | 50 +++++++++++++++++----------------- libraries/MySensors/MyMQTT.cpp | 42 ++++++++++++++-------------- libraries/MySensors/MyMQTT.h | 9 ++---- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/MQTTGateway/MQTTGateway.ino b/MQTTGateway/MQTTGateway.ino index 467ac44..54da02d 100755 --- a/MQTTGateway/MQTTGateway.ino +++ b/MQTTGateway/MQTTGateway.ino @@ -1,20 +1,20 @@ /* MyMQTT Broker Gateway 0.1b - Created by Daniel Wiegert - Based on MySensors Ethernet Gateway by Henrik Ekblad - http://www.mysensors.org +Created by Daniel Wiegert +Based on MySensors Ethernet Gateway by Henrik Ekblad +http://www.mysensors.org - Requires MySensors lib 1.4b +Requires MySensors lib 1.4b - * Change below; TCP_IP, TCP_PORT, TCP_MAC - This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. - *1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. +* Change below; TCP_IP, TCP_PORT, TCP_MAC +This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. +*1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. - *2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change - the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. - http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 +*2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change + the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. + http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 - * Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h! +* Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h! define TCPDUMP and connect serial interface if you have problems, please write on http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to @@ -29,8 +29,9 @@ MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes. This can be useful if you want to send latest state back to the MQTT client. Just check if incoming message has any length or not. + Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. - * Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/[SensorType] +* Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/[SensorType] NodeID and SensorID is uint8 (0-255) number. Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions. User can change this to their needs. We have also left some space for custom types. @@ -39,18 +40,18 @@ Special: (sensor 255 reserved for special commands) You can receive a node sketch name with MyMQTT/20/255/Sketch_name (or version with _version) To-do: - Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself. - Be able to send ACK so client returns the data being sent. - ... Please come with ideas! - - Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation) - - http://www.openhab.org/ - - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en - ... Please notify me if you use this broker with other software. +Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself. +Be able to send ACK so client returns the data being sent. +... Please come with ideas! + +Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation) +- http://www.openhab.org/ +- https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en +... Please notify me if you use this broker with other software. - * Example Openhab configuration: -openhab.cfg +* Example Openhab configuration: +openhab.cfg --- mqtt:mysensor.url=tcp://192.168.0.234:1883 mqtt:mysensor.clientId=MQTT @@ -75,7 +76,7 @@ sitemap/test.site --- sitemap demo label="Menu" Frame label="Openhab" { - Group item=test label="Test group" + Group item=test label="Test group" } --- @@ -148,7 +149,7 @@ int main(void) { delay(1000); // Wait for Ethernet to get configured. gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet); server.begin(); -// Add led timer interrupt + // Add led timer interrupt if (gw.isLedMode()) { MsTimer2::set(200, ledTimersInterrupt); MsTimer2::start(); @@ -159,4 +160,3 @@ int main(void) { } } - diff --git a/libraries/MySensors/MyMQTT.cpp b/libraries/MySensors/MyMQTT.cpp index 2e1d49e..d2a0352 100755 --- a/libraries/MySensors/MyMQTT.cpp +++ b/libraries/MySensors/MyMQTT.cpp @@ -67,15 +67,15 @@ char S_50[] PROGMEM = "Sketch_version"; // Does not exist in MyMessage.h! PROGMEM const char *sType[] = { - S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, S_8, S_9, S_10, + S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, S_8, S_9, S_10, S_11, S_12, S_13, S_14, S_15, S_16, S_17, S_18, S_19, S_20, - S_21, S_22, S_23, S_24, S_25, S_26, S_27, S_28, S_29, S_30, + S_21, S_22, S_23, S_24, S_25, S_26, S_27, S_28, S_29, S_30, S_31, S_32, S_33, S_34, S_35, S_36, S_37, S_38, S_39, S_40, S_41, S_42, S_43, S_44, S_45, S_46, S_47, S_48, S_49, S_50 }; -MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin, uint8_t _rx, uint8_t _tx, uint8_t _er) : +MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin, uint8_t _rx, uint8_t _tx, uint8_t _er) : MySensor(_cepin, _cspin) { if (_rx != NULL) { pinRx = _rx; @@ -85,7 +85,7 @@ MySensor(_cepin, _cspin) { if (_tx != NULL) { pinTx = _tx; pinMode(pinTx, OUTPUT); - ledMode = true; + ledMode = true; } if (_er != NULL) { pinEr = _er; @@ -132,7 +132,7 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { buffer[0]= 0; buffsize = 0; #ifdef TCPDUMP - Serial.print("<<"); + Serial.print("<<"); char buf[4]; for (int a=0; a 0) { #ifdef TCPDUMP - Serial.print(">>"); + Serial.print(">>"); char buf[4]; - for (int a=0; a> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { + if ((byte)inputString[0] >> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { buffer[0]= 0; buffsize = 0; if ((byte)inputString[0] >> 4 == MQTTSUBSCRIBE) { @@ -194,11 +194,11 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { } else if (i==3) { char match=0; for (int j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(sType[j]))) ; j++) { - if (strcmp(str,convBuf)==0) { - match=j; + if (strcmp(str,convBuf)==0) { + match=j; break; } - } + } msg.type = match; } i++; @@ -206,7 +206,7 @@ void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { if ((char)inputString[1] > (char)(inputString[3]+2) && !((byte)inputString[0] >> 4 == MQTTSUBSCRIBE)) { strcpy(convBuf,inputString+(inputString[3]+4)); msg.set(convBuf); - } else { + } else { msg.set(""); } msg.sender = GATEWAY_ADDRESS; @@ -227,7 +227,7 @@ void MyMQTT::SendMQTT(MyMessage &msg) { if (msg.isAck()) { Serial.println("msg is ack!"); if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) { - // TODO: sending ACK request on id_response fucks node up. doesn't work. + // TODO: sending ACK request on id_response fucks node up. doesn't work. // The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. } } else { @@ -239,11 +239,11 @@ void MyMQTT::SendMQTT(MyMessage &msg) { saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); } if (mGetCommand(msg)==C_INTERNAL && msg.type==I_CONFIG) { // CONFIG - // As for now there is only one 'config' request. + // As for now there is only one 'config' request. // We force SI! Resistance is futile! // - // Todo : Support for more config types, Maybe just read from own EEPROM? - // Use internal EEPROM_CONTROLLER_CONFIG_ADDRESS and special MQTT address to write to + // Todo : Support for more config types, Maybe just read from own EEPROM? + // Use internal EEPROM_CONTROLLER_CONFIG_ADDRESS and special MQTT address to write to // EEPROM_CONTROLLER_CONFIG_ADDRESS & EEPROM_LOCAL_CONFIG_ADDRESS msg.destination = msg.sender; //NodeID msg.sender = GATEWAY_ADDRESS; @@ -273,10 +273,10 @@ void MyMQTT::SendMQTT(MyMessage &msg) { mSetVersion(msg, PROTOCOL_VERSION); txBlink(1); if (!sendRoute(msg)) errBlink(1); -// if (sendRoute(msg)) saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); // If send OK save to eeprom. DOES NOT ALWAYS RETURN 'OK'!? + // if (sendRoute(msg)) saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); // If send OK save to eeprom. DOES NOT ALWAYS RETURN 'OK'!? } else if (mGetCommand(msg)!=0) { if (mGetCommand(msg)==3) msg.type=msg.type+38; - buffer[buffsize++] = MQTTPUBLISH << 4; // 0: + buffer[buffsize++] = MQTTPUBLISH << 4; // 0: buffer[buffsize++] = 0x09; // 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2 buffer[buffsize++] = 0x00; // 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!) buffer[buffsize++] = 0x08; // 3: Length LSB (ADDR), We'll set this later @@ -297,11 +297,11 @@ void MyMQTT::SendMQTT(MyMessage &msg) { #ifdef TCPDUMP Serial.print(">>"); char buf[4]; - for (int a=0; a