homebridge-smartsystem 7.1.19 → 7.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/scheduled_tasks.lock +1 -0
- package/CLAUDE.md +118 -0
- package/accessories/temperature.js +2 -1
- package/duotecno/logger.js +1 -0
- package/duotecno/protocol.js +6 -6
- package/duotecno/types.js +12 -0
- package/package.json +2 -1
- package/server/overkiz.js +143 -0
- package/server/platform.js +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"29e28b48-3a89-4159-baf0-58e668c1fe0d","pid":61331,"procStart":"Wed Sep 16 12:58:32 2026","acquiredAt":1789563711220}
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# CLAUDE.md — handover notes for AI coding agents
|
|
2
|
+
|
|
3
|
+
Project: **homebridge-smartsystem** ("SmartSocket"), a Homebridge plugin + standalone
|
|
4
|
+
server that bridges **Duotecno** home-automation gateways (and a few other power/energy
|
|
5
|
+
sources) to HomeKit, a web UI, and a WebSocket/HTTP API. Author: Johan Coppieters.
|
|
6
|
+
|
|
7
|
+
## What this thing actually is
|
|
8
|
+
|
|
9
|
+
- It's a Homebridge **platform plugin** (`homebridge-smartsystem` in [package.json](package.json)),
|
|
10
|
+
registered from [index.ts](index.ts) via `api.registerPlatform(...)`.
|
|
11
|
+
- It also runs stand-alone as an Express-like web/proxy server (no Homebridge) — see
|
|
12
|
+
`server/webapp.ts`, `server/smartapp.ts`, `server/socapp.ts`.
|
|
13
|
+
- Talks to one or more **Duotecno masters** (physical IP-connected controllers) over raw
|
|
14
|
+
TCP using a custom binary protocol, and exposes their nodes/units (switches, dimmers,
|
|
15
|
+
moods, up/downs, temperature sensors, locks, garage doors, window coverings...) as:
|
|
16
|
+
- HomeKit accessories (via Homebridge)
|
|
17
|
+
- a web UI (EJS views in `server/views/`, static assets in `www/`)
|
|
18
|
+
- a WebSocket device-control API (see [WEBSOCKET-API.md](WEBSOCKET-API.md))
|
|
19
|
+
- proxied raw TCP-over-WebSocket (`server/proxy.ts`)
|
|
20
|
+
- Also integrates power/energy sources: Smappee (MQTT), a P1 smart meter, Shelly, and
|
|
21
|
+
can drive Somfy screens over GPIO on a Raspberry Pi.
|
|
22
|
+
|
|
23
|
+
## Source layout
|
|
24
|
+
|
|
25
|
+
- [index.ts](index.ts) — Homebridge plugin entry point.
|
|
26
|
+
- `duotecno/` — protocol layer, independent of Homebridge/HTTP:
|
|
27
|
+
- [protocol.ts](duotecno/protocol.ts) — binary frame encode/decode, `Unit` types.
|
|
28
|
+
- [master.ts](duotecno/master.ts) (885 lines) — one TCP connection to a Duotecno master; heartbeat, reconnect logic.
|
|
29
|
+
- [system.ts](duotecno/system.ts) — collection of masters/nodes/units, the in-memory model.
|
|
30
|
+
- [smartsocket.ts](duotecno/smartsocket.ts), [Q.ts](duotecno/Q.ts) — low-level socket/queue helpers.
|
|
31
|
+
- [config.ts](duotecno/config.ts), [types.ts](duotecno/types.ts), [logger.ts](duotecno/logger.ts), [colors.ts](duotecno/colors.ts).
|
|
32
|
+
- `server/` — everything HTTP/WebSocket/Homebridge-facing:
|
|
33
|
+
- [platform.ts](server/platform.ts) — Homebridge `Platform` class; wires `System` + `SmartApp` + `SocApp` to Homebridge accessories.
|
|
34
|
+
- [smartapp.ts](server/smartapp.ts) (1691 lines, **the biggest file**) — web app: routes, device WebSocket API, power/energy bindings, links, switches. See [MIXINS-GUIDE.md](MIXINS-GUIDE.md) for a *proposed but not-yet-applied* refactor plan to split this file.
|
|
35
|
+
- [webapp.ts](server/webapp.ts) — generic HTTP server base (Express-like) that `smartapp`/`socapp` extend.
|
|
36
|
+
- [socapp.ts](server/socapp.ts) — raw-socket flavored app variant.
|
|
37
|
+
- [proxy.ts](server/proxy.ts) — WebSocket⇄TCP proxy.
|
|
38
|
+
- [base.ts](server/base.ts) — tiny shared base class.
|
|
39
|
+
- [smappee.ts](server/smappee.ts), [p1.ts](server/p1.ts), [shelly.ts](server/shelly.ts) — power measurement sources.
|
|
40
|
+
- [somfy.ts](server/somfy.ts) — GPIO control for Somfy screens (Raspberry Pi only).
|
|
41
|
+
- [HA-API.ts](server/HA-API.ts) — Home Assistant / openHAB style API stubs.
|
|
42
|
+
- [HB.ts](server/HB.ts) — Homebridge-specific glue.
|
|
43
|
+
- [mDNS.ts](server/mDNS.ts) — Bonjour service advertisement (`*.local` names).
|
|
44
|
+
- [support.ts](server/support.ts) — misc helpers.
|
|
45
|
+
- `views/` — EJS templates for the built-in web UI.
|
|
46
|
+
- `accessories/` — one file per HomeKit accessory type (bulb, dimmer, switch, lock, door,
|
|
47
|
+
garagedoor, mood, temperature, windowcovering) — each maps a Duotecno unit type/name
|
|
48
|
+
convention to a HomeKit service. The naming-convention rules (`$`, `*`, `!` markers in
|
|
49
|
+
Duotecno unit names) are documented at the bottom of [README.md](README.md) (v5.4.0 entry) — this is important domain logic, not incidental.
|
|
50
|
+
- `www/` — built/bundled front-end assets (webpack output, not source you'd hand-edit).
|
|
51
|
+
- `data/` — sample/backup JSON dumps of real systems (groups/scenes/system), used for
|
|
52
|
+
local testing, not app config.
|
|
53
|
+
- Root `test*.ts` (`testHB.ts`, `testWS.ts`, `testProxy.ts`) — standalone manual test
|
|
54
|
+
scripts/harnesses, not a unit test suite. See [TESTING-GUIDE.md](TESTING-GUIDE.md).
|
|
55
|
+
- `config*.json` at repo root — real/sample runtime configs for different installs
|
|
56
|
+
(`config.gm.json`, `config.peter.json`, ...). `config.json` is the active one used when
|
|
57
|
+
running locally via the `start` npm script.
|
|
58
|
+
|
|
59
|
+
## Build & run
|
|
60
|
+
|
|
61
|
+
- **Language**: TypeScript, compiled to plain `.js` sitting next to each `.ts` file
|
|
62
|
+
(`"outDir"` = same folder, per [tsconfig.json](tsconfig.json)). Every `.ts` file has a
|
|
63
|
+
matching committed `.js` + `.js.map` — **the compiled JS is checked into git** and is
|
|
64
|
+
what Homebridge actually loads (`main: index.js`). Always rebuild after editing `.ts`.
|
|
65
|
+
- Build once: `npm run build` (`tsc --build`).
|
|
66
|
+
- Watch mode: `npm run watch` (also runs automatically on folder open, task `npm: 1`).
|
|
67
|
+
- Run under Homebridge locally: `npm start` (`homebridge -D -P <this dir>`), reads
|
|
68
|
+
`config.json` for platform config.
|
|
69
|
+
- No automated test framework/CI configured — testing is manual via `testHB.ts` /
|
|
70
|
+
`testWS.ts` / `testProxy.ts` and the guides in [TESTING-GUIDE.md](TESTING-GUIDE.md).
|
|
71
|
+
- Releases: `npm run release:patch|minor|major` — bumps version, commits, tags, publishes
|
|
72
|
+
to npm, and **pushes to origin**. Never run these without the user's explicit go-ahead.
|
|
73
|
+
|
|
74
|
+
## Conventions / gotchas worth knowing before editing
|
|
75
|
+
|
|
76
|
+
- Compiled `.js` files are committed — after any `.ts` change, rebuild (or rely on the
|
|
77
|
+
watch task) before assuming the runtime behavior changed, and commit the regenerated
|
|
78
|
+
`.js`/`.js.map` alongside the `.ts` change.
|
|
79
|
+
- Duotecno unit *display names* encode behavior via trailing marker characters
|
|
80
|
+
(`$`, `*`, `!`, `#`), e.g. an "updown" unit named with `$` becomes a HomeKit
|
|
81
|
+
`GarageDoor`, with `*` becomes a `Door`, otherwise a `WindowCovering` — same pattern for
|
|
82
|
+
moods (`mood`/`unlocker`) and switches (`lock`/`switch`/`lightbulb`). This logic lives
|
|
83
|
+
across `accessories/*.ts` and `duotecno/types.ts` — check [README.md](README.md)'s
|
|
84
|
+
v5.4.0 section for the authoritative rule table before changing accessory-type mapping.
|
|
85
|
+
- `server/smartapp.ts` is large and mixes several concerns (device WS API, links, HTTP
|
|
86
|
+
switches, power bindings, proxy config). [MIXINS-GUIDE.md](MIXINS-GUIDE.md) captures a
|
|
87
|
+
discussed refactor (module/delegate pattern) that was **never carried out** — don't
|
|
88
|
+
assume that structure exists; it's a plan, not current code.
|
|
89
|
+
- Multiple root `config*.json` files exist for different physical installs/customers
|
|
90
|
+
(gm, peter, homebridge). Don't assume `config.json` is representative of all of them;
|
|
91
|
+
check which one is relevant when debugging a specific report.
|
|
92
|
+
- Hex formatting convention for Duotecno addresses: always display Node/Unit addresses
|
|
93
|
+
as hex with `0x` prefix (e.g. `0x04`, `0xFC`) in any UI/log output you add.
|
|
94
|
+
- `raspberry-pi-setup.sh`, `update.sh`, `updserv.sh` are deployment scripts for the actual
|
|
95
|
+
Raspberry Pi gateway hardware in the field — treat changes to these as
|
|
96
|
+
infrastructure-affecting, confirm with the user before running them.
|
|
97
|
+
- Somfy/GPIO code (`server/somfy.ts`) only makes sense on real Raspberry Pi hardware.
|
|
98
|
+
|
|
99
|
+
## Where to look for more detail
|
|
100
|
+
|
|
101
|
+
- [README.md](README.md) — full version history/changelog; the most reliable source of
|
|
102
|
+
"why does this weird naming rule exist" answers.
|
|
103
|
+
- [WEBSOCKET-API.md](WEBSOCKET-API.md) — device WebSocket protocol (client/server message
|
|
104
|
+
formats, device ID = `node*256 + unit`).
|
|
105
|
+
- [MIXINS-GUIDE.md](MIXINS-GUIDE.md) — proposed (unapplied) refactor of `smartapp.ts`.
|
|
106
|
+
- [TESTING-GUIDE.md](TESTING-GUIDE.md) — manual testing steps using `testHB.ts`/`testWS.ts`.
|
|
107
|
+
- [SETTINGS-UPDATE.md](SETTINGS-UPDATE.md) — notes on the web UI Settings page state
|
|
108
|
+
(some features intentionally disabled/commented out pending real implementation).
|
|
109
|
+
|
|
110
|
+
## Working style expected on this repo
|
|
111
|
+
|
|
112
|
+
- Prefer lean, minimal diffs; avoid speculative refactors or defensive code not clearly
|
|
113
|
+
needed (see the large-file/mixins situation above — it's known and intentionally
|
|
114
|
+
deferred, don't "fix" it unprompted).
|
|
115
|
+
- Commit locally often once a coherent, verified chunk of work is done (this user has
|
|
116
|
+
lost uncommitted work before). Never push or run `release:*` scripts without explicit
|
|
117
|
+
confirmation.
|
|
118
|
+
- Split unrelated changes into separate commits with descriptive messages.
|
|
@@ -23,7 +23,8 @@ class Temperature extends accessory_1.Accessory {
|
|
|
23
23
|
getTemperature(next) {
|
|
24
24
|
if (this.unit) {
|
|
25
25
|
(0, logger_1.log)("accessory", "getTemperature was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
26
|
-
|
|
26
|
+
const limited = Math.max(-100, Math.min(100, this.unit.value / 10.0));
|
|
27
|
+
next(null, limited);
|
|
27
28
|
}
|
|
28
29
|
else {
|
|
29
30
|
next(new Error("accessory -> getTemperature needs a unit."));
|
package/duotecno/logger.js
CHANGED
package/duotecno/protocol.js
CHANGED
|
@@ -754,13 +754,13 @@ exports.Protocol = {
|
|
|
754
754
|
let kind = "-";
|
|
755
755
|
if (next.cmd === Rec.Sensor) {
|
|
756
756
|
// sensor -> value
|
|
757
|
-
unit.value = this.
|
|
757
|
+
unit.value = this.makeSignedWord(next.message, 9); // 10x current temperature
|
|
758
758
|
unit.status = next.message[7]; // 0=idle, 1=heating, 2=cooling
|
|
759
759
|
unit.preset = (next.message[6]) ? next.message[8] : -1; // 0=sun, 1=half sun, 2=moon, 3=half moon, -1 = off
|
|
760
|
-
unit.sun = this.
|
|
761
|
-
unit.hsun = this.
|
|
762
|
-
unit.moon = this.
|
|
763
|
-
unit.hmoon = this.
|
|
760
|
+
unit.sun = this.makeSignedWord(next.message, 11); // 10x temperature
|
|
761
|
+
unit.hsun = this.makeSignedWord(next.message, 13); // 10x temperature
|
|
762
|
+
unit.moon = this.makeSignedWord(next.message, 15); // 10x temperature
|
|
763
|
+
unit.hmoon = this.makeSignedWord(next.message, 17); // 10x temperature
|
|
764
764
|
(0, logger_1.debug)("protocol", "received status - " + unit.getDisplayName() + ", temperature = " + unit.value / 10.0 + ", sun = " + unit.sun);
|
|
765
765
|
kind = "S";
|
|
766
766
|
// Dimmers, switches and moods have
|
|
@@ -815,7 +815,7 @@ exports.Protocol = {
|
|
|
815
815
|
// only change dim value when state = 1 (ON, PIR ON, DIM STOP) for Dimmers and IRTX + for any setpoint event
|
|
816
816
|
if ((((next.message[4] === 1) || (next.message[4] === 6) || (next.message[4] === 7)) && (next.message[5] === 1)) ||
|
|
817
817
|
(next.message[4] === 11)) {
|
|
818
|
-
unit.value = this.
|
|
818
|
+
unit.value = this.makeSignedWord(next.message, 6);
|
|
819
819
|
}
|
|
820
820
|
else if (next.message[4] === 32) {
|
|
821
821
|
// unit_type_duoswitch -> Event = 32
|
package/duotecno/types.js
CHANGED
|
@@ -214,6 +214,7 @@ exports.Sanitizers = {
|
|
|
214
214
|
config.smappee = config.smappee || false;
|
|
215
215
|
config.p1 = config.p1 || false;
|
|
216
216
|
config.shelly = config.shelly || false;
|
|
217
|
+
config.overkiz = config.overkiz || false;
|
|
217
218
|
config.smartapp = config.smartapp || null;
|
|
218
219
|
config.system = exports.Sanitizers.system(config.system);
|
|
219
220
|
config.proxy = exports.Sanitizers.proxy(config.proxy, config.system);
|
|
@@ -308,6 +309,17 @@ exports.Sanitizers = {
|
|
|
308
309
|
cfg.addresses = (config === null || config === void 0 ? void 0 : config.addresses) || "";
|
|
309
310
|
return cfg;
|
|
310
311
|
},
|
|
312
|
+
overkiz: function (config) {
|
|
313
|
+
if (!config)
|
|
314
|
+
config = {};
|
|
315
|
+
config.debug = config.debug || false;
|
|
316
|
+
config.service = config.service || "local";
|
|
317
|
+
config.user = config.user || "";
|
|
318
|
+
config.password = config.password || "";
|
|
319
|
+
config.pollingPeriod = config.pollingPeriod || 10;
|
|
320
|
+
config.refreshPeriod = config.refreshPeriod || 60;
|
|
321
|
+
return config;
|
|
322
|
+
},
|
|
311
323
|
linkConfig: function (aLink) {
|
|
312
324
|
const link = exports.Sanitizers.unitDef(aLink);
|
|
313
325
|
link.accId = aLink.accId || "";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-smartsystem",
|
|
3
3
|
"displayname": "Duotecno Bridge",
|
|
4
|
-
"version": "7.1.
|
|
4
|
+
"version": "7.1.20",
|
|
5
5
|
"description": "SmartServer (Proxy TCP sockets to the cloud, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Johan Coppieters",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"mqtt": "^4.3.7",
|
|
45
45
|
"multicast-dns": "^7.2.5",
|
|
46
46
|
"node-fetch": "^3.2.4",
|
|
47
|
+
"overkiz-client": "^1.0.23",
|
|
47
48
|
"rpi-gpio": "^2.1.7",
|
|
48
49
|
"ws": "^7.4.6"
|
|
49
50
|
},
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Direct Somfy/TaHoma (Overkiz) integration.
|
|
3
|
+
//
|
|
4
|
+
// Talks straight to the Overkiz gateway (local TaHoma Developer Mode API, or
|
|
5
|
+
// cloud API as a fallback) using the same client library ("overkiz-client")
|
|
6
|
+
// that dubocr/homebridge-tahoma itself depends on. This replaces the old
|
|
7
|
+
// detour of running homebridge-tahoma as a second Homebridge platform and
|
|
8
|
+
// then polling its HomeKit accessories back into Duotecno via server/HB.ts
|
|
9
|
+
// and the Link mechanism in smartapp.ts.
|
|
10
|
+
//
|
|
11
|
+
// Phase 1 (this file): connect, discover devices, send open/close/stop
|
|
12
|
+
// commands, and emit translated Duotecno-style states when Overkiz reports
|
|
13
|
+
// a change. Wiring this into the Link UI (so a Duotecno unit can be coupled
|
|
14
|
+
// to a specific Somfy screen) is a follow-up step once connectivity against
|
|
15
|
+
// real hardware is confirmed.
|
|
16
|
+
//
|
|
17
|
+
// Johan Coppieters, 2026.
|
|
18
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
19
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
20
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
21
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
22
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
23
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
24
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.Overkiz = void 0;
|
|
29
|
+
const events_1 = require("events");
|
|
30
|
+
const overkiz_client_1 = require("overkiz-client");
|
|
31
|
+
const types_1 = require("../duotecno/types");
|
|
32
|
+
const logger_1 = require("../duotecno/logger");
|
|
33
|
+
const base_1 = require("./base");
|
|
34
|
+
// core:ClosureState / core:ClosureOrRollerShutterPositionState: 0 = fully
|
|
35
|
+
// open, 100 = fully closed (opposite of HomeKit's TargetPosition scale).
|
|
36
|
+
const kOpenThreshold = 5;
|
|
37
|
+
const kClosedThreshold = 95;
|
|
38
|
+
function closureToUnitState(closure, previousClosure) {
|
|
39
|
+
if (closure <= kOpenThreshold)
|
|
40
|
+
return types_1.UnitState.kOpen;
|
|
41
|
+
if (closure >= kClosedThreshold)
|
|
42
|
+
return types_1.UnitState.kClosed;
|
|
43
|
+
if (typeof previousClosure === "number") {
|
|
44
|
+
if (closure < previousClosure)
|
|
45
|
+
return types_1.UnitState.kOpening;
|
|
46
|
+
if (closure > previousClosure)
|
|
47
|
+
return types_1.UnitState.kClosing;
|
|
48
|
+
}
|
|
49
|
+
return types_1.UnitState.kStopped;
|
|
50
|
+
}
|
|
51
|
+
class Overkiz extends base_1.Base {
|
|
52
|
+
constructor(system) {
|
|
53
|
+
super("overkiz");
|
|
54
|
+
this.emitter = new events_1.EventEmitter();
|
|
55
|
+
this.devices = new Map();
|
|
56
|
+
this.closures = new Map();
|
|
57
|
+
this.system = system;
|
|
58
|
+
if (this.config.user && this.config.password) {
|
|
59
|
+
this.connect().catch(e => (0, logger_1.err)("overkiz", "connect failed: " + (e.message || e)));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
(0, logger_1.log)("overkiz", "Overkiz not configured (missing user/password) -> not starting.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
connect() {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const bridge = {
|
|
68
|
+
warn: (...args) => (0, logger_1.log)("overkiz", args.join(" ")),
|
|
69
|
+
error: (...args) => (0, logger_1.err)("overkiz", args.join(" ")),
|
|
70
|
+
debug: (...args) => (0, logger_1.debug)("overkiz", args.join(" ")),
|
|
71
|
+
info: (...args) => (0, logger_1.log)("overkiz", args.join(" ")),
|
|
72
|
+
log: (...args) => (0, logger_1.log)("overkiz", args.join(" ")),
|
|
73
|
+
};
|
|
74
|
+
this.client = new overkiz_client_1.Client(bridge, {
|
|
75
|
+
service: this.config.service || "local",
|
|
76
|
+
user: this.config.user,
|
|
77
|
+
password: this.config.password,
|
|
78
|
+
pollingPeriod: this.config.pollingPeriod || 10,
|
|
79
|
+
refreshPeriod: this.config.refreshPeriod || 60,
|
|
80
|
+
});
|
|
81
|
+
const setup = yield this.client.getSetup();
|
|
82
|
+
setup.devices.forEach(device => this.attachDevice(device));
|
|
83
|
+
(0, logger_1.log)("overkiz", `connected -> ${setup.devices.length} device(s) found`);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
attachDevice(device) {
|
|
87
|
+
this.devices.set(device.deviceURL, device);
|
|
88
|
+
const closure = device.getNumber("core:ClosureState");
|
|
89
|
+
if (device.hasState("core:ClosureState"))
|
|
90
|
+
this.closures.set(device.deviceURL, closure);
|
|
91
|
+
device.on("states", (states) => this.onStates(device, states));
|
|
92
|
+
}
|
|
93
|
+
onStates(device, states) {
|
|
94
|
+
(0, logger_1.debug)("overkiz", `states for ${device.label} -> ${JSON.stringify(states)}`);
|
|
95
|
+
const closureState = states.find(s => s.name === "core:ClosureState");
|
|
96
|
+
if (closureState) {
|
|
97
|
+
const closure = Number(closureState.value);
|
|
98
|
+
const previous = this.closures.get(device.deviceURL);
|
|
99
|
+
const unitState = closureToUnitState(closure, previous);
|
|
100
|
+
this.closures.set(device.deviceURL, closure);
|
|
101
|
+
(0, logger_1.log)("overkiz", `${device.label} -> closure ${closure} -> UnitState ${types_1.UnitState[unitState]}`);
|
|
102
|
+
this.emitter.emit("state", device.deviceURL, unitState, closure);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
listDevices() {
|
|
106
|
+
return Array.from(this.devices.values()).map(d => ({
|
|
107
|
+
deviceURL: d.deviceURL, label: d.label, widget: d.definition.widgetName,
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
execute(deviceURL, commandName, parameters = []) {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
if (!this.client)
|
|
113
|
+
throw new Error("Overkiz not connected");
|
|
114
|
+
(0, logger_1.log)("overkiz", `execute ${commandName}${parameters.length ? "(" + parameters.join(",") + ")" : ""} on ${deviceURL}`);
|
|
115
|
+
yield this.client.execute("apply", {
|
|
116
|
+
label: "smartsocket",
|
|
117
|
+
actions: [{ deviceURL, commands: [{ name: commandName, parameters }] }],
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
up(deviceURL) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
yield this.execute(deviceURL, "open");
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
down(deviceURL) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
yield this.execute(deviceURL, "close");
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
stop(deviceURL) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
yield this.execute(deviceURL, "stop");
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
setClosure(deviceURL, percentClosed) {
|
|
137
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
yield this.execute(deviceURL, "setClosure", [percentClosed]);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.Overkiz = Overkiz;
|
|
143
|
+
//# sourceMappingURL=overkiz.js.map
|
package/server/platform.js
CHANGED
|
@@ -28,6 +28,7 @@ const door_1 = require("../accessories/door");
|
|
|
28
28
|
const lock_1 = require("../accessories/lock");
|
|
29
29
|
const p1_1 = require("./p1");
|
|
30
30
|
const shelly_1 = require("./shelly");
|
|
31
|
+
const overkiz_1 = require("./overkiz");
|
|
31
32
|
const config_1 = require("../duotecno/config");
|
|
32
33
|
const fs_1 = require("fs");
|
|
33
34
|
const proxy_1 = require("./proxy");
|
|
@@ -85,6 +86,7 @@ class Platform extends base_1.Base {
|
|
|
85
86
|
this.startPower("smappee", smappee_1.Smappee);
|
|
86
87
|
this.startPower("p1", p1_1.P1);
|
|
87
88
|
this.startPower("shelly", shelly_1.Shelly);
|
|
89
|
+
this.startPower("overkiz", overkiz_1.Overkiz);
|
|
88
90
|
// startup a smartApp if configured
|
|
89
91
|
if (this.config.smartapp) {
|
|
90
92
|
try {
|