|
7 | 7 | import os |
8 | 8 | import re |
9 | 9 | import time |
| 10 | +import copy |
10 | 11 | from dataclasses import dataclass |
11 | 12 | from enum import Enum |
12 | 13 | from typing import TYPE_CHECKING, Union |
@@ -224,6 +225,9 @@ class registry_map_entry: |
224 | 225 | write_mode : WriteMode = WriteMode.READ |
225 | 226 | ''' enable disable reading/writing ''' |
226 | 227 |
|
| 228 | + has_enum_mapping : bool = False |
| 229 | + ''' indicates if this field has enum mappings that should be treated as strings ''' |
| 230 | + |
227 | 231 | def __str__(self): |
228 | 232 | return self.variable_name |
229 | 233 |
|
@@ -698,7 +702,8 @@ def process_row(row): |
698 | 702 | value_regex=value_regex, |
699 | 703 | read_command = read_command, |
700 | 704 | read_interval=read_interval, |
701 | | - write_mode=writeMode |
| 705 | + write_mode=writeMode, |
| 706 | + has_enum_mapping=value_is_json |
702 | 707 | ) |
703 | 708 | registry_map.append(item) |
704 | 709 |
|
@@ -807,6 +812,11 @@ def calculate_registry_ranges(self, map : list[registry_map_entry], max_register |
807 | 812 | except ValueError: |
808 | 813 | pass |
809 | 814 |
|
| 815 | + # Debug: log the parameters |
| 816 | + import logging |
| 817 | + log = logging.getLogger(__name__) |
| 818 | + log.debug(f"calculate_registry_ranges: max_register={max_register}, max_batch_size={max_batch_size}, map_size={len(map)}, init={init}") |
| 819 | + |
810 | 820 | start = -max_batch_size |
811 | 821 | ranges : list[tuple] = [] |
812 | 822 |
|
@@ -884,6 +894,7 @@ def load_registry_map(self, registry_type : Registry_Type, file : str = "", sett |
884 | 894 | size = item.register |
885 | 895 |
|
886 | 896 | self.registry_map_size[registry_type] = size |
| 897 | + self._log.debug(f"load_registry_map: {registry_type.name} - loaded {len(self.registry_map[registry_type])} entries, max_register={size}") |
887 | 898 | self.registry_map_ranges[registry_type] = self.calculate_registry_ranges(self.registry_map[registry_type], self.registry_map_size[registry_type], init=True) |
888 | 899 |
|
889 | 900 | def process_register_bytes(self, registry : dict[int,bytes], entry : registry_map_entry): |
@@ -1128,7 +1139,8 @@ def process_register_ushort(self, registry : dict[int, int], entry : registry_ma |
1128 | 1139 | value = registry[entry.register].to_bytes((16 + 7) // 8, byteorder=byte_order) #convert to ushort to bytes |
1129 | 1140 | value = value.hex() #convert bytes to hex |
1130 | 1141 | elif entry.data_type == Data_Type.ASCII: |
1131 | | - value = registry[entry.register].to_bytes((16 + 7) // 8, byteorder=byte_order) #convert to ushort to bytes |
| 1142 | + # For ASCII data, use little-endian byte order to read characters in correct order |
| 1143 | + value = registry[entry.register].to_bytes((16 + 7) // 8, byteorder="little") #convert to ushort to bytes |
1132 | 1144 | try: |
1133 | 1145 | value = value.decode("utf-8") #convert bytes to ascii |
1134 | 1146 | except UnicodeDecodeError as e: |
@@ -1313,4 +1325,47 @@ def replace_vars(match): |
1313 | 1325 | for r in results: |
1314 | 1326 | print(evaluate_expression(r)) |
1315 | 1327 |
|
| 1328 | + def reset_register_timestamps(self): |
| 1329 | + """Reset the next_read_timestamp values for all registry entries""" |
| 1330 | + for registry_type in Registry_Type: |
| 1331 | + if registry_type in self.registry_map: |
| 1332 | + for entry in self.registry_map[registry_type]: |
| 1333 | + entry.next_read_timestamp = 0 |
| 1334 | + self._log.debug(f"Reset timestamps for all registry entries in protocol {self.protocol}") |
| 1335 | + |
| 1336 | + def __deepcopy__(self, memo): |
| 1337 | + """Custom deep copy implementation to handle non-copyable attributes""" |
| 1338 | + # Create a new instance |
| 1339 | + new_instance = protocol_settings.__new__(protocol_settings) |
| 1340 | + |
| 1341 | + # Copy basic attributes |
| 1342 | + new_instance.protocol = self.protocol |
| 1343 | + new_instance.settings_dir = self.settings_dir |
| 1344 | + new_instance.transport_settings = self.transport_settings |
| 1345 | + new_instance.byteorder = self.byteorder |
| 1346 | + |
| 1347 | + # Copy dictionaries and lists |
| 1348 | + new_instance.variable_mask = copy.deepcopy(self.variable_mask, memo) |
| 1349 | + new_instance.variable_screen = copy.deepcopy(self.variable_screen, memo) |
| 1350 | + new_instance.codes = copy.deepcopy(self.codes, memo) |
| 1351 | + new_instance.settings = copy.deepcopy(self.settings, memo) |
| 1352 | + |
| 1353 | + # Copy registry maps with deep copy of entries |
| 1354 | + new_instance.registry_map = {} |
| 1355 | + for registry_type, entries in self.registry_map.items(): |
| 1356 | + new_instance.registry_map[registry_type] = copy.deepcopy(entries, memo) |
| 1357 | + |
| 1358 | + new_instance.registry_map_size = copy.deepcopy(self.registry_map_size, memo) |
| 1359 | + new_instance.registry_map_ranges = copy.deepcopy(self.registry_map_ranges, memo) |
| 1360 | + |
| 1361 | + # Copy transport |
| 1362 | + new_instance.transport = self.transport |
| 1363 | + |
| 1364 | + # Recreate logger (not copyable) |
| 1365 | + new_instance._log_level = self._log_level |
| 1366 | + new_instance._log = logging.getLogger(__name__) |
| 1367 | + new_instance._log.setLevel(new_instance._log_level) |
| 1368 | + |
| 1369 | + return new_instance |
| 1370 | + |
1316 | 1371 | #settings = protocol_settings('v0.14') |
0 commit comments