Skip to content

Commit

Permalink
Revert "3.0.0"
Browse files Browse the repository at this point in the history
  • Loading branch information
Koenkk authored Dec 1, 2024
1 parent 2a3f28a commit fe3e4bb
Show file tree
Hide file tree
Showing 36 changed files with 1,350 additions and 2,211 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"clean": "rimraf temp coverage dist",
"prepack": "pnpm run clean && pnpm run build"
},
"version": "3.0.0-pre.1",
"version": "2.1.9",
"jest": {
"coverageThreshold": {
"global": {
Expand Down
126 changes: 118 additions & 8 deletions src/adapter/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import events from 'events';

import Bonjour, {Service} from 'bonjour-service';

import * as Models from '../models';
import {logger} from '../utils/logger';
import {BroadcastAddress} from '../zspec/enums';
import * as Zcl from '../zspec/zcl';
import * as Zdo from '../zspec/zdo';
import * as ZdoTypes from '../zspec/zdo/definition/tstypes';
import {discoverAdapter} from './adapterDiscovery';
import * as AdapterEvents from './events';
import * as TsType from './tstype';

const NS = 'zh:adapter';

interface AdapterEventMap {
deviceJoined: [payload: AdapterEvents.DeviceJoinedPayload];
zclPayload: [payload: AdapterEvents.ZclPayload];
Expand Down Expand Up @@ -56,6 +60,15 @@ abstract class Adapter extends events.EventEmitter<AdapterEventMap> {
const {EZSPAdapter} = await import('./ezsp/adapter');
const {EmberAdapter} = await import('./ember/adapter');
const {ZBOSSAdapter} = await import('./zboss/adapter');
type AdapterImplementation =
| typeof ZStackAdapter
| typeof DeconzAdapter
| typeof ZiGateAdapter
| typeof EZSPAdapter
| typeof EmberAdapter
| typeof ZBOSSAdapter;

let adapters: AdapterImplementation[];
const adapterLookup = {
zstack: ZStackAdapter,
deconz: DeconzAdapter,
Expand All @@ -65,16 +78,111 @@ abstract class Adapter extends events.EventEmitter<AdapterEventMap> {
zboss: ZBOSSAdapter,
};

const [adapter, path] = await discoverAdapter(serialPortOptions.adapter, serialPortOptions.path);

if (adapterLookup[adapter]) {
serialPortOptions.adapter = adapter;
serialPortOptions.path = path;
if (serialPortOptions.adapter && serialPortOptions.adapter !== 'auto') {
if (adapterLookup[serialPortOptions.adapter]) {
adapters = [adapterLookup[serialPortOptions.adapter]];
} else {
throw new Error(`Adapter '${serialPortOptions.adapter}' does not exists, possible options: ${Object.keys(adapterLookup).join(', ')}`);
}
} else {
adapters = Object.values(adapterLookup);
}

return new adapterLookup[adapter](networkOptions, serialPortOptions, backupPath, adapterOptions);
// Use ZStackAdapter by default
let adapter: AdapterImplementation = adapters[0];

if (!serialPortOptions.path) {
logger.debug('No path provided, auto detecting path', NS);
for (const candidate of adapters) {
const path = await candidate.autoDetectPath();
if (path) {
logger.debug(`Auto detected path '${path}' from adapter '${candidate.name}'`, NS);
serialPortOptions.path = path;
adapter = candidate;
break;
}
}

if (!serialPortOptions.path) {
throw new Error('No path provided and failed to auto detect path');
}
} else if (serialPortOptions.path.startsWith('mdns://')) {
const mdnsDevice = serialPortOptions.path.substring(7);

if (mdnsDevice.length == 0) {
throw new Error(`No mdns device specified. You must specify the coordinator mdns service type after mdns://, e.g. mdns://my-adapter`);
}

const bj = new Bonjour();
const mdnsTimeout = 2000; // timeout for mdns scan

logger.info(`Starting mdns discovery for coordinator: ${mdnsDevice}`, NS);

await new Promise((resolve, reject) => {
bj.findOne({type: mdnsDevice}, mdnsTimeout, function (service: Service) {
if (service) {
if (service.txt?.radio_type && service.txt?.baud_rate && service.addresses && service.port) {
const mdnsIp = service.addresses[0];
const mdnsPort = service.port;
const mdnsAdapter = (
service.txt.radio_type == 'znp' ? 'zstack' : service.txt.radio_type
) as TsType.SerialPortOptions['adapter'];
const mdnsBaud = parseInt(service.txt.baud_rate);

logger.info(`Coordinator Ip: ${mdnsIp}`, NS);
logger.info(`Coordinator Port: ${mdnsPort}`, NS);
logger.info(`Coordinator Radio: ${mdnsAdapter}`, NS);
logger.info(`Coordinator Baud: ${mdnsBaud}\n`, NS);
bj.destroy();

serialPortOptions.path = `tcp://${mdnsIp}:${mdnsPort}`;
serialPortOptions.adapter = mdnsAdapter;
serialPortOptions.baudRate = mdnsBaud;

if (
serialPortOptions.adapter &&
serialPortOptions.adapter !== 'auto' &&
adapterLookup[serialPortOptions.adapter] !== undefined
) {
adapter = adapterLookup[serialPortOptions.adapter];
resolve(new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions));
} else {
reject(new Error(`Adapter ${serialPortOptions.adapter} is not supported.`));
}
} else {
bj.destroy();
reject(
new Error(
`Coordinator returned wrong Zeroconf format! The following values are expected:\n` +
`txt.radio_type, got: ${service.txt?.radio_type}\n` +
`txt.baud_rate, got: ${service.txt?.baud_rate}\n` +
`address, got: ${service.addresses?.[0]}\n` +
`port, got: ${service.port}`,
),
);
}
} else {
bj.destroy();
reject(new Error(`Coordinator [${mdnsDevice}] not found after timeout of ${mdnsTimeout}ms!`));
}
});
});
} else {
throw new Error(`Adapter '${adapter}' does not exists, possible options: ${Object.keys(adapterLookup).join(', ')}`);
try {
// Determine adapter to use
for (const candidate of adapters) {
if (await candidate.isValidPath(serialPortOptions.path)) {
logger.debug(`Path '${serialPortOptions.path}' is valid for '${candidate.name}'`, NS);
adapter = candidate;
break;
}
}
} catch (error) {
logger.debug(`Failed to validate path: '${error}'`, NS);
}
}

return new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
}

public abstract start(): Promise<TsType.StartResult>;
Expand All @@ -93,6 +201,8 @@ abstract class Adapter extends events.EventEmitter<AdapterEventMap> {

public abstract getNetworkParameters(): Promise<TsType.NetworkParameters>;

public abstract setTransmitPower(value: number): Promise<void>;

public abstract addInstallCode(ieeeAddress: string, key: Buffer): Promise<void>;

public abstract waitFor(
Expand Down
Loading

0 comments on commit fe3e4bb

Please sign in to comment.