WolkAbout C++11 Connector library for connecting devices to WolkAbout Gateway.
Supported protocol(s):
- JSON_PROTOCOL
This repository must be cloned from the command line using:
git clone --recurse-submodules https://github.com/Wolkabout/WolkGatewayModule-SDK-Cpp.git
Following tools/libraries are required in order to build WolkAbout C++ connector
- cmake - version 3.5 or later
- autotools
- autoconf
- libtool
- m4
- zlib1g-dev
- openssl
Former can be installed on Debian based system from terminal by invoking
apt-get install autotools-dev autoconf libtool m4 zlib1g-dev cmake libssl-dev
Afterwards dependencies are built, and Makefile build system is generated by invoking
./configure
Generated build system is located inside 'out' directory
WolkAbout C++ Connector library, and example are built from 'out' directory by invoking
make
in terminal. To make tests, you need to invoke make tests
.
Establishing connection with WolkAbout IoT platform:
wolkabout::Device device("DEVICE_KEY", "DEVICE_PASSWORD", {"ACTUATOR_REFERENCE_ONE", "ACTUATOR_REFERENCE_TWO"});
std::unique_ptr<wolkabout::Wolk> wolk =
wolkabout::Wolk::newBuilder()
.actuationHandler([](const std::string& deviceKey, const std::string& reference, const std::string& value) -> void {
// TODO Invoke your code which activates actuator of specified device.
std::cout << "Actuation request received - Key: " << deviceKey << " Reference: " << reference << " value: " << value << std::endl;
})
.actuatorStatusProvider([](const std::string& deviceKey, const std::string& reference) -> wolkabout::ActuatorStatus {
// TODO Invoke code which reads the state of the actuator of specified device.
if (deviceKey == "DEVICE_KEY" && reference == "SWITCH_ACTUATOR_REF") {
return wolkabout::ActuatorStatus("true", wolkabout::ActuatorStatus::State::READY);
return wolkabout::ActuatorStatus("", wolkabout::ActuatorStatus::State::READY);
})
.configurationHandler([](const std::map<std::string, std::string>& configuration) -> void {
// TODO invoke code which sets device configuration
})
.configurationProvider([]() -> const std::map<std::string, std::string>& {
// TODO invoke code which reads device configuration
return std::map<std::string, std::string>();
})
.deviceStatusProvider([](const std::string& deviceKey) -> wolkabout::DeviceStatus {
// TODO Invoke code which reads the status of specified device.
if (deviceKey == "DEVICE_KEY")
{
return wolkabout::DeviceStatus::CONNECTED;
}
return wolkabout::DeviceStatus::OFFLINE;
})
.build();
wolk->connect();
Creating devices:
wolkabout::SensorManifest temperatureSensor{"Temperature", // name
"TEMPERATURE_REF", // reference
"Temperature sensor", // description
"℃", // unit
"TEMPERATURE", // reading type
wolkabout::SensorManifest::DataType::NUMERIC, // data type
1, // percision
-273.15, // min value
100000000}; // max value
wolkabout::SensorManifest pressureSensor{"Pressure",
"PRESSURE_REF",
"Pressure sensor",
"mb",
"PRESSURE",
wolkabout::SensorManifest::DataType::NUMERIC,
1,
0,
1100};
wolkabout::SensorManifest accelerationSensor{"Acceleration",
"ACCELEROMETER_REF",
"Acceleration sensor",
"m/s²",
"ACCELEROMETER",
wolkabout::SensorManifest::DataType::NUMERIC,
1,
0,
20000,
"%", // delimiter
{"x", "y", "z"}}; // labels
wolkabout::ActuatorManifest switchActuator{"Switch",
"SWITCH_ACTUATOR_REF",
"Switch actuator",
"",
"SW",
wolkabout::ActuatorManifest::DataType::BOOLEAN,
1,
0,
1};
wolkabout::AlarmManifest highHumidityAlarm{"High Humidity", // name
wolkabout::AlarmManifest::AlarmSeverity::ALERT, // severity
"HUMIDITY_ALARM_REF", // reference
"High Humidity", // message
"High Humidity alarm"}; // description
wolkabout::DeviceManifest deviceManifest1{"DEVICE_MANIFEST_NAME",
"DEVICE_MANIFEST_DESCRIPTION",
"JsonProtocol",
"",
{},
{temperatureSensor, pressureSensor},
{},
{switchActuator}};
wolkabout::Device device1{"DEVICE_NAME", "DEVICE_KEY", deviceManifest};
wolk->addDevice(device);
Publishing sensor readings:
wolk->addSensorReading("DEVICE_KEY", "TEMPERATURE_REF", 23.4);
wolk->addSensorReading("DEVICE_KEY", "PRESSURE_REF", 1080);
wolk->addSensorReading("DEVICE_KEY_2", "ACCELEROMETER_REF", {0, -5, 10});
Publishing actuator statuses:
wolk->publishActuatorStatus("DEVICE_KEY", "SWITCH_ACTUATOR_REF");
This will invoke the ActuationStatusProvider to read the actuator status, and publish actuator status.
Publish device configuration to platform:
wolk->publishConfiguration("DEVICE_KEY");
This will invoke the ConfigurationProvider to read the configuration and publish it.
Publishing alarms:
wolk->addAlarm("DEVICE_KEY", "HUMIDITY_ALARM_REF", "ALARM_VALUE");
Data publish strategy:
Sensor readings, and alarms are pushed to WolkAbout IoT platform on demand by calling
wolk->publish();
wolk->publish("DEVICE_KEY");
Publishing without providing device key publishes all available data, whereas publishing with device key only data for the specified device is published
Actuator statuses are published automatically by calling:
wolk->publishActuatorStatus("DEVICE_KEY", "ACTUATOR_REFERENCE_ONE");
Configuration is published automatically by calling:
wolk->publishConfiguration("DEVICE_KEY");
Disconnecting from the platform:
wolk->disconnect();
Data persistence:
WolkAbout C++ Connector provides mechanism for persisting data in situations where readings can not be sent to WolkAbout Gateway.
Persisted readings are sent to WolkAbout Gateway once connection is established. Data persistence mechanism used by default stores data in-memory.
In cases when provided in-memory persistence is suboptimal, one can use custom persistence by implementing wolkabout::Persistence interface, and forwarding it to builder in following manner:
std::unique_ptr<wolkabout::Wolk> wolk =
wolkabout::Wolk::newBuilder()
.actuationHandler([](const std::string& deviceKey, const std::string& reference, const std::string& value) -> void {
// TODO Invoke your code which activates actuator of specified device.
std::cout << "Actuation request received - Key: " << deviceKey << " Reference: " << reference << " value: " << value << std::endl;
})
.actuatorStatusProvider([](const std::string& deviceKey, const std::string& reference) -> wolkabout::ActuatorStatus {
// TODO Invoke code which reads the state of the actuator of specified device.
if (deviceKey == "DEVICE_KEY" && reference == "SWITCH_ACTUATOR_REF") {
return wolkabout::ActuatorStatus("true", wolkabout::ActuatorStatus::State::READY);
return wolkabout::ActuatorStatus("", wolkabout::ActuatorStatus::State::READY);
})
.configurationHandler([](const std::map<std::string, std::string>& configuration) -> void {
// TODO invoke code which sets device configuration
})
.configurationProvider([]() -> const std::map<std::string, std::string>& {
// TODO invoke code which reads device configuration
return std::map<std::string, std::string>();
})
.deviceStatusProvider([](const std::string& deviceKey) -> wolkabout::DeviceStatus {
// TODO Invoke code which reads the status of specified device.
if (deviceKey == "DEVICE_KEY")
{
return wolkabout::DeviceStatus::CONNECTED;
}
return wolkabout::DeviceStatus::OFFLINE;
})
.withPersistence(std::make_shared<CustomPersistenceImpl>()) // Enable data persistance via custom persistence mechanism
.build();
wolk->connect();
For more info on persistence mechanism see wolkabout::Persistence and wolkabout::InMemoryPersistence classes
Firmware Update
WolkAbout C++ Connector provides mechanism for updating devices' firmware. To enable firmware update one must provide implementation for wolkabout::FirmwareInstaller and wolkabout::FirmwareVersionProvider
See code snippet below on how to enable device firmware update for devices.
class CustomFirmwareInstaller: public wolkabout::FirmwareInstaller
{
public:
void install(const std::string& deviceKey, const std::string& firmwareFile,
std::function<void(const std::string& deviceKey)> onSuccess,
std::function<void(const std::string& deviceKey)> onFail) override
{
// Mock install
std::cout << "Updating firmware for device " << deviceKey << " with file " << firmwareFile << std::endl;
onSuccess(deviceKey);
}
bool abort(const std::string& deviceKey) override
{
// Mock abort
std::cout << "Aborting firmware installation for device " << deviceKey << std::endl;
return false;
}
};
class CustomFirmwareVersionProvider : public wolkabout::FirmwareVersionProvider
{
public:
std::string getFirmwareVersion(const std::string& deviceKey)
{
// return firmware version for the device
return "1.0";
}
};
auto installer = std::make_shared<CustomFirmwareInstaller>();
auto provider = std::make_shared<CustomFirmwareVersionProvider>();
auto builder = wolkabout::Wolk::newBuilder()
.actuationHandler([](const std::string& deviceKey, const std::string& reference, const std::string& value) -> void {
// TODO Invoke your code which activates actuator of specified device.
std::cout << "Actuation request received - Key: " << deviceKey << " Reference: " << reference << " value: " << value << std::endl;
})
.actuatorStatusProvider([](const std::string& deviceKey, const std::string& reference) -> wolkabout::ActuatorStatus {
// TODO Invoke code which reads the state of the actuator of specified device.
if (deviceKey == "DEVICE_KEY" && reference == "SWITCH_ACTUATOR_REF") {
return wolkabout::ActuatorStatus("true", wolkabout::ActuatorStatus::State::READY);
return wolkabout::ActuatorStatus("", wolkabout::ActuatorStatus::State::READY);
})
.configurationHandler([](const std::map<std::string, std::string>& configuration) -> void {
// TODO invoke code which sets device configuration
})
.configurationProvider([]() -> const std::map<std::string, std::string>& {
// TODO invoke code which reads device configuration
return std::map<std::string, std::string>();
})
.deviceStatusProvider([](const std::string& deviceKey) -> wolkabout::DeviceStatus {
// TODO Invoke code which reads the status of specified device.
if (deviceKey == "DEVICE_KEY")
{
return wolkabout::DeviceStatus::CONNECTED;
}
return wolkabout::DeviceStatus::OFFLINE;
})
.withFirmwareUpdate(installer, provider)
.build();