optolink-bridge 1.1.1 → 1.2.0
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/CHANGELOG.md +8 -0
- package/config.toml +4 -0
- package/index.js +32 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
This file documents all *major & minor* releases. For revisions, please consult the [commit history](https://github.com/kristian/optolink-bridge/commits/main).
|
|
4
4
|
|
|
5
|
+
## [1.2] - 2026-01-08
|
|
6
|
+
|
|
7
|
+
Introduce a `publish_bus_state` MQTT option
|
|
8
|
+
|
|
9
|
+
## [1.1] - 2025-12-17
|
|
10
|
+
|
|
11
|
+
Major dependencies bump & allow Vitoconnect to reset the synchronization
|
|
12
|
+
|
|
5
13
|
## [1.0] - 2025-02-26
|
|
6
14
|
|
|
7
15
|
Initial release
|
package/config.toml
CHANGED
|
@@ -150,6 +150,10 @@ suffix = "<dpname>"
|
|
|
150
150
|
# note: if set to false, home assistant will not be able to determine if the devices / entities are available
|
|
151
151
|
online = true
|
|
152
152
|
|
|
153
|
+
# publish a "bus_state" topic, e.g. Vito/bus_state, indicating the current state of the optolink bus. defaults to true /
|
|
154
|
+
# "bus_state", set to a string to use a different topic. possible bus states are: 0: syncing, 1: synced, 2: flowing
|
|
155
|
+
publish_bus_state = true
|
|
156
|
+
|
|
153
157
|
# publish unknown data points to MQTT as raw data
|
|
154
158
|
publish_unknown_dps = false
|
|
155
159
|
# the suffix to use to publish unknown data points, defaults to "raw/<addr>"
|
package/index.js
CHANGED
|
@@ -12,6 +12,17 @@ import { publishDevice } from './discovery.js';
|
|
|
12
12
|
let logLevel, trace, logger = {};
|
|
13
13
|
let dps, pollQueue = new Queue(), pollIntervals;
|
|
14
14
|
let busState = 0; // 0: syncing, 1: synced, 2: flowing
|
|
15
|
+
let afterBusStateUpdate = async (newState, oldState) => {};
|
|
16
|
+
async function updateBusState(state) {
|
|
17
|
+
const oldState = busState; busState = state;
|
|
18
|
+
if (typeof afterBusStateUpdate === 'function') {
|
|
19
|
+
try {
|
|
20
|
+
await afterBusStateUpdate(state, oldState);
|
|
21
|
+
} catch {
|
|
22
|
+
// ignore errors
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
15
26
|
let deviceSerialNo = undefined, deviceDiscoveryOptions = { enabled: true }, deviceDiscovery;
|
|
16
27
|
|
|
17
28
|
async function applyConfig(config) {
|
|
@@ -113,10 +124,23 @@ deviceDiscovery = async function(options = (deviceDiscoveryOptions ?? { enabled:
|
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
if (config.mqtt && config.mqtt.url) {
|
|
116
|
-
config.mqtt.online ??= true; // if not set, use
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
config.mqtt.online ??= true; // if not set, use topic "online"
|
|
128
|
+
config.mqtt.publish_bus_state ??= true; // if not set, use topic "bus_state"
|
|
129
|
+
|
|
130
|
+
mqttTopic = config.mqtt.topic ?? 'Vito';
|
|
131
|
+
function prefixMqttTopic(topic, defaultTopic) {
|
|
132
|
+
return `${mqttTopic}${mqttTopic.endsWith('/') || topic?.startsWith?.('/') ? '' : '/'}${
|
|
133
|
+
typeof topic === 'string' ? topic : defaultTopic}`;
|
|
134
|
+
}
|
|
135
|
+
mqttAvailabilityTopic = prefixMqttTopic(config.mqtt.online, 'online');
|
|
136
|
+
|
|
137
|
+
if (config.mqtt.publish_bus_state) {
|
|
138
|
+
const mqttBusStateTopic = prefixMqttTopic(config.mqtt.publish_bus_state, 'bus_state');
|
|
139
|
+
afterBusStateUpdate = async state => {
|
|
140
|
+
await mqttClient.publishAsync(
|
|
141
|
+
mqttBusStateTopic, `${state}`);
|
|
142
|
+
};
|
|
143
|
+
}
|
|
120
144
|
|
|
121
145
|
const mqttOptions = {
|
|
122
146
|
username: config.mqtt.username,
|
|
@@ -150,17 +174,17 @@ const packetQueue = async.queue(async task => {
|
|
|
150
174
|
trace && console.log(dateTimeString(), directionName(task.direction), (task.data ?? encodePacket(task.packet, task.direction & fromOpto)).toString('hex'));
|
|
151
175
|
|
|
152
176
|
const packet = task.packet ?? parsePacket(task.data, task.direction & fromOpto);
|
|
153
|
-
if (packet.rest) {
|
|
177
|
+
if (packet.rest?.length) {
|
|
154
178
|
// if there is any rest, two packets have been sent in the same direction, so unshift the rest as the next packet to the queue
|
|
155
179
|
packetQueue.unshift({ data: packet.rest, direction: task.direction });
|
|
156
180
|
}
|
|
157
181
|
|
|
158
182
|
if (task.direction === fromVitoToOpto && packet.start === 0x04) {
|
|
159
|
-
|
|
183
|
+
await updateBusState(0); // reset synchronization
|
|
160
184
|
} else if (busState === 0 && task.direction & toOpto && packet.start === 0x16 && 'zero' in packet) {
|
|
161
|
-
|
|
185
|
+
await updateBusState(1);
|
|
162
186
|
} else if (busState === 1 && task.direction & fromOpto && packet.res === 0x06 && !packet.peek?.length) {
|
|
163
|
-
|
|
187
|
+
await updateBusState(2);
|
|
164
188
|
|
|
165
189
|
logger.info('Synchronization completed. Streams are now flowing');
|
|
166
190
|
}
|
package/package.json
CHANGED