Arduino Library for ESP32/ESP8266 - a composition-oriented Internet of Things framework that provides a simple and extendable architecture, handles device setup (WiFi setup, MQTT and application-specific configuration), network connectivity, MQTT telemetry protocol, and more...
ksIotFrameworkLib is an Arduino-based C++ framework designed for ESP32 and ESP8266 microcontrollers.
The library handles the typical IoT boilerplate for you, from initial Wi-Fi provisioning via a captive portal to MQTT connectivity with a robust reconnection mechanism. It also includes a built-in LAN-accessible web portal for device configuration, over-the-air firmware updates, live status monitoring, and terminal access. The terminal, a special feature of the web portal, lets you view real-time application logs and define your own commands.
By handling these repetitive foundations, ksIotFrameworkLib lets you concentrate on the unique logic of your smart sensors, controllers, or DIY automations - without needing to reinvent connectivity or configuration layers every time.
- Smart home solutions (services, monitoring, alarming)
- Telemetry systems (sending sensor data, device statuses)
- Remote control applications (switching devices, executing commands)
π‘ The library is not limited to these examples - itβs designed to support a wide range of IoT projects. For instance, one of my personal implementations involves remotely controlling a heating boiler, fully integrated with Home Assistant via MQTT. I have devices running continuously for months without interruptions, demonstrating the libraryβs stability and reliability in real-world deployments.
- Create a solid starting point for developing applications targeting Espressif microcontrollers.
- Streamline the process of adapting and reusing code across multiple devices.
- Apply the DRY principle (Don't Repeat Yourself) to DIY IoT projects by consolidating common functionality into a simple, reusable library.
- Detailed documentation can be found here.
- For examples, refer to the examples directory.
IMPORTANT FOR ESP32
This library targets Arduino 3+ on ESP32. Due to PlatformIO limitations, it does not automatically fetch the latest versions. Use the pioarduino fork by Jason2866 in your
platformio.inifile:platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zipIMPORTANT FOR ESP8266
For ESP8266, the latest supported version is based on SDK305. To use it, please add this build flag:
DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
flowchart TD
 subgraph Application_Init["Application_Init"]
        B("Mark app state as initialized")
        A("Add initial components")
  end
 subgraph Application_Loop["Application_Loop"]
        CCS{"State?"}
        Loop{{"For each component"}}
        LP1@{ label: "Call component's loop" }
        LP2@{ label: "Call component's init" }
        LP3@{ label: "Call component's postInit" }
        LP4("Remove component")
        DF{"Success?"}
        SCS2("State -> Initialized")
        SCS3("State -> Active")
        X0{{"Continue"}}
        X1{{"Break"}}
        Continue["Continue"]
  end
    AppState{"AppState"} -- NotInitialized --> Application_Init
    AppState -- Initialized --> Application_Loop
    A --> B
    Loop --> CCS
    CCS -- Active --> LP1
    CCS -- NotInitialized --> LP2
    CCS -- Initialized --> LP3
    CCS -- ToRemove --> LP4
    LP2 --> SCS2
    SCS2 --> DF
    LP3 --> SCS3
    SCS3 --> DF
    LP1 --> DF
    DF -- True --> X0
    DF -- False --> X1
    LP4 --> Continue
    LP1@{ shape: rounded}
    LP2@{ shape: rounded}
    LP3@{ shape: rounded}
    - Only one application runs at a time.
- Each application manages its own set of components, the framework's core building blocks.
- Component states are managed within the application's loopfunction.
- Components implement init,postInit, andloopmethods.
- Components marked for removal are safely deleted in the next cycle.
    π ksf
    βββ π ksAppRotator                 βββ Application rotator component
    βββ π ksApplication                βββ Base application class
    βββ π ksRtti                       βββ Implements RTTI (run-time type information) for objects
    βββ π ksComponent                  βββ Base component class
    βββ π ksConstants                  βββ Basic low-level definitions
    βββ π evt
    β   βββ π ksEvent                  βββ Event system implementation
    β   βββ π ksEventHandle            βββ Event handle management
    β   βββ π ksEventInterface         βββ Event interface definition
    βββ π misc
    β   βββ π ksCertUtils              βββ MQTT certificate utilities
    β   βββ π ksConfig                 βββ Configuration file handling
    β   βββ π ksDomainQuery            βββ Custom DNS implementation
    β   βββ π ksSimpleTimer            βββ Simple timer functionality
    β   βββ π ksWSServer               βββ Internal WS handling for device portal
    βββ π res
    β   βββ π otaWebpage               βββ OTA update webpage resources
    βββ π comp
        βββ π ksConfigProvider         βββ Manages configuration parameters and storage
        βββ π ksDevStatMqttReporter    βββ Sends periodic device status updates via MQTT
        βββ π ksDevicePortal           βββ Implements a web-based configuration portal
        βββ π ksLed                    βββ Simplifies LED control
        βββ π ksMqttConfigProvider     βββ Manages MQTT-related configuration
        βββ π ksMqttConnector          βββ Handles MQTT connection management
        βββ π ksResetButton            βββ Implements reset button functionality
        βββ π ksWifiConfigurator       βββ Handles WiFi configuration setup
        βββ π ksWifiConnector          βββ Manages WiFi connection
- Components should be added in the app's initmethod, so they will be available forpostInitmethods. (you can anytime later, from theloopbut please treat it like exceptional case)
- The initmethod is the best place to add dependent components, setup initial pin values etc.
- The postInitmethod is the best place to obtain a weak pointer to another component by callingfindComponent. This will handle cases when other components were added viainitmethod.
To create an application, define a new class that inherits from ksApplication and add initial components in the init method. Refer to projects like emon_fw for a practical example.
- The application is instantiated, and its initmethod is called. Ifinitreturnsfalse, theloopmethod is skipped, and the App Rotator proceeds to instantiate and run the next application in its sequence.
- If initreturnstrue, theloopmethod executes, initializing all components.
- In the next iteration, each componentβs postInitmethod is invoked.
- Once initialized, the application enters a continuous loop, calling each componentβs loopmethod.
- If any componentβs loopmethod returnsfalse, the application terminates, and the App Rotator proceeds to the next application.
bool PelletInfo::init()
{
    // Add WiFi and MQTT debug components
    addComponent<ksf::comps::ksWifiConnector>(PelletInfoConfig::pelletInfoDeviceName);
    addComponent<ksf::comps::ksMqttDebugResponder>();
    addComponent<ksf::comps::ksDevStatMqttReporter>();
    // Add OTA updater component
    addComponent<ksf::comps::ksDevicePortal>();
    // Add state display and receiver components
    addComponent<comps::StateDisplay>();
    addComponent<comps::StateReceiver>();
    // Add reset button component
    addComponent<ksf::comps::ksResetButton>(CFG_PUSH_PIN, LOW);
    // Add MQTT connector component
    addComponent<ksf::comps::ksMqttConnector>();
    // Initialization completed; return true to indicate success
    return true;
}The library provides a very useful utility called ksAppRotator. This object can wrap application instantiation logic into a carousel-like rotation mechanism.
Typically, a device hosts two applications:
- Core application - Runs the core device logic.
- Configuration assistant - Assists the user with device configuration.
Each application implements its own loop() method to manage its logic. In case of a failure at any point (including during the applicationβs construction), the rotator will seamlessly switch to the next application and begin executing its logic.
This design is highly flexible. For example, you can trigger a failure (return false) during an applicationβs init() method, allowing the system to immediately switch into configuration mode if conditions require it (e.g. missing WiFi credentials).
- Bare Arduino projects need to have gnu++2aenabled viacompiler.cpp.extra_flags=option in theboard.txtfile.
- Use the KSF_RTTI_DECLARATIONSmacro to provide proper runtime type information generation for proper casting of components.
- See ksConfigProvider.hfor an example. Your application components should use this macro, otherwise the component finding mechanism won't work.
- Modem sleep is enabled by default and can be controlled as an optional parameter in the ksWifiConnectorconstructor.
- Automatic modem sleep requires the DTIM (Delivery Traffic Indication Message) to be correctly set on the access point.
- The best value for me was 3. It allows the ESP32 to go down from around 100mA to 20mA.
- It is highly recommended to use PlatformIO as it will automatically download dependencies!
- PubSubClient originally developed by @knolleary
- arduinoWebSockets originally developed by @Links2004
