Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
40384be
build: drop the container build mode argument
f2calv Oct 22, 2026
875df7e
docs(skills): remove attribution footer
f2calv Oct 22, 2026
68494ec
fix(api): align typed JSON and validation contracts
f2calv Oct 22, 2026
dfb76fd
fix(api): propagate cancellation and validate power commands
f2calv Oct 22, 2026
74a4a4a
refactor(knx): bind bus workers to shared leadership
f2calv Oct 22, 2026
508b377
refactor(ddns): bind updates to shared leadership
f2calv Oct 22, 2026
ec215c7
fix(webapi): validate device commands and preserve cancellation
f2calv Oct 22, 2026
b59330f
refactor(webapi): move camera webhook handling into the service
f2calv Oct 22, 2026
76bf3c7
fix(miele): standardize appliance API contracts
f2calv Oct 22, 2026
edb3d29
fix(webapi): align request examples and discover DDns controllers
f2calv Oct 23, 2026
9d0b2f8
fix(runtime): close ownership and resilience gaps
f2calv Oct 23, 2026
9a8c99c
test(clients): pass test cancellation to integration calls
f2calv Oct 23, 2026
ba78c11
fix(wiz): initialize Azure persistence before discovery
f2calv Oct 23, 2026
ece80b1
fix(deps): consume verified releases and remove vulnerable dependency…
f2calv Oct 24, 2026
5ea5c1f
docs(release): document supported Release builds and 1.1 migration
f2calv Oct 24, 2026
137a747
build(deps): update the collector to its stable multi-platform image
f2calv Oct 24, 2026
987a063
refactor(workers): simplify leadership worker operations
f2calv Oct 24, 2026
50c97b7
refactor(ddns): skip irrelevant records before address processing
f2calv Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/skills/sync-appsettings-to-configmap/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: sync-appsettings-to-configmap
description: 'Synchronize an appsettings JSON file into an existing ConfigMap in a caller-configured private GitOps repository. Use after local deployment configuration changes, before an application rollout, or when checking configuration drift. - Brought to you by f2calv/SmartHaus'
description: 'Synchronize an appsettings JSON file into an existing ConfigMap in a caller-configured private GitOps repository. Use after local deployment configuration changes, before an application rollout, or when checking configuration drift.'
argument-hint: '[mode={check|sync}]'
user-invocable: true
---
Expand Down Expand Up @@ -135,5 +135,3 @@ Run the synthetic Pester regression suite after changing the script:
| Target is already modified | Review the existing GitOps change before synchronizing again |
| Semantic verification fails | Restore the target from Git and inspect the `yq` version and source syntax |
| Argo CD does not reconcile | Commit and push through the normal GitOps workflow, then inspect the Application |

