-
-
Notifications
You must be signed in to change notification settings - Fork 3
Architecture
This section explains the high-level architecture and design principles of ksIotFrameworkLib.
ksIotFrameworkLib is built on three core principles:
Build applications by composing reusable components rather than creating deep inheritance hierarchies. Each component encapsulates a specific piece of functionality and can be easily combined with others.
The framework separates:
- Hardware interaction from business logic
- Configuration from runtime behavior
- Network management from application logic
Applications can gracefully fall back to alternative modes (like configuration assistant) when normal operation fails.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Arduino Framework β
β (ESP32/ESP8266 Core + C++ Runtime) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Application Rotator β
β - Manages application lifecycle β
β - Handles failover between apps β
β - Implements setup() and loop() for Arduino β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββ΄ββββββββββββββββ
βΌ βΌ
ββββββββββββββββββββββββ ββββββββββββββββββββββββ
β Main Application β β Config Application β
β (Device Logic) β β (Setup Assistant) β
ββββββββββββββββββββββββ ββββββββββββββββββββββββ
β β
βββββββββββββββββ¬ββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Component Manager β
β - Component lifecycle management β
β - Dependency resolution β
β - State transitions β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β ksWifiConnectorβ β ksMqttConnector β β ksDevicePortal β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Hardware & Network β
β (WiFi, MQTT, WebSockets, Files, GPIO) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ksIotFrameworkLib/
βββ src/ksf/
β βββ Core Framework
β β βββ ksApplication.h/cpp # Base application class
β β βββ ksComponent.h/cpp # Base component class
β β βββ ksAppRotator.h # Application rotator
β β βββ ksRtti.h # Custom RTTI system
β β βββ ksConstants.h/cpp # Framework constants
β β
β βββ Components (ksf/comp/)
β β βββ ksWifiConnector.h/cpp # WiFi connection management
β β βββ ksWifiConfigurator.h/cpp # WiFi provisioning
β β βββ ksMqttConnector.h/cpp # MQTT client
β β βββ ksMqttConfigProvider.h # MQTT configuration
β β βββ ksDevicePortal.h/cpp # Web portal
β β βββ ksDevStatMqttReporter.h # Device status
β β βββ ksLed.h/cpp # LED control
β β βββ ksResetButton.h/cpp # Reset button
β β βββ ksConfigProvider.h # Config base class
β β
β βββ Event System (ksf/evt/)
β β βββ ksEvent.h # Event implementation
β β βββ ksEventHandle.h # Event handle management
β β βββ ksEventInterface.h # Event interface
β β
β βββ Utilities (ksf/misc/)
β β βββ ksConfig.h # Configuration files
β β βββ ksSimpleTimer.h # Timer utility
β β βββ ksCertUtils.h # Certificate utilities
β β βββ ksWSServer.h # WebSocket server
β β
β βββ Resources (ksf/res/)
β βββ otaWebpage # OTA update HTML
β
βββ ksIotFrameworkLib.h # Main include header
void setup() {
// Implemented by ksAppRotator
// Creates first application
}
void loop() {
// Implemented by ksAppRotator
// Manages application switching
}// App rotator creates application instance
MyApp* app = new MyApp();app->init() {
// Add components
addComponent<ksWifiConnector>();
addComponent<ksMqttConnector>();
// ... more components
}app->postInit() {
// Components can find dependencies
auto mqtt = findComponent<ksMqttConnector>();
auto led = findComponent<ksLed>();
}app->loop() {
// Each component's loop() is called
for (component : components) {
component->loop();
}
}// If any component returns false:
delete app;
app = new ConfigApp(); // Switch to configββββββββββββ
β Created β addComponent<T>()
βββββββ¬βββββ
β
βΌ
ββββββββββββ
β Init β init() called by app
βββββββ¬βββββ
β
βΌ
ββββββββββββ
β PostInit β postInit() - find dependencies
βββββββ¬βββββ
β
βΌ
ββββββββββββ
β Active β loop() called repeatedly
βββββββ¬βββββ
β
βΌ false
ββββββββββββ
β ToRemove β marked for deletion
βββββββ¬βββββ
β
βΌ
ββββββββββββ
β Deleted β memory freed
ββββββββββββ
Method 1: Direct Reference (postInit)
bool postInit() {
auto mqtt = findComponent<ksMqttConnector>();
if (mqtt) {
// Use mqtt directly
}
}Method 2: Event System
// Publish
event->publish("button_pressed", data);
// Subscribe
event->subscribe("button_pressed", callback);Method 3: Shared State via Application
// Store shared data in application
app->setData("sensor", value);
// Retrieve from other component
auto value = app->getData("sensor");The rotator enables robust multi-application scenarios:
-
Main Application
- Normal device operation
- Reads sensors, controls actuators
- Communicates via MQTT
-
Configuration Application
- Activates on first boot or error
- Provides captive portal for setup
- Saves configuration to storage
// In main application
bool init() {
if (!hasWifiCredentials()) {
return false; // Trigger switch to config
}
return true;
}- Resilience: Device never gets stuck
- UX: Easy setup without reflashing
- Safety: Always recoverable to config mode
Components use smart pointers for automatic memory management:
using ComponentPtr = std::shared_ptr<ksComponent>;
// Automatically cleaned when:
// - Application is destroyed
// - Component is removed-
Application owns components
- Components are destroyed with application
-
Components own their resources
- Cleanup in destructor or onRemove()
-
No manual delete needed
- Framework handles all memory
// β
Good - Let framework manage memory
addComponent<ksLed>(LED_PIN);
// β Bad - Manual memory management
ksLed* led = new ksLed(LED_PIN); // Don't do thisThe framework is single-threaded by design:
void loop() {
for (component : components) {
component->loop(); // Sequential execution
}
}- No mutexes needed - Only one thread
- Predictable timing - Sequential execution
- Watchdog friendly - Always returns from loop
- Simpler debugging - No race conditions
For async tasks (network, MQTT):
// Component handles non-blocking I/O
bool loop() {
mqtt->loop(); // Process available data
wifi->loop(); // Check connection
return true; // Always return quickly
}class MySensor : public ksComponent {
KSF_RTTI_DECLARATIONS(MySensor, ksComponent)
bool init() override {
// Setup sensor
return true;
}
bool loop() override {
// Read sensor
return true;
}
};class MyApp : public ksApplication {
bool init() override {
addComponent<MySensor>();
addComponent<ksMqttConnector>();
return true;
}
};event->subscribe("custom_event", [](auto data) {
// Handle event
});class MyConfigProvider : public ksConfigProvider {
// Custom storage backend
};- Base framework: ~10KB flash
- Typical app: +20-50KB for components
- RAM usage: ~30-50KB (varies by components)
- Idle: Minimal (main loop overhead)
- WiFi: Active during connection/data
- MQTT: Event-driven, low overhead
- Web portal: Only when accessed
- Active: ~100mA (ESP32)
- Modem sleep: ~20mA (when idle)
- Deep sleep: ~10Β΅A (application controlled)
β
Manages WiFi connections
β
Handles MQTT communication
β
Provides web interface
β
Manages configuration
β
Handles OTA updates
- Application logic - Your specific device behavior
- Custom components - Specialized functionality
- Business rules - When/how to act
- Hardware integration - Sensor/actuator specifics
Now that you understand the architecture:
- π§© Core Concepts β Deep dive into Applications and Components
- π¦ Components Reference β All built-in components
- π Examples β See architecture in action
π€ This wiki is automatically generated and may contain errors.
Please report any issues here:
π https://github.com/cziter15/ksIotFrameworkLib/issues