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 Dale.CliVerify the installation:
dale --versionEarly Access
The Dale CLI is currently distributed via a private NuGet feed. Contact VION for access. Public NuGet distribution is planned.
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 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 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 logicblock ThermostatOpen SmartThermostat/Thermostat.cs and replace the generated code:
using Dale.Sdk.Core;
using Microsoft.Extensions.Logging;
public class Thermostat : LogicBlockBase
{
private readonly ILogger _logger;
[ServiceProperty("Target Temperature", "°C")]
public double TargetTemperature { get; set; } = 21.0;
[ServiceProperty("Heating Active")]
[ServiceMeasuringPoint("Heating Active")]
public bool HeatingActive { get; private set; }
[ServiceMeasuringPoint("Current Temperature", "°C")]
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 DashboardCurrentTemperature— a measuring point (in production, read from a sensor via a service provider contract)HeatingActive— both a property and a measuring point, computed from the other two[Timer(2)]— polls every 2 seconds
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