diff --git a/.vscode/arduino.json b/.vscode/arduino.json index 4fc6458..95194fb 100644 --- a/.vscode/arduino.json +++ b/.vscode/arduino.json @@ -1,7 +1,7 @@ { "configuration": "PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none", "board": "esp32:esp32:esp32", - "sketch": "project/src/Main/Main.ino", + "sketch": "project/Main/Main.ino", "output": "build", - "port": "/dev/ttyUSB0" + "port": "COM3" } \ No newline at end of file diff --git a/README.md b/README.md index 8f049fa..6b5e086 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,31 @@ # Thesis on Precision Air Quality Measurements Over Network via the MQTT Protocol using ESP32 MCUs -## Main milestones and their subgoals - -- [x] SDK -- [x] WiFi connection -- [x] Peripheral communication -- [x] Communication with a cloud storage provider - - [x] Investigate possible cloud providers. - - Possible providers are: [ESP-IDF supported Cloud Frameworks](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32/libraries-and-frameworks/cloud-frameworks.html). - - The choice fell on [Azure IoT](https://azure.microsoft.com/en-us/overview/iot/). - - TBA - - TBA -- [ ] PCB implementation -- [ ] Collect data and export it -- [ ] Printable formal thesis -- [ ] *(Optional)* Create a frontend for interactive data representation - -## These links are useful resources I have used, grouped by topics: +This project aims to create an expandable smart net of air quality sensors. I wish to provide firmware, a backend solution for data processing, communication and a hardware prototype. -### Containerization +In theory almost all the hardware, software and infrastructure can be swapped out if one complies with the interfaces described in the project, but due to the nature and complexity of the system, some might not integrate as well. + +## Development tools used -- [Docker Compose Syntax: Volume or Bind Mount?](https://maximorlov.com/docker-compose-syntax-volume-or-bind-mount/) +- [Visual Studio Code](https://code.visualstudio.com/) +- [Arduino Expansion Pack](https://marketplace.visualstudio.com/items?itemName=mpty.pack-arduino) +- [C/C++ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack) - [IoT Telemetry Simulator](https://github.com/azure-samples/iot-telemetry-simulator/tree/master/) -- [VSCode Remote Development Docoumentation](https://code.visualstudio.com/api/advanced-topics/remote-extensions#architecture-and-extension-types) + +## Libraries used in firmware + +The following libraries and board definition(s) should be installed via the Arduino framework. + +The versions referenced here are guaranteed to compile and function as expected, but you can try upgrading them if you want to, however it is possible that between versions there might be incompatibility. It is also possible that if you wish to build and flash firmware which communicates with a cloud platform with Azure, you might have to update the cloud configuration if not using the Azure templates in this repository. Always consult the documentation properly. + +- [esp32 by Espressif Systems](https://github.com/espressif/arduino-esp32) (version 2.0.7) (Board definition for Arduino) +- [DHT sensor library by Adafruit](https://github.com/adafruit/DHT-sensor-library) (version 1.4.4) +- [ArduinoJSON](https://github.com/bblanchon/ArduinoJson) (version 6.21.0) +- [Adafruit MCP3008 by Adafruit](https://github.com/adafruit/Adafruit_MCP3008) (version 1.3.1) +- [Azure SDK for C by Microsoft Corporation](https://github.com/Azure/azure-sdk-for-c) (version 1.1.3) + +## Useful links + +### Containerization + +- [Docker Compose Syntax: Volume or Bind Mount?](https://maximorlov.com/docker-compose-syntax-volume-or-bind-mount/): For configuring the telemetry simulator. +- [VSCode Remote Development Docoumentation](https://code.visualstudio.com/api/advanced-topics/remote-extensions#architecture-and-extension-types): For developing remotely or on immutable systems. \ No newline at end of file diff --git a/project/Main/Main.ino b/project/Main/Main.ino new file mode 100644 index 0000000..8dab4c9 --- /dev/null +++ b/project/Main/Main.ino @@ -0,0 +1,16 @@ +// Licensed under: GNU GENERAL PUBLIC LICENSE Version 2 + +#include "src/tasks/Tasks.hpp" + +void setup() +{ + Tasks::configureLocalPeripherials(); + Tasks::initializeConnection(); +} + +void loop() +{ + Tasks::doMeasurements(); + Tasks::sendTelemetry(); + Tasks::Helpers::startSleep(); +} \ No newline at end of file diff --git a/project/src/Main/Common.cpp b/project/Main/src/common/Common.cpp similarity index 85% rename from project/src/Main/Common.cpp rename to project/Main/src/common/Common.cpp index 14fd115..ba81c37 100644 --- a/project/src/Main/Common.cpp +++ b/project/Main/src/common/Common.cpp @@ -1,9 +1,9 @@ // Licensed under: GNU GENERAL PUBLIC LICENSE Version 2 #include -#include "Common.h" +#include "Common.hpp" uint32_t getSecsSinceEpoch() { return (uint32_t)time(NULL); -} \ No newline at end of file +} diff --git a/project/src/Main/Common.h b/project/Main/src/common/Common.hpp similarity index 52% rename from project/src/Main/Common.h rename to project/Main/src/common/Common.hpp index 7cb69d7..1219b80 100644 --- a/project/src/Main/Common.h +++ b/project/Main/src/common/Common.hpp @@ -1,9 +1,9 @@ // Licensed under: GNU GENERAL PUBLIC LICENSE Version 2 -#ifndef COMMON_H -#define COMMON_H +#ifndef COMMON_HPP +#define COMMON_HPP -#include "SerialLogger.h" +#include "serial-logger/SerialLogger.hpp" #define DEBUG_MODE @@ -22,25 +22,27 @@ #define NULL_TERMINATOR '\0' // WARNING: Only use this macro if the argument is an actual 1-dimensional C-like array. -// Passing normal pointers will cause "sizeof(arg)" to return the system pointer width, resulting in a silent bug. +// Passing normal pointers will cause "sizeof(arg)" to return the system pointer width, resulting in a silent bug. #define sizeofarray(arg) (sizeof(arg) / sizeof(arg[0])) uint32_t getSecsSinceEpoch(); #ifdef DEBUG_MODE - #define LogInfo(text) Logger.Info(text) - #define LogError(text) Logger.Error(text) - #define SerialPrint(text) Serial.print(text) - #define SerialPrintln() Serial.println() - #define SerialPrintlnTimeinfo(timeinfo, formattedText) Serial.println(timeinfo, formattedText) - #define DelayForSerialConnection(time) delay(time); +#define LogInfo(text) Logger.Info(text) +#define LogWarning(text) Logger.Warning(text) +#define LogError(text) Logger.Error(text) +#define SerialPrint(text) Serial.print(text) +#define SerialNewLine() Serial.println() +#define SerialTimeinfo(timeinfo, formattedText) Serial.println(timeinfo, formattedText) +#define DelayForSerialConnection(time) delay(time); #else - #define LogInfo(text) - #define LogError(text) - #define SerialPrint(text) - #define SerialPrintln() - #define SerialPrintlnTimeinfo(timeinfo, formattedText) - #define DelayForSerialConnection(time) +#define LogInfo(text) +#define LogWarning(text) +#define LogError(text) +#define SerialPrint(text) +#define SerialNewLine() +#define SerialTimeinfo(timeinfo, formattedText) +#define DelayForSerialConnection(time) #endif -#endif \ No newline at end of file +#endif // COMMON_HPP diff --git a/project/Main/src/common/CommonConfig.hpp b/project/Main/src/common/CommonConfig.hpp new file mode 100644 index 0000000..af59495 --- /dev/null +++ b/project/Main/src/common/CommonConfig.hpp @@ -0,0 +1,34 @@ +#ifndef COMMON_CONFIG_HPP +#define COMMON_CONFIG_HPP + +#include "../network/Network.hpp" + +#define DEFAULT_INBOUND_DATA_SIZE_BYTES 128 +#define DEFAULT_SERIAL_BAUD_RATE 9600 +#define DEFAULT_TIME_TO_SLEEP_IN_S 30 +#define DEFAULT_DELAY_FOR_SERIAL_CONNECTION 5000 + +#define CONFIG_SERIAL_BAUD_RATE DEFAULT_SERIAL_BAUD_RATE +#define CONFIG_TIME_TO_SLEEP_IN_S DEFAULT_TIME_TO_SLEEP_IN_S +#define CONFIG_DELAY_FOR_SERIAL_CONNECTION DEFAULT_DELAY_FOR_SERIAL_CONNECTION + +namespace Configurations +{ + namespace Common + { + namespace Defaults + { + constexpr uint8_t INBOUND_DATA_SIZE_BYTES = 128; + constexpr uint16_t SERIAL_BAUD_RATE = 9600; + constexpr uint16_t TIME_TO_SLEEP_SEC = 30; + constexpr uint16_t DELAY_FOR_SERIAL_MILISEC = 5000; + } + + const uint8_t INBOUND_DATA_SIZE_BYTES = Defaults::INBOUND_DATA_SIZE_BYTES; + const uint16_t SERIAL_BAUD_RATE = Defaults::SERIAL_BAUD_RATE; + const uint16_t TIME_TO_SLEEP_SEC = Defaults::TIME_TO_SLEEP_SEC; + const uint16_t DELAY_FOR_SERIAL_MILISEC = Defaults::DELAY_FOR_SERIAL_MILISEC; + } +} + +#endif // COMMON_CONFIG_HPP diff --git a/project/src/Main/SerialLogger.cpp b/project/Main/src/common/serial-logger/SerialLogger.cpp similarity index 81% rename from project/src/Main/SerialLogger.cpp rename to project/Main/src/common/serial-logger/SerialLogger.cpp index 2cb444b..6f5a09c 100644 --- a/project/src/Main/SerialLogger.cpp +++ b/project/Main/src/common/serial-logger/SerialLogger.cpp @@ -1,14 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT +// Modified by project author. -#include "SerialLogger.h" #include +#include "SerialLogger.hpp" + #define UNIX_EPOCH_START_YEAR 1900 static void writeTime() { - struct tm* ptm; + struct tm *ptm; time_t now = time(NULL); ptm = gmtime(&now); @@ -44,10 +46,10 @@ static void writeTime() Serial.print(ptm->tm_sec); } -SerialLogger::SerialLogger() { Serial.begin(SERIAL_LOGGER_BAUD_RATE); } - -// TODO: Use conditional compilation here instead of wrapping this into one. -// TODO: Wrap these into one function call rather. +SerialLogger::SerialLogger() +{ + Serial.begin(SERIAL_LOGGER_BAUD_RATE); +} void SerialLogger::Info(String message) { diff --git a/project/src/Main/SerialLogger.h b/project/Main/src/common/serial-logger/SerialLogger.hpp similarity index 73% rename from project/src/Main/SerialLogger.h rename to project/Main/src/common/serial-logger/SerialLogger.hpp index 10bdaaa..8998d58 100644 --- a/project/src/Main/SerialLogger.h +++ b/project/Main/src/common/serial-logger/SerialLogger.hpp @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT +// Modified by project author. -#ifndef SERIALLOGGER_H -#define SERIALLOGGER_H +#ifndef SERIALLOGGER_HPP +#define SERIALLOGGER_HPP #include -#include "CommonConfig.h" +#include "../CommonConfig.hpp" #ifndef SERIAL_LOGGER_BAUD_RATE #define SERIAL_LOGGER_BAUD_RATE CONFIG_SERIAL_BAUD_RATE @@ -22,4 +23,4 @@ class SerialLogger extern SerialLogger Logger; -#endif // SERIALLOGGER_H +#endif // SERIALLOGGER_HPP diff --git a/project/src/Main/Network.cpp b/project/Main/src/network/Network.cpp similarity index 83% rename from project/src/Main/Network.cpp rename to project/Main/src/network/Network.cpp index ce2b2ae..dd4e8c5 100644 --- a/project/src/Main/Network.cpp +++ b/project/Main/src/network/Network.cpp @@ -9,15 +9,16 @@ #include #include -#include "CommonConfig.h" -#include "Network.h" -#include "NetworkConfig.h" +#include "../common/CommonConfig.hpp" +#include "Network.hpp" +#include "NetworkConfig.hpp" -#include "AzIoTSasToken.h" -#include "SecretsConfig.h" +#include "azure/AzIoTSasToken.hpp" +#include "azure/SecretsConfig.hpp" -#include "SerialLogger.h" -#include "NetworkConfig.h" +#include "../common/serial-logger/SerialLogger.hpp" + +#include "NetworkConfig.hpp" #define MAGIC_TIMESTAMP (uint32_t)1510592825 @@ -39,13 +40,13 @@ namespace Network static az_iot_hub_client client; static uint8_t sas_signature_buffer[256]; static AzIoTSasToken sasToken( - &Network::client, - AZ_SPAN_FROM_STR(CONFIG_AZURE_DEVICE_KEY), - AZ_SPAN_FROM_BUFFER(Network::sas_signature_buffer), - AZ_SPAN_FROM_BUFFER(Network::mqtt_password)); + &Network::client, + AZ_SPAN_FROM_STR(CONFIG_AZURE_DEVICE_KEY), + AZ_SPAN_FROM_BUFFER(Network::sas_signature_buffer), + AZ_SPAN_FROM_BUFFER(Network::mqtt_password)); static char serializedTelemetryData[CONFIG_TELEMETRY_DATA_MAXIMUM_SIZE]; - + namespace _WiFi { void _connect(void) @@ -61,12 +62,12 @@ namespace Network { ESP.restart(); } - + delay(CONFIG_WIFI_WAIT_MSEC); SerialPrint('.'); } - SerialPrintln(); + SerialNewLine(); LogInfo("Connected to " + String(CONFIG_WIFI_SSID) + " with IP of " + WiFi.localIP().toString()); } } @@ -92,7 +93,7 @@ namespace Network } struct tm timeinfo; - SerialPrintln(); + SerialNewLine(); if (!getLocalTime(&timeinfo)) { @@ -101,7 +102,7 @@ namespace Network else { LogInfo("Got local time: "); - SerialPrintlnTimeinfo(&timeinfo, TIMEINFO_FORMAT_STRING); + SerialTimeinfo(&timeinfo, TIMEINFO_FORMAT_STRING); } } } @@ -120,19 +121,16 @@ namespace Network case MQTT_EVENT_CONNECTED: LogInfo("MQTT event: MQTT_EVENT_CONNECTED"); subscribe_message_id = esp_mqtt_client_subscribe(Network::mqtt_client, - AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, - CONFIG_MQTT_CLIENT_QOS); + AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, + CONFIG_MQTT_CLIENT_QOS); if (subscribe_message_id == -1) { - LogError("Could not subscribe to topic " + String(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - + " with QoS level of " + String(CONFIG_MQTT_CLIENT_QOS)); + LogError("Could not subscribe to topic " + String(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) + " with QoS level of " + String(CONFIG_MQTT_CLIENT_QOS)); } else { - LogInfo("Subscribed to topic " - + String(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) + " with message ID " - + String(subscribe_message_id) + " with QoS level of " + String(CONFIG_MQTT_CLIENT_QOS)); + LogInfo("Subscribed to topic " + String(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) + " with message ID " + String(subscribe_message_id) + " with QoS level of " + String(CONFIG_MQTT_CLIENT_QOS)); } break; @@ -169,20 +167,20 @@ namespace Network } // FIXME: Find out why does this cause "Core 1 panic'ed (StoreProhibited)" - void _configureMQTTConfiguration(esp_mqtt_client_config_t* mqtt_configuration) + void _configureMQTTConfiguration(esp_mqtt_client_config_t *mqtt_configuration) { memset(mqtt_configuration, 0, sizeof(mqtt_configuration)); - mqtt_configuration -> uri = Network::mqtt_broker_uri; - mqtt_configuration -> port = Network::mqtt_port; - mqtt_configuration -> client_id = Network::mqtt_client_id; - mqtt_configuration -> username = Network::mqtt_username; - mqtt_configuration -> password = (const char *)az_span_ptr(Network::sasToken.Get()); - mqtt_configuration -> keepalive = 30; - mqtt_configuration -> disable_clean_session = 0; - mqtt_configuration -> disable_auto_reconnect = false; - mqtt_configuration -> event_handle = MQTT::_MQTTEventHandler; - mqtt_configuration -> user_context = NULL; - mqtt_configuration -> cert_pem = (const char *)ca_pem; + mqtt_configuration->uri = Network::mqtt_broker_uri; + mqtt_configuration->port = Network::mqtt_port; + mqtt_configuration->client_id = Network::mqtt_client_id; + mqtt_configuration->username = Network::mqtt_username; + mqtt_configuration->password = (const char *)az_span_ptr(Network::sasToken.Get()); + mqtt_configuration->keepalive = 30; + mqtt_configuration->disable_clean_session = 0; + mqtt_configuration->disable_auto_reconnect = false; + mqtt_configuration->event_handle = MQTT::_MQTTEventHandler; + mqtt_configuration->user_context = NULL; + mqtt_configuration->cert_pem = (const char *)ca_pem; } void _initializeMQTTClient(void) @@ -194,7 +192,7 @@ namespace Network } esp_mqtt_client_config_t mqtt_configuration; - + memset(&mqtt_configuration, 0, sizeof(mqtt_configuration)); mqtt_configuration.uri = Network::mqtt_broker_uri; mqtt_configuration.port = Network::mqtt_port; @@ -207,14 +205,15 @@ namespace Network mqtt_configuration.event_handle = MQTT::_MQTTEventHandler; mqtt_configuration.user_context = NULL; mqtt_configuration.cert_pem = (const char *)ca_pem; - - //configureMQTTConfiguration(&mqtt_configuration); // FIXME: Find out why does this cause "Core 1 panic'ed (StoreProhibited)" + + // configureMQTTConfiguration(&mqtt_configuration); // FIXME: Find out why does this cause "Core 1 panic'ed (StoreProhibited)" mqtt_client = esp_mqtt_client_init(&mqtt_configuration); - + if (mqtt_client == NULL) { - return LogError("Failed creating MQTT client.");; + return LogError("Failed creating MQTT client."); + ; } esp_err_t start_result = esp_mqtt_client_start(mqtt_client); @@ -320,13 +319,13 @@ namespace Network } result = esp_mqtt_client_publish( - Network::mqtt_client, - Network::telemetry_topic, - Network::serializedTelemetryData, - strlen(Network::serializedTelemetryData), - CONFIG_MQTT_CLIENT_QOS, - CONFIG_MQTT_CLIENT_MESSAGE_RETAIN_POLICY); - + Network::mqtt_client, + Network::telemetry_topic, + Network::serializedTelemetryData, + strlen(Network::serializedTelemetryData), + CONFIG_MQTT_CLIENT_QOS, + CONFIG_MQTT_CLIENT_MESSAGE_RETAIN_POLICY); + if (result == 0) { LogError("Publishing of payload failed! No telemetry was NOT sent :( "); @@ -334,13 +333,13 @@ namespace Network else { LogInfo("Message published successfully! :) "); - } + } } } namespace Telemetry { - void processTelemetryData(Network::Telemetry::telemetryData_t* telemetryData) + void processTelemetryData(Network::Telemetry::telemetryData_t *telemetryData) { if (telemetryData == nullptr) { @@ -348,6 +347,7 @@ namespace Network } StaticJsonDocument telemetry_message; + telemetry_message["deviceId"] = "phys1"; telemetry_message[CONFIG_TELEMETRY_DATA_TEMPERATURE_ID] = telemetryData->temperature; telemetry_message[CONFIG_TELEMETRY_DATA_HUMIDITY_ID] = telemetryData->humidity; telemetry_message[CONFIG_TELEMETRY_DATA_CO_ID] = telemetryData->CO; @@ -363,7 +363,6 @@ namespace Network LogInfo("WiFi was turned off, turning on as station again for telemetry."); WiFi.mode(WIFI_STA); } - if (WiFi.status() != WL_CONNECTED) { LogInfo("WiFi is not connected to an AP, trying to reconnect."); @@ -396,6 +395,7 @@ namespace Network Network::_WiFi::_connect(); Network::SNTP::_setup(); Network::IoTHub::_initializeIoTHubClient(); - if (turnOffWifiAfterSetup) Network::turnOffWiFi(); + if (turnOffWifiAfterSetup) + Network::turnOffWiFi(); } } diff --git a/project/src/Main/Network.h b/project/Main/src/network/Network.hpp similarity index 80% rename from project/src/Main/Network.h rename to project/Main/src/network/Network.hpp index c18337b..a7d06ba 100644 --- a/project/src/Main/Network.h +++ b/project/Main/src/network/Network.hpp @@ -3,7 +3,7 @@ #ifndef NETWORK_H #define NETWORK_H -#include "Common.h" +#include "../common/Common.hpp" #define MQTT_QOS_LEVEL_AT_MOST_ONCE 0 #define MQTT_QOS_LEVEL_AT_LEAST_ONCE 1 @@ -16,17 +16,18 @@ namespace Network { namespace Telemetry { - typedef struct telemetryData { + typedef struct telemetryData + { float temperature; float humidity; - float CO; + double CO; } telemetryData_t; - void processTelemetryData(Network::Telemetry::telemetryData_t* telemetryData); + void processTelemetryData(Network::Telemetry::telemetryData_t *telemetryData); void sendTelemetry(); } void turnOffWiFi(void); void setupNetworking(bool turnOffWifiAfterSetup = WIFI_KEEP_ON); } -#endif \ No newline at end of file +#endif // NETWORK_H diff --git a/project/src/Main/NetworkConfig.h b/project/Main/src/network/NetworkConfig.hpp similarity index 56% rename from project/src/Main/NetworkConfig.h rename to project/Main/src/network/NetworkConfig.hpp index 4260caa..1f6b090 100644 --- a/project/src/Main/NetworkConfig.h +++ b/project/Main/src/network/NetworkConfig.hpp @@ -1,20 +1,19 @@ #ifndef NETWORK_CONFIG_H #define NETWORK_CONFIG_H -#include "Network.h" +#include "Network.hpp" #define DEFAULT_MQTT_QOS MQTT_QOS_LEVEL_AT_LEAST_ONCE #define DEFAULT_SAS_TOKEN_DURATION_IN_MINUTES 60 #define DEFAULT_MQTT_QOS MQTT_QOS_LEVEL_AT_LEAST_ONCE #define DEFAULT_WAIT_MSEC (uint32_t)1000 #define DEFAULT_TELEMETRY_DATA_MAXIMUM_SIZE 128 -#define DEFAULT_TELEMETRY_DATA_TEMPERATURE_ID "t" -#define DEFAULT_TELEMETRY_DATA_HUMIDITY_ID "h" -#define DEFAULT_TELEMETRY_DATA_CO_ID "c" +#define DEFAULT_TELEMETRY_DATA_TEMPERATURE_ID "temperature" +#define DEFAULT_TELEMETRY_DATA_HUMIDITY_ID "humidity" +#define DEFAULT_TELEMETRY_DATA_CO_ID "co_level" #define DEFAULT_WIFI_WAIT_TICKS 10 #define DEFAULT_SNTP_WAIT_TICKS 30 -// FIXME: Which MQTT QOS macro is needed? #define CONFIG_MQTT_CLIENT_QOS DEFAULT_MQTT_QOS #define CONFIG_MQTT_QOS DEFAULT_MQTT_QOS #define CONFIG_MQTT_CLIENT_MESSAGE_RETAIN_POLICY MQTT_MESSAGE_RETAIN_POLICY_OFF @@ -29,4 +28,23 @@ #define CONFIG_SAS_TOKEN_DURATION_IN_MINUTES DEFAULT_SAS_TOKEN_DURATION_IN_MINUTES -#endif +namespace Configurations +{ + namespace Network + { + namespace Defaults + { + constexpr uint8_t INBOUND_DATA_SIZE_BYTES = 128; + constexpr uint16_t SERIAL_BAUD_RATE = 9600; + constexpr uint16_t TIME_TO_SLEEP_SEC = 30; + constexpr uint16_t DELAY_FOR_SERIAL_MILISEC = 5000; + } + + const uint8_t INBOUND_DATA_SIZE_BYTES = Defaults::INBOUND_DATA_SIZE_BYTES; + const uint16_t SERIAL_BAUD_RATE = Defaults::SERIAL_BAUD_RATE; + const uint16_t TIME_TO_SLEEP_SEC = Defaults::TIME_TO_SLEEP_SEC; + const uint16_t DELAY_FOR_SERIAL_MILISEC = Defaults::DELAY_FOR_SERIAL_MILISEC; + } +} + +#endif // NETWORK_CONFIG_H diff --git a/project/src/Main/AzIoTSasToken.cpp b/project/Main/src/network/azure/AzIoTSasToken.cpp similarity index 83% rename from project/src/Main/AzIoTSasToken.cpp rename to project/Main/src/network/azure/AzIoTSasToken.cpp index 3cdc2f7..4a1384e 100644 --- a/project/src/Main/AzIoTSasToken.cpp +++ b/project/Main/src/network/azure/AzIoTSasToken.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT -#include "AzIoTSasToken.h" -#include "SerialLogger.h" #include #include #include @@ -10,13 +8,17 @@ #include #include +#include "../../common/serial-logger/SerialLogger.hpp" + +#include "AzIoTSasToken.hpp" + #define INDEFINITE_TIME ((time_t)-1) #define is_az_span_empty(x) (az_span_size(x) == az_span_size(AZ_SPAN_EMPTY) && az_span_ptr(x) == az_span_ptr(AZ_SPAN_EMPTY)) -static uint32_t getSasTokenExpiration(const char* sasToken) +static uint32_t getSasTokenExpiration(const char *sasToken) { - const char SE[] = { '&', 's', 'e', '=' }; + const char SE[] = {'&', 's', 'e', '='}; uint32_t se_as_unix_time = 0; int i, j; @@ -44,11 +46,14 @@ static uint32_t getSasTokenExpiration(const char* sasToken) } else { - int k = i; - while (sasToken[k] != '\0' && sasToken[k] != '&') { k++; } + int k = i; + while (sasToken[k] != '\0' && sasToken[k] != '&') + { + k++; + } if (az_result_failed( - az_span_atou32(az_span_create((uint8_t*)sasToken + i, k - i), &se_as_unix_time))) + az_span_atou32(az_span_create((uint8_t *)sasToken + i, k - i), &se_as_unix_time))) { Logger.Error("Failed parsing SAS token expiration timestamp"); } @@ -64,9 +69,9 @@ static void mbedtls_hmac_sha256(az_span key, az_span payload, az_span signed_pay mbedtls_md_init(&ctx); mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1); - mbedtls_md_hmac_starts(&ctx, (const unsigned char*)az_span_ptr(key), az_span_size(key)); - mbedtls_md_hmac_update(&ctx, (const unsigned char*)az_span_ptr(payload), az_span_size(payload)); - mbedtls_md_hmac_finish(&ctx, (byte*)az_span_ptr(signed_payload)); + mbedtls_md_hmac_starts(&ctx, (const unsigned char *)az_span_ptr(key), az_span_size(key)); + mbedtls_md_hmac_update(&ctx, (const unsigned char *)az_span_ptr(payload), az_span_size(payload)); + mbedtls_md_hmac_finish(&ctx, (byte *)az_span_ptr(signed_payload)); mbedtls_md_free(&ctx); } @@ -74,7 +79,7 @@ static void hmac_sha256_sign_signature( az_span decoded_key, az_span signature, az_span signed_signature, - az_span* out_signed_signature) + az_span *out_signed_signature) { mbedtls_hmac_sha256(decoded_key, signature, signed_signature); *out_signed_signature = az_span_slice(signed_signature, 0, 32); @@ -83,7 +88,7 @@ static void hmac_sha256_sign_signature( static void base64_encode_bytes( az_span decoded_bytes, az_span base64_encoded_bytes, - az_span* out_base64_encoded_bytes) + az_span *out_base64_encoded_bytes) { size_t len; if (mbedtls_base64_encode( @@ -91,8 +96,7 @@ static void base64_encode_bytes( (size_t)az_span_size(base64_encoded_bytes), &len, az_span_ptr(decoded_bytes), - (size_t)az_span_size(decoded_bytes)) - != 0) + (size_t)az_span_size(decoded_bytes)) != 0) { Logger.Error("mbedtls_base64_encode fail"); } @@ -103,7 +107,7 @@ static void base64_encode_bytes( static int decode_base64_bytes( az_span base64_encoded_bytes, az_span decoded_bytes, - az_span* out_decoded_bytes) + az_span *out_decoded_bytes) { memset(az_span_ptr(decoded_bytes), 0, (size_t)az_span_size(decoded_bytes)); @@ -113,8 +117,7 @@ static int decode_base64_bytes( (size_t)az_span_size(decoded_bytes), &len, az_span_ptr(base64_encoded_bytes), - (size_t)az_span_size(base64_encoded_bytes)) - != 0) + (size_t)az_span_size(base64_encoded_bytes)) != 0) { Logger.Error("mbedtls_base64_decode fail"); return 1; @@ -130,12 +133,12 @@ static int iot_sample_generate_sas_base64_encoded_signed_signature( az_span sas_base64_encoded_key, az_span sas_signature, az_span sas_base64_encoded_signed_signature, - az_span* out_sas_base64_encoded_signed_signature) + az_span *out_sas_base64_encoded_signed_signature) { // Decode the sas base64 encoded key to use for HMAC signing. char sas_decoded_key_buffer[32]; az_span sas_decoded_key = AZ_SPAN_FROM_BUFFER(sas_decoded_key_buffer); - + if (decode_base64_bytes(sas_base64_encoded_key, sas_decoded_key, &sas_decoded_key) != 0) { Logger.Error("Failed generating encoded signed signature"); @@ -164,7 +167,7 @@ int64_t iot_sample_get_epoch_expiration_time_from_minutes(uint32_t minutes) } az_span generate_sas_token( - az_iot_hub_client* hub_client, + az_iot_hub_client *hub_client, az_span device_key, az_span sas_signature, unsigned int expiryTimeInMinutes, @@ -186,12 +189,12 @@ az_span generate_sas_token( // Generate the encoded, signed signature (b64 encoded, HMAC-SHA256 signing). char b64enc_hmacsha256_signature[64]; az_span sas_base64_encoded_signed_signature = AZ_SPAN_FROM_BUFFER(b64enc_hmacsha256_signature); - + if (iot_sample_generate_sas_base64_encoded_signed_signature( - device_key, - sas_signature, - sas_base64_encoded_signed_signature, - &sas_base64_encoded_signed_signature) != 0) + device_key, + sas_signature, + sas_base64_encoded_signed_signature, + &sas_base64_encoded_signed_signature) != 0) { Logger.Error("Failed generating SAS token signed signature"); return AZ_SPAN_EMPTY; @@ -204,7 +207,7 @@ az_span generate_sas_token( sas_duration, sas_base64_encoded_signed_signature, AZ_SPAN_EMPTY, - (char*)az_span_ptr(sas_token), + (char *)az_span_ptr(sas_token), az_span_size(sas_token), &mqtt_password_length); @@ -215,12 +218,12 @@ az_span generate_sas_token( } else { - return az_span_slice(sas_token, 0, mqtt_password_length); + return az_span_slice(sas_token, 0, mqtt_password_length); } } AzIoTSasToken::AzIoTSasToken( - az_iot_hub_client* client, + az_iot_hub_client *client, az_span deviceKey, az_span signatureBuffer, az_span sasTokenBuffer) @@ -241,7 +244,7 @@ int AzIoTSasToken::Generate(unsigned int expiryTimeInMinutes) this->signatureBuffer, expiryTimeInMinutes, this->sasTokenBuffer); - + if (is_az_span_empty(this->sasToken)) { Logger.Error("Failed generating SAS token"); @@ -249,7 +252,7 @@ int AzIoTSasToken::Generate(unsigned int expiryTimeInMinutes) } else { - this->expirationUnixTime = getSasTokenExpiration((const char*)az_span_ptr(this->sasToken)); + this->expirationUnixTime = getSasTokenExpiration((const char *)az_span_ptr(this->sasToken)); if (this->expirationUnixTime == 0) { @@ -259,7 +262,7 @@ int AzIoTSasToken::Generate(unsigned int expiryTimeInMinutes) } else { - return 0; + return 0; } } } diff --git a/project/src/Main/AzIoTSasToken.h b/project/Main/src/network/azure/AzIoTSasToken.hpp similarity index 88% rename from project/src/Main/AzIoTSasToken.h rename to project/Main/src/network/azure/AzIoTSasToken.hpp index ec25233..5673786 100644 --- a/project/src/Main/AzIoTSasToken.h +++ b/project/Main/src/network/azure/AzIoTSasToken.hpp @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT -#ifndef AZIOTSASTOKEN_H -#define AZIOTSASTOKEN_H +#ifndef AZIOTSASTOKEN_HPP +#define AZIOTSASTOKEN_HPP #define SAS_TOKEN_GENERATION_OK 0 @@ -31,4 +31,4 @@ class AzIoTSasToken uint32_t expirationUnixTime; }; -#endif // AZIOTSASTOKEN_H +#endif // AZIOTSASTOKEN_HPP diff --git a/project/Main/src/network/azure/SecretsConfig.hpp b/project/Main/src/network/azure/SecretsConfig.hpp new file mode 100644 index 0000000..d62feec --- /dev/null +++ b/project/Main/src/network/azure/SecretsConfig.hpp @@ -0,0 +1,11 @@ +#ifndef SECRETS_CONFIG_HPP +#define SECRETS_CONFIG_HPP + +#define CONFIG_WIFI_SSID "test-network" +#define CONFIG_WIFI_PASSWORD "esp-test" + +#define CONFIG_AZURE_FQDN "co-sensors-iot-hub.azure-devices.net" +#define CONFIG_AZURE_DEVICE_ID "prototype" +#define CONFIG_AZURE_DEVICE_KEY "2KaZGGae1aWhYgKz7XR8EesqGF7kCHYiWEn+UZbbbNE=" + +#endif // SECRETS_CONFIG_HPP diff --git a/project/Main/src/peripherials/adc/Adc.hpp b/project/Main/src/peripherials/adc/Adc.hpp new file mode 100644 index 0000000..dedaffd --- /dev/null +++ b/project/Main/src/peripherials/adc/Adc.hpp @@ -0,0 +1,12 @@ +#ifndef ADC_HPP +#define ADC_HPP + +#include "AdcConfig.hpp" + +namespace Adc +{ + bool initializeAdc(uint8_t chipSelectPin = Configurations::Adc::SPI_CHIP_SELECT_PIN); + uint32_t readAdc(uint8_t channel = Configurations::Adc::ADC_CHANNEL); +} + +#endif // ADC_HPP diff --git a/project/Main/src/peripherials/adc/AdcConfig.hpp b/project/Main/src/peripherials/adc/AdcConfig.hpp new file mode 100644 index 0000000..e24e1b3 --- /dev/null +++ b/project/Main/src/peripherials/adc/AdcConfig.hpp @@ -0,0 +1,78 @@ +#ifndef ADC_DRIVER_CONFIG_HPP +#define ADC_DRIVER_CONFIG_HPP + +/*! + * @brief Contains configurations. + */ +namespace Configurations +{ + /*! + * @brief Contains configuration for the ADC peripherial. + */ + namespace Adc + { + /*! + * @brief The enumeration of possible ADC channels. + */ + enum AdcChannel : uint8_t + { + ch1 = 1, + ch2 = 2, + ch3 = 3, + ch4 = 4, + ch5 = 5, + ch6 = 6, + ch7 = 7, + ch8 = 8 + + }; + + /*! + * @brief The project defined defaults for the ADC. + */ + namespace Defaults + { + /*! + * @brief The project defined channel to read. + */ + constexpr uint8_t ADC_CHANNEL = AdcChannel::ch1; + + /*! + * @brief The project defined chip select (CS) pin for SPI communication with the ADC. + */ + constexpr uint8_t SPI_CHIP_SELECT_PIN = 5; + + /*! + * @brief The project defined number of ADC levels. + */ + constexpr uint16_t PRECISION_BITS = 1024; + + /*! + * @brief The project defined reference voltage the ADC to be measured against. + */ + constexpr float REFERENCE_VOLTAGE = 1.5; + } + + /*! + * @brief The build defined channel to read. + */ + const uint8_t ADC_CHANNEL = Defaults::ADC_CHANNEL; + + /*! + * @brief The build defined chip select (CS) pin for SPI communication with the ADC. + */ + const uint8_t SPI_CHIP_SELECT_PIN = Defaults::SPI_CHIP_SELECT_PIN; + + /*! + * @brief The build defined number of ADC levels. + */ + const uint16_t PRECISION_BITS = Defaults::PRECISION_BITS; + + /*! + * @brief The build defined reference voltage the ADC to be measured against. + */ + const float REFERENCE_VOLTAGE = Defaults::REFERENCE_VOLTAGE; + } +} + +#endif // ADC_DRIVER_CONFIG_HPP diff --git a/project/Main/src/peripherials/adc/MCP3008.cpp b/project/Main/src/peripherials/adc/MCP3008.cpp new file mode 100644 index 0000000..5cef2b0 --- /dev/null +++ b/project/Main/src/peripherials/adc/MCP3008.cpp @@ -0,0 +1,50 @@ +#include + +#include "../../common/Common.hpp" +#include "Adc.hpp" + +Adafruit_MCP3008 adc; + +bool Adc::initializeAdc(uint8_t chipSelectPin) +{ +#ifdef DEBUG_MODE + LogInfo("Trying to initialize the ADC for CS pin: " + String(chipSelectPin)); + bool chip_init_success = adc.begin(chipSelectPin); + if (true == chip_init_success) + { + LogInfo("Hardware SPI communication with ADC successful on CS pin " + String(chipSelectPin)); + } + else + { + LogError("Hardware SPI communication with ADC failed on CS pin " + String(chipSelectPin)); + } + return chip_init_success; +#endif +#ifndef DEBUG_MODE + return adc.begin(chipSelectPin) +#endif +} + +uint32_t Adc::readAdc(uint8_t channel) +{ +#ifdef DEBUG_MODE + LogInfo("Trying to read the ADC from channel " + String(channel)); + uint32_t value_read = adc.readADC(channel); + if (-1 == value_read) + { + LogError("ADC channel " + String(channel) + " is incorrect!"); + } + else if (0 == value_read) + { + LogWarning("Reading from ADC channel " + String(channel) + " resulted in 0. This might be correct, but it can also indicate incorrect functioning!"); + } + else + { + LogInfo("ADC read successfully with value: " + String(value_read)); + } + return value_read; +#endif +#ifndef DEBUG_MODE + return adc.readADC(channel); +#endif +} diff --git a/project/Main/src/peripherials/co-sensor/COSensor.hpp b/project/Main/src/peripherials/co-sensor/COSensor.hpp new file mode 100644 index 0000000..a989d05 --- /dev/null +++ b/project/Main/src/peripherials/co-sensor/COSensor.hpp @@ -0,0 +1,24 @@ +#ifndef CO_SENSOR_HPP +#define CO_SENSOR_HPP + +namespace COSensor +{ + /*! + * @brief Initialize the relevant hardware for the CO sensor. + * @return true if initialization was successful + */ + bool initializeSensor(); + + /*! + * @brief Makes a measurement. + */ + void makeMeasurement(); + + /*! + * @brief Gets the carbon monoxide level. + * @return the parts-per-million (PPM) of CO in the air + */ + double getPPMLevel(); +} + +#endif // CO_SENSOR_HPP diff --git a/project/Main/src/peripherials/co-sensor/COSensorConfig.hpp b/project/Main/src/peripherials/co-sensor/COSensorConfig.hpp new file mode 100644 index 0000000..3c6b690 --- /dev/null +++ b/project/Main/src/peripherials/co-sensor/COSensorConfig.hpp @@ -0,0 +1,32 @@ +#ifndef CO_SENSOR_CONFIG_HPP +#define CO_SENSOR_CONFIG_HPP + +/*! + * @brief Contains configurations. + */ +namespace Configurations +{ + /*! + * @brief Contains configuration for the CO sensor. + */ + namespace COSensor + { + /*! + * @brief Contains the project defined default values for the CO sensor configuration. + */ + namespace Defaults + { + /*! + * @brief The project defined resistor value. + */ + constexpr uint16_t RESISTOR_VALUE = 10000; + } + + /*! + * @brief The build defined resistor value. + */ + const uint16_t RESISTOR_VALUE = Defaults::RESISTOR_VALUE; + } +} + +#endif // CO_SENSOR_CONFIG_HPP diff --git a/project/Main/src/peripherials/co-sensor/Spec110-102.cpp b/project/Main/src/peripherials/co-sensor/Spec110-102.cpp new file mode 100644 index 0000000..2431429 --- /dev/null +++ b/project/Main/src/peripherials/co-sensor/Spec110-102.cpp @@ -0,0 +1,43 @@ +#include + +#include "../../common/Common.hpp" +#include "../adc/Adc.hpp" + +#include "COSensor.hpp" + +double ppm = 0.0; +/*! +* @brief This is the measured PPM level in a well ventillated environment. +*/ +constexpr double offset = 74400.0; + +bool COSensor::initializeSensor() +{ + LogInfo("CO sensor triggered ADC initialization."); + bool chip_init_success = Adc::initializeAdc(); + if (true == chip_init_success) + { + LogInfo("CO initialization successful!"); + } + else + { + LogError("CO initialization failed!"); + } + return chip_init_success; +} + +void COSensor::makeMeasurement() +{ + LogInfo("Trying to measure CO level."); + uint32_t adcResult = Adc::readAdc(); + double adcCurrent = (adcResult * Configurations::Adc::REFERENCE_VOLTAGE) / Configurations::Adc::PRECISION_BITS; + LogInfo("ADC current is: " + String(adcCurrent) + "A"); + double _ppm = (offset - adcCurrent * 1000000000.0) / 2.0; // Calculated by scaling to nA and 1 PPM is per 2 nA. + LogInfo("CO level is: " + String(_ppm) + "PPM"); + ppm = _ppm; +} + +double COSensor::getPPMLevel() +{ + return ppm; +} diff --git a/project/src/Main/DHTConfig.h b/project/Main/src/peripherials/rh-temp-sensor/DHTConfig.hpp similarity index 91% rename from project/src/Main/DHTConfig.h rename to project/Main/src/peripherials/rh-temp-sensor/DHTConfig.hpp index 1294427..e993101 100644 --- a/project/src/Main/DHTConfig.h +++ b/project/Main/src/peripherials/rh-temp-sensor/DHTConfig.hpp @@ -9,4 +9,4 @@ #define DHT_SAMPLING_PERIOD (uint32_t)2000 #endif -#endif \ No newline at end of file +#endif // DHT_CONFIG_H diff --git a/project/src/Main/RelativeHumidityTempSensor.cpp b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.cpp similarity index 76% rename from project/src/Main/RelativeHumidityTempSensor.cpp rename to project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.cpp index 92a0056..232776e 100644 --- a/project/src/Main/RelativeHumidityTempSensor.cpp +++ b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.cpp @@ -1,13 +1,13 @@ -#include "RelativeHumidityTempSensor.h" -#include "DHTConfig.h" -#include "DHT.h" -#include "DHTConfig.h" -#include "SerialLogger.h" +#include +#include + +#include "../../common/serial-logger/SerialLogger.hpp" + +#include "RelativeHumidityTempSensor.hpp" +#include "DHTConfig.hpp" #define CPU_FREQ_DHT_COMPLIANT 240 -// TODO: Implement moving avarage (so that failed measurements do not mess up the value). -// TODO: Decouple from DHT sensor libs. namespace RHTempSensor { static DHT dht_sensor(CONFIG_PIN, CONFIG_DHT_TYPE); @@ -15,9 +15,11 @@ namespace RHTempSensor static bool badResult = false; static uint8_t moving_avarage_actual_samples = CONFIG_MEASUREMENT_TIMES; - // Checks if the result is a number. - // If it is one, then it stores it in storage and returns true. - // If it is not, then it ignores it and returns false, leaving handling to caller. + /*! + * @brief Checks if the result is a number. If it is one, then it stores it in storage and returns true. If it is not, then it ignores it and returns false, leaving handling to caller. + * @return true if measurement result could be handled, false if not + */ + // FIXME: Float should not be handled as a memory address if the CPU has appropriate register handling for this non-complex type. bool _handleResult(float *checkable, float *storage) { if (checkable == nullptr or storage == nullptr) @@ -38,6 +40,7 @@ namespace RHTempSensor } } + // FIXME: Float should not be handled as a memory address if the CPU has appropriate register handling for this non-complex type. void _readFromSensor(float *storage, float result) { bool is_ok = RHTempSensor::_handleResult(&result, storage); @@ -46,7 +49,6 @@ namespace RHTempSensor RHTempSensor::moving_avarage_actual_samples--; *storage = 0; } - } static void _handleLogging(float *value, uint8_t *i, bool isHumidity) @@ -56,7 +58,7 @@ namespace RHTempSensor LogError("Could not handle logging as either the value or the index was null"); return; } - + if (!RHTempSensor::badResult) { if (!isHumidity) @@ -77,12 +79,15 @@ namespace RHTempSensor void initializeSensor(void) { +#ifdef DEBUG_MODE + LogInfo("Trying to initialize DHT sensor, but due to library limitations WILL NOT have proper feedback if it was successful!"); +#endif dht_sensor.begin(); } + // FIXME: Find out why DHT11 only works when CPU freq is at 240 MHz. Maybe it should be reinitialized here? void makeMeasurements(void) { - // TODO: Find out why DHT11 only works when CPU freq is at 240 MHz. setCpuFrequencyMhz(CPU_FREQ_DHT_COMPLIANT); for (uint8_t i = 0; i < CONFIG_MEASUREMENT_TIMES; i++) { diff --git a/project/src/Main/RelativeHumidityTempSensor.h b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.hpp similarity index 60% rename from project/src/Main/RelativeHumidityTempSensor.h rename to project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.hpp index d334a92..72adb2b 100644 --- a/project/src/Main/RelativeHumidityTempSensor.h +++ b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensor.hpp @@ -1,8 +1,8 @@ -#ifndef RELATIVE_HUMIDITY_TEMP_SENSOR_H -#define RELATIVE_HUMIDITY_TEMP_SENSOR_H +#ifndef RELATIVE_HUMIDITY_TEMP_SENSOR_HPP +#define RELATIVE_HUMIDITY_TEMP_SENSOR_HPP -#include "Common.h" -#include "RelativeHumidityTempSensorConfig.h" +#include "../../common/Common.hpp" +#include "RelativeHumidityTempSensorConfig.hpp" namespace RHTempSensor { @@ -18,4 +18,4 @@ namespace RHTempSensor float getTemperature(); } -#endif +#endif // RELATIVE_HUMIDITY_TEMP_SENSOR_HPP diff --git a/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensorConfig.hpp b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensorConfig.hpp new file mode 100644 index 0000000..d889783 --- /dev/null +++ b/project/Main/src/peripherials/rh-temp-sensor/RelativeHumidityTempSensorConfig.hpp @@ -0,0 +1,9 @@ +#ifndef RELATIVE_HUMIDITY_TEMP_SENSOR_CONFIG_HPP +#define RELATIVE_HUMIDITY_TEMP_SENSOR_CONFIG_HPP + +#define DEFAULT_MEASUREMENT_TIMES 1 +#define CONFIG_MEASUREMENT_TIMES (uint8_t) DEFAULT_MEASUREMENT_TIMES +#define DEFAULT_CONFIG_PIN 4 +#define CONFIG_PIN (uint8_t) DEFAULT_CONFIG_PIN + +#endif // RELATIVE_HUMIDITY_TEMP_SENSOR_CONFIG_HPP diff --git a/project/Main/src/tasks/Tasks.cpp b/project/Main/src/tasks/Tasks.cpp new file mode 100644 index 0000000..4faba58 --- /dev/null +++ b/project/Main/src/tasks/Tasks.cpp @@ -0,0 +1,67 @@ +#include "Tasks.hpp" +#include "../common/serial-logger/SerialLogger.hpp" +#include "../common/Common.hpp" +#include "../common/CommonConfig.hpp" +#include "../network/Network.hpp" +#include "../peripherials/rh-temp-sensor/RelativeHumidityTempSensor.hpp" +#include "../peripherials/co-sensor/COSensor.hpp" + +namespace Tasks +{ + void configureLocalPeripherials(void *RTOSparameter) + { +#ifdef DEBUG_MODE + Helpers::delayForSerialConnection(); + Serial.begin(CONFIG_SERIAL_BAUD_RATE); +#endif + LogInfo("Started task \"taskConfigureLocalPeripherials\""); + LogInfo("Started peripherial initialization...."); + LogInfo("Trying to set power save clock to " + String(CPU_FREQ_POWER_SAVER)); + setCpuFrequencyMhz(CPU_FREQ_POWER_SAVER); + esp_sleep_enable_timer_wakeup(CONFIG_TIME_TO_SLEEP_IN_S * uS_TO_S_FACTOR); + + RHTempSensor::initializeSensor(); + COSensor::initializeSensor(); + LogInfo("Completed peripherial initialization!"); + LogInfo("Completed task \"taskConfigureLocalPeripherials\""); + } + void initializeConnection(void *RTOSparameter) + { + LogInfo("Started task \"taskInitializeConnection\""); + btStop(); + Network::setupNetworking(); + LogInfo("Completed task \"taskInitializeConnection\""); + } + void sendTelemetry(void *RTOSparameter) + { + LogInfo("Started task \"taskSendTelemetry\""); + Network::Telemetry::telemetryData_t sensorData; + sensorData.temperature = RHTempSensor::getTemperature(); + sensorData.humidity = RHTempSensor::getHumidity(); + sensorData.CO = COSensor::getPPMLevel(); + Network::Telemetry::processTelemetryData(&sensorData); + Network::Telemetry::sendTelemetry(); + LogInfo("Completed task \"taskSendTelemetry\""); + } + void doMeasurements(void *RTOSparameter) + { + LogInfo("Started task \"taskDoMeasurements\""); + RHTempSensor::makeMeasurements(); + COSensor::makeMeasurement(); + LogInfo("Completed task \"taskDoMeasurements\""); + } + + namespace Helpers + { + void delayForSerialConnection(void) + { + DelayForSerialConnection(CONFIG_DELAY_FOR_SERIAL_CONNECTION); + } + void startSleep() + { + LogInfo("Going to sleep! Zzzzz..."); + esp_light_sleep_start(); + LogInfo("Woke up from sleep!"); + } + } +} diff --git a/project/Main/src/tasks/Tasks.hpp b/project/Main/src/tasks/Tasks.hpp new file mode 100644 index 0000000..6be8459 --- /dev/null +++ b/project/Main/src/tasks/Tasks.hpp @@ -0,0 +1,42 @@ +#ifndef TASKS_HPP +#define TASKS_HPP + +/*! + * @brief Contains the tasks to be executed by firmware. + */ +namespace Tasks +{ + /*! + * @brief Configure all local peripherials. + */ + void configureLocalPeripherials(void *RTOSparameter = nullptr); + /*! + * @brief Initialize connection to remote. + */ + void initializeConnection(void *RTOSparameter = nullptr); + /*! + * @brief Send the collected telemetry. + */ + void sendTelemetry(void *RTOSparameter = nullptr); + /*! + * @brief Make local measurements. + */ + void doMeasurements(void *RTOSparameter = nullptr); + + /*! + * @brief Contains the tasks to be executed by firmware. + */ + namespace Helpers + { + /*! + * @brief Delay UART serial. Useful for debugging. + */ + void delayForSerialConnection(void); + /*! + * @brief Change into sleep mode. + */ + void startSleep(); + } +} + +#endif // TASKS_HPP diff --git a/project/src/Main/Makefile b/project/Makefile similarity index 100% rename from project/src/Main/Makefile rename to project/Makefile diff --git a/project/src/Main/CommonConfig.h b/project/src/Main/CommonConfig.h deleted file mode 100644 index ec946f6..0000000 --- a/project/src/Main/CommonConfig.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef COMMON_CONFIG_H -#define COMMON_CONFIG_H - -#include "Network.h" - -#define DEFAULT_INBOUND_DATA_SIZE_BYTES 128 -#define DEFAULT_SERIAL_BAUD_RATE 9600 -#define DEFAULT_TIME_TO_SLEEP_IN_S 30 -#define DEFAULT_DELAY_FOR_SERIAL_CONNECTION 5000 - -#define CONFIG_SERIAL_BAUD_RATE DEFAULT_SERIAL_BAUD_RATE -#define CONFIG_TIME_TO_SLEEP_IN_S DEFAULT_TIME_TO_SLEEP_IN_S -#define CONFIG_DELAY_FOR_SERIAL_CONNECTION DEFAULT_DELAY_FOR_SERIAL_CONNECTION - -#endif diff --git a/project/src/Main/Main.ino b/project/src/Main/Main.ino deleted file mode 100644 index 28fa880..0000000 --- a/project/src/Main/Main.ino +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed under: GNU GENERAL PUBLIC LICENSE Version 2 - -#include "Tasks.h" - -// TODO: In general, we should examine if header variables are supposed to be static or they should be extern's of the source globals. - -void setup() -{ - Tasks::Helpers::taskHelperDelayForSerialConnection(); - Tasks::taskConfigureLocalPeripherials(); - Tasks::taskInitializeConnection(); -} - -void loop() -{ - Tasks::taskDoMeasurements(); - Tasks::taskSendTelemetry(); - Tasks::Helpers::taskHelperStartSleep(); -} \ No newline at end of file diff --git a/project/src/Main/RelativeHumidityTempSensorConfig.h b/project/src/Main/RelativeHumidityTempSensorConfig.h deleted file mode 100644 index a3e8d05..0000000 --- a/project/src/Main/RelativeHumidityTempSensorConfig.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef RELATIVE_HUMIDITY_TEMP_SENSOR_CONFIG_H -#define RELATIVE_HUMIDITY_TEMP_SENSOR_CONFIG_H - -#define DEFAULT_MEASUREMENT_TIMES 1 -#define CONFIG_MEASUREMENT_TIMES (uint8_t)DEFAULT_MEASUREMENT_TIMES -#define DEFAULT_CONFIG_PIN 4 -#define CONFIG_PIN (uint8_t) DEFAULT_CONFIG_PIN - -#endif diff --git a/project/src/Main/SecretsConfig.h b/project/src/Main/SecretsConfig.h deleted file mode 100644 index ba3fc0d..0000000 --- a/project/src/Main/SecretsConfig.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef IOT_CONFIGURATION_H -#define IOT_CONFIGURATION_H - -#define CONFIG_WIFI_SSID "" -#define CONFIG_WIFI_PASSWORD "" - -#define CONFIG_AZURE_FQDN ".azure-devices.net" -#define CONFIG_AZURE_DEVICE_ID "" -#define CONFIG_AZURE_DEVICE_KEY "" - -#endif diff --git a/project/src/Main/Tasks.cpp b/project/src/Main/Tasks.cpp deleted file mode 100644 index 86dc3a6..0000000 --- a/project/src/Main/Tasks.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "Tasks.h" -#include "SerialLogger.h" -#include "Common.h" -#include "CommonConfig.h" -#include "Network.h" -#include "RelativeHumidityTempSensor.h" - -namespace Tasks -{ - void taskConfigureLocalPeripherials(void* RTOSparameter) - { - setCpuFrequencyMhz(CPU_FREQ_POWER_SAVER); - esp_sleep_enable_timer_wakeup(CONFIG_TIME_TO_SLEEP_IN_S * uS_TO_S_FACTOR); - Serial.begin(CONFIG_SERIAL_BAUD_RATE); - RHTempSensor::initializeSensor(); - } - void taskInitializeConnection(void* RTOSparameter) - { - btStop(); - Network::setupNetworking(); - } - void taskSendTelemetry(void* RTOSparameter) - { - Network::Telemetry::telemetryData_t sensorData; - sensorData.temperature = RHTempSensor::getTemperature(); - sensorData.humidity = RHTempSensor::getHumidity(); - sensorData.CO = (float)3.3; // Dummy data for testing. - Network::Telemetry::processTelemetryData(&sensorData); - Network::Telemetry::sendTelemetry(); - } - void taskDoMeasurements(void* RTOSparameter) - { - RHTempSensor::makeMeasurements(); - } - - namespace Helpers - { - void taskHelperDelayForSerialConnection(void) - { - DelayForSerialConnection(CONFIG_DELAY_FOR_SERIAL_CONNECTION); - } - void taskHelperStartSleep() - { - esp_light_sleep_start(); - LogInfo("Woke up from sleep!"); - } - } -} - diff --git a/project/src/Main/Tasks.h b/project/src/Main/Tasks.h deleted file mode 100644 index bacd4ae..0000000 --- a/project/src/Main/Tasks.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TASKS_H -#define TASKS_H - -namespace Tasks -{ - void taskConfigureLocalPeripherials(void* RTOSparameter = nullptr); - void taskInitializeConnection(void* RTOSparameter = nullptr); - void taskSendTelemetry(void* RTOSparameter = nullptr); - void taskDoMeasurements(void* RTOSparameter = nullptr); - - namespace Helpers - { - void taskHelperDelayForSerialConnection(void); - void taskHelperStartSleep(); - } -} - -#endif