|
35 | 35 | DataType, |
36 | 36 | ElementID, |
37 | 37 | FunctionCode, |
| 38 | + Ids, |
38 | 39 | Opcode, |
39 | 40 | ProtocolVersion, |
40 | 41 | READ_FUNCTION_CODES, |
@@ -716,34 +717,51 @@ def _handle_explore(self, seq_num: int, session_id: int, request_data: bytes) -> |
716 | 717 | ) |
717 | 718 | response += encode_uint32_vlq(0) # Return code: success |
718 | 719 |
|
719 | | - # Return list of data blocks as objects |
| 720 | + # Return list of data blocks as objects using standard S7CommPlus IDs |
720 | 721 | for db_num, db in sorted(self._data_blocks.items()): |
721 | 722 | response += bytes([ElementID.START_OF_OBJECT]) |
722 | 723 | response += struct.pack(">I", db.object_id) # Relation ID |
723 | 724 | response += encode_uint32_vlq(0x00000100) # Class: DataBlock |
724 | 725 | response += encode_uint32_vlq(0x00000000) # Class flags |
725 | 726 | response += encode_uint32_vlq(0x00000000) # Attribute ID |
726 | 727 |
|
727 | | - # DB number attribute |
| 728 | + # ObjectVariableTypeName (233) -- DB name as WSTRING |
728 | 729 | response += bytes([ElementID.ATTRIBUTE]) |
729 | | - response += encode_uint32_vlq(0x0001) # DB number attribute ID |
730 | | - response += encode_typed_value(DataType.UINT, db_num) |
| 730 | + response += encode_uint32_vlq(Ids.OBJECT_VARIABLE_TYPE_NAME) |
| 731 | + name_bytes = f"DB{db_num}".encode("utf-16-be") |
| 732 | + response += bytes([0x00, DataType.WSTRING]) |
| 733 | + response += encode_uint32_vlq(len(name_bytes)) |
| 734 | + response += name_bytes |
731 | 735 |
|
732 | | - # DB size attribute |
| 736 | + # Block_BlockNumber (2521) -- DB number as UDINT |
733 | 737 | response += bytes([ElementID.ATTRIBUTE]) |
734 | | - response += encode_uint32_vlq(0x0002) # DB size attribute ID |
735 | | - response += encode_typed_value(DataType.UDINT, len(db.data)) |
| 738 | + response += encode_uint32_vlq(Ids.BLOCK_BLOCK_NUMBER) |
| 739 | + response += bytes([0x00, DataType.UDINT]) |
| 740 | + response += encode_uint32_vlq(db_num) |
736 | 741 |
|
737 | | - # Variable list |
| 742 | + # DB size attribute (non-standard, for backward compat) |
| 743 | + response += bytes([ElementID.ATTRIBUTE]) |
| 744 | + response += encode_uint32_vlq(0x0002) |
| 745 | + response += bytes([0x00, DataType.UDINT]) |
| 746 | + response += encode_uint32_vlq(len(db.data)) |
| 747 | + |
| 748 | + # Variable list -- used by browse to resolve field names |
738 | 749 | if db.variables: |
739 | | - response += bytes([ElementID.VARNAME_LIST]) |
740 | | - response += encode_uint32_vlq(len(db.variables)) |
741 | 750 | for var_name, var in db.variables.items(): |
742 | | - name_bytes = var_name.encode("utf-8") |
743 | | - response += encode_uint32_vlq(len(name_bytes)) |
744 | | - response += name_bytes |
745 | | - response += encode_uint32_vlq(var.soft_datatype) |
746 | | - response += encode_uint32_vlq(var.byte_offset) |
| 751 | + response += bytes([ElementID.START_OF_OBJECT]) |
| 752 | + response += struct.pack(">I", 0) # child RID |
| 753 | + response += encode_uint32_vlq(0) |
| 754 | + response += encode_uint32_vlq(0) |
| 755 | + response += encode_uint32_vlq(0) |
| 756 | + |
| 757 | + response += bytes([ElementID.ATTRIBUTE]) |
| 758 | + response += encode_uint32_vlq(Ids.OBJECT_VARIABLE_TYPE_NAME) |
| 759 | + vname_bytes = var_name.encode("utf-16-be") |
| 760 | + response += bytes([0x00, DataType.WSTRING]) |
| 761 | + response += encode_uint32_vlq(len(vname_bytes)) |
| 762 | + response += vname_bytes |
| 763 | + |
| 764 | + response += bytes([ElementID.TERMINATING_OBJECT]) |
747 | 765 |
|
748 | 766 | response += bytes([ElementID.TERMINATING_OBJECT]) |
749 | 767 |
|
|
0 commit comments