zigbee-herdsman 6.0.0 → 6.0.2

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.
Files changed (96) hide show
  1. package/.github/workflows/ci.yml +10 -5
  2. package/.github/workflows/typedoc.yaml +2 -2
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +19 -0
  5. package/biome.json +1 -1
  6. package/dist/adapter/ezsp/driver/uart.js +1 -1
  7. package/dist/adapter/ezsp/driver/uart.js.map +1 -1
  8. package/dist/adapter/z-stack/adapter/zStackAdapter.js +4 -4
  9. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
  10. package/dist/adapter/zigate/adapter/zigateAdapter.js +4 -4
  11. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
  12. package/dist/controller/controller.d.ts.map +1 -1
  13. package/dist/controller/controller.js +7 -10
  14. package/dist/controller/controller.js.map +1 -1
  15. package/dist/controller/events.d.ts +1 -1
  16. package/dist/controller/events.d.ts.map +1 -1
  17. package/dist/controller/helpers/request.d.ts.map +1 -1
  18. package/dist/controller/helpers/request.js +2 -1
  19. package/dist/controller/helpers/request.js.map +1 -1
  20. package/dist/controller/helpers/zclFrameConverter.d.ts +2 -4
  21. package/dist/controller/helpers/zclFrameConverter.d.ts.map +1 -1
  22. package/dist/controller/helpers/zclFrameConverter.js +2 -0
  23. package/dist/controller/helpers/zclFrameConverter.js.map +1 -1
  24. package/dist/controller/model/device.d.ts +13 -24
  25. package/dist/controller/model/device.d.ts.map +1 -1
  26. package/dist/controller/model/device.js +89 -129
  27. package/dist/controller/model/device.js.map +1 -1
  28. package/dist/controller/model/endpoint.d.ts +17 -16
  29. package/dist/controller/model/endpoint.d.ts.map +1 -1
  30. package/dist/controller/model/endpoint.js +31 -16
  31. package/dist/controller/model/endpoint.js.map +1 -1
  32. package/dist/controller/model/group.d.ts +6 -6
  33. package/dist/controller/model/group.d.ts.map +1 -1
  34. package/dist/controller/model/group.js +5 -3
  35. package/dist/controller/model/group.js.map +1 -1
  36. package/dist/controller/model/index.d.ts +1 -0
  37. package/dist/controller/model/index.d.ts.map +1 -1
  38. package/dist/controller/model/index.js +3 -1
  39. package/dist/controller/model/index.js.map +1 -1
  40. package/dist/controller/model/zigbeeEntity.d.ts +8 -0
  41. package/dist/controller/model/zigbeeEntity.d.ts.map +1 -0
  42. package/dist/controller/model/zigbeeEntity.js +11 -0
  43. package/dist/controller/model/zigbeeEntity.js.map +1 -0
  44. package/dist/controller/tstype.d.ts +22 -0
  45. package/dist/controller/tstype.d.ts.map +1 -1
  46. package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
  47. package/dist/zspec/zcl/definition/cluster.js +2 -9
  48. package/dist/zspec/zcl/definition/cluster.js.map +1 -1
  49. package/dist/zspec/zcl/definition/clusters-typegen.js +61 -13
  50. package/dist/zspec/zcl/definition/clusters-typegen.js.map +1 -1
  51. package/dist/zspec/zcl/definition/clusters-types.d.ts +173 -140
  52. package/dist/zspec/zcl/definition/clusters-types.d.ts.map +1 -1
  53. package/dist/zspec/zcl/definition/enums.d.ts +10 -0
  54. package/dist/zspec/zcl/definition/enums.d.ts.map +1 -1
  55. package/dist/zspec/zcl/definition/enums.js +12 -1
  56. package/dist/zspec/zcl/definition/enums.js.map +1 -1
  57. package/dist/zspec/zcl/definition/tstype.d.ts +1 -1
  58. package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
  59. package/dist/zspec/zcl/index.d.ts +1 -0
  60. package/dist/zspec/zcl/index.d.ts.map +1 -1
  61. package/dist/zspec/zcl/index.js.map +1 -1
  62. package/dist/zspec/zcl/utils.d.ts +1 -1
  63. package/dist/zspec/zcl/utils.d.ts.map +1 -1
  64. package/dist/zspec/zcl/utils.js +1 -1
  65. package/dist/zspec/zcl/utils.js.map +1 -1
  66. package/package.json +3 -4
  67. package/src/adapter/ezsp/driver/driver.ts +1 -1
  68. package/src/adapter/ezsp/driver/uart.ts +1 -1
  69. package/src/adapter/z-stack/adapter/zStackAdapter.ts +4 -4
  70. package/src/adapter/zigate/adapter/zigateAdapter.ts +4 -4
  71. package/src/controller/controller.ts +11 -15
  72. package/src/controller/events.ts +1 -1
  73. package/src/controller/helpers/request.ts +3 -1
  74. package/src/controller/helpers/zclFrameConverter.ts +13 -17
  75. package/src/controller/model/device.ts +104 -148
  76. package/src/controller/model/endpoint.ts +112 -64
  77. package/src/controller/model/group.ts +33 -9
  78. package/src/controller/model/index.ts +1 -0
  79. package/src/controller/model/zigbeeEntity.ts +30 -0
  80. package/src/controller/tstype.ts +234 -0
  81. package/src/zspec/zcl/definition/cluster.ts +2 -9
  82. package/src/zspec/zcl/definition/clusters-typegen.ts +96 -19
  83. package/src/zspec/zcl/definition/clusters-types.ts +195 -146
  84. package/src/zspec/zcl/definition/enums.ts +11 -0
  85. package/src/zspec/zcl/definition/tstype.ts +0 -1
  86. package/src/zspec/zcl/index.ts +1 -0
  87. package/src/zspec/zcl/utils.ts +1 -1
  88. package/test/adapter/ezsp/uart.test.ts +2 -2
  89. package/test/adapter/z-stack/znp.test.ts +4 -4
  90. package/test/benchOptions.ts +14 -0
  91. package/test/controller.bench.ts +96 -75
  92. package/test/controller.test.ts +296 -98
  93. package/test/requests.bench.ts +37 -14
  94. package/test/vitest.config.mts +1 -2
  95. package/test/zcl.test.ts +1 -1
  96. package/test/zspec/zcl/utils.test.ts +4 -4
