Build a SubNode Application
Use the WEDA SubNode SDK to turn equipment readings or application output into telemetry that WEDA can manage. Start with the included Modbus simulator, then configure a real source and package an image for deployment through WEDA Node.
WEDA SubNode SDK on GitHub
provides the source, project templates, examples and detailed SDK documentation.
The examples below use the repository's release/v1.1.0 branch.
Understand SubNode and WEDA Node
A SubNode application reads its sources, processes the readings and sends telemetry through WEDA Node. WEDA Node carries the connection to WEDA Cloud. The SubNode has its own device identity in Cloud, separate from its parent WEDA Node.
Within the SDK, a SubNode can contain multiple Device objects, each with its own Sensors. These Device objects represent equipment or data sources inside your application; they are different from the SubNode's Cloud device record.
For example, the template in this guide contains one Modbus Device with a temperature Sensor. You first test its readings locally, then verify that its telemetry reaches the SubNode's DataStreams in Cloud.
Get the SDK and Prepare Your Environment
Prepare the tools for the stage you are working on:
| Stage | Requirements |
|---|---|
| Build and run locally | Git, .NET 10.0 SDK and a C# editor; access to restore the project's NuGet packages |
| Build a container image | Docker on the build machine |
| Publish an image | Access to a container registry and an image architecture compatible with the target WEDA Node |
The repository also includes a VS Code Dev Container with development tools and templates. The shell commands in this guide use Bash.
-
Obtain the source:
git clone --branch release/v1.1.0 https://github.com/Advantech-WEDA/WEDA-Sub-Node.git
cd WEDA-Sub-Node
dotnet --version -
Confirm that .NET SDK 10.0 is available. Keep the repository layout: the templates reference SDK projects under
src/. -
Use
templates/for new projects,examples/for existing integrations and the SDK documentation for configuration and extension details.
Install Project Templates
From the repository root, install both templates:
dotnet new install ./templates/wedabuilder
dotnet new install ./templates/subnode
dotnet new list weda
| Short name | Development approach |
|---|---|
wedabuilder | Builder pattern with host-managed lifecycle; use this for the walkthrough below |
subnode | Console-style application with explicit SubNode initialization and lifecycle control |
Check the result: The template list includes both wedabuilder and subnode.
If you use bash scripts/install-templates.sh instead, note that it removes known
older WEDA template registrations before installing the repository's templates.
Create and Run Your First Project
-
Create the project under
apps/inside the cloned repository:mkdir -p apps
cd apps
dotnet new wedabuilder -n MyFirstSubNode
cd MyFirstSubNode
dotnet run -
Watch the terminal for the simulator starting and
temperature_sensorreadings. The generated configuration uses127.0.0.1:5020for the Modbus simulator. -
Press Ctrl+C to stop the application before changing its configuration.
The template starts a Modbus simulator and calls UseMockCloud(). MockCloud
simulates the Cloud service locally; this run does not create a device or send
telemetry to your WEDA Cloud environment.
Check the result: You can read changing simulated temperature values without physical equipment or a WEDA Node connection.
Keep the generated project under apps/MyFirstSubNode/. Its project references
use ../../src/; moving only the application directory breaks those references.
Connect Sensors and Configure Data
The generated files separate the integration settings:
| File | What you configure |
|---|---|
Program.cs | Device registration, hosting and MockCloud selection |
MyFirstDevice.cs | The Modbus Device class and handling of received readings |
devicecfg.json | SubNode metadata, source connection, Sensors and reporting |
appsettings.json | Logging and the built-in Modbus simulator |
systemcfg.json | The connection and authentication settings for WEDA Node |
For the temperature example:
-
In
devicecfg.json, setSubNode.NametoMyFirstSubNode. Keep theDeviceConfigs.MyFirstDevicekey aligned withAddDevice<MyFirstDevice>("MyFirstDevice")inProgram.cs. -
Review the existing Sensor in
DeviceConfigs.MyFirstDevice.Sensors. It reads two holding registers as a Float32 and declares the resulting telemetry asdouble:{
"Name": "temperature_sensor",
"SensorGroup": "TEMP",
"SensorInfo": {
"DisplayName": "Temperature Sensor",
"Description": "Main temperature reading",
"Schema": "double"
},
"Parameters": {
"RegisterType": "HoldingRegister",
"RegisterAddress": 0,
"RegisterCount": 2,
"DataType": "Float32"
},
"Report": {
"Enabled": true,
"Interval": 1000,
"Unit": "celsius"
}
}Parameters.DataTypedescribes how to interpret the Modbus registers.SensorInfo.Schemadescribes the telemetry value.Report.Intervalis in milliseconds. Keep the Sensor name stable when continuing the same integration. -
For real equipment, change
DeviceCommunication.Host,Port,Properties.SlaveIdand the Sensor register settings to match its register map. Remove the simulator hosted-service registration fromProgram.cswhen the simulator is no longer needed. -
Run the application again and compare its readings with the source.
The SDK provides integrations for Modbus TCP/RTU, MQTT and HTTP, and supports custom Device implementations. Select a matching Device class or repository example; the Modbus fields above do not configure a different protocol.
For optional processing, configure Report.TransformPipeline for operations such
as calibration or unit conversion, followed by Report.DspPipeline for filtering.
See the pipeline configuration guide
for processor settings. Image and binary integrations have different value and
schema requirements; use the image-sensor example
when developing those sources.
Check the result: The application reads the intended source with the expected value type, unit and reporting settings before you package the application.
Implement Custom Commands
Your application can implement actions that a Cloud application invokes through WEDA Node. Define the command keyword and parameters, validate the request, handle the operation and return a structured result.
The public Custom Command Handler Example
is on feature/v1.2.0-rc. It is an optional reference, separate from the
release/v1.1.0 template walkthrough above. Use the example with its own SDK
checkout; do not copy its files into the earlier project and assume compatibility.
Start with sensor.read, which returns the latest available reading for a
named Sensor. It demonstrates the application side of the Cloud command used in
Remote Commands.
| Concern | File under examples/feature-custom-commands/ |
|---|---|
| Keyword and parameters | Commands/SensorRead/Models/SensorReadCommand.cs: [DeviceCmd("sensor.read")], optional deviceName, required sensorName |
| Request validation | Commands/SensorRead/SensorReadCommandValidator.cs |
| Execution | Commands/SensorRead/SensorReadCommandHandler.cs |
| Typed result | Commands/SensorRead/Models/SensorReadResult.cs |
| Local test dispatch | Services/CommandDemoService.cs |
To study it locally:
-
Obtain a separate checkout:
git clone --branch feature/v1.2.0-rc https://github.com/Advantech-WEDA/WEDA-Sub-Node.git WEDA-Sub-Node-commands
cd WEDA-Sub-Node-commands/examples/feature-custom-commands -
In that example's
Program.cs, explicitly select MockCloud for an offline test:var builder = WedaApplication.CreateDefaultBuilder(args)
.UseMockCloud();The current example's source defaults to a real Node connection. Keep its simulator and
CommandDemoServiceregistrations for this local test. -
Run
dotnet run. Inspect the demo command outcomes and the returned Sensor value, timestamp and unit. The demo service also exercisestag.setandprops.get, which illustrate typed map parameters and results. -
When adapting the example, implement your own handler and validation. The Host discovers handlers in the application assembly. Before production packaging, remove the local demo dispatcher and
UseMockCloud().
Check the result: Local dispatch reaches the intended handler and returns a result. This checks the SDK command implementation, not the Cloud transport or the Cloud command catalog. Use the deployment guide below for that verification.
The README shows a device-message envelope using deviceCmd, timeout and
respTopic. A Cloud caller uses the public REST contract, including
deviceCommand and parameters; it does not POST that device envelope.
Package an Image for WEDA Deployment
-
Prepare the application for a real Node connection. In the main walkthrough's
Program.cs, remove.UseMockCloud():var builder = WedaApplication.CreateDefaultBuilder(args);Keep the simulator only if you intend to deploy the simulated-temperature demonstration. Remove it when using your real source. Connection settings are supplied at deployment time in
systemcfg.json. -
Keep only placeholder credentials in configuration files included in the build. The generated Dockerfile copies the source tree and publishes the application's JSON files. Prepare real connection credentials separately on the target device.
-
From the repository root, build and publish an image. Replace the illustrative registry host, repository and tag with your own:
SUBNODE_IMAGE='registry.example.com/weda/my-first-subnode:1.0.0'
docker build -f apps/MyFirstSubNode/Dockerfile -t "$SUBNODE_IMAGE" .
docker login registry.example.com
docker push "$SUBNODE_IMAGE"The build context includes
src/and shared build files. Build for the target device's CPU architecture; a successful build on your workstation does not establish device compatibility. -
Prepare the generated configuration files and an image-based Compose definition using the next guide's example. Replace the template's
build:section with the publishedimage:reference.
Check the result: You have a versioned image in the registry, the application configuration files and a Compose definition referencing that image. Building or publishing the image does not create a WEDA deployment.
Continue with Deploy a SubNode Application with WEDA to prepare the target Node, deploy the Stack and check the container and SubNode separately.
References for Further Integration
Choose the reference that matches your next task:
| Task | Official SDK reference |
|---|---|
| Check Sensor fields and protocol settings | Sensor Configuration Reference (v1.1.0) |
| Combine multiple sources in one SubNode | SubNode Hierarchy (v1.1.0) |
| Start from an existing Docker-based integration | SI Integration Guide (v1.1.0) |
| Report an AI container's HTTP or MQTT output | Edge AI Container Integration Recipe (v1.1.0) |
The Edge AI recipe explains data-source and parser patterns. Adapt its code and payload mapping to your SDK version and application; adding arbitrary JSON alone does not implement a new protocol parser.
Constraints and Troubleshooting
For image or binary sources, account for Base64 expansion: the SDK's default MIME validator checks an encoded string against 10,485,760 characters before decoding. For local recording, configure retention and capacity for your workload; older recordings can be removed by cleanup.
| Symptom | What to check |
|---|---|
| Template is not listed | Install from the cloned repository and check the .NET SDK version |
| SDK project cannot be found | Keep the application under apps/<project>/ so ../../src/ resolves |
| No local temperature readings | Match the simulator/source endpoint, Device key, enabled Sensor and register settings |