-
Notifications
You must be signed in to change notification settings - Fork 3
DeviceFactoryAndClasses
The device factory manages device class registration and instantiation.
RaftBusDevice:
- Automatically created for devices detected on buses
- Uses device type records for all configuration
- Handles generic I2C devices
Custom Device Classes:
- Application-specific device implementations
- Can override detection, initialization, polling
- May provide custom data processing
// In device class implementation file
static RaftDevice* create(const char* pClassName, const char* pDevConfigJson)
{
return new MyCustomDevice(pClassName, pDevConfigJson);
}
// Registration (typically in device class static initializer)
class MyCustomDeviceRegistrar
{
public:
MyCustomDeviceRegistrar()
{
deviceFactory.registerDevice("MyCustomDevice", create);
}
};
static MyCustomDeviceRegistrar registrar;Static Devices (Configured):
- Defined in SysType configuration
- Created during DeviceManager setup
- Always present (may be offline)
- Example: Built-in displays, dedicated sensors
Dynamic Devices (Auto-discovered):
- Created when detected on bus
- RaftBusDevice instances
- Hot-swap capable
- Example: Pluggable I2C modules
Device types are primarily defined in generated code, but can be extended:
{
"DevMan": {
"Devices": [
{
"name": "CustomSensor",
"class": "CustomSensorClass",
"enable": true
}
]
}
}Here is a more concrete example of a buzzer device which is implemented using the following code snippets:
// DeviceBuzzer.h
#pragma once
#include "RaftCore.h"
#include "driver/ledc.h"
class RestAPIEndpointManager;
class CommsCoreIF;
class APISourceInfo;
class DeviceBuzzer : public RaftDevice
{
public:
DeviceBuzzer(const char* pClassName, const char *pDevConfigJson)
: RaftDevice(pClassName, pDevConfigJson) {}
virtual ~DeviceBuzzer() {}
// Create function
static RaftDevice* create(const char* pClassName, const char* pDevConfigJson)
{
return new DeviceBuzzer(pClassName, pDevConfigJson);
}
/// @brief Setup the device
virtual void setup() override final
{
// Buzzer pin
_buzzerPin = deviceConfig.getInt("pin", -1);
// LEDC config
_ledcChannel = (ledc_channel_t)deviceConfig.getInt("ledcChannel", LEDC_CHANNEL_0);
_ledcTimer = (ledc_timer_t)deviceConfig.getInt("ledcTimer", LEDC_TIMER_1);
// ... setup ledc here using ESP IDF standard code
}
/// @brief Main loop for the device (called frequently)
virtual void loop() override final {}
// Add REST API endpoints
virtual void addRestAPIEndpoints(RestAPIEndpointManager& endpointManager) override final
{
// Audio
endpointManager.addEndpoint("buzzer", RestAPIEndpoint::ENDPOINT_CALLBACK, RestAPIEndpoint::ENDPOINT_GET,
std::bind(&DeviceBuzzer::apiControl, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
"buzzer/note/<freq>");
}
private:
// Buzzer pin
int _buzzerPin = -1;
// LEDC config
ledc_channel_t _ledcChannel = LEDC_CHANNEL_0;
ledc_timer_t _ledcTimer = LEDC_TIMER_1;
// API
RaftRetCode apiControl(const String &reqStr, String &respStr, const APISourceInfo& sourceInfo)
{
RaftJson cmdJson = RaftJson::getJSONFromRESTRequest(reqStr);
if (cmdJson.getString("path[1]","").equalsIgnoreCase("note"))
{
playFreq(int(cmdJson.getString("path[2]", "440")));
}
}
// Play a frequency
void playFreq(uint32_t freqHz)
{
// ... LEDC play note
}
};
In the startup process (e.g. in main.cpp) the device must be registered with the device factory using code like this - note that the name "Buzzer" must match the section in the SysType JSON (see below) otherwise the device will not be instantiated.
#include "DeviceFactory.h"
#include "DeviceBuzzer.h"
extern "C" void app_main(void)
{
/// ... Other setup code
// Register DeviceBuzzer
deviceFactory.registerDevice("Buzzer", DeviceBuzzer::create);
}And the device is automatically configured when it is initialized by the device manager through the SysType mechanism under the DevMan\Devices key (which is an array of device settings).
"DevMan": {
"Devices":
[
{
"enable": 1,
"class": "Buzzer",
"name": "Buzzer",
"pin": 5,
"ledcTimer": 1,
"ledcChannel": 0,
"volume": 20
},
{
...
}
]
}