first commit

This commit is contained in:
Julien Lazarewicz 2025-05-21 01:47:20 +02:00
commit 0dfcd46b56
10 changed files with 792 additions and 0 deletions

57
.clang-format Normal file
View File

@ -0,0 +1,57 @@
---
BasedOnStyle: Mozilla
AccessModifierOffset: '-4'
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: 'true'
AlignConsecutiveDeclarations: 'true'
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortBlocksOnASingleLine: 'true'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: Empty
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: 'true'
BreakConstructorInitializers: AfterColon
BreakStringLiterals: 'false'
ColumnLimit: '100'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
ConstructorInitializerIndentWidth: '0'
ContinuationIndentWidth: '4'
Cpp11BracedListStyle: 'false'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
ExperimentalAutoDetectBinPacking: 'true'
IndentCaseLabels: 'true'
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
JavaScriptQuotes: Single
KeepEmptyLinesAtTheStartOfBlocks: 'false'
Language: Cpp
MaxEmptyLinesToKeep: '2'
NamespaceIndentation: None
ObjCBlockIndentWidth: '4'
ObjCSpaceAfterProperty: 'false'
ObjCSpaceBeforeProtocolList: 'false'
PointerAlignment: Left
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '2'
SpacesInAngles: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Cpp11
TabWidth: '4'
UseTab: Always
...

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

0
README.md Normal file
View File

37
include/README Normal file
View File

@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

61
include/config.h Normal file
View File

@ -0,0 +1,61 @@
// AHT20 SENSOR ENABLE / DISABLE
#define AHT20_ENABLE true
// SGP40 SENSOR ENABLE / DISABLE
#define SGP40_ENABLE true
// BH1750 SENSOR ENABLE / DISABLE
#define BH1750_ENABLE true
// BATTERY TESTING ENABLE / DISABLE
#define BAT_TEST_ENABLE true
// Thingsboard library debug
#define THINGSBOARD_ENABLE_DEBUG true
// Serial debug output
#define SERIAL_DEBUG true
#if SERIAL_DEBUG
#define SERIAL_PRINT_SENSOR_VALUES false
#endif
constexpr char WIFI_SSID[] = "thingsboard";
constexpr char WIFI_PASSWORD[] = "thingsboard";
// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
constexpr char TOKEN[] = "HOMECTRL";
// constexpr char mqtt_attribute_topic[] = "v1/devices/me/attributes";
// Thingsboard we want to establish a connection too
constexpr char THINGSBOARD_SERVER[] = "10.42.0.1";
// Whether the given script is using encryption or not,
// generally recommended as it increases security (communication with the server is not in clear
// text anymore), it does come with an overhead tough as having an encrypted session requires a lot
// of memory, which might not be avaialable on lower end devices.
#define ENCRYPTED false
// While we wait for Feather ESP32 V2 to get added to the Espressif BSP,
// we have to select PICO D4 and UNCOMMENT this line!
#define ADAFRUIT_FEATHER_ESP32_V2
// Sending data can either be done over MQTT and the PubSubClient
// or HTTPS and the HTTPClient, when using the ESP32 or ESP8266
#define USING_HTTPS false
// Enables the ThingsBoard class to be fully dynamic instead of requiring template arguments to
// statically allocate memory. If enabled the program might be slightly slower and all the memory
// will be placed onto the heap instead of the stack.
#define THINGSBOARD_ENABLE_DYNAMIC 1
// If the THINGSBOARD_ENABLE_DYNAMIC 1 setting causes this error log message to appear [TB] Unable
// to de-serialize received json data with error (DeserializationError::NoMemory). Simply add this
// configuration line as well.
// #define THINGSBOARD_ENABLE_PSRAM 0
// Enables sending messages that are bigger than the predefined message size,
// where the message will be sent byte by byte as a fallback instead.
// Requires an additional library, see https://github.com/bblanchon/ArduinoStreamUtils for more
// information. Simply install that library and the feature will be enabled automatically.
#define THINGSBOARD_ENABLE_STREAM_UTILS 0

1
include/version.h Normal file
View File

@ -0,0 +1 @@
#define VERSION "0.0.2"

46
lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

21
platformio.ini Normal file
View File

@ -0,0 +1,21 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
board = adafruit_feather_esp32_v2
framework = arduino
lib_deps =
thingsboard/ThingsBoard@^0.15.0
adafruit/Adafruit AHTX0@^2.0.5
adafruit/Adafruit SGP40 Sensor@^1.1.3
adafruit/Adafruit NeoPixel@^1.12.5
starmbi/hp_BH1750@^1.0.2
upload_port = /dev/cu.usbserial-59170079101

553
src/main.cpp Normal file
View File

