Arduino Library for ESP32/ESP8266 - composition oriented internet of things framework that provides simple and extendable architecture, handles device setup (WiFi setup, MQTT and application specific configuration), network connectivity, MQTT telemetry protocol and more...
- Important
- This library targets Arduino 3+ on ESP32. However, due to Platformio statement it will not automatically pull latest versions. If you want latest version support, set your platform to pioarduino (by Jason2866) fork in your
platformio.ini
file.
= https://github.com/pioarduino/platform-espressif32.git
-
When it comes to ESP8266, latest version supported is based on SDK305. To use it, add
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
to your build flags.
đą Motivation
- The goal of this project is to create a simple template or starting point to develop IoT applications using Espressif microcontrollers.
- I was frequently copying and modifying source code for different devices and this is an attempt to streamline this process.
đ Doxygen
- Detailed documentation can be found on here.
đ Examples
- Soome people prefer to learn by example. In this, open the [examples directory](examples).
âšī¸ Architecture
flowchart TD
AppState{AppState}
AppState --> |NotInitialized| Application::Init
AppState --> |Initialized| Application::Loop
subgraph Application::Init
A(Add initial components) -->
B(Mark app state as initialized)
end
subgraph Application::Loop
Loop{{For each component}} --> CCS{State?}
CCS --> |Active|LP1(Call component's loop)
CCS --> |NotInitialized|LP2(Call component's init)
CCS --> |Initialized|LP3(Call component's postInit)
CCS --> |ToRemove|LP4(Remove component)
LP2 --> SCS2(State -> Initialized) --> DF
LP3 --> SCS3(State -> Active) --> DF
LP1 --> DF
DF{Success?}
DF --> |True|X0{{Continue}}
DF --> |False|X1{{Break}}
LP4 --> Continue
end
- Only one application can be executed simultaneously.
- Each application has its own components. Components are a key part of the framework.
- Components have states. State change logic is handled in the application's loop.
- Each component has init, postInit, and loop methods.
- Components can be marked for removal, and they will be safely released in the next tick.
đ Utilities
đ¨ Components
đ
Rules:
- Components should be added in the app's init method, so they will be available for postInit methods. (you can add them later, in loop() but that's another case)
- The init method is the best place to add dependent components, setup initial pin values etc.
- The postInit method is the best place to obtain a weak pointer to another component by calling findComponent. This will handle cases when other components were added via init method.
đą Building the application
To build an application, simply create a new class inherited from ksApplication and add your initial components inside the init method. See projects like emon_fw for reference.
đ How does it work under the hood?
- The application is created, followed by the invocation of its init() method. If false is returned from the init method, the subsequent execution of the loop will be skipped, resulting in no iteration over the components. The App Rotator will then try to run next apllication.
- In case the init() method returns true, the application proceeds to execute its loop() function. This function traverses through the components, initializing each of them.
- In the subsequent iteration, the application triggers the postInitialize() method for each component.
- Following this, the application is fully initialized and enters a looping state where it iterates over the components, invoking their respective loop methods.
- If any component returns false during it's loop method, the application will break and the App Rotator will select the next application for execution.
++
bool PelletInfo::init()
{
addComponent<ksf::comps::ksWifiConnector>(PelletInfoConfig::pelletInfoDeviceName);
addComponent<ksf::comps::ksMqttDebugResponder>();
addComponent<ksf::comps::ksDevStatMqttReporter>();
addComponent<ksf::comps::ksDevicePortal>();
addComponent<comps::StateDisplay>();
addComponent<comps::StateReceiver>();
addComponent<ksf::comps::ksResetButton>(CFG_PUSH_PIN, LOW);
addComponent<ksf::comps::ksMqttConnector>();
return true;
}
đ Application rotator
The library implements one very useful utility named ksAppRotator. This object can wrap application instantiation logic into something like carousel or rotator.
Typically the device hosts two applications. First application is running core device logic while the second one is dedicated to help the user with the device configuration.
Each application has it's own loop method taking care of all underlying logic. In case of fail (which can happen anytime, even when creating the application object), the rotator will spawn next application and start processing it's logic until fail or break.
This is very flexible, because you can even raise fail (false) from application's init method and then go directly into the configuration mode (for example there's no WiFi credentials provided by the user).
đŖ Compiler flags
- Bare Arduino projects need to have
gnu++2a
enabled via compiler.cpp.extra_flags=
option in the board.txt
file.
#ī¸âŖ Custom RTTI
- Use the KSF_RTTI_DECLARATIONS macro to provide proper runtime type information generation for proper casting of components.
- See ksConfigProvider.h for an example. Your application components should use this macro, otherwise the component finding mechanism won't work.
đĨ Saving power
- By default, this framework supports enables power saving for the modem.
- Automatic modem sleep requires the DTIM to be set on the access point.
- The best value for was 3. It allows the ESP32 to go down from around 100mA to 20mA.
đ Dependencies
- It is highly recommended to use PlatformIO as it will automatically download dependencies!
đĄ Frameworks
đĄ Libraries