diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 29bce20..26326dc 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -142,6 +142,8 @@ #include "core/MyLeds.h" #endif +#include "core/MyIndication.cpp" + // INCLUSION MODE #if defined(MY_INCLUSION_MODE_FEATURE) diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index 8126bc6..b848de1 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -151,6 +151,8 @@ bool gatewayTransportSend(MyMessage &message) bool ret = true; char *_ethernetMsg = protocolFormat(message); + setIndication(INDICATION_GW_TX); + _w5100_spi_en(true); #if defined(MY_CONTROLLER_IP_ADDRESS) #if defined(MY_USE_UDP) @@ -267,6 +269,7 @@ bool gatewayTransportAvailable() if (packet_size) { //debug(PSTR("UDP packet available. Size:%d\n"), packet_size); + setIndication(INDICATION_GW_RX); #if defined(MY_GATEWAY_ESP8266) _ethernetServer.read(inputString[0].string, MY_GATEWAY_MAX_RECEIVE_LENGTH); inputString[0].string[packet_size] = 0; @@ -316,6 +319,7 @@ bool gatewayTransportAvailable() // Loop over clients connect and read available data for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { if (_readFromClient(i)) { + setIndication(INDICATION_GW_RX); _w5100_spi_en(false); return true; } @@ -341,6 +345,7 @@ bool gatewayTransportAvailable() client.stop(); } else { if (_readFromClient()) { + setIndication(INDICATION_GW_RX); _w5100_spi_en(false); return true; } diff --git a/libraries/MySensors/core/MyGatewayTransportMQTTClient.cpp b/libraries/MySensors/core/MyGatewayTransportMQTTClient.cpp index 326d349..2ab0308 100644 --- a/libraries/MySensors/core/MyGatewayTransportMQTTClient.cpp +++ b/libraries/MySensors/core/MyGatewayTransportMQTTClient.cpp @@ -59,6 +59,8 @@ MyMessage _mqttMsg; bool gatewayTransportSend(MyMessage &message) { if (!_client.connected()) return false; + setIndication(INDICATION_GW_TX); + snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR(MY_MQTT_PUBLISH_TOPIC_PREFIX "/%d/%d/%d/%d/%d"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type); debug(PSTR("Sending message on topic: %s\n"), _fmtBuffer); return _client.publish(_fmtBuffer, message.getString(_convBuffer)); diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.cpp b/libraries/MySensors/core/MyGatewayTransportSerial.cpp index 85bb6a3..e3ea5fb 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.cpp +++ b/libraries/MySensors/core/MyGatewayTransportSerial.cpp @@ -31,6 +31,7 @@ MyMessage _serialMsg; bool gatewayTransportSend(MyMessage &message) { + setIndication(INDICATION_GW_TX); MY_SERIALDEVICE.print(protocolFormat(message)); // Serial print is always successful return true; diff --git a/libraries/MySensors/core/MyIndication.cpp b/libraries/MySensors/core/MyIndication.cpp new file mode 100644 index 0000000..9b4fd89 --- /dev/null +++ b/libraries/MySensors/core/MyIndication.cpp @@ -0,0 +1,42 @@ +/** + * 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-2016 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 "MyIndication.h" +#ifdef MY_LEDS_BLINKING_FEATURE +#include "MyLeds.h" +#endif + +void setIndication( const indication_t ind ) +{ +#ifdef MY_LEDS_BLINKING_FEATURE + if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) + { + ledsBlinkTx(1); + } else if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) + { + ledsBlinkRx(1); + } else if (ind > INDICATION_ERR_START) + { + // Number of blinks indicates which error occurred. + ledsBlinkErr(ind-INDICATION_ERR_START); + } +#endif + if (indication) + indication(ind); +} diff --git a/libraries/MySensors/core/MyIndication.h b/libraries/MySensors/core/MyIndication.h new file mode 100644 index 0000000..342fc1d --- /dev/null +++ b/libraries/MySensors/core/MyIndication.h @@ -0,0 +1,72 @@ +/** + * 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-2016 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 MyIndication_h +#define MyIndication_h + +/** + * Indication type + */ +typedef enum { + INDICATION_TX = 0, //!< Sent a message. + INDICATION_RX, //!< Received a message. + + INDICATION_GW_TX, //!< Gateway transmit message. + INDICATION_GW_RX, //!< Gateway receive message. + + INDICATION_FIND_PARENT, //!< Start finding parent node. + INDICATION_GOT_PARENT, //!< Found parent node. + INDICATION_REQ_NODEID, //!< Request node ID. + INDICATION_GOT_NODEID, //!< Got a node ID. + INDICATION_REBOOT, //!< Rebooting node. + INDICATION_PRESENT, //!< Presenting node to gateway. + INDICATION_CLEAR_ROUTING, //!< Clear rrouting table requested. + INDICATION_SLEEP, //!< Node goes to sleep. + INDICATION_WAKEUP, //!< Node just woke from sleep. + INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process. + INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data. + + INDICATION_ERR_START = 100, + INDICATION_ERR_TX, //!< Failed to transmit message. + INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure. + INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node. + INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID. + INDICATION_ERR_SIGN, //!< Error signing. + INDICATION_ERR_VERSION, //!< Protocol version mismatch. + INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken. + INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure. + INDICATION_ERR_LOCKED, //!< Node is locked. + INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure. + INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout. + INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch. + INDICATION_ERR_END +} indication_t; + +/** + * Function which is called when something changes about the internal state of MySensors. + * @param ind Event indication of what happened. + */ +void setIndication( const indication_t ind ); + +/** + * Allow user to define their own indication handler. + */ +void indication( const indication_t ) __attribute__((weak)); + +#endif diff --git a/libraries/MySensors/core/MyLeds.cpp b/libraries/MySensors/core/MyLeds.cpp index 10ce2f5..fd0a541 100644 --- a/libraries/MySensors/core/MyLeds.cpp +++ b/libraries/MySensors/core/MyLeds.cpp @@ -19,81 +19,64 @@ #include "MyLeds.h" +#define LED_ON_OFF_RATIO (4) // Power of 2 please +#define LED_PROCESS_INTERVAL_MS (MY_DEFAULT_LED_BLINK_PERIOD/LED_ON_OFF_RATIO) + // 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 _blink_next_time; +static uint8_t countRx; +static uint8_t countTx; +static uint8_t countErr; +static unsigned long prevTime = millis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. + + +inline void ledsInit() +{ + // initialize counters + countRx = 0; + countTx = 0; + countErr = 0; -inline void ledsInit() { // Setup led pins - pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); - pinMode(MY_DEFAULT_TX_LED_PIN, 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 - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - - // initialize counters - _countRx = 0; - _countTx = 0; - _countErr = 0; + ledsProcess(); } -inline void ledsProcess() { +void ledsProcess() { // Just return if it is not the time... - // http://playground.arduino.cc/Code/TimingRollover - if ((long)(hwMillis() - _blink_next_time) < 0) + if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) return; - else - _blink_next_time = hwMillis() + MY_DEFAULT_LED_BLINK_PERIOD; - // do the actual blinking - if(_countRx && _countRx != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); - } - else if(!_countRx) { - // switching off - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - } - if(_countRx != 255) - --_countRx; + prevTime += LED_PROCESS_INTERVAL_MS; - if(_countTx && _countTx != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); - } - else if(!_countTx) { - // switching off - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - } - if(_countTx != 255) - --_countTx; + uint8_t state; - if(_countErr && _countErr != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); - } - else if(!_countErr) { - // switching off - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - } - if(_countErr != 255) - --_countErr; + // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] + // until the counter becomes 0. + state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); + if (countRx) --countRx; + + state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); + if (countTx) --countTx; + + state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); + if (countErr) --countErr; } void ledsBlinkRx(uint8_t cnt) { - if(_countRx == 255) { _countRx = cnt; } + if (!countRx) { countRx = cnt*LED_ON_OFF_RATIO; } } void ledsBlinkTx(uint8_t cnt) { - if(_countTx == 255) { _countTx = cnt; } + if(!countTx) { countTx = cnt*LED_ON_OFF_RATIO; } } void ledsBlinkErr(uint8_t cnt) { - if(_countErr == 255) { _countErr = cnt; } + if(!countErr) { countErr = cnt*LED_ON_OFF_RATIO; } } diff --git a/libraries/MySensors/core/MyOTAFirmwareUpdate.cpp b/libraries/MySensors/core/MyOTAFirmwareUpdate.cpp index 8c4d72e..419802f 100644 --- a/libraries/MySensors/core/MyOTAFirmwareUpdate.cpp +++ b/libraries/MySensors/core/MyOTAFirmwareUpdate.cpp @@ -34,6 +34,7 @@ inline void firmwareOTAUpdateRequest() { unsigned long enter = hwMillis(); if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) { if (!_fwRetry) { + setIndication(INDICATION_ERR_FW_TIMEOUT); debug(PSTR("fw upd fail\n")); // Give up. We have requested MY_OTA_RETRY times without any packet in return. _fwUpdateOngoing = false; @@ -57,11 +58,13 @@ inline bool firmwareOTAUpdateProcess() { NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data; // compare with current node configuration, if they differ, start fw fetch process if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) { + setIndication(INDICATION_FW_START); debug(PSTR("fw update\n")); // copy new FW config memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); // Init flash if (!_flash.initialize()) { + setIndication(INDICATION_ERR_FW_FLASH_INIT); debug(PSTR("flash init fail\n")); _fwUpdateOngoing = false; } else { @@ -81,6 +84,7 @@ inline bool firmwareOTAUpdateProcess() { } else if (_msg.type == ST_FIRMWARE_RESPONSE) { if (_fwUpdateOngoing) { // Save block to flash + setIndication(INDICATION_FW_RX); debug(PSTR("fw block %d\n"), _fwBlock); // extract FW block ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data; @@ -102,6 +106,7 @@ inline bool firmwareOTAUpdateProcess() { hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); hwReboot(); } else { + setIndication(INDICATION_ERR_FW_CHECKSUM); debug(PSTR("fw checksum fail\n")); } } diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index b2040c1..847b9ec 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -65,6 +65,9 @@ void _infiniteLoop() { #if defined(MY_GATEWAY_ESP8266) yield(); #endif + #if defined (MY_LEDS_BLINKING_FEATURE) + ledsProcess(); + #endif } } @@ -79,6 +82,10 @@ void _begin() { debug(PSTR("Starting " MY_NODE_TYPE " (" MY_CAPABILITIES ", " LIBRARY_VERSION ")\n")); + #if defined(MY_LEDS_BLINKING_FEATURE) + ledsInit(); + #endif + signerInit(); #if defined(MY_RADIO_FEATURE) @@ -86,6 +93,7 @@ void _begin() { // Setup radio if (!transportInit()) { + setIndication(INDICATION_ERR_INIT_TRANSPORT); debug(PSTR("Radio init failed. Check wiring.\n")); // Nothing more we can do _infiniteLoop(); @@ -101,6 +109,7 @@ void _begin() { // initialize the transport driver if (!gatewayTransportInit()) { + setIndication(INDICATION_ERR_INIT_GWTRANSPORT); debug(PSTR("Transport driver init fail\n")); // Nothing more we can do _infiniteLoop(); @@ -108,11 +117,6 @@ void _begin() { #endif - - #if defined(MY_LEDS_BLINKING_FEATURE) - ledsInit(); - #endif - // Read latest received controller configuration from EEPROM hwReadConfigBlock((void*)&_cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); if (_cc.isMetric == 0xff) { @@ -141,6 +145,7 @@ void _begin() { // We don't actually know the distance to gw here. Let's pretend it is 1. // If the current node is also repeater, be aware of this. _nc.distance = 1; + setIndication(INDICATION_GOT_PARENT); } else if (!isValidParent(_nc.parentNodeId)) { // Auto find parent, but parent in eeprom is invalid. Try find one. transportFindParentNode(); @@ -151,6 +156,7 @@ void _begin() { _nc.nodeId = MY_NODE_ID; // Save static id in eeprom hwWriteConfig(EEPROM_NODE_ID_ADDRESS, MY_NODE_ID); + setIndication(INDICATION_GOT_NODEID); } else if (_nc.nodeId == AUTO && isValidParent(_nc.parentNodeId)) { // Try to fetch node-id from gateway transportRequestNodeId(); @@ -174,6 +180,7 @@ void _begin() { } else { // Disable pullup pinMode(MY_NODE_UNLOCK_PIN, INPUT); + setIndication(INDICATION_ERR_LOCKED); nodeLock("LDB"); //Locked during boot } } else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) { @@ -222,7 +229,6 @@ boolean _sendRoute(MyMessage &message) { if (message.destination == _nc.nodeId) { // This is a message sent from a sensor attached on the gateway node. // Pass it directly to the gateway transport layer. - ledBlinkTx(1); return gatewayTransportSend(message); } #endif @@ -278,6 +284,7 @@ void _processInternalMessages() { #if !defined(MY_DISABLE_REMOTE_RESET) if (type == I_REBOOT) { // Requires MySensors or other bootloader with watchdogs enabled + setIndication(INDICATION_REBOOT); hwReboot(); } else #endif @@ -310,6 +317,7 @@ void _processInternalMessages() { #if defined(MY_REPEATER_FEATURE) if (_msg.data[0] == 'C') { // Clears child relay data for this node + setIndication(INDICATION_CLEAR_ROUTING); debug(PSTR("clear routing table\n")); uint8_t i = 255; do { @@ -354,6 +362,7 @@ void _processInternalMessages() { for (int i=EEPROM_START;i SEARCH_FAILURES) { transportFindParentNode(); @@ -336,6 +339,7 @@ boolean transportSendRoute(MyMessage &message) { void transportRequestNodeId() { + setIndication(INDICATION_REQ_NODEID); debug(PSTR("req id\n")); transportSetAddress(_nc.nodeId); build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); @@ -344,6 +348,7 @@ void transportRequestNodeId() { } void transportPresentNode() { + setIndication(INDICATION_PRESENT); // Open reading pipe for messages directed to this node (set write pipe to same) transportSetAddress(_nc.nodeId); // Present node and request config @@ -386,6 +391,8 @@ void transportFindParentNode() { return; findingParentNode = true; + setIndication(INDICATION_FIND_PARENT); + _failedTransmissions = 0; // Set distance to max diff --git a/libraries/MySensors/examples/BinarySwitchSensorIndication/BinarySwitchSensorIndication.ino b/libraries/MySensors/examples/BinarySwitchSensorIndication/BinarySwitchSensorIndication.ino new file mode 100644 index 0000000..1c1eb63 --- /dev/null +++ b/libraries/MySensors/examples/BinarySwitchSensorIndication/BinarySwitchSensorIndication.ino @@ -0,0 +1,150 @@ +/** + * 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-2016 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 + * + * Simple binary switch example + * Connect button or door/window reed switch between + * digitial I/O pin 3 (BUTTON_PIN below) and GND. + * A NeoPixel LED will be used to provide visual feedback of the sensor status. + * http://www.mysensors.org/build/binary + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include +#include +#include + +#define LED_CYCLE_MS 30 // Update rate of LEDs, in [ms]. +#define NEO_PIN 6 // NeoPixels input pin +#define CHILD_ID 3 +#define BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch + +Bounce debouncer = Bounce(); +int oldValue=-1; + +static Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, NEO_PIN, NEO_GRB + NEO_KHZ800); + +// Change to V_LIGHT if you use S_LIGHT in presentation below +MyMessage msg(CHILD_ID,V_TRIPPED); + +#define BLINK_TIMES(x) (x<<4) + +static uint8_t ledR = 0; +static uint8_t ledG = 0; +static uint8_t ledB = 0; + +static void updateLed(void) +{ + // Update the pattern (setting leds). + if (ledR > 0) --ledR; + if (ledG > 0) --ledG; + if (ledB > 0) --ledB; + // Determine of each color if it should be on or off. + uint8_t r = ((ledR & 0x0F) < 6) ? 0 : 255; + uint8_t g = ((ledG & 0x0F) < 6) ? 0 : 255; + uint8_t b = ((ledB & 0x0F) < 6) ? 0 : 255; + pixels.setPixelColor(0, r, g, b); + pixels.show(); +} + +void before() +{ + // Initialize the NeoPixel chain + pixels.begin(); + pixels.show(); + + // Configure timer interrupt + MsTimer2::set(LED_CYCLE_MS, updateLed); + MsTimer2::start(); +} + +void setup() +{ + // Setup the button + pinMode(BUTTON_PIN,INPUT); + // Activate internal pull-up + digitalWrite(BUTTON_PIN,HIGH); + + // After setting up the button, setup debouncer + debouncer.attach(BUTTON_PIN); + debouncer.interval(5); +} + +void presentation() { + // Register binary input sensor to gw (they will be created as child devices) + // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. + // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. + present(CHILD_ID, S_DOOR); +} + +void indication( const indication_t ind ) +{ + if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) + { + // Blink Blue 1x + ledB = BLINK_TIMES(1); + Serial.println(F("TX")); + } else if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) + { + // Blink Blue 1x + ledB = BLINK_TIMES(1); + Serial.println(F("RX")); + } else if (INDICATION_FIND_PARENT == ind) + { + // Blink Green 5x + ledG = BLINK_TIMES(5); + Serial.println(F("JOIN")); + } else if (INDICATION_GOT_PARENT == ind) + { + // Green off + ledG = BLINK_TIMES(0); + Serial.println(F("JOINED")); + } else if (ind > INDICATION_ERR_START) + { + // Blink Red, depending on the error number + ledR = BLINK_TIMES(ind - INDICATION_ERR_START); + Serial.print(F("ERROR")); Serial.println(ind - INDICATION_ERR_START); + } +} + +// Check if digital input has changed and send in new value +void loop() +{ + debouncer.update(); + // Get the update value + int value = debouncer.read(); + + if (value != oldValue) { + // Send in the new value + send(msg.set(value==HIGH ? 1 : 0)); + oldValue = value; + } +} +