Get rid of deps

This commit is contained in:
2026-07-06 23:21:42 +02:00
parent a426b62d4a
commit b176c7705d
21 changed files with 262 additions and 528 deletions
+4 -5
View File
@@ -1,8 +1,7 @@
/log/
/intermediate/
/node_modules/
/output/
/environment.json
/output
/result
/result-
/src/www/documentation.html
.direnv
.devenv
-2
View File
@@ -1,2 +0,0 @@
@annex4:registry=https://npm.pkg.github.com
@c3c:registry=https://git.c3c.cz/api/packages/c3c/npm/
+51
View File
@@ -0,0 +1,51 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
Control4 DriverWorks KNX driver for presence-based automation (lights/media) in the C3C house. Produces a `.c4z` package containing a Lua driver.
This project is part of a larger AI skill (`control4-driverworks`). Read the skill's SKILL.md and references/KNX.md for full Control4/DriverWorks/KNX API documentation.
## Build
Nix flake-based. Requires `direnv` or manual `nix develop`.
```bash
# Dev shell (provides luajit, zip, xmllint)
nix develop
# Build .c4z package
nix build
# Build and copy to ../compiled/ for Composer Pro
nix run
```
No test suite or linter configured.
## Architecture
```
src/
driver.xml # C4 device manifest (proxies, connections, events, properties)
driver.lua # Lua driver: lifecycle hooks, initialization logic
control4-utils/ # Driver library (logging, KNX wrappers, hooks), shared between drivers DO NOT MODIFY WITHOUT PRIOR CONSENT
lib/ # Custom driver logic (presence handling per room, daytime state)
www/
icons/ # Composer list icons (logo_16.png / logo_32.png)
documentation.html # Built output (generated by nix build from README.md via lowdown, DO NOT edit)
README.md # Built into src/www/documentation.html using lowdown
```
### Key conventions
- **Version injection**: `DRIVER_VERSION` in `driver.lua` is replaced by nix build with git rev. Bump `<version>` integer in `driver.xml` on every change.
- **Proxy binding ID**: `5000` used consistently across `driver.xml` (proxy) — this is a live, deployed binding id, do not change it.
- **Driver slug**: must match c4z filename (`c3c-knx-presence`). Defined as `driverName` in `flake.nix`, `DRIVER_NAME` in Lua, `<proxy>`/`<model>` in XML.
- **KNX group addresses**: accessed exclusively through `C3C.KnxAddresses.Get`/`.Watch` from `control4-utils/knx`. Never talk to the KNX proxy directly.
## Bump version
**ALWAYS increment `<version>` in `src/driver.xml` in the same response where you edit ANY source files.** Do not defer to commit time. Multiple bumps per session is fine. Nix does not auto-increment.
-1
View File
@@ -1 +0,0 @@
[]
-1
View File
@@ -1 +0,0 @@
[]
-16
View File
@@ -1,16 +0,0 @@
[
{
"id": 1,
"connectionname": "KNX Control",
"type": 1,
"consumer": true,
"classes": [
{
"classname": "KNX_DEVICE",
"autobind": false
}
],
"linelevel": true,
"facing": 6
}
]
-12
View File
@@ -1,12 +0,0 @@
[
{
"id": 100,
"description": "Start Media in Upper Floor Bathroom",
"name": "UpperFloorBathroomMediaStart"
},
{
"id": 101,
"description": "End Media in Upper Floor Bathroom",
"name": "UpperFloorBathroomMediaEnd"
}
]
-1
View File
@@ -1 +0,0 @@
[]
-12
View File
@@ -1,12 +0,0 @@
[
{
"name": "Log Level",
"type": "DYNAMIC_LIST",
"readonly": false
},
{
"name": "Log Mode",
"type": "DYNAMIC_LIST",
"readonly": false
}
]
-7
View File
@@ -1,7 +0,0 @@
[
{
"id": 5000,
"proxy": "c3c-knx-presence",
"name": "KNX Presence"
}
]
-1
View File
@@ -1 +0,0 @@
[]
Generated
+29 -244
View File
@@ -1,229 +1,30 @@
{
"nodes": {
"cachix": {
"flake-utils": {
"inputs": {
"devenv": [
"nix",
"devenv"
],
"flake-compat": [
"nix",
"devenv"
],
"git-hooks": [
"nix",
"devenv"
],
"nixpkgs": "nixpkgs"
"systems": "systems"
},
"locked": {
"lastModified": 1742042642,
"narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
"owner": "cachix",
"repo": "cachix",
"rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "latest",
"repo": "cachix",
"type": "github"
}
},
"devenv": {
"inputs": {
"cachix": "cachix",
"flake-compat": "flake-compat",
"git-hooks": "git-hooks",
"nix": "nix_2",
"nixpkgs": [
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1744876578,
"narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
"owner": "cachix",
"repo": "devenv",
"rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nix",
"devenv",
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1712014858,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": [
"nix",
"devenv"
],
"gitignore": "gitignore",
"nixpkgs": [
"nix",
"devenv",
"nixpkgs"
]
},
"locked": {
"lastModified": 1742649964,
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"nix",
"devenv",
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"libgit2": {
"flake": false,
"locked": {
"lastModified": 1697646580,
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
"owner": "libgit2",
"repo": "libgit2",
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
"type": "github"
},
"original": {
"owner": "libgit2",
"repo": "libgit2",
"type": "github"
}
},
"nix": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1744882253,
"narHash": "sha256-SHedYfKXqJ0BuB0XDaIbWS0umcqj9ScYTrrWYN8HmMo=",
"ref": "refs/heads/main",
"rev": "49a4dc963156c87f2c13d0ef3db0d8d244bdaa2d",
"revCount": 14,
"type": "git",
"url": "ssh://git@git.c3c.cz/C3C/nix"
},
"original": {
"type": "git",
"url": "ssh://git@git.c3c.cz/C3C/nix"
}
},
"nix_2": {
"inputs": {
"flake-compat": [
"nix",
"devenv"
],
"flake-parts": "flake-parts",
"libgit2": "libgit2",
"nixpkgs": "nixpkgs_2",
"nixpkgs-23-11": [
"nix",
"devenv"
],
"nixpkgs-regression": [
"nix",
"devenv"
],
"pre-commit-hooks": [
"nix",
"devenv"
]
},
"locked": {
"lastModified": 1741798497,
"narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
"owner": "domenkozar",
"repo": "nix",
"rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.24",
"repo": "nix",
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1733212471,
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
"lastModified": 1782959384,
"narHash": "sha256-xnJJk+ct+D2+wdRxj1wk36w5zV9RVESwRqcklPdt3fM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
"rev": "65179426c83bb3f6bc14898b42ea1c6f01d374b0",
"type": "github"
},
"original": {
@@ -233,41 +34,25 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1717432640,
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1744536153,
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nix": "nix"
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
+82 -74
View File
@@ -1,84 +1,92 @@
{
description = "c3c-knx-presence development environment";
inputs = {
nix.url = "git+ssh://git@git.c3c.cz/C3C/nix";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{ self, nix }:
{
formatter = nix.formatter;
self,
nixpkgs,
flake-utils,
}:
let
version = "0.0.1";
gitRev = self.shortRev or self.dirtyShortRev;
driverName = "c3c-knx-presence";
in
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
formatter = pkgs.nixfmt-rfc-style;
packages = nix.lib.forAllSystems (pkgs: {
devenv-up = self.devShells.${pkgs.system}.default.config.procfileScript;
devenv-test = self.devShells.${pkgs.system}.default.config.test;
});
devShells = nix.lib.forAllSystems (pkgs: {
default = nix.lib.mkDevenvShell {
inherit pkgs;
inputs = {
self = self;
nixpkgs = pkgs;
};
modules = [
{
packages = [
nix.lib.control4-env.${pkgs.system}
];
scripts = {
menu = {
description = "Print this menu";
exec = ''
echo "Commands:"
echo -n '${
builtins.toJSON (
builtins.mapAttrs (s: value: value.description) self.devShells.${pkgs.system}.default.config.scripts
)
}' | \
${pkgs.jq}/bin/jq -r 'to_entries | map(" \(.key)\n" + " - \(if .value == "" then "no description provided" else .value end)") | "" + .[]'
'';
};
generate = {
exec = ''
${nix.lib.cd_root}
rm -rf ./src/control4-utils
cp -rp node_modules/@c3c/control4-utils/src ./src/control4-utils
node_modules/@c3c/control4-utils/bin/driver-manager ./package.json
mdtohtml -page README.md > src/www/documentation.html
'';
};
github-push = {
description = "Push current branch and all tags to github, lazy workaround for automated mirror. TODO: Automate";
exec = ''
b=$(git rev-parse --abbrev-ref HEAD)
git push git@github.com:Sharsie/control4-knx-presence.git "$b":"$b"
git push git@github.com:Sharsie/control4-knx-presence.git --tags
'';
};
lint = {
exec = ''
${nix.lib.cd_root}
'';
};
fix = {
exec = ''
${nix.lib.cd_root}
nix fmt ./*.nix
stylua ./src
'';
};
};
}
devShells.default = pkgs.mkShell {
packages = with pkgs; [
luajit
zip
unzip
libxml2
];
shellHook = ''
echo "${driverName} dev shell"
echo " build build .c4z into working dir"
'';
};
});
};
apps.default = {
type = "app";
program = "${pkgs.writeShellScript "build-c4z" ''
set -euo pipefail
nix build
# Move the file into a predefined directory mounted in the Composer Pro environment
rm -f ../compiled/${driverName}.c4z
cp -L result/${driverName}.c4z ../compiled
echo "Built ${gitRev}: ../compiled/${driverName}.c4z"
''}";
};
packages.default = pkgs.stdenv.mkDerivation {
pname = driverName;
inherit version;
src = ./.;
nativeBuildInputs = [
pkgs.libxml2
pkgs.luajit
pkgs.zip
];
buildPhase = ''
# Prepare build dir
cp -r src build-src
${pkgs.lowdown}/bin/lowdown -s README.md > build-src/www/documentation.html
# Validate Lua syntax (compile-check only; driver.lua calls into the
# real Control4 "C4" global at load time, so it cannot be executed here)
cd build-src
luajit -e "assert(loadfile('driver.lua'))"
cd -
# Validate driver manifest
xmllint --noout build-src/driver.xml
# Stamp git rev into driver.lua
( ${pkgs.gnused}/bin/sed -i 's/DRIVER_VERSION = "uninitialized"/DRIVER_VERSION = "${gitRev}"/' build-src/driver.lua)
'';
installPhase = ''
mkdir -p $out
cd build-src
zip -rq $out/${driverName}.c4z .
'';
};
}
);
}
-64
View File
@@ -1,64 +0,0 @@
{
"name": "c3c-knx-presence",
"version": "0.0.232",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "c3c-knx-presence",
"version": "0.0.232",
"hasInstallScript": true,
"license": "GPL-3.0-only",
"devDependencies": {
"@c3c/control4-utils": "^0.5.2",
"@prettier/plugin-lua": "0.0.2",
"prettier": "^3"
}
},
"node_modules/@c3c/control4-utils": {
"version": "0.5.2",
"resolved": "https://git.c3c.cz/api/packages/C3C/npm/%40c3c%2Fcontrol4-utils/-/0.5.2/control4-utils-0.5.2.tgz",
"integrity": "sha512-aKbyjB7SG8mZxYhuBnqngWA1RaFL+3TsH+CDtkOzb4VGZ9VfLk/3a4uvREuClSJMqC6EdrG1t9gz5DTwL2h1Uw==",
"dev": true,
"license": "GPL-3.0-only"
},
"node_modules/@prettier/plugin-lua": {
"version": "0.0.2",
"dev": true,
"license": "MIT",
"dependencies": {
"luaparse": "0.2.1"
},
"engines": {
"node": ">=10.13.0"
},
"peerDependencies": {
"prettier": ">=2.0.0"
}
},
"node_modules/luaparse": {
"version": "0.2.1",
"dev": true,
"license": "MIT",
"bin": {
"luaparse": "bin/luaparse"
}
},
"node_modules/prettier": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
}
}
}
-39
View File
@@ -1,39 +0,0 @@
{
"author": "C3C",
"control4": {
"capabilities": {},
"control": "lua_gen",
"controlmethod": "KNX",
"created": "5/14/2023, 10:16:49 PM",
"icon": {
"image_source": "c4z",
"large": "icons/logo_32.png",
"small": "icons/logo_16.png"
},
"manufacturer": "C3C",
"model": "Presence",
"name": "KNX Presence"
},
"description": "",
"devDependencies": {
"@c3c/control4-utils": "^0.5.2",
"@prettier/plugin-lua": "0.0.2",
"prettier": "^3"
},
"homepage": "https://git.c3c.cz/C3C/control4-knx-presence",
"keywords": [],
"license": "GPL-3.0-only",
"main": "src/driver.lua",
"name": "c3c-knx-presence",
"repository": {
"type": "git",
"url": "https://git.c3c.cz/C3C/control4-knx-presence.git"
},
"scripts": {
"driver-manager": "node_modules/@c3c/control4-utils/bin/driver-manager ./package.json",
"install-control4-utils": "rm -rf ./src/control4-utils && cp -rp node_modules/@c3c/control4-utils/src ./src/control4-utils",
"postinstall": "npm run install-control4-utils && npm run driver-manager",
"test": "busted tests/test.lua"
},
"version": "0.0.232"
}
+18 -1
View File
@@ -23,6 +23,20 @@ do
}
local responding = false
local throttlingRead = false
function class:Read()
if throttlingRead == false then
C3C.KnxProxy.Read(class.GA)
end
throttlingRead = true
C3C.OneShotTimer.Add(10000, function()
throttlingRead = false
C3C.KnxProxy.Read(class.GA)
end, "GroupAddressReadThrottle" .. class.GA)
end
---@param v number
function class:Send(v)
@@ -31,6 +45,7 @@ do
end
function class:RespondToRead()
C3C.KnxAddresses.Watch(class.Name)
responding = true
end
@@ -99,7 +114,7 @@ do
---@param onValueChange nil|fun(current: GroupAddress, state: { newVal: number, prevVal: number? })
Watch = function(n, onValueReceive, onValueChange)
if namedRegistry[n] == nil then
C3C.Logger.Error(W
C3C.Logger.Error(
"error accessing non existing group address name to Listen, this should never happen...never",
{ name = n }
)
@@ -180,6 +195,8 @@ do
if addr ~= nil and addr.Value ~= nil and addr:isResponding() then
addr:Send(addr.Value)
end
return
end
if strCommand ~= "DATA_FROM_KNX" then
+6 -9
View File
@@ -12,6 +12,7 @@
---|"Control LF Hallway Presence"
---|"Control LF Hallway Presence Enable"
---|"Control LF Hallway Presence Enable Workaround"
---|"Control LF Hallway Presence End"
---|"Control LF Hallway Presence Alarm"
---|"Control LF Hallway Presence Alarm State"
---|"Control LF Study LED Brightness Night"
@@ -408,7 +409,7 @@
---|"Heat Temperature Setpoint"
--- HAS UNKNOWN DPT
---|"Heat Temperature Setpoint State"
---|"Heat Heating Off lock"
---|"Heat Heating Off Lock"
---|"Heat UF+LF Heating Circulation Pump"
---|"Heat UF+LF Heating Circulation Pump State"
@@ -581,6 +582,8 @@
--- Study Primary
---|"Switch LF Study Primary Light 2"
--- Study Primary
---|"Switch LF Study Primary Light Table"
--- Study Primary
---|"Switch LF Study Primary FB"
--- Study Primary
---|"Switch LF Study Primary CTRL FB"
@@ -588,6 +591,8 @@
---|"Switch LF Study Primary Light 1 FB"
--- Study Primary
---|"Switch LF Study Primary Light 2 FB"
--- Study Primary
---|"Switch LF Study Primary Light Table State"
--- Study Ambient
---|"Switch LF Study Ambient"
--- Study Ambient
@@ -651,17 +656,9 @@
---|"Switch UF Hallway Entry"
---|"Switch UF Hallway Isle"
---|"Switch UF Hallway CTRL"
---|"Switch UF Hallway Entry 1"
---|"Switch UF Hallway Entry 2"
---|"Switch UF Hallway Isle 1"
---|"Switch UF Hallway Isle 2"
---|"Switch UF Hallway Entry FB"
---|"Switch UF Hallway Isle FB"
---|"Switch UF Hallway CTRL FB"
---|"Switch UF Hallway Entry 1 FB"
---|"Switch UF Hallway Entry 2 FB"
---|"Switch UF Hallway Isle 1 FB"
---|"Switch UF Hallway Isle 2 FB"
---|"Switch UF Bathroom Primary"
---|"Switch UF Bathroom Primary CTRL"
---|"Switch UF Bathroom Primary Light 1"
@@ -1,7 +1,6 @@
---@return table<number,GroupAddress>
function C3CKnxCreateGroupAddresses()
return {
return {
C3C.KnxGroupAddress("Entry", "0/0/1", "DPT_1"),
C3C.KnxGroupAddress("Exit", "0/0/2", "DPT_1"),
C3C.KnxGroupAddress("Present", "0/0/3", "DPT_1"),
@@ -95,10 +94,12 @@ function C3CKnxCreateGroupAddresses()
C3C.KnxGroupAddress("Switch LF Study Primary CTRL", "1/0/141", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light 1", "1/0/142", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light 2", "1/0/143", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light Table", "1/0/144", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary FB", "1/0/147", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary CTRL FB", "1/0/148", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light 1 FB", "1/0/149", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light 2 FB", "1/0/150", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Primary Light Table State", "1/0/151", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Ambient", "1/0/155", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Ambient CTRL", "1/0/156", "DPT_1"),
C3C.KnxGroupAddress("Switch LF Study Ambient Light 1", "1/0/157", "DPT_1"),
@@ -136,17 +137,9 @@ function C3CKnxCreateGroupAddresses()
C3C.KnxGroupAddress("Switch UF Hallway Entry", "1/1/0", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle", "1/1/1", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway CTRL", "1/1/2", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Entry 1", "1/1/3", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Entry 2", "1/1/4", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle 1", "1/1/5", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle 2", "1/1/6", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Entry FB", "1/1/7", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle FB", "1/1/8", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway CTRL FB", "1/1/9", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Entry 1 FB", "1/1/10", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Entry 2 FB", "1/1/11", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle 1 FB", "1/1/12", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Hallway Isle 2 FB", "1/1/13", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Bathroom Primary", "1/1/20", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Bathroom Primary CTRL", "1/1/21", "DPT_1"),
C3C.KnxGroupAddress("Switch UF Bathroom Primary Light 1", "1/1/22", "DPT_1"),
@@ -503,7 +496,7 @@ function C3CKnxCreateGroupAddresses()
C3C.KnxGroupAddress("Heat Heating-Cooling State", "3/7/1", "DPT_1"),
C3C.KnxGroupAddress("Heat Temperature Setpoint", "3/7/2", "DPT_1"),
C3C.KnxGroupAddress("Heat Temperature Setpoint State", "3/7/3", "DPT_1"),
C3C.KnxGroupAddress("Heat Heating Off lock", "3/7/4", "DPT_1"),
C3C.KnxGroupAddress("Heat Heating Off Lock", "3/7/4", "DPT_1"),
C3C.KnxGroupAddress("Heat UF+LF Heating Circulation Pump", "3/7/20", "DPT_1"),
C3C.KnxGroupAddress("Heat UF+LF Heating Circulation Pump State", "3/7/21", "DPT_1"),
C3C.KnxGroupAddress("Vent LF PLACEHOLDER Hallway", "4/0/0", "DPT_1"),
@@ -616,6 +609,7 @@ function C3CKnxCreateGroupAddresses()
C3C.KnxGroupAddress("Control LF Hallway Presence", "6/0/0", "DPT_1"),
C3C.KnxGroupAddress("Control LF Hallway Presence Enable", "6/0/1", "DPT_1"),
C3C.KnxGroupAddress("Control LF Hallway Presence Enable Workaround", "6/0/2", "DPT_3"),
C3C.KnxGroupAddress("Control LF Hallway Presence End", "6/0/5", "DPT_1"),
C3C.KnxGroupAddress("Control LF Hallway Presence Alarm", "6/0/10", "DPT_1"),
C3C.KnxGroupAddress("Control LF Hallway Presence Alarm State", "6/0/11", "DPT_1"),
C3C.KnxGroupAddress("Control LF Study LED Brightness Night", "6/0/146", "DPT_5"),
@@ -625,4 +619,3 @@ function C3CKnxCreateGroupAddresses()
C3C.KnxGroupAddress("Control UF Bathroom Brightness", "6/1/35", "DPT_9"),
}
end
+4 -3
View File
@@ -1,4 +1,5 @@
local VERSION = "2025.10.0"
DRIVER_NAME = "c3c-knx-presence"
DRIVER_VERSION = "uninitialized"
local ID_KNX = 1
@@ -7,7 +8,7 @@ require("control4-utils.hooks")
require("control4-utils.helpers")
require("control4-utils.knx")
C3C.KnxProxy.Setup(ID_KNX)
C3C.RemoteLogger.Setup("c4c-knx-presence")
C3C.RemoteLogger.Setup(DRIVER_NAME)
C3C.Logger.DisableRemoteLogging()
-- C4:AllowExecute(false)
C3C.Lib = {}
@@ -33,7 +34,7 @@ Driver = (function()
end
function class:SetInitialized()
C3C.RemoteLogger.Info("C3C KNX Presence driver initialized", { version = VERSION })
C3C.RemoteLogger.Info("C3C KNX Presence driver initialized", { version = DRIVER_VERSION })
class.initialized = true
end
+63
View File
@@ -0,0 +1,63 @@
<devicedata>
<copyright>Copyright 2026 C3C</copyright>
<creator>C3C</creator>
<manufacturer>C3C</manufacturer>
<name>KNX Presence</name>
<model>c3c-knx-presence</model>
<created>2023-05-14</created>
<modified>2026-07-04</modified>
<version>233</version>
<agent>false</agent>
<control>lua_gen</control>
<controlmethod>KNX</controlmethod>
<driver>DriverWorks</driver>
<minimum_os_version>4.0.0</minimum_os_version>
<proxies qty="1">
<proxy proxybindingid="5000" name="KNX Presence" small_image="www/icons/logo_16.png" large_image="www/icons/logo_32.png" image_source="c4z">c3c-knx-presence</proxy>
</proxies>
<combo>true</combo>
<connections>
<connection>
<id>1</id>
<connectionname>KNX Control</connectionname>
<facing>6</facing>
<type>1</type>
<consumer>true</consumer>
<linelevel>true</linelevel>
<classes>
<class>
<classname>KNX_DEVICE</classname>
<autobind>false</autobind>
</class>
</classes>
</connection>
</connections>
<events>
<event>
<id>100</id>
<name>UpperFloorBathroomMediaStart</name>
<description>Start Media in Upper Floor Bathroom</description>
</event>
<event>
<id>101</id>
<name>UpperFloorBathroomMediaEnd</name>
<description>End Media in Upper Floor Bathroom</description>
</event>
</events>
<config>
<script jit="1" file="driver.lua"/>
<documentation file="www/documentation.html"/>
<properties>
<property>
<name>Log Level</name>
<type>DYNAMIC_LIST</type>
<readonly>false</readonly>
</property>
<property>
<name>Log Mode</name>
<type>DYNAMIC_LIST</type>
<readonly>false</readonly>
</property>
</properties>
</config>
</devicedata>
-24
View File
@@ -1,24 +0,0 @@
-- Include NPM dependencies
dofile('tests/generated.lua')
-- Load test module
require('busted')
-- Load driver
require('driver')
local inspect = require 'inspect'
describe("Driver", function()
it("loads", function()
local start1, result1 = pcall(_G["OnDriverLateInit"])
local start2, result2 = pcall(_G["OnDriverInit"])
if (not start1) then
assert.are.equal(true, start2)
return
end
assert.are.equal(true, start1)
end)
end)