@@ -1,3 +1,16 @@
1
+ import type {
2
+ TClusterAttributes,
3
+ TClusterCommandResponses,
4
+ TClusterCommands,
5
+ TClusterPayload,
6
+ TClusters,
7
+ TFoundation,
8
+ TFoundationGenericPayload,
9
+ TFoundationPayload,
10
+ TPartialClusterAttributes,
11
+ } from "../zspec/zcl/definition/clusters-types";
12
+ import type {DataType} from "../zspec/zcl/definition/enums";
13
+
1
14
  export interface KeyValue {
2
15
  // biome-ignore lint/suspicious/noExplicitAny: API
3
16
  [s: string]: any;
@@ -38,3 +51,224 @@ export interface GreenPowerDeviceJoinedPayload {
38
51
  networkAddress: number;
39
52
  securityKey?: Buffer;
40
53
  }
54
+
55
+ export interface TCustomCluster {
56
+ attributes: Record<string, unknown> | never;
57
+ commands: Record<string, Record<string, unknown | never>> | never;
58
+ commandResponses: Record<string, Record<string, unknown | never>> | never;
59
+ }
60
+
61
+ export type RawClusterAttribute = {value: unknown; type: DataType};
62
+
63
+ export type RawClusterAttributes = Record<number, RawClusterAttribute>;
64
+
65
+ // below Cluster types follow roughly the same logic:
66
+ // - if cluster has attributes/commands/commandsResponse
67
+ // - if Custom is defined and has attributes/commands/commandsResponse, use Custom and/or raw
68
+ // - else use raw
69
+ // - else
70
+ // - if cluster is ZCL
71
+ // - if Custom is defined and has attributes/commands/commandsResponse, use Custom and/or ZCL and/or raw
72
+ // - else use ZCL and/or raw
73
+ // - else
74
+ // - if Custom is defined, use Custom and/or raw
75
+ // - else use raw
76
+ //
77
+ // where `raw` represents the type used for full manual input (usually using ID)
78
+
79
+ export type ClusterOrRawAttributeKeys<
80
+ Cl extends string | number,
81
+ Custom extends TCustomCluster | undefined = undefined,
82
+ > = TClusterAttributes<Cl> extends never
83
+ ? Custom extends TCustomCluster
84
+ ? Custom["attributes"] extends never
85
+ ? number[]
86
+ : (keyof Custom["attributes"] | number)[]
87
+ : number[]
88
+ : Cl extends keyof TClusters
89
+ ? Custom extends TCustomCluster
90
+ ? Custom["attributes"] extends never
91
+ ? // don't use `TClusterAttributeKeys<Cl>` as that allows "symbol"
92
+ (keyof TClusters[Cl]["attributes"] | number)[]
93
+ : (keyof Custom["attributes"] | keyof TClusters[Cl]["attributes"] | number)[]
94
+ : (keyof TClusters[Cl]["attributes"] | number)[]
95
+ : Custom extends TCustomCluster
96
+ ? Custom["attributes"] extends never
97
+ ? number[]
98
+ : (keyof Custom["attributes"] | number)[]
99
+ : number[];
100
+
101
+ export type ClusterOrRawWriteAttributes<
102
+ Cl extends string | number,
103
+ Custom extends TCustomCluster | undefined = undefined,
104
+ > = TClusterAttributes<Cl> extends never
105
+ ? Custom extends TCustomCluster
106
+ ? Custom["attributes"] extends never
107
+ ? RawClusterAttributes
108
+ : Custom["attributes"] & RawClusterAttributes
109
+ : RawClusterAttributes
110
+ : Cl extends keyof TClusters
111
+ ? (Custom extends TCustomCluster
112
+ ? Custom["attributes"] extends never
113
+ ? TClusterAttributes<Cl>
114
+ : Custom["attributes"] & TClusterAttributes<Cl>
115
+ : TClusterAttributes<Cl>) &
116
+ RawClusterAttributes
117
+ : Custom extends TCustomCluster
118
+ ? Custom["attributes"] extends never
119
+ ? RawClusterAttributes
120
+ : Custom["attributes"] & RawClusterAttributes
121
+ : RawClusterAttributes;
122
+
123
+ export type PartialClusterOrRawWriteAttributes<
124
+ Cl extends string | number,
125
+ Custom extends TCustomCluster | undefined = undefined,
126
+ > = TClusterAttributes<Cl> extends never
127
+ ? Custom extends TCustomCluster
128
+ ? Custom["attributes"] extends never
129
+ ? RawClusterAttributes
130
+ : Partial<Custom["attributes"]> & RawClusterAttributes
131
+ : RawClusterAttributes
132
+ : Cl extends keyof TClusters
133
+ ? (Custom extends TCustomCluster
134
+ ? Custom["attributes"] extends never
135
+ ? TPartialClusterAttributes<Cl>
136
+ : Partial<Custom["attributes"]> & TPartialClusterAttributes<Cl>
137
+ : TPartialClusterAttributes<Cl>) &
138
+ RawClusterAttributes
139
+ : Custom extends TCustomCluster
140
+ ? Custom["attributes"] extends never
141
+ ? RawClusterAttributes
142
+ : Partial<Custom["attributes"]> & RawClusterAttributes
143
+ : RawClusterAttributes;
144
+
145
+ export type ClusterOrRawAttributes<
146
+ Cl extends string | number,
147
+ Custom extends TCustomCluster | undefined = undefined,
148
+ > = TClusterAttributes<Cl> extends never
149
+ ? Custom extends TCustomCluster
150
+ ? Custom["attributes"] extends never
151
+ ? Record<number, unknown>
152
+ : Custom["attributes"] & Record<number, unknown>
153
+ : Record<number, unknown>
154
+ : Cl extends keyof TClusters
155
+ ? (Custom extends TCustomCluster
156
+ ? Custom["attributes"] extends never
157
+ ? TClusterAttributes<Cl>
158
+ : Custom["attributes"] & TClusterAttributes<Cl>
159
+ : TClusterAttributes<Cl>) &
160
+ Record<number, unknown>
161
+ : Custom extends TCustomCluster
162
+ ? Custom["attributes"] extends never
163
+ ? Record<number, unknown>
164
+ : Custom["attributes"] & Record<number, unknown>
165
+ : Record<number, unknown>;
166
+
167
+ export type PartialClusterOrRawAttributes<
168
+ Cl extends string | number,
169
+ Custom extends TCustomCluster | undefined = undefined,
170
+ > = TClusterAttributes<Cl> extends never
171
+ ? Custom extends TCustomCluster
172
+ ? Custom["attributes"] extends never
173
+ ? Record<number, unknown>
174
+ : Partial<Custom["attributes"]> & Record<number, unknown>
175
+ : Record<number, unknown>
176
+ : Cl extends keyof TClusters
177
+ ? (Custom extends TCustomCluster
178
+ ? Custom["attributes"] extends never
179
+ ? TPartialClusterAttributes<Cl>
180
+ : Partial<Custom["attributes"]> & TPartialClusterAttributes<Cl>
181
+ : TPartialClusterAttributes<Cl>) &
182
+ Record<number, unknown>
183
+ : Custom extends TCustomCluster
184
+ ? Custom["attributes"] extends never
185
+ ? Record<number, unknown>
186
+ : Partial<Custom["attributes"]> & Record<number, unknown>
187
+ : Record<number, unknown>;
188
+
189
+ export type ClusterCommandKeys<Cl extends string | number, Custom extends TCustomCluster | undefined = undefined> = TClusterCommands<Cl> extends never
190
+ ? Custom extends TCustomCluster
191
+ ? Custom["commands"] extends never
192
+ ? number[]
193
+ : (keyof Custom["commands"] | number)[]
194
+ : number[]
195
+ : Cl extends keyof TClusters
196
+ ? Custom extends TCustomCluster
197
+ ? Custom["commands"] extends never
198
+ ? // don't use `TClusterCommandKeys<Cl>` as that allows "symbol"
199
+ (keyof TClusters[Cl]["commands"] | number)[]
200
+ : (keyof Custom["commands"] | keyof TClusters[Cl]["commands"] | number)[]
201
+ : (keyof TClusters[Cl]["commands"] | number)[]
202
+ : Custom extends TCustomCluster
203
+ ? Custom["commands"] extends never
204
+ ? number[]
205
+ : (keyof Custom["commands"] | number)[]
206
+ : number[];
207
+
208
+ export type ClusterCommandResponseKeys<
209
+ Cl extends string | number,
210
+ Custom extends TCustomCluster | undefined = undefined,
211
+ > = TClusterCommandResponses<Cl> extends never
212
+ ? Custom extends TCustomCluster
213
+ ? Custom["commandResponses"] extends never
214
+ ? number[]
215
+ : (keyof Custom["commandResponses"] | number)[]
216
+ : number[]
217
+ : Cl extends keyof TClusters
218
+ ? Custom extends TCustomCluster
219
+ ? Custom["commandResponses"] extends never
220
+ ? // don't use `TClusterCommandResponseKeys<Cl>` as that allows "symbol"
221
+ (keyof TClusters[Cl]["commandResponses"] | number)[]
222
+ : (keyof Custom["commandResponses"] | keyof TClusters[Cl]["commandResponses"] | number)[]
223
+ : (keyof TClusters[Cl]["commandResponses"] | number)[]
224
+ : Custom extends TCustomCluster
225
+ ? Custom["commandResponses"] extends never
226
+ ? number[]
227
+ : (keyof Custom["commandResponses"] | number)[]
228
+ : number[];
229
+
230
+ export type TCustomClusterPayload<Custom extends TCustomCluster, Co extends string | number> = Custom["commands"] extends never
231
+ ? Custom["commandResponses"] extends never
232
+ ? never
233
+ : Co extends keyof Custom["commandResponses"]
234
+ ? Custom["commandResponses"][Co]
235
+ : never
236
+ : Co extends keyof Custom["commands"]
237
+ ? Custom["commands"][Co]
238
+ : Co extends keyof Custom["commandResponses"]
239
+ ? Custom["commandResponses"][Co]
240
+ : never;
241
+
242
+ export type ClusterOrRawPayload<
243
+ Cl extends string | number,
244
+ Co extends string | number,
245
+ Custom extends TCustomCluster | undefined = undefined,
246
+ > = Cl extends number
247
+ ? Record<string, unknown>
248
+ : Co extends number
249
+ ? Record<string, unknown>
250
+ : TClusterPayload<Cl, Co> extends never
251
+ ? Custom extends TCustomCluster
252
+ ? TCustomClusterPayload<Custom, Co> extends never
253
+ ? never
254
+ : TCustomClusterPayload<Custom, Co>
255
+ : never
256
+ : Cl extends keyof TClusters
257
+ ? Custom extends TCustomCluster
258
+ ? TCustomClusterPayload<Custom, Co> extends never
259
+ ? TClusterPayload<Cl, Co>
260
+ : TCustomClusterPayload<Custom, Co> & TClusterPayload<Cl, Co>
261
+ : TClusterPayload<Cl, Co>
262
+ : Custom extends TCustomCluster
263
+ ? TCustomClusterPayload<Custom, Co> extends never
264
+ ? never
265
+ : TCustomClusterPayload<Custom, Co>
266
+ : never;
267
+
268
+ export type FoundationOrRawPayload<Co extends string | number> = Co extends number
269
+ ? TFoundationGenericPayload
270
+ : TFoundationPayload<Co> extends never
271
+ ? never
272
+ : Co extends keyof TFoundation
273
+ ? TFoundationPayload<Co>
274
+ : never;
@@ -2167,6 +2167,7 @@ export const Clusters: Readonly<Record<ClusterName, Readonly<ClusterDefinition>>
2167
2167
  },
