Create embServe Workload
Services to be deployed in Far-Edge devices powered by embServe can be generated using C code. For that, an SDK is provided by embServe, which services must use to ensure compatibility. This page details a simple example showing how this process works.
embServe SDK Setup
The SDK includes everything needed to generate embServe-compliant files. To setup the SDK:
-
Download the SDK bundle from here
-
Unzip file
unzip embservesdk-*.zip -d embserve-sdk
- Setup Python venv
cd embserve-sdk
python3 -m venv .venv
. .venv/bin/activate
- Setup the toolchain
./setup_toolchain.sh
- Export the toolchain path as instructed by the setup script. As an example:
export ZEPHYR_SDK_PATH=/home/user/Workspace/embserve-sdk/toolchain/zephyr/zephyr-sdk-0.16.1
- Add the folder
embserve-sdk/toolchain/udynlink-ngto the PATH. As an example:
export PATH=/home/user/Workspace/embserve-sdk/toolchain/udynlink-ng:$PATH
You need to run the commands above every time you open a new shell. To prevent this, you can add them to the end of your ~/.bashrc or ~/.profile
- Validate the mkmodule command is available:
mkmodule --help
Creating an embServe Service
- Create a folder inside the
embserve-sdk/folder
cd embserve-sdk
mkdir service
- Create the file service.c in the
embserve-sdk/folder with the following:
#include "../include/embserve.h"
#include <string.h>
#include <stdio.h>
static bool running = false;
static int delay_ms;
int setup(void) {
printf("%s started!", SERVICE_NAME);
running = true;
delay_ms = 30000;
return 0;
}
void loop(void) {
printf("Loop");
embserve_sensor_data_t sensor_data = {0};
int sensor_id = 0;
while(running) {
int res = embserve_get_sensor(SENSOR_TEMPERATURE, &sensor_id);
if(res < 0) {
printf("Failed to get sensor!");
return;
}
res = embserve_get_sensor_data(sensor_id, &sensor_data);
if(res < 0) {
printf("Failed to get sensor data!");
return;
}
embserve_io_t output = {
.key = "value",
.type = EMBSERVE_FLOAT,
.data_len = 1,
.data = sensor_data.values
};
embserve_output(&output);
sleep(delay_ms);
}
}
void on_input(embserve_io_t * input) {
if(strcmp(input->key, "rate") == 0) {
int new_delay_ms = *(int *)input->data;
if(new_delay_ms < 1000) {
printf("on_input(): Bad input. Rate too low (%d)", new_delay_ms);
return;
}
delay_ms = new_delay_ms;
printf("on_input(): New rate %d ms", delay_ms);
}
}
void on_quit(void) {
running = false;
}
This service collects Temperature data and sends it as an output ("value"). The sample rate is configurable with the input "rate".
- Build the service:
mkmodule service.c ../src/*.c --name temperature_sensor
- Get the base64 of the generated binary
base64 temperature_sensor.bin -w 0
- Create the JSON manifest,
service.json. Replace<service binary in base64>with the output of the previous command :
{
"name": "temperature_sensor",
"version": 1,
"service": <service binary in base64>,
"dependencies": {
"sdk_api": 1
},
"inputs": [
{
"key": "rate",
"type": 0
}
],
"outputs": [
{
"key": "value",
"type": 1
}
]
}
The inputs and outputs section must match your service. Any output or input not matching the manifest will be discarded by embServe!
- Service manifest is now ready to be deployed
For more information about embServe and its services, refer to this article.
Refer to Deploy Workloads on Far-edge Devices to learn how to deploy this service using FITA.