homematic-manager 3.0.0-beta.32 → 3.0.0-beta.33
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/node_modules/@homematic-manager/backend/dist/api/backend.d.ts +7 -0
- package/node_modules/@homematic-manager/backend/dist/api/backend.js +160 -23
- package/node_modules/@homematic-manager/backend/dist/interfaces/lite.d.ts +105 -0
- package/node_modules/@homematic-manager/backend/dist/interfaces/lite.js +691 -0
- package/node_modules/@homematic-manager/backend/dist/interfaces/manager.d.ts +35 -3
- package/node_modules/@homematic-manager/backend/dist/interfaces/manager.js +1 -1
- package/node_modules/@homematic-manager/backend/dist/meta/service.js +1 -0
- package/node_modules/@homematic-manager/backend/dist/meta/system.d.ts +51 -1
- package/node_modules/@homematic-manager/backend/dist/meta/system.js +142 -4
- package/node_modules/@homematic-manager/backend/package.json +1 -1
- package/node_modules/@homematic-manager/core/dist/api/types.d.ts +86 -0
- package/node_modules/@homematic-manager/core/dist/api/types.js +1 -0
- package/node_modules/@homematic-manager/core/dist/i18n/lookup.d.ts +8 -0
- package/node_modules/@homematic-manager/core/dist/i18n/lookup.js +13 -0
- package/node_modules/@homematic-manager/core/package.json +1 -1
- package/package.json +3 -3
- package/ui/assets/index-C-5bKNPO.css +1 -0
- package/ui/assets/index-DH86pPK8.js +20 -0
- package/ui/index.html +2 -2
- package/ui/assets/index-Co1znn_z.js +0 -20
- package/ui/assets/index-Xv-mu1eX.css +0 -1
|
@@ -17,7 +17,9 @@ import { maintenanceAddress, type AppConfig, type ApiEventName, type ApiEvents,
|
|
|
17
17
|
import { type ConfigStoreOptions } from '../config/store.js';
|
|
18
18
|
import { type DiscoverOptions } from '../discovery/discover.js';
|
|
19
19
|
import { InterfaceManager, type InterfaceManagerOptions } from '../interfaces/manager.js';
|
|
20
|
+
import { LiteInterfaces, type LiteInterfacesOptions } from '../interfaces/lite.js';
|
|
20
21
|
import { type MetaServiceOptions } from '../meta/service.js';
|
|
22
|
+
import { type PairWithSystemOptions } from '../meta/system.js';
|
|
21
23
|
import { RegaService, type RegaServiceOptions } from '../rega/client.js';
|
|
22
24
|
import { ApiEventEmitter } from '../util/emitter.js';
|
|
23
25
|
import { type CallbackNetwork } from '../util/net.js';
|
|
@@ -87,6 +89,11 @@ export interface BackendOptions extends Omit<ConfigStoreOptions, 'version'> {
|
|
|
87
89
|
readonly now?: () => number;
|
|
88
90
|
/** Injected by the tests in place of the real world. */
|
|
89
91
|
readonly createInterfaceManager?: (options: InterfaceManagerOptions) => InterfaceManager;
|
|
92
|
+
/** Task 72: the same for the openccu-lite path of a remote connection. */
|
|
93
|
+
readonly createLiteInterfaces?: (options: LiteInterfacesOptions) => LiteInterfaces;
|
|
94
|
+
readonly liteOptions?: Partial<LiteInterfacesOptions>;
|
|
95
|
+
/** Task 72: occulite-client's `pair()`, replaced by the tests. */
|
|
96
|
+
readonly pair?: PairWithSystemOptions['pair'];
|
|
90
97
|
readonly createRega?: (options: RegaServiceOptions) => RegaService;
|
|
91
98
|
/** D-40: injected by the tests, and by the integration test that runs a real occulited. */
|
|
92
99
|
readonly metaOptions?: Partial<MetaServiceOptions>;
|
|
@@ -18,15 +18,16 @@ import { RPC_METHOD_NAMES, RSSI_UNKNOWN, countsAsServiceMessage, isAcknowledgeab
|
|
|
18
18
|
import { CacheStore } from '../cache/store.js';
|
|
19
19
|
import { ConfigStore } from '../config/store.js';
|
|
20
20
|
import { LinkTemplateStore } from '../config/linkTemplates.js';
|
|
21
|
-
import { validateConnection, writePaceFor } from '../config/defaults.js';
|
|
21
|
+
import { normaliseConnection, validateConnection, writePaceFor } from '../config/defaults.js';
|
|
22
22
|
import { DataFileServer } from '../data/files.js';
|
|
23
23
|
import { installModeCalls } from '../devices/installMode.js';
|
|
24
24
|
import { discoverCcus } from '../discovery/discover.js';
|
|
25
25
|
import { BackendError, configError, connectionError, errorMessage, internalError, isMethodUnsupported, validationError, } from '../errors.js';
|
|
26
26
|
import { DEFAULT_IDLE_UNSUBSCRIBE_MS, InterfaceManager, LOOPBACK_IP, callbackBindHost, firstBidcosInterfaceAddress, } from '../interfaces/manager.js';
|
|
27
|
+
import { LiteInterfaces } from '../interfaces/lite.js';
|
|
27
28
|
import { HeatingGroupsClient } from '../groups/client.js';
|
|
28
29
|
import { MetaService, hostBaseUrl } from '../meta/service.js';
|
|
29
|
-
import { DETECT_TIMEOUT_MS, detectSystem, transportFor } from '../meta/system.js';
|
|
30
|
+
import { DETECT_TIMEOUT_MS, detectSystem, pairWithSystem, testSystem, transportFor, } from '../meta/system.js';
|
|
30
31
|
import { RegaService } from '../rega/client.js';
|
|
31
32
|
import { listDevicesAnswer } from '../rpc/server.js';
|
|
32
33
|
import { ApiEventEmitter } from '../util/emitter.js';
|
|
@@ -77,7 +78,16 @@ export class Backend {
|
|
|
77
78
|
#now;
|
|
78
79
|
#methodCache = new Map();
|
|
79
80
|
#caches;
|
|
81
|
+
/**
|
|
82
|
+
* Task 72: the interface processes - through callback servers and `init` on a CCU (and on the
|
|
83
|
+
* system itself, where the addon runs), through lite-rpc on an openccu-lite system reached from
|
|
84
|
+
* off it. Everything below the API talks to the {@link Interfaces} surface and nothing else.
|
|
85
|
+
*/
|
|
80
86
|
#manager;
|
|
87
|
+
/** Task 72: counts the connects, so a connect that waited for the probe knows it is still the current one. */
|
|
88
|
+
#connectSeq = 0;
|
|
89
|
+
/** Task 72: the pairing with an openccu-lite system that is running, if any. */
|
|
90
|
+
#pairing;
|
|
81
91
|
#rega;
|
|
82
92
|
/** D-40: the metadata store of this connection - this profile's own, or an openccu-lite box. */
|
|
83
93
|
#meta;
|
|
@@ -358,6 +368,12 @@ export class Backend {
|
|
|
358
368
|
return this.#clearCaches();
|
|
359
369
|
case 'config.callbackAddresses':
|
|
360
370
|
return this.#callbackAddresses(p[0]);
|
|
371
|
+
case 'connection.test':
|
|
372
|
+
return this.#testConnection(p[0]);
|
|
373
|
+
case 'connection.pair':
|
|
374
|
+
return this.#startPairing(p[0]);
|
|
375
|
+
case 'connection.pairCancel':
|
|
376
|
+
return this.#cancelPairing();
|
|
361
377
|
case 'interfaces.list':
|
|
362
378
|
return this.#manager?.states() ?? [];
|
|
363
379
|
case 'interfaces.reconnect':
|
|
@@ -592,12 +608,34 @@ export class Backend {
|
|
|
592
608
|
}
|
|
593
609
|
async #connectNow() {
|
|
594
610
|
const connection = this.#config.connection;
|
|
611
|
+
const seq = ++this.#connectSeq;
|
|
595
612
|
this.#paramsetIds.clear();
|
|
596
613
|
this.#noServiceMessages.clear();
|
|
597
614
|
this.#serviceMessageFailures.clear();
|
|
598
615
|
this.#listedMethods.clear();
|
|
599
616
|
this.#noListMethods.clear();
|
|
600
|
-
|
|
617
|
+
// Task 72: a connection from off the system with an API token may be one to an openccu-lite
|
|
618
|
+
// system, which never calls a remote client back (its D-70): the probe decides *before* the
|
|
619
|
+
// interfaces are started, and its answer picks lite-rpc over callback servers. Only then is
|
|
620
|
+
// the probe waited for - for everybody else (the addon on the system, a profile without a
|
|
621
|
+
// token, every CCU) it runs alongside the interface start as before (D-40's rule: a host
|
|
622
|
+
// that swallows the packet holds up the names, never the interfaces).
|
|
623
|
+
const token = (connection.metaToken ?? '').trim();
|
|
624
|
+
const mayBeRemoteLite = connection.local !== true && token !== '';
|
|
625
|
+
let hostProbe;
|
|
626
|
+
let liteProbe;
|
|
627
|
+
if (mayBeRemoteLite) {
|
|
628
|
+
liteProbe = await this.#probeHost(connection);
|
|
629
|
+
if (this.#stopped || seq !== this.#connectSeq) {
|
|
630
|
+
// disconnected while the host was being asked
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
hostProbe = Promise.resolve(liteProbe);
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
hostProbe = this.#probeHost(connection);
|
|
637
|
+
}
|
|
638
|
+
const shared = {
|
|
601
639
|
connection,
|
|
602
640
|
handler: this.#callbackHandler(),
|
|
603
641
|
onStateChanged: (states) => {
|
|
@@ -611,27 +649,45 @@ export class Backend {
|
|
|
611
649
|
this.#onCall(record);
|
|
612
650
|
},
|
|
613
651
|
originOf: currentOrigin,
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
: {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
652
|
+
};
|
|
653
|
+
const manager = liteProbe?.answer !== undefined
|
|
654
|
+
? (this.#options.createLiteInterfaces ?? ((options) => new LiteInterfaces(options)))({
|
|
655
|
+
...shared,
|
|
656
|
+
baseUrl: liteProbe.baseUrl ?? hostBaseUrl(connection),
|
|
657
|
+
token,
|
|
658
|
+
transport: transportFor({
|
|
659
|
+
fetch: this.#options.metaOptions?.fetch,
|
|
660
|
+
trust: connection.systemTrust,
|
|
661
|
+
}),
|
|
662
|
+
...(this.#options.rpcTimeoutMs === undefined ? {} : { rpcTimeoutMs: this.#options.rpcTimeoutMs }),
|
|
663
|
+
...(this.#options.now === undefined ? {} : { now: this.#options.now }),
|
|
664
|
+
...this.#options.liteOptions,
|
|
665
|
+
})
|
|
666
|
+
: (this.#options.createInterfaceManager ?? ((options) => new InterfaceManager(options)))({
|
|
667
|
+
...shared,
|
|
668
|
+
...(this.#options.callbackHost === undefined ? {} : { callbackHost: this.#options.callbackHost }),
|
|
669
|
+
...(this.#options.defaultCallbackPorts === undefined
|
|
670
|
+
? {}
|
|
671
|
+
: { defaultCallbackPorts: this.#options.defaultCallbackPorts }),
|
|
672
|
+
...(this.#config.callbackPins === undefined ? {} : { callbackPins: this.#config.callbackPins }),
|
|
673
|
+
// B-69: read at every watchdog round - the cache is replaced when the host changes
|
|
674
|
+
listsDevices: (interfaceName) => this.#caches.devices.size(interfaceName) > 0,
|
|
675
|
+
...(this.#options.rpcTimeoutMs === undefined ? {} : { rpcTimeoutMs: this.#options.rpcTimeoutMs }),
|
|
676
|
+
...(this.#options.watchdogIntervalMs === undefined
|
|
677
|
+
? {}
|
|
678
|
+
: { watchdogIntervalMs: this.#options.watchdogIntervalMs }),
|
|
679
|
+
...(this.#options.localAddresses === undefined
|
|
680
|
+
? {}
|
|
681
|
+
: { localAddresses: this.#options.localAddresses }),
|
|
682
|
+
...(this.#options.network === undefined ? {} : { network: this.#options.network }),
|
|
683
|
+
...(this.#keepsConfiguredCallbackIp() ? { keepConfiguredCallbackIp: true } : {}),
|
|
684
|
+
...(this.#options.now === undefined ? {} : { now: this.#options.now }),
|
|
685
|
+
...this.#options.interfaceManagerOptions,
|
|
686
|
+
});
|
|
631
687
|
this.#manager = manager;
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
688
|
+
if (liteProbe?.answer !== undefined) {
|
|
689
|
+
this.#notice('info', `${connection.host}: an openccu-lite system - the interfaces are reached through its lite-rpc with the API token, without callbacks`);
|
|
690
|
+
}
|
|
635
691
|
try {
|
|
636
692
|
await manager.start();
|
|
637
693
|
}
|
|
@@ -717,6 +773,7 @@ export class Backend {
|
|
|
717
773
|
};
|
|
718
774
|
}
|
|
719
775
|
async #disconnect() {
|
|
776
|
+
this.#connectSeq += 1;
|
|
720
777
|
this.#clearTimers();
|
|
721
778
|
this.#queue.cancel();
|
|
722
779
|
await this.#manager?.stop();
|
|
@@ -1006,6 +1063,83 @@ export class Backend {
|
|
|
1006
1063
|
const origin = currentOrigin();
|
|
1007
1064
|
return this.#queue.enqueue(interfaceName, () => client.call(method, params, { origin }));
|
|
1008
1065
|
}
|
|
1066
|
+
/*
|
|
1067
|
+
* task 72: the connection test and the pairing with an openccu-lite system
|
|
1068
|
+
*/
|
|
1069
|
+
/** `connection.test`: what is at the draft's host, and what its token is worth there. */
|
|
1070
|
+
async #testConnection(input) {
|
|
1071
|
+
const connection = normaliseConnection(input);
|
|
1072
|
+
const baseUrl = hostBaseUrl(connection);
|
|
1073
|
+
if (baseUrl === '') {
|
|
1074
|
+
throw validationError('no CCU address configured');
|
|
1075
|
+
}
|
|
1076
|
+
return testSystem(transportFor({ fetch: this.#options.metaOptions?.fetch, trust: connection.systemTrust }), baseUrl, (connection.metaToken ?? '').trim(), this.#options.metaOptions?.detectTimeoutMs ?? DETECT_TIMEOUT_MS);
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* `connection.pair`: asks the system for a token and answers at once; the steps come as
|
|
1080
|
+
* `pairing.changed` (openccu-lite task 219: the code is shown here and on the system's Status
|
|
1081
|
+
* page, an administrator approves it there). One pairing at a time - a new one cancels the old.
|
|
1082
|
+
*/
|
|
1083
|
+
#startPairing(input) {
|
|
1084
|
+
const connection = normaliseConnection(input);
|
|
1085
|
+
const baseUrl = hostBaseUrl(connection);
|
|
1086
|
+
if (baseUrl === '') {
|
|
1087
|
+
throw validationError('no CCU address configured');
|
|
1088
|
+
}
|
|
1089
|
+
this.#cancelPairing();
|
|
1090
|
+
const controller = new AbortController();
|
|
1091
|
+
this.#pairing = controller;
|
|
1092
|
+
this.events.emit('pairing.changed', { state: 'requesting' });
|
|
1093
|
+
void this.#runPairing(connection, baseUrl, controller);
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
async #runPairing(connection, baseUrl, controller) {
|
|
1097
|
+
const current = () => this.#pairing === controller;
|
|
1098
|
+
try {
|
|
1099
|
+
const paired = await pairWithSystem({
|
|
1100
|
+
transport: transportFor({ fetch: this.#options.metaOptions?.fetch, trust: connection.systemTrust }),
|
|
1101
|
+
baseUrl,
|
|
1102
|
+
appVersion: this.#config.config.version,
|
|
1103
|
+
detectTimeoutMs: this.#options.metaOptions?.detectTimeoutMs ?? DETECT_TIMEOUT_MS,
|
|
1104
|
+
signal: controller.signal,
|
|
1105
|
+
onCode: (code) => {
|
|
1106
|
+
if (current()) {
|
|
1107
|
+
this.events.emit('pairing.changed', { state: 'code', code });
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
...(this.#options.pair === undefined ? {} : { pair: this.#options.pair }),
|
|
1111
|
+
});
|
|
1112
|
+
if (!current()) {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
this.#pairing = undefined;
|
|
1116
|
+
this.events.emit('pairing.changed', {
|
|
1117
|
+
state: 'approved',
|
|
1118
|
+
token: paired.token,
|
|
1119
|
+
fingerprint256: paired.fingerprint256,
|
|
1120
|
+
scopes: paired.scopes,
|
|
1121
|
+
name: paired.name,
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
catch (error) {
|
|
1125
|
+
if (!current()) {
|
|
1126
|
+
// cancelled, or replaced by a newer one: that one said so
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
this.#pairing = undefined;
|
|
1130
|
+
this.events.emit('pairing.changed', { state: 'failed', message: errorMessage(error) });
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
/** `connection.pairCancel`: withdraws the request, on the system too (the client does that). */
|
|
1134
|
+
#cancelPairing() {
|
|
1135
|
+
const controller = this.#pairing;
|
|
1136
|
+
if (controller !== undefined) {
|
|
1137
|
+
this.#pairing = undefined;
|
|
1138
|
+
controller.abort();
|
|
1139
|
+
this.events.emit('pairing.changed', { state: 'cancelled' });
|
|
1140
|
+
}
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1009
1143
|
/*
|
|
1010
1144
|
* configuration
|
|
1011
1145
|
*/
|
|
@@ -1951,6 +2085,9 @@ export const API_METHOD_NAMES = [
|
|
|
1951
2085
|
'config.discover',
|
|
1952
2086
|
'config.clearCaches',
|
|
1953
2087
|
'config.callbackAddresses',
|
|
2088
|
+
'connection.test',
|
|
2089
|
+
'connection.pair',
|
|
2090
|
+
'connection.pairCancel',
|
|
1954
2091
|
'interfaces.list',
|
|
1955
2092
|
'interfaces.reconnect',
|
|
1956
2093
|
'rega.state',
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 72: the interfaces of an openccu-lite system, reached from off the system.
|
|
3
|
+
*
|
|
4
|
+
* A CCU calls its clients back, so `manager.ts` runs callback servers and subscribes to every
|
|
5
|
+
* interface process with `init`. openccu-lite does not call a remote client at all (its D-70): the
|
|
6
|
+
* requests go to the system's web port - lite-rpc's JSON-RPC path, one per interface, with the
|
|
7
|
+
* profile's API token - and the events come from a stream the client opens itself. occulite-client
|
|
8
|
+
* owns that stream and its reliability: reconnect with backoff, resume by the last event id, a
|
|
9
|
+
* `resync` after a gap or another boot of the system. What is left here is this application's:
|
|
10
|
+
*
|
|
11
|
+
* - the {@link Interfaces} surface the backend talks to, so the write queue, the RPC log and every
|
|
12
|
+
* `ApiMethods` handler are the same code on both paths;
|
|
13
|
+
* - the stream's events handed to the very same {@link CallbackHandler} the callback servers feed,
|
|
14
|
+
* so the grids, the service messages and the event log do not know where an event came from;
|
|
15
|
+
* - the state per interface as the popup shows it, from the system's interface list and the
|
|
16
|
+
* client's status;
|
|
17
|
+
* - the errors as the backend knows them: a fault of the interface process stays a fault, a
|
|
18
|
+
* scope the token lacks is said as such and never taken for a lost connection (task 78's tiers).
|
|
19
|
+
*
|
|
20
|
+
* The CCU path is untouched: on the system itself the addon keeps its loopback callbacks
|
|
21
|
+
* (maintainer, 2026-09-27: "remote only"), and a CCU never gets here at all.
|
|
22
|
+
*/
|
|
23
|
+
import { OccuLite, type Options as OccuLiteOptions, type Transport } from 'occulite-client';
|
|
24
|
+
import { type ConnectionConfig, type InterfaceState, type ResolvedInterface, type RpcOrigin, type RpcValue } from '@homematic-manager/core';
|
|
25
|
+
import type { RpcCallRecord, RpcOutValue } from '../rpc/client.js';
|
|
26
|
+
import type { CallbackHandler } from '../rpc/server.js';
|
|
27
|
+
import type { InterfaceLink, Interfaces } from './manager.js';
|
|
28
|
+
/**
|
|
29
|
+
* The waits between two attempts to reach a system that does not answer: quick at first (it may be
|
|
30
|
+
* booting), then a minute. A remote system that is off for the night is not asked every two seconds.
|
|
31
|
+
*/
|
|
32
|
+
export declare const LITE_RETRY_DELAYS_MS: readonly number[];
|
|
33
|
+
/** How long one request may take; the same as the CCU path's clients. */
|
|
34
|
+
export declare const LITE_RPC_TIMEOUT_MS = 20000;
|
|
35
|
+
/** How long the first picture - the version, the credential, the interfaces, the values - may take. */
|
|
36
|
+
export declare const LITE_CONNECT_TIMEOUT_MS = 30000;
|
|
37
|
+
export interface LiteInterfacesOptions {
|
|
38
|
+
readonly connection: ConnectionConfig;
|
|
39
|
+
/** Where the system answered the detection: `https://…` when it redirected there (B-67). */
|
|
40
|
+
readonly baseUrl: string;
|
|
41
|
+
/** The profile's API token (`metaToken`); paired, or made on the system's API tokens page. */
|
|
42
|
+
readonly token: string;
|
|
43
|
+
/** The transport with the profile's certificate trust (`systemTransport`). */
|
|
44
|
+
readonly transport: Transport;
|
|
45
|
+
/** What the stream's events become - the same handler the callback servers feed. */
|
|
46
|
+
readonly handler: CallbackHandler;
|
|
47
|
+
readonly onStateChanged: (states: InterfaceState[]) => void;
|
|
48
|
+
readonly onNotice: (level: 'debug' | 'info' | 'warn' | 'error', message: string, interfaceName?: string) => void;
|
|
49
|
+
/** Called once an interface is reachable - the backend fills its caches there. */
|
|
50
|
+
readonly onConnected?: (interfaceName: string) => void | Promise<void>;
|
|
51
|
+
readonly onCall?: (record: RpcCallRecord) => void;
|
|
52
|
+
/** Task 48: the origin of a call that names none (the backend's request context). */
|
|
53
|
+
readonly originOf?: () => RpcOrigin;
|
|
54
|
+
readonly now?: () => number;
|
|
55
|
+
readonly rpcTimeoutMs?: number;
|
|
56
|
+
readonly connectTimeoutMs?: number;
|
|
57
|
+
/** The retry schedule after a system that does not answer; {@link LITE_RETRY_DELAYS_MS}. */
|
|
58
|
+
readonly retryDelaysMs?: readonly number[];
|
|
59
|
+
/** Injected by the tests. */
|
|
60
|
+
readonly createClient?: (options: OccuLiteOptions) => OccuLite;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A value as lite-rpc's JSON path takes it. The core writes a `FLOAT` as `{explicitDouble: n}` for
|
|
64
|
+
* the XML-RPC and BIN-RPC encoders; the JSON path types a double as `{"double": n}` where the system
|
|
65
|
+
* says it understands that (`json_double`, openccu-lite task 196's S2), and takes the plain number
|
|
66
|
+
* everywhere else - a fraction is a double either way, only a whole number needs the hint.
|
|
67
|
+
*/
|
|
68
|
+
export declare function toWire(value: RpcOutValue, typedDouble: boolean): unknown;
|
|
69
|
+
/**
|
|
70
|
+
* An answer of the JSON path as an `RpcValue`: JSON has `null` where XML-RPC has an empty string
|
|
71
|
+
* (a method without a result), and nothing else the contract does not know.
|
|
72
|
+
*/
|
|
73
|
+
export declare function fromWire(value: unknown): RpcValue;
|
|
74
|
+
/** The interfaces of an openccu-lite system, over occulite-client. */
|
|
75
|
+
export declare class LiteInterfaces implements Interfaces {
|
|
76
|
+
#private;
|
|
77
|
+
constructor(options: LiteInterfacesOptions);
|
|
78
|
+
get idle(): boolean;
|
|
79
|
+
/** The client in use, for a test and for the backend's values (task 68). */
|
|
80
|
+
get box(): OccuLite | undefined;
|
|
81
|
+
states(): InterfaceState[];
|
|
82
|
+
client(interfaceName: string): InterfaceLink;
|
|
83
|
+
isConnected(interfaceName: string): boolean;
|
|
84
|
+
names(): string[];
|
|
85
|
+
resolved(interfaceName: string): ResolvedInterface | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Builds the entries and opens the client. Resolves once the first attempt is through - a
|
|
88
|
+
* system that does not answer leaves an error in every state and is tried again; it does not
|
|
89
|
+
* throw.
|
|
90
|
+
*/
|
|
91
|
+
start(): Promise<void>;
|
|
92
|
+
/** D-31: closes the stream and forgets nothing; {@link subscribe} opens it again. */
|
|
93
|
+
unsubscribe(): Promise<void>;
|
|
94
|
+
subscribe(): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* `interfaces.reconnect`: the user saying "try now". A client that is not up is opened again at
|
|
97
|
+
* once (a token pasted after a refusal, a system that came back); one that is up re-reads the
|
|
98
|
+
* interface's devices, which is all a subscription-less path has to redo.
|
|
99
|
+
*/
|
|
100
|
+
reconnect(interfaceName?: string): Promise<void>;
|
|
101
|
+
/** Closes the stream; nothing is de-registered, because nothing was registered. */
|
|
102
|
+
stop(): Promise<void>;
|
|
103
|
+
noteEvent(interfaceName: string, kind?: 'event' | 'device'): void;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=lite.d.ts.map
|