2168
2168
  getWeeklySchedule: {
2169
2169
  ID: 2,
2170
+ response: 0,
2170
2171
  parameters: [
2171
2172
  {name: "daystoreturn", type: DataType.UINT8},
2172
2173
  {name: "modetoreturn", type: DataType.UINT8},
@@ -2178,6 +2179,7 @@ export const Clusters: Readonly<Record<ClusterName, Readonly<ClusterDefinition>>
2178
2179
  },
2179
2180
  getRelayStatusLog: {
2180
2181
  ID: 4,
2182
+ response: 1,
2181
2183
  parameters: [],
2182
2184
  },
2183
2185
  danfossSetpointCommand: {
@@ -5438,15 +5440,6 @@ export const Clusters: Readonly<Record<ClusterName, Readonly<ClusterDefinition>>
5438
5440
  commands: {},
5439
5441
  commandsResponse: {},
5440
5442
  },
5441
- sprutDevice: {
5442
- ID: 26112,
5443
- manufacturerCode: 26214,
5444
- attributes: {
5445
- debug: {ID: 0, type: DataType.BOOLEAN},
5446
- },
5447
- commands: {},
5448
- commandsResponse: {},
5449
- },
5450
5443
  sprutVoc: {
5451
5444
  ID: 26113,
5452
5445
  manufacturerCode: 26214,
@@ -18,11 +18,11 @@ import {Clusters} from "./cluster";
18
18
  import {BuffaloZclDataType, DataType} from "./enums";
19
19
  import {Foundation, type FoundationCommandName, type FoundationDefinition} from "./foundation";
20
20
  import {ManufacturerCode} from "./manufacturerCode";
21
- import type {AttributeDefinition, ClusterName, CommandDefinition} from "./tstype";
21
+ import type {AttributeDefinition, ClusterName, CommandDefinition, ParameterDefinition} from "./tstype";
22
22
 
23
23
  const FILENAME = "clusters-types.ts";
24
24
 
25
- const file = ts.createSourceFile(FILENAME, "", ts.ScriptTarget.ES2022, false, ts.ScriptKind.TS);
25
+ const file = ts.createSourceFile(FILENAME, "", ts.ScriptTarget.ESNext, false, ts.ScriptKind.TS);
26
26
  const printer = ts.createPrinter({newLine: ts.NewLineKind.LineFeed});
27
27
 
28
28
  const emptyObject = ts.factory.createTypeReferenceNode("Record", [
@@ -40,12 +40,16 @@ const namedImports = ts.factory.createImportDeclaration(
40
40
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ExtensionFieldSet")),
41
41
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("Gpd")),
42
42
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdAttributeReport")),
43
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdChannelConfiguration")),
43
44
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdChannelRequest")),
45
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdCommissioningReply")),
46
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdCustomReply")),
44
47
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("MiboxerZone")),
45
48
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("Struct")),
46
49
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("StructuredSelector")),
47
50
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ThermoTransition")),
48
51
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("TuyaDataPointValue")),
52
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZclArray")),
49
53
  // ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZclDate")), // XXX: currently unused
