| 1346 | |
| 1347 | |
| 1348 | class ZigbeeClusterLibrary(Packet): |
| 1349 | name = "Zigbee Cluster Library (ZCL) Frame" |
| 1350 | deprecated_fields = { |
| 1351 | "direction": ("command_direction", "2.5.0"), |
| 1352 | } |
| 1353 | fields_desc = [ |
| 1354 | # Frame control (8 bits) |
| 1355 | BitField("reserved", 0, 3), |
| 1356 | BitField("disable_default_response", 0, 1), # 0 default response command will be returned # noqa: E501 |
| 1357 | BitField("command_direction", 0, 1), # 0 command sent from client to server; 1 command sent from server to client # noqa: E501 |
| 1358 | BitField("manufacturer_specific", 0, 1), # 0 manufacturer code shall not be included in the ZCL frame # noqa: E501 |
| 1359 | # Frame Type |
| 1360 | # 0b00 command acts across the entire profile |
| 1361 | # 0b01 command is specific to a cluster |
| 1362 | # 0b10 - 0b11 reserved |
| 1363 | BitEnumField("zcl_frametype", 0, 2, {0: 'profile-wide', 1: 'cluster-specific', 2: 'reserved2', 3: 'reserved3'}), # noqa: E501 |
| 1364 | # Manufacturer code (0/16 bits) only present then manufacturer_specific field is set to 1 # noqa: E501 |
| 1365 | ConditionalField(XLEShortField("manufacturer_code", 0x0), |
| 1366 | lambda pkt: pkt.getfieldval("manufacturer_specific") == 1 # noqa: E501 |
| 1367 | ), |
| 1368 | # Transaction sequence number (8 bits) |
| 1369 | ByteField("transaction_sequence", 0), |
| 1370 | # Command identifier (8 bits): the cluster command |
| 1371 | ByteEnumField("command_identifier", 0, _zcl_command_frames), |
| 1372 | ] |
| 1373 | |
| 1374 | def guess_payload_class(self, payload): |
| 1375 | if self.zcl_frametype == 0x00: |
| 1376 | # Profile-wide command |
| 1377 | if (self.command_identifier in |
| 1378 | {0x00, 0x01, 0x02, 0x04, 0x06, 0x07, 0x0a, 0x0b}): |
| 1379 | # done in bind_layers |
| 1380 | pass |
| 1381 | elif self.zcl_frametype == 0x01: |
| 1382 | # Cluster-specific command |
| 1383 | if self.underlayer.cluster == 0x0500: |
| 1384 | # IAS Zone |
| 1385 | if self.command_direction == 0: |
| 1386 | # Client-to-Server command |
| 1387 | if self.command_identifier == 0x00: |
| 1388 | return ZCLIASZoneZoneEnrollResponse |
| 1389 | elif self.command_direction == 1: |
| 1390 | # Server-to-Client command |
| 1391 | if self.command_identifier == 0x00: |
| 1392 | return ZCLIASZoneZoneStatusChangeNotification |
| 1393 | elif self.command_identifier == 0x01: |
| 1394 | return ZCLIASZoneZoneEnrollRequest |
| 1395 | elif self.underlayer.cluster == 0x0700: |
| 1396 | # Price cluster |
| 1397 | if self.command_direction == 0: |
| 1398 | # Client-to-Server command |
| 1399 | if self.command_identifier == 0x00: |
| 1400 | return ZCLPriceGetCurrentPrice |
| 1401 | elif self.command_identifier == 0x01: |
| 1402 | return ZCLPriceGetScheduledPrices |
| 1403 | elif self.command_direction == 1: |
| 1404 | # Server-to-Client command |
| 1405 | if self.command_identifier == 0x00: |
nothing calls this directly
no test coverage detected
searching dependent graphs…