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).
This commit is contained in:
Henrik Ekblad
2014-08-22 20:35:22 +02:00
parent 85d6daf0fa
commit e01dc2eccc
6 changed files with 150 additions and 134 deletions
+30 -53
View File
@@ -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<strlen(convBuf); a++) { // Payload
for (unsigned int a=0; a<strlen(convBuf); a++) { // Payload
buffer[buffsize++] = convBuf[a];
}
buffer[1]=buffsize-2; // Set correct Remaining length on byte 2.
@@ -304,38 +312,7 @@ void MyMQTT::SendMQTT(MyMessage &msg) {
}
}
boolean MyMQTT::isLedMode() {
return ledMode;
}
void MyMQTT::ledTimersInterrupt() {
if(countRx && countRx != 255) {
// switch led on
digitalWrite(pinRx, LOW);
} else if(!countRx) {
// switching off
digitalWrite(pinRx, HIGH);
}
if(countRx != 255) { countRx--; }
if(countTx && countTx != 255) {
// switch led on
digitalWrite(pinTx, LOW);
} else if(!countTx) {
// switching off
digitalWrite(pinTx, HIGH);
}
if(countTx != 255) { countTx--; }
if(countErr && countErr != 255) {
// switch led on
digitalWrite(pinEr, LOW);
} else if(!countErr) {
// switching off
digitalWrite(pinEr, HIGH);
}
if(countErr != 255) { countErr--; }
}
void MyMQTT::rxBlink(uint8_t cnt) {
if(countRx == 255) { countRx = cnt; }
@@ -347,7 +324,7 @@ void MyMQTT::errBlink(uint8_t cnt) {
if(countErr == 255) { countErr = cnt; }
}
char MyMQTT::strncpysType_retL(char *str, char index, char start) {
char MyMQTT::strncpysType_retL(char *str, unsigned char index, char start) {
char c;
char l;
char *p = (char *)pgm_read_word(&(sType[index]));
+7 -14
View File
@@ -30,7 +30,7 @@ version 2 as published by the Free Software Foundation.
///////////////////////////////////////////////////////////////////////////////////
#define EEPROM_LATEST_NODE_ADDRESS EEPROM_LOCAL_CONFIG_ADDRESS+0
#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS)
#define MQTT_MAX_PACKET_SIZE 100
#define MQTTPROTOCOLVERSION 3
@@ -57,35 +57,28 @@ version 2 as published by the Free Software Foundation.
class MyMQTT :
public MySensor {
public:
MyMQTT(uint8_t _cepin=5, uint8_t _cspin=6, uint8_t _rx=NULL, uint8_t _tx=NULL, uint8_t _er=NULL);
void begin(rf24_pa_dbm_e paLevel=RF24_PA_LEVEL_GW, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE, void (*dataCallback)(char *, int *)=NULL);
MyMQTT(uint8_t _cepin=5, uint8_t _cspin=6);
void begin(rf24_pa_dbm_e paLevel=RF24_PA_LEVEL_GW, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE, void (*dataCallback)(const char *, int *)=NULL, uint8_t _rx=6, uint8_t _tx=5, uint8_t _er=4 );
void processRadioMessage();
void processMQTTMessage(char *inputString, int inputPos);
boolean isLedMode();
void ledTimersInterrupt();
private:
bool MQTTClientConnected;
char buffer[MQTT_MAX_PACKET_SIZE];
int buffsize;
char convBuf[MAX_PAYLOAD*2+1];
boolean useWriteCallback;
void (*dataCallback)(char *, int *);
void (*dataCallback)(const char *, int *);
void SendMQTT(MyMessage &msg);
char strncpysType_retL(char *str, char index, char start);
char strncpysType_retL(char *str, unsigned char index, char start);
volatile uint8_t countRx;
volatile uint8_t countTx;
volatile uint8_t countErr;
uint8_t pinRx;
uint8_t pinTx;
uint8_t pinEr;
boolean ledMode;
void ledTimers();
void rxBlink(uint8_t cnt);
void txBlink(uint8_t cnt);
void errBlink(uint8_t cnt);
};
extern void ledTimersInterrupt();
#endif
@@ -44,17 +44,15 @@
* Powering: both NRF24l01 radio and Ethernet(ENC28J60) uses 3.3V
*/
#include <SPI.h>
#include <MsTimer2.h>
#include <PinChangeInt.h>
#include <MyGateway.h>
#include <stdarg.h>
#include <UIPEthernet.h> // Use this if you have attached a Ethernet ENC28J60 shields
//#include <Ethernet.h> // Use this fo WizNET module and Arduino Ethernet Shield
// Use this if you have attached a Ethernet ENC28J60 shields
#include <UIPEthernet.h>
// Use this fo WizNET module and Arduino Ethernet Shield
//#include <Ethernet.h>
#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<MAX_RECEIVE_LENGTH-1) {
// if newline then command is complete
if (inChar == '\n')
{ // a command was issued by the client
if (inChar == '\n') {
// a command was issued by the client
// we will now try to send it to the actuator
inputString[inputPos] = 0;
@@ -146,11 +131,10 @@ void processEthernetMessages()
// clear the string:
inputPos = 0;
}
else
{ // add it to the inputString:
inputString[inputPos] = inChar;
inputPos++;
} else {
// add it to the inputString:
inputString[inputPos] = inChar;
inputPos++;
}
} else {
// Incoming message too long. Throw away
@@ -158,24 +142,7 @@ void processEthernetMessages()
}
}
}
}
void loop()
{
// check for incoming commands from clients
processEthernetMessages();
gw.processRadioMessage();
}
void startInclusionInterrupt() {
gw.startInclusionInterrupt();
}
void ledTimersInterrupt() {
gw.ledTimersInterrupt();
gw.processRadioMessage();
}
@@ -92,7 +92,6 @@ transform/1on0off.map
#include <SPI.h>
#include <MyMQTT.h>
#include <Ethernet.h>
#include <MsTimer2.h>
// 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();
@@ -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) {
}
}
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2013 Henrik Ekblad <henrik.ekblad@gmail.com>
*
* 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 <SPI.h>
#include <MyGateway.h>
#include <stdarg.h>
#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<MAX_RECEIVE_LENGTH-1 && !commandComplete) {
if (inChar == '\n') {
inputString[inputPos] = 0;
commandComplete = true;
} else {
// add it to the inputString:
inputString[inputPos] = inChar;
inputPos++;
}
} else {
// Incoming message too long. Throw away
inputPos = 0;
}
}
}