50
54
  // ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZclTimeOfDay")), // XXX: currently unused
51
55
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZoneInfo")),
@@ -61,6 +65,16 @@ const getTypeFromDataType = (dataType: DataType | BuffaloZclDataType): ts.TypeNo
61
65
  case DataType.UNKNOWN: {
62
66
  return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword);
63
67
  }
68
+ case DataType.DATA56:
69
+ case DataType.BITMAP56:
70
+ case DataType.UINT56:
71
+ case DataType.DATA64:
72
+ case DataType.BITMAP64:
73
+ case DataType.UINT64:
74
+ case DataType.INT56:
75
+ case DataType.INT64: {
76
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BigIntKeyword);
77
+ }
64
78
  case DataType.OCTET_STR:
65
79
  case DataType.LONG_OCTET_STR:
66
80
  case DataType.SEC_KEY: {
@@ -74,7 +88,11 @@ const getTypeFromDataType = (dataType: DataType | BuffaloZclDataType): ts.TypeNo
74
88
  case DataType.ARRAY:
75
89
  case DataType.SET:
76
90
  case DataType.BAG: {
77
- return ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
91
+ // mismatch on read vs write, have to union
92
+ return ts.factory.createUnionTypeNode([
93
+ ts.factory.createTypeReferenceNode("ZclArray"),
94
+ ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)),
95
+ ]);
78
96
  }
