██╗ ██╗ ██████╗ ██╗ ██╗ ██╗ ██████╗ █████╗ ████████╗███████╗██╗ ██╗ █████╗ ██╗ ██╗
██║ ██║██╔═══██╗██║ ██║ ██╔╝██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝██║ ██║██╔══██╗╚██╗ ██╔╝
██║ █╗ ██║██║ ██║██║ █████╔╝ ██║ ███╗███████║ ██║ █████╗ ██║ █╗ ██║███████║ ╚████╔╝
██║███╗██║██║ ██║██║ ██╔═██╗ ██║ ██║██╔══██║ ██║ ██╔══╝ ██║███╗██║██╔══██║ ╚██╔╝
╚███╔███╔╝╚██████╔╝███████╗██║ ██╗╚██████╔╝██║ ██║ ██║ ███████╗╚███╔███╔╝██║ ██║ ██║
╚══╝╚══╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝
WolkGateway bridges communication between WolkAbout IoT platform and multiple devices connected to it.
WolkGateway supports bridging of devices using following protocol(s):
- WolkAbout protocol
This repository must be cloned from the command line using:
git clone --recurse-submodules https://github.com/Wolkabout/WolkGateway.git
Following tools are required in order to build WolkGateway
- CMake - version 3.5 or later
- Mosquitto MQTT broker
- OpenSSL
- Optional: Docker CE (For running WolkGateway inside Docker container)
Former can be installed on Debian based system from terminal by invoking:
apt-get install mosquitto cmake libssl-dev
Before proceeding with steps from this section complete steps listed in 'Prerequisite' section.
- Generate build system by invoking
./configure
from within WolkGateway base directory. Build system is generated toout
directory - Change current directory to
out
. Following steps are performed from within this directory - Build WolkGateway by invoking
make all -j$(nproc)
- Run WolkGateway tests by invoking
make tests -j$(nproc)
, and if you want to run them again, just execute./WolkGatewayTests
, since you don't have to compile them again.
You can do sudo make install
, which installs the program on your system, adding a systemctl
unit file
and placing the configuration in /etc/wolkGateway
. After that, you can use sudo service wolk_gateway status/start/stop
,
and skip to the next paragraph (next section is about running it manually).
Before proceeding with steps from this section complete steps listed in 'Building' section.
- Change current directory to
out
- Open
gatewayConfiguration.json
and fill name, key and password fields with data provided by WolkAbout IoT platform after gateway device creation and choose who will be responsible for registering and deleting devices - gateway or platform - Make sure mosquitto is running by invoking
systemctl start mosquitto
- Run gateway by invoking
./WolkGatewayApp gatewayConfiguration.json
Note: Running additional instances of WolkGateway on the same network requires having an additional mosquitto broker per gateway. Start a mosquitto daemon from the terminal with mosquitto -p <port> -d
. The port entered here should also be entered into gatewayConfiguration.json
for the matching gateway and into the configuration file of all of the gateway's modules.
Devices are connected to the gateway using modules. Module must implement communication protocol for specific device and manage all communication between devices and the gateway including sending device data and registering devices to WolkAbout platform.
Module communicates with gateway via local mqtt broker which is run along with gateway.
A single Module may handle multiple devices, and there may be multiple modules deployed.
WolkGatewayModule-Cpp is a SDK which implements data handling and device registration with the gateway, and the user needs to implement communication with the devices.
Module may be implemented in any desired language as a mqtt client.
If subdevice management was set to platform
in gatewayConfiguration.json
, then the deletion of devices is enabled on the web application and the gateway stores no information about registered devices, it simply forwards all received data to the platform.
If subdevice management was set to gateway
in gatewayConfiguration.json
, then the gateway keeps track of all devices that are registered via modules. Keys of all registered devices are stored in a file existingDevices.json
which is located in the same directory as gateway executable.
To delete device from gateway open existingDevices.json
file and remove the line containing the key of device which should be deleted, and restart gateway.
Upon starting the gateway will delete all registered devices whose keys no longer appear in existingDevices.json
file.
Note that the device will be registered again if the gateway receives registration request for that device from module.
Gateway can have its own feeds, configuration and firmware update.
Specifying gateway template
std::map<std::string, std::string> typeParameters;
typeParameters.insert(std::pair<std::string, std::string>("subdeviceManagement", "GATEWAY"));
wolkabout::DeviceTemplate gatewayTemplate(
{wolkabout::ConfigurationTemplate("Heating start hour", "HSH", wolkabout::DataType::NUMERIC, "", "8", 0, 24)},
{wolkabout::SensorTemplate("Temperature", "T", wolkabout::DataType::NUMERIC, "", -20, 70)},
{wolkabout::AlarmTemplate("Humidity alarm", "HH", "")},
{wolkabout::ActuatorTemplate("Light switch", "SW", wolkabout::DataType::BOOLEAN, "")},
"",
typeParameters,
{},
{});
wolkabout::GatewayDevice device(gatewayConfiguration.getKey(), gatewayConfiguration.getPassword(), gatewayTemplate);
auto builder = wolkabout::Wolk::newBuilder(device)
.gatewayHost(gatewayConfiguration.getLocalMqttUri())
.platformHost(gatewayConfiguration.getPlatformMqttUri())
.build();
wolk->connectService();
Specifying actuation and configuration handlers/providers
auto builder = wolkabout::Wolk::newBuilder(device)
.gatewayHost(gatewayConfiguration.getLocalMqttUri())
.platformHost(gatewayConfiguration.getPlatformMqttUri())
.actuationHandler([](const std::string& reference, const std::string& value) -> void {
// TODO Invoke your code which activates your actuator.
std::cout << "Actuation request received - Reference: " << reference << " value: " << value << std::endl;
})
.actuatorStatusProvider([](const std::string& reference) -> wolkabout::ActuatorStatus {
// TODO Invoke code which reads the state of the actuator.
if (reference == "ACTUATOR_REFERENCE_ONE") {
return wolkabout::ActuatorStatus("65", wolkabout::ActuatorStatus::State::READY);
} else if (reference == "ACTUATOR_REFERENCE_TWO") {
return wolkabout::ActuatorStatus("false", 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 gateway configuration
})
.configurationProvider([]() -> const std::map<std::string, std::string>& {
// TODO invoke code which reads gateway configuration
return std::map<std::string, std::string>();
})
.build();
wolk->connectService();
Publishing sensor readings
wolk->addSensorReading("TEMPERATURE_REF", 23.4);
wolk->addSensorReading("BOOL_SENSOR_REF", true);
Publishing actuator statuses
wolk->publishActuatorStatus("ACTUATOR_REFERENCE_ONE");
This will invoke the ActuationStatusProvider to read the actuator status, and publish actuator status.
Publish device configuration to platform
wolk->publishConfiguration();
Publishing events
wolk->addAlarm("ALARM_REF", true);
Data publish strategy
Sensor readings, and alarms are pushed to WolkAbout IoT platform on demand by calling
wolk->publish();
Whereas actuator statuses are published automatically by calling:
wolk->publishActuatorStatus("ACTUATOR_REFERENCE_ONE");
Trust store
By default Gateway searches for file named 'ca.crt' in the current directory.
See code snippet below on how to specify trust store for gateway.
wolkabout::GatewayDevice device(gatewayConfiguration.getKey(), gatewayConfiguration.getPassword(),
gatewayConfiguration.getSubdeviceManagement());
auto builder = wolkabout::Wolk::newBuilder(device)
.gatewayHost(gatewayConfiguration.getLocalMqttUri())
.platformHost(gatewayConfiguration.getPlatformMqttUri())
// Specify trust store
.platformTrustStore("path_to_trust_store");
.build();
wolk->connectService();
Firmware Update
WolkAbout Gateway provides mechanism for updating gateway and subdevices firmware.
By default this feature is disabled for gateway and enabled for subdevices. See code snippet below on how to enable device firmware update for gateway.
class CustomFirmwareInstaller: public wolkabout::FirmwareInstaller
{
public:
bool install(const std::string& firmwareFile) override
{
// Mock install
std::cout << "Updating firmware with file " << firmwareFile << std::endl;
// Optionally delete 'firmwareFile
return true;
}
};
auto installer = std::make_shared<CustomFirmwareInstaller>();
wolkabout::GatewayDevice device(gatewayConfiguration.getKey(), gatewayConfiguration.getPassword(),
wolkabout::SubdeviceManagement::GATEWAY, true, true);
auto builder = wolkabout::Wolk::newBuilder(device)
.gatewayHost(gatewayConfiguration.getLocalMqttUri())
.platformHost(gatewayConfiguration.getPlatformMqttUri())
// Enable firmware update
.withFirmwareUpdate("2.1.0", // Current firmware version of the gateway
installer, // Implementation of FirmwareInstaller, which performs installation of obtained gateway firmware
".", // Directory where downloaded firmware files will be stored
10 * 1024 * 1024, // Maximum acceptable size of firmware file, in bytes
1024 * 1024, // Size of firmware file transfer chunk, in bytes
urlDownloader) // Optional implementation of UrlFileDownloader for cases when one wants to download device firmware via given URL
.build();
wolk->connectService();
Firmware update for gateway subdevices is enabled by default. To change default settings without enabling firmware update for gateway use the above api and pass false for firmwareUpdateEnabled in GatewayDevice.