Skip to content

Commit

Permalink
Merge pull request #41 from Luligu/dev
Browse files Browse the repository at this point in the history
Fix dockerfile
  • Loading branch information
Luligu authored Jun 4, 2024
2 parents 1a9d096 + 9c80df1 commit 609c1fb
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 24 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,11 @@ docker logs --tail 1000 -f matterbridge

# Known issues

## Session XYZ does not exist
This message may appear after Matterbridge restarts, indicating that the controller is still using a session from the previous connection that has since been closed.
After some time, it will reconnect.
In this context, the message is not indicative of a problem.

## Apple Home issues

The HomePods, being a WiFi devices, sometimes pruduce message trasmission errors. The Apple TV with network cable is more reliable (but also more expensive).
Expand Down
7 changes: 4 additions & 3 deletions docker/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ FROM node:20-bullseye-slim as base
WORKDIR /app
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git && \
apt-get clean && \
npm install -g npm@10.7.0
apt-get clean

# && npm install -g npm@10.7.0

FROM base as builder
WORKDIR /app
Expand Down Expand Up @@ -78,4 +79,4 @@ COPY --from=builder /matterbridge-eve-weather/*.tgz .
RUN npm -g install *.tgz
RUN rm *.tgz

CMD ["matterbridge", "-bridge", "-docker", "-frontend", "8283"]
CMD ["matterbridge", "-bridge", "-docker"]
4 changes: 2 additions & 2 deletions docker/Dockerfile.main
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:20-bullseye-slim as base
WORKDIR /app
RUN npm install -g npm@10.7.0
# RUN npm install -g npm@10.7.0


FROM base as builder
Expand Down Expand Up @@ -32,4 +32,4 @@ RUN npm -g install matterbridge-eve-room
RUN npm -g install matterbridge-eve-weather

WORKDIR /app
CMD ["matterbridge", "-bridge", "-docker", "-frontend", "8283"]
CMD ["matterbridge", "-bridge", "-docker"]
6 changes: 4 additions & 2 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 @@ -99,4 +99,4 @@
"node-persist-manager": "^1.0.7",
"ws": "^8.17.0"
}
}
}
21 changes: 20 additions & 1 deletion src/matterbridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { requireMinNodeVersion, getParameter, getIntParameter, hasParameter } fr
import { CryptoNode } from '@project-chip/matter-node.js/crypto';
import { CommissioningOptions } from '@project-chip/matter-node.js/protocol';
import { shelly_config, shelly_schema, somfytahoma_config, somfytahoma_schema, zigbee2mqtt_config, zigbee2mqtt_schema } from './defaultConfigSchema.js';
import { ExposedFabricInformation } from '@project-chip/matter-node.js/fabric';

// Define an interface of common elements from MatterbridgeDynamicPlatform and MatterbridgeAccessoryPlatform
interface MatterbridgePlatform {
Expand Down Expand Up @@ -99,6 +100,7 @@ interface BaseRegisteredPlugin {
configured?: boolean;
paired?: boolean;
connected?: boolean;
fabricInfo?: ExposedFabricInformation[];
registeredDevices?: number;
addedDevices?: number;
qrPairingCode?: string;
Expand Down Expand Up @@ -188,6 +190,9 @@ export class Matterbridge extends EventEmitter {
public globalModulesDirectory = '';
public matterbridgeVersion = '';
public matterbridgeLatestVersion = '';
public matterbridgeFabricInfo: ExposedFabricInformation[] = [];
public matterbridgePaired = false;
public matterbridgeConnected = false;
private checkUpdateInterval?: NodeJS.Timeout; // = 24 * 60 * 60 * 1000; // 24 hours

public bridgeMode: 'bridge' | 'childbridge' | 'controller' | '' = '';
Expand Down Expand Up @@ -2037,9 +2042,14 @@ export class Matterbridge extends EventEmitter {
fabricInfo?.forEach((info) => {
this.log.info(`- fabric index ${zb}${info.fabricIndex}${nf} id ${zb}${info.fabricId}${nf} vendor ${zb}${info.rootVendorId}${nf} ${this.getVendorIdName(info.rootVendorId)} ${info.label}`);
});
if (pluginName === 'Matterbridge') {
this.matterbridgeFabricInfo = fabricInfo;
this.matterbridgePaired = true;
}
if (pluginName !== 'Matterbridge') {
const plugin = this.findPlugin(pluginName);
if (plugin) {
plugin.fabricInfo = fabricInfo;
plugin.paired = true;
}
}
Expand Down Expand Up @@ -2205,6 +2215,10 @@ export class Matterbridge extends EventEmitter {
}
});
if (connected) {
if (this.bridgeMode === 'bridge') {
this.matterbridgePaired = true;
this.matterbridgeConnected = true;
}
if (this.bridgeMode === 'childbridge') {
const plugin = this.findPlugin(pluginName);
if (plugin) {
Expand Down Expand Up @@ -2250,10 +2264,14 @@ export class Matterbridge extends EventEmitter {
await commissioningServer.factoryReset();
if (pluginName === 'Matterbridge') {
await this.matterbridgeContext?.clearAll();
this.matterbridgeFabricInfo = [];
this.matterbridgePaired = false;
this.matterbridgeConnected = false;
} else {
for (const plugin of this.registeredPlugins) {
if (plugin.name === pluginName) {
await plugin.platform?.onShutdown('Commissioning removed by the controller');
plugin.fabricInfo = [];
plugin.paired = false;
plugin.connected = false;
await plugin.storageContext?.clearAll();
Expand Down Expand Up @@ -2663,7 +2681,7 @@ export class Matterbridge extends EventEmitter {
* Retrieves an array of base registered devices from the registered plugins.
* @returns {BaseRegisteredPlugin[]} An array of base registered devices.
*/
private getBaseRegisteredDevices() {
private getBaseRegisteredDevices(): BaseRegisteredPlugin[] {
const baseRegisteredPlugins: BaseRegisteredPlugin[] = this.registeredPlugins.map((plugin) => ({
path: plugin.path,
type: plugin.type,
Expand All @@ -2676,6 +2694,7 @@ export class Matterbridge extends EventEmitter {
started: plugin.started,
paired: plugin.paired,
connected: plugin.connected,
fabricInfo: plugin.fabricInfo,
registeredDevices: plugin.registeredDevices,
}));
return baseRegisteredPlugins;
Expand Down
71 changes: 56 additions & 15 deletions src/matterbridgeV8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ import { QrCode } from '@project-chip/matter-node.js/schema';
import { FabricAction } from '@project-chip/matter-node.js/fabric';
import { AggregatorEndpoint } from '@project-chip/matter.js/endpoints/AggregatorEndpoint';
import { BridgedNodeEndpoint } from '@project-chip/matter.js/endpoints/BridgedNodeEndpoint';
import { BridgedDeviceBasicInformationServer } from '@project-chip/matter.js/behavior/definitions/bridged-device-basic-information';
import { OnOffServer } from '@project-chip/matter.js/behavior/definitions/on-off';
import { ColorDimmerSwitchDevice } from '@project-chip/matter.js/devices/ColorDimmerSwitchDevice';

import { AnsiLogger, BRIGHT, RESET, TimestampFormat, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, er, nf, rs, wr, RED, GREEN, zb, CYAN } from 'node-ansi-logger';

import EventEmitter from 'events';
import path from 'path';
import { promises as fs } from 'fs';
import { MatterbridgeDeviceV8 } from './matterbridgeDeviceV8.js';
import { BasicInformationCluster } from '@project-chip/matter-node.js/cluster';

/**
* Represents the Matterbridge application.
Expand Down Expand Up @@ -98,6 +102,8 @@ export class MatterbridgeV8 extends EventEmitter {
this.environment.vars.set('log.level', level);
this.environment.vars.set('log.format', format);
this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, 'matterstorage'));
this.environment.vars.set('runtime.signals', false);
this.environment.vars.set('runtime.exitcode', false);
}

private async setupMatterStorage() {
Expand Down Expand Up @@ -152,7 +158,7 @@ export class MatterbridgeV8 extends EventEmitter {
}
log.debug(`Creating commissioning server storage context for ${pluginName}...`);
const storageContext = this.matterStorageManager.createContext('persist');
const random = 'CS' + CryptoNode.getRandomData(8).toHex();
const random = 'AG' + CryptoNode.getRandomData(8).toHex();
await storageContext.set('storeId', pluginName);
await storageContext.set('deviceName', deviceName);
await storageContext.set('deviceType', deviceType);
Expand Down Expand Up @@ -243,29 +249,62 @@ export class MatterbridgeV8 extends EventEmitter {
* In this case we directly use the default command implementation from matter.js. Check out the DeviceNodeFull example
* to see how to customize the command handlers.
*/
const endpoint = new Endpoint(OnOffLightDevice, { id: 'onoff' });
// await this.matterServerNode.add(endpoint);
// const mbV8 = new MatterbridgeDeviceV8(DeviceTypes.OnOffLight);
// const endpoint = mbV8.getBridgedNodeEndpointV8();

const aggregator = new Endpoint(AggregatorEndpoint, { id: 'aggregator' });
const lightEndpoint = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {
id: 'OnOffLight',
bridgedDeviceBasicInformation: {
vendorId: VendorId(await this.matterStorageContext.get<number>('vendorId')),
vendorName: await this.matterStorageContext.get<string>('vendorName'),

await this.matterServerNode.add(aggregator);
productName: 'Light',
productLabel: 'Light',
nodeLabel: 'Light',

await aggregator.add(endpoint);
serialNumber: '0x123456789',
uniqueId: '0x123456789',
reachable: true,
},
});
console.log('lightEndpoint', lightEndpoint);

/**
* Register state change handlers and events of the node for identify and onoff states to react to the commands.
* If the code in these change handlers fail then the change is also rolled back and not executed and an error is
* reported back to the controller.
*/
/*
endpoint.events.identify.startIdentifying.on(() => log.notice('Run identify logic, ideally blink a light every 0.5s ...'));
lightEndpoint.events.identify.startIdentifying.on(() => log.notice('Run identify logic, ideally blink a light every 0.5s ...'));

lightEndpoint.events.identify.stopIdentifying.on(() => log.notice('Stop identify logic ...'));

endpoint.events.identify.stopIdentifying.on(() => log.notice('Stop identify logic ...'));
lightEndpoint.events.onOff.onOff$Changed.on((value) => log.notice(`OnOff is now ${value ? 'ON' : 'OFF'}`));

const switchEndpoint = new Endpoint(ColorDimmerSwitchDevice.with(BridgedDeviceBasicInformationServer, OnOffServer), {
id: 'OnOffSwitch',
bridgedDeviceBasicInformation: {
vendorId: VendorId(await this.matterStorageContext.get<number>('vendorId')),
vendorName: await this.matterStorageContext.get<string>('vendorName'),

productName: 'Switch',
productLabel: 'Switch',
nodeLabel: 'Switch',

serialNumber: '0x123456789S',
uniqueId: '0x123456789S',
reachable: true,
},
});

console.log('switchEndpoint', switchEndpoint);

// await this.matterServerNode.add(endpoint);
// const mbV8 = new MatterbridgeDeviceV8(DeviceTypes.OnOffLight);
// const endpoint = mbV8.getBridgedNodeEndpointV8();

const aggregator = new Endpoint(AggregatorEndpoint, { id: 'aggregator' });

await this.matterServerNode.add(aggregator);

endpoint.events.onOff.onOff$Changed.on((value) => log.notice(`OnOff is now ${value ? 'ON' : 'OFF'}`));
*/
await aggregator.add(lightEndpoint);
await aggregator.add(switchEndpoint);

/**
* Log the endpoint structure for debugging reasons and to allow to verify anything is correct
Expand Down Expand Up @@ -326,6 +365,8 @@ export class MatterbridgeV8 extends EventEmitter {
});

await this.matterServerNode.bringOnline();
console.log('lightEndpoint', lightEndpoint);
console.log('switchEndpoint', switchEndpoint);
}

showServerNodeQR() {
Expand Down Expand Up @@ -361,6 +402,6 @@ if (process.argv.includes('MatterbridgeV8')) {
process.on('SIGINT', async function () {
console.log('Caught interrupt signal');
await matterbridge.stopServerNode();
// process.exit();
process.exit();
});
}

0 comments on commit 609c1fb

Please sign in to comment.