79
97
  case DataType.STRUCT: {
80
98
  return ts.factory.createTypeReferenceNode("Struct");
@@ -115,6 +133,9 @@ const getTypeFromDataType = (dataType: DataType | BuffaloZclDataType): ts.TypeNo
115
133
  ts.factory.createPropertySignature(undefined, "raw", undefined, ts.factory.createTypeReferenceNode("Buffer")),
116
134
  ]),
117
135
  ts.factory.createTypeReferenceNode("Record<string, never>"),
136
+ ts.factory.createTypeReferenceNode("GpdCommissioningReply"),
137
+ ts.factory.createTypeReferenceNode("GpdChannelConfiguration"),
138
+ ts.factory.createTypeReferenceNode("GpdCustomReply"),
118
139
  ]);
119
140
  }
120
141
  case BuffaloZclDataType.STRUCTURED_SELECTOR: {
@@ -132,6 +153,28 @@ const getTypeFromDataType = (dataType: DataType | BuffaloZclDataType): ts.TypeNo
132
153
  }
133
154
  };
134
155
 
156
+ const getConditionStr = (conditions: ParameterDefinition["conditions"]): string | undefined => {
157
+ if (conditions) {
158
+ let str = ", Conditions: [";
159
+
160
+ for (const condition of conditions) {
161
+ str += `{${condition.type}`;
162
+
163
+ for (const key in condition) {
164
+ if (key === "type") {
165
+ continue;
166
+ }
167
+
168
+ str += ` ${key}=${condition[key as keyof typeof condition]}`;
169
+ }
170
+
171
+ str += "}";
172
+ }
173
+
174
+ return `${str}]`;
175
+ }
176
+ };
177
+
135
178
  const addAttributes = (attributes: Readonly<Record<string, Readonly<AttributeDefinition>>>): ts.TypeNode => {
136
179
  const elements: ts.PropertySignature[] = [];
137
180
 
@@ -157,7 +200,7 @@ const addAttributes = (attributes: Readonly<Record<string, Readonly<AttributeDef
157
200
  ts.addSyntheticLeadingComment(element, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);
158
201
  }
159
202
 
160
- return elements.length > 0 ? ts.factory.createTypeLiteralNode(elements) : emptyObject;
203
+ return elements.length > 0 ? ts.factory.createTypeLiteralNode(elements) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword);
161
204
  };
