Fable suggestion #1394
helto4real
started this conversation in
General
Replies: 1 comment
-
|
this is the spec it wrote :) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I asked Fable for ideas how to improve. This was just a fun query and this dores NOT mean that ND will move in this direction. I put it out here to have access to it.
—————-
NetDaemon vNext — Design Proposal
A ground-up redesign of NetDaemon: modern async-first C#, AI-agent friendly, AOT-capable, with a V5 compatibility shim. Not backwards compatible at the core, but feature complete and with a legacy API layer so existing apps recompile.
1. Design goals
Task/ValueTask/IAsyncEnumerableas the primary model; Rx becomes an optional adapter, not the foundation.nd-codegentool; no runtime reflection; Native AOT publishable.2. New user-facing APIs
Three tiers, all built on the same core. Users pick one; they compose cleanly.
2.1 Tier 1 — Declarative fluent automations (the "minimal API" of home automation)
Inspired by ASP.NET Core minimal APIs. Ideal for 80% of automations and the easiest form for AI agents to generate correctly, because lifecycle, disposal, and threading are invisible.
Key properties:
AutomationModemirrors Home Assistant's semantics (single, restart, queued, parallel) — a concept V5 users constantly reimplement by hand withSwitch()/Throttle().ctxcarries aCancellationToken, structured trace, and helpers (Delay,WaitFor(trigger, timeout)).Trigger.Any(a, b),Trigger.All(...),e.Sensor.Temp.DropsBelow(18),Trigger.Cron("0 22 * * *"),Trigger.AtSunset(offset: ...),Trigger.OnEvent("zha_event", data => ...).2.2 Tier 2 — Class-based apps with attribute triggers
For larger apps with state and DI. Handlers are plain async methods; the runtime wires triggers via source-generated code (no reflection).
partiallets the generator emit the registration code.ND0101: entity 'binary_sensor.hallway_motio' not found; did you mean 'hallway_motion'?).[Persist] public int TriggerCount { get; set; }— snapshotted to disk/HA storage across restarts.2.3 Tier 3 — Streams for power users
IAsyncEnumerable-based streams replace Rx as the low-level primitive:Standard LINQ-for-async (
System.Linq.Async) coversWhere/Select/Throttle/Debounceneeds. AnNetDaemon.Reactiveadapter package exposes the same streams asIObservable<T>for those who prefer Rx — but Rx is no longer a core dependency.2.4 Entities and services — source-generated, typed end to end
Entities,Services, typed attribute records, and typed service parameters are generated by a Roslyn source generator from.netdaemon/ha-schema.json(see §5). No external codegen tool, no generated files checked in, always in sync with the schema file.LightEntity.StateisLightState { OnOff IsOn, byte? BrightnessPct, ... }instead of string + attribute dictionary spelunking. Raw access remains available (entity.RawState,entity.Attributes["foo"]).var forecast = await e.Weather.Home.GetForecastsAsync(...).home.Areas["Kitchen"].Lights.TurnOnAsync(), labels, devices, floors — target sets (ServiceTarget) become typed collections you can query with LINQ.3. Architecture redesign for maintainability
Strict layering, each layer its own package with interface seams:
Principles:
Microsoft.Extensions.*idioms: DI,IOptions<T>,ILogger,IHostedService, and .NET 8+TimeProvidereverywhere — no custom scheduler abstraction to maintain, and tests getFakeTimeProviderfor free.INetDaemonExtensionregisters services, triggers, and CLI/MCP surface. MQTT entity management, Zigbee event helpers, notification engines, etc. are extensions — the core never grows integration-specific code.ctpropagation, unknown entity ids, service parameter typos. Compile output becomes the feedback loop (crucial for §5).4. Performant networking & backend
ClientWebSocketfed intoSystem.IO.Pipelines; parse withUtf8JsonReaderstraight off the pipe (no intermediate strings/DOM). Serialization via source-generatedSystem.Text.Jsoncontexts.subscribe_entitiesdiff protocol instead of rawstate_changedevents where possible — HA sends compressed state diffs, dramatically reducing payload size and allocations on busy installations. Fall back to classic event subscription for full fidelity (contexts, event data) where needed.Channel<T>per app. Backpressure policy is configurable per app (drop-oldest / wait / fault). A slow or stuck app fills its own channel only; the global loop and other apps are unaffected. This replaces V5's shared Rx pipeline where one bad subscriber can stall or exception-poison others.FrozenDictionaryrebuilt on registry changes, copy-on-write for state updates. Reads are lock-free; an automation always sees a consistent snapshot of the world at trigger time (passed inctx.Snapshot).Microsoft.Extensions.Resilience(Polly v8) pipelines for reconnect with jittered backoff; sequence-number gap detection triggers a state resync; triggers get aConnectionRestoredsignal so apps can re-evaluate.5. AI-agent friendliness (first-class, not bolted on)
The theme: make the whole system legible offline and verifiable in a tight loop.
.netdaemon/ha-schema.json: entities, attributes, services with parameter schemas, areas, devices, labels. Pulled withnd schema pull. This single file gives an agent complete knowledge of the home without a live connection, powers the source generator, and makes builds deterministic.await: all becomeND####diagnostics with fix-it suggestions. An agent's edit→build→read-errors loop converges fast because errors are specific and actionable.nd) —nd new app,nd schema pull,nd validate,nd test,nd simulate --scenario scenarios/evening.yaml(drives the in-memory fake with scripted state changes and asserts outcomes),nd trace <automation-id>.NetDaemon.Mcp) — exposes tools:list_entities,get_state,search_schema,validate_project,run_simulation,get_automation_trace,tail_logs. An agent in Claude Code/Codex can inspect the home, write an automation, simulate it, and read the trace without a human in the loop.AGENTS.md+ skills — conventions (one automation per file, naming, where schema lives, how to runnd validate) documented in the format agents actually consume, plus aSKILL.mdfor thendworkflow.6. Legacy compatibility layer (
NetDaemon.Compat.V5)Goal: existing V5 apps recompile without source changes against the new core.
IHaContext,Entity/NumericEntity,StateChange,IHaRegistry,INetDaemonScheduler, AppModel attributes ([NetDaemonApp],[Focus]), and yaml/JSON config injection — all as facades overNetDaemon.Model/Runtime.Entity.StateChanges()returnsIObservable<StateChange>bridged from the per-app channel via the Rx adapter; scheduler maps ontoTimeProvider-based scheduling.Entities,Services,LightEntities…) is reproduced by a compat mode of the new source generator, so generated-code-dependent apps also work.UseSharedDispatchOrdering = truepreserves V5 ordering for apps that depend on it.nd migrateruns Roslyn codemods for mechanical rewrites (RxSubscribe→ attribute trigger orawait foreach,Throttle→WithThrottle, scheduler calls →[Trigger.Cron]), and flags what needs a human. Compat layer is a permanent supported package, not a temporary bridge — but new features land only in the new API.7. Feature-completeness checklist vs V5
StateChanges()/StateAllChanges()IAsyncEnumerablestreams + Rx adapter + compat shimEntities/ServicesCallService/ service response dataCallServiceAsyncescape hatchTrigger.Cron,Trigger.At,TimeProvider-basedISchedulerhome.Sun+ sunset/sunrise triggers with offsetsHassEvent)Trigger.HassEvent+ typed event payload bindingIOptions<T>binding (yaml/json/env), source-generated bindingNetDaemon.Extensions.Mqtton the extension modelNetDaemon.Extensions.TtsNetDaemon.Testingwith HA fake +FakeTimeProvider8. Suggested phasing
subscribe_entities, channels, snapshot cache; prove perf targets.NetDaemon.Testing.nd migrate; run the existing integration-test app suite through the shim as the acceptance gate.Beta Was this translation helpful? Give feedback.
All reactions