diff --git a/.gitignore b/.gitignore index 94fad8b..c5c41c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ -/log/ -/intermediate/ -/node_modules/ -/output/ -/environment.json +/output +/result +/result- +/src/www/documentation.html .direnv .devenv diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 64f9127..0000000 --- a/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -@annex4:registry=https://npm.pkg.github.com -@c3c:registry=https://git.c3c.cz/api/packages/c3c/npm/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ac32fe9 --- /dev/null +++ b/CLAUDE.md @@ -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 `` 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, ``/`` 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 `` 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. diff --git a/components/actions.c4c b/components/actions.c4c deleted file mode 100644 index fe51488..0000000 --- a/components/actions.c4c +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/components/commands.c4c b/components/commands.c4c deleted file mode 100644 index fe51488..0000000 --- a/components/commands.c4c +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/components/connections.c4c b/components/connections.c4c deleted file mode 100644 index bbcdb29..0000000 --- a/components/connections.c4c +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "id": 1, - "connectionname": "KNX Control", - "type": 1, - "consumer": true, - "classes": [ - { - "classname": "KNX_DEVICE", - "autobind": false - } - ], - "linelevel": true, - "facing": 6 - } -] diff --git a/components/events.c4c b/components/events.c4c deleted file mode 100644 index 2b71cb1..0000000 --- a/components/events.c4c +++ /dev/null @@ -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" - } -] diff --git a/components/navdisplayoptions.c4c b/components/navdisplayoptions.c4c deleted file mode 100644 index 0637a08..0000000 --- a/components/navdisplayoptions.c4c +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/components/properties.c4c b/components/properties.c4c deleted file mode 100644 index 1f11c23..0000000 --- a/components/properties.c4c +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "name": "Log Level", - "type": "DYNAMIC_LIST", - "readonly": false - }, - { - "name": "Log Mode", - "type": "DYNAMIC_LIST", - "readonly": false - } -] diff --git a/components/proxies.c4c b/components/proxies.c4c deleted file mode 100644 index e60129f..0000000 --- a/components/proxies.c4c +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "id": 5000, - "proxy": "c3c-knx-presence", - "name": "KNX Presence" - } -] diff --git a/components/ui.c4c b/components/ui.c4c deleted file mode 100644 index fe51488..0000000 --- a/components/ui.c4c +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/flake.lock b/flake.lock index 7097d60..b6f56ac 100644 --- a/flake.lock +++ b/flake.lock @@ -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" } } }, diff --git a/flake.nix b/flake.nix index 0267978..6055e06 100644 --- a/flake.nix +++ b/flake.nix @@ -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 . + ''; + }; + } + ); } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index bba2854..0000000 --- a/package-lock.json +++ /dev/null @@ -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" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 5deab82..0000000 --- a/package.json +++ /dev/null @@ -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" -} diff --git a/src/control4-utils/knx/GroupAddress.lua b/src/control4-utils/knx/GroupAddress.lua index 08447d2..4658103 100644 --- a/src/control4-utils/knx/GroupAddress.lua +++ b/src/control4-utils/knx/GroupAddress.lua @@ -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 diff --git a/src/control4-utils/knx/gen/ADDRESSES.lua b/src/control4-utils/knx/gen/ADDRESSES.lua index 330859d..092cf9a 100644 --- a/src/control4-utils/knx/gen/ADDRESSES.lua +++ b/src/control4-utils/knx/gen/ADDRESSES.lua @@ -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" diff --git a/src/control4-utils/knx/gen/createGroupAddresses.lua b/src/control4-utils/knx/gen/createGroupAddresses.lua index 8acfe14..2e6360d 100644 --- a/src/control4-utils/knx/gen/createGroupAddresses.lua +++ b/src/control4-utils/knx/gen/createGroupAddresses.lua @@ -1,7 +1,6 @@ - ---@return table 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 - \ No newline at end of file diff --git a/src/driver.lua b/src/driver.lua index 9d71743..af674fe 100644 --- a/src/driver.lua +++ b/src/driver.lua @@ -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 diff --git a/src/driver.xml b/src/driver.xml new file mode 100644 index 0000000..95b6cf2 --- /dev/null +++ b/src/driver.xml @@ -0,0 +1,63 @@ + + Copyright 2026 C3C + C3C + C3C + KNX Presence + c3c-knx-presence + 2023-05-14 + 2026-07-04 + 233 + false + lua_gen + KNX + DriverWorks + 4.0.0 + + c3c-knx-presence + + true + + + 1 + KNX Control + 6 + 1 + true + true + + + KNX_DEVICE + false + + + + + + + 100 + UpperFloorBathroomMediaStart + Start Media in Upper Floor Bathroom + + + 101 + UpperFloorBathroomMediaEnd + End Media in Upper Floor Bathroom + + + +