162
205
 
163
206
  const addCommands = (commands: Readonly<Record<string, Readonly<CommandDefinition>>>): ts.TypeNode => {
@@ -179,12 +222,13 @@ const addCommands = (commands: Readonly<Record<string, Readonly<CommandDefinitio
179
222
  parameter.conditions ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
180
223
  paramType,
181
224
  );
225
+ const conditionComment = getConditionStr(parameter.conditions);
182
226
 
183
227
  cmdElements.push(cmdElement);
184
228
  ts.addSyntheticLeadingComment(
185
229
  cmdElement,
186
230
  ts.SyntaxKind.MultiLineCommentTrivia,
187
- `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]} `,
231
+ `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]}${conditionComment ?? ""} `,
188
232
  true,
189
233
  );
190
234
  } else if (
@@ -266,13 +310,14 @@ const addParameters = (foundation: Readonly<FoundationDefinition>): ts.TypeNode
266
310
  parameter.conditions ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
267
311
  getTypeFromDataType(parameter.type),
268
312
  );
313
+ const conditionComment = getConditionStr(parameter.conditions);
269
314
 
270
315
  elements.push(element);
271
316
 
272
317
  ts.addSyntheticLeadingComment(
273
318
  element,
274
319
  ts.SyntaxKind.MultiLineCommentTrivia,
275
- `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]} `,
320
+ `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]}${conditionComment ?? ""} `,
276
321
  true,
277
322
  );