> Brought to you by f2calv/SmartHaus
5 changes: 1 addition & 4 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@
<PropertyGroup>
<!-- CS1574 - XML comment has cref attribute that could not be resolved -->
<!-- NETSDK1233 - Targeting .NET 10.0 or higher in Visual Studio 2022 XX.XX is not supported. -->
<!-- NU1901 - Package has a known low severity vulnerability. -->
<!-- NU1902 - Package has a known moderate severity vulnerability. -->
<!-- NU1903 - Package has a known high severity vulnerability. -->
<NoWarn>CS1574;NETSDK1233;NU1901;NU1902;NU1903</NoWarn>
<NoWarn>CS1574;NETSDK1233</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down
46 changes: 24 additions & 22 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,30 @@
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="10.2.1" />
<PackageVersion Include="AspNetCore.HealthChecks.Azure.Data.Tables" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.Azure.Storage.Blobs" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.UI" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.1.0" />
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.2" />
<PackageVersion Include="Azure.Identity" Version="1.21.0" />
<PackageVersion Include="Azure.ResourceManager.Dns" Version="1.1.1" />
<PackageVersion Include="CasCap.AgentRuntime.Contracts" Version="1.0.1" />
<PackageVersion Include="CasCap.Api.Azure.Auth" Version="1.7.0" />
<PackageVersion Include="CasCap.Api.Azure.CognitiveServices" Version="1.7.0" />
<PackageVersion Include="CasCap.Api.Azure.Storage" Version="1.7.0" />
<PackageVersion Include="CasCap.Comms.AI" Version="1.0.1" />
<PackageVersion Include="CasCap.Signalizr.Client" Version="1.0.1" />
<PackageVersion Include="CasCap.Signalizr.Client.Testing" Version="1.0.1" />
<PackageVersion Include="CasCap.Common.Abstractions" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Caching" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Configuration" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Extensions" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Extensions.Diagnostics.HealthChecks" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Hosting.AspNetCore" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Logging" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Net" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Serialization.Json" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Serialization.MessagePack" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Services" Version="4.16.0" />
<PackageVersion Include="CasCap.Common.Testing" Version="4.16.0" />
<PackageVersion Include="CasCap.AgentRuntime.Contracts" Version="1.2.0" />
<PackageVersion Include="CasCap.Api.Azure.Auth" Version="1.7.1" />
<PackageVersion Include="CasCap.Api.Azure.CognitiveServices" Version="1.7.1" />
<PackageVersion Include="CasCap.Api.Azure.Storage" Version="1.7.1" />
<PackageVersion Include="CasCap.Comms.AI" Version="1.0.2" />
<PackageVersion Include="CasCap.Signalizr.Client" Version="1.0.2" />
<PackageVersion Include="CasCap.Signalizr.Client.Testing" Version="1.0.2" />
<PackageVersion Include="CasCap.Common.Abstractions" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Caching" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Configuration" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Extensions" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Extensions.Diagnostics.HealthChecks" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Hosting.AspNetCore" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Logging" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Net" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Serialization.Json" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Serialization.MessagePack" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Services" Version="4.17.0" />
<PackageVersion Include="CasCap.Common.Testing" Version="4.17.0" />
<PackageVersion Include="ILGPU" Version="1.5.3" />
<PackageVersion Include="Iot.Device.Bindings" Version="4.2.0" />
<PackageVersion Include="LibreHardwareMonitorLib" Version="0.9.6" />
Expand All @@ -57,6 +55,8 @@
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.12.0" />
<!--<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />-->
<PackageVersion Include="ModelContextProtocol.AspNetCore" Version="2.3.0" />
<!-- PeterPuff.BuderusKm200Reader brings vulnerable Newtonsoft.Json 11.0.1. -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="OpenWiz" Version="1.1.0" />
<!--<PackageVersion Include="OpenAI" Version="2.8.0" />-->
<PackageVersion Include="OpenTelemetry" Version="1.20.1" />
Expand All @@ -67,7 +67,7 @@
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.20.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.20.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.20.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Process" Version="1.20.0-rc.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Process" Version="1.20.1-rc.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.20.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.StackExchangeRedis" Version="1.20.1-beta.1" />
<PackageVersion Include="PeterPuff.BuderusKm200Reader" Version="1.1.0" />
Expand All @@ -76,6 +76,8 @@
<PackageVersion Include="Spectre.Console.ImageSharp" Version="0.57.2" />
<PackageVersion Include="Spectre.Console.Json" Version="0.57.2" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.3.1" />
<!-- Falcon brings XML 7.0.0 and its vulnerable PKCS dependency. -->
<PackageVersion Include="System.Security.Cryptography.Xml" Version="10.0.13" />
<PackageVersion Include="Tiveria.Home.Knx" Version="2.0.81" />
<!--<PackageVersion Include="UnifiApi" Version="1.0.0.17" />-->
<PackageVersion Include="xunit.v3" Version="4.0.2" />
Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ The standalone device libraries can also be used without running SmartHaus.

With Docker and Compose installed:

Current source limitation: the backend's Agent Runtime contracts and communications integration
have Debug project references without corresponding Release package references. A clean Release
build, including the source-built demo below, may therefore fail before startup. The Debug
source-dependency path in [Development](#development) is the available alternative; this README
does not report an executed demo.
The source-built demo uses the Release graph, resolving shared libraries, Agent Runtime contracts
and communications packages from NuGet. Debug source builds instead use the adjacent checkouts
listed in [Development](#development). This README does not report an executed demo.

```bash
git clone https://github.com/f2calv/SmartHaus.git
Expand Down Expand Up @@ -71,6 +69,15 @@ its own device, cloud authentication and configuration requirements.
| Helm charts | [Application](charts/smarthaus/README.md), [Grafana dashboards](charts/smarthaus-dashboards/README.md) | Configurable workload aliases and dashboard provisioning | `oci://ghcr.io/f2calv/charts/smarthaus` |
| Tests | [Buderus](src/CasCap.Api.Buderus.Tests/README.md), [DoorBird](src/CasCap.Api.DoorBird.Tests/README.md), [Fronius](src/CasCap.Api.Fronius.Tests/README.md), [KNX](src/CasCap.Api.Knx.Tests/README.md), [Miele](src/CasCap.Api.Miele.Tests/README.md), [host](src/CasCap.App.Server.Tests/README.md), [backend](src/CasCap.Backend.Tests/README.md) | Source-declared inventories and prerequisites | Not published |

## Compatibility

The 1.1 release intentionally includes incompatible contracts despite its minor version.
Rebuild package consumers and migrate the
[Buderus query-service write result](src/CasCap.Api.Buderus/README.md#migrating-to-11).
HTTP callers must also check the current typed device responses, string-enum JSON and
[validated Miele command bodies](src/CasCap.Api.Miele/README.md#commands-and-failures);
unrecognized Miele fields are rejected rather than forwarded.

## Use a Standalone Library

For a host application with configuration and logging, install a device client:
Expand Down
2 changes: 1 addition & 1 deletion build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ $scripts = @(
)
$implementation = $scripts | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1
if (-not $implementation) { throw "Invoke-Build.ps1 was not found. Checked: $($scripts -join ', ')" }
& $implementation -RepositoryRoot $PSScriptRoot -BuildMode Application @args
& $implementation -RepositoryRoot $PSScriptRoot @args
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ services:
redis:
condition: service_healthy
otelcol:
image: otel/opentelemetry-collector:0.162.0
image: otel/opentelemetry-collector:0.163.1
ports:
- 4317:4317
- 4318:4318
Expand Down
18 changes: 16 additions & 2 deletions requests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,19 @@ request files.
| `knx-controller.http` | KNX bus, HVAC, lighting, outlet, and shutter endpoints |
| `ubiquiti-demo.http` | Local Docker Compose demo webhook requests |

Some requests change device or application state. Review the method, URL, and payload before sending
them.
## Execution Safety

Review each request's `# @note`, URL, credentials and payload before sending it. A `GET` is not
necessarily read-only: DoorBird device commands can unlock doors or reboot hardware, while
DoorBird and Ubiquiti event callbacks publish events. Depending on enabled sinks, callbacks can
capture media, invoke analysis and send notifications. Demo events also enter the configured
pipeline; synthetic identifiers do not make them a dry run.

KNX names are synthetic examples using the current category and room names. Choose existing
group/address names from the read endpoints before sending a command. Examples with `dryRun=true`
resolve proposed changes without queuing or sending KNX commands; the other command examples can
operate physical devices. Body fields and validation apply to dry runs too.

Controller endpoints are available only when their feature is enabled. In particular, enabling
`DDns` exposes its read-only IP query but also enables the DNS update worker; do not enable it merely
to try the request without first configuring the feature's write permissions and target zone.
4 changes: 2 additions & 2 deletions requests/buderus-controller.http
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ GET {{baseUrl}}/api/v1/buderus/dhwCircuits
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Set a datapoint value
# @note
# @note Writes a heating setpoint directly to the configured heat pump.
PUT {{baseUrl}}/api/v1/buderus/heatingCircuits/hc1/temperatureRoomSetpoint
Authorization: Basic {{$dotenv HAUS_API_AUTH}}
Content-Type: application/json

{
"value": 21.0
"value": "21.0"
}
4 changes: 4 additions & 0 deletions requests/doorbird-client.http
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ GET {{baseUrl}}/bha-api/video.cgi
Authorization: Basic {{auth}}

### Unlock door (relay 1)
# @note Activates the device's default door relay and can unlock a physical door.
GET {{baseUrl}}/bha-api/open-door.cgi
Authorization: Basic {{auth}}

### Unlock door (specific relay)
# @note Activates relay 2 and can unlock a physical door.
GET {{baseUrl}}/bha-api/open-door.cgi?r=2
Authorization: Basic {{auth}}

### Turn on IR light
# @note Activates the physical device's infrared light.
GET {{baseUrl}}/bha-api/light-on.cgi
Authorization: Basic {{auth}}

Expand All @@ -38,5 +41,6 @@ GET {{baseUrl}}/bha-api/sip.cgi
Authorization: Basic {{auth}}

### Restart device
# @note Reboots the physical intercom and temporarily interrupts its services.
GET {{baseUrl}}/bha-api/restart.cgi
Authorization: Basic {{auth}}
13 changes: 8 additions & 5 deletions requests/doorbird-controller.http
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ GET {{baseUrl}}/api/v1/doorbird/video
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Unlock front door relay
# @note
# @note Activates the configured door relay and publishes an event; configured sinks may send notifications.
POST {{baseUrl}}/api/v1/doorbird/relay
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Turn light on
# @note
# @note Activates the physical intercom's infrared light.
POST {{baseUrl}}/api/v1/doorbird/light
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

Expand All @@ -30,7 +30,7 @@ GET {{baseUrl}}/api/v1/doorbird/info
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Restart device
# @note
# @note Reboots the physical intercom and temporarily interrupts its services.
POST {{baseUrl}}/api/v1/doorbird/restart
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

Expand Down Expand Up @@ -59,20 +59,23 @@ GET {{baseUrl}}/api/v1/doorbird/notifications
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Subscribe to notification
# @note
# @note Registers a device notification callback; replace the synthetic URL with an approved receiver.
POST {{baseUrl}}/api/v1/doorbird/notifications/subscribe?subscriberUrl=http://example.com/callback&eventType=doorbell
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Unsubscribe from notification
# @note
# @note Removes a device notification callback subscription.
POST {{baseUrl}}/api/v1/doorbird/notifications/unsubscribe?subscriberUrl=http://example.com/callback&eventType=doorbell
Authorization: Basic {{$dotenv HAUS_API_AUTH}}

### Event callback - doorbell ring (no auth required)
# @note Captures an image and publishes an event; configured sinks may capture clips, invoke analysis and send notifications.
GET {{baseUrl}}/api/v1/doorbird/event/ring

### Event callback - motion detected (no auth required)
# @note Captures an image and publishes an event; configured sinks may capture clips, invoke analysis and send notifications.
GET {{baseUrl}}/api/v1/doorbird/event/motion

### Event callback - RFID (no auth required)
# @note Captures an image and publishes an event; configured sinks may capture clips, invoke analysis and send notifications.
GET {{baseUrl}}/api/v1/doorbird/event/rfid
Loading