diff --git a/README.md b/README.md index b803e58..c79ceb0 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,11 @@ Arduino MySensors Arduino Library v1.5 Please visit www.mysensors.org for more information + +Current build status of master branch: [![Build Status](http://ci.mysensors.org/job/MySensorsArduino/branch/master/badge/icon)](http://ci.mysensors.org/job/MySensorsArduino/branch/master/) + +Current build status of development branch: [![Build Status](http://ci.mysensors.org/job/MySensorsArduino/branch/development/badge/icon)](http://ci.mysensors.org/job/MySensorsArduino/branch/development/) + +Current build status of master branch (nightly build of Arduino IDE): [![Build Status](http://ci.mysensors.org/job/MySensorsArduinoNightly/branch/master/badge/icon)](http://ci.mysensors.org/job/MySensorsArduinoNightly/branch/master/) + +Current build status of development branch (nightly build of Arduino IDE): [![Build Status](http://ci.mysensors.org/job/MySensorsArduinoNightly/branch/development/badge/icon)](http://ci.mysensors.org/job/MySensorsArduinoNightly/branch/development/) diff --git a/hardware/MySensors/avr/platform.txt b/hardware/MySensors/avr/platform.txt index 28f482c..8f61be7 100644 --- a/hardware/MySensors/avr/platform.txt +++ b/hardware/MySensors/avr/platform.txt @@ -11,17 +11,23 @@ version=1.6.0 # AVR compile variables # --------------------- +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + # Default "compiler.path" is correct, change only if you want to overidde the initial value compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc -compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD +compiler.c.flags=-c -g -Os {compiler.warning_flags} -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 # This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain -compiler.c.elf.flags=-w -Os -Wl,--gc-sections +compiler.c.elf.flags={compiler.warning_flags} -Os -Wl,--gc-sections compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=avr-g++ -compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD +compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD compiler.ar.cmd=avr-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy diff --git a/libraries/Bounce2/Bounce2.cpp b/libraries/Bounce2/Bounce2.cpp index 96e0d16..1d3b1f9 100644 --- a/libraries/Bounce2/Bounce2.cpp +++ b/libraries/Bounce2/Bounce2.cpp @@ -18,7 +18,7 @@ Bounce::Bounce() { void Bounce::attach(int pin) { this->pin = pin; debouncedState = unstableState = digitalRead(pin); - #ifdef BOUNCE_LOCK-OUT + #ifdef BOUNCE_LOCK_OUT previous_millis = 0; #else previous_millis = millis(); @@ -37,7 +37,7 @@ void Bounce::interval(unsigned long interval_millis) bool Bounce::update() { -#ifdef BOUNCE_LOCK-OUT +#ifdef BOUNCE_LOCK_OUT stateChanged = false; // Ignore everything if we are locked out if (millis() - previous_millis >= interval_millis) { diff --git a/libraries/Bounce2/Bounce2.h b/libraries/Bounce2/Bounce2.h index 6d2b62b..86c1520 100644 --- a/libraries/Bounce2/Bounce2.h +++ b/libraries/Bounce2/Bounce2.h @@ -24,7 +24,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Uncomment the following line for "LOCK-OUT" debounce method -//#define BOUNCE_LOCK-OUT +//#define BOUNCE_LOCK_OUT #ifndef Bounce2_h diff --git a/libraries/DHT/DHT.cpp b/libraries/DHT/DHT.cpp index d32c83f..1584d6a 100644 --- a/libraries/DHT/DHT.cpp +++ b/libraries/DHT/DHT.cpp @@ -142,9 +142,9 @@ void DHT::readSensor() // - Then 40 bits: RISING and then a FALLING edge per bit // To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long - word rawHumidity; - word rawTemperature; - word data; + word rawHumidity = 0; + word rawTemperature = 0; + word data = 0; for ( int8_t i = -3 ; i < 2 * 40; i++ ) { byte age; diff --git a/libraries/DallasTemperature/DallasTemperature.cpp b/libraries/DallasTemperature/DallasTemperature.cpp index 8cf7515..80ee4f8 100644 --- a/libraries/DallasTemperature/DallasTemperature.cpp +++ b/libraries/DallasTemperature/DallasTemperature.cpp @@ -700,6 +700,7 @@ void DallasTemperature::setAlarmHandler(AlarmHandler *handler) // The default alarm handler void DallasTemperature::defaultAlarmHandler(const uint8_t* deviceAddress) { + (void)deviceAddress; } #endif diff --git a/libraries/DigitalIO/SoftI2cMaster.cpp b/libraries/DigitalIO/SoftI2cMaster.cpp index efc338a..a698636 100644 --- a/libraries/DigitalIO/SoftI2cMaster.cpp +++ b/libraries/DigitalIO/SoftI2cMaster.cpp @@ -50,7 +50,6 @@ */ bool I2cMasterBase::transfer(uint8_t addrRW, void *buf, size_t nbytes, uint8_t option) { - uint8_t* p = reinterpret_cast(buf); if (_state != STATE_REP_START) { start(); } diff --git a/libraries/DigitalIO/SoftI2cMaster.h b/libraries/DigitalIO/SoftI2cMaster.h index e2d559a..7bf3c00 100644 --- a/libraries/DigitalIO/SoftI2cMaster.h +++ b/libraries/DigitalIO/SoftI2cMaster.h @@ -132,7 +132,7 @@ class SoftI2cMaster : public I2cMasterBase { //---------------------------------------------------------------------------- void sclDelay(uint8_t n) {_delay_loop_1(n);} //---------------------------------------------------------------------------- - bool writeScl(bool value) { + void writeScl(bool value) { uint8_t s = SREG; noInterrupts(); if (value == LOW) { @@ -145,7 +145,7 @@ class SoftI2cMaster : public I2cMasterBase { SREG = s; } //---------------------------------------------------------------------------- - bool writeSda(bool value) { + void writeSda(bool value) { uint8_t s = SREG; noInterrupts(); if (value == LOW) { diff --git a/libraries/IRLib/IRLib.cpp b/libraries/IRLib/IRLib.cpp index 7307bac..a8748bd 100644 --- a/libraries/IRLib/IRLib.cpp +++ b/libraries/IRLib/IRLib.cpp @@ -649,7 +649,7 @@ bool IRdecodeRC6::decode(void) { * Hopefully this code is unique for each button. */ #define FNV_PRIME_32 16777619 -#define FNV_BASIS_32 2166136261 +#define FNV_BASIS_32 2166136261UL // Compare two tick values, returning 0 if newval is shorter, // 1 if newval is equal, and 2 if newval is longer int IRdecodeHash::compare(unsigned int oldval, unsigned int newval) { @@ -730,12 +730,12 @@ void IRrecvBase::resume() { bool IRrecvLoop::GetResults(IRdecodeBase *decoder) { bool Finished=false; byte OldState=HIGH;byte NewState; - unsigned long StartTime, DeltaTime, EndTime; + unsigned long StartTime, DeltaTime=0, EndTime=0; StartTime=micros(); while(irparams.rawlen 10000) { //If it's a very long wait - if(Finished=irparams.rawlen) break; //finished unless it's the opening gap + if((Finished=irparams.rawlen)) break; //finished unless it's the opening gap } } if(Finished) break; @@ -798,6 +798,9 @@ void IRrecvPCI_Handler(){ case STATE_IDLE: if(digitalRead(irparams.recvpin)) return; else irparams.rcvstate=STATE_RUNNING; break; + default: + // what of STATE_UNKNOWN, STATE_MARK and STATE_SPACE? + break; }; irparams.rawbuf[irparams.rawlen]=DeltaTime; irparams.timer=ChangeTime; @@ -982,6 +985,9 @@ ISR(TIMER_INTR_NAME) irparams.timer = 0; } break; + default: + // what of STATE_UNKNOWN and STATE_RUNNING? + break; } do_Blink(); } diff --git a/libraries/IRLib/IRLib.h b/libraries/IRLib/IRLib.h index c8e6c38..0dd05a2 100644 --- a/libraries/IRLib/IRLib.h +++ b/libraries/IRLib/IRLib.h @@ -48,7 +48,7 @@ #define RAWBUF 100 // Length of raw duration buffer (cannot exceed 255) -typedef char IRTYPES; //formerly was an enum +typedef unsigned char IRTYPES; //formerly was an enum #define UNKNOWN 0 #define NEC 1 #define SONY 2 diff --git a/libraries/LiquidCrystal/LCD.h b/libraries/LiquidCrystal/LCD.h index 9b977f4..43367aa 100644 --- a/libraries/LiquidCrystal/LCD.h +++ b/libraries/LiquidCrystal/LCD.h @@ -90,6 +90,8 @@ inline static void waitUsec ( uint16_t uSec ) { #ifndef FAST_MODE delayMicroseconds ( uSec ); +#else + (void)uSec; #endif // FAST_MODE } @@ -481,7 +483,7 @@ public: @param value: pin associated to backlight control. @param pol: backlight polarity control (POSITIVE, NEGATIVE) */ - virtual void setBacklightPin ( uint8_t value, t_backlighPol pol ) { }; + virtual void setBacklightPin ( uint8_t /*value*/, t_backlighPol /*pol*/ ) { }; /*! @function @@ -500,7 +502,7 @@ public: BACKLIGHT_OFF will be interpreted as off and BACKLIGHT_ON will drive the backlight on. */ - virtual void setBacklight ( uint8_t value ) { }; + virtual void setBacklight ( uint8_t /*value*/ ) { }; /*! @function @@ -514,9 +516,9 @@ public: @param value[in] Value to write to the LCD. */ #if (ARDUINO < 100) - virtual void write(uint8_t value); + virtual void write(uint8_t /*value*/); #else - virtual size_t write(uint8_t value); + virtual size_t write(uint8_t /*value*/); #endif #if (ARDUINO < 100) @@ -566,9 +568,9 @@ private: the LCD. */ #if (ARDUINO < 100) - virtual void send(uint8_t value, uint8_t mode) { }; + virtual void send(uint8_t /*value*/, uint8_t /*mode*/) { }; #else - virtual void send(uint8_t value, uint8_t mode) = 0; + virtual void send(uint8_t /*value*/, uint8_t /*mode*/) = 0; #endif }; diff --git a/libraries/LiquidCrystal/LiquidCrystal_I2C_ByVac.cpp b/libraries/LiquidCrystal/LiquidCrystal_I2C_ByVac.cpp index 69dd9e7..9f73fab 100644 --- a/libraries/LiquidCrystal/LiquidCrystal_I2C_ByVac.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal_I2C_ByVac.cpp @@ -38,7 +38,7 @@ LiquidCrystal_I2C_ByVac::LiquidCrystal_I2C_ByVac( uint8_t lcd_Addr ) { _Addr = lcd_Addr; - _polarity == NEGATIVE; + _polarity = NEGATIVE; } // PUBLIC METHODS diff --git a/libraries/LiquidCrystal/LiquidCrystal_SR.cpp b/libraries/LiquidCrystal/LiquidCrystal_SR.cpp index a966caa..64aae2f 100644 --- a/libraries/LiquidCrystal/LiquidCrystal_SR.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal_SR.cpp @@ -110,6 +110,8 @@ LiquidCrystal_SR::LiquidCrystal_SR (uint8_t srdata, uint8_t srclock, void LiquidCrystal_SR::init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font) { + (void)lines; + (void)font; // Initialise private variables _two_wire = 0; @@ -200,10 +202,10 @@ void LiquidCrystal_SR::send(uint8_t value, uint8_t mode) // // setBacklightPin void LiquidCrystal_SR::setBacklightPin ( uint8_t pin, t_backlighPol pol ) -{ } +{ (void)pin; (void)pol; } // // setBacklight void LiquidCrystal_SR::setBacklight ( uint8_t mode ) -{ } +{ (void)mode; } diff --git a/libraries/LiquidCrystal/LiquidCrystal_SR1W.cpp b/libraries/LiquidCrystal/LiquidCrystal_SR1W.cpp index f32ef70..a04dfb2 100644 --- a/libraries/LiquidCrystal/LiquidCrystal_SR1W.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal_SR1W.cpp @@ -49,6 +49,8 @@ LiquidCrystal_SR1W::LiquidCrystal_SR1W (uint8_t srdata, t_sr1w_circuitType circu // init void LiquidCrystal_SR1W::init(uint8_t srdata, t_sr1w_circuitType circuitType, t_backlighPol blpol, uint8_t lines, uint8_t font) { + (void)lines; + (void)font; _srRegister = fio_pinToOutputRegister(srdata); _srMask = fio_pinToBit(srdata); diff --git a/libraries/LiquidCrystal/LiquidCrystal_SR1W.h b/libraries/LiquidCrystal/LiquidCrystal_SR1W.h index d71c173..7b26900 100644 --- a/libraries/LiquidCrystal/LiquidCrystal_SR1W.h +++ b/libraries/LiquidCrystal/LiquidCrystal_SR1W.h @@ -154,7 +154,7 @@ // | | | / | 1k // | +--8-|GND Q'H|--9-----+ | // | | +---------+ | | (GND)--(LCD RW) -// | | 0.1uF | \ +/* | | 0.1uF | \ */ // | (GND)-----||----(VCC) +------)--------------(LCD EN) // | | / // |----|<|----+--[ Resistor ]--| | diff --git a/libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp b/libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp index df4559a..e76a585 100644 --- a/libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp @@ -47,6 +47,8 @@ LiquidCrystal_SR2W::LiquidCrystal_SR2W (uint8_t srdata, uint8_t srclock, t_backl // init void LiquidCrystal_SR2W::init(uint8_t srdata, uint8_t srclock, t_backlighPol blpol, uint8_t lines, uint8_t font) { + (void)lines; + (void)font; _srDataRegister = fio_pinToOutputRegister(srdata); _srDataMask = fio_pinToBit(srdata); _srClockRegister = fio_pinToOutputRegister(srclock); diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 9b0a2d7..9731a71 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -24,11 +24,15 @@ // Enable debug flag for debug prints. This will add a lot to the size of the final sketch but good // to see what is actually is happening when developing -#define DEBUG +#define MY_DEBUG + +// Disable this line, If you are using TX(1), RX(0) as normal I/O pin +#define MY_ENABLED_SERIAL // Serial output baud rate (for debug prints and serial gateway) +#ifndef MY_BAUD_RATE #define MY_BAUD_RATE 115200 - +#endif /********************************** * Over the air firmware updates @@ -40,10 +44,13 @@ // requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE //#define MY_OTA_FIRMWARE_FEATURE // Slave select pin for external flash +#ifdef MY_OTA_FLASH_SS #define MY_OTA_FLASH_SS 8 +#endif // Flash jdecid +#ifdef MY_OTA_FLASH_JDECID #define MY_OTA_FLASH_JDECID 0x1F65 - +#endif /********************************** * Information LEDs blinking @@ -63,23 +70,30 @@ // default LEDs blinking period in milliseconds +#ifndef MY_DEFAULT_LED_BLINK_PERIOD #define MY_DEFAULT_LED_BLINK_PERIOD 300 +#endif // The RX LED default pin +#ifndef MY_DEFAULT_RX_LED_PIN #define MY_DEFAULT_RX_LED_PIN 6 +#endif // The TX LED default pin +#ifndef MY_DEFAULT_TX_LED_PIN #define MY_DEFAULT_TX_LED_PIN 5 +#endif // The Error LED default pin +#ifndef MY_DEFAULT_ERR_LED_PIN #define MY_DEFAULT_ERR_LED_PIN 4 - +#endif /********************************************** * Gateway inclusion button/mode configuration **********************************************/ // Enabled inclusion mode feature -#define MY_INCLUSION_MODE_FEATURE +//#define MY_INCLUSION_MODE_FEATURE // Enables inclusion-mode button feature on the gateway device -#define MY_INCLUSION_BUTTON_FEATURE +//#define MY_INCLUSION_BUTTON_FEATURE // Disable inclusion mode button if inclusion mode feature is not enabled #ifndef MY_INCLUSION_MODE_FEATURE @@ -87,9 +101,13 @@ #endif // The default input pin used for the inclusion mode button +#ifndef MY_INCLUSION_MODE_BUTTON_PIN #define MY_INCLUSION_MODE_BUTTON_PIN 3 +#endif // Number of seconds (default one minute) inclusion mode should be enabled +#ifndef MY_INCLUSION_MODE_DURATION #define MY_INCLUSION_MODE_DURATION 60 +#endif /********************************** * Message Signing Settings @@ -122,7 +140,6 @@ // Key to use for HMAC calculation in MySigningAtsha204Soft (32 bytes) #define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - /********************************** * NRF24L01 Driver Defaults ***********************************/ @@ -170,6 +187,6 @@ //#define IP_ADDRESS_DHCP // Enable to use UDP instead of plain Ethernet -#define USE_UDP +#define MY_USE_UDP #endif diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp deleted file mode 100644 index 2eeb039..0000000 --- a/libraries/MySensors/MyGateway.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * 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. - */ - -#include "MyGateway.h" - -// Inline function and macros -static inline MyMessage& build(MyMessage &msg, uint8_t type) { - msg.sender = GATEWAY_ADDRESS; - msg.destination = GATEWAY_ADDRESS; - msg.sensor = 0; - msg.type = type; - mSetCommand(msg, C_INTERNAL); - mSetRequestAck(msg, false); - mSetAck(msg, false); - return msg; -} - -MyGateway::MyGateway(MyGatewayTransport &_transport, MyTransport &_radio, - MyHw &_hw -#ifdef MY_SIGNING_FEATURE - , MySigning &_signer -#endif -#ifdef MY_LEDS_BLINKING_FEATURE - , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period -#endif - ) : - transport(_transport), MySensor(_radio, _hw -#ifdef MY_SIGNING_FEATURE - , _signer -#endif -#ifdef MY_LEDS_BLINKING_FEATURE - , _rx, _tx, _er, _blink_period -#endif - ) -{ -#ifdef MY_INCLUSION_MODE_FEATURE - inclusionMode = false; -#endif -} - -void MyGateway::begin(void (*_msgCallback)(const MyMessage &) -#ifdef MY_INCLUSION_MODE_FEATURE - , int _inclusionModeDuration -#ifdef MY_INCLUSION_BUTTON_FEATURE - , uint8_t _inclusionModeButtonPin -#endif -#endif - -) { - // Setup digital in that triggers inclusion mode -#ifdef MY_INCLUSION_MODE_FEATURE - inclusionDuration = _inclusionModeDuration*1000; -#ifdef MY_INCLUSION_BUTTON_FEATURE - inclusionButtonPin = _inclusionModeButtonPin; - pinMode(inclusionButtonPin, INPUT); - digitalWrite(inclusionButtonPin, HIGH); -#endif -#endif - - // initialize the transport driver - if (!transport.begin()) { - debug(PSTR("transport driver init fail\n")); - while(1); // Nothing more we can do - } - - // Start MySensors in repeater mode - MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS); - - // Startup complete - transport.send(build(msg, I_GATEWAY_READY).set("Gateway startup complete.")); - -} - -boolean MyGateway::sendRoute(MyMessage &message) { - if (message.destination == GATEWAY_ADDRESS) { - // This is a message sent from a sensor attached on the gateway node. - // Pass it directly to the gateway transport layer. - transport.send(message); - } else { - MySensor::sendRoute(message); - } -} - -boolean MyGateway::process() { -#ifdef MY_INCLUSION_MODE_FEATURE - checkInclusionMode(); -#endif - bool newMessage = false; - if (transport.available()) { - MyMessage &gmsg = transport.receive(); - if (msg.destination == GATEWAY_ADDRESS) { - // Check if sender requests an ack back. - if (mGetRequestAck(gmsg)) { - // Copy message - tmpMsg = gmsg; - mSetRequestAck(tmpMsg, false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(tmpMsg, true); - tmpMsg.sender = nc.nodeId; - tmpMsg.destination = msg.sender; - transport.send(tmpMsg); - } - if (mGetCommand(gmsg) == C_INTERNAL) { - if (msg.type == I_VERSION) { - // Request for version. Create the response - transport.send(build(msg, I_VERSION).set(LIBRARY_VERSION)); -#ifdef MY_INCLUSION_MODE_FEATURE - } else if (msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(msg.data) == 1); -#endif - } else { - processInternalMessages(gmsg); - } - } else { - // Call incoming message callback if available - if (msgCallback != NULL) { - msgCallback(msg); - } - newMessage = true; - } - } - } - - // new message from sensor node - if (MySensor::process()) { - MyMessage &msg = MySensor::getLastMessage(); - newMessage = true; - transport.send(msg); - } - - return newMessage; -} - -#ifdef MY_INCLUSION_MODE_FEATURE -void MyGateway::setInclusionMode(boolean newMode) { - if (newMode != inclusionMode) { - inclusionMode = newMode; - // Send back mode change to controller - transport.send(build(msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); - if (inclusionMode) { - - inclusionStartTime = hw_millis(); - Serial.println(inclusionStartTime); - Serial.println(inclusionDuration); - - } - } -} - -void MyGateway::checkInclusionMode() { - - #ifdef MY_INCLUSION_BUTTON_FEATURE - if (!inclusionMode && digitalRead(inclusionButtonPin) == LOW) { - // Start inclusion mode - setInclusionMode(true); - } - #endif - - if (inclusionMode && hw_millis()-inclusionStartTime>inclusionDuration) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - setInclusionMode(false); - } -} - - -#endif - - diff --git a/libraries/MySensors/MyGateway.h b/libraries/MySensors/MyGateway.h deleted file mode 100644 index 7ec55dc..0000000 --- a/libraries/MySensors/MyGateway.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * 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. - */ - -#ifndef MyGateway_h -#define MyGateway_h - - -#include "MyConfig.h" -#include "MySensor.h" -#include "MyHw.h" -#include "MyTransport.h" -#include "MyTransportNRF24.h" -#ifdef MY_SIGNING_FEATURE -#include "MySigning.h" -#include "MySigningNone.h" -#endif -#include "MyMessage.h" -#ifdef MY_OTA_FIRMWARE_FEATURE -#include "utility/SPIFlash.h" -#endif - -#include "MyProtocol.h" -#include "MyGatewayTransport.h" -#include "MyGatewayTransportSerial.h" - -#include -#include - - -class MyGateway : public MySensor -{ -public: - // MyProtocolSerial constructor - MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() -#ifdef MY_SIGNING_FEATURE - , MySigning &signer=*new MySigningNone() -#endif -#ifdef MY_LEDS_BLINKING_FEATURE - , uint8_t _rx=MY_DEFAULT_RX_LED_PIN - , uint8_t _tx=MY_DEFAULT_TX_LED_PIN - , uint8_t _er=MY_DEFAULT_ERR_LED_PIN - , unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD -#endif - ); - - - /** - * Begin operation of the MySensors library - * - * 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 inclusionModeDuration Number of milliseconds inclusion mode should be enabled - * @param inclusionModeButtonPin Button pin used for enabling inclusion mode - */ - - void begin(void (* msgCallback)(const MyMessage &)=NULL -#ifdef MY_INCLUSION_MODE_FEATURE - , int inclusionModeDuration=MY_INCLUSION_MODE_DURATION -#ifdef MY_INCLUSION_BUTTON_FEATURE - , uint8_t inclusionModeButtonPin=MY_INCLUSION_MODE_BUTTON_PIN -#endif -#endif - ); - - - /** - * See MySensor.h - * - * Overloaded to handle local sensor data sent to controller. - */ - boolean sendRoute(MyMessage &message); - - /** - * Processes incoming messages to this node. - * Returns true if there is a message addressed for this node was received. - * Preferred way of handling incoming messages is to use the callback defined in begin(). - */ - boolean process(); - -private: - - MyGatewayTransport &transport; - -#ifdef MY_INCLUSION_MODE_FEATURE - - void setInclusionMode(bool newMode); - void checkInclusionMode(); - unsigned long inclusionStartTime; - bool inclusionMode; - unsigned long inclusionDuration; - - #ifdef MY_INCLUSION_BUTTON_FEATURE - uint8_t inclusionButtonPin; - #endif -#endif -}; - -#endif diff --git a/libraries/MySensors/MyGatewayTransportEthernet.cpp b/libraries/MySensors/MyGatewayTransportEthernet.cpp index 7d5e948..7b9083d 100644 --- a/libraries/MySensors/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/MyGatewayTransportEthernet.cpp @@ -58,7 +58,7 @@ bool MyGatewayTransportEthernet::begin() { // TODO: use HW delay delay(1000); -#ifdef USE_UDP +#ifdef MY_USE_UDP server = new EthernetUDP(); server->begin(gatewayPort); #else @@ -78,7 +78,7 @@ bool MyGatewayTransportEthernet::send(MyMessage &message) } else { msg = protocol.format(message); -#ifdef USE_UDP +#ifdef MY_USE_UDP server->beginPacket(controllerIP, controllerPort); server->write(msg, strlen(msg)); // returns 1 if the packet was sent successfully @@ -107,7 +107,7 @@ bool MyGatewayTransportEthernet::available() renewIP(); #endif -#ifdef USE_UDP +#ifdef MY_USE_UDP int packet_size = server->parsePacket(); if (server->available()) { diff --git a/libraries/MySensors/MyGatewayTransportEthernet.h b/libraries/MySensors/MyGatewayTransportEthernet.h index fefda1c..7256b1a 100644 --- a/libraries/MySensors/MyGatewayTransportEthernet.h +++ b/libraries/MySensors/MyGatewayTransportEthernet.h @@ -26,17 +26,17 @@ #include "MyGatewayTransport.h" #include "MyProtocolDefault.h" -#include +#include "drivers/Ethernet_W5100/IPAddress.h" // Use this if you have attached a Ethernet ENC28J60 shields //#include // Use this fo WizNET W5100 module and Arduino Ethernet Shield -#include +#include "drivers/Ethernet_W5100/Ethernet.h" -#ifdef USE_UDP -#include -#endif /* USE_UDP */ +#ifdef MY_USE_UDP +#include "drivers/Ethernet_W5100/EthernetUdp.h" +#endif /* MY_USE_UDP */ #define CONTROLLER_PORT 5003 #define IP_RENEWAL_INTERVAL 60000 // in milliseconds @@ -86,11 +86,11 @@ protected: IPAddress gatewayIP; uint16_t gatewayPort; -#ifndef USE_UDP +#ifdef MY_USE_UDP + EthernetUDP *server; +#else EthernetServer *server; uint8_t inputPos; -#else - EthernetUDP *server; #endif char inputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface diff --git a/libraries/MySensors/MyHw.h b/libraries/MySensors/MyHw.h index 74ceb13..506648b 100644 --- a/libraries/MySensors/MyHw.h +++ b/libraries/MySensors/MyHw.h @@ -45,7 +45,7 @@ public: virtual void sleep(unsigned long ms) = 0; virtual bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) = 0; virtual uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) = 0; - #ifdef DEBUG + #ifdef MY_DEBUG virtual void debugPrint(bool isGW, const char *fmt, ... ) = 0; #endif diff --git a/libraries/MySensors/MyHwATMega328.cpp b/libraries/MySensors/MyHwATMega328.cpp index a9e6de7..ad05033 100644 --- a/libraries/MySensors/MyHwATMega328.cpp +++ b/libraries/MySensors/MyHwATMega328.cpp @@ -17,6 +17,8 @@ * version 2 as published by the Free Software Foundation. */ +#ifdef ARDUINO_ARCH_AVR + #include "MyHw.h" #include "MyHwATMega328.h" @@ -119,7 +121,9 @@ void powerDown(period_t period) { void MyHwATMega328::internalSleep(unsigned long ms) { // Let serial prints finish (debug, log etc) - Serial.flush(); + #ifdef MY_ENABLED_SERIAL + Serial.flush(); + #endif pinIntTrigger = 0; while (!pinIntTrigger && ms >= 8000) { powerDown(SLEEP_8S); ms -= 8000; } if (!pinIntTrigger && ms >= 4000) { powerDown(SLEEP_4S); ms -= 4000; } @@ -148,7 +152,9 @@ bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { pinTriggeredWakeup = false; } } else { - Serial.flush(); + #ifdef MY_ENABLED_SERIAL + Serial.flush(); + #endif powerDown(SLEEP_FOREVER); } detachInterrupt(interrupt); @@ -166,7 +172,9 @@ inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t i retVal = -1; } } else { - Serial.flush(); + #ifdef MY_ENABLED_SERIAL + Serial.flush(); + #endif powerDown(SLEEP_FOREVER); } detachInterrupt(interrupt1); @@ -182,7 +190,7 @@ inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t i -#ifdef DEBUG +#ifdef MY_DEBUG void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) { char fmtBuffer[300]; if (isGW) { @@ -209,3 +217,4 @@ void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) { } #endif +#endif // #ifdef ARDUINO_ARCH_AVR diff --git a/libraries/MySensors/MyHwATMega328.h b/libraries/MySensors/MyHwATMega328.h index 5070c2c..a992ff2 100644 --- a/libraries/MySensors/MyHwATMega328.h +++ b/libraries/MySensors/MyHwATMega328.h @@ -20,6 +20,8 @@ #ifndef MyHwATMega328_h #define MyHwATMega328_h +#ifdef ARDUINO_ARCH_AVR + #include "MyHw.h" #include "MyConfig.h" #include "MyMessage.h" @@ -109,10 +111,11 @@ public: void sleep(unsigned long ms); bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms); uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); -#ifdef DEBUG +#ifdef MY_DEBUG void debugPrint(bool isGW, const char *fmt, ... ); #endif private: void internalSleep(unsigned long ms); }; #endif +#endif // #ifdef ARDUINO_ARCH_AVR diff --git a/libraries/MySensors/MyHwESP8266.cpp b/libraries/MySensors/MyHwESP8266.cpp new file mode 100644 index 0000000..fa36ebf --- /dev/null +++ b/libraries/MySensors/MyHwESP8266.cpp @@ -0,0 +1,184 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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. + */ + +#ifdef ARDUINO_ARCH_ESP8266 + +#include "MyHw.h" +#include "MyHwESP8266.h" +#include + +/* +int8_t pinIntTrigger = 0; +void wakeUp() //place to send the interrupts +{ + pinIntTrigger = 1; +} +void wakeUp2() //place to send the second interrupts +{ + pinIntTrigger = 2; +} + +// Watchdog Timer interrupt service routine. This routine is required +// to allow automatic WDIF and WDIE bit clearance in hardware. +ISR (WDT_vect) +{ + // WDIE & WDIF is cleared in hardware upon entering this ISR + wdt_disable(); +} +*/ + +static void hw_initConfigBlock( size_t length = 1024 /*ATMega328 has 1024 bytes*/ ) +{ + static bool initDone = false; + if (!initDone) + { + EEPROM.begin(length); + initDone = true; + } +} + +void hw_readConfigBlock(void* buf, void* adr, size_t length) +{ + hw_initConfigBlock(); + uint8_t* dst = static_cast(buf); + int offs = reinterpret_cast(adr); + while (length-- > 0) + { + *dst++ = EEPROM.read(offs++); + } +} + +void hw_writeConfigBlock(void* buf, void* adr, size_t length) +{ + hw_initConfigBlock(); + uint8_t* src = static_cast(buf); + int offs = reinterpret_cast(adr); + while (length-- > 0) + { + EEPROM.write(offs++, *src++); + } + EEPROM.commit(); +} + +uint8_t hw_readConfig(int adr) +{ + uint8_t value; + hw_readConfigBlock(&value, reinterpret_cast(adr), 1); + return value; +} + +void hw_writeConfig(int adr, uint8_t value) +{ + uint8_t curr = hw_readConfig(adr); + if (curr != value) + { + hw_writeConfigBlock(&value, reinterpret_cast(adr), 1); + } +} + + + +MyHwESP8266::MyHwESP8266() : MyHw() +{ +} + + +/* + +// The following was redifined as macros to save space + +inline uint8_t MyHwATMega328::readConfig(uint8_t pos) { + return eeprom_read_byte((uint8_t*)pos); +} + +inline void MyHwATMega328::writeConfig(uint8_t pos, uint8_t value) { + eeprom_update_byte((uint8_t*)pos, value); +} + +inline void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) { + eeprom_read_block(buf, (void*)pos, length); +} + +inline void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) { + eeprom_write_block((void*)pos, (void*)buf, length); +} + + +inline void MyHwATMega328::init() { + Serial.begin(BAUD_RATE); +} + +inline void MyHwATMega328::watchdogReset() { + wdt_reset(); +} + +inline void MyHwATMega328::reboot() { + wdt_enable(WDTO_15MS); for (;;); +} + +inline unsigned long MyHwATMega328::millis() { + return ::millis(); +} +*/ + + +void MyHwESP8266::sleep(unsigned long ms) { + // TODO: Not supported! +} + +bool MyHwESP8266::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { + // TODO: Not supported! + return false; +} + +inline uint8_t MyHwESP8266::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { + // TODO: Not supported! + return 0; +} + + + +#ifdef MY_DEBUG +void MyHwESP8266::debugPrint(bool isGW, const char *fmt, ... ) { + char fmtBuffer[300]; + if (isGW) { + // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) + snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); + Serial.print(fmtBuffer); + } + va_list args; + va_start (args, fmt ); + va_end (args); + if (isGW) { + // Truncate message if this is gateway node + vsnprintf_P(fmtBuffer, 60, fmt, args); + fmtBuffer[59] = '\n'; + fmtBuffer[60] = '\0'; + } else { + vsnprintf_P(fmtBuffer, 299, fmt, args); + } + va_end (args); + Serial.print(fmtBuffer); + Serial.flush(); + + //Serial.write(freeRam()); +} +#endif + +#endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/MyHwESP8266.h b/libraries/MySensors/MyHwESP8266.h new file mode 100644 index 0000000..03f47c3 --- /dev/null +++ b/libraries/MySensors/MyHwESP8266.h @@ -0,0 +1,86 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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. + */ + +#ifdef ARDUINO_ARCH_ESP8266 + +#ifndef MyHwESP8266_h +#define MyHwESP8266_h + +#include "MyHw.h" +#include "MyConfig.h" +#include "MyMessage.h" + + +#ifdef __cplusplus +#include +#include +#endif + +// Define these as macros to save valuable space + +#define hw_digitalWrite(__pin, __value) (digitalWrite(__pin, __value)) +#define hw_init() Serial.begin(BAUD_RATE) +#define hw_watchdogReset() wdt_reset() +#define hw_reboot() wdt_enable(WDTO_15MS); while (1) +#define hw_millis() millis() + +void hw_readConfigBlock(void* buf, void* adr, size_t length); +void hw_writeConfigBlock(void* buf, void* adr, size_t length); +void hw_writeConfig(int adr, uint8_t value); +uint8_t hw_readConfig(int adr); + +enum period_t +{ + SLEEP_15Ms, + SLEEP_30MS, + SLEEP_60MS, + SLEEP_120MS, + SLEEP_250MS, + SLEEP_500MS, + SLEEP_1S, + SLEEP_2S, + SLEEP_4S, + SLEEP_8S, + SLEEP_FOREVER +}; + +class MyHwESP8266 : public MyHw +{ +public: + MyHwESP8266(); + +/* void init(); + void watchdogReset(); + void reboot(); + unsigned long millis(); + uint8_t readConfig(uint8_t pos); + void writeConfig(uint8_t pos, uint8_t value); + void readConfigBlock(void* buf, void * pos, size_t length); + void writeConfigBlock(void* pos, void* buf, size_t length); */ + + void sleep(unsigned long ms); + bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms); + uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); +#ifdef MY_DEBUG + void debugPrint(bool isGW, const char *fmt, ... ); +#endif +}; +#endif + +#endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/MyMessage.h b/libraries/MySensors/MyMessage.h index 03a203c..5a9fc43 100644 --- a/libraries/MySensors/MyMessage.h +++ b/libraries/MySensors/MyMessage.h @@ -58,7 +58,7 @@ typedef enum { S_UV, // Uv sensor, V_UV S_WEIGHT, // Personal scale sensor, V_WEIGHT, V_IMPEDANCE S_POWER, // Power meter, V_WATT, V_KWH - S_HEATER, // Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE + S_HEATER, // Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE, V_TEMP S_DISTANCE, // Distance sensor, V_DISTANCE S_LIGHT_LEVEL, // Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage), V_LEVEL (light level in lux) S_ARDUINO_NODE, // Used (internally) for presenting a non-repeating Arduino node @@ -73,53 +73,56 @@ typedef enum { S_RGB_LIGHT, // RGB light. Send color component data using V_RGB. Also supports V_WATT S_RGBW_LIGHT, // RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT S_COLOR_SENSOR, // Color sensor, send color information using V_RGB - S_HVAC, // Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE + S_HVAC, // Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_TEMP S_MULTIMETER, // Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE S_SPRINKLER, // Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) S_WATER_LEAK, // Water leak sensor, V_TRIPPED, V_ARMED S_SOUND, // Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB) S_VIBRATION, // Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz) S_MOISTURE, // Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?) + S_INFO, // LCD text device / Simple information device on controller, V_TEXT + S_GAS, // Gas meter, V_FLOW, V_VOLUME + } mysensor_sensor; // Type of sensor data (for set/req/ack messages) typedef enum { - V_TEMP, // S_TEMP - V_HUM, // S_HUM - V_STATUS, // S_LIGHT, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting binary (on/off) status. 1=on, 0=off + V_TEMP, // S_TEMP. Temperature S_TEMP, S_HEATER, S_HVAC + V_HUM, // S_HUM. Humidity + V_STATUS, // S_LIGHT, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off V_LIGHT=2, // Same as V_STATUS - V_PERCENTAGE, // S_DIMMER. Used for sending a percentage value (0-100). + V_PERCENTAGE, // S_DIMMER. Used for sending a percentage value 0-100 (%). V_DIMMER=3, // S_DIMMER. Same as V_PERCENTAGE. - V_PRESSURE, // S_BARO - V_FORECAST, // S_BARO - V_RAIN, // S_RAIN - V_RAINRATE, // S_RAIN - V_WIND, // S_WIND - V_GUST, // S_WIND - V_DIRECTION, // S_WIND - V_UV, // S_UV - V_WEIGHT, // S_WEIGHT - V_DISTANCE, // S_DISTANCE - V_IMPEDANCE, // S_MULTIMETER, S_WEIGHT - V_ARMED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER - V_TRIPPED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER (for sprinklers with fire detection) - V_WATT, // S_POWER, S_LIGHT, S_DIMMER - V_KWH, // S_POWER - V_SCENE_ON, // S_SCENE_CONTROLLER - V_SCENE_OFF, // S_SCENE_CONTROLLER + V_PRESSURE, // S_BARO. Atmospheric Pressure + V_FORECAST, // S_BARO. Whether forecast. string of "stable", "sunny", "cloudy", "unstable", "thunderstorm" or "unknown" + V_RAIN, // S_RAIN. Amount of rain + V_RAINRATE, // S_RAIN. Rate of rain + V_WIND, // S_WIND. Wind speed + V_GUST, // S_WIND. Gust + V_DIRECTION, // S_WIND. Wind direction 0-360 (degrees) + V_UV, // S_UV. UV light level + V_WEIGHT, // S_WEIGHT. Weight(for scales etc) + V_DISTANCE, // S_DISTANCE. Distance + V_IMPEDANCE, // S_MULTIMETER, S_WEIGHT. Impedance value + V_ARMED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER. Armed status of a security sensor. 1 = Armed, 0 = Bypassed + V_TRIPPED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER, S_WATER_LEAK, S_SOUND, S_VIBRATION, S_MOISTURE. Tripped status of a security sensor. 1 = Tripped, 0 + V_WATT, // S_POWER, S_LIGHT, S_DIMMER, S_RGB, S_RGBW. Watt value for power meters + V_KWH, // S_POWER. Accumulated number of KWH for a power meter + V_SCENE_ON, // S_SCENE_CONTROLLER. Turn on a scene + V_SCENE_OFF, // S_SCENE_CONTROLLER. Turn of a scene V_HEATER, // Deprecated. Use V_HVAC_FLOW_STATE instead. - V_HVAC_FLOW_STATE=21, // HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver"). S_HEATER, S_HVAC - V_HVAC_SPEED, // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") - V_LIGHT_LEVEL, // Used for sending light level in uncalibrated percentage. See also V_LEVEL (light level in lux). S_LIGHT_LEVEL + V_HVAC_FLOW_STATE=21, // S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver") + V_HVAC_SPEED, // S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + V_LIGHT_LEVEL, // S_LIGHT_LEVEL. Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux V_VAR1, V_VAR2, V_VAR3, V_VAR4, V_VAR5, - V_UP, // S_COVER - V_DOWN, // S_COVER - V_STOP, // S_COVER - V_IR_SEND, // S_IR - V_IR_RECEIVE, // S_IR - V_FLOW, // S_WATER - V_VOLUME, // S_WATER - V_LOCK_STATUS, // S_LOCK + V_UP, // S_COVER. Window covering. Up + V_DOWN, // S_COVER. Window covering. Down + V_STOP, // S_COVER. Window covering. Stop + V_IR_SEND, // S_IR. Send out an IR-command + V_IR_RECEIVE, // S_IR. This message contains a received IR-command + V_FLOW, // S_WATER. Flow of water (in meter) + V_VOLUME, // S_WATER. Water volume + V_LOCK_STATUS, // S_LOCK. Set or get lock status. 1=Locked, 0=Unlocked V_LEVEL, // S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux) V_VOLTAGE, // S_MULTIMETER V_CURRENT, // S_MULTIMETER @@ -128,16 +131,17 @@ typedef enum { // Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component) V_RGBW, // S_RGBW_LIGHT // Used for sending color information to multi color LED lighting. - // Sent as ASCII hex: RRGGBBWW (WW=while component) + // Sent as ASCII hex: RRGGBBWW (WW=white component) V_ID, // S_TEMP // Used for sending in sensors hardware ids (i.e. OneWire DS1820b). - V_UNIT_PREFIX, // Allows sensors to send in a string representing the - // unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch. - // Can be used for S_DISTANCE or gas concentration (S_DUST, S_AIR_QUALITY) - V_HVAC_SETPOINT_COOL, // HVAC cool setpoint (Integer between 0-100). S_HVAC - V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC - V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn"). S_HVAC - + V_UNIT_PREFIX, // S_DUST, S_AIR_QUALITY + // Allows sensors to send in a string representing the + // unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch. + // Can be used for S_DISTANCE or gas concentration + V_HVAC_SETPOINT_COOL, // S_HVAC. HVAC cool setpoint (Integer between 0-100) + V_HVAC_SETPOINT_HEAT, // S_HEATER, S_HVAC. HVAC/Heater setpoint (Integer between 0-100) + V_HVAC_FLOW_MODE, // S_HVAC. Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") + V_TEXT, // S_INFO. Text message to display on LCD or controller device } mysensor_data; @@ -163,7 +167,9 @@ typedef enum { +#ifndef BIT #define BIT(n) ( 1<<(n) ) +#endif // Create a bitmask of length len. #define BIT_MASK(len) ( BIT(len)-1 ) // Create a bitfield mask of length starting at bit 'start'. diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index 500a9e1..6a8f96e 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -18,8 +18,29 @@ */ + #include "MySensor.h" + + +#include "drivers/RF24/RF24.cpp" + +#include "drivers/RFM69/RFM69.cpp" + +#include "drivers/ATSHA204/ATSHA204.cpp" +#include "drivers/ATSHA204/sha256.cpp" + +#include "drivers/SPIFlash/SPIFlash.cpp" + + +#include "drivers/Ethernet_W5100/utility/socket.cpp" +#include "drivers/Ethernet_W5100/utility/w5100.cpp" +#include "drivers/Ethernet_W5100/DNS.cpp" +#include "drivers/Ethernet_W5100/Ethernet.cpp" +#include "drivers/Ethernet_W5100/EthernetUdp.cpp" +#include "drivers/Ethernet_W5100/IPAddress.cpp" + + #define DISTANCE_INVALID (0xFF) #ifdef MY_SIGNING_FEATURE @@ -52,9 +73,6 @@ static inline bool isValidDistance( const uint8_t distance ) { MySensor::MySensor(MyTransport &_radio, MyHw &_hw #ifdef MY_SIGNING_FEATURE , MySigning &_signer -#endif -#ifdef MY_LEDS_BLINKING_FEATURE - , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period #endif ) : @@ -62,9 +80,6 @@ MySensor::MySensor(MyTransport &_radio, MyHw &_hw #ifdef MY_SIGNING_FEATURE signer(_signer), #endif -#ifdef MY_LEDS_BLINKING_FEATURE - pinRx(_rx), pinTx(_tx), pinEr(_er), ledBlinkPeriod(_blink_period), -#endif #ifdef MY_OTA_FIRMWARE_FEATURE flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID), #endif @@ -95,45 +110,45 @@ bool MySensor::isValidFirmware() { #ifdef MY_LEDS_BLINKING_FEATURE void MySensor::handleLedsBlinking() { - static unsigned long next_time = hw_millis() + ledBlinkPeriod; + static unsigned long next_time = hw_millis() + MY_DEFAULT_LED_BLINK_PERIOD; // Just return if it is not the time... // http://playground.arduino.cc/Code/TimingRollover - if ((long)(hw_millis() - next_time) < 0) + if ((long)(hw_millis() - blink_next_time) < 0) return; else - next_time = hw_millis() + ledBlinkPeriod; + blink_next_time = hw_millis() + ledBlinkPeriod; // do the actual blinking if(countRx && countRx != 255) { // switch led on - hw_digitalWrite(pinRx, LED_ON); + hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); } else if(!countRx) { // switching off - hw_digitalWrite(pinRx, LED_OFF); + hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); } if(countRx != 255) --countRx; if(countTx && countTx != 255) { // switch led on - hw_digitalWrite(pinTx, LED_ON); + hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); } else if(!countTx) { // switching off - hw_digitalWrite(pinTx, LED_OFF); + hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); } if(countTx != 255) --countTx; if(countErr && countErr != 255) { // switch led on - hw_digitalWrite(pinEr, LED_ON); + hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); } else if(!countErr) { // switching off - hw_digitalWrite(pinEr, LED_OFF); + hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); } if(countErr != 255) --countErr; @@ -153,7 +168,9 @@ void MySensor::errBlink(uint8_t cnt) { #endif void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) { - hw_init(); + #ifdef MY_ENABLED_SERIAL + hw_init(); + #endif repeaterMode = _repeaterMode; msgCallback = _msgCallback; failedTransmissions = 0; @@ -174,14 +191,14 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b #ifdef MY_LEDS_BLINKING_FEATURE // Setup led pins - pinMode(pinRx, OUTPUT); - pinMode(pinTx, OUTPUT); - pinMode(pinEr, OUTPUT); + pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); // Set initial state of leds - hw_digitalWrite(pinRx, LED_OFF); - hw_digitalWrite(pinTx, LED_OFF); - hw_digitalWrite(pinEr, LED_OFF); + hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); + hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); + hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); // initialize counters countRx = 0; @@ -397,6 +414,10 @@ boolean MySensor::sendRoute(MyMessage &message) { #endif if (dest == GATEWAY_ADDRESS || !repeaterMode) { + // Store this address in routing table (if repeater) + if (repeaterMode) { + hw_writeConfig(EEPROM_ROUTES_ADDRESS+sender, last); + } // If destination is the gateway or if we aren't a repeater, let // our parent take care of the message ok = sendWrite(nc.parentNodeId, message); @@ -555,6 +576,7 @@ boolean MySensor::process() { #endif uint8_t len = radio.receive((uint8_t *)&msg); + (void)len; //until somebody makes use of 'len' #ifdef MY_LEDS_BLINKING_FEATURE rxBlink(1); #endif @@ -887,3 +909,148 @@ int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, ui #endif } + + + + +// Inline function and macros +static inline MyMessage& buildGw(MyMessage &msg, uint8_t type) { + msg.sender = GATEWAY_ADDRESS; + msg.destination = GATEWAY_ADDRESS; + msg.sensor = 0; + msg.type = type; + mSetCommand(msg, C_INTERNAL); + mSetRequestAck(msg, false); + mSetAck(msg, false); + return msg; +} + +MyGateway::MyGateway(MyGatewayTransport &_transport, MyTransport &_radio, + MyHw &_hw +#ifdef MY_SIGNING_FEATURE + , MySigning &_signer +#endif + ) : + transport(_transport), MySensor(_radio, _hw +#ifdef MY_SIGNING_FEATURE + , _signer +#endif + ) +{ +#ifdef MY_INCLUSION_MODE_FEATURE + inclusionMode = false; +#endif +} + +void MyGateway::begin(void (*_msgCallback)(const MyMessage &)) { + // Setup digital in that triggers inclusion mode +#ifdef MY_INCLUSION_MODE_FEATURE +#ifdef MY_INCLUSION_BUTTON_FEATURE + pinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); + digitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); +#endif +#endif + + // initialize the transport driver + if (!transport.begin()) { + debug(PSTR("transport driver init fail\n")); + while(1); // Nothing more we can do + } + + // Start MySensors in repeater mode + MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS); + + // Startup complete + transport.send(buildGw(msg, I_GATEWAY_READY).set("Gateway startup complete.")); + +} + +boolean MyGateway::sendRoute(MyMessage &message) { + if (message.destination == GATEWAY_ADDRESS) { + // This is a message sent from a sensor attached on the gateway node. + // Pass it directly to the gateway transport layer. + transport.send(message); + } else { + MySensor::sendRoute(message); + } +} + +boolean MyGateway::process() { +#ifdef MY_INCLUSION_MODE_FEATURE + checkInclusionMode(); +#endif + bool newMessage = false; + if (transport.available()) { + MyMessage &gmsg = transport.receive(); + if (msg.destination == GATEWAY_ADDRESS) { + // Check if sender requests an ack back. + if (mGetRequestAck(gmsg)) { + // Copy message + tmpMsg = gmsg; + mSetRequestAck(tmpMsg, false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(tmpMsg, true); + tmpMsg.sender = nc.nodeId; + tmpMsg.destination = msg.sender; + transport.send(tmpMsg); + } + if (mGetCommand(gmsg) == C_INTERNAL) { + if (msg.type == I_VERSION) { + // Request for version. Create the response + transport.send(buildGw(msg, I_VERSION).set(LIBRARY_VERSION)); +#ifdef MY_INCLUSION_MODE_FEATURE + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(msg.data) == 1); +#endif + } else { + processInternalMessages(gmsg); + } + } else { + // Call incoming message callback if available + if (msgCallback != NULL) { + msgCallback(msg); + } + newMessage = true; + } + } + } + + // new message from sensor node + if (MySensor::process()) { + MyMessage &msg = MySensor::getLastMessage(); + newMessage = true; + transport.send(msg); + } + + return newMessage; +} + +#ifdef MY_INCLUSION_MODE_FEATURE +void MyGateway::setInclusionMode(boolean newMode) { + if (newMode != inclusionMode) { + inclusionMode = newMode; + // Send back mode change to controller + transport.send(buildGw(msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); + if (inclusionMode) { + inclusionStartTime = hw_millis(); + } + } +} + +void MyGateway::checkInclusionMode() { + + #ifdef MY_INCLUSION_BUTTON_FEATURE + if (!inclusionMode && digitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == LOW) { + // Start inclusion mode + setInclusionMode(true); + } + #endif + + if (inclusionMode && hw_millis()-inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { + // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode + setInclusionMode(false); + } +} +#endif + + diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 0ca9793..b1d3795 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -32,20 +32,29 @@ #endif #include "MyMessage.h" #ifdef MY_OTA_FIRMWARE_FEATURE -#include "utility/SPIFlash.h" +#include "drivers/SPIFlash/SPIFlash.h" #endif + +#include "MyGatewayTransport.h" +#include "MyGatewayTransportSerial.h" + #include #include // Set the hardware driver to use (initialized by MySensor-class) //#if defined __AVR_ATmega328P__ +#if defined(ARDUINO_ARCH_ESP8266) +#include "MyHwESP8266.h" +typedef MyHwESP8266 MyHwDriver; +#elif defined(ARDUINO_ARCH_AVR) #include "MyHwATMega328.h" typedef MyHwATMega328 MyHwDriver; +#endif //#endif -#ifdef DEBUG +#ifdef MY_DEBUG #define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__) #else #define debug(x,...) @@ -152,12 +161,6 @@ class MySensor MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() #ifdef MY_SIGNING_FEATURE , MySigning &signer=*new MySigningNone() -#endif -#ifdef MY_LEDS_BLINKING_FEATURE - , uint8_t _rx=MY_DEFAULT_RX_LED_PIN, - uint8_t _tx=MY_DEFAULT_TX_LED_PIN, - uint8_t _er=MY_DEFAULT_ERR_LED_PIN, - unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD #endif ); @@ -349,32 +352,28 @@ class MySensor MyMessage msg; // Buffer for incoming messages. MyMessage tmpMsg ; // Buffer for temporary messages (acks and nonces among others). -#ifdef MY_SIGNING_FEATURE - uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication - MyMessage msgSign; // Buffer for message to sign. - MySigning& signer; -#endif #ifdef MY_LEDS_BLINKING_FEATURE - uint8_t pinRx; // Rx led pin - uint8_t pinTx; // Tx led pin - uint8_t pinEr; // Err led pin - // these variables don't need to be volatile, since we are not using interrupts uint8_t countRx; uint8_t countTx; uint8_t countErr; - unsigned long ledBlinkPeriod; void handleLedsBlinking(); // do the actual blinking + unsigned long blink_next_time; #endif MyTransport& radio; +#ifdef MY_SIGNING_FEATURE + uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication + MyMessage msgSign; // Buffer for message to sign. + MySigning& signer; +#endif MyHw& hw; boolean sendWrite(uint8_t dest, MyMessage &message); void processInternalMessages(MyMessage &msg); -#ifdef DEBUG +#ifdef MY_DEBUG char convBuf[MAX_PAYLOAD*2+1]; #endif uint8_t failedTransmissions; @@ -396,4 +395,56 @@ class MySensor }; #endif + +class MyGateway : public MySensor +{ +public: + // MyProtocolSerial constructor + MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() +#ifdef MY_SIGNING_FEATURE + , MySigning &signer=*new MySigningNone() +#endif + ); + + + /** + * Begin operation of the MySensors library + * + * 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 inclusionModeDuration Number of milliseconds inclusion mode should be enabled + * @param inclusionModeButtonPin Button pin used for enabling inclusion mode + */ + + void begin(void (* msgCallback)(const MyMessage &)=NULL); + + + /** + * See MySensor.h + * + * Overloaded to handle local sensor data sent to controller. + */ + boolean sendRoute(MyMessage &message); + + /** + * Processes incoming messages to this node. + * Returns true if there is a message addressed for this node was received. + * Preferred way of handling incoming messages is to use the callback defined in begin(). + */ + boolean process(); + +private: + + MyGatewayTransport& transport; + +#ifdef MY_INCLUSION_MODE_FEATURE + + void setInclusionMode(bool newMode); + void checkInclusionMode(); + unsigned long inclusionStartTime; + bool inclusionMode; +#endif +}; + + #endif diff --git a/libraries/MySensors/MySigningAtsha204.cpp b/libraries/MySensors/MySigningAtsha204.cpp index 2baa0dd..06d1b45 100644 --- a/libraries/MySensors/MySigningAtsha204.cpp +++ b/libraries/MySensors/MySigningAtsha204.cpp @@ -24,10 +24,13 @@ * HMAC-SHA256 authentication with a readout-protected key. * */ +#if defined(ARDUINO_ARCH_AVR) #include "MySigning.h" #include "MySigningAtsha204.h" +#define SIGNING_IDENTIFIER (1) + // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING @@ -264,3 +267,4 @@ uint8_t* MySigningAtsha204::sha256(const uint8_t* data, size_t sz) { DEBUG_SIGNING_PRINTBUF(F("SHA:"), &rx_buffer[SHA204_BUFFER_POS_DATA], 32); return &rx_buffer[SHA204_BUFFER_POS_DATA]; } +#endif // #if defined(ARDUINO_ARCH_AVR) diff --git a/libraries/MySensors/MySigningAtsha204.h b/libraries/MySensors/MySigningAtsha204.h index 5232c00..1242db7 100644 --- a/libraries/MySensors/MySigningAtsha204.h +++ b/libraries/MySensors/MySigningAtsha204.h @@ -30,11 +30,9 @@ #include "MyConfig.h" #include "MySigning.h" -#include "utility/ATSHA204.h" +#include "drivers/ATSHA204/ATSHA204.h" #include -#define SIGNING_IDENTIFIER (1) - #ifdef MY_SECURE_NODE_WHITELISTING typedef struct { uint8_t nodeId; diff --git a/libraries/MySensors/MySigningAtsha204Soft.cpp b/libraries/MySensors/MySigningAtsha204Soft.cpp index 043d367..fc52085 100644 --- a/libraries/MySensors/MySigningAtsha204Soft.cpp +++ b/libraries/MySensors/MySigningAtsha204Soft.cpp @@ -31,7 +31,9 @@ #include "MyConfig.h" #include "MySigning.h" #include "MySigningAtsha204Soft.h" -#include "utility/sha256.h" +#include "drivers/ATSHA204/sha256.h" + +#define SIGNING_IDENTIFIER (1) // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING @@ -72,15 +74,14 @@ MySigningAtsha204Soft::MySigningAtsha204Soft(bool requestSignatures, uint8_t randomseedPin) : MySigning(requestSignatures), - rndPin(randomseedPin), #ifdef MY_SECURE_NODE_WHITELISTING whitlist_sz(nof_whitelist_entries), whitelist(the_whitelist), node_serial_info(the_serial), #endif + Sha256(), verification_ongoing(false), - Sha256() - + rndPin(randomseedPin) { } diff --git a/libraries/MySensors/MySigningAtsha204Soft.h b/libraries/MySensors/MySigningAtsha204Soft.h index 5d8090e..2919812 100644 --- a/libraries/MySensors/MySigningAtsha204Soft.h +++ b/libraries/MySensors/MySigningAtsha204Soft.h @@ -33,12 +33,10 @@ #include "MyConfig.h" #include "MySigning.h" -#include "utility/ATSHA204.h" -#include "utility/sha256.h" +#include "drivers/ATSHA204/ATSHA204.h" +#include "drivers/ATSHA204/sha256.h" #include -#define SIGNING_IDENTIFIER (1) - #ifdef MY_SECURE_NODE_WHITELISTING typedef struct { uint8_t nodeId; diff --git a/libraries/MySensors/MySigningNone.cpp b/libraries/MySensors/MySigningNone.cpp index a73a375..d9aa5ab 100644 --- a/libraries/MySensors/MySigningNone.cpp +++ b/libraries/MySensors/MySigningNone.cpp @@ -29,6 +29,8 @@ #include "MySigning.h" #include "MySigningNone.h" +#define SIGNING_IDENTIFIER (0) + // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING @@ -61,6 +63,7 @@ MySigningNone::MySigningNone() : MySigning() { } bool MySigningNone::getNonce(MyMessage &msg) { + (void)msg; return true; } @@ -69,6 +72,7 @@ bool MySigningNone::checkTimer() { } bool MySigningNone::putNonce(MyMessage &msg) { + (void)msg; return true; } diff --git a/libraries/MySensors/MySigningNone.h b/libraries/MySensors/MySigningNone.h index b024b41..4b27103 100644 --- a/libraries/MySensors/MySigningNone.h +++ b/libraries/MySensors/MySigningNone.h @@ -32,8 +32,6 @@ #include "MySigning.h" #include -#define SIGNING_IDENTIFIER (0) - // The "none" signing driver that can be used for nodes // not requiring signing // It does check SIGNING_IDENTIFIER byte to avoid illegal mixing of signing back-ends in diff --git a/libraries/MySensors/MyTransportNRF24.cpp b/libraries/MySensors/MyTransportNRF24.cpp index fee7dca..d11545d 100644 --- a/libraries/MySensors/MyTransportNRF24.cpp +++ b/libraries/MySensors/MyTransportNRF24.cpp @@ -74,6 +74,7 @@ bool MyTransportNRF24::send(uint8_t to, const void* data, uint8_t len) { bool MyTransportNRF24::available(uint8_t *to) { uint8_t pipe = 255; boolean avail = rf24.available(&pipe); + (void)avail; //until somebody makes use of 'avail' if (pipe == CURRENT_NODE_PIPE) *to = _address; else if (pipe == BROADCAST_PIPE) diff --git a/libraries/MySensors/MyTransportNRF24.h b/libraries/MySensors/MyTransportNRF24.h index 8c582fb..535186d 100644 --- a/libraries/MySensors/MyTransportNRF24.h +++ b/libraries/MySensors/MyTransportNRF24.h @@ -23,8 +23,8 @@ #include "MyConfig.h" #include "MyTransport.h" #include -#include "utility/RF24.h" -#include "utility/RF24_config.h" +#include "drivers/RF24/RF24.h" +#include "drivers/RF24/RF24_config.h" #define TO_ADDR(x) (RF24_BASE_RADIO_ID + x) diff --git a/libraries/MySensors/MyTransportRFM69.cpp b/libraries/MySensors/MyTransportRFM69.cpp index 4ad8fb4..757c9a5 100644 --- a/libraries/MySensors/MyTransportRFM69.cpp +++ b/libraries/MySensors/MyTransportRFM69.cpp @@ -33,7 +33,7 @@ bool MyTransportRFM69::init() { // Start up the radio library (_address will be set later by the MySensors library) radio.initialize(_freqBand, _address, _networkId); #ifdef RFM69_ENABLE_ENCRYPTION - radio.encrypt(ENCRYPTKEY); + radio.encrypt(RFM69_ENCRYPTKEY); #endif return true; } diff --git a/libraries/MySensors/MyTransportRFM69.h b/libraries/MySensors/MyTransportRFM69.h index afb7643..ea9eaa6 100644 --- a/libraries/MySensors/MyTransportRFM69.h +++ b/libraries/MySensors/MyTransportRFM69.h @@ -23,7 +23,7 @@ #include "MyConfig.h" #include "MyTransport.h" #include -#include "utility/RFM69.h" +#include "drivers/RFM69/RFM69.h" #include diff --git a/libraries/MySensors/utility/ATSHA204.cpp b/libraries/MySensors/drivers/ATSHA204/ATSHA204.cpp similarity index 99% rename from libraries/MySensors/utility/ATSHA204.cpp rename to libraries/MySensors/drivers/ATSHA204/ATSHA204.cpp index 504d73d..113038f 100644 --- a/libraries/MySensors/utility/ATSHA204.cpp +++ b/libraries/MySensors/drivers/ATSHA204/ATSHA204.cpp @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_AVR) + #include "Arduino.h" #include "ATSHA204.h" @@ -463,7 +465,8 @@ uint8_t ATSHA204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t uint8_t poll_delay, poll_timeout, response_size; uint8_t *p_buffer; uint8_t len; - + (void)tx_size; + // Supply delays and response size. switch (op_code) { @@ -571,3 +574,5 @@ uint8_t ATSHA204Class::sha204c_check_crc(uint8_t *response) return (crc[0] == response[count] && crc[1] == response[count + 1]) ? SHA204_SUCCESS : SHA204_BAD_CRC; } + +#endif // defined(ARDUINO_ARCH_AVR) \ No newline at end of file diff --git a/libraries/MySensors/utility/ATSHA204.h b/libraries/MySensors/drivers/ATSHA204/ATSHA204.h similarity index 100% rename from libraries/MySensors/utility/ATSHA204.h rename to libraries/MySensors/drivers/ATSHA204/ATSHA204.h diff --git a/libraries/MySensors/utility/sha256.cpp b/libraries/MySensors/drivers/ATSHA204/sha256.cpp similarity index 97% rename from libraries/MySensors/utility/sha256.cpp rename to libraries/MySensors/drivers/ATSHA204/sha256.cpp index f0376ab..511d78a 100644 --- a/libraries/MySensors/utility/sha256.cpp +++ b/libraries/MySensors/drivers/ATSHA204/sha256.cpp @@ -1,6 +1,10 @@ #include -#include -#include +#if defined(__AVR__) + #include + #define PRIPSTR "%S" +#elif defined(ESP8266) +#include +#endif #include "sha256.h" diff --git a/libraries/MySensors/utility/sha256.h b/libraries/MySensors/drivers/ATSHA204/sha256.h similarity index 100% rename from libraries/MySensors/utility/sha256.h rename to libraries/MySensors/drivers/ATSHA204/sha256.h diff --git a/libraries/MySensors/utility/RF24.cpp b/libraries/MySensors/drivers/RF24/RF24.cpp similarity index 93% rename from libraries/MySensors/utility/RF24.cpp rename to libraries/MySensors/drivers/RF24/RF24.cpp index 5f5329d..16bff15 100644 --- a/libraries/MySensors/utility/RF24.cpp +++ b/libraries/MySensors/drivers/RF24/RF24.cpp @@ -41,7 +41,7 @@ void RF24::csn(bool mode) delayMicroseconds(11); // allow csn to settle } } -#else if !defined (__arm__) || defined (CORE_TEENSY) +#elif !defined (__arm__) || defined (CORE_TEENSY) digitalWrite(csn_pin,mode); #endif @@ -422,7 +422,7 @@ void RF24::printDetails(void) print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR); print_byte_register(PSTR("RF_CH"),RF_CH); print_byte_register(PSTR("RF_SETUP"),RF_SETUP); - print_byte_register(PSTR("CONFIG"),CONFIG); + print_byte_register(PSTR("CONFIG"),NRF_CONFIG); print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2); #if defined(__arm__) @@ -498,7 +498,7 @@ void RF24::begin(void) // Reset current status // Notice reset and flush is the last thing we do - write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + write_register(RF24_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); // Set up default configuration. Callers can always change it later. // This channel should be universally safe and not bleed over into adjacent @@ -513,7 +513,7 @@ void RF24::begin(void) // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) // PTX should use only 22uA of power - write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); + write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); } @@ -524,8 +524,8 @@ void RF24::startListening(void) #if !defined (RF24_TINY) powerUp(); #endif - write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX)); - write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PRIM_RX)); + write_register(RF24_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); // Restore the pipe0 adddress, if exists if (pipe0_reading_address[0] > 0){ @@ -546,36 +546,49 @@ void RF24::startListening(void) } /****************************************************************************/ -static const uint8_t child_pipe_enable[] PROGMEM = +static uint8_t get_child_pipe_mask(const uint8_t idx) { - ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5 -}; +#ifdef ESP8266 + static const uint8_t child_pipe_enable[] = + { + _BV(ERX_P0), _BV(ERX_P1), _BV(ERX_P2), _BV(ERX_P3), _BV(ERX_P4), _BV(ERX_P5) + }; + return child_pipe_enable[idx]; +#else + static const uint8_t child_pipe_enable[] PROGMEM = + { + _BV(ERX_P0), _BV(ERX_P1), _BV(ERX_P2), _BV(ERX_P3), _BV(ERX_P4), _BV(ERX_P5) + }; + return pgm_read_byte(&child_pipe_enable[idx]); +#endif +} void RF24::stopListening(void) { - ce(LOW); #if defined(__arm__) delayMicroseconds(300); #endif delayMicroseconds(130); + if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ flush_tx(); } + //flush_rx(); - write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); + write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); #if defined (RF24_TINY) // for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle if (ce_pin == csn_pin) { powerDown(); - powerUp(); + powerUp(); } #endif - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 + + write_register(EN_RXADDR,read_register(EN_RXADDR) | get_child_pipe_mask(0)); // Enable RX on pipe0 delayMicroseconds(100); - } /****************************************************************************/ @@ -583,7 +596,7 @@ void RF24::stopListening(void) void RF24::powerDown(void) { ce(LOW); // Guarantee CE is low on powerDown - write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP)); + write_register(NRF_CONFIG,read_register(NRF_CONFIG) & ~_BV(PWR_UP)); } /****************************************************************************/ @@ -591,11 +604,11 @@ void RF24::powerDown(void) //Power up now. Radio will not power down unless instructed by MCU for config changes etc. void RF24::powerUp(void) { - uint8_t cfg = read_register(CONFIG); + uint8_t cfg = read_register(NRF_CONFIG); // if not powered up then power up and wait for the radio to initialize if (!(cfg & _BV(PWR_UP))){ - write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP)); + write_register(NRF_CONFIG,read_register(NRF_CONFIG) | _BV(PWR_UP)); // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before @@ -636,7 +649,7 @@ bool RF24::write( const void* buf, uint8_t len, const bool multicast ) ce(LOW); - uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + uint8_t status = write_register(RF24_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); //Max retries exceeded if( status & _BV(MAX_RT)){ @@ -686,7 +699,7 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout ) /****************************************************************************/ void RF24::reUseTX(){ - write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag + write_register(RF24_STATUS,_BV(MAX_RT) ); //Clear max retry flag spiTrans( REUSE_TX_PL ); ce(LOW); //Re-Transfer packet ce(HIGH); @@ -709,7 +722,7 @@ bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast ) if( get_status() & _BV(MAX_RT)){ //reUseTX(); //Set re-transmit - write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag + write_register(RF24_STATUS,_BV(MAX_RT) ); //Clear max retry flag return 0; //Return 0. The previous payload has been retransmitted //From the user perspective, if you get a 0, just keep trying to send the same payload } @@ -777,7 +790,7 @@ bool RF24::txStandBy(){ #endif while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ if( get_status() & _BV(MAX_RT)){ - write_register(STATUS,_BV(MAX_RT) ); + write_register(RF24_STATUS,_BV(MAX_RT) ); ce(LOW); flush_tx(); //Non blocking, flush the data return 0; @@ -802,7 +815,7 @@ bool RF24::txStandBy(uint32_t timeout){ while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ if( get_status() & _BV(MAX_RT)){ - write_register(STATUS,_BV(MAX_RT) ); + write_register(RF24_STATUS,_BV(MAX_RT) ); ce(LOW); //Set re-transmit ce(HIGH); if(millis() - start >= timeout){ @@ -826,7 +839,7 @@ bool RF24::txStandBy(uint32_t timeout){ void RF24::maskIRQ(bool tx, bool fail, bool rx){ - write_register(CONFIG, ( read_register(CONFIG) ) | fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR ); + write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) | fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR ); } /****************************************************************************/ @@ -891,7 +904,7 @@ void RF24::read( void* buf, uint8_t len ){ read_payload( buf, len ); //Clear the two possible interrupt flags with one command - write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); + write_register(RF24_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); } @@ -901,7 +914,7 @@ void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready) { // Read the status & reset the status in one easy call // Or is that such a good idea? - uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + uint8_t status = write_register(RF24_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); // Report to the user what happened tx_ok = status & _BV(TX_DS); @@ -972,7 +985,7 @@ void RF24::openReadingPipe(uint8_t child, uint64_t address) // Note it would be more efficient to set all of the bits for all open // pipes at once. However, I thought it would make the calling code // more simple to do it this way. - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + write_register(EN_RXADDR,read_register(EN_RXADDR) | get_child_pipe_mask(child)); } } @@ -1009,7 +1022,7 @@ void RF24::openReadingPipe(uint8_t child, const uint8_t *address) // Note it would be more efficient to set all of the bits for all open // pipes at once. However, I thought it would make the calling code // more simple to do it this way. - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + write_register(EN_RXADDR,read_register(EN_RXADDR) | get_child_pipe_mask(child)); } } @@ -1018,7 +1031,7 @@ void RF24::openReadingPipe(uint8_t child, const uint8_t *address) void RF24::closeReadingPipe( uint8_t pipe ) { - write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe]))); + write_register(EN_RXADDR,read_register(EN_RXADDR) & ~get_child_pipe_mask(pipe)); } /****************************************************************************/ @@ -1268,7 +1281,7 @@ rf24_datarate_e RF24::getDataRate( void ) void RF24::setCRCLength(rf24_crclength_e length) { - uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; + uint8_t config = read_register(NRF_CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; // switch uses RAM (evil!) if ( length == RF24_CRC_DISABLED ) @@ -1284,7 +1297,7 @@ void RF24::setCRCLength(rf24_crclength_e length) config |= _BV(EN_CRC); config |= _BV( CRCO ); } - write_register( CONFIG, config ) ; + write_register( NRF_CONFIG, config ) ; } /****************************************************************************/ @@ -1293,7 +1306,7 @@ rf24_crclength_e RF24::getCRCLength(void) { rf24_crclength_e result = RF24_CRC_DISABLED; - uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; + uint8_t config = read_register(NRF_CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; uint8_t AA = read_register(EN_AA); if ( config & _BV(EN_CRC ) || AA) @@ -1311,8 +1324,8 @@ rf24_crclength_e RF24::getCRCLength(void) void RF24::disableCRC( void ) { - uint8_t disable = read_register(CONFIG) & ~_BV(EN_CRC) ; - write_register( CONFIG, disable ) ; + uint8_t disable = read_register(NRF_CONFIG) & ~_BV(EN_CRC) ; + write_register( NRF_CONFIG, disable ) ; } /****************************************************************************/ diff --git a/libraries/MySensors/utility/RF24.h b/libraries/MySensors/drivers/RF24/RF24.h similarity index 100% rename from libraries/MySensors/utility/RF24.h rename to libraries/MySensors/drivers/RF24/RF24.h diff --git a/libraries/MySensors/utility/RF24_config.h b/libraries/MySensors/drivers/RF24/RF24_config.h similarity index 95% rename from libraries/MySensors/utility/RF24_config.h rename to libraries/MySensors/drivers/RF24/RF24_config.h index 2addc27..d38ac88 100644 --- a/libraries/MySensors/utility/RF24_config.h +++ b/libraries/MySensors/drivers/RF24/RF24_config.h @@ -87,7 +87,7 @@ // Avoid spurious warnings // Arduino DUE is arm and uses traditional PROGMEM constructs #if 1 -#if ! defined( NATIVE ) && defined( ARDUINO ) && ! defined(__arm__) && ! defined( CORE_TEENSY3 ) +#if ! defined( NATIVE ) && defined( ARDUINO ) && ! defined(__arm__) && ! defined( CORE_TEENSY3 ) && ! defined(ESP8266) #undef PROGMEM #define PROGMEM __attribute__(( section(".progmem.data") )) #undef PSTR @@ -97,18 +97,21 @@ // Progmem is Arduino-specific // Arduino DUE is arm and does not include avr/pgmspace -#if defined(ARDUINO) && ! defined(__arm__) +#if defined(__AVR__) #include #define PRIPSTR "%S" #else +#if defined(ESP8266) +#include +#else #if ! defined(ARDUINO) // This doesn't work on Arduino DUE typedef char const char; #else // Fill in pgm_read_byte that is used, but missing from DUE #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #endif +#endif - -#if !defined ( CORE_TEENSY ) +#if !defined ( CORE_TEENSY ) && ! defined(ESP8266) typedef uint16_t prog_uint16_t; #define PSTR(x) (x) #define printf_P printf diff --git a/libraries/MySensors/utility/nRF24L01.h b/libraries/MySensors/drivers/RF24/nRF24L01.h similarity index 98% rename from libraries/MySensors/utility/nRF24L01.h rename to libraries/MySensors/drivers/RF24/nRF24L01.h index 132de94..181dae1 100644 --- a/libraries/MySensors/utility/nRF24L01.h +++ b/libraries/MySensors/drivers/RF24/nRF24L01.h @@ -24,14 +24,14 @@ */ /* Memory Map */ -#define CONFIG 0x00 +#define NRF_CONFIG 0x00 #define EN_AA 0x01 #define EN_RXADDR 0x02 #define SETUP_AW 0x03 #define SETUP_RETR 0x04 #define RF_CH 0x05 #define RF_SETUP 0x06 -#define STATUS 0x07 +#define RF24_STATUS 0x07 #define OBSERVE_TX 0x08 #define CD 0x09 #define RX_ADDR_P0 0x0A diff --git a/libraries/MySensors/utility/RFM69.cpp b/libraries/MySensors/drivers/RFM69/RFM69.cpp similarity index 96% rename from libraries/MySensors/utility/RFM69.cpp rename to libraries/MySensors/drivers/RFM69/RFM69.cpp index 24bb2d3..56e47e5 100644 --- a/libraries/MySensors/utility/RFM69.cpp +++ b/libraries/MySensors/drivers/RFM69/RFM69.cpp @@ -55,9 +55,9 @@ bool RFM69::initialize(byte freqBand, byte nodeID, byte networkID) /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, //default:5khz, (FDEV + BitRate/2 <= 500Khz) /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000}, - /* 0x07 */ { REG_FRFMSB, (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, - /* 0x08 */ { REG_FRFMID, (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, - /* 0x09 */ { REG_FRFLSB, (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, + /* 0x07 */ { REG_FRFMSB, (freqBand==RF69_315MHZ ? (const byte)RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? (const byte)RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? (const byte)RF_FRFMSB_868 : (const byte)RF_FRFMSB_915))) }, + /* 0x08 */ { REG_FRFMID, (freqBand==RF69_315MHZ ? (const byte)RF_FRFMID_315 : (freqBand==RF69_433MHZ ? (const byte)RF_FRFMID_433 : (freqBand==RF69_868MHZ ? (const byte)RF_FRFMID_868 : (const byte)RF_FRFMID_915))) }, + /* 0x09 */ { REG_FRFLSB, (freqBand==RF69_315MHZ ? (const byte)RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? (const byte)RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? (const byte)RF_FRFLSB_868 : (const byte)RF_FRFLSB_915))) }, // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm // +17dBm and +20dBm are possible on RFM69HW @@ -384,8 +384,10 @@ void RFM69::writeReg(byte addr, byte value) void RFM69::select() { noInterrupts(); //save current SPI settings +#ifndef ESP8266 _SPCR = SPCR; _SPSR = SPSR; +#endif //set RFM69 SPI settings SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); @@ -397,8 +399,10 @@ void RFM69::select() { void RFM69::unselect() { digitalWrite(_slaveSelectPin, HIGH); //restore SPI settings to what they were before talking to RFM69 +#ifndef ESP8266 SPCR = _SPCR; SPSR = _SPSR; +#endif interrupts(); } diff --git a/libraries/MySensors/utility/RFM69.h b/libraries/MySensors/drivers/RFM69/RFM69.h similarity index 97% rename from libraries/MySensors/utility/RFM69.h rename to libraries/MySensors/drivers/RFM69/RFM69.h index 452a2ae..11c73e4 100644 --- a/libraries/MySensors/utility/RFM69.h +++ b/libraries/MySensors/drivers/RFM69/RFM69.h @@ -40,17 +40,20 @@ #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) #define RF69_IRQ_PIN 2 #define RF69_IRQ_NUM 0 -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) +#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) #define RF69_IRQ_PIN 2 #define RF69_IRQ_NUM 2 #elif defined(__AVR_ATmega32U4__) #define RF69_IRQ_PIN 3 #define RF69_IRQ_NUM 0 #else + // ESP8266 should fall into this category now + // TODO !! Untested code! Entering unknown territory... #define RF69_IRQ_PIN 2 #define RF69_IRQ_NUM 0 #endif + #define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access #define RF69_MODE_SLEEP 0 // XTAL OFF #define RF69_MODE_STANDBY 1 // XTAL ON diff --git a/libraries/MySensors/utility/RFM69registers.h b/libraries/MySensors/drivers/RFM69/RFM69registers.h similarity index 100% rename from libraries/MySensors/utility/RFM69registers.h rename to libraries/MySensors/drivers/RFM69/RFM69registers.h diff --git a/libraries/MySensors/utility/SPIFlash.cpp b/libraries/MySensors/drivers/SPIFlash/SPIFlash.cpp similarity index 99% rename from libraries/MySensors/utility/SPIFlash.cpp rename to libraries/MySensors/drivers/SPIFlash/SPIFlash.cpp index e250c17..9fa26ad 100644 --- a/libraries/MySensors/utility/SPIFlash.cpp +++ b/libraries/MySensors/drivers/SPIFlash/SPIFlash.cpp @@ -32,7 +32,7 @@ // Please maintain this license information along with authorship // and copyright notices in any redistribution of this code -#include +#include "SPIFlash.h" uint8_t SPIFlash::UNIQUEID[8]; @@ -56,8 +56,10 @@ void SPIFlash::select() { #ifndef SPI_HAS_TRANSACTION noInterrupts(); #endif +#ifndef ESP8266 _SPCR = SPCR; _SPSR = SPSR; +#endif #ifdef SPI_HAS_TRANSACTION SPI.beginTransaction(_settings); @@ -80,15 +82,19 @@ void SPIFlash::unselect() { #else interrupts(); #endif +#ifndef ESP8266 SPCR = _SPCR; SPSR = _SPSR; +#endif } /// setup SPI, read device ID etc... boolean SPIFlash::initialize() { +#ifndef ESP8266 _SPCR = SPCR; _SPSR = SPSR; +#endif pinMode(_slaveSelectPin, OUTPUT); #ifdef SPI_HAS_TRANSACTION _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); @@ -290,4 +296,4 @@ void SPIFlash::wakeup() { /// cleanup void SPIFlash::end() { SPI.end(); -} \ No newline at end of file +} diff --git a/libraries/MySensors/utility/SPIFlash.h b/libraries/MySensors/drivers/SPIFlash/SPIFlash.h similarity index 100% rename from libraries/MySensors/utility/SPIFlash.h rename to libraries/MySensors/drivers/SPIFlash/SPIFlash.h diff --git a/libraries/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino b/libraries/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino index 40c51da..87d0d6e 100644 --- a/libraries/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino +++ b/libraries/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino @@ -30,8 +30,6 @@ #include #include -#define DEBUG 1 // Debug enables Serial.print 1 = Yes 0 = No - int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point MySensor gw; @@ -41,7 +39,11 @@ int oldBatteryPcnt = 0; void setup() { // use the 1.1 V internal reference +#if defined(__AVR_ATmega2560__) + analogReference(INTERNAL1V1); +#else analogReference(INTERNAL); +#endif gw.begin(); // Send the sketch version information to the gateway and Controller @@ -52,7 +54,7 @@ void loop() { // get the battery Voltage int sensorValue = analogRead(BATTERY_SENSE_PIN); - #if DEBUG > 0 + #ifdef DEBUG Serial.println(sensorValue); #endif @@ -63,7 +65,7 @@ void loop() float batteryV = sensorValue * 0.003363075; int batteryPcnt = sensorValue / 10; - #if DEBUG > 0 + #ifdef DEBUG Serial.print("Battery Voltage: "); Serial.print(batteryV); Serial.println(" V"); diff --git a/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino b/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino index 34e0a17..bd3a81f 100644 --- a/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino +++ b/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino @@ -75,7 +75,7 @@ void setup() digitalWrite(SECONDARY_BUTTON_PIN, HIGH); // Send the sketch version information to the gateway and Controller - sensor_node.sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER); + sensor_node.sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER); // Register binary input sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. diff --git a/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino b/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino new file mode 100644 index 0000000..a9cbca7 --- /dev/null +++ b/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino @@ -0,0 +1,100 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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 + * + * MH-Z14 CO2 sensor + * + * Wiring: + * Pad 1, Pad 5: Vin (Voltage input 4.5V-6V) + * Pad 2, Pad 3, Pad 12: GND + * Pad 6: PWM output ==> pin 6 + * + * From: http://davidegironi.blogspot.fr/2014/01/co2-meter-using-ndir-infrared-mh-z14.html + * MH-Z14 has a PWM output, with a sensitivity range of 0ppm to 2000ppm CO2, an accurancy of ±200ppm. + * The cycle is 1004ms±5%, given the duty cicle Th (pulse high), Tl is 1004-Th, we can convert it to CO2 value using the formula: + * CO2ppm = 2000 * (Th - 2ms) /(Th + Tl - 4ms) + * From: http://airqualityegg.wikispaces.com/Sensor+Tests + * - response time is less than 30 s + * - 3 minute warm up time + * datasheet: http://www.futurlec.com/Datasheet/Sensor/MH-Z14.pdf +* Contributor: epierre +**/ + + +#include +#include + +#define CHILD_ID_AIQ 0 +#define AIQ_SENSOR_ANALOG_PIN 6 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) + +float valAIQ =0.0; +float lastAIQ =0.0; + +MySensor gw; +MyMessage msg(CHILD_ID_AIQ, V_LEVEL); +MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX); + +void setup() +{ + gw.begin(); + + // Send the sketch version information to the gateway and Controller + gw.sendSketchInfo("AIQ Sensor CO2 MH-Z14", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + gw.present(CHILD_ID_AIQ, S_AIR_QUALITY); + gw.send(msg2.set("ppm")); + + gw.sleep(SLEEP_TIME); + + pinMode(AIQ_SENSOR_ANALOG_PIN, INPUT); + +} + +void loop() { + + //unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + while(digitalRead(AIQ_SENSOR_ANALOG_PIN) == HIGH) {;} + //wait for the pin to go HIGH and measure HIGH time + unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + + //Serial.print(duration/1000); Serial.println(" ms "); + //from datasheet + //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms) + // given Tl + Th = 1004 + // Tl = 1004 - Th + // = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms) + // = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms) + long co2ppm = 2 * ((duration/1000) - 2); + //Serial.print(co2ppm); + if ((co2ppm != lastAIQ)&&(abs(co2ppm-lastAIQ)>=10)) { + gw.send(msg.set((long)ceil(co2ppm))); + lastAIQ = ceil(co2ppm); + } + + //Serial.println(); + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + gw.sleep(SLEEP_TIME); //sleep for: sleepTime +} diff --git a/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino b/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino index 81fe076..2386526 100644 --- a/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino +++ b/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino @@ -133,7 +133,7 @@ void incomingMessage(const MyMessage &message) newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE); } // Send dimmer level back to controller with ack enabled - gw.send(dimmerMsg.set(0), true); + gw.send(dimmerMsg.set(newLevel), true); // We do not change any levels here until ack comes back from gateway return; } else if (message.type == V_DIMMER) { diff --git a/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino b/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino index a21e86a..59f15a8 100644 --- a/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino +++ b/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino @@ -51,7 +51,7 @@ void setup() // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID, S_DISTANCE); - boolean metric = gw.getConfig().isMetric; + metric = gw.getConfig().isMetric; } void loop() diff --git a/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino b/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino new file mode 100644 index 0000000..ca88a73 --- /dev/null +++ b/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino @@ -0,0 +1,144 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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 + * + * Dust Sensor for SamYoung DSM501 + * connect the sensor as follows : + * Pin 2 of dust sensor PM1 -> Digital 3 (PMW) + * Pin 3 of dust sensor -> +5V + * Pin 4 of dust sensor PM2.5 -> Digital 6 (PWM) + * Pin 5 of dust sensor -> Ground + * Datasheet: http://www.samyoungsnc.com/products/3-1%20Specification%20DSM501.pdf +* Contributor: epierre +**/ + + +#include +#include + +#define CHILD_ID_DUST_PM10 0 +#define CHILD_ID_DUST_PM25 1 +#define DUST_SENSOR_DIGITAL_PIN_PM10 6 +#define DUST_SENSOR_DIGITAL_PIN_PM25 3 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) +//VARIABLES +int val = 0; // variable to store the value coming from the sensor +float valDUSTPM25 =0.0; +float lastDUSTPM25 =0.0; +float valDUSTPM10 =0.0; +float lastDUSTPM10 =0.0; +unsigned long duration; +unsigned long starttime; +unsigned long endtime; +unsigned long sampletime_ms = 30000; +unsigned long lowpulseoccupancy = 0; +float ratio = 0; +long concentrationPM25 = 0; +long concentrationPM10 = 0; + +MySensor gw; +MyMessage dustMsgPM10(CHILD_ID_DUST_PM10, V_LEVEL); +MyMessage msgPM10(CHILD_ID_DUST_PM10, V_UNIT_PREFIX); +MyMessage dustMsgPM25(CHILD_ID_DUST_PM25, V_LEVEL); +MyMessage msgPM25(CHILD_ID_DUST_PM25, V_UNIT_PREFIX); + +void setup() +{ + gw.begin(); + + // Send the sketch version information to the gateway and Controller + gw.sendSketchInfo("Dust Sensor DSM501", "1.4"); + + // Register all sensors to gateway (they will be created as child devices) + gw.present(CHILD_ID_DUST_PM10, S_DUST); + gw.send(msgPM10.set("ppm")); + gw.present(CHILD_ID_DUST_PM25, S_DUST); + gw.send(msgPM25.set("ppm")); + + pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); + pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); + +} + +void loop() +{ + + //get PM 2.5 density of particles over 2.5 μm. + concentrationPM25=(long)getPM(DUST_SENSOR_DIGITAL_PIN_PM25); + Serial.print("PM25: "); + Serial.println(concentrationPM25); + Serial.print("\n"); + + if ((concentrationPM25 != lastDUSTPM25)&&(concentrationPM25>0)) { + gw.send(dustMsgPM25.set((long)ceil(concentrationPM25))); + lastDUSTPM25 = ceil(concentrationPM25); + } + //get PM 1.0 - density of particles over 1 μm. + concentrationPM10=getPM(DUST_SENSOR_DIGITAL_PIN_PM10); + Serial.print("PM10: "); + Serial.println(concentrationPM10); + Serial.print("\n"); + //ppmv=mg/m3 * (0.08205*Tmp)/Molecular_mass + //0.08205 = Universal gas constant in atm·m3/(kmol·K) + int temp=20; //external temperature, if you can replace this with a DHT11 or better + long ppmv=(concentrationPM10*0.0283168/100/1000) * (0.08205*temp)/0.01; + + if ((ceil(concentrationPM10) != lastDUSTPM10)&&((long)concentrationPM10>0)) { + gw.send(dustMsgPM10.set((long)ppmv)); + lastDUSTPM10 = ceil(concentrationPM10); + } + + //sleep to save on radio + gw.sleep(SLEEP_TIME); + +} + + +long getPM(int DUST_SENSOR_DIGITAL_PIN) { + + starttime = millis(); + + while (1) { + + duration = pulseIn(DUST_SENSOR_DIGITAL_PIN, LOW); + lowpulseoccupancy += duration; + endtime = millis(); + + if ((endtime-starttime) > sampletime_ms) + { + ratio = (lowpulseoccupancy-endtime+starttime)/(sampletime_ms*10.0); // Integer percentage 0=>100 + long concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve + //Serial.print("lowpulseoccupancy:"); + //Serial.print(lowpulseoccupancy); + //Serial.print("\n"); + //Serial.print("ratio:"); + //Serial.print(ratio); + //Serial.print("\n"); + //Serial.print("DSM501A:"); + //Serial.println(concentration); + //Serial.print("\n"); + + lowpulseoccupancy = 0; + return(concentration); + } + } +} diff --git a/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino new file mode 100644 index 0000000..ee828b5 --- /dev/null +++ b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino @@ -0,0 +1,265 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * Contribution by a-lurker and Anticimex, + * Contribution by Norbert Truchsess + * Contribution by Ivo Pullens (ESP8266 support) + * + * DESCRIPTION + * The EthernetGateway sends data received from sensors to the WiFi link. + * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. + * + * VERA CONFIGURATION: + * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. + * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003 + * + * LED purposes: + * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h + * - 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 + * + * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. + * The ESP8266 however requires different wiring: + * nRF24L01+ ESP8266 + * VCC VCC + * CE GPIO4 + * CSN/CS GPIO15 + * SCK GPIO14 + * MISO GPIO12 + * MOSI GPIO13 + * + * Not all ESP8266 modules have all pins available on their external interface. + * This code has been tested on an ESP-12 module. + * The ESP8266 requires a certain pin configuration to download code, and another one to run code: + * - Connect REST (reset) via 10K pullup resistor to VCC, and via switch to GND ('reset switch') + * - Connect GPIO15 via 10K pulldown resistor to GND + * - Connect CH_PD via 10K resistor to VCC + * - Connect GPIO2 via 10K resistor to VCC + * - Connect GPIO0 via 10K resistor to VCC, and via switch to GND ('bootload switch') + * + * Inclusion mode button: + * - Connect GPIO5 via switch to GND ('inclusion switch') + * + * Hardware SHA204 signing is currently not supported! + * + * Make sure to fill in your ssid and WiFi password below for ssid & pass. + */ +#define NO_PORTB_PINCHANGES + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "GatewayUtil.h" + +const char *ssid = "MySSID"; // cannot be longer than 32 characters! +const char *pass = "MyVerySecretPassword"; // + +#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_PIN 5 // Digital pin used for inclusion mode button + +#define RADIO_CE_PIN 4 // radio chip enable +#define RADIO_SPI_SS_PIN 15 // radio SPI serial select + +#ifdef WITH_LEDS_BLINKING +#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 +#endif + + +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); +//MyTransportRFM69 transport; + + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +#ifdef MY_SIGNING_FEATURE +MySigningNone signer; +//MySigningAtsha204Soft signer; +#endif + +// Hardware profile +MyHwESP8266 hw; + +// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h +MySensor gw(transport, hw +#ifdef MY_SIGNING_FEATURE + , signer +#endif +#ifdef WITH_LEDS_BLINKING + , RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN +#endif + ); + + +#define IP_PORT 5003 // The port you want to open +#define MAX_SRV_CLIENTS 5 // how many clients should be able to telnet to this ESP8266 + +// a R/W server on the port +static WiFiServer server(IP_PORT); +static WiFiClient clients[MAX_SRV_CLIENTS]; +static bool clientsConnected[MAX_SRV_CLIENTS]; +static inputBuffer inputString[MAX_SRV_CLIENTS]; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + + +void output(const char *fmt, ... ) +{ + char serialBuffer[MAX_SEND_LENGTH]; + va_list args; + va_start (args, fmt ); + vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args); + va_end (args); + Serial.print(serialBuffer); + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + if (clients[i] && clients[i].connected()) + { +// Serial.print("Client "); Serial.print(i); Serial.println(" write"); + clients[i].write((uint8_t*)serialBuffer, strlen(serialBuffer)); + } + } +} + +void setup() +{ + // Setup console + hw_init(); + + Serial.println(); Serial.println(); + Serial.println("ESP8266 MySensors Gateway"); + Serial.print("Connecting to "); Serial.println(ssid); + + (void)WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println("Connected!"); + Serial.print("IP: "); Serial.println(WiFi.localIP()); + Serial.flush(); + + setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output); + + // Initialize gateway at maximum PA level, channel 70 and callback for write operations + gw.begin(incomingMessage, 0, true, 0); + + // start listening for clients + server.begin(); + server.setNoDelay(true); +} + + +void loop() { + gw.process(); + + checkButtonTriggeredInclusion(); + checkInclusionFinished(); + + // Go over list of clients and stop any that are no longer connected. + // If the server has a new client connection it will be assigned to a free slot. + bool allSlotsOccupied = true; + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + if (!clients[i].connected()) + { + if (clientsConnected[i]) + { + Serial.print("Client "); Serial.print(i); Serial.println(" disconnected"); + clients[i].stop(); + } + //check if there are any new clients + if (server.hasClient()) + { + clients[i] = server.available(); + inputString[i].idx = 0; + Serial.print("Client "); Serial.print(i); Serial.println(" connected"); + output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY); + } + } + bool connected = clients[i].connected(); + clientsConnected[i] = connected; + allSlotsOccupied &= connected; + } + if (allSlotsOccupied && server.hasClient()) + { + //no free/disconnected spot so reject + Serial.println("No free slot available"); + WiFiClient c = server.available(); + c.stop(); + } + + // Loop over clients connect and read available data + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + while(clients[i].connected() && clients[i].available()) + { + char inChar = clients[i].read(); + if ( inputString[i].idx < MAX_RECEIVE_LENGTH - 1 ) + { + // if newline then command is complete + if (inChar == '\n') + { + // a command was issued by the client + // we will now try to send it to the actuator + inputString[i].string[inputString[i].idx] = 0; + + // echo the string to the serial port + Serial.print("Client "); Serial.print(i); Serial.print(": "); Serial.println(inputString[i].string); + + parseAndSend(gw, inputString[i].string); + + // clear the string: + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; + } else { + // add it to the inputString: + inputString[i].string[inputString[i].idx++] = inChar; + } + } else { + // Incoming message too long. Throw away + Serial.print("Client "); Serial.print(i); Serial.println(": Message too long"); + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; + } + } + } +} + + + diff --git a/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h b/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h new file mode 100644 index 0000000..fa814b3 --- /dev/null +++ b/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h @@ -0,0 +1,136 @@ +#ifndef __GATEWAYUTIL_H__ +#define __GATEWAYUTIL_H__ + +#ifdef ARDUINO + +static uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled +static uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode + +#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller +#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller + + +typedef struct +{ + char string[MAX_RECEIVE_LENGTH]; + uint8_t idx; +} inputBuffer; + +static volatile boolean buttonTriggeredInclusion; +static boolean inclusionMode; // Keeps track on inclusion mode +bool inclusionButtonSupported = false; +void (*serial)(const char *fmt, ... ); + +MyParserSerial parser; + +void setInclusionMode(boolean newMode); + +char convBuf[MAX_PAYLOAD*2+1]; +unsigned long inclusionStartTime; + + +void startInclusionInterrupt() { + buttonTriggeredInclusion = true; +} + +void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) { + inclusionMode = 0; + buttonTriggeredInclusion = false; + serial = _serial; + + inclusionTime = _incTime; + inclusionButtonSupported = (_inc != 255); + if (inclusionButtonSupported) + { + pinInclusion = _inc; + + // Setup digital in that triggers inclusion mode + pinMode(pinInclusion, INPUT_PULLUP); + + // Add interrupt for inclusion button to pin + attachInterrupt(pinInclusion, startInclusionInterrupt, FALLING); + } +} + +void incomingMessage(const MyMessage &message) { +// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { +// gw.rxBlink(3); +// } else { +// gw.rxBlink(1); +// } + // Pass along the message from sensors to serial line + serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf)); +} + + + +void checkButtonTriggeredInclusion() { + if (inclusionButtonSupported) + { + if (buttonTriggeredInclusion) { + // Ok, someone pressed the inclusion button on the gateway + // start inclusion mode for 1 munute. + #ifdef DEBUG + serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE); + #endif + buttonTriggeredInclusion = false; + setInclusionMode(true); + } + } +} + +void checkInclusionFinished() { + if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) { + // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode + setInclusionMode(false); + } +} + +void parseAndSend(MySensor &gw, char *commandBuffer) { + boolean ok; + MyMessage &msg = gw.getLastMessage(); + + if (parser.parse(msg, commandBuffer)) { + uint8_t command = mGetCommand(msg); + + if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { + // Handle messages directed to gateway + if (msg.type == I_VERSION) { + // Request for version + serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(msg.data) == 1); + } + } else { + #ifdef WITH_LEDS_BLINKING + gw.txBlink(1); + #endif + ok = gw.sendRoute(msg); + if (!ok) { + #ifdef WITH_LEDS_BLINKING + gw.errBlink(1); + #endif + } + } + } +} + +void setInclusionMode(boolean newMode) { + if (newMode != inclusionMode) { + inclusionMode = newMode; + // Send back mode change on serial line to ack command + serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0); + + if (inclusionMode) { + inclusionStartTime = millis(); + } + } +} + + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 823a8c0..7b6adaa 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -59,32 +59,38 @@ #include // This include can be removed when using UIPEthernet module #include -#include -#include -#include -#include -#include -#include +//#include +//#include +//#include +//#include +//#include +//#include -#include -#include -#include -// needed due to Arduino IDE -#include +#define MY_WITH_LEDS_BLINKING +#define MY_INCLUSION_MODE_FEATURE +#define MY_INCLUSION_BUTTON_FEATURE -#define INCLUSION_MODE_TIME 60 // Number of minutes inclusion mode is enabled -#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button + +#define MY_DEFAULT_LED_BLINK_PERIOD 300 + +#define MY_INCLUSION_MODE_DURATION 60 // Number of minutes inclusion mode is enabled +#define MY_INCLUSION_MODE_BUTTON_PIN 3 // Digital pin used for inclusion mode button + +#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin +#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED #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 +#include +#include +#include -#define IP_PORT 5003 // The port you want to open -#ifndef IP_ADDRESS_DHCP + +#define MY_IP_PORT 5003 // The port you want to open +#ifndef MY_IP_ADDRESS_DHCP // Gateway IP address if not using DHCP IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later! #endif /* IP_ADDRESS_DHCP */ @@ -122,22 +128,11 @@ MyGatewayTransportEthernet ctrlTransport(protocol, mac, myIp, /* gw port */ CONT // Construct MyGateway library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) // To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h -#ifdef MY_WITH_LEDS_BLINKING -MyGateway gw(ctrlTransport, transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); -#else MyGateway gw(ctrlTransport, transport, hw /*, signer*/); -#endif void setup() { - gw.begin(NULL -#ifdef MY_INCLUSION_MODE_FEATURE - , INCLUSION_MODE_TIME -#ifdef MY_INCLUSION_BUTTON_FEATURE - , INCLUSION_MODE_PIN -#endif -#endif - ); + gw.begin(NULL); } void loop() { diff --git a/libraries/MySensors/examples/IrrigationController/IrrigationController.ino b/libraries/MySensors/examples/IrrigationController/IrrigationController.ino index 41e6eb9..abd26e0 100644 --- a/libraries/MySensors/examples/IrrigationController/IrrigationController.ino +++ b/libraries/MySensors/examples/IrrigationController/IrrigationController.ino @@ -191,7 +191,7 @@ void setup() //check for saved date in EEPROM DEBUG_PRINTLN(F("Checking EEPROM for stored date:")); delay(500); - if (gw.loadState(0) == 0xFF); // EEPROM flag + if (gw.loadState(0) == 0xFF) // EEPROM flag { DEBUG_PRINTLN(F("Retreiving last run time from EEPROM...")); for (int i = 0; i < 4 ; i++) @@ -439,7 +439,7 @@ void loop() state = STAND_BY_ALL_OFF; } } - else if (state = ZONE_SELECT_MENU) + else if (state == ZONE_SELECT_MENU) { displayMenu(); } @@ -771,6 +771,9 @@ void updateDisplay() lcd.print(totalTimeRan); lcd.print(" Minutes "); } + default: + // what of ZONE_SELECT_MENU? + break; } lastUpdateTime = millis(); } diff --git a/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino index 8d23a59..3190440 100644 --- a/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino +++ b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino @@ -1,81 +1,9 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * 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. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - idefix - * - * DESCRIPTION - * Arduino BH1750FVI Light sensor - * communicate using I2C Protocol - * this library enable 2 slave device addresses - * Main address 0x23 - * secondary address 0x5C - * connect the sensor as follows : - * - * VCC >>> 5V - * Gnd >>> Gnd - * ADDR >>> NC or GND - * SCL >>> A5 - * SDA >>> A4 - * http://www.mysensors.org/build/light - */ - +#include #include -#include -#include -#include -#define CHILD_ID_LIGHT 0 -unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) +MyTransportNRF24 transport; +MyHwATMega328 hw; +MySensor gw(transport, hw); -BH1750 lightSensor; -MySensor gw; - -// V_LIGHT_LEVEL should only be used for uncalibrated light level 0-100%. -// If your controller supports the new V_LEVEL variable, use this instead for -// transmitting LUX light level. -MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); -// MyMessage msg(CHILD_ID_LIGHT, V_LEVEL); -uint16_t lastlux; - -void setup() -{ - gw.begin(); - - // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Light Lux Sensor", "1.0"); - - // Register all sensors to gateway (they will be created as child devices) - gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); - - lightSensor.begin(); -} - -void loop() -{ - uint16_t lux = lightSensor.readLightLevel();// Get Lux value - Serial.println(lux); - if (lux != lastlux) { - gw.send(msg.set(lux)); - lastlux = lux; - } - - gw.sleep(SLEEP_TIME); -} +void setup() {} +void loop() {} diff --git a/libraries/MySensors/examples/LightningSensor/LightningSensor.ino b/libraries/MySensors/examples/LightningSensor/LightningSensor.ino index 8d2bace..63b1a53 100644 --- a/libraries/MySensors/examples/LightningSensor/LightningSensor.ino +++ b/libraries/MySensors/examples/LightningSensor/LightningSensor.ino @@ -42,7 +42,6 @@ void setup() // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID_DISTANCE, S_DISTANCE); gw.present(CHILD_ID_INTENSITY, S_CUSTOM); - boolean metric = gw.getConfig().isMetric; Serial.begin(115200); Serial.println("Playing With Fusion: AS3935 Lightning Sensor, SEN-39001"); @@ -118,4 +117,4 @@ void loop() void AS3935_ISR() { AS3935_ISR_Trig = 1; -} \ No newline at end of file +} diff --git a/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino b/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino new file mode 100644 index 0000000..9c5b60b --- /dev/null +++ b/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino @@ -0,0 +1,614 @@ +/* MyMQTT Client Gateway 0.1b + Created by Norbert Truchsess + Based on MyMQTT-broker gateway created by Daniel Wiegert + Based on MySensors Ethernet Gateway by Henrik Ekblad + http://www.mysensors.org + + Changes by Thomas Krebs + - Add signing support from MySensors 1.5 and update for MySensors 1.5; + - Restructured code back to a C like implementation following the existing MQTTGateway + Requires MySensors lib 1.5 + + * 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 + * 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 + 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. + 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]/V_[SensorType][/set | /get] + NodeID and SensorID is uint8 (0-255) number. + Segment after SensorID 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) + + The last seqment is a command to to be send down to the sensor. The gateway is subscribed to topics which have + a command present! This is to avoid that a publish by the gateway will end up in the gateway via it subsription. + You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version) + + So far tested in openhab and MyMQTT for Android (Not my creation) + - http://www.openhab.org/ + * How to set-up Openhab and MQTTGateway: + http://forum.mysensors.org/topic/303/mqtt-broker-gateway + + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MyMQTTClient.h" + +#ifdef MY_SIGNING_FEATURE +#include +#include +#include +#endif + +//#define DSRTC +#ifdef DSRTC +#include +#include // a basic DS1307 library that returns time as a time_t +#endif + +/* + * To configure MQTTClientGateway.ino to use an ENC28J60 based board include + * 'UIPEthernet.h' (SPI.h required for MySensors anyway). The UIPEthernet-library can be downloaded + * from: https://github.com/ntruchsess/arduino_uip + */ + +//#include +/* + * To execute MQTTClientGateway.ino on Yun uncomment Bridge.h and YunClient.h. + * Do not include Ethernet.h or SPI.h in this case. + * On Yun there's no need to configure local_ip and mac in the sketch + * as this is configured on the linux-side of Yun. + */ + +//#include +//#include +// * 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*/ + +// CE_PIN and SPI_SS_PIN for Mega +#define RADIO_CE_PIN 48 // radio chip enable +#define RADIO_SPI_SS_PIN 49 // 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*/ + +//replace with ip of server you want to connect to, comment out if using 'remote_host' +uint8_t remote_ip[] = { 192, 168, 178, 74 }; // Mosquitto broker + +//replace with hostname of server you want to connect to, comment out if using 'remote_ip' +//char* remote_ip = "server.local"; +//replace with the port that your server is listening on +#define remote_port 1883 +//replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun +uint8_t local_ip[] = {192, 168, 178, 11}; +//replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun +uint8_t mac[] = { 0xA2, 0xAE, 0xAD, 0xA0, 0xA0, 0xA2 }; + +#if defined remote_ip && defined remote_host +#error "cannot define both remote_ip and remote_host at the same time!" +#endif + +#ifdef _YUN_CLIENT_H_ +YunClient ethClient; +#else +EthernetClient ethClient; +#endif + +//////////////////////////////////////////////////////////////// +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); +//MyTransportRFM69 transport; + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +//MySigningNone signer; +//MySigningAtsha204Soft signer(true); +//MySigningAtsha204 signer; + +// Hardware profile +MyHwATMega328 hw; + +MyMessage msg; +char convBuf[MAX_PAYLOAD * 2 + 1]; +uint8_t buffsize; +char buffer[MQTT_MAX_PACKET_SIZE]; +char user[sizeof(MQTT_USER)]; // introduced the bufs to get rid of compiler warnings +char pwd[sizeof(MQTT_PWD)]; // see above +char connID[sizeof(MQTT_CONN_ID)]; // see above +char mqttTopicMask[sizeof(MQTT_TOPIC_MASK)]; // see above + +//////////////////////////////////////////////////////////////// + +volatile uint8_t countRx; +volatile uint8_t countTx; +volatile uint8_t countErr; + + +//////////////////////////////////////////////////////////////// + +void processMQTTMessages(char* topic, byte* payload, unsigned int length); +PubSubClient client(remote_ip, remote_port, processMQTTMessages, ethClient); + +//////////////////////////////////////////////////////////////// + + +// Declare and initialize MySensor instance +// Construct MyMQTTClient (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h, if signing +// feature not to be used, uncomment) +// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h +MySensor gw(transport, hw +#ifdef MY_SIGNING_FEATURE + , signer +#endif +#ifdef WITH_LEDS_BLINKING + , RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN +#endif + ); + +/* + * setup + */ +void setup() +{ + strcpy(connID,MQTT_CONN_ID); + strcpy(mqttTopicMask,MQTT_TOPIC_MASK); + + countRx = 0; + countTx = 0; + countErr = 0; + + Ethernet.begin(mac, local_ip); + //Bridge.begin(); + delay(1000); // Wait for Ethernet to get configured. + + begin(); +} + +/* + * loop + */ +void loop() +{ + if (!client.connected()) + { + boolean ret; +#ifdef MQTT_AUTH_REQUIRED + strcpy(user, MQTT_USER); + strcpy(pwd, MQTT_PWD); + ret = client.connect(connID, user,pwd); +#else + ret = client.connect(connID); +#endif + if (ret) { + Serial.println("Connected to MQTT broker"); + } else { + Serial.println("Connection to MQTT broker failed"); + } + client.subscribe(mqttTopicMask); + } + client.loop(); + gw.process(); +} + +/* + * processRadioMessage + * + * Receives radio message, parses it and forwards it to the MQTT broker + */ +void processRadioMessage(const MyMessage &message) +{ + rxBlink(1); + sendMQTT(message); +} + +/* + * sendMQTT + * Handles processing of radio messages and eventually publishes it to the MQTT broker + */ +void sendMQTT(const MyMessage &inMsg) +{ + MyMessage msg = inMsg; + buffsize = 0; + if (!client.connected()) + return; //We have no connections - return + if (msg.isAck()) + { +#ifdef DEBUG + Serial.println("msg is ack!"); +#endif + 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. + // The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. + } + } + 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. + uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS) + 1; + if (newNodeID <= MQTT_FIRST_SENSORID) + newNodeID = MQTT_FIRST_SENSORID; + if (msg.sender == newNodeID) + { + gw.saveState(EEPROM_LATEST_NODE_ADDRESS, newNodeID); + } + if (mGetCommand(msg) == C_INTERNAL) + { + if (msg.type == I_CONFIG) + { + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_CONFIG, 0).set("M"))) + errBlink(1); + } + else if (msg.type == I_TIME) + { +#ifdef DEBUG + Serial.println("I_TIME requested!"); +#endif + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_TIME, 0).set(now()))) + errBlink(1); + } + else if (msg.type == I_ID_REQUEST && msg.sender == 255) + { + uint8_t newNodeID = gw.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 :( + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_ID_RESPONSE, 0).set(newNodeID))) + errBlink(1); + } + else if (msg.type == I_BATTERY_LEVEL) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/BATTERY_LEVEL", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + else if (msg.type == I_SKETCH_NAME) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_NAME", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + else if (msg.type == I_SKETCH_VERSION) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_VERSION", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + + } + else if (mGetCommand(msg) != 0) + { + if (mGetCommand(msg) == 3) + msg.type = msg.type + (S_FIRSTCUSTOM - 10); //Special message + + if (msg.type > VAR_TOTAL) + msg.type = VAR_TOTAL; // If type > defined types set to unknown. + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/%i/V_%s", msg.sender, + msg.sensor, getType(convBuf, &VAR_Type[msg.type])); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + } +} + +/* + * build + * Constructs a radio message + */ +inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, + uint8_t command, uint8_t type, bool enableAck) +{ + msg.destination = destination; + msg.sender = sender; + msg.sensor = sensor; + msg.type = type; + mSetCommand(msg, command); + mSetRequestAck(msg, enableAck); + mSetAck(msg, false); + return msg; +} + +/* + * getType + */ +char *getType(char *b, const char **index) +{ + char *q = b; + char *p = (char *) pgm_read_word(index); + while (*q++ = pgm_read_byte(p++)) + ; + *q = 0; + return b; +} + +/* + * begin + * wraps MySensors begin method; setup of RTC and led timers interrupt + */ +void begin() +{ +#ifdef DEBUG + Serial.begin(BAUD_RATE); +#endif +#ifdef DSRTC + // Attach RTC + setSyncProvider(RTC.get); // the function to get the time from the RTC + setSyncInterval(60); +#endif + + gw.begin(processRadioMessage, 0, true, 0); + + MsTimer2::set(200, ledTimersInterrupt); + MsTimer2::start(); + +#ifdef DEBUG + Serial.print(getType(convBuf, &VAR_Type[S_FIRSTCUSTOM])); +#endif +} + +/* + * processMQTTMessages + * message handler for the PubSubClient + */ +void processMQTTMessages(char* topic, byte* payload, unsigned int length) +{ + processMQTTMessage(topic, payload, length); +} + +/* + * processMQTTMessage + * processes MQTT messages, parses the topic, extracts radio address out of topic and sends them + * to the respective radio + */ +void processMQTTMessage(char* topic, byte* payload, + unsigned int length) +{ + char *str, *p; + uint8_t i = 0; + buffer[0] = 0; + buffsize = 0; + int8_t cmd = -1; + + for (str = strtok_r(topic, "/", &p); str && i < 5; + str = strtok_r(NULL, "/", &p)) + { + switch (i) + { + case 0: + { + if (strcmp_P(str, mqtt_prefix) != 0) + { //look for MQTT_PREFIX + return; //Message not for us or malformatted! + } + break; + } + case 1: + { + msg.destination = atoi(str); //NodeID + break; + } + case 2: + { + msg.sensor = atoi(str); //SensorID + break; + } + case 3: + { + char match = 0; //SensorType + //strcpy(str,(char*)&str[2]); //Strip VAR_ + + for (uint8_t j = 0; + strcpy_P(convBuf, (char*) pgm_read_word(&(VAR_Type[j]))); j++) + { + if (strcmp((char*) &str[2], convBuf) == 0) + { //Strip VAR_ and compare + match = j; + break; + } + if (j >= VAR_TOTAL) + { // No match found! + match = VAR_TOTAL; // last item. + break; + } + } + msg.type = match; + break; + } + case 4: + { + // support the command get and set; get will be mapped to a C_REQ and set to C_SET + if (strcmp(str,MQTT_CMD_SET) == 0) + { + cmd = C_SET; + } + else if (strcmp(str,MQTT_CMD_GET) == 0) { + cmd = C_REQ; + } + else { +#ifdef DEBUG + Serial.print("Received unsupported command - ignore: "); + Serial.println(str); +#endif + } + } + } + i++; + } //Check if packge has payload + + if (cmd != -1) { + char* ca; + ca = (char *)payload; + ca += length; + *ca = '\0'; + + msg.set((const char*)payload); //Payload + + txBlink(1); + // inject time + if ((msg.destination == 0) && (msg.sensor == 199)) { + unsigned long epoch = atol((char*)payload); + if (epoch > 10000) { +#ifdef DSRTC + RTC.set(epoch); // this sets the RTC to the time from controller - which we do want periodically +#endif + setTime(epoch); + } +#ifdef DEBUG + Serial.print("Time received "); + Serial.println(epoch); +#endif + } + // + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.destination, msg.sensor, C_SET, msg.type, + 0))) + errBlink(1); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Led handling +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * ledTimersIntterupt + */ +void ledTimersInterrupt() { + if (countRx && countRx != 255) { + // switch led on + digitalWrite(RADIO_RX_LED_PIN, LOW); + } else if (!countRx) { + // switching off + digitalWrite(RADIO_RX_LED_PIN, HIGH); + } + if (countRx != 255) { + countRx--; + } + + if (countTx && countTx != 255) { + // switch led on + digitalWrite(RADIO_TX_LED_PIN, LOW); + } else if (!countTx) { + // switching off + digitalWrite(RADIO_TX_LED_PIN, HIGH); + } + if (countTx != 255) { + countTx--; + } + + if (countErr && countErr != 255) { + // switch led on + digitalWrite(RADIO_ERROR_LED_PIN, LOW); + } else if (!countErr) { + // switching off + digitalWrite(RADIO_ERROR_LED_PIN, HIGH); + } + if (countErr != 255) { + countErr--; + } +} + + +void rxBlink(uint8_t cnt) +{ + if (countRx == 255) + { + countRx = cnt; + } +} + +void txBlink(uint8_t cnt) +{ + if (countTx == 255) + { + countTx = cnt; + } +} + +void errBlink(uint8_t cnt) +{ + if (countErr == 255) + { + countErr = cnt; + } +} + + diff --git a/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h b/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h new file mode 100644 index 0000000..d347825 --- /dev/null +++ b/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h @@ -0,0 +1,129 @@ +/* +The MySensors library adds a new layer on top of the RF24 library. +It handles radio network routing, relaying and ids. +Created by Henrik Ekblad +Modified by Daniel Wiegert +Modified by Norbert Truchsess +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. +*/ + + +#ifndef MyMQTTClient_h +#define MyMQTTClient_h + +////////////////////////////////////////////////////////////////// + +#ifdef DEBUG +#define TCPDUMP // Dump TCP packages. +#endif +#define MQTT_FIRST_SENSORID 20 // If you want manually configured nodes below this value. 255 = Disable +#define MQTT_LAST_SENSORID 254 // 254 is max! 255 reserved. +#define MQTT_PREFIX "MyMQTT" // First prefix in MQTT tree, keep short! +#define MQTT_TOPIC_MASK "MyMQTT/+/+/+/+" // Topic mask the client will subscribe to. This ensures that it will not receive any sensor data send by sensors + // the following topic structure is assumed: MyMQTT//// +#define MQTT_SEND_SUBSCRIPTION 1 // Send empty payload (request) to node upon MQTT client subscribe request. +#define MQTT_CMD_SET "set" // command (see MQTT_TOPIC_MASK); mapped to C_SET command type of sensor network +#define MQTT_CMD_GET "get" // command (see MQTT_TOPIC_MASK); mapped to C_REQ command type of sensor network + + +#define MQTT_AUTH_REQUIRED // if your broker has anonymous access uncomment +#define MQTT_USER "user" // username on MQTT broker +#define MQTT_PWD "pwd" // password for MQTT username above +#define MQTT_CONN_ID "MySensors" // passed as id to the MQTT broker + + +// NOTE above : Beware to check if there is any length on payload in your incommingMessage code: +// Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. + +////////////////////////////////////////////////////////////////// + + +char VAR_0[] PROGMEM = "TEMP"; //V_TEMP +char VAR_1[] PROGMEM = "HUM"; //V_HUM +char VAR_2[] PROGMEM = "LIGHT"; //V_LIGHT +char VAR_3[] PROGMEM = "DIMMER"; //V_DIMMER +char VAR_4[] PROGMEM = "PRESSURE"; //V_PRESSURE +char VAR_5[] PROGMEM = "FORECAST"; //V_FORECAST +char VAR_6[] PROGMEM = "RAIN"; //V_RAIN +char VAR_7[] PROGMEM = "RAINRATE"; //V_RAINRATE +char VAR_8[] PROGMEM = "WIND"; //V_WIND +char VAR_9[] PROGMEM = "GUST"; //V_GUST +char VAR_10[] PROGMEM = "DIRECTON"; //V_DIRECTON +char VAR_11[] PROGMEM = "UV"; //V_UV +char VAR_12[] PROGMEM = "WEIGHT"; //V_WEIGHT +char VAR_13[] PROGMEM = "DISTANCE"; //V_DISTANCE +char VAR_14[] PROGMEM = "IMPEDANCE"; //V_IMPEDANCE +char VAR_15[] PROGMEM = "ARMED"; //V_ARMED +char VAR_16[] PROGMEM = "TRIPPED"; //V_TRIPPED +char VAR_17[] PROGMEM = "WATT"; //V_WATT +char VAR_18[] PROGMEM = "KWH"; //V_KWH +char VAR_19[] PROGMEM = "SCENE_ON"; //V_SCENE_ON +char VAR_20[] PROGMEM = "SCENE_OFF"; //V_SCENE_OFF +char VAR_21[] PROGMEM = "HEATER"; //V_HEATER +char VAR_22[] PROGMEM = "HEATER_SW"; //V_HEATER_SW +char VAR_23[] PROGMEM = "LIGHT_LEVEL"; //V_LIGHT_LEVEL +char VAR_24[] PROGMEM = "VAR1"; //V_VAR1 +char VAR_25[] PROGMEM = "VAR2"; //V_VAR2 +char VAR_26[] PROGMEM = "VAR3"; //V_VAR3 +char VAR_27[] PROGMEM = "VAR4"; //V_VAR4 +char VAR_28[] PROGMEM = "VAR5"; //V_VAR5 +char VAR_29[] PROGMEM = "UP"; //V_UP +char VAR_30[] PROGMEM = "DOWN"; //V_DOWN +char VAR_31[] PROGMEM = "STOP"; //V_STOP +char VAR_32[] PROGMEM = "IR_SEND"; //V_IR_SEND +char VAR_33[] PROGMEM = "IR_RECEIVE"; //V_IR_RECEIVE +char VAR_34[] PROGMEM = "FLOW"; //V_FLOW +char VAR_35[] PROGMEM = "VOLUME"; //V_VOLUME +char VAR_36[] PROGMEM = "LOCK_STATUS"; //V_LOCK_STATUS +char VAR_37[] PROGMEM = "LEVEL"; // S_DUST, S_LIGHT_LEVEL, ... +char VAR_38[] PROGMEM = "VOLTAGE"; //V_VOLTAGE +char VAR_39[] PROGMEM = "CURRENT"; //V_CURRENT +char VAR_40[] PROGMEM = "RGB"; //V_RGB +char VAR_41[] PROGMEM = ""; // +char VAR_42[] PROGMEM = ""; // +char VAR_43[] PROGMEM = ""; // +char VAR_44[] PROGMEM = ""; // +char VAR_45[] PROGMEM = ""; // +char VAR_46[] PROGMEM = ""; // +char VAR_47[] PROGMEM = ""; // +char VAR_48[] PROGMEM = ""; // +char VAR_49[] PROGMEM = ""; // +char VAR_50[] PROGMEM = ""; // +char VAR_51[] PROGMEM = ""; // +char VAR_52[] PROGMEM = ""; // +char VAR_53[] PROGMEM = ""; // +char VAR_54[] PROGMEM = ""; // +char VAR_55[] PROGMEM = ""; // +char VAR_56[] PROGMEM = ""; // +char VAR_57[] PROGMEM = ""; // +char VAR_58[] PROGMEM = ""; // +char VAR_59[] PROGMEM = ""; // +char VAR_60[] PROGMEM = "Started!\n"; //Custom for MQTTGateway +char VAR_61[] PROGMEM = "SKETCH_NAME"; //Custom for MQTTGateway +char VAR_62[] PROGMEM = "SKETCH_VERSION"; //Custom for MQTTGateway +char VAR_63[] PROGMEM = "UNKNOWN"; //Custom for MQTTGateway + +////////////////////////////////////////////////////////////////// + +PROGMEM const char *VAR_Type[] = +{ VAR_0, VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9, VAR_10, VAR_11, VAR_12, VAR_13, + VAR_14, VAR_15, VAR_16, VAR_17, VAR_18, VAR_19, VAR_20, VAR_21, VAR_22, VAR_23, VAR_24, VAR_25, + VAR_26, VAR_27, VAR_28, VAR_29, VAR_30, VAR_31, VAR_32, VAR_33, VAR_34, VAR_35, VAR_36, VAR_37, + VAR_38, VAR_39, VAR_40, VAR_41, VAR_42, VAR_43, VAR_44, VAR_45, VAR_46, VAR_47, VAR_48, VAR_49, + VAR_50, VAR_51, VAR_52, VAR_53, VAR_54, VAR_55, VAR_56, VAR_57, VAR_58, VAR_59, VAR_60, VAR_61, + VAR_62, VAR_63 +}; + +char mqtt_prefix[] PROGMEM = MQTT_PREFIX; + +#define S_FIRSTCUSTOM 60 +#define TYPEMAXLEN 20 +#define VAR_TOTAL (sizeof(VAR_Type)/sizeof(char *))-1 + + +#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS) + +//#define DSRTC // RTC Dallas support -> disable debug and use isp programmer to free memory +#endif diff --git a/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino b/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino index 0bb722d..34d3fff 100644 --- a/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino +++ b/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino @@ -279,6 +279,7 @@ void processMQTTMessage(char *inputString, uint8_t inputPos) { uint8_t i = 0; buffer[0]= 0; buffsize = 0; + (void)inputPos; if ((uint8_t)inputString[0] >> 4 == MQTTCONNECT) { buffer[buffsize++] = MQTTCONNACK << 4; @@ -336,7 +337,7 @@ void processMQTTMessage(char *inputString, uint8_t inputPos) { } else if (i==2) { msg.sensor = atoi(str); //SensorID } else if (i==3) { - char match=255; //SensorType + unsigned char match=255; //SensorType #ifdef MQTT_TRANSLATE_TYPES for (uint8_t j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(vType[j]))) ; j++) { @@ -348,7 +349,7 @@ void processMQTTMessage(char *inputString, uint8_t inputPos) { } #endif - if ( atoi(str)!=0 || str=="0" ) { + if ( atoi(str)!=0 || (str[0]=='0' && str[1] =='\0') ) { match=atoi(str); } diff --git a/libraries/MySensors/examples/MockMySensors/MockMySensors.ino b/libraries/MySensors/examples/MockMySensors/MockMySensors.ino index 2eb1629..c88a700 100644 --- a/libraries/MySensors/examples/MockMySensors/MockMySensors.ino +++ b/libraries/MySensors/examples/MockMySensors/MockMySensors.ino @@ -2,23 +2,31 @@ * MockMySensors * * This skecth is intended to crate fake sensors which register and respond to the controller -* -* Barduino 2015 +* *** +* Barduino 2015, GizMoCuz 2015 */ +#include +#include +#include +#include +#include +#include + #include #include +#include -// SPI Pins -#define CE_PIN 9 -#define CS_PIN 10 +#define RADIO_ERROR_LED_PIN 4 // Error led pin +#define RADIO_RX_LED_PIN 6 // Receive led pin +#define RADIO_TX_LED_PIN 5 // the PCB, on board LED // Wait times #define LONG_WAIT 500 #define SHORT_WAIT 50 -#define SKETCH_NAME "FakeMySensors " -#define SKETCH_VERSION "v0.2" +#define SKETCH_NAME "MockMySensors " +#define SKETCH_VERSION "v0.5" // Define Sensors ids /* S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND, @@ -30,67 +38,115 @@ ////#define ID_S_ARDUINO_NODE //auto defined in initialization ////#define ID_S_ARDUINO_REPEATER_NODE //auto defined in initialization -//#define ID_S_DOOR 1 -//#define ID_S_MOTION 2 -//#define ID_S_SMOKE 3 -//#define ID_S_LIGHT 4 -//#define ID_S_DIMMER 5 -//#define ID_S_COVER 6 -//#define ID_S_TEMP 7 -//#define ID_S_HUM 8 -//#define ID_S_BARO 9 -//#define ID_S_WIND 10 -//#define ID_S_RAIN 11 -//#define ID_S_UV 12 -//#define ID_S_WEIGHT 13 -#define ID_S_POWER 14 -#define ID_S_HEATER 15 -#define ID_S_DISTANCE 16 -#define ID_S_LIGHT_LEVEL 17 -#define ID_S_LOCK 18 -#define ID_S_IR 19 -#define ID_S_WATER 20 -#define ID_S_AIR_QUALITY 21 -#define ID_S_DUST 22 -#define ID_S_SCENE_CONTROLLER 23 -#define ID_S_CUSTOM 24 +// Some of these ID's have not been updated for v1.5. Uncommenting too many of them +// will make the sketch too large for a pro mini's memory so it's probably best to try +// one at a time. + +#define ID_S_ARMED 0 // dummy to controll armed stated for several sensors +#define ID_S_DOOR 1 +//#define ID_S_MOTION 2 +//#define ID_S_SMOKE 3 +//#define ID_S_LIGHT 4 +//#define ID_S_DIMMER 5 +//#define ID_S_COVER 6 +//#define ID_S_TEMP 7 +//#define ID_S_HUM 8 +//#define ID_S_BARO 9 +//#define ID_S_WIND 10 +//#define ID_S_RAIN 11 +//#define ID_S_UV 12 +//#define ID_S_WEIGHT 13 +//#define ID_S_POWER 14 +//#define ID_S_HEATER 15 +//#define ID_S_DISTANCE 16 +//#define ID_S_LIGHT_LEVEL 17 +//#define ID_S_LOCK 18 +//#define ID_S_IR 19 +//#define ID_S_WATER 20 +//#define ID_S_AIR_QUALITY 21 +//#define ID_S_DUST 22 +//#define ID_S_SCENE_CONTROLLER 23 +//// Lib 1.5 sensors +//#define ID_S_RGB_LIGHT 24 +//#define ID_S_RGBW_LIGHT 25 +//#define ID_S_COLOR_SENSOR 26 +//#define ID_S_HVAC 27 +//#define ID_S_MULTIMETER 28 +//#define ID_S_SPRINKLER 29 +//#define ID_S_WATER_LEAK 30 +//#define ID_S_SOUND 31 +//#define ID_S_VIBRATION 32 +//#define ID_S_MOISTURE 33 +// +//#define ID_S_CUSTOM 99 + + // Global Vars -unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds) +unsigned long SLEEP_TIME = 900000; // Sleep time between reads (in milliseconds) boolean metric = true; long randNumber; // Instanciate MySersors Gateway -MySensor gw(CE_PIN,CS_PIN); +MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL); +//MyTransportRFM69 transport; + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +//MySigningNone signer; +//MySigningAtsha204Soft signer; +//MySigningAtsha204 signer; + +// Hardware profile +MyHwATMega328 hw; + +// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h +#ifdef WITH_LEDS_BLINKING + MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); +#else + MySensor gw(transport, hw /*, signer*/); +#endif + +//MySensor gw; //Instanciate Messages objects -#ifdef ID_S_DOOR - MyMessage msg_S_DOOR(ID_S_DOOR,V_TRIPPED); +#ifdef ID_S_ARMED + bool isArmed; #endif -#ifdef ID_S_MOTION +#ifdef ID_S_DOOR // V_TRIPPED, V_ARMED + MyMessage msg_S_DOOR_T(ID_S_DOOR,V_TRIPPED); + MyMessage msg_S_DOOR_A(ID_S_DOOR,V_ARMED); +#endif + +#ifdef ID_S_MOTION // V_TRIPPED, V_ARMED MyMessage msg_S_MOTION_A(ID_S_MOTION,V_ARMED); MyMessage msg_S_MOTION_T(ID_S_MOTION,V_TRIPPED); #endif -#ifdef ID_S_SMOKE - MyMessage msg_S_SMOKE(ID_S_SMOKE,V_TRIPPED); +#ifdef ID_S_SMOKE // V_TRIPPED, V_ARMED + MyMessage msg_S_SMOKE_T(ID_S_SMOKE,V_TRIPPED); + MyMessage msg_S_SMOKE_A(ID_S_SMOKE,V_ARMED); #endif #ifdef ID_S_LIGHT MyMessage msg_S_LIGHT(ID_S_LIGHT,V_LIGHT); + bool isLightOn=0; #endif #ifdef ID_S_DIMMER MyMessage msg_S_DIMMER(ID_S_DIMMER,V_DIMMER); + int dimmerVal=100; #endif #ifdef ID_S_COVER MyMessage msg_S_COVER_U(ID_S_COVER,V_UP); MyMessage msg_S_COVER_D(ID_S_COVER,V_DOWN); MyMessage msg_S_COVER_S(ID_S_COVER,V_STOP); + MyMessage msg_S_COVER_V(ID_S_COVER,V_VAR1); + int coverState=0; //0=Stop; 1=up; -1=down #endif #ifdef ID_S_TEMP @@ -126,16 +182,33 @@ MySensor gw(CE_PIN,CS_PIN); #endif #ifdef ID_S_POWER - MyMessage msg_S_POWER_I(ID_S_POWER,V_IMPEDANCE); MyMessage msg_S_POWER_W(ID_S_POWER,V_WATT); MyMessage msg_S_POWER_K(ID_S_POWER,V_KWH); - MyMessage msg_S_POWER_V(ID_S_POWER,V_VOLTAGE); - MyMessage msg_S_POWER_C(ID_S_POWER,V_CURRENT); #endif + #ifdef ID_S_HEATER - MyMessage msg_S_HEATER_M(ID_S_HEATER,V_HEATER); - MyMessage msg_S_HEATER_S(ID_S_HEATER,V_HEATER_SW); + + //////// REVIEW IMPLEMENTATION //////////// + + MyMessage msg_S_HEATER_SET_POINT(ID_S_HEATER,V_HVAC_SETPOINT_HEAT); // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC + MyMessage msg_S_HEATER_FLOW_STATE(ID_S_HEATER,V_HVAC_FLOW_STATE); // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" // S_HVAC, S_HEATER + + //MyMessage msg_S_HEATER_STATUS(ID_S_HEATER,V_STATUS); + //MyMessage msg_S_HEATER_TEMP(ID_S_HEATER,V_TEMP); + + float heater_setpoint=21.5; + String heater_flow_state="Off"; + +// float heater_temp=23.5; +// bool heater_status=false; + + + // V_TEMP // Temperature + // V_STATUS // Binary status. 0=off 1=on + // V_HVAC_FLOW_STATE // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" + // V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + // V_HVAC_SETPOINT_HEAT // HVAC/Heater setpoint #endif #ifdef ID_S_DISTANCE @@ -148,11 +221,13 @@ MySensor gw(CE_PIN,CS_PIN); #ifdef ID_S_LOCK MyMessage msg_S_LOCK(ID_S_LOCK,V_LOCK_STATUS); + bool isLocked = 0; #endif #ifdef ID_S_IR MyMessage msg_S_IR_S(ID_S_IR,V_IR_SEND); MyMessage msg_S_IR_R(ID_S_IR,V_IR_RECEIVE); + long irVal = 0; #endif #ifdef ID_S_WATER @@ -161,19 +236,110 @@ MySensor gw(CE_PIN,CS_PIN); #endif #ifdef ID_S_AIR_QUALITY - MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_VAR1); + MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_LEVEL); #endif #ifdef ID_S_DUST - MyMessage msg_S_DUST(ID_S_DUST,V_DUST_LEVEL); + MyMessage msg_S_DUST(ID_S_DUST,V_LEVEL); #endif #ifdef ID_S_SCENE_CONTROLLER MyMessage msg_S_SCENE_CONTROLLER_ON(ID_S_SCENE_CONTROLLER,V_SCENE_ON); MyMessage msg_S_SCENE_CONTROLLER_OF(ID_S_SCENE_CONTROLLER,V_SCENE_OFF); + // not sure if scene controller sends int or chars + // betting on ints as Touch Display Scen by Hek // compiler warnings + char *scenes[] = { + (char *)"Good Morning", + (char *)"Clean Up!", + (char *)"All Lights Off", + (char *)"Music On/Off" + }; + + int sceneVal=0; + int sceneValPrevious=0; + #endif +#ifdef ID_S_RGB_LIGHT + MyMessage msg_S_RGB_LIGHT_V_RGB(ID_S_RGB_LIGHT,V_RGB); + MyMessage msg_S_RGB_LIGHT_V_WATT(ID_S_RGB_LIGHT,V_WATT); + String rgbState="000000"; + //RGB light V_RGB, V_WATT + //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) +#endif + +#ifdef ID_S_RGBW_LIGHT + MyMessage msg_S_RGBW_LIGHT_V_RGBW(ID_S_RGBW_LIGHT,V_RGBW); + MyMessage msg_S_RGBW_LIGHT_V_WATT(ID_S_RGBW_LIGHT,V_WATT); + String rgbwState="00000000"; + //RGBW light (with separate white component) V_RGBW, V_WATT + //RGBW value transmitted as ASCII hex string (I.e "ff0000ff" for red + full white) S_RGBW_LIGHT +#endif + +#ifdef ID_S_COLOR_SENSOR + MyMessage msg_S_COLOR_SENSOR_V_RGB(ID_S_COLOR_SENSOR,V_RGB); + //Color sensor V_RGB + //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) S_RGB_LIGHT, S_COLOR_SENSOR +#endif + +#ifdef ID_S_HVAC + MyMessage msg_S_HVAC_V_HVAC_SETPOINT_HEAT(ID_S_HVAC,V_HVAC_SETPOINT_HEAT); + MyMessage msg_S_HVAC_V_HVAC_SETPOINT_COOL(ID_S_HVAC,V_HVAC_SETPOINT_COOL); + MyMessage msg_S_HVAC_V_HVAC_FLOW_STATET(ID_S_HVAC,V_HVAC_FLOW_STATE); + MyMessage msg_S_HVAC_V_HVAC_FLOW_MODE(ID_S_HVAC,V_HVAC_FLOW_MODE); + MyMessage msg_S_HVAC_V_HVAC_SPEED(ID_S_HVAC,V_HVAC_SPEED); + + float hvac_SetPointHeat = 16.5; + float hvac_SetPointCool = 25.5; + String hvac_FlowState = "AutoChangeOver"; + String hvac_FlowMode = "Auto"; + String hvac_Speed = "Normal"; + + //Thermostat/HVAC device + //V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint + //V_HVAC_SETPOINT_COOL, // HVAC cold setpoint + //V_HVAC_FLOW_STATE, // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" + //V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") + //V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + + // NOT IMPLEMENTED YET + //V_TEMP // Temperature + //V_STATUS // Binary status. 0=off 1=on +#endif + +#ifdef ID_S_MULTIMETER + MyMessage msg_S_MULTIMETER_V_IMPEDANCE(ID_S_MULTIMETER,V_IMPEDANCE); + MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE); + MyMessage msg_S_MULTIMETER_V_CURRENT(ID_S_MULTIMETER,V_CURRENT); + + // Multimeter device V_VOLTAGE, V_CURRENT, V_IMPEDANCE + // V_IMPEDANCE 14 Impedance value + // V_VOLTAGE 38 Voltage level + // V_CURRENT 39 Current level +#endif + +#ifdef ID_S_SPRINKLER + // S_SPRINKLER 31 Sprinkler device V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) + // V_STATUS 2 Binary status. 0=off 1=on + // V_ARMED 15 Armed status of a security sensor. 1=Armed, 0=Bypassed + // V_TRIPPED 16 Tripped status of a security sensor. 1=Tripped, 0=Untripped +#endif + +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif + +#ifdef ID_S_MOISTURE + MyMessage msg_S_MOISTURE(ID_S_MOISTURE,V_LEVEL); +#endif + #ifdef ID_S_CUSTOM + MyMessage msg_S_CUSTOM_1(ID_S_CUSTOM,V_VAR1); MyMessage msg_S_CUSTOM_2(ID_S_CUSTOM,V_VAR2); MyMessage msg_S_CUSTOM_3(ID_S_CUSTOM,V_VAR3); MyMessage msg_S_CUSTOM_4(ID_S_CUSTOM,V_VAR4); @@ -206,151 +372,203 @@ void setup() Serial.println(metric ? "Metric":"Imperial"); gw.wait(LONG_WAIT); + // Init Armed + #ifdef ID_S_ARMED + isArmed = true; + #endif + // Register all sensors to gw (they will be created as child devices) Serial.println("Presenting Nodes"); Serial.println("________________"); #ifdef ID_S_DOOR Serial.println(" S_DOOR"); - gw.present(ID_S_DOOR,S_DOOR); + gw.present(ID_S_DOOR,S_DOOR,"Outside Door"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_MOTION Serial.println(" S_MOTION"); - gw.present(ID_S_MOTION,S_MOTION); + gw.present(ID_S_MOTION,S_MOTION,"Outside Motion"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_SMOKE Serial.println(" S_SMOKE"); - gw.present(ID_S_SMOKE,S_SMOKE); + gw.present(ID_S_SMOKE,S_SMOKE,"Kitchen Smoke"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_LIGHT Serial.println(" S_LIGHT"); - gw.present(ID_S_LIGHT,S_LIGHT); + gw.present(ID_S_LIGHT,S_LIGHT,"Hall Light"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_DIMMER Serial.println(" S_DIMMER"); - gw.present(ID_S_DIMMER,S_DIMMER); + gw.present(ID_S_DIMMER,S_DIMMER,"Living room dimmer"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_COVER - Serial.println(" S_COVER"; - gw.present(ID_S_COVER,S_COVER); + Serial.println(" S_COVER"); + gw.present(ID_S_COVER,S_COVER,"Window cover"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_TEMP - Serial.println(" S_TMEP"); - gw.present(ID_S_TEMP,S_TEMP); + Serial.println(" S_TEMP"); + gw.present(ID_S_TEMP,S_TEMP,"House Temperarue"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_HUM Serial.println(" S_HUM"); - gw.present(ID_S_HUM,S_HUM); + gw.present(ID_S_HUM,S_HUM,"Current Humidity"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_BARO Serial.println(" S_BARO"); - gw.present(ID_S_BARO,S_BARO); + gw.present(ID_S_BARO,S_BARO," Air pressure"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_WIND Serial.println(" S_WIND"); - gw.present(ID_S_WIND,S_WIND); + gw.present(ID_S_WIND,S_WIND,"Wind Station"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_RAIN Serial.println(" S_RAIN"); - gw.present(ID_S_RAIN,S_RAIN); + gw.present(ID_S_RAIN,S_RAIN,"Rain Station"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_UV Serial.println(" S_UV"); - gw.present(ID_S_UV,S_UV); + gw.present(ID_S_UV,S_UV,"Ultra Violet"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_WEIGHT - Serial.println(" S_WEIGHT"): - gw.present(ID_S_WEIGHT,S_WEIGHT); + Serial.println(" S_WEIGHT"); + gw.present(ID_S_WEIGHT,S_WEIGHT,"Outdoor Scale"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_POWER Serial.println(" S_POWER"); - gw.present(ID_S_POWER,S_POWER); + gw.present(ID_S_POWER,S_POWER,"Power Metric"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_HEATER Serial.println(" S_HEATER"); - gw.present(ID_S_HEATER,S_HEATER); + gw.present(ID_S_HEATER,S_HEATER,"Garage Heater"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_DISTANCE Serial.println(" S_DISTANCE"); - gw.present(ID_S_DISTANCE,S_DISTANCE); + gw.present(ID_S_DISTANCE,S_DISTANCE,"Distance Measure"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_LIGHT_LEVEL Serial.println(" S_LIGHT_LEVEL"); - gw.present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL); + gw.present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL,"Outside Light Level"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_LOCK Serial.println(" S_LOCK"); - gw.present(ID_S_LOCK,S_LOCK); + gw.present(ID_S_LOCK,S_LOCK,"Front Door Lock"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_IR Serial.println(" S_IR"); - gw.present(ID_S_IR,S_IR); + gw.present(ID_S_IR,S_IR,"Univeral Command"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_WATER Serial.println(" S_WATER"); - gw.present(ID_S_WATER,S_WATER); + gw.present(ID_S_WATER,S_WATER,"Water Level"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_AIR_QUALITY Serial.println(" S_AIR_QUALITY"); - gw.present(ID_S_AIR_QUALITY,S_AIR_QUALITY); + gw.present(ID_S_AIR_QUALITY,S_AIR_QUALITY,"Air Station"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_DUST Serial.println(" S_DUST"); - gw.present(ID_S_DUST,S_DUST); + gw.present(ID_S_DUST,S_DUST,"Dust Level"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_SCENE_CONTROLLER Serial.println(" S_SCENE_CONTROLLER"); - gw.present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER); + gw.present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER,"Scene Controller"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_RGB_LIGHT + Serial.println(" RGB_LIGHT"); + gw.present(ID_S_RGB_LIGHT,S_RGB_LIGHT,"Mood Light"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_RGBW_LIGHT + Serial.println(" RGBW_LIGHT"); + gw.present(ID_S_RGBW_LIGHT,S_RGBW_LIGHT,"Mood Light 2"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_COLOR_SENSOR + Serial.println(" COLOR_SENSOR"); + gw.present(ID_S_COLOR_SENSOR,S_COLOR_SENSOR,"Hall Painting"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_HVAC + Serial.println(" HVAC"); + gw.present(ID_S_HVAC,S_HVAC,"HVAC"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_MULTIMETER + Serial.println(" MULTIMETER"); + gw.present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Staion"); + gw.wait(SHORT_WAIT); + #endif + + #ifdef ID_S_SPRINKLER + #endif + #ifdef ID_S_WATER_LEAK + #endif + #ifdef ID_S_SOUND + #endif + #ifdef ID_S_VIBRATION + #endif + #ifdef ID_S_MOISTURE + #endif + + #ifdef ID_S_MOISTURE + Serial.println(" S_MOISTURE"); + gw.present(ID_S_MOISTURE,S_MOISTURE,"Basement Sensor"); gw.wait(SHORT_WAIT); #endif #ifdef ID_S_CUSTOM Serial.println(" S_CUSTOM"); - gw.present(ID_S_CUSTOM,S_CUSTOM); + gw.present(ID_S_CUSTOM,S_CUSTOM,"Other Stuff"); gw.wait(SHORT_WAIT); #endif @@ -381,7 +599,7 @@ void loop() gw.wait(LONG_WAIT); //Read Sensors - #ifdef S_ID_DOOR + #ifdef ID_S_DOOR door(); #endif @@ -473,6 +691,41 @@ void loop() scene(); #endif + #ifdef ID_S_RGB_LIGHT + rgbLight(); + #endif + + #ifdef ID_S_RGBW_LIGHT + rgbwLight(); + #endif + + #ifdef ID_S_COLOR_SENSOR + color(); + #endif + + #ifdef ID_S_HVAC + hvac(); + #endif + + #ifdef ID_S_MULTIMETER + multimeter(); + #endif + + #ifdef ID_S_SPRINKLER + #endif + #ifdef ID_S_WATER_LEAK + #endif + #ifdef ID_S_SOUND + #endif + #ifdef ID_S_VIBRATION + #endif + #ifdef ID_S_MOISTURE + #endif + + #ifdef ID_S_MOISTURE + moisture(); + #endif + #ifdef ID_S_CUSTOM custom(); #endif @@ -494,25 +747,29 @@ void receiveTime(unsigned long controllerTime) { //void door(){} -#ifdef S_ID_DOOR +#ifdef ID_S_DOOR void door(){ - + Serial.print("Door is: " ); if (randNumber <= 50) { Serial.println("Open"); - gw.send(msg_S_DOOR.set(1)); + gw.send(msg_S_DOOR_T.set(1)); } else { Serial.println("Closed"); - gw.send(msg_S_DOOR.set(0)); + gw.send(msg_S_DOOR_T.set(0)); } - + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + gw.send(msg_S_DOOR_A.set(isArmed)); + #endif } #endif #ifdef ID_S_MOTION void motion(){ - + Serial.print("Motion is: " ); if (randNumber <= 50) { @@ -523,6 +780,11 @@ void motion(){ gw.send(msg_S_MOTION_T.set(0)); } + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + gw.send(msg_S_MOTION_A.set(isArmed)); + #endif } #endif @@ -533,38 +795,35 @@ void smoke(){ if (randNumber <= 50) { Serial.println("Active"); - gw.send(msg_S_SMOKE.set(1)); + gw.send(msg_S_SMOKE_T.set(1)); } else { Serial.println("Quiet"); - gw.send(msg_S_SMOKE.set(0)); + gw.send(msg_S_SMOKE_T.set(0)); } + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + gw.send(msg_S_SMOKE_A.set(isArmed)); + #endif + } #endif #ifdef ID_S_LIGHT void light(){ - bool isLightOn = gw.loadState(ID_S_LIGHT); - Serial.print("Light is: " ); + Serial.println((isLightOn ? "On":"Off")); - if (isLightOn) { - Serial.println("On"); - gw.send(msg_S_LIGHT.set(1)); - } else { - Serial.println("Off"); - gw.send(msg_S_LIGHT.set(0)); - } - + gw.send(msg_S_LIGHT.set(isLightOn)); + } #endif #ifdef ID_S_DIMMER void dimmer(){ - int dimmerVal = gw.loadState(ID_S_DIMMER); - Serial.print("Dimmer is set to: " ); Serial.println(dimmerVal); @@ -576,24 +835,19 @@ void dimmer(){ #ifdef ID_S_COVER void cover(){ - int coverVal = gw.loadState(ID_S_COVER); - Serial.print("Cover is : " ); - - switch (coverVal) { - case 0: + + if (coverState == 1){ Serial.println("Opening"); - gw.send(msg_S_COVER_U.set(V_UP)); - break; - case 1: + gw.send(msg_S_COVER_U.set(1)); + }else if (coverState == -1){ Serial.println("Closing"); - gw.send(msg_S_COVER_D.set(V_DOWN)); - break; - default: + gw.send(msg_S_COVER_D.set(0)); + }else{ Serial.println("Idle"); - gw.send(msg_S_COVER_S.set(V_STOP)); + gw.send(msg_S_COVER_S.set(-1)); } - + gw.send(msg_S_COVER_V.set(coverState)); } #endif @@ -623,7 +877,7 @@ void hum(){ void baro(){ const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"}; - long pressure = map(randNumber,1,100,87000,108600); + long pressure = map(randNumber,1,100,870,1086);// hPa? int forecast = map(randNumber,1,100,0,5); Serial.print("Atmosferic Pressure is: " ); @@ -695,66 +949,40 @@ void weight(){ #ifdef ID_S_POWER void power(){ - - Serial.print("Impedance is: " ); - Serial.println(map(randNumber,1,100,0,150)); - gw.send(msg_S_POWER_I.set(map(randNumber,1,100,0,150))); - Serial.print("Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - + Serial.println(map(randNumber,1,100,0,150)); gw.send(msg_S_POWER_W.set(map(randNumber,1,100,0,150))); Serial.print("KWH is: " ); - Serial.println(map(randNumber,1,100,0,150)); - + Serial.println(map(randNumber,1,100,0,150)); gw.send(msg_S_POWER_K.set(map(randNumber,1,100,0,150))); - Serial.print("Voltage is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - gw.send(msg_S_POWER_V.set(map(randNumber,1,100,0,150))); - - Serial.print("Current is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - gw.send(msg_S_POWER_C.set(map(randNumber,1,100,0,150))); - } #endif #ifdef ID_S_HEATER void heater(){ - int heater_mode = gw.loadState(ID_S_HEATER); - bool heater_switch = gw.loadState(ID_S_HEATER+1); +// float heater_setpoint=21.5; +// float heater_temp=23.5; +// bool heater_status=false; +// String heatState="Off"; - Serial.print("Heater mode is: " ); - - if (heater_mode == 0){ - Serial.println("Off"); - } - else if (heater_mode == 1){ - Serial.println("Heat On"); - } - else if (heater_mode == 2){ - Serial.println("Cool On"); - } - else if (heater_mode == 3){ - Serial.println("Auto Change Over"); - } - else { - Serial.print("Unknown Heater Mode: "); - Serial.println(heater_mode); - } - - gw.send(msg_S_HEATER_M.set(heater_mode)); + Serial.print("Heater flow state is: " ); + Serial.println(heater_flow_state); + gw.send(msg_S_HEATER_FLOW_STATE.set(heater_flow_state.c_str())); - Serial.print("Heater is: " ); - Serial.println(heater_switch?"On":"Off"); - - gw.send(msg_S_HEATER_S.set(heater_switch)); +// Serial.print("Heater on/off is: " ); +// Serial.println((heater_status==true)?"On":"Off"); +// gw.send(msg_S_HEATER_STATUS.set(heater_status)); +// Serial.print("Heater Temperature is: " ); +// Serial.println(heater_temp,1); +// gw.send(msg_S_HEATER_TEMP.set(heater_temp,1)); + + Serial.print("Heater Setpoint: " ); + Serial.println(heater_setpoint,1); + gw.send(msg_S_HEATER_SET_POINT.set(heater_setpoint,1)); } #endif @@ -783,30 +1011,21 @@ void light_level(){ #ifdef ID_S_LOCK void lock(){ - bool isLocked = gw.loadState(ID_S_LOCK); - Serial.print("Lock is: " ); - - if (isLocked) { - Serial.println("On"); - gw.send(msg_S_LOCK.set(1)); - } else { - Serial.println("Off"); - gw.send(msg_S_LOCK.set(0)); - } + Serial.println((isLocked ? "Locked":"Unlocked")); + gw.send(msg_S_LOCK.set(isLocked)); } #endif #ifdef ID_S_IR void ir(){ - - int irVal = gw.loadState(ID_S_IR); Serial.print("Infrared is: " ); Serial.println(irVal); gw.send(msg_S_IR_S.set(irVal)); + gw.send(msg_S_IR_R.set(irVal)); } #endif @@ -852,16 +1071,134 @@ void dust(){ #ifdef ID_S_SCENE_CONTROLLER void scene(){ - bool isSceneOn = gw.loadState(ID_S_SCENE_CONTROLLER); - Serial.print("Scene is: " ); - Serial.println(isSceneOn ? "On":"Off"); + Serial.println(scenes[sceneVal]); - if(isSceneOn) - gw.send(msg_S_SCENE_CONTROLLER_ON.set(isSceneOn)); - else - gw.send(msg_S_SCENE_CONTROLLER_OF.set(isSceneOn)); + if(sceneValPrevious != sceneVal){ + gw.send(msg_S_SCENE_CONTROLLER_OF.set(sceneValPrevious)); + gw.send(msg_S_SCENE_CONTROLLER_ON.set(sceneVal)); + sceneValPrevious=sceneVal; + } + +} +#endif + +#ifdef ID_S_RGB_LIGHT +void rgbLight(){ + Serial.print("RGB Light state is: " ); + Serial.println(rgbState); + gw.send(msg_S_RGB_LIGHT_V_RGB.set(rgbState.c_str())); + + Serial.print("RGB Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + gw.send(msg_S_RGB_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_RGBW_LIGHT +void rgbwLight(){ + + Serial.print("RGBW Light state is: " ); + Serial.println(rgbwState); + gw.send(msg_S_RGBW_LIGHT_V_RGBW.set(rgbwState.c_str())); + + Serial.print("RGBW Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + gw.send(msg_S_RGBW_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_COLOR_SENSOR +void color(){ + String colorState; + + String red = String(random(0,256),HEX); + String green = String(random(0,256),HEX); + String blue = String(random(0,256),HEX); + + colorState=String(red + green + blue); + + Serial.print("Color state is: " ); + Serial.println(colorState); + gw.send(msg_S_COLOR_SENSOR_V_RGB.set(colorState.c_str())); + +} +#endif + +#ifdef ID_S_HVAC +void hvac(){ + +// float hvac_SetPointHeat = 16.5; +// float hvac_SetPointCool = 25.5; +// String hvac_FlowState = "AutoChangeOver"; +// String hvac_FlowMode = "Auto"; +// String hvac_Speed = "Normal"; + + Serial.print("HVAC Set Point Heat is: " ); + Serial.println(hvac_SetPointHeat); + gw.send(msg_S_HVAC_V_HVAC_SETPOINT_HEAT.set(hvac_SetPointHeat,1)); + + Serial.print("HVAC Set Point Cool is: " ); + Serial.println(hvac_SetPointCool); + gw.send(msg_S_HVAC_V_HVAC_SETPOINT_COOL.set(hvac_SetPointCool,1)); + + Serial.print("HVAC Flow State is: " ); + Serial.println(hvac_FlowState); + gw.send(msg_S_HVAC_V_HVAC_FLOW_STATET.set(hvac_FlowState.c_str())); + + Serial.print("HVAC Flow Mode is: " ); + Serial.println(hvac_FlowMode); + gw.send(msg_S_HVAC_V_HVAC_FLOW_MODE.set(hvac_FlowMode.c_str())); + + Serial.print("HVAC Speed is: " ); + Serial.println(hvac_Speed); + gw.send(msg_S_HVAC_V_HVAC_SPEED.set(hvac_Speed.c_str())); + +} +#endif + +#ifdef ID_S_MULTIMETER +void multimeter(){ + int impedance=map(randNumber,1,100,0,15000); + int volt=map(randNumber,1,100,0,380); + int amps=map(randNumber,1,100,0,16); + + Serial.print("Impedance is: " ); + Serial.println(impedance); + gw.send(msg_S_MULTIMETER_V_IMPEDANCE.set(impedance)); + + Serial.print("Voltage is: " ); + Serial.println(volt); + gw.send(msg_S_MULTIMETER_V_VOLTAGE.set(volt)); + + Serial.print("Current is: " ); + Serial.println(amps); + gw.send(msg_S_MULTIMETER_V_CURRENT.set(amps)); + +} +#endif + +#ifdef ID_S_SPRINKLER +#endif +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif + +#ifdef ID_S_MOISTURE +void moisture(){ + + Serial.print("Moisture level is: " ); + Serial.println(randNumber); + + gw.send(msg_S_MOISTURE.set(randNumber)); } #endif @@ -871,6 +1208,7 @@ void custom(){ Serial.print("Custom value is: " ); Serial.println(randNumber); + gw.send(msg_S_CUSTOM_1.set(randNumber)); gw.send(msg_S_CUSTOM_2.set(randNumber)); gw.send(msg_S_CUSTOM_3.set(randNumber)); gw.send(msg_S_CUSTOM_4.set(randNumber)); @@ -882,15 +1220,49 @@ void custom(){ void incomingMessage(const MyMessage &message) { switch (message.type) { + #ifdef ID_S_ARMED + case V_ARMED: + isArmed = message.getBool(); + Serial.print("Incoming change for ID_S_ARMED:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println((isArmed ? "Armed":"Disarmed" )); + #ifdef ID_S_DOOR + door();//temp ack for door + #endif + #ifdef ID_S_MOTION + motion();//temp ack + #endif + #ifdef ID_S_SMOKE + smoke();//temp ack + #endif + break; + #endif + + + case V_STATUS: // V_LIGHT: #ifdef ID_S_LIGHT - case V_LIGHT: - gw.saveState(ID_S_LIGHT, message.getBool()); + if(message.sensor==ID_S_LIGHT){ + isLightOn = message.getBool(); Serial.print("Incoming change for ID_S_LIGHT:"); Serial.print(message.sensor); Serial.print(", New status: "); - Serial.println(message.getBool()); - break; + Serial.println((isLightOn ? "On":"Off")); + light(); // temp ack + } #endif +// #ifdef ID_S_HEATER +// if(message.sensor == ID_S_HEATER){ +// heater_status = message.getBool(); +// Serial.print("Incoming change for ID_S_HEATER:"); +// Serial.print(message.sensor); +// Serial.print(", New status: "); +// Serial.println(heater_status); +// heater();//temp ack +// } +// #endif + break; + #ifdef ID_S_DIMMER case V_DIMMER: @@ -898,113 +1270,210 @@ void incomingMessage(const MyMessage &message) { Serial.println( "V_DIMMER data invalid (should be 0..100)" ); break; } - gw.saveState(ID_S_DIMMER, message.getInt()); + dimmerVal= message.getInt(); Serial.print("Incoming change for ID_S_DIMMER:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getInt()); + dimmer();// temp ack break; #endif #ifdef ID_S_COVER case V_UP: - gw.saveState(ID_S_COVER, 0); + coverState=1; Serial.print("Incoming change for ID_S_COVER:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println("V_UP"); + cover(); // temp ack break; case V_DOWN: - gw.saveState(ID_S_COVER, 1); + coverState=-1; Serial.print("Incoming change for ID_S_COVER:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println("V_DOWN"); + cover(); //temp ack break; case V_STOP: - gw.saveState(ID_S_COVER, 2); + coverState=0; Serial.print("Incoming change for ID_S_COVER:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println("V_STOP"); + cover(); //temp ack break; #endif - #ifdef ID_S_HEATER - case V_HEATER: - gw.saveState(ID_S_HEATER, message.getInt()); - Serial.print("Incoming change for ID_S_HEATER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); + + case V_HVAC_SETPOINT_HEAT: + + #ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER){ + heater_setpoint=message.getFloat(); - if (message.getInt() == 0){ - Serial.println("Off"); - } - else if (message.getInt() == 1){ - Serial.println("Heat On"); - } - else if (message.getInt() == 2){ - Serial.println("Cool On"); - } - else if (message.getInt() == 3){ - Serial.println("Auto Change Over"); - } - else { - Serial.print("Unknown Heater Mode: "); - Serial.println(message.getInt()); - } - break; - - case V_HEATER_SW: - gw.saveState(ID_S_HEATER+1, message.getBool()); - Serial.print("Incoming change for ID_S_HEATER:"); + Serial.print("Incoming set point for ID_S_HEATER:"); Serial.print(message.sensor); Serial.print(", New status: "); - Serial.println((message.getBool() ? "On":"Off")); + Serial.println(heater_setpoint,1); + heater();//temp ack + } + #endif + + #ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC){ + hvac_SetPointHeat=message.getFloat(); + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointHeat,1); + hvac();//temp ack + } + #endif + break; + + case V_HVAC_FLOW_STATE: + #ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER){ + heater_flow_state=message.getString(); + Serial.print("Incoming flow state change for ID_S_HEATER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(heater_flow_state); + heater();//temp ack + } + #endif + + #ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC){ + hvac_FlowState=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowState); + hvac();//temp ack + } + #endif break; - #endif #ifdef ID_S_LOCK case V_LOCK_STATUS: - gw.saveState(ID_S_LOCK, message.getBool()); + isLocked = message.getBool(); Serial.print("Incoming change for ID_S_LOCK:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()?"Locked":"Unlocked"); + lock(); //temp ack break; #endif #ifdef ID_S_IR - case V_IR_RECEIVE: - gw.saveState(ID_S_IR, message.getInt()); + case V_IR_SEND: + irVal = message.getLong(); Serial.print("Incoming change for ID_S_IR:"); Serial.print(message.sensor); Serial.print(", New status: "); - Serial.println(message.getInt()); + Serial.println(irVal); + ir(); // temp ack + break; + case V_IR_RECEIVE: + irVal = message.getLong(); + Serial.print("Incoming change for ID_S_IR:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(irVal); + ir(); // temp ack break; #endif #ifdef ID_S_SCENE_CONTROLLER case V_SCENE_ON: - gw.saveState(ID_S_SCENE_CONTROLLER, 1); + sceneVal = message.getInt(); Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); Serial.print(message.sensor); Serial.print(", New status: "); - Serial.println("On"); + Serial.print(scenes[sceneVal]); + Serial.println(" On"); + scene();// temp ack break; case V_SCENE_OFF: - gw.saveState(ID_S_SCENE_CONTROLLER, 0); + sceneVal = message.getInt(); Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); Serial.print(message.sensor); Serial.print(", New status: "); - Serial.println("Off"); + Serial.print(scenes[sceneVal]); + Serial.println(" Off"); + scene();// temp ack break; #endif - + + #ifdef ID_S_RGB_LIGHT + case V_RGB: + rgbState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGB_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbState); + rgbLight(); // temp ack + + break; + #endif + + #ifdef ID_S_RGBW_LIGHT + case V_RGBW: + rgbwState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGBW_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbwState); + rgbwLight(); + break; + #endif + + #ifdef ID_S_HVAC + // hvac_SetPointHeat + // hvac_SetPointCool + // hvac_FlowState + // hvac_FlowMode + // hvac_Speed + + case V_HVAC_SETPOINT_COOL: + hvac_SetPointCool=message.getFloat(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointCool,1); + hvac();//temp ack + break; + + case V_HVAC_FLOW_MODE: + hvac_Speed=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_Speed); + hvac();//temp ack + break; + + case V_HVAC_SPEED: + hvac_FlowMode=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowMode); + hvac();//temp ack + break; + #endif + default: - Serial.print("Unknown/UnImplemented message type:"); + Serial.print("Unknown/UnImplemented message type: "); Serial.println(message.type); } diff --git a/libraries/MySensors/examples/MockMySensors/README.md b/libraries/MySensors/examples/MockMySensors/README.md index 24e2ce9..ef2062e 100644 --- a/libraries/MySensors/examples/MockMySensors/README.md +++ b/libraries/MySensors/examples/MockMySensors/README.md @@ -3,13 +3,38 @@ Arduino sketch to fake sensor for the MySensors Library This skecth is intended to crate fake sensors which register and respond to the controller -Barduino 2015 +Barduino, GizMoCuz 2015 ----------------- Comment/Uncomment the sensors you would like to test Arduino Uno R3 can support about 12 sensors before it runs out of memory. -You probably need to turn of the MySensor Lib debug to save some memory +(turning off the MySensors debug helps if you are memory limited) -Nest step will be to remove the read/write to the eprom -and extend to support the v1.5 sensors +With a Mega you can have them all + + +Changes Log +----------------- + +2015-09-07 +Five more sensors + S_RGB_LIGHT + S_RGBW_LIGHT + S_COLOR_SENSOR + S_HVAC + S_MULTIMETER +Consolidated HVAC and HEATER incoming message + +2015-09-06 + +Merge with Gizmocuz (implementation of S_HEATER & S_MOISTURE +Implementation of S_COVER, S_IR, S_SCENE_CONTROLLER + + +2015-08-19 + +Removed the load/save to eeprom +Touched the heater sensor +Created a pseudo sensor to handle the V_ARMED message. +All sensors which support V_ARMED will arm/disarm at the same time diff --git a/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino b/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino index d54e599..50e3e6c 100644 --- a/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino +++ b/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino @@ -56,6 +56,8 @@ #define PANIC_DISTANCE 5 // Mix distance we red warning indication should be active (in cm) #define PARKED_DISTANCE 20 // Distance when "parked signal" should be sent to controller (in cm) +#define PARK_OFF_TIMEOUT 20000 // Number of milliseconds until turning off light when parked. + // Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest // example for more information on possible values. @@ -67,17 +69,18 @@ NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and #define CHILD_ID 1 MySensor gw; MyMessage msg(CHILD_ID,V_TRIPPED); -int oldParkedStatus=-1; -int sendInterval = 5000; // Send park status at maximum every 5 second. -unsigned long lastSend; #endif +unsigned long sendInterval = 5000; // Send park status at maximum every 5 second. +unsigned long lastSend; -int blinkInterval = 100; // blink interval (milliseconds) +int oldParkedStatus=-1; + +unsigned long blinkInterval = 100; // blink interval (milliseconds) unsigned long lastBlinkPeriod; bool blinkColor = true; // To make a fading motion on the led ring/tape we only move one pixel/distDebounce time -int distDebounce = 30; +unsigned long distDebounce = 30; unsigned long lastDebouncePeriod; int numLightPixels=0; int skipZero=0; @@ -109,7 +112,6 @@ void loop() { if (now-lastDebouncePeriod > distDebounce) { lastDebouncePeriod = now; -#ifdef SEND_STATUS_TO_CONTROLLER // Update parked status int parked = displayDist != 0 && displayDist sendInterval) { @@ -117,47 +119,55 @@ void loop() { Serial.println("Car Parked"); else Serial.println("Car Gone"); +#ifdef SEND_STATUS_TO_CONTROLLER gw.send(msg.set(parked)); +#endif oldParkedStatus = parked; lastSend = now; } -#endif - - if (displayDist == 0) { - // No reading from sensor, assume no object found - numLightPixels--; - } else { - skipZero = 0; - int newLightPixels = NUMPIXELS - (NUMPIXELS*(displayDist-PANIC_DISTANCE)/MAX_DISTANCE); - if (newLightPixels>numLightPixels) { - // Fast raise - numLightPixels += max((newLightPixels - numLightPixels) / 2, 1); - } else if (newLightPixels=NUMPIXELS) { - // Do some intense red blinking - if (now-lastBlinkPeriod > blinkInterval) { - blinkColor = !blinkColor; - lastBlinkPeriod = now; - } - for(int i=0;i PARK_OFF_TIMEOUT) { + // We've been parked for a while now. Turn off all pixels + for(int i=0;inumLightPixels) { + // Fast raise + numLightPixels += max((newLightPixels - numLightPixels) / 2, 1); + } else if (newLightPixels=NUMPIXELS) { + // Do some intense red blinking + if (now-lastBlinkPeriod > blinkInterval) { + blinkColor = !blinkColor; + lastBlinkPeriod = now; + } + for(int i=0;i + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Created by vil1driver + * + * DESCRIPTION + * RGB led strip controled with three dimmers + one On/Off for run/stop rgb color cycle :p + * + */ + +#define SN "RGB Led strip 3D" +#define SV "v1" + +// Load mysensors library +#include +// Load Serial Peripheral Interface library +#include + +// Arduino pin attached to MOSFET Gate pin +#define RED_PIN 3 +#define GREEN_PIN 5 +#define BLUE_PIN 6 + +MySensor gw; + +// Define message name and type to send sensor info +MyMessage RedStatus(RED_PIN, V_DIMMER); +MyMessage GreenStatus(GREEN_PIN, V_DIMMER); +MyMessage BlueStatus(BLUE_PIN, V_DIMMER); +MyMessage Status(1, V_DIMMER); +MyMessage rgbShowState(0, V_LIGHT); + +// Serial.print translate sensor id to sensor name +char color[][6] = {"","","","RED","","GREEN","BLUE"}; + +// Vars for rgbShow function +int redval = 0; +int greenval = 0; +int blueval = 0; +long time=0; +int isShow; + +void setup() +{ + // Initializes the sensor node (Callback function for incoming messages, node id, is repeater) + gw.begin(incomingMessage, 31, true); + + // Present sketch (name, version) + gw.sendSketchInfo(SN, SV); + + // Register sensors (id, type, description, ack back) + gw.present(RED_PIN, S_DIMMER, "present RED light", false); + gw.present(GREEN_PIN, S_DIMMER, "present GREEN light", false); + gw.present(BLUE_PIN, S_DIMMER, "present BLUE light", false); + gw.present(0, S_LIGHT, "present Show button", false); + + // Define pin mode (pin number, type) + pinMode(RED_PIN, OUTPUT); + pinMode(GREEN_PIN, OUTPUT); + pinMode(BLUE_PIN, OUTPUT); + + // Correct saved RGB value for first start + gw.saveState(RED_PIN, constrain((int8_t)gw.loadState(RED_PIN), 0, 100)); + gw.saveState(GREEN_PIN, constrain((int8_t)gw.loadState(GREEN_PIN), 0, 100)); + gw.saveState(BLUE_PIN, constrain((int8_t)gw.loadState(BLUE_PIN), 0, 100)); + + // Get value from eeprom and write to output + analogWrite(RED_PIN, 255 * gw.loadState(RED_PIN) / 100); + analogWrite(GREEN_PIN, 255 * gw.loadState(GREEN_PIN) / 100); + analogWrite(BLUE_PIN, 255 * gw.loadState(BLUE_PIN) / 100); + + // Write some debug info + Serial.print("Load from eeprom RED: "); + Serial.print(gw.loadState(RED_PIN)); + Serial.println("%"); + Serial.print("Load from eeprom GREEN: "); + Serial.print(gw.loadState(GREEN_PIN)); + Serial.println("%"); + Serial.print("Load from eeprom BLUE: "); + Serial.print(gw.loadState(BLUE_PIN)); + Serial.println("%"); + + // Send RGB value to controler (request ack back: true/false) + Serial.println("Send eeprom value to controler"); + gw.send( RedStatus.set(gw.loadState(RED_PIN)), false ); + gw.send( GreenStatus.set(gw.loadState(GREEN_PIN)), false ); + gw.send( BlueStatus.set(gw.loadState(BLUE_PIN)), false ); + + // Correct RGB show state for first start and load it (set to 'On' at first start) + gw.saveState(0, constrain((int8_t)gw.loadState(0), 0, 1)); + isShow=gw.loadState(0); + + // Send RGB show state to controler (request ack back: true/false) + gw.send( rgbShowState.set(isShow), false); + + if (isShow==1){Serial.println("RGB show running..."); } + Serial.println("Ready to receive messages..."); +} + +void loop() +{ + // Process incoming messages (like config and light state from controller) + gw.process(); + + // Run RGB show if is set + if (isShow==1) + { + rgbShow(); + analogWrite(RED_PIN, redval); + analogWrite(GREEN_PIN, greenval); + analogWrite(BLUE_PIN, blueval); + } +} + + +void incomingMessage(const MyMessage &message) +{ + if (message.isAck()) + { + Serial.println("Got ack from gateway"); + } + if (message.type == V_LIGHT) + { + // Incoming on/off command sent from controller ("1" or "0") + int lightState = message.getString()[0] == '1'; + + // if receive RGB Show On commands, start the show + if (message.sensor==0 && lightState==1){ rgbShowOn(); } + // if receive RGB Show Off commands, stop the show + else if (message.sensor==0 && lightState==0){ rgbShowOff(); } + + // if receive RGB switch On command + else if (lightState==1) + { + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.println(": On"); + Serial.print("Load from eeprom: "); + + if ( gw.loadState(message.sensor) == 0) + { + // Pick up last saved dimmer level from the eeprom + analogWrite(message.sensor, 255 * gw.loadState(10*message.sensor) / 100); + // Save loaded value to current + gw.saveState(message.sensor, gw.loadState(10*message.sensor)); + Serial.print(gw.loadState(10*message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + gw.send(Status.setSensor(message.sensor).set(gw.loadState(10*message.sensor)),false); + } + else + { + // Pick up last saved dimmer level from the eeprom + analogWrite(message.sensor, 255 * gw.loadState(message.sensor) / 100); + Serial.print(gw.loadState(message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + gw.send(Status.setSensor(message.sensor).set(gw.loadState(message.sensor)),false); + } + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } + // if recieve switch Off command + else if (lightState==0) + { + // Write output to 0 (Off) + analogWrite(message.sensor, 0); + // Save old value to eeprom if it'was not zero + if ( gw.loadState(message.sensor) != 0 ) + { + gw.saveState(10*message.sensor, constrain((int8_t)gw.loadState(message.sensor), 0, 100)); + } + // Save new value to eeprom + gw.saveState(message.sensor, 0); + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.print(": "); + Serial.println("Off"); + Serial.print("Store old value: "); + Serial.print(gw.loadState(10*message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + gw.send(Status.setSensor(message.sensor).set(gw.loadState(message.sensor)),false); + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } + } + else if (message.type == V_DIMMER) + { + uint8_t incomingDimmerStatus = message.getByte(); + // limits range of sensor values to between 0 and 100 + incomingDimmerStatus = constrain((int8_t)incomingDimmerStatus, 0, 100); + // Change Dimmer level + analogWrite(message.sensor, 255 * incomingDimmerStatus / 100); + //Save value to eeprom + gw.saveState(message.sensor, incomingDimmerStatus); + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.print(": "); + Serial.print(incomingDimmerStatus); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + gw.send(Status.setSensor(message.sensor).set(gw.loadState(message.sensor)),false); + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } +} + +void rgbShow() +{ + time = millis(); + redval = 128+250*cos(2*PI/300000*time); + greenval = 128+250*cos(2*PI/300000*time-222); + blueval = 128+250*cos(2*PI/300000*time-111); + // limits range of sensor values to between 0 and 255 + redval = constrain(redval, 0, 255); + greenval = constrain(greenval, 0, 255); + blueval = constrain(blueval, 0, 255); +} + +void rgbShowOn() +{ + // define show On + isShow=1; + // Save state + gw.saveState(0, 1); + // Write some debug info + Serial.println("Show must go on"); +} + +void rgbShowOff() +{ + // define show Off + isShow=0; + // Save state + gw.saveState(0, 0); + // Save RGB value to eeprom + gw.saveState(RED_PIN, 100 * redval / 255); + gw.saveState(GREEN_PIN, 100 * greenval / 255); + gw.saveState(BLUE_PIN, 100 * blueval / 255); + // Write some debug info + Serial.println("Stop the show"); + // Send actual RGB value and state to controler and request ack back (true/false) + Serial.println("Send eeprom value to controler"); + gw.send( RedStatus.set(gw.loadState(RED_PIN)), false ); + gw.send( GreenStatus.set(gw.loadState(GREEN_PIN)), false ); + gw.send( BlueStatus.set(gw.loadState(BLUE_PIN)), false ); + gw.send( rgbShowState.set(0), false); +} + +void rgbShowStop(int sensor) +{ + // define show Off + isShow=0; + // Save state + gw.saveState(0, 0); + // Write some debug info + Serial.println("Stop the show"); + // Send actual RGB value and state to controler and request ack back (true/false) + Serial.println("Send eeprom value to controler"); + if (sensor != RED_PIN) + { + gw.saveState(RED_PIN, 100 * redval / 255); + gw.send( RedStatus.set(gw.loadState(RED_PIN)), false ); + } + if (sensor != GREEN_PIN) + { + gw.saveState(GREEN_PIN, 100 * greenval / 255); + gw.send( GreenStatus.set(gw.loadState(GREEN_PIN)), false ); + } + if (sensor != BLUE_PIN) + { + gw.saveState(BLUE_PIN, 100 * blueval / 255); + gw.send( BlueStatus.set(gw.loadState(BLUE_PIN)), false ); + } + gw.send( rgbShowState.set(0), false); +} + + + diff --git a/libraries/MySensors/examples/RainGauge/RainGauge.ino b/libraries/MySensors/examples/RainGauge/RainGauge.ino index 475eb0c..59b84a6 100644 --- a/libraries/MySensors/examples/RainGauge/RainGauge.ino +++ b/libraries/MySensors/examples/RainGauge/RainGauge.ino @@ -123,7 +123,7 @@ volatile int wasTippedBuffer = 0; int rainSensorThreshold = 50; //default rain sensor sensitivity in hundredths. Will be overwritten with msgTrippedVar2. byte state = 0; byte oldState = -1; -int lastRainRate = 0; +unsigned int lastRainRate = 0; int lastMeasure = 0; boolean gotTime = false; byte lastHour; diff --git a/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino b/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino index a4c5944..6db9727 100644 --- a/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino +++ b/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino @@ -88,8 +88,8 @@ void loop() // If no time has been received yet, request it every 10 second from controller // When time has been received, request update every hour - if ((!timeReceived && now-lastRequest > 10*1000) - || (timeReceived && now-lastRequest > 60*1000*60)) { + if ((!timeReceived && (now-lastRequest) > (10UL*1000UL)) + || (timeReceived && (now-lastRequest) > (60UL*1000UL*60UL))) { // Request time from controller. Serial.println("requesting time"); gw.requestTime(receiveTime); diff --git a/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino b/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino index ec2a4ef..56374e5 100644 --- a/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino +++ b/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino @@ -298,7 +298,6 @@ boolean validateKnock(){ // reads the secret knock from EEPROM. (if any.) void readSecretKnock(){ byte reading; - int i; reading = gw.loadState(1); if (reading == eepromValid){ // only read EEPROM if the signature byte is correct. for (int i=0; i < maximumKnocks ;i++){ diff --git a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino index cae4b81..cb69354 100644 --- a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino +++ b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino @@ -71,7 +71,7 @@ MySigningAtsha204 signer; #endif MySensor gw(radio, hw, signer); #else -#error SecureActuator cannot possibly be secure without signing enabled +// WARNING! SecureActuator cannot possibly be secure without signing enabled MySensor gw(radio, hw); #endif @@ -85,7 +85,7 @@ void setup() // Fetch lock status for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) { // Register all locks to gw (they will be created as child devices) - gw.present(lock, S_LOCK, false); + gw.present(lock, S_LOCK, "SecureActuator", false); // Then set lock pins in output mode pinMode(pin, OUTPUT); // Set lock to last known state (using eeprom storage) diff --git a/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino b/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino new file mode 100644 index 0000000..b4bb4d7 --- /dev/null +++ b/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino @@ -0,0 +1,48 @@ +// Sensebender Micro board +// Simple blinking FW to test OTA updates + +#include +#include +#include "utility/SPIFlash.h" + +#define SketchName "Sensebender Blink" +#define SketchVersion "20150721" +#define NODE_ID AUTO +#define CHILD_ID_COUNTER 0 + +#define LED_PIN A2 +#define BLINK_INTERVAL 500 +#define REPORT_TIME 5000L + +unsigned long lastUpdate = 0; +boolean LED_STATUS = false; + +SPIFlash flash(8, 0x1F65); +MySensor gw; +MyMessage msgCounter(CHILD_ID_COUNTER, V_VAR1); + +void setup() { + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LED_STATUS); + + // repeater mode on + gw.begin(NULL,NODE_ID,true); + gw.sendSketchInfo(SketchName, SketchVersion); + + gw.present(CHILD_ID_COUNTER, S_CUSTOM,"Millis()"); + +} + +void loop() { + gw.wait(BLINK_INTERVAL); + LED_STATUS ^= true; + digitalWrite(LED_PIN, LED_STATUS); + + if (millis()-lastUpdate > REPORT_TIME) { + gw.send(msgCounter.set( millis() )); + lastUpdate = millis(); + } + +} + + diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino index cbf52d7..0566f3c 100644 --- a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -80,14 +80,7 @@ MyGateway gw(ctrlTransport, transport, hw /*, signer*/); void setup() { - gw.begin(NULL - #ifdef MY_INCLUSION_MODE_FEATURE - , INCLUSION_MODE_TIME - #ifdef MY_INCLUSION_BUTTON_FEATURE - , INCLUSION_MODE_PIN - #endif - #endif - ); + gw.begin(NULL); } diff --git a/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino b/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino index 92acedf..4c542df 100644 --- a/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino +++ b/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino @@ -237,7 +237,6 @@ void write_key(uint8_t* key) void dump_configuration() { - uint8_t config_word[4]; uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; uint8_t ret_code; @@ -682,6 +681,8 @@ void setup() uint8_t lockConfig = 0; uint8_t lockValue = 0; uint16_t crc; + (void)crc; + Serial.begin(115200); Serial.println(F("ATSHA204 personalization sketch for MySensors usage.")); diff --git a/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino b/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino index 2a2a108..2c3c74e 100644 --- a/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino +++ b/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino @@ -18,48 +18,168 @@ * ******************************* * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * * DESCRIPTION - * Example sketch sending soil moisture alarm to controller - * http://www.mysensors.org/build/moisture - */ - + * + * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil + * Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148 + * + * Gypsum sensor and calibration: + * DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html + * Built: Davis / Watermark 200SS + * http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product + * http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf + * cb (centibar) http://www.irrometer.com/basics.html + * 0-10 Saturated Soil. Occurs for a day or two after irrigation + * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range) + * 30-60 Usual range to irrigate or water (except heavy clay soils). + * 60-100 Usual range to irrigate heavy clay soils + * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution. + * + * Connection: + * D6, D7: alternative powering to avoid sensor degradation + * A0, A1: alternative resistance mesuring + * + * Based on: + * "Vinduino" portable soil moisture sensor code V3.00 + * Date December 31, 2012 + * Reinier van der Lee and Theodore Kaskalis + * www.vanderleevineyard.com + * Contributor: epierre +**/ + +// Copyright (C) 2015, Reinier van der Lee +// www.vanderleevineyard.com + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +#include // Conversion equation from resistance to % #include -#include +#include -#define DIGITAL_INPUT_SOIL_SENSOR 3 // Digital input did you attach your soil sensor. -#define INTERRUPT DIGITAL_INPUT_SOIL_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) -#define CHILD_ID 0 // Id of the sensor child +// Setting up format for reading 3 soil sensors +#define NUM_READS 10 // Number of sensor reads for filtering +#define CHILD_ID 0 -MySensor gw; -MyMessage msg(CHILD_ID, V_TRIPPED); -int lastSoilValue = -1; +MySensor gw; // Arduino initialization +MyMessage msg(CHILD_ID, V_LEVEL); +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) -void setup() -{ +long buffer[NUM_READS]; +int index; + +typedef struct { // Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) + int moisture; + long resistance; +} values; + +const long knownResistor = 4700; // Constant value of known resistor in Ohms + +int supplyVoltage; // Measured supply voltage +int sensorVoltage; // Measured sensor voltage + +values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered + +int i; // Simple index variable + +void setup() { + // initialize serial communications at 9600 bps: + Serial.begin(115200); gw.begin(); + gw.sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); + gw.present(CHILD_ID, S_HUM); + // initialize the digital pins as an output. + // Pin 6,7 is for sensor 1 + // initialize the digital pin as an output. + // Pin 6 is sense resistor voltage supply 1 + pinMode(6, OUTPUT); + + // initialize the digital pin as an output. + // Pin 7 is sense resistor voltage supply 2 + pinMode(7, OUTPUT); + - // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Soil Moisture Sensor", "1.0"); - // sets the soil sensor digital pin as input - pinMode(DIGITAL_INPUT_SOIL_SENSOR, INPUT); - // Register all sensors to gw (they will be created as child devices) - gw.present(CHILD_ID, S_MOTION); } - -void loop() -{ - // Read digital soil value - int soilValue = digitalRead(DIGITAL_INPUT_SOIL_SENSOR); // 1 = Not triggered, 0 = In soil with water - if (soilValue != lastSoilValue) { - Serial.println(soilValue); - gw.send(msg.set(soilValue==0?1:0)); // Send the inverse to gw as tripped should be when no water in soil - lastSoilValue = soilValue; + +void loop() { + + measure(6,7,1); + Serial.print ("\t"); + Serial.println (average()); + long read1 = average(); + + measure(7,6,0); + Serial.print ("\t"); + Serial.println (average()); + long read2= average(); + + long sensor1 = (read1 + read2)/2; + + Serial.print ("resistance bias =" ); + Serial.println (read1-read2); + Serial.print ("sensor bias compensated value = "); + Serial.println (sensor1); + Serial.println (); + + //send back the values + gw.send(msg.set((long int)ceil(sensor1))); + // delay until next measurement (msec) + gw.sleep(SLEEP_TIME); +} + +void measure (int phase_b, int phase_a, int analog_input) +{ + // read sensor, filter, and calculate resistance value + // Noise filter: median filter + + for (i=0; i= NUM_READS) index = 0; +} + +long average(){ + long sum = 0; + for (int i = 0; i < NUM_READS; i++){ + sum += buffer[i]; + } + return (long)(sum / NUM_READS); +} diff --git a/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino b/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino index 7dfe1b0..f546119 100644 --- a/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino +++ b/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino @@ -59,8 +59,8 @@ void loop() // If no time has been received yet, request it every 10 second from controller // When time has been received, request update every hour - if ((!timeReceived && now-lastRequest > 10*1000) - || (timeReceived && now-lastRequest > 60*1000*60)) { + if ((!timeReceived && (now-lastRequest) > (10UL*1000UL)) + || (timeReceived && (now-lastRequest) > (60UL*1000UL*60UL))) { // Request time from controller. Serial.println("requesting time"); gw.requestTime(receiveTime); diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino index 7a1946a..c5e9dec 100644 --- a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino @@ -77,17 +77,19 @@ int RESEND_DEBOUNCE = 2000; // Number of millisecons interval between sending of // Add your buttons here. Max is 5 if you still want time at the top. char *buttons[] = { - "Good Morning", - "Clean Up!", - "All Lights Off", - "Music On/Off" + (char *)"Good Morning", + (char *)"Clean Up!", + (char *)"All Lights Off", + (char *)"Music On/Off" }; const int buttonCount = sizeof(buttons)/sizeof(char *); const int padding = 10; const int topBarHeight = 60; -MySensor gw(17,18); +MyTransportNRF24 radio; // NRFRF24L01 radio driver +MyHwATMega328 hw; // Select AtMega328 hardware profile +MySensor gw(radio, hw); MyMessage on(CHILD_ID, V_SCENE_ON); MyMessage off(CHILD_ID, V_SCENE_OFF); @@ -142,13 +144,12 @@ void loop() unsigned long now = millis(); if (myTouch.dataAvailable()) { - unsigned long startPress = millis(); int pressedButton = myButtons.checkButtons(); if (pressedButton>=0) { - bool longPress = millis()-now>LONG_PRESS; + bool longPress = millis()-now>(unsigned long)LONG_PRESS; - if (pressedButton != lastPressedButton || now-lastPressedButtonTime > RESEND_DEBOUNCE) { + if (pressedButton != lastPressedButton || now-lastPressedButtonTime > (unsigned long)RESEND_DEBOUNCE) { if (longPress) { gw.send(off.set(pressedButton)); Serial.print("Long pressed: "); @@ -165,8 +166,8 @@ void loop() // If no time has been received yet, request it every 10 second from controller // When time has been received, request update every hour - if ((!timeReceived && now-lastRequest > 10*1000) - || (timeReceived && now-lastRequest > 60*1000*60)) { + if ((!timeReceived && now-lastRequest > (unsigned long)10*1000) + || (timeReceived && now-lastRequest > (unsigned long)60*1000*60)) { // Request time from controller. Serial.println("requesting time"); gw.requestTime(receiveTime); diff --git a/libraries/MySensors/examples/UVSensor/UVSensor.ino b/libraries/MySensors/examples/UVSensor/UVSensor.ino index a00ed7f..7db2aae 100644 --- a/libraries/MySensors/examples/UVSensor/UVSensor.ino +++ b/libraries/MySensors/examples/UVSensor/UVSensor.ino @@ -53,7 +53,7 @@ MyMessage uvMsg(CHILD_ID_UV, V_UV); unsigned long lastSend =0; float uvIndex; float lastUV = -1; -int uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170}; +uint16_t uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170}; void setup() { @@ -98,7 +98,7 @@ void loop() //Serial.println(uvIndex,2); //Send value to gateway if changed, or at least every 5 minutes - if ((uvIndex != lastUV)||(currentTime-lastSend >= 5*60*1000)) { + if ((uvIndex != lastUV)||(currentTime-lastSend >= 5UL*60UL*1000UL)) { lastSend=currentTime; gw.send(uvMsg.set(uvIndex,2)); lastUV = uvIndex; diff --git a/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino b/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino new file mode 100644 index 0000000..93db4c5 --- /dev/null +++ b/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino @@ -0,0 +1,94 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * 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 + * + * Vibration Sensor + * + * connect the sensor as follows : + * + * VCC >>> 5V + * S >>> D3 + * GND >>> GND + * + * Based on: http://www.dfrobot.com/wiki/index.php/DFRobot_Digital_Vibration_Sensor_V2_SKU:DFR0027 + * Contributor: epierre +**/ + + +#include +#include +#include + +#define CHILD_ID_VIBRATION 0 +#define VIBRATION_SENSOR_DIGITAL_PIN 3 +#define SensorLED 13 + +unsigned long SLEEP_TIME = 10*1000; // Sleep time between reads (in seconds) + +//VARIABLES +int val = 0; // variable to store the value coming from the sensor +float valVIBRATION =0.0; +float lastVIBRATION =0.0; +unsigned char state = 0; + +MySensor gw; +MyMessage vibrationMsg(CHILD_ID_VIBRATION, V_LEVEL); + +void setup() +{ + gw.begin(); + + // Send the sketch version information to the gateway and Controller + gw.sendSketchInfo("VIBRATION Sensor", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + gw.present(CHILD_ID_VIBRATION, S_VIBRATION); + + + pinMode(VIBRATION_SENSOR_DIGITAL_PIN, INPUT); + attachInterrupt(1, blink, FALLING);// Trigger the blink function when the falling edge is detected + pinMode(SensorLED, OUTPUT); +} + +void loop() +{ + + if(state>=40){ // basically below 40 so ignire basic level + gw.send(vibrationMsg.set(int(state))); + state = 0; + digitalWrite(SensorLED,HIGH); + } else { + state = 0; + digitalWrite(SensorLED,LOW); + } + + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + delay(1000); //delay to allow serial to fully print before sleep + + gw.sleep(SLEEP_TIME); //sleep for: sleepTime +} + +void blink()//Interrupts function +{ + state++; +} diff --git a/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino index d676d6c..81c0c8e 100644 --- a/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino +++ b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino @@ -20,6 +20,7 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad + * Version 1.1 - GizMoCuz * * DESCRIPTION * Use this sensor to measure volume and flow of your house watermeter. @@ -33,8 +34,8 @@ * http://www.mysensors.org/build/pulse_water */ -#include #include +#include #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) @@ -47,7 +48,7 @@ #define CHILD_ID 1 // Id of the sensor child -unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. +unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. MySensor gw; MyMessage flowMsg(CHILD_ID,V_FLOW); @@ -72,8 +73,11 @@ void setup() { gw.begin(incomingMessage); + // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) + pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); + // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Water Meter", "1.2"); + gw.sendSketchInfo("Water Meter", "1.1"); // Register this device as Waterflow sensor gw.present(CHILD_ID, S_WATER); @@ -85,7 +89,7 @@ void setup() lastSend = lastPulse = millis(); - attachInterrupt(SENSOR_INTERRUPT, onPulse, RISING); + attachInterrupt(SENSOR_INTERRUPT, onPulse, FALLING); } @@ -93,7 +97,7 @@ void loop() { gw.process(); unsigned long currentTime = millis(); - + // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY)) { @@ -124,7 +128,7 @@ void loop() } // Pulse count has changed - if (pulseCount != oldPulseCount) { + if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) { oldPulseCount = pulseCount; Serial.print("pulsecount:"); @@ -133,7 +137,7 @@ void loop() gw.send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1 double volume = ((double)pulseCount/((double)PULSE_FACTOR)); - if (volume != oldvolume) { + if ((volume != oldvolume)||(!SLEEP_MODE)) { oldvolume = volume; Serial.print("volume:"); @@ -152,6 +156,7 @@ void incomingMessage(const MyMessage &message) { if (message.type==V_VAR1) { unsigned long gwPulseCount=message.getULong(); pulseCount += gwPulseCount; + flow=oldflow=0; Serial.print("Received last pulse count from gw:"); Serial.println(pulseCount); pcReceived = true; @@ -178,4 +183,3 @@ void onPulse() } pulseCount++; } - diff --git a/libraries/PN532/PN532.cpp b/libraries/PN532/PN532.cpp index c6c5490..a9ab4c6 100644 --- a/libraries/PN532/PN532.cpp +++ b/libraries/PN532/PN532.cpp @@ -61,6 +61,7 @@ void PN532::begin() /**************************************************************************/ void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes) { + (void)data; for (uint8_t i = 0; i < numBytes; i++) { DMSG("0x"); DMSG_HEX(data[i]); @@ -86,11 +87,11 @@ void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes) } DMSG(" "); for (uint8_t i = 0; i < numBytes; i++) { - char c = data[i]; + uint8_t c = data[i]; if (c <= 0x1f || c > 0x7f) { DMSG('.'); } else { - DMSG(c); + DMSG((char)c); } } @@ -548,7 +549,7 @@ uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIden // in NDEF records // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) - uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, (uint8_t)(len + 5), 0xD1, 0x01, (uint8_t)(len + 1), 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -653,6 +654,7 @@ uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer) bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) { uint8_t i; + (void)i; pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE; pn532_packetbuffer[1] = inListedTag; diff --git a/libraries/PN532/llcp.cpp b/libraries/PN532/llcp.cpp index ad00236..68da733 100644 --- a/libraries/PN532/llcp.cpp +++ b/libraries/PN532/llcp.cpp @@ -37,6 +37,7 @@ int8_t LLCP::activate(uint16_t timeout) int8_t LLCP::waitForConnection(uint16_t timeout) { uint8_t type; + (void)timeout; sequence = 0; @@ -76,6 +77,7 @@ int8_t LLCP::waitForConnection(uint16_t timeout) int8_t LLCP::waitForDisconnection(uint16_t timeout) { uint8_t type; + (void)timeout; // Get DISC PDU DMSG("wait for a DISC PDU\n"); @@ -113,6 +115,7 @@ int8_t LLCP::waitForDisconnection(uint16_t timeout) int8_t LLCP::connect(uint16_t timeout) { uint8_t type; + (void)timeout; sequence = 0; @@ -165,6 +168,7 @@ int8_t LLCP::connect(uint16_t timeout) int8_t LLCP::disconnect(uint16_t timeout) { uint8_t type; + (void)timeout; // try to get a SYMM PDU if (2 > link.read(headerBuf, headerBufLen)) { @@ -207,7 +211,6 @@ int8_t LLCP::disconnect(uint16_t timeout) bool LLCP::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) { - uint8_t type; uint8_t buf[3]; if (2 != link.read(buf, sizeof(buf))) { diff --git a/libraries/PN532/snep.cpp b/libraries/PN532/snep.cpp index 650532d..f690878 100644 --- a/libraries/PN532/snep.cpp +++ b/libraries/PN532/snep.cpp @@ -79,7 +79,7 @@ int16_t SNEP::read(uint8_t *buf, uint8_t len, uint16_t timeout) } // check message's length - uint32_t length = (buf[2] << 24) + (buf[3] << 16) + (buf[4] << 8) + buf[5]; + uint32_t length = ((uint32_t)buf[2] << 24) + ((uint32_t)buf[3] << 16) + (buf[4] << 8) + buf[5]; // length should not be more than 244 (header + body < 255, header = 6 + 3 + 2) if (length > (status - 6)) { DMSG("The SNEP message is too large\n"); diff --git a/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp index 1d2b8a0..b512121 100644 --- a/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp +++ b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp @@ -78,15 +78,8 @@ uint8_t PWF_AS3935::_sing_reg_read(uint8_t RegAdd) void PWF_AS3935::_sing_reg_write(uint8_t RegAdd, uint8_t DataMask, uint8_t RegData) { - // start by reading original register data (only modifying what we need to) - uint8_t OrigRegData = _sing_reg_read(RegAdd); - - // calculate new register data... 'delete' old targeted data, replace with new data - // note: 'DataMask' must be bits targeted for replacement - // add'l note: this function does NOT shift values into the proper place... they need to be there already - uint8_t NewRegData = ((OrigRegData & ~DataMask) | (RegData & DataMask)); - - // now configure and write the updated register value + (void)DataMask; + // Configure and write the updated register value digitalWrite(_cs, LOW); // set pin low to start talking to IC // next pack command byte, send AS3935.... structure is shown below // MODE Register Address/Direct Cmd @@ -228,7 +221,7 @@ uint32_t PWF_AS3935::AS3935_GetStrikeEnergyRaw(void) { uint32_t nrgy_raw = ((_sing_reg_read(0x06) & 0x1F) << 8); // MMSB, shift 8 bits left, make room for MSB nrgy_raw |= _sing_reg_read(0x05); // read MSB - nrgy_raw <= 8; // shift 8 bits left, make room for LSB + nrgy_raw <<= 8; // shift 8 bits left, make room for LSB nrgy_raw |= _sing_reg_read(0x04); // read LSB, add to others return nrgy_raw; diff --git a/libraries/PinChangeInt/PinChangeInt.h b/libraries/PinChangeInt/PinChangeInt.h index 807b20d..6ccd1df 100644 --- a/libraries/PinChangeInt/PinChangeInt.h +++ b/libraries/PinChangeInt/PinChangeInt.h @@ -474,7 +474,8 @@ void PCintPort::detachInterrupt(uint8_t arduinoPin) // there isn't really a good way to back-map ports and masks to pins. void PCintPort::PCint() { uint8_t thisChangedPin; //MIKE - + (void)thisChangedPin; + #ifdef FLASH if (*led_port & led_mask) *led_port&=not_led_mask; else *led_port|=led_mask; diff --git a/libraries/PubSubClient/CHANGES.txt b/libraries/PubSubClient/CHANGES.txt new file mode 100755 index 0000000..8688011 --- /dev/null +++ b/libraries/PubSubClient/CHANGES.txt @@ -0,0 +1,47 @@ +1.9 + * Do not split MQTT packets over multiple calls to _client->write() + * API change: All constructors now require an instance of Client + to be passed in. + * Fixed example to match 1.8 api changes - dpslwk + * Added username/password support - WilHall + * Added publish_P - publishes messages from PROGMEM - jobytaffey + +1.8 + * KeepAlive interval is configurable in PubSubClient.h + * Maximum packet size is configurable in PubSubClient.h + * API change: Return boolean rather than int from various functions + * API change: Length parameter in message callback changed + from int to unsigned int + * Various internal tidy-ups around types +1.7 + * Improved keepalive handling + * Updated to the Arduino-1.0 API +1.6 + * Added the ability to publish a retained message + +1.5 + * Added default constructor + * Fixed compile error when used with arduino-0021 or later + +1.4 + * Fixed connection lost handling + +1.3 + * Fixed packet reading bug in PubSubClient.readPacket + +1.2 + * Fixed compile error when used with arduino-0016 or later + + +1.1 + * Reduced size of library + * Added support for Will messages + * Clarified licensing - see LICENSE.txt + + +1.0 + * Only Quality of Service (QOS) 0 messaging is supported + * The maximum message size, including header, is 128 bytes + * The keepalive interval is set to 30 seconds + * No support for Will messages + diff --git a/libraries/PubSubClient/LICENSE.txt b/libraries/PubSubClient/LICENSE.txt new file mode 100755 index 0000000..f512cba --- /dev/null +++ b/libraries/PubSubClient/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2012 Nicholas O'Leary + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libraries/PubSubClient/PubSubClient.cpp b/libraries/PubSubClient/PubSubClient.cpp new file mode 100755 index 0000000..dbb538a --- /dev/null +++ b/libraries/PubSubClient/PubSubClient.cpp @@ -0,0 +1,427 @@ +/* + PubSubClient.cpp - A simple client for MQTT. + Nicholas O'Leary + http://knolleary.net +*/ + +#include "PubSubClient.h" +#include + +PubSubClient::PubSubClient() { + this->_client = NULL; + this->stream = NULL; +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; + this->callback = callback; + this->ip = ip; + this->port = port; + this->domain = NULL; + this->stream = NULL; +} + +PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; + this->callback = callback; + this->domain = domain; + this->port = port; + this->stream = NULL; +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client, Stream& stream) { + this->_client = &client; + this->callback = callback; + this->ip = ip; + this->port = port; + this->domain = NULL; + this->stream = &stream; +} + +PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client, Stream& stream) { + this->_client = &client; + this->callback = callback; + this->domain = domain; + this->port = port; + this->stream = &stream; +} + +boolean PubSubClient::connect(char *id) { + return connect(id,NULL,NULL,0,0,0,0); +} + +boolean PubSubClient::connect(char *id, char *user, char *pass) { + return connect(id,user,pass,0,0,0,0); +} + +boolean PubSubClient::connect(char *id, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) +{ + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); +} + +boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) { + if (!connected()) { + int result = 0; + + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } + + if (result) { + nextMsgId = 1; + uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p',MQTTPROTOCOLVERSION}; + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + unsigned int j; + for (j = 0;j<9;j++) { + buffer[length++] = d[j]; + } + + uint8_t v; + if (willTopic) { + v = 0x06|(willQos<<3)|(willRetain<<5); + } else { + v = 0x02; + } + + if(user != NULL) { + v = v|0x80; + + if(pass != NULL) { + v = v|(0x80>>1); + } + } + + buffer[length++] = v; + + buffer[length++] = ((MQTT_KEEPALIVE) >> 8); + buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + length = writeString(id,buffer,length); + if (willTopic) { + length = writeString(willTopic,buffer,length); + length = writeString(willMessage,buffer,length); + } + + if(user != NULL) { + length = writeString(user,buffer,length); + if(pass != NULL) { + length = writeString(pass,buffer,length); + } + } + + write(MQTTCONNECT,buffer,length-5); + + lastInActivity = lastOutActivity = millis(); + + while (!_client->available()) { + unsigned long t = millis(); + if (t-lastInActivity > MQTT_KEEPALIVE*1000UL) { + _client->stop(); + return false; + } + } + uint8_t llen; + uint16_t len = readPacket(&llen); + + if (len == 4 && buffer[3] == 0) { + lastInActivity = millis(); + pingOutstanding = false; + return true; + } + } + _client->stop(); + } + return false; +} + +uint8_t PubSubClient::readByte() { + while(!_client->available()) {} + return _client->read(); +} + +uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { + uint16_t len = 0; + buffer[len++] = readByte(); + bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + uint32_t multiplier = 1; + uint16_t length = 0; + uint8_t digit = 0; + uint16_t skip = 0; + uint8_t start = 0; + + do { + digit = readByte(); + buffer[len++] = digit; + length += (digit & 127) * multiplier; + multiplier *= 128; + } while ((digit & 128) != 0); + *lengthLength = len-1; + + if (isPublish) { + // Read in topic length to calculate bytes to skip over for Stream writing + buffer[len++] = readByte(); + buffer[len++] = readByte(); + skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + start = 2; + if (buffer[0]&MQTTQOS1) { + // skip message id + skip += 2; + } + } + + for (uint16_t i = start;istream) { + if (isPublish && len-*lengthLength-2>skip) { + this->stream->write(digit); + } + } + if (len < MQTT_MAX_PACKET_SIZE) { + buffer[len] = digit; + } + len++; + } + + if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + len = 0; // This will cause the packet to be ignored. + } + + return len; +} + +boolean PubSubClient::loop() { + if (connected()) { + unsigned long t = millis(); + if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if (pingOutstanding) { + _client->stop(); + return false; + } else { + buffer[0] = MQTTPINGREQ; + buffer[1] = 0; + _client->write(buffer,2); + lastOutActivity = t; + lastInActivity = t; + pingOutstanding = true; + } + } + if (_client->available()) { + uint8_t llen; + uint16_t len = readPacket(&llen); + uint16_t msgId = 0; + uint8_t *payload; + if (len > 0) { + lastInActivity = t; + uint8_t type = buffer[0]&0xF0; + if (type == MQTTPUBLISH) { + if (callback) { + uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; + char topic[tl+1]; + for (uint16_t i=0;i0 + if ((buffer[0]&0x06) == MQTTQOS1) { + msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; + payload = buffer+llen+3+tl+2; + callback(topic,payload,len-llen-3-tl-2); + + buffer[0] = MQTTPUBACK; + buffer[1] = 2; + buffer[2] = (msgId >> 8); + buffer[3] = (msgId & 0xFF); + _client->write(buffer,4); + lastOutActivity = t; + + } else { + payload = buffer+llen+3+tl; + callback(topic,payload,len-llen-3-tl); + } + } + } else if (type == MQTTPINGREQ) { + buffer[0] = MQTTPINGRESP; + buffer[1] = 0; + _client->write(buffer,2); + } else if (type == MQTTPINGRESP) { + pingOutstanding = false; + } + } + } + return true; + } + return false; +} + +boolean PubSubClient::publish(char* topic, char* payload) { + return publish(topic,(uint8_t*)payload,strlen(payload),false); +} + +boolean PubSubClient::publish(char* topic, uint8_t* payload, unsigned int plength) { + return publish(topic, payload, plength, false); +} + +boolean PubSubClient::publish(char* topic, uint8_t* payload, unsigned int plength, boolean retained) { + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + length = writeString(topic,buffer,length); + uint16_t i; + for (i=0;i 0) { + digit |= 0x80; + } + buffer[pos++] = digit; + llen++; + } while(len>0); + + pos = writeString(topic,buffer,pos); + + rc += _client->write(buffer,pos); + + for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); + } + + lastOutActivity = millis(); + + return rc == tlen + 4 + plength; +} + +boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { + uint8_t lenBuf[4]; + uint8_t llen = 0; + uint8_t digit; + uint8_t pos = 0; + uint8_t rc; + uint8_t len = length; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + lenBuf[pos++] = digit; + llen++; + } while(len>0); + + buf[4-llen] = header; + for (int i=0;iwrite(buf+(4-llen),length+1+llen); + + lastOutActivity = millis(); + return (rc == 1+llen+length); +} + +boolean PubSubClient::subscribe(char* topic) { + return subscribe(topic, 0); +} + +boolean PubSubClient::subscribe(char* topic, uint8_t qos) { + if (qos > 1) + return false; + + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +boolean PubSubClient::unsubscribe(char* topic) { + if (connected()) { + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +void PubSubClient::disconnect() { + buffer[0] = MQTTDISCONNECT; + buffer[1] = 0; + _client->write(buffer,2); + _client->stop(); + lastInActivity = lastOutActivity = millis(); +} + +uint16_t PubSubClient::writeString(char* string, uint8_t* buf, uint16_t pos) { + char* idp = string; + uint16_t i = 0; + pos += 2; + while (*idp) { + buf[pos++] = *idp++; + i++; + } + buf[pos-i-2] = (i >> 8); + buf[pos-i-1] = (i & 0xFF); + return pos; +} + + +boolean PubSubClient::connected() { + boolean rc; + if (_client == NULL ) { + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) _client->stop(); + } + return rc; +} + diff --git a/libraries/PubSubClient/PubSubClient.h b/libraries/PubSubClient/PubSubClient.h new file mode 100755 index 0000000..f2faff8 --- /dev/null +++ b/libraries/PubSubClient/PubSubClient.h @@ -0,0 +1,81 @@ +/* + PubSubClient.h - A simple client for MQTT. + Nicholas O'Leary + http://knolleary.net +*/ + +#ifndef PubSubClient_h +#define PubSubClient_h + +#include +#include "Client.h" +#include "Stream.h" + +// MQTT_MAX_PACKET_SIZE : Maximum packet size +#define MQTT_MAX_PACKET_SIZE 128 + +// MQTT_KEEPALIVE : keepAlive interval in Seconds +#define MQTT_KEEPALIVE 15 + +#define MQTTPROTOCOLVERSION 3 +#define MQTTCONNECT 1 << 4 // Client request to connect to Server +#define MQTTCONNACK 2 << 4 // Connect Acknowledgment +#define MQTTPUBLISH 3 << 4 // Publish message +#define MQTTPUBACK 4 << 4 // Publish Acknowledgment +#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) +#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) +#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) +#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request +#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment +#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request +#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment +#define MQTTPINGREQ 12 << 4 // PING Request +#define MQTTPINGRESP 13 << 4 // PING Response +#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting +#define MQTTReserved 15 << 4 // Reserved + +#define MQTTQOS0 (0 << 1) +#define MQTTQOS1 (1 << 1) +#define MQTTQOS2 (2 << 1) + +class PubSubClient { +private: + Client* _client; + uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint16_t nextMsgId; + unsigned long lastOutActivity; + unsigned long lastInActivity; + bool pingOutstanding; + void (*callback)(char*,uint8_t*,unsigned int); + uint16_t readPacket(uint8_t*); + uint8_t readByte(); + boolean write(uint8_t header, uint8_t* buf, uint16_t length); + uint16_t writeString(char* string, uint8_t* buf, uint16_t pos); + uint8_t *ip; + char* domain; + uint16_t port; + Stream* stream; +public: + PubSubClient(); + PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); + PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client, Stream&); + PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); + PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client, Stream&); + boolean connect(char *); + boolean connect(char *, char *, char *); + boolean connect(char *, char *, uint8_t, uint8_t, char *); + boolean connect(char *, char *, char *, char *, uint8_t, uint8_t, char*); + void disconnect(); + boolean publish(char *, char *); + boolean publish(char *, uint8_t *, unsigned int); + boolean publish(char *, uint8_t *, unsigned int, boolean); + boolean publish_P(char *, uint8_t *, unsigned int, boolean); + boolean subscribe(char *); + boolean subscribe(char *, uint8_t qos); + boolean unsubscribe(char *); + boolean loop(); + boolean connected(); +}; + + +#endif diff --git a/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino b/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino new file mode 100755 index 0000000..c8a519a --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino @@ -0,0 +1,39 @@ +/* + Basic MQTT example with Authentication + + - connects to an MQTT server, providing username + and password + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient", "testuser", "testpass")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino b/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino new file mode 100755 index 0000000..72276cd --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino @@ -0,0 +1,38 @@ +/* + Basic MQTT example + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino new file mode 100755 index 0000000..ece5c2e --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino @@ -0,0 +1,61 @@ +/* + Publishing in the callback + + - connects to an MQTT server + - subscribes to the topic "inTopic" + - when a message is received, republishes it to "outTopic" + + This example shows how to publish messages within the + callback function. The callback function header needs to + be declared before the PubSubClient constructor and the + actual callback defined afterwards. + This ensures the client reference in the callback function + is valid. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +// Callback function header +void callback(char* topic, byte* payload, unsigned int length); + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +// Callback function +void callback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + + // Allocate the correct amount of memory for the payload copy + byte* p = (byte*)malloc(length); + // Copy the payload to the new buffer + memcpy(p,payload,length); + client.publish("outTopic", p, length); + // Free the memory + free(p); +} + +void setup() +{ + + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino b/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino new file mode 100755 index 0000000..a416ee2 --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino @@ -0,0 +1,58 @@ +/* + Example of using a Stream object to store the message payload + + Uses SRAM library: https://github.com/ennui2342/arduino-sram + but could use any Stream based class such as SD + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +SRAM sram(4, SRAM_1024); + +void callback(char* topic, byte* payload, unsigned int length) { + sram.seek(1); + + // do something with the message + for(uint8_t i=0; i=0; zz--) @@ -1080,7 +1080,7 @@ void UTFT::printNumF(double num, byte dec, int x, int y, char divider, int lengt if (divider != '.') { - for (int i=0; i= buttons[i].pos_x) and (touch_x <= (buttons[i].pos_x + buttons[i].width)) and (touch_y >= buttons[i].pos_y) and (touch_y <= (buttons[i].pos_y + buttons[i].height))) + if ((touch_x >= (int)buttons[i].pos_x) and (touch_x <= (int)(buttons[i].pos_x + buttons[i].width)) and (touch_y >= (int)buttons[i].pos_y) and (touch_y <= (int)(buttons[i].pos_y + buttons[i].height))) result = i; } } diff --git a/libraries/sha204/sha204_library.cpp b/libraries/sha204/sha204_library.cpp index 8e43890..8728096 100644 --- a/libraries/sha204/sha204_library.cpp +++ b/libraries/sha204/sha204_library.cpp @@ -791,6 +791,19 @@ uint8_t atsha204Class::sha204m_check_parameters(uint8_t op_code, uint8_t param1, return SHA204_SUCCESS; #else + (void)rx_size; + (void)tx_size; + (void)tx_buffer; + (void)rx_buffer; + (void)param1; + (void)param2; + (void)data1; + (void)data2; + (void)data3; + (void)datalen1; + (void)datalen2; + (void)datalen3; + (void)op_code; return SHA204_SUCCESS; #endif }