diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index c4d902eb9..22d4a42a4 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -41,6 +41,7 @@ jobs: {"fqbn": "arduino:samd:mkr1000", "type": "mkr1000"}, {"fqbn": "arduino:samd:mkrwifi1010", "type": "nina"}, {"fqbn": "arduino:samd:nano_33_iot", "type": "nina"}, + {"fqbn": "arduino:megaavr:uno2018", "type": "megaavr"}, {"fqbn": "arduino:samd:mkrwan1300", "type": "wan"}, {"fqbn": "arduino:samd:mkrgsm1400", "type": "gsm"}, {"fqbn": "arduino:samd:mkrnb1500", "type": "nb"}, @@ -79,6 +80,20 @@ jobs: sketch-paths: | - examples/utility/Provisioning - examples/utility/SelfProvisioning + # Uno WiFi Rev2 + - board: + type: "megaavr" + platforms: | + - name: arduino:megaavr + libraries: | + - name: ArduinoECCX08 + - source-url: https://github.com/arduino-libraries/Arduino_AVRSTL.git + - name: WiFiNINA + - name: Arduino_JSON + - name: ArduinoBearSSL + sketch-paths: | + - examples/utility/Provisioning + - examples/utility/SelfProvisioning # LoRaWAN boards - board: type: "wan" diff --git a/library.properties b/library.properties index 9b41bd40e..0b450496c 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266 +architectures=mbed,samd,esp8266,megaavr includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 2515575c9..59292db11 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -30,31 +30,65 @@ #define NTP_USE_RANDOM_PORT (1) #endif -#ifndef DBG_ERROR - #define DBG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +#ifndef DEBUG_ERROR +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +# else +# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +# endif #endif -#ifndef DBG_WARNING - #define DBG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +#ifndef DEBUG_WARNING +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_WARNING(fmt, ...) +# else +# define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +# endif #endif -#ifndef DBG_INFO - #define DBG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +#ifndef DEBUG_INFO +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_INFO(fmt, ...) +# else +# define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +# endif #endif -#ifndef DBG_DEBUG - #define DBG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +#ifndef DEBUG_DEBUG +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_DEBUG(fmt, ...) +# else +# define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +# endif #endif -#ifndef DBG_VERBOSE - #define DBG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +#ifndef DEBUG_VERBOSE +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_VERBOSE(fmt, ...) +# else +# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# endif +#endif + +#if defined(ARDUINO_AVR_UNO_WIFI_REV2) && !(defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE)) +/* Provide defines for constants provided within Arduino_DebugUtils + * in order to allow older sketches using those constants to still + * compile. + */ +# define DBG_NONE -1 +# define DBG_ERROR 0 +# define DBG_WARNING 1 +# define DBG_INFO 2 +# define DBG_DEBUG 3 +# define DBG_VERBOSE 4 #endif /****************************************************************************** * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_STORAGE_SNU (1) #else #define OTA_STORAGE_SNU (0) @@ -66,20 +100,25 @@ #define OTA_STORAGE_SSU (0) #endif -#if OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU +#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) #endif -#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRWIFI1010) || \ - defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ +#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ defined(ARDUINO_PORTENTA_H7_M4) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_HAS_OFFLOADED_ECCX08 + #define HAS_TCP +#endif + #if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) #define HAS_LORA #endif diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index cf7557e5a..0f117e993 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -179,3 +179,8 @@ void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const eve (*callback)(); } } + +__attribute__((weak)) void setDebugMessageLevel(int const /* level */) +{ + /* do nothing */ +} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 1be41e9e8..0130e3efc 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -25,7 +25,10 @@ #include #include -#include + +#if defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE) +# include +#endif #include "AIoTC_Const.h" @@ -154,4 +157,7 @@ class ArduinoIoTCloudClass #include "ArduinoIoTCloudLPWAN.h" #endif +// declaration for boards without debug library +void setDebugMessageLevel(int const level); + #endif diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 9f8bfd9b2..29458f21a 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -87,8 +87,8 @@ void ArduinoIoTCloudLPWAN::update() void ArduinoIoTCloudLPWAN::printDebugInfo() { - DBG_INFO(F("***** Arduino IoT Cloud LPWAN - configuration info *****")); - DBG_INFO(F("Thing ID: %s"), getThingId().c_str()); + DEBUG_INFO("***** Arduino IoT Cloud LPWAN - configuration info *****"); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); } /****************************************************************************** @@ -106,8 +106,8 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DBG_VERBOSE(F("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); - DBG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); + DEBUG_INFO("Connected to Arduino IoT Cloud"); return State::Connected; } @@ -115,7 +115,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() { if (!connected()) { - DBG_ERROR(F("ArduinoIoTCloudLPWAN::%s connection to gateway lost"), __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudLPWAN::%s connection to gateway lost", __FUNCTION__); return State::ConnectPhy; } @@ -175,4 +175,4 @@ int ArduinoIoTCloudLPWAN::writeProperties(const byte data[], int length) ArduinoIoTCloudLPWAN ArduinoCloud; -#endif \ No newline at end of file +#endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 29d2b042a..4a68ac7ae 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -28,6 +28,11 @@ #include "tls/utility/CryptoUtil.h" #endif +#ifdef BOARD_HAS_OFFLOADED_ECCX08 +#include +#include "tls/utility/CryptoUtil.h" +#endif + #include "utility/ota/OTA.h" #include "utility/ota/FlashSHA256.h" @@ -98,7 +103,16 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _brokerAddress = brokerAddress; _brokerPort = brokerPort; -#if OTA_ENABLED +#if defined(__AVR__) + String const nina_fw_version = WiFi.firmwareVersion(); + if (nina_fw_version < "1.4.2") + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s NINA firmware needs to be >= 1.4.2 to support cloud on Uno WiFi Rev. 2, current %s", __FUNCTION__, nina_fw_version.c_str()); + return 0; + } +#endif /* AVR */ + +#if OTA_ENABLED && !defined(__AVR__) /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash * until we detect one containing only 0xFF (= flash erased). This only works @@ -112,10 +126,36 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); #endif /* OTA_ENABLED */ + #ifdef BOARD_HAS_OFFLOADED_ECCX08 + if (!ECCX08.begin()) + { + DEBUG_ERROR("ECCX08.begin() failed."); + return 0; + } + if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + { + DEBUG_ERROR("CryptoUtil::readDeviceId(...) failed."); + return 0; + } + ECCX08.end(); + #endif + #ifdef BOARD_HAS_ECCX08 - if (!ECCX08.begin()) { DBG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); return 0; } - if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR(F("Cryptography processor read failure.")); return 0; } - if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) { DBG_ERROR(F("Cryptography certificate reconstruction failure.")); return 0; } + if (!ECCX08.begin()) + { + DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); + return 0; + } + if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + { + DEBUG_ERROR("Cryptography processor read failure."); + return 0; + } + if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) + { + DEBUG_ERROR("Cryptography certificate reconstruction failure."); + return 0; + } _sslClient.setClient(_connection->getClient()); _sslClient.setEccSlot(static_cast(ECCX08Slot::Key), _eccx08_cert.bytes(), _eccx08_cert.length()); #elif defined(BOARD_ESP) @@ -146,11 +186,11 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(DEVICE_WINS); #endif /* OTA_ENABLED */ -#if OTA_STORAGE_SNU +#if OTA_STORAGE_SNU && OTA_ENABLED String const nina_fw_version = WiFi.firmwareVersion(); if (nina_fw_version < "1.4.1") { _ota_cap = false; - DBG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s"), __FUNCTION__, nina_fw_version.c_str()); + DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s", __FUNCTION__, nina_fw_version.c_str()); } else { _ota_cap = true; @@ -187,10 +227,10 @@ int ArduinoIoTCloudTCP::connected() void ArduinoIoTCloudTCP::printDebugInfo() { - DBG_INFO(F("***** Arduino IoT Cloud - configuration info *****")); - DBG_INFO(F("Device ID: %s"), getDeviceId().c_str()); - DBG_INFO(F("Thing ID: %s"), getThingId().c_str()); - DBG_INFO(F("MQTT Broker: %s:%d"), _brokerAddress.c_str(), _brokerPort); + DEBUG_INFO("***** Arduino IoT Cloud - configuration info *****"); + DEBUG_INFO("Device ID: %s", getDeviceId().c_str()); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); + DEBUG_INFO("MQTT Broker: %s:%d", _brokerAddress.c_str(), _brokerPort); } /****************************************************************************** @@ -208,7 +248,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } @@ -217,7 +257,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) return State::SubscribeMqttTopics; - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not connect to %s:%d"), __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::ConnectPhy; } @@ -225,8 +265,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_dataTopicIn)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _dataTopicIn.c_str()); - DBG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); +#if !defined(__AVR__) + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); +#endif return State::SubscribeMqttTopics; } @@ -234,13 +276,15 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_shadowTopicIn)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _shadowTopicIn.c_str()); - DBG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); +#if !defined(__AVR__) + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); +#endif return State::SubscribeMqttTopics; } } - DBG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_INFO("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); if (_shadowTopicIn != "") @@ -255,7 +299,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() unsigned long const now = millis(); if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values requested"), __FUNCTION__, now); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); _lastSyncRequestTickTime = now; } @@ -267,7 +311,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); /* Forcefully disconnect MQTT client and trigger a reconnection. */ _mqttClient.stop(); @@ -347,7 +391,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -397,7 +441,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); /* Status flag to prevent the reset from being executed * when HTTPS download is not supported. @@ -413,7 +457,7 @@ void ArduinoIoTCloudTCP::onOTARequest() uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); _ota_error = static_cast(OTAError::DownloadFailed); return; } @@ -422,9 +466,11 @@ void ArduinoIoTCloudTCP::onOTARequest() ota_download_success = true; #endif /* OTA_STORAGE_SNU */ +#ifndef __AVR__ /* Perform the reset to reboot to SxU. */ if (ota_download_success) NVIC_SystemReset(); +#endif } #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 78eab72b1..c26e08ec3 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -33,6 +33,11 @@ #include #endif +#ifdef BOARD_HAS_OFFLOADED_ECCX08 +#include "tls/utility/ECCX08Cert.h" +#include +#endif + #include /****************************************************************************** @@ -60,7 +65,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual int connected () override; virtual void printDebugInfo() override; - #ifdef BOARD_HAS_ECCX08 + #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #else int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); @@ -98,9 +103,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass int _mqtt_data_len; bool _mqtt_data_request_retransmit; - #ifdef BOARD_HAS_ECCX08 + #if defined(BOARD_HAS_ECCX08) ECCX08CertClass _eccx08_cert; BearSSLClient _sslClient; + #elif defined(BOARD_HAS_OFFLOADED_ECCX08) + ECCX08CertClass _eccx08_cert; + WiFiBearSSLClient _sslClient; #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; String _password; diff --git a/src/cbor/CBORDecoder.h b/src/cbor/CBORDecoder.h index a0f9d7360..d1bf91ca0 100644 --- a/src/cbor/CBORDecoder.h +++ b/src/cbor/CBORDecoder.h @@ -22,6 +22,12 @@ INCLUDE ******************************************************************************/ +#include + +#ifdef __AVR__ +# include +#endif + #undef max #undef min #include diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index abaa9d4b7..2370a7b50 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -22,6 +22,16 @@ * INCLUDE ******************************************************************************/ +#include + +#ifdef __AVR__ +# include +#endif + +#undef max +#undef min +#include + #include "../property/PropertyContainer.h" /****************************************************************************** diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h index e81df0ec3..cb759fd5b 100644 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ b/src/cbor/lib/tinycbor/src/cbor.h @@ -25,6 +25,11 @@ #ifndef CBOR_H #define CBOR_H +#ifdef __AVR__ +#define FP_NAN NAN +#define FP_INFINITE INFINITY +#endif + #ifndef assert #include #endif diff --git a/src/cbor/lib/tinycbor/src/cborpretty.c b/src/cbor/lib/tinycbor/src/cborpretty.c index 2db4b253a..b82b985ac 100644 --- a/src/cbor/lib/tinycbor/src/cborpretty.c +++ b/src/cbor/lib/tinycbor/src/cborpretty.c @@ -28,6 +28,8 @@ # define __STDC_LIMIT_MACROS 1 #endif +#ifndef __AVR__ + #include "cbor.h" #include "cborinternal_p.h" #include "compilersupport_p.h" @@ -580,4 +582,6 @@ CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *t #pragma GCC diagnostic pop +#endif // __AVR__ + /** @} */ diff --git a/src/cbor/lib/tinycbor/src/cbortojson.c b/src/cbor/lib/tinycbor/src/cbortojson.c index ed6a16666..0e669f27e 100644 --- a/src/cbor/lib/tinycbor/src/cbortojson.c +++ b/src/cbor/lib/tinycbor/src/cbortojson.c @@ -30,6 +30,8 @@ # define __STDC_LIMIT_MACROS 1 #endif +#ifndef __AVR__ + #include "cbor.h" #include "cborjson.h" #include "cborinternal_p.h" @@ -701,4 +703,6 @@ CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) #pragma GCC diagnostic pop +#endif // __AVR__ + /** @} */ diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c index e535c9c79..707dbb1c4 100644 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ b/src/cbor/lib/tinycbor/src/open_memstream.c @@ -34,6 +34,10 @@ #include +#ifdef __AVR__ +typedef size_t ssize_t; +#endif + typedef ssize_t RetType; typedef size_t LenType; diff --git a/src/nonstd/nonstd.h b/src/nonstd/nonstd.h new file mode 100644 index 000000000..b591919c6 --- /dev/null +++ b/src/nonstd/nonstd.h @@ -0,0 +1,235 @@ +#pragma once +#ifdef __AVR__ +#include +extern void * operator new(size_t size, void * ptr); +namespace nonstd{ + + templatestruct tag{using type=T;}; + templateusing type_t=typename Tag::type; + + using size_t=decltype(sizeof(int)); + + //move + + template + T&& move(T&t){return static_cast(t);} + + //forward + + template + struct remove_reference:tag{}; + template + struct remove_reference:tag{}; + templateusing remove_reference_t=type_t>; + + template + T&& forward( remove_reference_t& t ) { + return static_cast(t); + } + template + T&& forward( remove_reference_t&& t ) { + return static_cast(t); + } + + //decay + + template + struct remove_const:tag{}; + template + struct remove_const:tag{}; + + template + struct remove_volatile:tag{}; + template + struct remove_volatile:tag{}; + + template + struct remove_cv:remove_const>>{}; + + + template + struct decay3:remove_cv{}; + template + struct decay3:tag{}; + template + struct decay2:decay3{}; + template + struct decay2:tag{}; + + template + struct decay:decay2>{}; + + template + using decay_t=type_t>; + + //is_convertible + + template + T declval(); // no implementation + + template + struct integral_constant{ + static constexpr T value=t; + constexpr integral_constant() {}; + constexpr operator T()const{ return value; } + constexpr T operator()()const{ return value; } + }; + template + using bool_t=integral_constant; + using true_type=bool_t; + using false_type=bool_t; + + templatestruct voider:tag{}; + templateusing void_t=type_t>; + + namespace details { + templateclass Z, class, class...Ts> + struct can_apply:false_type{}; + templateclass Z, class...Ts> + struct can_apply>, Ts...>:true_type{}; + } + templateclass Z, class...Ts> + using can_apply = details::can_apply; + + namespace details { + template + using try_convert = decltype( To{declval()} ); + } + template + struct is_convertible : can_apply< details::try_convert, From, To > {}; + template<> + struct is_convertible:true_type{}; + + //enable_if + + template + struct enable_if {}; + template + struct enable_if:tag{}; + template + using enable_if_t=type_t>; + + //res_of + + namespace details { + template + using invoke_t = decltype( declval()(declval()...) ); + + template + struct res_of {}; + template + struct res_of>>: + tag> + {}; + } + template + using res_of = details::res_of; + template + using res_of_t=type_t>; + + //aligned_storage + + template + struct alignas(align) aligned_storage_t { + char buff[size]; + }; + + //is_same + + template + struct is_same:false_type{}; + template + struct is_same:true_type{}; + + template + struct small_task; + + template + struct small_task{ + struct vtable_t { + void(*mover)(void* src, void* dest); + void(*destroyer)(void*); + R(*invoke)(void const* t, Args&&...args); + template + static vtable_t const* get() { + static const vtable_t table = { + [](void* src, void*dest) { + new(dest) T(move(*static_cast(src))); + }, + [](void* t){ static_cast(t)->~T(); }, + [](void const* t, Args&&...args)->R { + return (*static_cast(t))(forward(args)...); + } + }; + return &table; + } + }; + vtable_t const* table = nullptr; + aligned_storage_t data; + template, + enable_if_t{}>* = nullptr, + enable_if_t, R >{}>* = nullptr + > + small_task( F&& f ): + table( vtable_t::template get() ) + { + static_assert( sizeof(dF) <= sz, "object too large" ); + static_assert( alignof(dF) <= algn, "object too aligned" ); + new(&data) dF(forward(f)); + } + ~small_task() { + if (table) + table->destroyer(&data); + } + small_task(const small_task& o): + table(o.table) + { + data = o.data; + } + small_task(small_task&& o): + table(o.table) + { + if (table) + table->mover(&o.data, &data); + } + small_task(){} + small_task& operator=(const small_task& o){ + this->~small_task(); + new(this) small_task( move(o) ); + return *this; + } + small_task& operator=(small_task&& o){ + this->~small_task(); + new(this) small_task( move(o) ); + return *this; + } + explicit operator bool()const{return table;} + R operator()(Args...args)const{ + return table->invoke(&data, forward(args)...); + } + }; + + template + inline bool operator==(const small_task& __f, nullptr_t) + { return !static_cast(__f); } + + /// @overload + template + inline bool operator==(nullptr_t, const small_task& __f) + { return !static_cast(__f); } + + template + inline bool operator!=(const small_task& __f, nullptr_t) + { return static_cast(__f); } + + /// @overload + template + inline bool operator!=(nullptr_t, const small_task& __f) + { return static_cast(__f); } + + template + using function = small_task; +} + +#endif \ No newline at end of file diff --git a/src/property/Property.cpp b/src/property/Property.cpp index bccbae1b8..20be6e35b 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -189,7 +189,12 @@ CborError Property::appendAttributeReal(String value, String attributeName, Cbor }, encoder); } -CborError Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { +#ifdef __AVR__ +CborError Property::appendAttributeName(String attributeName, nonstd::functionappendValue, CborEncoder *encoder) +#else +CborError Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) +#endif +{ if (attributeName != "") { // when the attribute name string is not empty, the attribute identifier is incremented in order to be encoded in the message if the _lightPayload flag is set _attributeIdentifier++; @@ -271,7 +276,11 @@ void Property::setAttributeReal(String& value, String attributeName) { }); } +#ifdef __AVR__ +void Property::setAttributeReal(String attributeName, nonstd::functionsetValue) +#else void Property::setAttributeReal(String attributeName, std::functionsetValue) +#endif { if (attributeName != "") { _attributeIdentifier++; diff --git a/src/property/Property.h b/src/property/Property.h index 4b5900782..803d77049 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -28,11 +28,18 @@ ******************************************************************************/ #include -// in order to allow to define its own max and min functions + #undef max #undef min + +#ifdef __AVR__ +# include +# include +#else +# include +#endif + #include -#include #include "../cbor/lib/tinycbor/cbor-lib.h" @@ -133,6 +140,10 @@ typedef void(*OnSyncCallbackFunc)(Property &); CLASS DECLARATION ******************************************************************************/ +#ifdef __AVR__ +#include "nonstd/nonstd.h" +#endif + class Property { public: @@ -177,13 +188,18 @@ class Property CborError appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); +#ifndef __AVR__ CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); + void setAttributeReal(String attributeName, std::functionsetValue); +#else + CborError appendAttributeName(String attributeName, nonstd::functionf, CborEncoder *encoder); + void setAttributeReal(String attributeName, nonstd::functionsetValue); +#endif void setAttributesFromCloud(std::list * map_data_list); void setAttributeReal(bool& value, String attributeName = ""); void setAttributeReal(int& value, String attributeName = ""); void setAttributeReal(float& value, String attributeName = ""); void setAttributeReal(String& value, String attributeName = ""); - void setAttributeReal(String attributeName, std::functionsetValue); String getAttributeName(String propertyName, char separator); virtual bool isDifferentFromCloud() = 0; diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index 3fd807a34..effa7d966 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -22,8 +22,14 @@ INCLUDE ******************************************************************************/ +#include + #include "Property.h" +#ifdef __AVR__ +# include +#endif + #undef max #undef min #include diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c index fb1924fe6..1ba0968e4 100644 --- a/src/tls/bearssl/dec32be.c +++ b/src/tls/bearssl/dec32be.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c index 471cddcac..dde2295d1 100644 --- a/src/tls/bearssl/enc32be.c +++ b/src/tls/bearssl/enc32be.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c index fb33c9b16..c17638706 100644 --- a/src/tls/bearssl/sha2small.c +++ b/src/tls/bearssl/sha2small.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/utility/CryptoUtil.cpp b/src/tls/utility/CryptoUtil.cpp index 248cc2d79..4348bc38d 100644 --- a/src/tls/utility/CryptoUtil.cpp +++ b/src/tls/utility/CryptoUtil.cpp @@ -21,7 +21,7 @@ #include "CryptoUtil.h" -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) /****************************************************************************** * PUBLIC MEMBER FUNCTIONS diff --git a/src/tls/utility/CryptoUtil.h b/src/tls/utility/CryptoUtil.h index 68e4ee5b3..32239a486 100644 --- a/src/tls/utility/CryptoUtil.h +++ b/src/tls/utility/CryptoUtil.h @@ -24,7 +24,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) #include #include diff --git a/src/tls/utility/ECCX08Cert.cpp b/src/tls/utility/ECCX08Cert.cpp index 0a232be00..164309e9a 100644 --- a/src/tls/utility/ECCX08Cert.cpp +++ b/src/tls/utility/ECCX08Cert.cpp @@ -21,7 +21,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "../../tls/bearssl/bearssl_hash.h" #include diff --git a/src/tls/utility/ECCX08Cert.h b/src/tls/utility/ECCX08Cert.h index 95437b352..4e1ef6209 100644 --- a/src/tls/utility/ECCX08Cert.h +++ b/src/tls/utility/ECCX08Cert.h @@ -24,7 +24,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 9f908a8c8..12290a612 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -20,7 +20,7 @@ ******************************************************************************/ #include -#if OTA_ENABLED +#if OTA_ENABLED && !defined(__AVR__) #include "FlashSHA256.h" @@ -100,8 +100,8 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz sha256_str += buf; }); /* Do some debug printout. */ - DBG_VERBOSE("SHA256: %d bytes read", flash_addr); - DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); + DEBUG_VERBOSE("SHA256: %d bytes read", flash_addr); + DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); return sha256_str; } diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 208d5e616..bd1476fba 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -25,7 +25,7 @@ #include #if OTA_ENABLED -#if OTA_STORAGE_SNU +#if OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #include #endif /* OTA_STORAGE_SNU */ diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index b5e35dcd7..07d50fec6 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -105,6 +105,7 @@ unsigned long TimeService::getRemoteTime() return connection_time; } +#ifndef __AVR__ /* If no valid network time is available try to obtain the * time via NTP next. */ @@ -112,6 +113,7 @@ unsigned long TimeService::getRemoteTime() if(isTimeValid(ntp_time)) { return ntp_time; } +#endif #endif /* ifndef HAS_LORA */