diff --git a/src/adapter/zboss/adapter/zbossAdapter.ts b/src/adapter/zboss/adapter/zbossAdapter.ts index ef42201e99..087e13638d 100644 --- a/src/adapter/zboss/adapter/zbossAdapter.ts +++ b/src/adapter/zboss/adapter/zbossAdapter.ts @@ -426,8 +426,13 @@ export class ZBOSSAdapter extends Adapter { } public async sendZclFrameToGroup(groupID: number, zclFrame: Zcl.Frame, sourceEndpoint?: number): Promise { - logger.error(() => `NOT SUPPORTED: sendZclFrameToGroup(${groupID},${JSON.stringify(zclFrame)},${sourceEndpoint})`, NS); - return; + await this.driver.grequest( + groupID, + sourceEndpoint === ZSpec.GP_ENDPOINT ? ZSpec.GP_PROFILE_ID : ZSpec.HA_PROFILE_ID, + zclFrame.cluster.ID, + sourceEndpoint || 0x01, + zclFrame.toBuffer(), + ); } public async sendZclFrameToAll( @@ -436,8 +441,14 @@ export class ZBOSSAdapter extends Adapter { sourceEndpoint: number, destination: ZSpec.BroadcastAddress, ): Promise { - logger.error(() => `NOT SUPPORTED: sendZclFrameToAll(${endpoint},${JSON.stringify(zclFrame)},${sourceEndpoint},${destination})`, NS); - return; + await this.driver.brequest( + destination, + sourceEndpoint === ZSpec.GP_ENDPOINT && endpoint === ZSpec.GP_ENDPOINT ? ZSpec.GP_PROFILE_ID : ZSpec.HA_PROFILE_ID, + zclFrame.cluster.ID, + endpoint, + sourceEndpoint || 0x01, + zclFrame.toBuffer(), + ); } public async setChannelInterPAN(channel: number): Promise { diff --git a/src/adapter/zboss/commands.ts b/src/adapter/zboss/commands.ts index 044575265c..8cd68be071 100644 --- a/src/adapter/zboss/commands.ts +++ b/src/adapter/zboss/commands.ts @@ -689,11 +689,11 @@ export const FRAMES: {[key in CommandId]?: ZBOSSFrameDesc} = { request: [ {name: 'paramLength', type: DataType.UINT8}, {name: 'dataLength', type: DataType.UINT16}, - {name: 'ieee', type: DataType.IEEE_ADDR}, + {name: 'addr', type: DataType.IEEE_ADDR}, {name: 'profileID', type: DataType.UINT16}, {name: 'clusterID', type: DataType.UINT16}, - //{name: 'dstEndpoint', type: DataType.UINT8, condition: (payload) => ![2,3].includes(payload.dstAddrMode)}, - {name: 'dstEndpoint', type: DataType.UINT8}, + {name: 'dstEndpoint', type: DataType.UINT8, condition: (payload) => [2, 3].includes(payload.dstAddrMode)}, + //{name: 'dstEndpoint', type: DataType.UINT8}, {name: 'srcEndpoint', type: DataType.UINT8}, {name: 'radius', type: DataType.UINT8}, {name: 'dstAddrMode', type: DataType.UINT8}, @@ -707,7 +707,7 @@ export const FRAMES: {[key in CommandId]?: ZBOSSFrameDesc} = { response: [ ...commonResponse, {name: 'ieee', type: DataType.IEEE_ADDR}, - {name: 'dstEndpoint', type: DataType.UINT8, condition: (payload) => ![2, 3].includes(payload.dstAddrMode)}, + {name: 'dstEndpoint', type: DataType.UINT8, condition: (payload) => [2, 3].includes(payload.dstAddrMode)}, {name: 'srcEndpoint', type: DataType.UINT8}, {name: 'txTime', type: DataType.UINT32}, {name: 'dstAddrMode', type: DataType.UINT8}, diff --git a/src/adapter/zboss/driver.ts b/src/adapter/zboss/driver.ts index 7d081107b5..8044815c5e 100644 --- a/src/adapter/zboss/driver.ts +++ b/src/adapter/zboss/driver.ts @@ -9,6 +9,7 @@ import {TsType} from '..'; import {KeyValue} from '../../controller/tstype'; import {Queue, Waitress} from '../../utils'; import {logger} from '../../utils/logger'; +import * as ZSpec from '../../zspec'; import * as Zdo from '../../zspec/zdo'; import {ZDO_REQ_CLUSTER_ID_TO_ZBOSS_COMMAND_ID} from './commands'; import {CommandId, DeviceType, PolicyType, ResetOptions, StatusCodeGeneric} from './enums'; @@ -305,7 +306,7 @@ export class ZBOSSDriver extends EventEmitter { const payload = { paramLength: 21, dataLength: data.length, - ieee: ieee, + addr: ieee, profileID: profileID, clusterID: clusterID, dstEndpoint: dstEp, @@ -321,6 +322,52 @@ export class ZBOSSDriver extends EventEmitter { return await this.execCommand(CommandId.APSDE_DATA_REQ, payload); } + public async brequest( + addr: ZSpec.BroadcastAddress, + profileID: number, + clusterID: number, + dstEp: number, + srcEp: number, + data: Buffer, + ): Promise { + const payload = { + paramLength: 21, + dataLength: data.length, + addr: `0x${addr.toString(16).padStart(16, '0')}`, + profileID: profileID, + clusterID: clusterID, + dstEndpoint: dstEp, + srcEndpoint: srcEp, + radius: 3, + dstAddrMode: 2, // ADDRESS MODE broadcast + txOptions: 2, // ROUTE DISCOVERY + useAlias: 0, + aliasAddr: 0, + aliasSequence: 0, + data: data, + }; + return await this.execCommand(CommandId.APSDE_DATA_REQ, payload); + } + + public async grequest(group: number, profileID: number, clusterID: number, srcEp: number, data: Buffer): Promise { + const payload = { + paramLength: 20, + dataLength: data.length, + addr: `0x${group.toString(16).padStart(16, '0')}`, + profileID: profileID, + clusterID: clusterID, + srcEndpoint: srcEp, + radius: 3, + dstAddrMode: 1, // ADDRESS MODE group + txOptions: 2, // ROUTE DISCOVERY + useAlias: 0, + aliasAddr: 0, + aliasSequence: 0, + data: data, + }; + return await this.execCommand(CommandId.APSDE_DATA_REQ, payload); + } + public async requestZdo(clusterId: Zdo.ClusterId, payload: Buffer, disableResponse: boolean): Promise { if (!this.port.portOpen) { throw new Error('Connection not initialized'); diff --git a/src/adapter/zboss/frame.ts b/src/adapter/zboss/frame.ts index b44e5b7b76..aafc154993 100644 --- a/src/adapter/zboss/frame.ts +++ b/src/adapter/zboss/frame.ts @@ -200,7 +200,7 @@ export function makeFrame(type: FrameType, commandId: CommandId, params: KeyValu for (const parameter of frameDesc) { // const options: BuffaloZclOptions = {payload}; - if (parameter.condition && !parameter.condition(payload, undefined)) { + if (parameter.condition && !parameter.condition(params, undefined)) { continue; }