Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ The adapter expects `HannahService.AgentConnect` to be available on the configur
Placeholder for the next version (at the beginning of the line):
### **WORK IN PROGRESS**
-->
### **WORK IN PROGRESS**
- Changed: updated to hannah-proto 3.2.0 — the gRPC connection now also sends a per-message compatibility marker alongside the existing protocol-version check, so future breaking changes elsewhere in the protocol won't unnecessarily disconnect this adapter
- Fixed: satellite-related types (`Satellite`, `GetSatellitesResponse`, `SetSatelliteDisplayNameRequest`) moved to their own module in a prior hannah-proto release — this adapter hadn't picked that up yet, which would have broken the build against any hannah-proto newer than 2.x

### 1.0.1 (2026-08-06)
- Fixed: the per-satellite do-not-disturb state stayed unconfirmed (`ack:false`) forever after a write — no way to tell whether it actually took effect. Now confirmed with `ack:true`, matching mute/volume

Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@grpc/grpc-js": "^1.14.4",
"@iobroker/adapter-core": "^3.4.3",
"@iobroker/dm-utils": "^3.2.0",
"@m1kad0/hannah-proto": "^2.1.0",
"@m1kad0/hannah-proto": "^3.2.0",
"adm-zip": "^0.6.0"
},
"devDependencies": {
Expand Down
16 changes: 10 additions & 6 deletions src/grpc-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as grpc from '@grpc/grpc-js';
import { PROTO_VERSION, agent, hannah } from '@m1kad0/hannah-proto';
import type { control, shared, satellite_provisioning, user_registry } from '@m1kad0/hannah-proto';
import { PROTO_VERSION, agent, hannah, compat_interceptor } from '@m1kad0/hannah-proto';
import type { control, satellite, shared, satellite_provisioning, user_registry } from '@m1kad0/hannah-proto';

/**
* Haengt die PROTO_VERSION der installierten hannah-proto npm-Version als `x-proto-version`-Metadata
Expand Down Expand Up @@ -100,8 +100,12 @@ export class GrpcClient {

const addr = `${host}:${port}`;
this.log.info(`[grpc] Connecting to Hannah Core: ${addr}`);
// compat_interceptor (hannah-proto#9/hannah#217) laeuft additiv neben
// protocolVersionInterceptor, nicht als Ersatz — ein Breaking Change,
// der auf eine Message begrenzt ist, muss nicht mehr jeden Client
// ablehnen, sondern nur Calls, die diese Message tatsaechlich nutzen.
this.client = new hannah.HannahServiceClient(addr, grpc.credentials.createInsecure(), {
interceptors: [protocolVersionInterceptor],
interceptors: [protocolVersionInterceptor, compat_interceptor.compatVersionInterceptor],
});
this.stream = this.client.agentConnect();

Expand Down Expand Up @@ -151,13 +155,13 @@ export class GrpcClient {
* back to an empty array — conflating the two previously caused every satellite object to
* be deleted as "stale" whenever Core was merely unreachable (Refs #<issue>).
*/
getSatellites(): Promise<control.Satellite[] | null> {
getSatellites(): Promise<satellite.Satellite[] | null> {
return new Promise(resolve => {
if (!this.client) {
resolve(null);
return;
}
this.client.getSatellites({}, (err: Error | null, response?: control.GetSatellitesResponse) => {
this.client.getSatellites({}, (err: Error | null, response?: satellite.GetSatellitesResponse) => {
if (err || !response) {
this.log.warn(`[grpc] GetSatellites failed: ${err?.message ?? 'no response'}`);
resolve(null);
Expand Down Expand Up @@ -213,7 +217,7 @@ export class GrpcClient {
return;
}
const timer = this._setTimeout(() => reject(new Error('timeout')), 5000);
const request: control.SetSatelliteDisplayNameRequest = { deviceId, displayName, requestorId };
const request: satellite.SetSatelliteDisplayNameRequest = { deviceId, displayName, requestorId };
this.client.setSatelliteDisplayName(request, (err: Error | null, response?: shared.StatusResponse) => {
this._clearTimeout(timer);
if (err || !response) {
Expand Down
4 changes: 2 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as utils from '@iobroker/adapter-core';
import type { agent, control } from '@m1kad0/hannah-proto';
import type { agent, satellite } from '@m1kad0/hannah-proto';
import { GrpcClient } from './grpc-client';
import { StateWatcher } from './state-watcher';
import { ResidentsWatcher } from './residents';
Expand Down Expand Up @@ -149,7 +149,7 @@ class Hannah extends utils.Adapter {
this.log.warn('[satellites] GetSatellites unavailable — skipping satellite sync this cycle.');
return;
}
const effectiveRoom = (sat: control.Satellite): string =>
const effectiveRoom = (sat: satellite.Satellite): string =>
sat.connected ? sat.room : sat.roomDisplayName || sat.roomId || '';
for (const sat of sats) {
await this.satellites!.handleSatelliteUpdate(
Expand Down