From e01dc2ecccbc261c4f8811a85e6e640d4d8187bb Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Fri, 22 Aug 2014 20:35:22 +0200 Subject: [PATCH] Fix a few warnings in MQTTGateway. Move all gateway examples to "examples" to work better with codebender and Arduino IDE. Ledmode is always enabled for gateway. Still optional to connect the wires though ;) Move MsTimer to local utility folder (no external dependencies). --- libraries/MySensors/MyMQTT.cpp | 83 +++++++---------- libraries/MySensors/MyMQTT.h | 21 ++--- .../EthernetGateway}/EthernetGateway.ino | 69 ++++---------- .../examples/MQTTGateway}/MQTTGateway.ino | 14 +-- .../RFIDLockSensor/RFIDLockSensor.ino | 8 +- .../examples/SerialGateway/SerialGateway.ino | 89 +++++++++++++++++++ 6 files changed, 150 insertions(+), 134 deletions(-) rename {EthernetGateway => libraries/MySensors/examples/EthernetGateway}/EthernetGateway.ino (79%) rename {MQTTGateway => libraries/MySensors/examples/MQTTGateway}/MQTTGateway.ino (94%) mode change 100755 => 100644 create mode 100644 libraries/MySensors/examples/SerialGateway/SerialGateway.ino diff --git a/libraries/MySensors/MyMQTT.cpp b/libraries/MySensors/MyMQTT.cpp index d2a0352..0884906 100755 --- a/libraries/MySensors/MyMQTT.cpp +++ b/libraries/MySensors/MyMQTT.cpp @@ -10,6 +10,9 @@ version 2 as published by the Free Software Foundation. */ #include "MyMQTT.h" +#include "utility/MsTimer2.h" + + char broker[] PROGMEM = MQTT_BROKER_PREFIX; @@ -75,26 +78,19 @@ PROGMEM const char *sType[] = { }; -MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin, uint8_t _rx, uint8_t _tx, uint8_t _er) : +extern volatile uint8_t countRx; +extern volatile uint8_t countTx; +extern volatile uint8_t countErr; +extern uint8_t pinRx; +extern uint8_t pinTx; +extern uint8_t pinEr; + +MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin) : MySensor(_cepin, _cspin) { - if (_rx != NULL) { - pinRx = _rx; - pinMode(pinRx, OUTPUT); - ledMode = true; - } - if (_tx != NULL) { - pinTx = _tx; - pinMode(pinTx, OUTPUT); - ledMode = true; - } - if (_er != NULL) { - pinEr = _er; - pinMode(pinEr, OUTPUT); - ledMode = true; - } + } -void MyMQTT::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate, void (*inDataCallback)(char *, int *)) { +void MyMQTT::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate, void (*inDataCallback)(const char *, int *), uint8_t _rx, uint8_t _tx, uint8_t _er) { Serial.begin(BAUD_RATE); repeaterMode = true; isGateway = true; @@ -110,6 +106,18 @@ void MyMQTT::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataR RF24::openReadingPipe(WRITE_PIPE, BASE_RADIO_ID); RF24::openReadingPipe(CURRENT_NODE_PIPE, BASE_RADIO_ID); RF24::startListening(); + + pinRx = _rx; + pinMode(pinRx, OUTPUT); + pinTx = _tx; + pinMode(pinTx, OUTPUT); + pinEr = _er; + pinMode(pinEr, OUTPUT); + + MsTimer2::set(200, ledTimersInterrupt); + MsTimer2::start(); + + // Send startup log message on serial //Serial.print(PSTR("Started\n"));//TODO: progmem gives error..? error: sType causes a section type conflict with __c Serial.print("Started\n");//TODO: fix this... @@ -127,7 +135,7 @@ void MyMQTT::processRadioMessage() { } void MyMQTT::processMQTTMessage(char *inputString, int inputPos) { - char *str, *p, *value=NULL; + char *str, *p; char i = 0; buffer[0]= 0; buffsize = 0; @@ -233,7 +241,7 @@ void MyMQTT::SendMQTT(MyMessage &msg) { } else { // we have to check every message if its a newly assigned id or not. // Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable. - char newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1; + uint8_t newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1; if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; if (msg.sender==newNodeID) { saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); @@ -259,7 +267,7 @@ void MyMQTT::SendMQTT(MyMessage &msg) { } else if (mGetCommand(msg)==C_PRESENTATION && (msg.type==S_ARDUINO_NODE || msg.type==S_ARDUINO_REPEATER_NODE)) { //Doesnt work to check new sensorID here, this message does not always arrive.. See above. } else if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) { - char newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1; + unsigned char newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1; if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; if (newNodeID >= MQTT_LAST_SENSORID) return; // Sorry no more id's left :( msg.destination = msg.sender; //NodeID @@ -289,7 +297,7 @@ void MyMQTT::SendMQTT(MyMessage &msg) { Serial.println((char*)&buffer[4]); #endif msg.getString(convBuf); - for (int a=0; a -#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 +// Use this if you have attached a Ethernet ENC28J60 shields +#include + +// Use this fo WizNET module and Arduino Ethernet Shield +//#include #define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled @@ -99,17 +97,6 @@ void setup() // start listening for clients server.begin(); - - // C++ classes and interrupts really sucks. Need to attach interrupt - // outside thw Gateway class due to language shortcomings! Gah! - - if (gw.isLedMode()) { - // Add led timer interrupt - MsTimer2::set(300, ledTimersInterrupt); - MsTimer2::start(); - // Add interrupt for inclustion button to pin - PCintPort::attachInterrupt(INCLUSION_MODE_PIN, startInclusionInterrupt, RISING); - } } // This will be called when data should be written to ethernet @@ -118,24 +105,22 @@ void writeEthernet(char *writeBuffer) { } -void processEthernetMessages() +void loop() { - // if an incoming client connects, there will be - // bytes available to read via the client object - EthernetClient client = server.available(); + // if an incoming client connects, there will be + // bytes available to read via the client object + EthernetClient client = server.available(); - if (client) - { + if (client) { // if got 1 or more bytes - if (client.available()) - { + if (client.available()) { // read the bytes incoming from the client char inChar = client.read(); if (inputPos #include #include -#include // Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above! @@ -135,12 +134,8 @@ void processEthernetMessages() { } } -void writeEthernet(char *writeBuffer, int *writeSize) { - server.write(writeBuffer, *writeSize); // Todo: Should this really be *writeSize? -} - -void ledTimersInterrupt() { - gw.ledTimersInterrupt(); +void writeEthernet(const char *writeBuffer, int *writeSize) { + server.write((const uint8_t *)writeBuffer, *writeSize); // Todo: Should this really be *writeSize? } int main(void) { @@ -149,11 +144,6 @@ 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 - if (gw.isLedMode()) { - MsTimer2::set(200, ledTimersInterrupt); - MsTimer2::start(); - } while (1) { processEthernetMessages(); gw.processRadioMessage(); diff --git a/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino b/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino index 96f7e25..ecb9756 100644 --- a/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino +++ b/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino @@ -34,9 +34,7 @@ const uint8_t maxKeyLength = 7; uint8_t validKeys[][maxKeyLength] = { { 0xB3, 0xC6, 0xD9, 0x80, 0x00, 0x00, 0x00 }, - { 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0 }, // ADD YOUR KEYS HERE! { 0, 0, 0, 0, 0, 0, 0 }}; int keyCount = sizeof validKeys / maxKeyLength; @@ -84,11 +82,12 @@ void setup() { } void loop() { + gw.process(); // Process incomming messages + boolean success; uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t currentKeyLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) - gw.process(); // Process incomming messages // Wait for an ISO14443A type cards (Mifare, etc.). When one is found // 'uid' will be populated with the UID, and uidLength will indicate @@ -159,3 +158,4 @@ void incomingMessage(const MyMessage &message) { } } + diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino new file mode 100644 index 0000000..83e9715 --- /dev/null +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -0,0 +1,89 @@ + /* + * Copyright (C) 2013 Henrik Ekblad + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * DESCRIPTION + * The ArduinoGateway prints data received from sensors on the serial link. + * The gateway accepts input on seral which will be sent out on radio network. + * + * The GW code is designed for Arduino Nano 328p / 16MHz + * + * Wire connections (OPTIONAL): + * - Inclusion button should be connected between digital pin 3 and GND + * - RX/TX/ERR leds need to be connected between +5V (anode) and digital ping 6/5/4 with resistor 270-330R in a series + * + * LEDs (OPTIONAL): + * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved + * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly + * - ERR (red) - fast blink on error during transmission error or recieve crc error + */ + +#include +#include +#include + +#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button + + +MyGateway gw(DEFAULT_CE_PIN, DEFAULT_CS_PIN, INCLUSION_MODE_TIME, INCLUSION_MODE_PIN, 6, 5, 4); + +char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface +int inputPos = 0; +boolean commandComplete = false; // whether the string is complete + +void setup() +{ + gw.begin(); +} + +void loop() +{ + gw.processRadioMessage(); + checkSerialInput(); +} + + + +void checkSerialInput() { + if (commandComplete) { + // A command wass issued from serial interface + // We will now try to send it to the actuator + gw.parseAndSend(inputString); + commandComplete = false; + inputPos = 0; + } +} + +/* + SerialEvent occurs whenever a new data comes in the + hardware serial RX. This routine is run between each + time loop() runs, so using delay inside loop can delay + response. Multiple bytes of data may be available. + */ +void serialEvent() { + while (Serial.available()) { + // get the new byte: + char inChar = (char)Serial.read(); + // if the incoming character is a newline, set a flag + // so the main loop can do something about it: + if (inputPos