34

Dependencies:   BSP libNDEF libxDot-mbed5 ST25DV

Files at this revision

API Documentation at this revision

Comitter:
umickelsen
Date:
Sat Oct 03 22:39:19 2020 +0000
Parent:
0:b15aed49e54b
Commit message:
Version 3.4

Changed in this revision

BSP.lib Show annotated file Show diff for this revision Revisions of this file
ST25DV.lib Show annotated file Show diff for this revision Revisions of this file
code/inc/RadioEvent.h Show annotated file Show diff for this revision Revisions of this file
code/inc/dot_util.h Show annotated file Show diff for this revision Revisions of this file
code/src/dot_util.cpp Show annotated file Show diff for this revision Revisions of this file
code/src/main.cpp Show annotated file Show diff for this revision Revisions of this file
code/src/sensores.cpp Show annotated file Show diff for this revision Revisions of this file
code/src/sensors.h Show annotated file Show diff for this revision Revisions of this file
code/src/x_nucleo_nfc04.cpp Show annotated file Show diff for this revision Revisions of this file
code/src/x_nucleo_nfc04.h Show annotated file Show diff for this revision Revisions of this file
examples/inc/RadioEvent.h Show diff for this revision Revisions of this file
examples/inc/dot_util.h Show diff for this revision Revisions of this file
examples/src/dot_util.cpp Show diff for this revision Revisions of this file
examples/src/main.cpp Show diff for this revision Revisions of this file
libNDEF.lib Show annotated file Show diff for this revision Revisions of this file
libmDot-mbed5.lib Show diff for this revision Revisions of this file
libxDot-mbed5.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
setup.sh Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSP.lib	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/ST-Expansion-SW-Team/code/BSP/#cf62b690f57c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ST25DV.lib	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/umickelsen/code/ST25DV/#3d652783d9e8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/inc/RadioEvent.h	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,75 @@
+#ifndef __RADIO_EVENT_H__
+#define __RADIO_EVENT_H__
+
+#include "dot_util.h"
+#include "mDotEvent.h"
+
+class RadioEvent : public mDotEvent
+{
+ 
+public:
+    RadioEvent() {}
+ 
+    virtual ~RadioEvent() {}
+ 
+    /*!
+     * MAC layer event callback prototype.
+     *
+     * \param [IN] flags Bit field indicating the MAC events occurred
+     * \param [IN] info  Details about MAC events occurred
+     */
+    virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
+ 
+        if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+            std::string msg = "OK";
+            switch (info->Status) {
+                case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                    msg = "ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                    msg = "TX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                    msg = "RX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                    msg = "RX_ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                    msg = "JOIN_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                    msg = "DOWNLINK_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                    msg = "ADDRESS_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                    msg = "MIC_FAIL";
+                    break;
+                default:
+                    break;
+            }
+            logTrace("Event: %s", msg.c_str());
+ 
+            logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                     flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+            logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                     info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                     info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+        }
+ 
+        if (flags->Bits.Rx) {
+            
+            logDebug("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                // print RX data as string and hexadecimal 
+                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                printf("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+            }
+        }
+    }
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/inc/dot_util.h	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,48 @@
+#ifndef __DOT_UTIL_H__
+#define __DOT_UTIL_H__
+
+#include "mbed.h"
+#include "mDot.h"
+#include "ChannelPlans.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+
+//#define TARGET_XDOT_L151CC
+
+//#include "example_config.h"
+
+extern mDot* dot;
+
+void display_config();
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power);
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);
+
+void join_network();
+//void join_network(uint8_t config_frequency_sub_band);
+
+void sleep_wake_rtc_only(bool deepsleep, unsigned int delay);
+
+void sleep_wake_interrupt_only(bool deepsleep);
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep,unsigned int delay);
+
+void sleep_save_io();
+
+void sleep_configure_io();
+
+void sleep_restore_io();
+
+void send_data(std::vector<uint8_t> data);
+int32_t send_string_data(std::string data);
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/dot_util.cpp	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,770 @@
+#include "dot_util.h"
+#if defined(TARGET_XDOT_L151CC)
+#include "xdot_low_power.h"
+#endif
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+uint32_t portA[6];
+uint32_t portB[6];
+uint32_t portC[6];
+uint32_t portD[6];
+uint32_t portH[6];
+#endif
+
+
+void display_config() {
+    // display configuration and library version information
+    logInfo("=====================");
+    logInfo("general configuration");
+    logInfo("=====================");
+    logInfo("version ------------------ %s", dot->getId().c_str());
+    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
+    logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
+    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
+    }
+    logInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
+    logInfo("=========================");
+    logInfo("credentials configuration");
+    logInfo("=========================");
+    logInfo("device class ------------- %s", dot->getClass().c_str());
+    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
+    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
+	logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
+	logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
+    } else {
+	logInfo("network name ------------- %s", dot->getNetworkName().c_str());
+	logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
+	logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
+	logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
+    }
+    logInfo("========================");
+    logInfo("communication parameters");
+    logInfo("========================");
+    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
+    } else {
+	logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
+    }
+    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
+    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
+    logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
+    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
+    if (dot->getLbtTimeUs()) {
+	logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
+	logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
+    }
+}
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::string current_network_name = dot->getNetworkName();
+    std::string current_network_passphrase = dot->getNetworkPassphrase();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+    
+    if (current_network_name != network_name) {
+        logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
+        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
+            logError("failed to set network name to \"%s\"", network_name.c_str());
+        }
+    }
+    
+    if (current_network_passphrase != network_passphrase) {
+        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
+        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
+            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_id = dot->getNetworkId();
+    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
+    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
+    
+    if (current_network_id != network_id_vector) {
+        logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
+        if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
+            logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
+        }
+    }
+    
+    if (current_network_key != network_key_vector) {
+        logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
+        if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    unsigned int i;
+    
+    /*logInfo("\r\nNET_ADDRESS: ");
+    for(i=0;i<4;i++)
+    {
+       logInfo("%02x ",network_address[i]);
+    }
+    logInfo("\r\n");
+    */
+    
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    //std::vector<uint8_t> network_address_vector = dot->getDeviceId();
+    //std::vector<uint8_t> network_address_vector(network_address);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint32_t current_tx_frequency = dot->getTxFrequency();
+    uint8_t current_tx_datarate = dot->getTxDataRate();
+    uint8_t current_tx_power = dot->getTxPower();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_tx_frequency != tx_frequency) {
+	logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
+	if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
+	    logError("failed to set TX frequency to %lu", tx_frequency);
+	}
+    }
+
+    if (current_tx_datarate != tx_datarate) {
+	logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
+	if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
+	    logError("failed to set TX datarate to %u", tx_datarate);
+	}
+    }
+
+    if (current_tx_power != tx_power) {
+	logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
+	if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
+	    logError("failed to set TX power to %u", tx_power);
+	}
+    }
+}
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
+    uint8_t current_link_check_count = dot->getLinkCheckCount();
+    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
+
+    if (current_link_check_count != link_check_count) {
+	logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
+	if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
+	    logError("failed to set link check count to %u", link_check_count);
+	}
+    }
+
+    if (current_link_check_threshold != link_check_threshold) {
+	logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
+	if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
+	    logError("failed to set link check threshold to %u", link_check_threshold);
+	}
+    }
+}
+
+void join_network()
+//void join_network(uint8_t config_frequency_sub_band) 
+{
+    int32_t j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+    // attempt to join the network
+    while (ret != mDot::MDOT_OK) 
+    {
+
+ 		/*if(config_frequency_sub_band != 0)
+ 		{
+ 			if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) 
+ 			{
+        		logError("failed to set frequency sub band %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    		}
+    	}
+        */  
+        logInfo("attempt %d to join network", ++j_attempts);
+        ret = dot->joinNetwork();
+        if (ret != mDot::MDOT_OK) {
+            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+            // in some frequency bands we need to wait until another channel is available before transmitting again
+            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+            if (delay_s < 2) {
+                logInfo("waiting %lu s until next free channel", delay_s);
+                wait(delay_s);
+            } else {
+                logInfo("sleeping %lu s until next free channel", delay_s);
+                dot->sleep(delay_s, mDot::RTC_ALARM, false);
+            }
+        }
+    }
+}
+
+void sleep_wake_rtc_only(bool deepsleep, unsigned int delay) 
+{
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    //if (delay_s < delay) 
+    //{
+        delay_s = delay;
+    //}
+    
+    
+    logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) 
+    {
+		// save the GPIO state.
+		sleep_save_io();
+
+		// configure GPIOs for lowest current
+		sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
+    dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
+
+    if (! deepsleep) 
+    {
+		// restore the GPIO state.
+		sleep_restore_io();
+    }
+}
+
+void sleep_wake_interrupt_only(bool deepsleep) {
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // since we're not waking on the RTC alarm, the interval is ignored
+    dot->sleep(0, mDot::INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep, unsigned int delay) 
+{
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+     delay_s = delay;
+
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) 
+    {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } 
+    else 
+    {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) 
+    {
+		// save the GPIO state.
+		sleep_save_io();
+
+		// configure GPIOs for lowest current
+		sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // whichever comes first will wake the xDot
+    dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
+
+    if (! deepsleep) 
+    {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_save_io() {
+#if defined(TARGET_XDOT_L151CC)
+	xdot_save_gpio_state();
+#else
+	portA[0] = GPIOA->MODER;
+	portA[1] = GPIOA->OTYPER;
+	portA[2] = GPIOA->OSPEEDR;
+	portA[3] = GPIOA->PUPDR;
+	portA[4] = GPIOA->AFR[0];
+	portA[5] = GPIOA->AFR[1];
+
+	portB[0] = GPIOB->MODER;
+	portB[1] = GPIOB->OTYPER;
+	portB[2] = GPIOB->OSPEEDR;
+	portB[3] = GPIOB->PUPDR;
+	portB[4] = GPIOB->AFR[0];
+	portB[5] = GPIOB->AFR[1];
+
+	portC[0] = GPIOC->MODER;
+	portC[1] = GPIOC->OTYPER;
+	portC[2] = GPIOC->OSPEEDR;
+	portC[3] = GPIOC->PUPDR;
+	portC[4] = GPIOC->AFR[0];
+	portC[5] = GPIOC->AFR[1];
+
+	portD[0] = GPIOD->MODER;
+	portD[1] = GPIOD->OTYPER;
+	portD[2] = GPIOD->OSPEEDR;
+	portD[3] = GPIOD->PUPDR;
+	portD[4] = GPIOD->AFR[0];
+	portD[5] = GPIOD->AFR[1];
+
+	portH[0] = GPIOH->MODER;
+	portH[1] = GPIOH->OTYPER;
+	portH[2] = GPIOH->OSPEEDR;
+	portH[3] = GPIOH->PUPDR;
+	portH[4] = GPIOH->AFR[0];
+	portH[5] = GPIOH->AFR[1];
+#endif
+}
+
+void sleep_configure_io() {
+#if defined(TARGET_XDOT_L151CC)
+    // GPIO Ports Clock Enable
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+    __GPIOH_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    // I2C_SDA & I2C_SCL to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_10;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#else
+    /* GPIO Ports Clock Enable */
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
+                | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
+
+    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
+
+    // PC_9 & PC_13 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    // XBEE_DIN - PA3
+    // XBEE_DIO2 - PA5
+    // XBEE_DIO3 - PA4
+    // XBEE_DIO4 - PA7
+    // XBEE_DIO5 - PC1
+    // XBEE_DIO6 - PA1
+    // XBEE_DIO7 - PA0
+    // XBEE_SLEEPRQ - PA11
+                
+    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_3;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+         if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_7;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_11;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#endif
+}
+
+void sleep_restore_io() {
+#if defined(TARGET_XDOT_L151CC)
+    xdot_restore_gpio_state();
+#else
+    GPIOA->MODER = portA[0];
+    GPIOA->OTYPER = portA[1];
+    GPIOA->OSPEEDR = portA[2];
+    GPIOA->PUPDR = portA[3];
+    GPIOA->AFR[0] = portA[4];
+    GPIOA->AFR[1] = portA[5];
+
+    GPIOB->MODER = portB[0];
+    GPIOB->OTYPER = portB[1];
+    GPIOB->OSPEEDR = portB[2];
+    GPIOB->PUPDR = portB[3];
+    GPIOB->AFR[0] = portB[4];
+    GPIOB->AFR[1] = portB[5];
+
+    GPIOC->MODER = portC[0];
+    GPIOC->OTYPER = portC[1];
+    GPIOC->OSPEEDR = portC[2];
+    GPIOC->PUPDR = portC[3];
+    GPIOC->AFR[0] = portC[4];
+    GPIOC->AFR[1] = portC[5];
+
+    GPIOD->MODER = portD[0];
+    GPIOD->OTYPER = portD[1];
+    GPIOD->OSPEEDR = portD[2];
+    GPIOD->PUPDR = portD[3];
+    GPIOD->AFR[0] = portD[4];
+    GPIOD->AFR[1] = portD[5];
+
+    GPIOH->MODER = portH[0];
+    GPIOH->OTYPER = portH[1];
+    GPIOH->OSPEEDR = portH[2];
+    GPIOH->PUPDR = portH[3];
+    GPIOH->AFR[0] = portH[4];
+    GPIOH->AFR[1] = portH[5];
+#endif
+}
+
+void send_data(std::vector<uint8_t> data) {
+    int32_t ret;
+
+    ret = dot->send(data);
+    if (ret != mDot::MDOT_OK) 
+    {
+        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
+    } 
+    else 
+    {
+        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
+    }
+}
+
+
+int32_t send_string_data(std::string data) {
+    int32_t ret;
+    std::vector<uint8_t> dvec(data.begin(), data.end());
+    
+    ret = dot->send(dvec);
+    if (ret != mDot::MDOT_OK) 
+    {
+        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
+    } 
+    else 
+    {
+        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
+    }
+    
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/main.cpp	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,1056 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+#include "sensors.h"
+#include "x_nucleo_nfc04a1_nfctag.h"
+
+/*** @@@@@@@@ Version de programa @@@@@@@@ ***/
+#define PROGRAM_BUILD "20200830.1"
+#define PROGRAM_VERSION "3.4.3"
+/*********************************************/
+
+////// Tipo de programa definido ////////
+
+#ifdef HIBER_DEMO
+#define PROGRAM_TYPE "Hiber_DEMO"
+#else
+#ifdef MODO_TEST_TX
+#define PROGRAM_TYPE "TEST"
+#else
+#ifdef PLACA_BARCO
+#define PROGRAM_TYPE "BARCO"
+#else
+#define PROGRAM_TYPE "SILO"
+#endif
+#endif
+#endif
+//////////////////////////////////
+
+#define MAX_MSG 17
+
+
+
+/******* @@@@@@@@  Definiciones para la red LoRA @@@@@@@@ ********/
+
+/////////////////////////////////////////////////////////////
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+// * either the network name and passphrase can be used or //
+//     the network ID (8 bytes) and KEY (16 bytes)         //
+/////////////////////////////////////////////////////////////
+
+
+//#define CHANNEL_PLAN CP_US915
+#define CHANNEL_PLAN CP_EU868
+
+/////////// Para gateway Multitech /////////////
+#ifdef OTA_MODE 
+static std::string network_name = "pruebalora";
+static std::string network_passphrase = "acdc1949";
+
+
+//Si colocamos sub_band en 0, busca una banda disponible
+//static uint8_t frequency_sub_band = 4;
+static uint8_t frequency_sub_band = 0;
+static bool public_network = false;
+static uint8_t ack = 0;
+static bool adr = true;
+/////////////////////////////////////////////////////
+
+#else 
+
+/////// Modo manual para gateway generico //////////
+
+static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+static uint8_t data_session_key[] =    { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+
+static uint8_t frequency_sub_band = 2;
+static lora::NetworkType network_type = lora::PUBLIC_LORAWAN;
+static uint8_t join_delay = 5;
+static uint8_t ack = 0;
+static bool adr = true;
+////////////////////////////////////////////////////
+
+#endif
+
+
+/************** @@@@@@@@ FIN definiciones red LoRa @@@@@@@@ ****************/
+
+
+/************ @@@@@@@@ Definiciones para dormir @@@@@@@@ ********************/
+// deepsleep consumes slightly less current than sleep
+// in sleep mode, IO state is maintained, RAM is retained, and application will 
+// resume after waking up
+// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
+// if deep_sleep == true, device will enter deepsleep mode
+static bool deep_sleep = true;
+
+//Tiempo de dormir en segundos
+#ifndef MODO_TEST_TX
+//#define DEFAULT_DELAY_SLEEP 5 //5seg
+//#define DEFAULT_DELAY_SLEEP 10 //10seg
+//#define DEFAULT_DELAY_SLEEP 30 //30seg
+#define DEFAULT_DELAY_SLEEP 60 //1 min
+//#define DEFAULT_DELAY_SLEEP 300 //5min
+//#define DEFAULT_DELAY_SLEEP 3600 //1hs
+//#define DEFAULT_DELAY_SLEEP 10800 //3hs
+//#define DEFAULT_DELAY_SLEEP 21600 //6hs
+
+
+//unsigned int delay_sleep = 21600; //6hs
+//unsigned int delay_sleep = 900; //15 min
+//unsigned int delay_sleep = 30; //30seg
+
+unsigned int delay_sleep = DEFAULT_DELAY_SLEEP; 
+
+#else
+unsigned int delay_sleep = 2;
+#endif
+
+/************ @@@@@@@@ Fin definiciones para dormir @@@@@@@@ ******************/
+
+/********* @@@@@@@@ Configuraciones de puertos I/O @@@@@@@@ **************/
+
+#ifdef PLACA_MDOT
+Serial pc(USBTX, USBRX);
+AnalogIn lux(XBEE_AD0);
+
+//Segun diagrama el PB_O es el A1 en la placa
+AnalogIn   a_temp(PB_0);
+
+//Segun diagrama el PC_1 es el A2
+AnalogIn   a_hum(PC_1);
+
+DigitalOut alimentacion(D3);
+DigitalOut led2(D7);
+
+#endif //De placa MDOT
+
+#ifdef PLACA_XDOT
+Serial pc(USBTX, USBRX);
+Serial co2sens(UART_TX,UART_RX);
+
+#ifdef DESARROLLO
+DigitalOut led2(PA_14);
+DigitalOut led1(LED1);
+
+#ifndef USE_SENSOR_I2C
+AnalogIn   a_temp(PB_0);
+AnalogIn   a_hum(PA_5);
+
+#else
+DigitalOut NFCOUT(PB_2);
+
+#endif 
+
+
+#else 
+
+#ifndef USE_SENSOR_I2C
+AnalogIn   a_temp(PA_4); //GPIO0
+AnalogIn   a_hum(PB_0); //GPIO2
+AnalogIn   a_bat(PA_5); //GPIO1
+
+#else
+DigitalOut NFCOUT(PB_2);
+#ifdef MEDIR_BAT
+AnalogIn   a_vbat(PA_4); //GPIO0
+#endif
+
+#endif 
+
+
+#endif // De desarrollo 
+
+//DigitalOut alimentacion(PB_2); //GPIO3
+
+DigitalOut alimentacion(PB_0); //GPIO2
+
+#endif //De PLACA_XDOT
+
+#ifdef USE_SENSOR_I2C
+I2C i2c(I2C_SDA , I2C_SCL ); 
+#endif
+
+/*********** @@@@@@@@ Fin de configuraciones puertos I/O  @@@@@@@@ ***********/
+
+/******************** Variables globales *********************/
+char co2_buffer[CO2_MAX_BUFFER];
+unsigned int co2_index;
+Timer t;
+time_t sleep_timestamp;
+mDot* dot = NULL;
+lora::ChannelPlan* plan = NULL;
+char retry_i2c;
+/*************************************************************/
+
+
+void flushSerialBuffer(Serial *device) 
+{ 
+    char char1 = 0; 
+    while (device->readable()) 
+    { 
+        char1 = device->getc(); 
+    }
+}
+
+void read_co2() 
+{       
+    //reset_co2_buffer();
+    
+    while (co2sens.readable() && (co2_index<CO2_MAX_BUFFER) )
+    { 
+        co2_buffer[co2_index] = co2sens.getc();
+        co2_index++;        
+    }
+    
+}
+
+void eui_to_netaddress(uint8_t *device_address)
+{
+    unsigned int i,j;
+    std::vector<uint8_t> node_eui = dot->getDeviceId();
+    
+    if(node_eui.size()<5)
+    {
+          for(i=0;i<node_eui.size();i++)
+            {
+                device_address[i] = node_eui.at(i);
+            }
+        }
+        else
+        {
+            for(i=4,j=0;(i<node_eui.size())&&j<4;i++,j++)
+            {
+                device_address[j] = node_eui.at(i);
+            }
+        }
+}
+
+/*******************************************************************/
+
+#ifdef HIBER_DEMO
+unsigned int seq;
+#endif
+
+    
+int main(void) 
+{
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+    
+    double t_temp, t_hum, temperatura, humedad,t_vbat;
+    unsigned int valor_co2, i,j;
+    
+    uint16_t temp_16, hum_16, co2_16;
+    unsigned char bat_8;
+    
+    std::string texto = "D04DE4F5";
+    char bufsend[MAX_MSG];
+    char aux[3];
+    char cmd[2];
+    char data[6] = {0};
+    bool done;
+    bool enable_tx_data = true;
+    bool wakeup_pin;
+    unsigned char extra_data;
+    char deviceid[MAX_DEVICE_ID];
+    char co2_str[4], temp_str[4], hum_str[4];
+    float bat_val = 0;
+    
+#ifndef OTA_MODE
+    uint8_t device_address[4];
+#endif    
+    
+#ifdef USE_SENSOR_I2C
+    const int addr8bit = I2C_SENSOR_ADDRESS << 1;
+#endif
+    
+//#ifdef MODO_TEST_TX
+    uint16_t seq;
+    //char seq_str[4];
+//#endif
+
+#ifdef USE_SENSOR_I2C
+    NFCTAG_StatusTypeDef NFC_STAT;
+    NFC_Memory_Layout NFC_Memory;
+    bool NFC_Init;
+#endif
+    
+    
+    //Abrimos el puerto serie del Co2
+    co2sens.baud(CO2_BAUDRATE);
+    
+    //Attachamos la interrupcion a la funcion de lectura 
+    //co2sens.attach(&read_co2);
+        
+    //Abrimos el puerto de debug
+    pc.baud(115200);
+    
+    
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+#if CHANNEL_PLAN == CP_US915
+    plan = new lora::ChannelPlan_US915();
+#elif CHANNEL_PLAN == CP_AU915
+    plan = new lora::ChannelPlan_AU915();
+#elif CHANNEL_PLAN == CP_EU868
+    plan = new lora::ChannelPlan_EU868();
+#elif CHANNEL_PLAN == CP_KR920
+    plan = new lora::ChannelPlan_KR920();
+#elif CHANNEL_PLAN == CP_AS923
+    plan = new lora::ChannelPlan_AS923();
+#elif CHANNEL_PLAN == CP_AS923_JAPAN
+    plan = new lora::ChannelPlan_AS923_Japan();
+#elif CHANNEL_PLAN == CP_IN865
+    plan = new lora::ChannelPlan_IN865();
+#endif
+    assert(plan);
+
+    dot = mDot::getInstance(plan);
+    assert(dot);
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+    
+    t.reset();
+    t.start();
+    
+    
+    if(!dot->nvmRead(TIME_SLEEP_ADDRESS,&sleep_timestamp, sizeof(time_t)))
+    {
+        pc.printf("ATENCION: No se pudo cargar sleep_timestamp\r\n");
+        sleep_timestamp = time(NULL);        
+    }
+    
+    unsigned int tiempo_sleep = (unsigned int)(time(NULL) - sleep_timestamp);
+    
+    pc.printf("%s%u%s%u\r\n","Tiempo actual:",(unsigned int)time(NULL)," Tiempo guardado:",(unsigned int)sleep_timestamp);
+    
+    if( tiempo_sleep < delay_sleep)
+    {
+        pc.printf("%s\n\n","DESPERTADO POR WAKE PIN"); 
+        wakeup_pin = true;
+#ifdef DESARROLLO
+        led1 = true;
+#endif
+    }
+    else
+    {
+        wakeup_pin = false;
+    }
+    
+    pc.printf("%s%u%s\r\n","Tiempo dormido: ",tiempo_sleep," seg.");
+    
+    #ifdef HIBER_DEMO
+    if(!dot->nvmRead(SEQ_ADDRESS,&seq, sizeof(uint16_t)))
+    {
+        pc.printf("ATENCION: No se pudo cargar la secuencia\r\n");
+        seq = 0x30;
+        
+    }
+    #endif
+
+    
+    pc.printf("\r\n%s%s%s%s%s%s%s\r\n","### Wiagro Lanza v",PROGRAM_VERSION,"-",PROGRAM_TYPE," build ",PROGRAM_BUILD," ###");
+    //pc.printf("Sizeof's: float = %d | double = %d | int = %d | long = %d \r\n",sizeof(float),sizeof(double),sizeof(int),sizeof(long int));
+    pc.printf("Sleep Time: %d seg = %d min = %d hs \r\n",delay_sleep,delay_sleep/60,delay_sleep/3600);
+    
+    #ifdef USE_SENSOR_I2C
+    //Inicializamos el NFC
+    //NFC_STAT = BSP_NFCTAG_Init(&i2c,&NFCOUT);
+    NFC_STAT = ST25DV_IO_Init(&i2c,&NFCOUT);
+    if(NFC_STAT != NFCTAG_OK)
+    {
+        pc.printf("%s%d\r\n","NFC NO iniciado. Error: ",NFC_STAT);
+        NFC_Init = false;
+    }
+    else
+    {
+        pc.printf("NFC OK\r\n");
+        NFC_Init = true;
+    }
+    #endif
+    
+    memset(deviceid,0,MAX_DEVICE_ID);
+    
+#ifndef OTA_MODE        
+    strncpy(deviceid,"00",MAX_DEVICE_ID);
+     
+    //Construimos el network address en funcion al EUI del dispositivo   
+
+    eui_to_netaddress(device_address);
+        
+     pc.printf("\n%s","Device Address = ");     
+     for(i=0;i<4;i++)
+     {
+        pc.printf("%02x ",device_address[i]);
+        snprintf(aux,3,"%02x",device_address[i]);
+        strncat(deviceid,aux,MAX_DEVICE_ID);
+     }
+    
+     strncat(deviceid,"\r\n",MAX_DEVICE_ID);
+     pc.printf("\r\n%s%s","Device Address NFC = ",deviceid);       
+   
+#endif 
+   
+    alimentacion = 1;
+    //alimentacion2 = 1;
+    wait(3);
+    
+   /* if(!dot->nvmRead(I2C_RETRY_ADDRESS,&retry_i2c, sizeof(char)))
+    {
+        pc.printf("ATENCION: No se pudo cargar i2c_retry\r\n");
+        retry_i2c = 0;
+        
+    }
+    
+    */
+     
+    
+//#ifdef MODO_TEST_TX
+    if(!dot->nvmRead(SEQ_ADDRESS,&seq, sizeof(uint16_t)))
+    {
+        pc.printf("ATENCION: No se pudo cargar la secuencia\r\n");
+        seq = 0;
+        
+    }
+//#endif
+    
+    co2_index = reset_co2_buffer(co2_buffer);
+
+    if (!dot->getStandbyFlag()) 
+    {
+        
+        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+        // start from a well-known state
+        logInfo("defaulting Dot configuration");
+        dot->resetConfig();
+        dot->resetNetworkSession();
+
+        // make sure library logging is turned on
+        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+#ifndef ONLY_SENSORS  
+#ifdef  OTA_MODE               
+        // update configuration if necessary
+        if (dot->getJoinMode() != mDot::OTA) 
+        {
+            logInfo("changing network join mode to OTA");
+            if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) 
+            {
+                logError("failed to set network join mode to OTA");
+            }
+        }
+        // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
+        // only one method or the other should be used!
+        // network ID = crc64(network name)
+        // network KEY = cmac(network passphrase)
+        update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
+        //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
+
+        // configure network link checks
+        // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
+        // check the link every count packets
+        // declare the Dot disconnected after threshold failed link checks
+        // for count = 3 and threshold = 5, the Dot will ask for a link check response every 5 packets and will consider the connection lost if it fails to receive 3 responses in a row
+        update_network_link_check_config(3, 5);
+
+        // enable or disable Adaptive Data Rate
+        dot->setAdr(adr);
+#else
+      // update configuration if necessary
+        if (dot->getJoinMode() != mDot::MANUAL) 
+        {
+            logInfo("changing network join mode to MANUAL");
+            if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) 
+            {
+                logError("failed to set network join mode to MANUAL");
+            }
+        }
+        // in MANUAL join mode there is no join request/response transaction
+        // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate
+        // network address - 4 bytes (00000001 - FFFFFFFE)
+        // network session key - 16 bytes
+        // data session key - 16 bytes
+        // to provision your Dot with a Conduit gateway, follow the following steps
+        //   * ssh into the Conduit
+        //   * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/
+        //      lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304
+        //   * if you change the network address, network session key, or data session key, make sure you update them on the gateway
+        // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation
+        
+        
+        
+        eui_to_netaddress(device_address);
+        
+        update_manual_config(device_address, network_session_key, data_session_key, frequency_sub_band, network_type, ack);
+
+        // enable or disable Adaptive Data Rate
+        dot->setAdr(adr);
+
+        // Configure the join delay
+        dot->setJoinDelay(join_delay);
+        
+        //std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+
+#endif //De OTA_MODE
+
+#endif //De ONLY_SENSORS   
+
+        // save changes to configuration
+        logInfo("saving configuration");
+        if (!dot->saveConfig()) 
+        {
+            logError("failed to save configuration");
+        }
+
+        // display configuration
+        display_config();
+    } 
+    else 
+    {
+#ifndef ONLY_SENSORS         
+        // restore the saved session if the dot woke from deepsleep mode
+        // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
+        //logInfo("restoring network session from NVM");
+        //dot->restoreNetworkSession();
+        dot->resetConfig();
+        dot->resetNetworkSession();
+#endif
+        if(!wakeup_pin)
+        {
+            t.reset();
+            pc.printf("Warming up sensores %d seg.\r\n",WARMING_UP_SENSORS);
+        }
+        else
+        {
+            pc.printf("Despertado por pin Wakeup: TRANSMISION INSTANTANEA\r\n");
+        }
+    }
+
+    // LOOP PRINCIPAL
+     t.start();
+    while (true) 
+    {
+        //Nos conectamos a la red LoRa si esta habilitado
+
+#ifndef ONLY_SENSORS    
+#ifdef OTA_MODE     
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) 
+        {     //join_network(config_frequency_sub_band);
+                join_network();
+                t.reset();
+                //alimentacion = 0;
+                //pc.printf("Warming up sensores %d seg.\r\n",WARMING_UP_SENSORS);               
+        }
+#else
+  if (dot->getJoinMode() != mDot::MANUAL) {
+            logInfo("changing network join mode to MANUAL");
+            if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) {
+                logError("failed to set network join mode to MANUAL");
+            }
+        }
+        // in MANUAL join mode there is no join request/response transaction
+        // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate
+        // network address - 4 bytes (00000001 - FFFFFFFE)
+        // network session key - 16 bytes
+        // data session key - 16 bytes
+        // to provision your Dot with a Conduit gateway, follow the following steps
+        //   * ssh into the Conduit
+        //   * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/
+        //      lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304
+        //   * if you change the network address, network session key, or data session key, make sure you update them on the gateway
+        // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation
+        
+        
+        eui_to_netaddress(device_address);
+        
+        /*pc.printf("\n%s","Device Address = ");     
+        for(i=0;i<4;i++)
+        {
+            pc.printf("%02x ",device_address[i]);            
+        }
+        */
+        update_manual_config(device_address, network_session_key, data_session_key, frequency_sub_band, network_type, ack);
+
+        // enable or disable Adaptive Data Rate
+        dot->setAdr(adr);
+
+        // Configure the join delay
+        dot->setJoinDelay(join_delay);
+                
+#endif //De OTA_MODE
+
+#endif // de ONLY_SENSORS
+
+        if((t.read() >= WARMING_UP_SENSORS)||(wakeup_pin))
+        {
+   
+            bat_8 = 0x00;
+
+#ifndef HIBER_DEMO           
+#ifndef USE_SENSOR_I2C
+            t_temp =  average_samples(NUMBER_SAMPLES, a_temp);
+            t_hum =  average_samples(NUMBER_SAMPLES, a_hum);
+           
+            temp_16 = a_temp.read_u16();
+            hum_16 = a_hum.read_u16();    
+       
+            pc.printf("tension Temp (av): %3.3fv \r\n", t_temp);
+            pc.printf("normalized: 0x%04X \r\n", temp_16);
+            temperatura = volt_to_temp(t_temp);       
+            pc.printf("Valor Temp: %3.3fC \r\n", temperatura);
+          
+            pc.printf("Tension Hum: %3.3fv \r\n", t_hum);
+            pc.printf("normalized: 0x%04X \r\n", hum_16);
+            humedad = volt_to_hum(t_hum);
+            pc.printf("Valor Hum : %3.3f% \r\n", humedad);
+#else
+            //i2c.frequency(1000);
+            done = false;
+            pc.printf("I2C Addr=0x%02x(8bit), 0x%02x(7bit)\r\n",addr8bit,I2C_SENSOR_ADDRESS);
+        
+            cmd[0] = 0x2c;
+            cmd[1] = 0x06; 
+            
+             for(j=0;j<6;j++)
+             {
+                   data[j] = 0;
+             }
+             pc.printf("I2C Write = %02x, %02x \r\n",cmd[0],cmd[1]);
+             i2c.write(addr8bit, cmd, 2);
+             wait(1);    
+                
+             i2c.read( addr8bit, data, 6);
+        
+             pc.printf("I2C Read = %02x, %02x, %02x, %02x, %02x, %02x\r\n",data[0],data[1],data[2],data[3],data[4],data[5]);
+             done = true;
+             /*if((data[0] == 0)&&(data[1] == 0)&&(data[3] == 0)&&(data[4] == 0))
+             {
+                 alimentacion = 0;
+                 wait(1);
+                 done = false;                    
+                 retry_i2c++;
+                 if(retry_i2c>20)
+                 {
+                     done = true;
+                     enable_tx_data = true;
+                     delay_sleep = DEFAULT_DELAY_SLEEP;
+                     retry_i2c = 0;
+                 }
+                 else
+                 {
+                     enable_tx_data = false;
+                     delay_sleep = 2;
+                 }        
+                 
+                 alimentacion = 1;
+                 wait(1);
+                    
+                 if(!dot->nvmWrite(I2C_RETRY_ADDRESS,&retry_i2c, sizeof(char)))
+                 {
+                      pc.printf("NO se pudo guardar retry_i2c\r\n");
+                 }
+                 else
+                 {
+                      pc.printf("retry_i2c = %d Guardado en NVRAM\r\n",retry_i2c);
+                 }                    
+
+            }
+            else
+            {
+                  //done = true;
+                  retry_i2c = 0;
+            }              
+            */
+            
+            if(done)
+            {
+                 temperatura = (((data[0] * 256) + data[1]) * 175.0) / 65535.0 - 45.0;                
+                 humedad = (((data[3] * 256) + data[4])) * 100.0 / 65535.0;
+                
+                 pc.printf("Temperature in Celsius : %.2f C \r\n", temperatura);
+                 pc.printf("Relative Humidity is : %.2f RH \r\n", humedad);  
+                 
+                 snprintf(temp_str,4,"%d",(unsigned int)temperatura); 
+                 strncat(temp_str,"C",4);
+                 snprintf(hum_str,4,"%d", (unsigned int)humedad); 
+                 strncat(hum_str,"%",4);
+                 
+            }  
+#ifdef MEDIR_BAT
+            t_vbat =  average_samples(NUMBER_SAMPLES, a_vbat);         
+            pc.printf("tension vbat (av): %3.3fv \r\n", t_vbat);    
+            bat_8 = (unsigned char)(t_vbat*255/VSAMPLE);            
+            pc.printf("tension vbat (char): %02x \r\n", bat_8); 
+            if(t_vbat>0.35)
+            {
+                bat_val = (t_vbat-0.35)/(0.64);
+                pc.printf("tension vbat (val): %3.3fv \r\n", bat_val);    
+            }            
+#endif
+            
+#endif //De USE_SENSOR_I2C
+       
+            pc.printf("---------------\r\n");
+#ifdef OLD_READ_CO2            
+            if(co2sens.readable()) 
+            {
+                co2sens.gets(co2_buffer,CO2_MAX_BUFFER);
+                pc.printf("CO2: %s ",co2_buffer);
+                //valor_co2 = (unsigned int)atoi(co2_buffer);
+                valor_co2 = convert_co2(co2_buffer);
+                
+                //Ojo: Truncamos 32 a 16 bits para transmitir
+                //Rango del sensor menor a 65536.
+                pc.printf("CO2 HEX = 0x%04X\r\n",co2_16);
+                co2_index = reset_co2_buffer(co2_buffer);                    
+            }
+                     
+            /*if(co2_buffer[0] != 0)
+            {
+                pc.printf("CO2: %s \r\n",co2_buffer);
+                co2_index = reset_co2_buffer(co2_buffer);                             
+            }
+            */
+            else
+            {
+                pc.printf("NO hay datos de CO2!\r\n");
+                valor_co2 = 0;
+            }
+            
+            co2_16 = valor_co2;
+                   
+#else
+            
+            for(i=0;i<3;i++)
+            {
+                memset(co2_buffer,0,CO2_MAX_BUFFER);
+            
+                Timer timeout_co2;
+                timeout_co2.reset();
+                timeout_co2.start();
+                char counter = 0;
+                while ((timeout_co2.read() < 5)) // give the data up to 5 seconds to arrive.
+                { 
+                    if (co2sens.readable()) 
+                    {
+                        co2sens.gets(co2_buffer,CO2_MAX_BUFFER);
+                        break;
+                    }
+                }
+                        
+                if(co2_buffer[0] == 0)
+                {
+                    pc.printf("NO hay datos de CO2!\r\n");
+                    valor_co2 = 0;                
+                }
+                else
+                {
+                     pc.printf("CO2: %s ",co2_buffer);
+                     valor_co2 = convert_co2(co2_buffer);
+                     co2_16 = valor_co2;
+                     pc.printf("CO2 (HEX) = %d | (0x%04X)\r\n",valor_co2,co2_16);
+                     co2_index = reset_co2_buffer(co2_buffer);
+                     snprintf(co2_str,4,"%d",valor_co2);
+                }
+                if(valor_co2 != 0)
+                {
+                    break;
+                }
+                
+                wait(1);
+            }
+            
+#endif
+#endif //de #ifndef HIBER_DEMO
+
+#ifdef HIBER_DEMO
+            std::vector<uint8_t> tx_data;
+            
+            tx_data.push_back('W');
+            tx_data.push_back('I');
+            tx_data.push_back('A');
+            tx_data.push_back('G');
+            tx_data.push_back('R');
+            tx_data.push_back('O');            
+            tx_data.push_back('+');
+            tx_data.push_back('H');
+            tx_data.push_back('I');
+            tx_data.push_back('B');
+            tx_data.push_back('E');            
+            tx_data.push_back('R');
+ #ifdef USE_NFC           
+    if(NFC_Init)
+    {
+        init_NFC_data(&NFC_Memory);
+        strncpy(NFC_Memory.DEVID,deviceid,NFC_MAX_ID);
+        strncpy(NFC_Memory.PAC,"WIAGRO+HIBER",NFC_MAX_ID);
+        
+        
+        seq++;
+        if((seq > 0x39)||(seq < 0x30))
+        {
+             seq = 0x30;
+        }
+        if(!dot->nvmWrite(SEQ_ADDRESS,&seq, sizeof(uint16_t)))
+        {
+             pc.printf("NO se pudo guardar la secuencia\r\n");
+        }
+        else
+        {
+             pc.printf("seq = %02x Guardado en NVRAM\r\n",seq);
+        }
+        
+        NFC_Memory.sn = seq;
+    
+        //uint8_t NFC_Data = NFC_Memory;
+    
+        //NFC_STAT = BSP_NFCTAG_WriteData((uint8_t *)&NFC_Memory,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        //NFC_STAT = ST25DV_IO_MemWrite((uint8_t *)&NFC_Memory,ST25DV_ADDR_DATA_I2C,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        NFC_STAT = ST25DV_i2c_WriteData((uint8_t *)&NFC_Memory,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        //NFC_STAT = ST25DV_i2c_WriteData((uint8_t *)deviceid,NFC_START_ADDRESS,sizeof(deviceid),&i2c);
+        if( NFC_STAT == NFCTAG_OK )
+        {
+            pc.printf("NFC Wrote!\r\n");
+        }
+        else
+        {
+            pc.printf("%s%d\r\n","NFC NO escrito. Error: ",NFC_STAT);
+        }
+    }
+    else
+    {
+        pc.printf("NFC NO iniciado\r\n");
+    }            
+            
+#endif //de NFC
+            
+#else //De Hiber Demo
+
+            std::vector<uint8_t> tx_data;
+
+            
+#ifdef MODO_TEST_TX
+            tx_data.push_back((seq >> 8) & 0xFF);
+            tx_data.push_back((seq & 0xFF));
+#endif
+            
+            //Enviamos el tipo de lanza y el estado de movimiento
+            extra_data = SENSOR_MODE;
+            if(wakeup_pin)
+            {
+                //Activamos el bit de movimiento
+                extra_data |= 0x10;
+            }
+            else
+            {
+                //Bajamos el bit de movimiento
+                extra_data &= 0xef;
+            }
+            
+            tx_data.push_back(extra_data);
+            
+            
+#ifndef USE_SENSOR_I2C
+            tx_data.push_back((temp_16 >> 8) & 0xFF);
+            tx_data.push_back((temp_16 & 0xFF));
+            
+            tx_data.push_back((hum_16 >> 8) & 0xFF);
+            tx_data.push_back((hum_16 & 0xFF));
+#else
+            //Temperatura MSB,LSB
+            tx_data.push_back(data[1]);
+            tx_data.push_back(data[0]);
+            
+            //Humedad MSB,LSB
+            tx_data.push_back(data[4]);
+            tx_data.push_back(data[3]);
+#endif
+            
+            tx_data.push_back((co2_16 >> 8) & 0xFF);
+            tx_data.push_back((co2_16 & 0xFF));            
+            
+            tx_data.push_back(bat_8);
+            
+        seq++;
+        if(seq > 9999)
+        {
+             seq = 0;
+        }
+        if(!dot->nvmWrite(SEQ_ADDRESS,&seq, sizeof(uint16_t)))
+        {
+             pc.printf("NO se pudo guardar la secuencia\r\n");
+        }
+        else
+        {
+            pc.printf("seq = %d Guardado en NVRAM\r\n",seq);
+        }
+                    
+#ifdef USE_NFC
+    if(NFC_Init)
+    {
+        init_NFC_data(&NFC_Memory);
+        //snprintf(seq_str,4,"%04d",seq);
+        //strncat(NFC_Memory.PAC,seq_str,NFC_MAX_ID);
+        
+#ifndef NFC_ORIG_LAYOUT        
+        strncpy(NFC_Memory.temp_str,temp_str,4);        
+        strncpy(NFC_Memory.hum_str,hum_str,4);
+        strncpy(NFC_Memory.co2_str,co2_str,4);        
+#endif
+        NFC_Memory.medicion_temperatura = fix16_from_float(temperatura);
+        NFC_Memory.medicion_humedad = fix16_from_float(humedad);
+        NFC_Memory.medicion_bateria = fix16_from_float(bat_val);
+        NFC_Memory.medicion_co2 = fix16_from_float((float)valor_co2);
+        
+        memset(NFC_Memory.DEVID,0,NFC_MAX_ID);        
+        strncpy(NFC_Memory.DEVID,deviceid,NFC_MAX_ID);
+
+        strncpy(NFC_Memory.PAC,"L_v",NFC_MAX_ID);        
+        strncat(NFC_Memory.PAC,PROGRAM_VERSION,NFC_MAX_ID);
+        strncat(NFC_Memory.PAC,"_",NFC_MAX_ID);
+        strncat(NFC_Memory.PAC,deviceid+4,NFC_MAX_ID);
+        NFC_Memory.PAC[strlen(NFC_Memory.PAC)] = 0;
+       
+        
+        //uint8_t NFC_Data = NFC_Memory;
+    
+        //NFC_STAT = BSP_NFCTAG_WriteData((uint8_t *)&NFC_Memory,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        //NFC_STAT = ST25DV_IO_MemWrite((uint8_t *)&NFC_Memory,ST25DV_ADDR_DATA_I2C,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        NFC_STAT = ST25DV_i2c_WriteData((uint8_t *)&NFC_Memory,NFC_START_ADDRESS,sizeof(NFC_Memory),&i2c);
+        //NFC_STAT = ST25DV_i2c_WriteData((uint8_t *)deviceid,NFC_START_ADDRESS,sizeof(deviceid),&i2c);
+        if( NFC_STAT == NFCTAG_OK )
+        {
+            pc.printf("NFC Wrote!\r\n");
+        }
+        else
+        {
+            pc.printf("%s%d\r\n","NFC NO escrito. Error: ",NFC_STAT);
+        }
+    }
+    else
+    {
+        pc.printf("NFC NO iniciado\r\n");
+    }
+    
+#endif
+            
+#endif //DE Hiber demo            
+
+            pc.printf("Enviando paquete: ");
+            for(i=0;i<MAX_MSG;i++)
+            {
+                bufsend[i] = 0;
+            }
+            for(i=0;i<tx_data.size();i++)
+            {
+                sprintf(aux,"%02x",tx_data.at(i));
+                strcat(bufsend,aux);
+                pc.printf(aux);
+            }                 
+            pc.printf("\r\n");
+            
+            std::string bufstr(bufsend);
+            
+             
+            //send_string_data(bufstr);
+#ifndef ONLY_SENSORS   
+            if(enable_tx_data)            
+                send_data(tx_data);
+            
+#ifdef MODO_TEST_TX
+            seq++;
+            if(seq > 60000)
+            {
+                seq = 0;
+            }
+            if(!dot->nvmWrite(SEQ_ADDRESS,&seq, sizeof(uint16_t)))
+            {
+                pc.printf("NO se pudo guardar la secuencia\r\n");
+            }
+            else
+            {
+                pc.printf("seq = %d Guardado en NVRAM\r\n",seq);
+            }
+                       
+ #endif //De MODO_TEST_TX
+
+ #endif //ONLY_SENSORS          
+
+            if (deep_sleep) 
+            {
+                //logInfo("saving network session to NVM");
+                //dot->saveNetworkSession();           
+              
+               //Abrimos el puerto serie del Co2
+               //co2sens.baud(CO2_BAUDRATE);                
+            }   
+            
+            sleep_timestamp = time(NULL);
+
+            if(!dot->nvmWrite(TIME_SLEEP_ADDRESS,(void*)&sleep_timestamp, sizeof(time_t)))
+            {
+                pc.printf("NO se pudo guardar sleep_timestamp\r\n");
+            }
+            else
+            {
+                pc.printf("sleep_timestamp = %u Guardado en NVRAM\r\n",(unsigned int)sleep_timestamp);
+            }   
+            printf("## Off sensores ##\r\n");
+            
+            #ifdef USE_NFC
+            BSP_NFCTAG_DeInit();
+            #endif 
+
+            //alimentacion = 0;
+            alimentacion = 1;      
+            
+            // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
+            //sleep_wake_rtc_only(deep_sleep,delay_sleep);
+            //sleep_wake_interrupt_only(deep_sleep);
+#ifndef NO_SLEEP            
+           
+           sleep_wake_rtc_or_interrupt(deep_sleep,delay_sleep);
+           
+           if(!deep_sleep)
+           { 
+               t.reset();
+               pc.printf("Warming up sensores %d seg.\r\n",WARMING_UP_SENSORS);
+           }
+#else
+               t.reset();
+               pc.printf("Warming up sensores %d seg.\r\n",WARMING_UP_SENSORS);
+#endif
+
+           
+          flushSerialBuffer(&pc);
+           
+        } //Fin del IF WarmingUp
+        
+#ifdef DESARROLLO
+        led1 = !led1;
+        wait(0.5);
+#endif
+
+
+        if(pc.readable()) 
+        {
+            if(pc.getc()=='c')
+            {
+                config_sensor(&pc,&co2sens,co2_buffer);
+            }
+            else
+            {
+                pc.printf("Comando Invalido\r\n");
+            }
+        }
+        
+        
+        
+    } //Fin del loop principal
+ 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/sensores.cpp	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,193 @@
+
+#include "sensors.h"
+
+
+float average_samples(unsigned int cant_samples, AnalogIn input)
+{
+    unsigned int i;
+    float sample;
+    
+    sample = 0;
+    
+    for(i=0;i<cant_samples;i++)
+    {
+        sample+= input.read();
+    }
+    sample = sample / (float)cant_samples;
+    
+    return (sample*VSAMPLE);
+}
+
+double volt_to_hum(float volt)
+{
+    double hum;
+    
+    hum = -12.5+125.0*((volt)/(double)VREF);
+    return hum;
+}
+
+double volt_to_temp(float volt)
+{
+    double temp;
+    temp = -66.875+218.75*((volt)/(double)VREF);
+    return temp;
+}
+
+    
+unsigned int reset_co2_buffer(char *co2_buffer)
+{
+    unsigned int i;
+    for(i=0;i<CO2_MAX_BUFFER;i++)
+    {
+        co2_buffer[i] = 0;
+    }
+    return 0;
+}
+
+void print_menu_sensor(Serial *pc)
+{
+   pc->printf("\r\nMenu sensor CO2\r\n");
+   pc->printf("c: Calibrar\r\n");
+   pc->printf("d: Salida default\r\n");
+   pc->printf("r: Leer valor\r\n");
+   pc->printf("s: Salir\r\n");
+   printf(": ");
+}
+
+char config_sensor(Serial *pc, Serial *co2sens, char *co2_buffer)
+{
+   time_t timeout;
+   char c;
+   bool pres;
+   
+   timeout = time(NULL); 
+   print_menu_sensor(pc);
+       
+   while(1)
+   {
+       if(pc->readable())
+       {
+           c = pc->getc();
+           switch(c)
+           {
+               case 'c':
+                    pc->printf("\r\nCalibrando...\r\n");
+                    co2sens->printf("G\r\n");
+                    pres = true;
+               break;
+               
+               case 'd':
+                    pc->printf("\r\nSal default...\r\n");
+                    co2sens->printf("M 6\r\n");               
+                    pres = true;
+               break;
+                
+               case 's':
+               return 0;
+               
+               case 'r':
+                    wait(0.1);
+                    co2sens->gets(co2_buffer,CO2_MAX_BUFFER);
+                    pc->printf("Resp: %s ",co2_buffer); 
+               break;
+                
+               default:
+                pc->printf("\r\nOpcion invalida\r\n");
+           }
+           
+           if(pres)
+           { 
+            wait(0.1);
+            co2sens->gets(co2_buffer,CO2_MAX_BUFFER);
+            pc->printf("Resp: %s ",co2_buffer);
+            pres = false;
+           }
+
+           timeout = time(NULL); 
+           print_menu_sensor(pc);      
+       }    
+       else
+       {
+            if((time(NULL)-timeout)>=TIMEOUT_MENU_CO2)
+            {
+                pc->printf("\r\nTIMEOUT Menu\r\n");
+                return 0;
+            }
+        }
+     }
+}
+
+#define CO2_START "Z "
+#define CO2_SEP ' '
+#define CO2_MAX_DIGIT 6
+
+unsigned int convert_co2(char *buffer)
+{
+    unsigned int i;
+    char *punt;
+    char aux[CO2_MAX_DIGIT];
+    
+    memset(aux,0,CO2_MAX_DIGIT);
+    
+    punt=strstr(buffer,(char *)CO2_START);
+    if(punt == NULL)
+    {
+        return 0;
+    }
+    punt = punt + strlen(CO2_START);
+    
+    //Ejemplo : "Z 00004 z 00004"
+    for(i=0; (i<strlen(punt))&&(i<CO2_MAX_DIGIT)&&(punt[i] != CO2_SEP); i++)
+    {
+        aux[i] = punt [i];
+    }
+    //pc.printf("\r\nAUX = %s\r\n",aux);
+    return (atoi(aux));
+}
+
+#ifdef USE_NFC
+
+#if defined(NFC_ORIG_LAYOUT) || defined(HIBER_DEMO)
+
+void init_NFC_data(NFC_Memory_Layout *data)
+{
+    data->sn = 0;
+    data->medicion_refint = 0;       //V
+    data->medicion_analog_in_0 = 0;  //V
+    data->medicion_temperatura = 0;  //ºC
+    data->medicion_humedad = 0;      //%
+    data->medicion_bateria = 0;      //V
+    data->medicion_co2 = 0;          //%
+
+    memset(data->DEVID,0,NFC_MAX_ID);
+    memset(data->PAC,0,NFC_MAX_ID);
+}
+
+#else
+
+void init_NFC_data(NFC_Memory_Layout *data)
+{
+
+    memset(data->temp_str,0,4);
+    memset(data->hum_str,0,4);
+    memset(data->co2_str,0,4);
+    data->medicion_temperatura = 0;  //ºC
+    data->medicion_humedad = 0;      //%
+    data->medicion_bateria = 0;      //V
+    data->medicion_co2 = 0;          //%
+
+    memset(data->DEVID,0,NFC_MAX_ID);
+    memset(data->PAC,0,NFC_MAX_ID);
+}
+
+#endif
+
+
+static const int32_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */
+int32_t fix16_from_float( float a )
+{
+    float temp = a * fix16_one;
+    temp += ( temp >= 0 ) ? 0.5f : -0.5f;
+    return ( int32_t )temp;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/sensors.h	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,135 @@
+#ifndef __SENSORS_H__
+#define __SENSORS_H__
+
+#include "mbed.h"
+
+//Sin dormir 
+//#define NO_SLEEP 
+
+/// Definimos el tipo de placa ///
+#define PLACA_XDOT
+//#define PLACA_MDOT
+
+//Demo HIBER
+//#define HIBER_DEMO
+
+#ifdef PLACA_XDOT
+#define VSAMPLE 3.3f
+#endif
+
+#ifdef PLACA_MDOT
+#define VSAMPLE 3.0f
+#endif
+
+#define MEDIR_BAT
+
+//Definir solo para probar sensado, sin conexion a la red
+//#define ONLY_SENSORS
+
+//Definir para placa de desarrollo 
+//#define DESARROLLO
+
+//Definir para sensor I2C en vez de conversor A/D
+//Si es I2C
+#define USE_SENSOR_I2C
+
+#ifdef DESARROLLO
+#define I2C_SENSOR_ADDRESS 0x45
+#else
+#define I2C_SENSOR_ADDRESS 0x44
+#endif 
+
+//Uso de NFC
+#define USE_NFC
+
+//tipo de lanza
+#ifdef PLACA_BARCO
+#define SENSOR_MODE 0x02
+#else
+#define SENSOR_MODE 0x01
+#endif
+
+#define MAX_DEVICE_ID 11
+
+#ifdef USE_NFC
+#define NFC_START_ADDRESS               0x00000
+#define NFC_MAX_ID 20
+
+#if defined(NFC_ORIG_LAYOUT) || defined(HIBER_DEMO)
+//#ifdef NFC_ORIG_LAYOUT
+
+typedef struct
+{
+    uint32_t sn;
+    int32_t  medicion_refint;       //V
+    int32_t  medicion_analog_in_0;  //V
+    int32_t  medicion_temperatura;  //ºC
+    int32_t  medicion_humedad;      //%
+    int32_t  medicion_bateria;      //V
+    int32_t  medicion_co2;          //%
+
+    char DEVID[20];
+    char PAC[20];
+} NFC_Memory_Layout;
+
+#else
+
+typedef struct
+{
+    char temp_str[4];
+    char hum_str[4];
+    char co2_str[4];
+    int32_t  medicion_temperatura;  //ºC
+    int32_t  medicion_humedad;      //%
+    int32_t  medicion_bateria;      //V
+    int32_t  medicion_co2;          //%
+    char DEVID[20];
+    char PAC[20];
+} NFC_Memory_Layout;
+
+#endif //de NFC Layout
+
+
+#endif //de USE_NFC 
+
+//Definir para enviar mensajes repetitivos con nro seq para pruebas de alcance
+//#define MODO_TEST_TX
+#define SEQ_ADDRESS 0x1000
+//#define I2C_RETRY_ADDRESS 0x1100
+////////////////////////////
+
+//Direccion de la NVRAM donde guardamos el timestamp antes de dormir
+#define TIME_SLEEP_ADDRESS 0x10F0
+
+#define NUMBER_SAMPLES 10
+#define VREF 3.3
+
+//Tiempo de espera en segundos para leer los sensores al despertarse
+#ifndef MODO_TEST_TX
+#define WARMING_UP_SENSORS 10
+//#define WARMING_UP_SENSORS 5
+#else
+#define WARMING_UP_SENSORS 5
+#endif
+
+
+
+#define CO2_BAUDRATE 9600
+#define CO2_MAX_BUFFER 20
+#define TIMEOUT_MENU_CO2 10
+
+//Declaracion de funciones
+float average_samples(unsigned int cant_samples, AnalogIn input);
+double volt_to_hum(float volt);
+double volt_to_temp(float volt);
+unsigned int reset_co2_buffer(char *co2_buffer);
+void print_menu_sensor(Serial *pc);
+char config_sensor(Serial *pc, Serial *co2sens, char *co2_buffer);
+unsigned int convert_co2(char *buffer);
+int32_t fix16_from_float( float a );
+
+#ifdef USE_NFC
+void init_NFC_data(NFC_Memory_Layout *data);
+#endif
+
+#endif // de __SENSORS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/x_nucleo_nfc04.cpp	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,142 @@
+#include "x_nucleo_nfc04.h"
+
+extern sCCFileInfo CCFileStruct;
+
+// This is a constructor
+
+X_Nucleo_NFC04::X_Nucleo_NFC04(I2C* i2cChannel, DigitalOut* led_1, DigitalOut* led_2, DigitalOut* led_3, DigitalOut* LPD, DigitalIn* MISO){
+    mi2cChannel = i2cChannel;
+    mled_1 = led_1;
+    mled_2 = led_2;
+    mled_3 = led_3;
+    mLPD = LPD;
+    mMISO = MISO;
+}
+
+/**
+  * @brief  This function initialize the device
+  * @param  mi2cChannel : I2C Channel
+  * @param  mLPD : A digital PIN
+  * @retval status(int) : Return if the write operation is succesful
+  */
+
+int X_Nucleo_NFC04::begin(I2C* mi2cChannel, DigitalOut *mLPD) {
+    int ret = 0;
+    
+    // Light some leds
+    ledOn(mled_1);
+    wait_ms( 300 );
+    ledOn(mled_2);
+
+    /* NFCTAG Init */
+    ret = BSP_NFCTAG_Init(mi2cChannel, mLPD);
+    if(ret != NDEF_OK)
+        return ret;
+
+    /* Reset MBEN Dynamic and initializes the CCFile struct */
+    BSP_NFCTAG_GetExtended_Drv()->ResetMBEN_Dyn( mi2cChannel );
+    if( NfcType5_NDEFDetection( mi2cChannel) != NDEF_OK )
+    {
+        CCFileStruct.MagicNumber = NFCT5_MAGICNUMBER_E1_CCFILE;
+        CCFileStruct.Version = NFCT5_VERSION_V1_0;
+        CCFileStruct.MemorySize = ( ST25DV_MAX_SIZE / 8 ) & 0xFF;
+        CCFileStruct.TT5Tag = 0x05;
+        /* Init of the Type Tag 5 component (M24LR) */
+        ret = NfcType5_TT5Init( mi2cChannel );
+        if (ret != NDEF_OK)
+            return ret;
+    }
+    
+    ledOff( mled_1 );
+    wait_ms( 300 );
+    ledOff( mled_2 );
+    wait_ms( 300 );
+    ledOff( mled_3 );
+    wait_ms( 300 );
+    return NDEF_OK;
+}
+
+
+/**
+  * @brief  This function light on selected Led
+  * @param  led : Led to be lit on
+  * @retval None
+  */
+void X_Nucleo_NFC04::ledOn(DigitalOut* led) {
+    led -> write(1);
+}
+
+/**
+  * @brief  This function light off selected Led
+  * @param  led : Led to be lit off
+  * @retval None
+  */
+
+void X_Nucleo_NFC04::ledOff(DigitalOut* led) {
+    *led = 0;
+}
+
+
+/**
+  * @brief  This function write an URI into the NFC Tag
+  * @param  protocol : Protocol of the uri to write
+  * @param  uri : String containing the uri to write in the NFC Tag
+  * @param  info : Additional info
+  * @param  mi2cChannel : Object of the I2C channel
+  * @retval status(int) : Return if the write operation is succesful
+  */
+int X_Nucleo_NFC04::writeURI(string protocol, string uri, string info, I2C* mi2cChannel) {
+    sURI_Info _URI;
+    strcpy( _URI.protocol,protocol.c_str() );
+    strcpy( _URI.URI_Message,uri.c_str() );
+    strcpy( _URI.Information,info.c_str() );
+
+
+    return NDEF_WriteURI( &_URI, mi2cChannel );
+}
+
+/**
+  * @brief  This function read an URI from the NFC Tag
+  * @param  mi2cChannel : Object of the I2C channel
+  * @retval string : Return the string that has been read from the NFC Tag
+  */
+
+string X_Nucleo_NFC04::readURI( I2C* mi2cChannel) {
+    sURI_Info uri = {"","",""};
+    sRecordInfo_t recordInfo;
+    // increase buffer size for bigger messages
+    if(NDEF_ReadNDEF(NDEF_Buffer, mi2cChannel))
+        return (string)NULL;
+    
+    if(NDEF_IdentifyBuffer(&recordInfo, NDEF_Buffer))
+        return (string)NULL;
+    if(NDEF_ReadURI(&recordInfo,&uri))
+        return (string)NULL;
+    return string(uri.protocol) + string(uri.URI_Message);
+}
+
+
+/**
+  * @brief  This function write WiFi Credentials into the NFC Tag
+  * @param  NetworkSSID : SSID of the WiFi Network
+  * @param  AuthenticationType :
+  * @param  EncryptionType :
+  * @param  NetworkKey : Password of the WiFi
+  * @param  mi2cChannel : Object of the I2C channel
+  * @retval status(int) : Return if the write operation is succesful
+  */
+uint16_t X_Nucleo_NFC04::writeWiFi(string NetworkSSID, Ndef_Wifi_Authentication_t AuthenticationType, Ndef_Wifi_Encryption_t EncryptionType, string NetworkKey, I2C* mi2cChannel ){
+
+    sWifiTokenInfo _wifi;
+
+    strcpy( _wifi.NetworkSSID,NetworkSSID.c_str() );
+    _wifi.AuthenticationType = AuthenticationType;
+    _wifi.EncryptionType = EncryptionType;
+    strcpy( _wifi.NetworkKey,NetworkKey.c_str() );
+
+
+
+     return NDEF_WriteWifiToken(&_wifi, mi2cChannel );
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code/src/x_nucleo_nfc04.h	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,62 @@
+#ifndef _X_NUCLEO_NFC04_H_
+#define _X_NUCLEO_NFC04_H_
+#include "BSP/x_nucleo_nfc04a1_nfctag.h"
+#include "libNDEF/NDEFcommon.h"
+#include "libNDEF/tagtype5_wrapper.h"
+#include "libNDEF/lib_NDEF_URI.h"
+#include "libNDEF/lib_NDEF_AAR.h"
+#include "libNDEF/lib_NDEF_Bluetooth.h"
+#include "libNDEF/lib_NDEF_Email.h"
+#include "libNDEF/lib_NDEF_Handover.h"
+#include "libNDEF/lib_NDEF_Geo.h"
+#include "libNDEF/lib_NDEF_MyApp.h"
+#include "libNDEF/lib_NDEF_SMS.h"
+#include "libNDEF/lib_NDEF_Text.h"
+#include "libNDEF/lib_NDEF_Vcard.h"
+#include "libNDEF/lib_NDEF_Wifi.h"
+
+//#include "ST25DV/st25dv.h"
+//#include "x_nucleo_nfc04a1.h"
+#include "mbed.h"
+#include "PinNames.h"
+#include "st25dv.h"
+
+#include <string>
+
+using namespace std;
+
+
+
+/* Class of the NFC04A1
+ *
+ * begin: It initializes the device in order to start the communication with it
+ * writeURI: Method that implements the write of an URI through I2C communication
+ * readURI: Reading of an URI coming from an NFC tag
+ * writeWiFi: Write the WiFi in the NFC tag
+ * readWiFi: Read the WiFi coming from another device that writes on the NFC tag
+ * ledON: It lights one of the three LED based on input PIN
+ * ledOFF: It lights off one of the three LED based on input PIN
+ *
+ */
+class X_Nucleo_NFC04 {
+    public:
+    X_Nucleo_NFC04(I2C* i2cChannel, DigitalOut* led_1, DigitalOut* led_2, DigitalOut* led_3, DigitalOut* LPD, DigitalIn* MISO);
+    int begin(I2C* mi2cChannel, DigitalOut * mLPD);
+    void ledOn(DigitalOut* led);
+    void ledOff(DigitalOut* led);
+    int writeURI(string protocol, string uri, string info, I2C* mi2cChannel);
+    uint16_t writeWiFi(string NetworkSSID, Ndef_Wifi_Authentication_t AuthenticationType, Ndef_Wifi_Encryption_t EncryptionType, string NetworkKey, I2C* mi2cChannel );
+    string readURI( I2C* mi2cChannel);
+    private:
+    DigitalOut *mled_1;
+    DigitalOut *mled_2;
+    DigitalOut *mled_3;
+    DigitalOut *mLPD;
+    DigitalIn *mMISO;
+    I2C *mi2cChannel;
+
+};
+
+extern X_Nucleo_NFC04 X_Nucleo_Nfc04;
+
+#endif
\ No newline at end of file
--- a/examples/inc/RadioEvent.h	Sat Sep 30 22:01:56 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#ifndef __RADIO_EVENT_H__
-#define __RADIO_EVENT_H__
-
-#include "dot_util.h"
-#include "mDotEvent.h"
-
-class RadioEvent : public mDotEvent
-{
- 
-public:
-    RadioEvent() {}
- 
-    virtual ~RadioEvent() {}
- 
-    /*!
-     * MAC layer event callback prototype.
-     *
-     * \param [IN] flags Bit field indicating the MAC events occurred
-     * \param [IN] info  Details about MAC events occurred
-     */
-    virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
- 
-        if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
-            std::string msg = "OK";
-            switch (info->Status) {
-                case LORAMAC_EVENT_INFO_STATUS_ERROR:
-                    msg = "ERROR";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
-                    msg = "TX_TIMEOUT";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
-                    msg = "RX_TIMEOUT";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
-                    msg = "RX_ERROR";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
-                    msg = "JOIN_FAIL";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
-                    msg = "DOWNLINK_FAIL";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
-                    msg = "ADDRESS_FAIL";
-                    break;
-                case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
-                    msg = "MIC_FAIL";
-                    break;
-                default:
-                    break;
-            }
-            logTrace("Event: %s", msg.c_str());
- 
-            logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
-                     flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
-            logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
-                     info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
-                     info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
-        }
- 
-        if (flags->Bits.Rx) {
-            
-            logDebug("Rx %d bytes", info->RxBufferSize);
-            if (info->RxBufferSize > 0) {
-                // print RX data as string and hexadecimal 
-                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
-                printf("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
-            }
-        }
-    }
-};
-
-#endif
-
--- a/examples/inc/dot_util.h	Sat Sep 30 22:01:56 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#ifndef __DOT_UTIL_H__
-#define __DOT_UTIL_H__
-
-#include "mbed.h"
-#include "mDot.h"
-#include "ChannelPlans.h"
-#include "MTSLog.h"
-#include "MTSText.h"
-//#include "example_config.h"
-
-extern mDot* dot;
-
-void display_config();
-
-void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
-
-void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
-
-void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
-
-void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power);
-
-void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);
-
-void join_network();
-
-void sleep_wake_rtc_only(bool deepsleep, unsigned int delay);
-
-void sleep_wake_interrupt_only(bool deepsleep);
-
-void sleep_wake_rtc_or_interrupt(bool deepsleep);
-
-void sleep_save_io();
-
-void sleep_configure_io();
-
-void sleep_restore_io();
-
-void send_data(std::vector<uint8_t> data);
-int32_t send_string_data(std::string data);
-
-#endif
--- a/examples/src/dot_util.cpp	Sat Sep 30 22:01:56 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,739 +0,0 @@
-#include "dot_util.h"
-#if defined(TARGET_XDOT_L151CC)
-#include "xdot_low_power.h"
-#endif
-
-#if defined(TARGET_MTS_MDOT_F411RE)
-uint32_t portA[6];
-uint32_t portB[6];
-uint32_t portC[6];
-uint32_t portD[6];
-uint32_t portH[6];
-#endif
-
-
-void display_config() {
-    // display configuration and library version information
-    logInfo("=====================");
-    logInfo("general configuration");
-    logInfo("=====================");
-    logInfo("version ------------------ %s", dot->getId().c_str());
-    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
-    logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
-    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
-    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
-        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
-    }
-    logInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
-    logInfo("=========================");
-    logInfo("credentials configuration");
-    logInfo("=========================");
-    logInfo("device class ------------- %s", dot->getClass().c_str());
-    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
-    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
-	logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
-	logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
-	logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
-    } else {
-	logInfo("network name ------------- %s", dot->getNetworkName().c_str());
-	logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
-	logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
-	logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
-    }
-    logInfo("========================");
-    logInfo("communication parameters");
-    logInfo("========================");
-    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
-	logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
-    } else {
-	logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
-    }
-    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
-    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
-    logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
-    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
-    if (dot->getLbtTimeUs()) {
-	logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
-	logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
-    }
-}
-
-void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
-    std::string current_network_name = dot->getNetworkName();
-    std::string current_network_passphrase = dot->getNetworkPassphrase();
-    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
-    bool current_public_network = dot->getPublicNetwork();
-    uint8_t current_ack = dot->getAck();
-    
-    if (current_network_name != network_name) {
-        logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
-        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
-            logError("failed to set network name to \"%s\"", network_name.c_str());
-        }
-    }
-    
-    if (current_network_passphrase != network_passphrase) {
-        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
-        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
-            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
-        }
-    }
-    
-    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
-	if (current_frequency_sub_band != frequency_sub_band) {
-	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
-	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
-		logError("failed to set frequency sub band to %u", frequency_sub_band);
-	    }
-	}
-    }
-    
-    if (current_public_network != public_network) {
-        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
-        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
-            logError("failed to set public network to %s", public_network ? "on" : "off");
-        }
-    }
-    
-    if (current_ack != ack) {
-        logInfo("changing acks from %u to %u", current_ack, ack);
-        if (dot->setAck(ack) != mDot::MDOT_OK) {
-            logError("failed to set acks to %u", ack);
-        }
-    }
-}
-
-void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
-    std::vector<uint8_t> current_network_id = dot->getNetworkId();
-    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
-    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
-    bool current_public_network = dot->getPublicNetwork();
-    uint8_t current_ack = dot->getAck();
-
-    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
-    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
-    
-    if (current_network_id != network_id_vector) {
-        logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
-        if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
-            logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
-        }
-    }
-    
-    if (current_network_key != network_key_vector) {
-        logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
-        if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
-            logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
-        }
-    }
-    
-    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
-	if (current_frequency_sub_band != frequency_sub_band) {
-	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
-	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
-		logError("failed to set frequency sub band to %u", frequency_sub_band);
-	    }
-	}
-    }
-    
-    if (current_public_network != public_network) {
-        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
-        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
-            logError("failed to set public network to %s", public_network ? "on" : "off");
-        }
-    }
-    
-    if (current_ack != ack) {
-        logInfo("changing acks from %u to %u", current_ack, ack);
-        if (dot->setAck(ack) != mDot::MDOT_OK) {
-            logError("failed to set acks to %u", ack);
-        }
-    }
-}
-
-void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
-    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
-    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
-    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
-    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
-    bool current_public_network = dot->getPublicNetwork();
-    uint8_t current_ack = dot->getAck();
-
-    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
-    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
-    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
-
-    if (current_network_address != network_address_vector) {
-        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
-        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
-            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
-        }
-    }
-    
-    if (current_network_session_key != network_session_key_vector) {
-        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
-        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
-            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
-        }
-    }
-    
-    if (current_data_session_key != data_session_key_vector) {
-        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
-        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
-            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
-        }
-    }
-    
-    if (current_frequency_sub_band != frequency_sub_band) {
-        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
-        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
-            logError("failed to set frequency sub band to %u", frequency_sub_band);
-        }
-    }
-    
-    if (current_public_network != public_network) {
-        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
-        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
-            logError("failed to set public network to %s", public_network ? "on" : "off");
-        }
-    }
-    
-    if (current_ack != ack) {
-        logInfo("changing acks from %u to %u", current_ack, ack);
-        if (dot->setAck(ack) != mDot::MDOT_OK) {
-            logError("failed to set acks to %u", ack);
-        }
-    }
-}
-
-void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) {
-    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
-    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
-    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
-    uint32_t current_tx_frequency = dot->getTxFrequency();
-    uint8_t current_tx_datarate = dot->getTxDataRate();
-    uint8_t current_tx_power = dot->getTxPower();
-
-    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
-    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
-    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
-
-    if (current_network_address != network_address_vector) {
-        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
-        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
-            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
-        }
-    }
-    
-    if (current_network_session_key != network_session_key_vector) {
-        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
-        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
-            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
-        }
-    }
-    
-    if (current_data_session_key != data_session_key_vector) {
-        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
-        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
-            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
-        }
-    }
-    
-    if (current_tx_frequency != tx_frequency) {
-	logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
-	if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
-	    logError("failed to set TX frequency to %lu", tx_frequency);
-	}
-    }
-
-    if (current_tx_datarate != tx_datarate) {
-	logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
-	if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
-	    logError("failed to set TX datarate to %u", tx_datarate);
-	}
-    }
-
-    if (current_tx_power != tx_power) {
-	logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
-	if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
-	    logError("failed to set TX power to %u", tx_power);
-	}
-    }
-}
-
-void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
-    uint8_t current_link_check_count = dot->getLinkCheckCount();
-    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
-
-    if (current_link_check_count != link_check_count) {
-	logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
-	if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
-	    logError("failed to set link check count to %u", link_check_count);
-	}
-    }
-
-    if (current_link_check_threshold != link_check_threshold) {
-	logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
-	if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
-	    logError("failed to set link check threshold to %u", link_check_threshold);
-	}
-    }
-}
-
-void join_network() {
-    int32_t j_attempts = 0;
-    int32_t ret = mDot::MDOT_ERROR;
-    
-    // attempt to join the network
-    while (ret != mDot::MDOT_OK) {
-        logInfo("attempt %d to join network", ++j_attempts);
-        ret = dot->joinNetwork();
-        if (ret != mDot::MDOT_OK) {
-            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-            // in some frequency bands we need to wait until another channel is available before transmitting again
-            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
-            if (delay_s < 2) {
-                logInfo("waiting %lu s until next free channel", delay_s);
-                wait(delay_s);
-            } else {
-                logInfo("sleeping %lu s until next free channel", delay_s);
-                dot->sleep(delay_s, mDot::RTC_ALARM, false);
-            }
-        }
-    }
-}
-
-void sleep_wake_rtc_only(bool deepsleep, unsigned int delay) 
-{
-    // in some frequency bands we need to wait until another channel is available before transmitting again
-    // wait at least 10s between transmissions
-    uint32_t delay_s = dot->getNextTxMs() / 1000;
-    if (delay_s < delay) 
-    {
-        delay_s = delay;
-    }
-    
-    logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
-    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
-
-    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
-    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
-    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
-    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
-    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
-    // steps are:
-    //   * save IO configuration
-    //   * configure IOs to reduce current consumption
-    //   * sleep
-    //   * restore IO configuration
-    if (! deepsleep) 
-    {
-		// save the GPIO state.
-		sleep_save_io();
-
-		// configure GPIOs for lowest current
-		sleep_configure_io();
-    }
-    
-    // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
-    dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
-
-    if (! deepsleep) 
-    {
-		// restore the GPIO state.
-		sleep_restore_io();
-    }
-}
-
-void sleep_wake_interrupt_only(bool deepsleep) {
-#if defined (TARGET_XDOT_L151CC)
-    if (deepsleep) {
-        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
-        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
-    } else {
-        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
-        //      other pins can be confgured instead: GPIO0-3 or UART_RX
-        dot->setWakePin(WAKE);    
-    }
-
-    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
-#else
-
-    if (deepsleep) {
-        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
-        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
-    } else {
-        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
-        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
-        dot->setWakePin(XBEE_DIO7);    
-    }
-
-    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
-#endif
-
-    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
-
-    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
-    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
-    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
-    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
-    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
-    // steps are:
-    //   * save IO configuration
-    //   * configure IOs to reduce current consumption
-    //   * sleep
-    //   * restore IO configuration
-    if (! deepsleep) {
-	// save the GPIO state.
-	sleep_save_io();
-
-	// configure GPIOs for lowest current
-	sleep_configure_io();
-    }
-    
-    // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
-    // since we're not waking on the RTC alarm, the interval is ignored
-    dot->sleep(0, mDot::INTERRUPT, deepsleep);
-
-    if (! deepsleep) {
-	// restore the GPIO state.
-	sleep_restore_io();
-    }
-}
-
-void sleep_wake_rtc_or_interrupt(bool deepsleep) 
-{
-    // in some frequency bands we need to wait until another channel is available before transmitting again
-    // wait at least 10s between transmissions
-    uint32_t delay_s = dot->getNextTxMs() / 1000;
-    if (delay_s < 10) {
-        delay_s = 10;
-    }
-
-#if defined (TARGET_XDOT_L151CC)
-    if (deepsleep) {
-        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
-        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
-    } else {
-        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
-        //      other pins can be confgured instead: GPIO0-3 or UART_RX
-        dot->setWakePin(WAKE);    
-    }
-
-    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
-#else
-    if (deepsleep) {
-        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
-        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
-    } else {
-        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
-        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
-        dot->setWakePin(XBEE_DIO7);    
-    }
-
-    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
-#endif
-
-    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
-
-    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
-    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
-    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
-    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
-    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
-    // steps are:
-    //   * save IO configuration
-    //   * configure IOs to reduce current consumption
-    //   * sleep
-    //   * restore IO configuration
-    if (! deepsleep) {
-	// save the GPIO state.
-	sleep_save_io();
-
-	// configure GPIOs for lowest current
-	sleep_configure_io();
-    }
-    
-    // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep)
-    // whichever comes first will wake the xDot
-    dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
-
-    if (! deepsleep) {
-	// restore the GPIO state.
-	sleep_restore_io();
-    }
-}
-
-void sleep_save_io() {
-#if defined(TARGET_XDOT_L151CC)
-	xdot_save_gpio_state();
-#else
-	portA[0] = GPIOA->MODER;
-	portA[1] = GPIOA->OTYPER;
-	portA[2] = GPIOA->OSPEEDR;
-	portA[3] = GPIOA->PUPDR;
-	portA[4] = GPIOA->AFR[0];
-	portA[5] = GPIOA->AFR[1];
-
-	portB[0] = GPIOB->MODER;
-	portB[1] = GPIOB->OTYPER;
-	portB[2] = GPIOB->OSPEEDR;
-	portB[3] = GPIOB->PUPDR;
-	portB[4] = GPIOB->AFR[0];
-	portB[5] = GPIOB->AFR[1];
-
-	portC[0] = GPIOC->MODER;
-	portC[1] = GPIOC->OTYPER;
-	portC[2] = GPIOC->OSPEEDR;
-	portC[3] = GPIOC->PUPDR;
-	portC[4] = GPIOC->AFR[0];
-	portC[5] = GPIOC->AFR[1];
-
-	portD[0] = GPIOD->MODER;
-	portD[1] = GPIOD->OTYPER;
-	portD[2] = GPIOD->OSPEEDR;
-	portD[3] = GPIOD->PUPDR;
-	portD[4] = GPIOD->AFR[0];
-	portD[5] = GPIOD->AFR[1];
-
-	portH[0] = GPIOH->MODER;
-	portH[1] = GPIOH->OTYPER;
-	portH[2] = GPIOH->OSPEEDR;
-	portH[3] = GPIOH->PUPDR;
-	portH[4] = GPIOH->AFR[0];
-	portH[5] = GPIOH->AFR[1];
-#endif
-}
-
-void sleep_configure_io() {
-#if defined(TARGET_XDOT_L151CC)
-    // GPIO Ports Clock Enable
-    __GPIOA_CLK_ENABLE();
-    __GPIOB_CLK_ENABLE();
-    __GPIOC_CLK_ENABLE();
-    __GPIOH_CLK_ENABLE();
-
-    GPIO_InitTypeDef GPIO_InitStruct;
-
-    // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
-    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
-    // I2C_SDA & I2C_SCL to analog nopull
-    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
-    // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
-    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
-    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
-    if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_0;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-    if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_4;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-    if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_5;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-    if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_0;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-    }
-    if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_2;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-    }
-    if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_10;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-#else
-    /* GPIO Ports Clock Enable */
-    __GPIOA_CLK_ENABLE();
-    __GPIOB_CLK_ENABLE();
-    __GPIOC_CLK_ENABLE();
-
-    GPIO_InitTypeDef GPIO_InitStruct;
-
-    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
-    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
-                | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
-
-    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
-    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
-
-    // PC_9 & PC_13 to analog nopull
-    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
-    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-    GPIO_InitStruct.Pull = GPIO_NOPULL;
-    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
-
-    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
-    // XBEE_DIN - PA3
-    // XBEE_DIO2 - PA5
-    // XBEE_DIO3 - PA4
-    // XBEE_DIO4 - PA7
-    // XBEE_DIO5 - PC1
-    // XBEE_DIO6 - PA1
-    // XBEE_DIO7 - PA0
-    // XBEE_SLEEPRQ - PA11
-                
-    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_3;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_5;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_4;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-         if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_7;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-     if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_1;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-    }
-
-     if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_1;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-     if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_0;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-
-     if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
-        GPIO_InitStruct.Pin = GPIO_PIN_11;
-        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
-        GPIO_InitStruct.Pull = GPIO_NOPULL;
-        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-    }
-#endif
-}
-
-void sleep_restore_io() {
-#if defined(TARGET_XDOT_L151CC)
-    xdot_restore_gpio_state();
-#else
-    GPIOA->MODER = portA[0];
-    GPIOA->OTYPER = portA[1];
-    GPIOA->OSPEEDR = portA[2];
-    GPIOA->PUPDR = portA[3];
-    GPIOA->AFR[0] = portA[4];
-    GPIOA->AFR[1] = portA[5];
-
-    GPIOB->MODER = portB[0];
-    GPIOB->OTYPER = portB[1];
-    GPIOB->OSPEEDR = portB[2];
-    GPIOB->PUPDR = portB[3];
-    GPIOB->AFR[0] = portB[4];
-    GPIOB->AFR[1] = portB[5];
-
-    GPIOC->MODER = portC[0];
-    GPIOC->OTYPER = portC[1];
-    GPIOC->OSPEEDR = portC[2];
-    GPIOC->PUPDR = portC[3];
-    GPIOC->AFR[0] = portC[4];
-    GPIOC->AFR[1] = portC[5];
-
-    GPIOD->MODER = portD[0];
-    GPIOD->OTYPER = portD[1];
-    GPIOD->OSPEEDR = portD[2];
-    GPIOD->PUPDR = portD[3];
-    GPIOD->AFR[0] = portD[4];
-    GPIOD->AFR[1] = portD[5];
-
-    GPIOH->MODER = portH[0];
-    GPIOH->OTYPER = portH[1];
-    GPIOH->OSPEEDR = portH[2];
-    GPIOH->PUPDR = portH[3];
-    GPIOH->AFR[0] = portH[4];
-    GPIOH->AFR[1] = portH[5];
-#endif
-}
-
-void send_data(std::vector<uint8_t> data) {
-    int32_t ret;
-
-    ret = dot->send(data);
-    if (ret != mDot::MDOT_OK) 
-    {
-        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
-    } 
-    else 
-    {
-        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
-    }
-}
-
-
-int32_t send_string_data(std::string data) {
-    int32_t ret;
-    std::vector<uint8_t> dvec(data.begin(), data.end());
-    
-    ret = dot->send(dvec);
-    if (ret != mDot::MDOT_OK) 
-    {
-        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
-    } 
-    else 
-    {
-        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
-    }
-    
-    return ret;
-}
--- a/examples/src/main.cpp	Sat Sep 30 22:01:56 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-#include "dot_util.h"
-#include "RadioEvent.h"
- 
-/////////////////////////////////////////////////////////////////////////////
-// -------------------- DOT LIBRARY REQUIRED ------------------------------//
-// * Because these example programs can be used for both mDot and xDot     //
-//     devices, the LoRa stack is not included. The libmDot library should //
-//     be imported if building for mDot devices. The libxDot library       //
-//     should be imported if building for xDot devices.                    //
-// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
-// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
-// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
-// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
-/////////////////////////////////////////////////////////////////////////////
-
-/******************** Definiciones para la red LoRA *********************/
-
-/////////////////////////////////////////////////////////////
-// * these options must match the settings on your gateway //
-// * edit their values to match your configuration         //
-// * frequency sub band is only relevant for the 915 bands //
-// * either the network name and passphrase can be used or //
-//     the network ID (8 bytes) and KEY (16 bytes)         //
-/////////////////////////////////////////////////////////////
-#define CHANNEL_PLAN CP_US915
-static std::string network_name = "pruebalora";
-static std::string network_passphrase = "acdc1949";
-
-//static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 };
-//static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B };
-
-static uint8_t frequency_sub_band = 0;
-static bool public_network = false;
-static uint8_t ack = 1;
-static bool adr = true;
-
-
-/***********************************************************************/
-
-/*************** Definiciones para dormir **************************/
-// deepsleep consumes slightly less current than sleep
-// in sleep mode, IO state is maintained, RAM is retained, and application will 
-// resume after waking up
-// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
-// if deep_sleep == true, device will enter deepsleep mode
-static bool deep_sleep = false;
-
-//Tiempo de dormir en segundos
-unsigned int delay_sleep = 20;
-/*******************************************************************/
-
-/*************** Configuraciones de puertos I/O **************************/
-Serial pc(USBTX, USBRX);
-AnalogIn lux(XBEE_AD0);
-
-/*******************************************************************/
-
-
-
-mDot* dot = NULL;
-lora::ChannelPlan* plan = NULL;
-
-
-#define MAX_MSG 10
-
-int main(void) 
-{
-    // Custom event handler for automatically displaying RX data
-    RadioEvent events;
-
-    pc.baud(115200);
-
-    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
-    
-#if CHANNEL_PLAN == CP_US915
-    plan = new lora::ChannelPlan_US915();
-#elif CHANNEL_PLAN == CP_AU915
-    plan = new lora::ChannelPlan_AU915();
-#elif CHANNEL_PLAN == CP_EU868
-    plan = new lora::ChannelPlan_EU868();
-#elif CHANNEL_PLAN == CP_KR920
-    plan = new lora::ChannelPlan_KR920();
-#elif CHANNEL_PLAN == CP_AS923
-    plan = new lora::ChannelPlan_AS923();
-#elif CHANNEL_PLAN == CP_AS923_JAPAN
-    plan = new lora::ChannelPlan_AS923_Japan();
-#elif CHANNEL_PLAN == CP_IN865
-    plan = new lora::ChannelPlan_IN865();
-#endif
-    assert(plan);
-
-    dot = mDot::getInstance(plan);
-    assert(dot);
-
-    // attach the custom events handler
-    dot->setEvents(&events);
-
-    if (!dot->getStandbyFlag()) 
-    {
-        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
-
-        // start from a well-known state
-        logInfo("defaulting Dot configuration");
-        dot->resetConfig();
-        dot->resetNetworkSession();
-
-        // make sure library logging is turned on
-        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
-
-        // update configuration if necessary
-        if (dot->getJoinMode() != mDot::OTA) 
-        {
-            logInfo("changing network join mode to OTA");
-            if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) 
-            {
-                logError("failed to set network join mode to OTA");
-            }
-        }
-        // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
-        // only one method or the other should be used!
-        // network ID = crc64(network name)
-        // network KEY = cmac(network passphrase)
-        update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
-        //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
-
-        // configure network link checks
-        // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
-        // check the link every count packets
-        // declare the Dot disconnected after threshold failed link checks
-        // for count = 3 and threshold = 5, the Dot will ask for a link check response every 5 packets and will consider the connection lost if it fails to receive 3 responses in a row
-        update_network_link_check_config(3, 5);
-
-        // enable or disable Adaptive Data Rate
-        dot->setAdr(adr);
-    
-        // save changes to configuration
-        logInfo("saving configuration");
-        if (!dot->saveConfig()) 
-        {
-            logError("failed to save configuration");
-        }
-
-        // display configuration
-        display_config();
-    } 
-    else 
-    {
-        // restore the saved session if the dot woke from deepsleep mode
-        // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
-        logInfo("restoring network session from NVM");
-        dot->restoreNetworkSession();
-    }
-
-    while (true) 
-    {
-        uint16_t light;
-        std::vector<uint8_t> tx_data;
-        std::string texto = "D04DE4F5";
-        
-
-        // join network if not joined
-        if (!dot->getNetworkJoinStatus()) {
-            join_network();
-        }
-
-
-        // get some dummy data and send it to the gateway
-        light = lux.read_u16();
-        tx_data.push_back((light >> 8) & 0xFF);
-        tx_data.push_back(light & 0xFF);
-        //logInfo("light DUMMY: %lu [0x%04X]", light, light);
-        //send_data(tx_data);
-
-        logInfo("Enviando texto: \"%s\"\n",texto);
-        send_string_data(texto);
-        
-        // if going into deepsleep mode, save the session so we don't need to join again after waking up
-        // not necessary if going into sleep mode since RAM is retained
-        if (deep_sleep) 
-        {
-            logInfo("saving network session to NVM");
-            dot->saveNetworkSession();
-        }
-        
-        // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
-        sleep_wake_rtc_only(deep_sleep,delay_sleep);
-        //sleep_wake_interrupt_only(deep_sleep);
-        //sleep_wake_rtc_or_interrupt(deep_sleep);
-    }
- 
-    return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libNDEF.lib	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/ST-Expansion-SW-Team/code/libNDEF/#de13951f30f6
--- a/libmDot-mbed5.lib	Sat Sep 30 22:01:56 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://os.mbed.com/teams/MultiTech/code/libmDot-mbed5/#255e2ddc294e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libxDot-mbed5.lib	Sat Oct 03 22:39:19 2020 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/teams/MultiTech/code/libxDot-mbed5/#47c194c843d5
--- a/mbed-os.lib	Sat Sep 30 22:01:56 2017 +0000
+++ b/mbed-os.lib	Sat Oct 03 22:39:19 2020 +0000
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/mbed-os/#fc1836545dcc2fc86f03b01292b62bf2089f67c3
+https://github.com/ARMmbed/mbed-os/#91e6db1ea251ffcc973001ed90477f42fdca5751