@ -0,0 +1,553 @@
#include "config.h"
#include "version.h"
#include "driver/rtc_io.h"
#define USE_EXT0_WAKEUP 0
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <Adafruit_NeoPixel.h>
#include <Arduino_MQTT_Client.h>
#include <ThingsBoard.h>
// AHT20 Temperature & Humidity sensor
#if AHT20_ENABLE
#include <Adafruit_AHTX0.h>
#endif
// SGP40 Air Quality Sensor
#if SGP40_ENABLE
#include <Adafruit_SGP40.h>
#endif
// BH1750 Luxmeter
#if BH1750_ENABLE
#include <hp_BH1750.h>
#endif
// Battery pin
#define VBATPIN A13
// then these pins will be defined for us
#if defined(ADAFRUIT_FEATHER_ESP32_V2) or defined(ARDUINO_ADAFRUIT_ITSYBITSY_ESP32)
#define PIN_NEOPIXEL 0
#define NEOPIXEL_I2C_POWER 2
#endif
#if defined(PIN_NEOPIXEL)
Adafruit_NeoPixel pixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
#endif
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 300 /* Time ESP32 will go to sleep (in seconds) */
#define MINUTES_5 300000
#define SECONDS_80 80000
RTC_DATA_ATTR int bootCount = 0;
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO) // 2 ^ GPIO_NUMBER in hex
#define WAKEUP_GPIO GPIO_NUM_33
void enableInternalPower();
void disableInternalPower();
void print_wakeup_reason();
void InitWiFi();
bool reconnect();
// MQTT port used to communicate with the server, 1883 is the default unencrypted MQTT port,
// whereas 8883 would be the default encrypted SSL MQTT port
#if ENCRYPTED
constexpr uint16_t THINGSBOARD_PORT = 8883U;
#else
constexpr uint16_t THINGSBOARD_PORT = 1883U;
#endif
// Maximum size packets will ever be sent or received by the underlying MQTT client,
// if the size is to small messages might not be sent or received messages will be discarded
constexpr uint16_t MAX_MESSAGE_SEND_SIZE = 128U;
constexpr uint16_t MAX_MESSAGE_RECEIVE_SIZE = 128U;
// Baud rate for the debugging serial connection
// If the Serial output is mangled, ensure to change the monitor speed accordingly to this variable
constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;
#if ENCRYPTED
// See https://comodosslstore.com/resources/what-is-a-root-ca-certificate-and-how-do-i-download-it/
// on how to get the root certificate of the server we want to communicate with,
// this is needed to establish a secure connection and changes depending on the website.
constexpr char ROOT_CERT[] = R"(-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)";
#endif
constexpr char CONNECTING_MSG[] = "Connecting to: (%s) with token (%s)\n";
constexpr char TEMPERATURE_KEY[] = "temperature";
constexpr char HUMIDITY_KEY[] = "humidity";
constexpr char VOCC_KEY[] = "voc";
constexpr char LUX_KEY[] = "lux";
constexpr char BAT_KEY[] = "battery";
constexpr char DOOR_1_KEY[] = "door_1";
constexpr char FIRMWARE_KEY[] = "version";
// Initialize underlying client, used to establish a connection
#if ENCRYPTED
WiFiClientSecure espClient;
#else
WiFiClient espClient;
#endif
// Initalize the Mqtt client instance
Arduino_MQTT_Client mqttClient(espClient);
// Initialize used apis
const std::array<IAPI_Implementation*, 0U> apis = {};
// Initialize ThingsBoard instance with the maximum needed buffer size
#if THINGSBOARD_ENABLE_DYNAMIC
#if THINGSBOARD_ENABLE_STREAM_UTILS
ThingsBoard tb(mqttClient,
MAX_MESSAGE_RECEIVE_SIZE,
MAX_MESSAGE_SEND_SIZE,
Default_Max_Stack_Size,
Default_Buffering_Size,
Default_Max_Response_Size,
apis.cbegin(),
apis.cend());
#else
ThingsBoard tb(mqttClient,
MAX_MESSAGE_RECEIVE_SIZE,
MAX_MESSAGE_SEND_SIZE,
Default_Max_Stack_Size,
Default_Max_Response_Size,
apis.cbegin(),
apis.cend());
#endif
#else
#if THINGSBOARD_ENABLE_STREAM_UTILS
ThingsBoard tb(mqttClient,
MAX_MESSAGE_RECEIVE_SIZE,
MAX_MESSAGE_SEND_SIZE,
Default_Max_Stack_Size,
Default_Buffering_Size,
apis.cbegin(),
apis.cend());
#else
ThingsBoard tb(mqttClient,
MAX_MESSAGE_RECEIVE_SIZE,
MAX_MESSAGE_SEND_SIZE,
Default_Max_Stack_Size,
apis.cbegin(),
apis.cend());
#endif
#endif
// AHT20 Temperature & Humidity sensor
#if AHT20_ENABLE
Adafruit_AHTX0 aht;
#endif
// SGP40 Air Quality Sensor
#if SGP40_ENABLE
Adafruit_SGP40 sgp;
#endif
// BH1750 Luxmeter
#if BH1750_ENABLE
hp_BH1750 BH1750;
#endif
#if BAT_TEST_ENABLE
float measuredvbat;
#endif
void setup()
{
// If analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
// Initalize serial connection for debugging
#if SERIAL_DEBUG
Serial.begin(SERIAL_DEBUG_BAUD);
delay(200);
#endif
// Increment boot number and print it every reboot
++bootCount;
#if SERIAL_DEBUG
Serial.println("Boot number: " + String(bootCount));
#endif
// Print the wakeup reason for ESP32
print_wakeup_reason();
// Enable wakeup timer
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
#if SERIAL_DEBUG
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
#endif
// Enable wakeup from RTC peripherical change
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
// Turn on any internal power switches for TFT, NeoPixels, I2C, etc!
enableInternalPower();
#if AHT20_ENABLE
// AHT20 init
if (!aht.begin())
{
#if SERIAL_DEBUG
Serial.println("AHT sensor not found !");
#endif
while (true) {};
}
#endif
#if SERIAL_DEBUG
Serial.println("AHT10 or AHT20 found");
#endif
// SGP40 init
#if SGP40_ENABLE
if (!sgp.begin())
{
#if SERIAL_DEBUG
Serial.println("SGP40 sensor not found !");
#endif
while (true) {};
}
#if SERIAL_DEBUG
Serial.print("SGP40 found serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);
#endif
#endif
// BH1750 init
#if BH1750_ENABLE
if (!BH1750.begin(BH1750_TO_GROUND))
{
#if SERIAL_DEBUG
Serial.println("BH1750 sensor not found !");
#endif
while (true) {};
}
unsigned int BH1750convtime;
BH1750convtime = BH1750.getMtregTime();
#if SERIAL_DEBUG
Serial.println("BH1750 sensor found");
#if SERIAL_PRINT_SENSOR_VALUES
Serial.printf("BH1750 conversion time: %dms\n", BH1750convtime);
#endif
#endif
BH1750.start();
#endif
InitWiFi();
// DATA COLLECTION START
sensors_event_t humidity, temperature;
float lux;
int32_t voc_index;
uint16_t sraw;
#if SERIAL_DEBUG
Serial.println("Waiting for 80 sec. for sensors accuracy ...");
#endif
// Run sensors data collection for 80 sec, needed for SGP sensor
while (SECONDS_80 > millis())
{
aht.getEvent(&humidity,
&temperature); // populate temp and humidity objects with fresh data
// TODO : if no AHT20 sensor get temperature and humidity from thingsboard
sraw = sgp.measureRaw(temperature.temperature, humidity.relative_humidity);
#if SERIAL_DEBUG
#if SERIAL_PRINT_SENSOR_VALUES
Serial.print("SGP40 - Raw measurement: ");
Serial.println(sraw);
#endif
#endif
voc_index = sgp.measureVocIndex(temperature.temperature, humidity.relative_humidity);
#if SERIAL_DEBUG
#if SERIAL_PRINT_SENSOR_VALUES
Serial.print("Voc Index: ");
Serial.println(voc_index);
#endif
#endif
if (BH1750.hasValue() == true)
{ // non blocking reading
lux = BH1750.getLux();
#if SERIAL_DEBUG
#if SERIAL_PRINT_SENSOR_VALUES
Serial.printf("BH1750 lux value : %.2f\n", lux);
#endif
#endif
BH1750.start();
}
#if BAT_TEST_ENABLE
// Read battery voltage
measuredvbat = analogReadMilliVolts(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat /= 1000; // convert to volts!
#endif
#if SERIAL_DEBUG
#if SERIAL_PRINT_SENSOR_VALUES
Serial.print("VBat: ");
Serial.println(measuredvbat);
#endif
#endif
delay(100);
}
// Uploads new telemetry to ThingsBoard using HTTP.
// See https://thingsboard.io/docs/reference/http-api/#telemetry-upload-api
// for more details
if (!reconnect())
{
return;
}
if (!tb.connected())
{
// Reconnect to the ThingsBoard server,
// if a connection was disrupted or has not yet been established
#if SERIAL_DEBUG
Serial.printf(CONNECTING_MSG, THINGSBOARD_SERVER, TOKEN);
#endif
if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT))
{
#if SERIAL_DEBUG
Serial.println("Failed to connect");
#endif
return;
}
}
#if AHT20_ENABLE
#if SERIAL_DEBUG
Serial.println("Sending temperature data...");
#endif
tb.sendTelemetryData(TEMPERATURE_KEY, temperature.temperature);
#if SERIAL_DEBUG
Serial.println("Sending humidity data...");
#endif
tb.sendTelemetryData(HUMIDITY_KEY, humidity.relative_humidity);
#endif
#if SGP40_ENABLE
#if SERIAL_DEBUG
Serial.println("Sending VOC data...");
#endif
tb.sendTelemetryData(VOCC_KEY, voc_index);
#endif
#if BH1750_ENABLE
#if SERIAL_DEBUG
Serial.println("Sending lux data...");
#endif
tb.sendTelemetryData(LUX_KEY, lux);
#endif
#if BAT_TEST_ENABLE
#if SERIAL_DEBUG
Serial.println("Sending battery...");
#endif
tb.sendTelemetryData(BAT_KEY, measuredvbat);
#endif
#if SERIAL_DEBUG
Serial.println("Sending version...");
#endif
tb.sendTelemetryData(FIRMWARE_KEY, VERSION);
tb.loop();
#if SERIAL_DEBUG
Serial.println("Going to sleep now");
#endif
delay(100);
disableInternalPower();
delay(100);
Serial.flush();
esp_deep_sleep_start();
#if SERIAL_DEBUG
Serial.println("This will never be printed");
#endif
}
void loop() {}
void enableInternalPower()
{
#if defined(NEOPIXEL_POWER)
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, HIGH);
#endif
#if defined(NEOPIXEL_I2C_POWER)
pinMode(NEOPIXEL_I2C_POWER, OUTPUT);
digitalWrite(NEOPIXEL_I2C_POWER, HIGH);
delay(100);
#endif
#if defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2)
// turn on the I2C power by setting pin to opposite of 'rest state'
pinMode(PIN_I2C_POWER, INPUT);
delay(1);
bool polarity = digitalRead(PIN_I2C_POWER);
pinMode(PIN_I2C_POWER, OUTPUT);
digitalWrite(PIN_I2C_POWER, !polarity);
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, HIGH);
#endif
}
void disableInternalPower()
{
#if defined(NEOPIXEL_POWER)
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, LOW);
#endif
#if defined(NEOPIXEL_I2C_POWER)
pinMode(NEOPIXEL_I2C_POWER, OUTPUT);
digitalWrite(NEOPIXEL_I2C_POWER, LOW);
#endif
#if defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2)
// turn off the I2C power by setting pin to rest state (off)
pinMode(PIN_I2C_POWER, INPUT);
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, LOW);
#endif
}
void print_wakeup_reason()
{
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0:
#if SERIAL_DEBUG
Serial.println("Wakeup caused by external signal using RTC_IO");
#endif
break;
case ESP_SLEEP_WAKEUP_EXT1:
#if SERIAL_DEBUG
Serial.println("Wakeup caused by external signal using RTC_CNTL");
#endif
break;
case ESP_SLEEP_WAKEUP_TIMER:
#if SERIAL_DEBUG
Serial.println("Wakeup caused by timer");
#endif
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
#if SERIAL_DEBUG
Serial.println("Wakeup caused by touchpad");
#endif
break;
case ESP_SLEEP_WAKEUP_ULP:
#if SERIAL_DEBUG
Serial.println("Wakeup caused by ULP program");
#endif
break;
default:
#if SERIAL_DEBUG
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
#endif
break;
}
}
/// @brief Initalizes WiFi connection,
// will endlessly delay until a connection has been successfully established
void InitWiFi()
{
#if SERIAL_DEBUG
Serial.println("Connecting to AP ...");
#endif
// Attempting to establish a connection to the given WiFi network
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
// Delay 500ms until a connection has been successfully established
delay(500);
#if SERIAL_DEBUG
Serial.print(".");
#endif
}
#if SERIAL_DEBUG
Serial.printf("\nConnected to AP : %s\n", WIFI_SSID);
#endif
#if ENCRYPTED
espClient.setCACert(ROOT_CERT);
#endif
}
/// @brief Reconnects the WiFi uses InitWiFi if the connection has been removed
/// @return Returns true as soon as a connection has been established again
bool reconnect()
{
// Check to ensure we aren't connected yet
const wl_status_t status = WiFi.status();
if (status == WL_CONNECTED)
{
return true;
}
// If we aren't establish a new connection to the given WiFi network
InitWiFi();
return true;
}

11
test/README Normal file
View File

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html