Index: leahi_dialin/common/alarm_defs.py =================================================================== diff -u -r489ce5ef49041b863501b7fecd6e4716e7dcaa9f -raf4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1 --- leahi_dialin/common/alarm_defs.py (.../alarm_defs.py) (revision 489ce5ef49041b863501b7fecd6e4716e7dcaa9f) +++ leahi_dialin/common/alarm_defs.py (.../alarm_defs.py) (revision af4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1) @@ -220,104 +220,42 @@ ALARM_ID_TD_PRIME_COMPLETED_MEDIUM = 198 # TD prime completed medium priority alarm ALARM_ID_TD_REPEATED_AIR_TRAP_LOWER_EVENTS = 199 # TD repeated air trap lower events ALARM_ID_TD_TUBE_SET_MISMATCH = 200 # TD tubeset mismatch alarm - ALARM_ID_FW_RESERVED_201 = 201 # FW reserved for use - ALARM_ID_TD_BATTERY_PACK_ERROR_DETECTED = 202 # FW reserved for use - ALARM_ID_TD_BATTERY_COMM_FAULT = 203 # FW reserved for use - ALARM_ID_TD_BATTERY_CHARGER_ERROR_DETECTED = 204 # FW reserved for use - ALARM_ID_FW_RESERVED_205 = 205 # FW reserved for use - ALARM_ID_FW_RESERVED_206 = 206 # FW reserved for use - ALARM_ID_FW_RESERVED_207 = 207 # FW reserved for use - ALARM_ID_FW_RESERVED_208 = 208 # FW reserved for use - ALARM_ID_FW_RESERVED_209 = 209 # FW reserved for use - ALARM_ID_FW_RESERVED_210 = 210 # FW reserved for use - ALARM_ID_FW_RESERVED_211 = 211 # FW reserved for use - ALARM_ID_FW_RESERVED_212 = 212 # FW reserved for use - ALARM_ID_FW_RESERVED_213 = 213 # FW reserved for use - ALARM_ID_FW_RESERVED_214 = 214 # FW reserved for use - ALARM_ID_FW_RESERVED_215 = 215 # FW reserved for use - ALARM_ID_FW_RESERVED_216 = 216 # FW reserved for use - ALARM_ID_FW_RESERVED_217 = 217 # FW reserved for use - ALARM_ID_FW_RESERVED_218 = 218 # FW reserved for use - ALARM_ID_FW_RESERVED_219 = 219 # FW reserved for use - ALARM_ID_FW_RESERVED_220 = 220 # FW reserved for use - ALARM_ID_FW_RESERVED_221 = 221 # FW reserved for use - ALARM_ID_FW_RESERVED_222 = 222 # FW reserved for use - ALARM_ID_FW_RESERVED_223 = 223 # FW reserved for use - ALARM_ID_FW_RESERVED_224 = 224 # FW reserved for use - ALARM_ID_FW_RESERVED_225 = 225 # FW reserved for use - ALARM_ID_FW_RESERVED_226 = 226 # FW reserved for use - ALARM_ID_FW_RESERVED_227 = 227 # FW reserved for use - ALARM_ID_FW_RESERVED_228 = 228 # FW reserved for use - ALARM_ID_FW_RESERVED_229 = 229 # FW reserved for use - ALARM_ID_FW_RESERVED_230 = 230 # FW reserved for use - ALARM_ID_FW_RESERVED_231 = 231 # FW reserved for use - ALARM_ID_FW_RESERVED_232 = 232 # FW reserved for use - ALARM_ID_FW_RESERVED_233 = 233 # FW reserved for use - ALARM_ID_FW_RESERVED_234 = 234 # FW reserved for use - ALARM_ID_FW_RESERVED_235 = 235 # FW reserved for use - ALARM_ID_FW_RESERVED_236 = 236 # FW reserved for use - ALARM_ID_FW_RESERVED_237 = 237 # FW reserved for use - ALARM_ID_FW_RESERVED_238 = 238 # FW reserved for use - ALARM_ID_FW_RESERVED_239 = 239 # FW reserved for use - ALARM_ID_FW_RESERVED_240 = 240 # FW reserved for use - ALARM_ID_FW_RESERVED_241 = 241 # FW reserved for use - ALARM_ID_FW_RESERVED_242 = 242 # FW reserved for use - ALARM_ID_FW_RESERVED_243 = 243 # FW reserved for use - ALARM_ID_FW_RESERVED_244 = 244 # FW reserved for use - ALARM_ID_FW_RESERVED_245 = 245 # FW reserved for use - ALARM_ID_FW_RESERVED_246 = 246 # FW reserved for use - ALARM_ID_FW_RESERVED_247 = 247 # FW reserved for use - ALARM_ID_FW_RESERVED_248 = 248 # FW reserved for use - ALARM_ID_FW_RESERVED_249 = 249 # FW reserved for use - ALARM_ID_FW_RESERVED_250 = 250 # FW reserved for use - ALARM_ID_FW_RESERVED_251 = 251 # FW reserved for use - ALARM_ID_FW_RESERVED_252 = 252 # FW reserved for use - ALARM_ID_FW_RESERVED_253 = 253 # FW reserved for use - ALARM_ID_FW_RESERVED_254 = 254 # FW reserved for use - ALARM_ID_FW_RESERVED_255 = 255 # FW reserved for use - ALARM_ID_FW_RESERVED_256 = 256 # FW reserved for use - ALARM_ID_FW_RESERVED_257 = 257 # FW reserved for use - ALARM_ID_FW_RESERVED_258 = 258 # FW reserved for use - ALARM_ID_FW_RESERVED_259 = 259 # FW reserved for use - ALARM_ID_FW_RESERVED_260 = 260 # FW reserved for use - ALARM_ID_FW_RESERVED_261 = 261 # FW reserved for use - ALARM_ID_FW_RESERVED_262 = 262 # FW reserved for use - ALARM_ID_FW_RESERVED_263 = 263 # FW reserved for use - ALARM_ID_FW_RESERVED_264 = 264 # FW reserved for use - ALARM_ID_FW_RESERVED_265 = 265 # FW reserved for use - ALARM_ID_FW_RESERVED_266 = 266 # FW reserved for use - ALARM_ID_FW_RESERVED_267 = 267 # FW reserved for use - ALARM_ID_FW_RESERVED_268 = 268 # FW reserved for use - ALARM_ID_FW_RESERVED_269 = 269 # FW reserved for use - ALARM_ID_FW_RESERVED_270 = 270 # FW reserved for use - ALARM_ID_FW_RESERVED_271 = 271 # FW reserved for use - ALARM_ID_FW_RESERVED_272 = 272 # FW reserved for use - ALARM_ID_FW_RESERVED_273 = 273 # FW reserved for use - ALARM_ID_FW_RESERVED_274 = 274 # FW reserved for use - ALARM_ID_FW_RESERVED_275 = 275 # FW reserved for use - ALARM_ID_FW_RESERVED_276 = 276 # FW reserved for use - ALARM_ID_FW_RESERVED_277 = 277 # FW reserved for use - ALARM_ID_FW_RESERVED_278 = 278 # FW reserved for use - ALARM_ID_FW_RESERVED_279 = 279 # FW reserved for use - ALARM_ID_FW_RESERVED_280 = 280 # FW reserved for use - ALARM_ID_FW_RESERVED_281 = 281 # FW reserved for use - ALARM_ID_FW_RESERVED_282 = 282 # FW reserved for use - ALARM_ID_FW_RESERVED_283 = 283 # FW reserved for use - ALARM_ID_FW_RESERVED_284 = 284 # FW reserved for use - ALARM_ID_FW_RESERVED_285 = 285 # FW reserved for use - ALARM_ID_FW_RESERVED_286 = 286 # FW reserved for use - ALARM_ID_FW_RESERVED_287 = 287 # FW reserved for use - ALARM_ID_FW_RESERVED_288 = 288 # FW reserved for use - ALARM_ID_FW_RESERVED_289 = 289 # FW reserved for use - ALARM_ID_FW_RESERVED_290 = 290 # FW reserved for use - ALARM_ID_FW_RESERVED_291 = 291 # FW reserved for use - ALARM_ID_FW_RESERVED_292 = 292 # FW reserved for use - ALARM_ID_FW_RESERVED_293 = 293 # FW reserved for use - ALARM_ID_FW_RESERVED_294 = 294 # FW reserved for use - ALARM_ID_FW_RESERVED_295 = 295 # FW reserved for use - ALARM_ID_FW_RESERVED_296 = 296 # FW reserved for use - ALARM_ID_FW_RESERVED_297 = 297 # FW reserved for use - ALARM_ID_FW_RESERVED_298 = 298 # FW reserved for use - ALARM_ID_FW_RESERVED_299 = 299 # FW reserved for use - ALARM_ID_FW_RESERVED_300 = 300 # FW reserved for use - NUM_OF_ALARM_IDS = 301 # Number of alarms + ALARM_ID_RESERVED_201 = 201 # Reserved for ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH + ALARM_ID_RESERVED_202 = 202 # Reserved for ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW + ALARM_ID_RESERVED_203 = 203 # Reserved for ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH + ALARM_ID_RESERVED_204 = 204 # Reserved for ALARM_ID_TD_SAFETY_SHUTDOWN_POST_TEST_FAILED + ALARM_ID_RESERVED_205 = 205 # Reserved for ALARM_ID_TD_UI_POST_TIMEOUT + ALARM_ID_RESERVED_206 = 206 # Reserved for ALARM_ID_TD_UI_COMPATIBILITY_ERROR + ALARM_ID_RESERVED_207 = 207 # Reserved for ALARM_ID_TD_BATTERY_PACK_ERROR_DETECTED + ALARM_ID_RESERVED_208 = 208 # Reserved for ALARM_ID_TD_BATTERY_COMM_FAULT + ALARM_ID_RESERVED_209 = 209 # Reserved for ALARM_ID_TD_BATTERY_CHARGER_ERROR_DETECTED + ALARM_ID_RESERVED_210 = 210 # Reserved for ALARM_ID_DD_TURN_OFF_INLET_WATER_VALVES + ALARM_ID_RESERVED_211 = 211 # Reserved for ALARM_ID_DD_CHEM_DISINFECT_FLUSH_FLUSH_SAMPLE + ALARM_ID_RESERVED_212 = 212 # Reserved for ALARM_ID_DD_RO_PERMEATE_SAMPLE_REMOVE_DIA_CAP + ALARM_ID_RESERVED_213 = 213 # Reserved for ALARM_ID_TD_BP_SYSTOLIC_LOW + ALARM_ID_RESERVED_214 = 214 # Reserved for ALARM_ID_TD_BP_SYSTOLIC_LOW_TOO_MANY + ALARM_ID_RESERVED_215 = 215 # Reserved for ALARM_ID_TD_BP_SYSTOLIC_HIGH + ALARM_ID_RESERVED_216 = 216 # Reserved for ALARM_ID_TD_BP_HEART_RATE_LOW + ALARM_ID_RESERVED_217 = 217 # Reserved for ALARM_ID_TD_BP_HEART_RATE_HIGH + ALARM_ID_RESERVED_218 = 218 # Reserved for ALARM_ID_TD_BP_MODULE_ERROR + ALARM_ID_RESERVED_219 = 219 # Reserved for ALARM_ID_TD_UI_POST_TEST_FAILED + ALARM_ID_DD_NVM_INVALID_SYSTEM_RECORD_CRC = 220 # DD invalid NVM System record + ALARM_ID_DD_NVM_INVALID_SERVICE_RECORD_CRC = 221 # DD invalid NVM Service record + ALARM_ID_DD_NVM_INVALID_CALIBRATION_RECORD_CRC = 222 # DD invalid NVM calibration record + ALARM_ID_DD_NVM_INVALID_INSTITUTIONAL_RECORD_CRC = 223 # DD invalid NVM institutional record + ALARM_ID_DD_NVM_INVALID_USAGE_RECORD_CRC = 224 # DD invalid NVM Usage Info record + ALARM_ID_DD_NVM_INVALID_SERIAL_NUMBER = 225 # DD invalid serial number + ALARM_ID_DD_NVM_INVALID_CAL_PRESSURE_SENSOR = 226 # DD invalid pressure sensor calibration record + ALARM_ID_DD_NVM_INVALID_CAL_TEMP_SENSOR = 227 # DD invalid temperature sensor calibration record + ALARM_ID_DD_NVM_INVALID_CAL_CONC_PUMP = 228 # DD invalid concentrate pump calibration record + ALARM_ID_DD_NVM_INVALID_CAL_D12_PUMP = 229 # DD invalid d12 dialysate pump calibration record + ALARM_ID_DD_NVM_INVALID_CAL_D48_PUMP = 230 # DD invalid d48 dialysate pump calibration record + ALARM_ID_DD_NVM_INVALID_CAL_ACID_CONCENTRATE = 231 # DD invalid acid concentrate calibration record + ALARM_ID_DD_NVM_INVALID_CAL_BICARB_CONCENTRATE = 232 # DD invalid bicarbonate concentrate calibration record + ALARM_ID_DD_NVM_INVALID_CAL_ACCEL_SENSOR = 233 # DD invalid accelerometer sensor calibration record + ALARM_ID_DD_NVM_INVALID_CAL_BLOOD_LEAK_SENSOR = 234 # DD invalid blood leak sensor calibration record + ALARM_ID_DD_NVM_INVALID_CAL_CONDUCTIVITY_SENSOR = 235 # DD invalid conductivity sensor calibration record + ALARM_ID_DD_NVM_INVALID_INSTIT_BASIC_RECORD_CRC = 236 # DD invalid basic institutional record + ALARM_ID_DD_NVM_INVALID_INSTIT_ADVANCED_RECORD_CRC = 237 # DD invalid advanced institutional record + ALARM_ID_DD_NVM_INVALID_INSTIT_ADDITIONAL_RECORD_CRC = 238 # DD invalid additional institutional record + NUM_OF_ALARM_IDS = 239 # Number of alarms Index: leahi_dialin/common/msg_defs.py =================================================================== diff -u -r489ce5ef49041b863501b7fecd6e4716e7dcaa9f -raf4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1 --- leahi_dialin/common/msg_defs.py (.../msg_defs.py) (revision 489ce5ef49041b863501b7fecd6e4716e7dcaa9f) +++ leahi_dialin/common/msg_defs.py (.../msg_defs.py) (revision af4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1) @@ -81,7 +81,11 @@ REQUEST_REJECT_REASON_CONFIRMATION_MISMATCH = 59 # Confirmed value does not match validated value REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE = 60 # Request is not allowed in current treatment sub-state REQUEST_REJECT_REASON_MODALITY_MISMATCH = 61 # Mismatched modality (Rx entered vs reatment initiation modality ) - NUM_OF_REQUEST_REJECT_REASONS = 62 # Number of settings change reject codes + REQUEST_REJECT_REASON_NVM_JOB_QUEUE_BUSY = 62 # NVM Job queue is busy sending other records. + REQUEST_REJECT_REASON_NVM_INVALID_CRC = 63 # NVM received CRC of the record is invalid + REQUEST_REJECT_REASON_NVM_INVALID_OPERATION_MODE = 64 # NVM Operation Mode is not Service mode. + REQUEST_REJECT_REASON_INDEX_OUT_OF_RANGE = 65 # Index is out of range + NUM_OF_REQUEST_REJECT_REASONS = 66 # Number of settings change reject codes RequestRejectReasons._str_list = { } Index: leahi_dialin/common/msg_ids.py =================================================================== diff -u -r489ce5ef49041b863501b7fecd6e4716e7dcaa9f -raf4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1 --- leahi_dialin/common/msg_ids.py (.../msg_ids.py) (revision 489ce5ef49041b863501b7fecd6e4716e7dcaa9f) +++ leahi_dialin/common/msg_ids.py (.../msg_ids.py) (revision af4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1) @@ -370,6 +370,8 @@ MSG_ID_TD_ALARM_PROPERTIES_RESPONSE = 0x8062 # TD send alarm table properties response to Dialin MSG_ID_TD_BATTERY_REGISTERS_OVERRIDE_REQUEST = 0x8063 # TD battery registers override. MSG_ID_TD_BATTERY_PUBLISH_INTERVAL_OVERRIDE_REQUEST = 0x8064 # TD battery publish interval override. + MSG_ID_TD_RINSEBACK_VOLUME_OVERRIDE = 0x8065 # TD rinseback volume override + MSG_ID_TD_RINSEBACK_PUBLISH_INTERVAL_OVERRIDE_REQUEST = 0x8066 # TD rinseback publish interval broadcast override. MSG_ID_TD_BATTERY_I2C_STATUS_OVERRIDE_REQUEST = 0x8068 # TD battery I2C status override. @@ -491,6 +493,7 @@ MSG_ID_DD_MIXING_CONTROL_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST = 0xA073 # DD DD mixing control broadcast data overrride request MSG_ID_DD_BICART_DEPRESSURISE_REQUEST_OVERRIDE_REQUEST = 0xA074 # DD dry bicart depressurise overrride request MSG_ID_DD_TREATMENT_PARAMS_OVERRIDE_REQUEST = 0xA075 # DD Treatment parameters override request + MSG_ID_DD_NVM_RECORD_CRC_OVERRIDE_REQUEST = 0xA076 # DD NVM Record CRC override Request MSG_ID_FP_TESTER_LOGIN_REQUEST = 0xB000 # FP tester log-in MSG_ID_FP_SOFTWARE_RESET_REQUEST = 0xB001 # FP reset request Index: leahi_dialin/utils/enum_updater.py =================================================================== diff -u -r81e359d6c7ced081bd4580ec3e6cc38939781c6a -raf4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1 --- leahi_dialin/utils/enum_updater.py (.../enum_updater.py) (revision 81e359d6c7ced081bd4580ec3e6cc38939781c6a) +++ leahi_dialin/utils/enum_updater.py (.../enum_updater.py) (revision af4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1) @@ -1,6 +1,25 @@ +########################################################################### +# +# Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file enum_updater.py +# +# @author (last) Zoltan Miskolci +# @date (last) 05-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 05-Aug-2026 +# +############################################################################ + +# Module imports from clang.cindex import Index, CursorKind, Config from datetime import datetime from os import path +import re +import subprocess from typing import List Config.set_library_file("/usr/lib/llvm-18/lib/libclang.so") @@ -13,10 +32,12 @@ """ Read the enums from the C++ file and then update the Python Enum definitions """ - + + cpp_repo_loc = path.abspath(f'{path.dirname(__file__)}/../../leahi-common') files_to_check = [] - files_to_check.append(path.abspath(f'{path.dirname(__file__)}/../../leahi-common/AlarmDefs.h')) - files_to_check.append(path.abspath(f'{path.dirname(__file__)}/../../leahi-common/MsgDefs.h')) + files_to_check.append(f'{cpp_repo_loc}/AlarmDefs.h') + files_to_check.append(f'{cpp_repo_loc}/MsgDefs.h') + _update_cpp_repo(cpp_repo_loc) common_location = path.abspath(f'{path.dirname(__file__)}/../common') file_to_update = {'AlarmList': (f'{common_location}/alarm_defs.py', 'AlarmEnum', False), @@ -26,22 +47,46 @@ } for file in files_to_check: if path.exists(file): - extracted_enums = _extract_enums(file) - for enum_name in extracted_enums: + extracted_cpp_enums = _extract_cpp_enums(file) + for enum_name in extracted_cpp_enums: if enum_name in file_to_update: - _generate_enum_file(file_location = file_to_update[enum_name][0], + + # Extract information from the dictionary + python_file = file_to_update[enum_name][0] + enum_type_name = file_to_update[enum_name][1] + is_enum_hex = file_to_update[enum_name][2] + + # Extract the original Python enums from the file + original_py_enums = _extract_python_enums(python_file) + new_enum = list(extracted_cpp_enums[enum_name]) + + # Get the enum member list + cpp_enum_values = [ item['value'] for item in extracted_cpp_enums[enum_name] ] + + # Add the original Python enum members that are not present in the C++ enum + new_enum.extend( + item + for item in original_py_enums.get(enum_name, []) + if item['value'] not in cpp_enum_values) + + # Sort the new enum list by the value to maintain order + new_enum.sort(key=lambda x: x['value']) + + # Generate the updated Python enum file + _generate_python_enum_file(file_location = python_file, enum_name = enum_name, - enum_member_list = extracted_enums[enum_name], - enum_type = file_to_update[enum_name][1], - is_hex = file_to_update[enum_name][2]) + enum_member_list = new_enum, + enum_type = enum_type_name, + is_hex = is_enum_hex) print(f'Updated enum: {enum_name}') # ============================================================ Private Methods ============================================================ -def _extract_enums(cpp_file): +def _extract_cpp_enums(cpp_file): """ Extract the enums from the provided C++ file + :param cpp_file: (String) The C++ file with full location :return: (Dictionary) The collected enums """ @@ -65,12 +110,55 @@ return enums -def _generate_enum_file(file_location: str, - enum_name: str, - enum_member_list: List[dict], - enum_type: str='Enum', - is_hex: bool=False) -> None: +def _extract_python_enums(py_file): """ + Extract the enums from the provided Python file + + :param py_file: (String) The Python file with full location + :return: (Dictionary) The collected enums + """ + result = {} + inside_enum = False + enum_name = None + + with open(py_file, "r", encoding="utf-8") as f: + for line in f: + # If we are not inside an enum, check if this line declares an enum class + if not inside_enum: + match = re.match(r"class (\w+)\(\w+Enum\):", line) + if match: + enum_name = match.group(1) + result[enum_name] = [] + inside_enum = True + continue + + # If we are inside an enum, process the enum members + else: + # Skip empty lines within the enum definition + if line.strip() == '': + continue + + # If the line is not indented, it means the enum definition has ended + if not line.startswith(' '): + inside_enum = False + continue + + match = re.match(r"\s*(\w+)\s*=\s*([0-9A-Fa-fx]+)\s*#\s*(.*)", line ) + if match: + member, value, comment = match.groups() + result[enum_name].append( { "member": member, + "value": int(value, 0), + "comment": comment, + } ) + return result + + +def _generate_python_enum_file(file_location: str, + enum_name: str, + enum_member_list: List[dict], + enum_type: str='Enum', + is_hex: bool=False) -> None: + """ Generate the enum file content :param file_location: (String) The enum file with full location :param enum_name: (String) The enum's name @@ -145,7 +233,46 @@ return lines +def _update_cpp_repo(cpp_repo: str) -> None: + """ + Update the C++ repository to ensure the latest changes are available for parsing. + :param cpp_repo: (String) The C++ folder with full location + :return: None + """ + try: + # # Switch to the staging branch + # subprocess.run( + # ["git", "-C", cpp_repo, "checkout", "staging"], + # check=True + # ) + + # Get latest refs from remote + subprocess.run( + ["git", "-C", cpp_repo, "fetch", "origin"], + check=True + ) + + # Discard all local changes + subprocess.run( + ["git", "-C", cpp_repo, "reset", "--hard", "HEAD"], + check=True + ) + + subprocess.run( + ["git", "-C", cpp_repo, "pull"], + check=True, + capture_output=True, + text=True + ) + print(f"Successfully updated repository: {cpp_repo}") + + except subprocess.CalledProcessError as e: + print(f"Failed to update repository: {cpp_repo}") + print(e.stderr) + + + # ============================================================ Main ============================================================ if __name__ == '__main__': EnumUpdater.execute()