Quick Start
This guide walks you through creating a logic block library, adding properties and a timer, testing it, and running it locally — all using the Dale CLI.
Prerequisites
- .NET 10 SDK
- A terminal (bash, PowerShell, or cmd)
Install the Dale CLI
dotnet tool install -g Vion.Dale.CliVerify the installation:
dale --versionThe CLI and SDK packages are on nuget.org under the Vion.* prefix. The Dale SDK source is available at VION-IoT/dale-sdk.
Create a New Project
dale new SmartThermostatThe Dale CLI prompts for a package ID, author, and first logic block name. Defaults are shown in brackets — press Enter to accept them.
This scaffolds a complete project:
SmartThermostat/
├── SmartThermostat/ # Logic block library
│ ├── DependencyInjection.cs # Service registration
│ ├── HelloWorld.cs # Simple example logic block
│ └── SmartLedController.cs # Comprehensive I/O example
├── SmartThermostat.DevHost/ # Local DevHost with web UI
├── SmartThermostat.Test/ # Unit tests
├── CLAUDE.md # AI agent instructions
└── AGENTS.md # Agent conventions and patternsExplore the Generated Code
The scaffolded HelloWorld.cs shows the essential building blocks — a writable property, a read-only measuring point, and a timer:
using Vion.Dale.Sdk.Core;
using Microsoft.Extensions.Logging;
public class HelloWorld : LogicBlockBase
{
private readonly ILogger _logger;
/// <summary>A writable property for the greeting message.</summary>
[ServiceProperty]
public string Greeting { get; set; } = "Hello, World!";
/// <summary>A measuring point tracking how many times we greeted.</summary>
[ServiceMeasuringPoint]
public int TimesGreeted { get; private set; }
public HelloWorld(ILogger logger) : base(logger)
{
_logger = logger;
}
/// <summary>Called every 5 seconds by the Dale runtime.</summary>
[Timer(5)]
public void Greet()
{
_logger.LogInformation(Greeting);
TimesGreeted++;
}
protected override void Ready()
{
_logger.LogInformation("HelloWorld is ready.");
}
}What you see here:
[ServiceProperty]with a public setter makesGreetingwritable — you can change it from the Dashboard or API at runtime, and it is automatically persisted across restarts.[ServiceMeasuringPoint]with a private setter makesTimesGreeteda read-only metric. It is recorded over time and visible in dashboards.[Timer(5)]callsGreet()every 5 seconds. The method runs inside the actor context, so it is thread-safe.Ready()is where initialization happens — subscribe to events, set initial state.
Run Locally
Start the DevHost to test your logic block with a web UI:
dale devOpen http://localhost:5000 in your browser. The DevHost shows your logic blocks with controls to inspect properties, modify writable values, and watch measuring points update in real-time.
Add Your Own Logic Block
The scaffolded HelloWorld shows the basics. Now create a second logic block — a simple thermostat controller. dale add runs from inside the logic block project folder:
cd SmartThermostat
dale add logicblock ThermostatOpen SmartThermostat/Thermostat.cs and replace the generated code:
using Vion.Dale.Sdk.Core;
using Microsoft.Extensions.Logging;
[LogicBlock(Name = "Thermostat", Icon = "temp-cold-line")]
public class Thermostat : LogicBlockBase
{
private readonly ILogger _logger;
[ServiceProperty(Title = "Target Temperature", Unit = "°C")]
[Presentation(Group = PropertyGroup.Configuration)]
public double TargetTemperature { get; set; } = 21.0;
[ServiceProperty(Title = "Heating Active")]
[ServiceMeasuringPoint]
[Presentation(Group = PropertyGroup.Status, Importance = Importance.Primary)]
public bool HeatingActive { get; private set; }
[ServiceMeasuringPoint(Title = "Current Temperature", Unit = "°C")]
[Presentation(Group = PropertyGroup.Status, Importance = Importance.Secondary)]
public double CurrentTemperature { get; private set; }
public Thermostat(ILogger logger) : base(logger)
{
_logger = logger;
}
[Timer(2)]
public void Poll()
{
// In production, this would read from a sensor via a service provider contract.
// For local testing, the DevHost UI lets you set CurrentTemperature manually.
HeatingActive = CurrentTemperature < TargetTemperature;
_logger.LogInformation(
"Thermostat: {Current:F1}°C / {Target:F1}°C → {State}",
CurrentTemperature, TargetTemperature,
HeatingActive ? "HEATING" : "idle");
}
protected override void Ready()
{
_logger.LogInformation("Thermostat ready. Target: {Target}°C", TargetTemperature);
}
}This logic block has:
TargetTemperature— a writable property that operators can adjust from the dashboard, rendered in the Configuration sectionCurrentTemperature— a measuring point (in production, read from a sensor via a service provider contract binding), rendered prominently in the Status sectionHeatingActive— both a property and a measuring point, surfaced as the primary tile value[Timer(2)]— polls every 2 seconds[Presentation(Group = ..., Importance = ...)]— separates UI hints from the schema, so[ServiceProperty]stays focused on the value itself (see Declarative Presentation)
Run dale dev and open the DevHost. You can change TargetTemperature and CurrentTemperature through the UI and watch HeatingActive respond in real-time.
Run Tests
The scaffolded project includes unit tests. Run them with:
dale testBuild, Package, and Upload
Build and package your library:
dale build
dale packTo upload to VION Cloud, authenticate and upload in one step:
dale login
dale uploadOnce uploaded, your logic block library is available for deployment to edge gateways through the VION Dashboard.
Next Steps
- Logic Blocks — lifecycle methods, thread safety, attributes
- Properties & Measuring Points — categories, display hints, computed properties
- Service Provider Contracts — connect to hardware I/O and Modbus devices
- Testing — unit testing with the Dale TestKit
- AI-Assisted Development — use Claude Code or other AI agents with the scaffolded AGENTS.md