278
323
  }
@@ -387,12 +432,6 @@ const coDecl = ts.factory.createTypeParameterDeclaration(
387
432
  ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
388
433
  ]),
389
434
  );
390
- const clusterGenericPayloadDecl = ts.factory.createTypeAliasDeclaration(
391
- [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
392
- "TClusterGenericPayload",
393
- undefined,
394
- ts.factory.createTypeReferenceNode("Record<string, unknown>"),
395
- );
396
435
  const clusterAttributeKeysDecl = ts.factory.createTypeAliasDeclaration(
397
436
  [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
398
437
  "TClusterAttributeKeys",
@@ -406,7 +445,7 @@ const clusterAttributesDecl = ts.factory.createTypeAliasDeclaration(
406
445
  "TClusterAttributes",
407
446
  [clDecl],
408
447
  ts.factory.createTypeReferenceNode(
409
- `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["attributes"] : ${clusterGenericPayloadDecl.name.escapedText}`,
448
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["attributes"] : never`,
410
449
  ),
411
450
  );
412
451
  const partialClusterAttributesDecl = ts.factory.createTypeAliasDeclaration(
@@ -414,7 +453,39 @@ const partialClusterAttributesDecl = ts.factory.createTypeAliasDeclaration(
414
453
  "TPartialClusterAttributes",
415
454
  [clDecl],
416
455
  ts.factory.createTypeReferenceNode(
417
- `Cl extends keyof ${clustersDecl.name.escapedText} ? Partial<${clustersDecl.name.escapedText}[Cl]["attributes"]> : ${clusterGenericPayloadDecl.name.escapedText}`,
456
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Partial<${clustersDecl.name.escapedText}[Cl]["attributes"]> : never`,
457
+ ),
458
+ );
459
+ const clusterCommandKeysDecl = ts.factory.createTypeAliasDeclaration(
460
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
461
+ "TClusterCommandKeys",
462
+ [clDecl],
463
+ ts.factory.createTypeReferenceNode(
464
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? (keyof ${clustersDecl.name.escapedText}[Cl]["commands"])[] : (string | number)[];`,
465
+ ),
466
+ );
467
+ const clusterCommandResponseKeysDecl = ts.factory.createTypeAliasDeclaration(
468
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
469
+ "TClusterCommandResponseKeys",
470
+ [clDecl],
471
+ ts.factory.createTypeReferenceNode(
472
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? (keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"])[] : (string | number)[];`,
473
+ ),
474
+ );
475
+ const clusterCommandsDecl = ts.factory.createTypeAliasDeclaration(
476
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
477
+ "TClusterCommands",
478
+ [clDecl],
479
+ ts.factory.createTypeReferenceNode(
480
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["commands"] : never`,
481
+ ),
482
+ );
483
+ const clusterCommandResponsesDecl = ts.factory.createTypeAliasDeclaration(
484
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
485
+ "TClusterCommandResponses",
486
+ [clDecl],
487
+ ts.factory.createTypeReferenceNode(
488
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"] : never`,
418
489
  ),
419
490
  );
420
491
  const clusterCommandPayloadDecl = ts.factory.createTypeAliasDeclaration(
@@ -422,7 +493,7 @@ const clusterCommandPayloadDecl = ts.factory.createTypeAliasDeclaration(
422
493
  "TClusterCommandPayload",
423
494
  [clDecl, coDecl],
424
495
  ts.factory.createTypeReferenceNode(
425
- `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
496
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : never : never;`,
426
497
  ),
427
498
  );
428
499
  const clusterCommandResponsePayloadDecl = ts.factory.createTypeAliasDeclaration(
@@ -430,7 +501,7 @@ const clusterCommandResponsePayloadDecl = ts.factory.createTypeAliasDeclaration(
430
501
  "TClusterCommandResponsePayload",
431
502
  [clDecl, coDecl],
432
503
  ts.factory.createTypeReferenceNode(
433
- `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
504
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : never : never;`,
434
505
  ),
435
506
  );
436
507
  const clusterPayloadDecl = ts.factory.createTypeAliasDeclaration(
@@ -438,7 +509,7 @@ const clusterPayloadDecl = ts.factory.createTypeAliasDeclaration(
438
509
  "TClusterPayload",
439
510
  [clDecl, coDecl],
440
511
  ts.factory.createTypeReferenceNode(
441
- `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["commands"] extends never ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"] extends never ? never : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
512
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["commands"] extends never ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"] extends never ? never : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : never : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : never : never;`,
442
513
  ),
443
514
  );
444
515
  const foundationGenericPayloadDecl = ts.factory.createTypeAliasDeclaration(
@@ -485,14 +556,20 @@ ${printer.printNode(ts.EmitHint.Unspecified, foundationFlatDecl, file)}
485
556
  ${printer.printNode(ts.EmitHint.Unspecified, foundationOneOfDecl, file)}
486
557
 
487
558
  // Clusters
488
- ${printer.printNode(ts.EmitHint.Unspecified, clusterGenericPayloadDecl, file)}
489
-
490
559
  ${printer.printNode(ts.EmitHint.Unspecified, clusterAttributeKeysDecl, file)}
491
560
 
492
561
  ${printer.printNode(ts.EmitHint.Unspecified, clusterAttributesDecl, file)}
493
562
 
494
563
  ${printer.printNode(ts.EmitHint.Unspecified, partialClusterAttributesDecl, file)}
495
564
 
565
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandKeysDecl, file)}
566
+
567
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandResponseKeysDecl, file)}
568
+
569
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandsDecl, file)}
570
+
571
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandResponsesDecl, file)}
572
+
496
573
  ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandPayloadDecl, file)}
497
574
 
498
575
  ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandResponsePayloadDecl, file)}