Index: leahi_dialin/common/dd_defs_proxy.py =================================================================== diff -u -rd10bf8fc145e54979dbeadaedfbaccf0f45d8234 -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/common/dd_defs_proxy.py (.../dd_defs_proxy.py) (revision d10bf8fc145e54979dbeadaedfbaccf0f45d8234) +++ leahi_dialin/common/dd_defs_proxy.py (.../dd_defs_proxy.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -82,14 +82,17 @@ SystemRecordFields = generic_defs.SystemRecordFields ServiceRecordFields = generic_defs.ServiceRecordFields CalibrationRecordFields = generic_defs.get_calibration_record_fields() - InstitutionalRecordFields = generic_defs.InstitutionalRecordFields + InstitutionalRecordBasicFields = generic_defs.InstitutionalRecordBasicFields + InstitutionalRecordAdvancedFields = generic_defs.InstitutionalRecordAdvancedFields + InstitutionalRecordAdditionalFields = generic_defs.InstitutionalRecordAdditionalFields UsageInformationRecordFields = generic_defs.UsageInformationRecordFields # Record support CalibRecordAccelerometerFields = generic_defs.CalibRecordAccelerometerFields CalibRecordBloodLeakFields = generic_defs.CalibRecordBloodLeakFields CalibRecordConcentrateFields = generic_defs.CalibRecordConcentrateFields CalibRecordSensorFields = generic_defs.CalibRecordSensorFields + CalibRecordConductivityFields = generic_defs.CalibRecordConductivityFields dd_enum_repository = DD_Defs() Index: leahi_dialin/common/generic_defs.py =================================================================== diff -u -r4c11f61e1e328407ed98a1b81a3e8b0adb278bd5 -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/common/generic_defs.py (.../generic_defs.py) (revision 4c11f61e1e328407ed98a1b81a3e8b0adb278bd5) +++ leahi_dialin/common/generic_defs.py (.../generic_defs.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -17,7 +17,7 @@ from enum import unique from ..utils.enums import DialinEnum -from .dd_defs import DDPressureSensorNames, DDTemperatureSensorNames, DDConcentratePumpNames, DDDialysatePumpNames +from .dd_defs import DDPressureSensorNames, DDTemperatureSensorNames, DDConcentratePumpNames, DDConductivitySensorNames, DDDialysatePumpNames from .disp_defs import AcidTypes, BicarbTypes from .fp_defs import FPPressureSensorNames @@ -191,32 +191,28 @@ ACCEL_Y_OFFSET = (1, DataTypes.F32) # DD accelerometer Y axis offset ACCEL_Z_OFFSET = (2, DataTypes.F32) # DD accelerometer Z axis offset CALIBRATION_TIME = (3, DataTypes.U32) # Calibration time - CRC = (4, DataTypes.U16) # CRC - NUM_OF_CALIBRATION_RECORD_ACCELEROMETER_FIELDS = (5, DataTypes.NONE) # Number of Calibration Record Accelerometer's Fields + NUM_OF_CALIBRATION_RECORD_ACCELEROMETER_FIELDS = (4, DataTypes.NONE) # Number of Calibration Record Accelerometer's Fields CalibRecordAccelerometerFields._str_list = { # Official Name : Accepted strings 'ACCEL_X_OFFSET': [], 'ACCEL_Y_OFFSET': [], 'ACCEL_Z_OFFSET': [], 'CALIBRATION_TIME': [], - 'CRC': [], 'NUM_OF_CALIBRATION_RECORD_ACCELEROMETER_FIELDS': [], } @unique class CalibRecordBloodLeakFields(RecordsBaseEnum): SET_POINT = (0, DataTypes.U16) # DD Blood leak sensor set point - CALIBRATION_TIME = (3, DataTypes.U32) # Calibration time - CRC = (4, DataTypes.U16) # CRC - NUM_OF_CALIBRATION_RECORD_BLOOD_LEAK_FIELDS = (5, DataTypes.NONE) # Number of Calibration Record Accelerometer's Fields + CALIBRATION_TIME = (1, DataTypes.U32) # Calibration time + NUM_OF_CALIBRATION_RECORD_BLOOD_LEAK_FIELDS = (2, DataTypes.NONE) # Number of Calibration Record Accelerometer's Fields CalibRecordBloodLeakFields._str_list = { # Official Name : Accepted strings 'SET_POINT': [], 'CALIBRATION_TIME': [], - 'CRC': [], 'NUM_OF_CALIBRATION_RECORD_BLOOD_LEAK_FIELDS': [], } @@ -228,8 +224,7 @@ CONDUCTIVITY_USPCM = (2, DataTypes.F32) # Acid or Bicarb conductivity in uS/cm. BOTTLE_TEMPERATURE_C = (3, DataTypes.F32) # Acid or Bicarb bottle temperature in C. CALIBRATION_TIME = (4, DataTypes.U32) # Calibration time - CRC = (5, DataTypes.U16) # CRC - NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS = (6, DataTypes.NONE) # Number of Calibration Record Acid and Bicarb Concentrate's Fields + NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS = (5, DataTypes.NONE) # Number of Calibration Record Acid and Bicarb Concentrate's Fields CalibRecordConcentrateFields._str_list = { # Official Name : Accepted strings @@ -238,31 +233,58 @@ 'CONDUCTIVITY_USPCM': [], 'BOTTLE_TEMPERATURE_C': [], 'CALIBRATION_TIME': [], - 'CRC': [], 'NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS': [], } @unique +class CalibRecordConductivityFields(RecordsBaseEnum): + K_HIGH = (0, DataTypes.F32) # Cell Coefficient High + ALPHA_HIGH = (1, DataTypes.F32) # Temperature correction High + ETA_HIGH = (2, DataTypes.F32) # Resistance Scale Factor High + ZETA_HIGH = (3, DataTypes.F32) # Resistance Offset High + K_LOW = (4, DataTypes.F32) # Cell Coefficient Low + ALPHA_LOW = (5, DataTypes.F32) # Temperature correction Low + ETA_LOW = (6, DataTypes.F32) # Resistance Scale Factor Low + ZETA_LOW = (7, DataTypes.F32) # Resistance Offset Low + BETA = (8, DataTypes.F32) # Temperature Scale Factor + DELTA = (9, DataTypes.F32) # Temperature Offset + RSRVD_1 = (10, DataTypes.F32) # Reserved slot + RSRVD_2 = (11, DataTypes.F32) # Reserved slot + CALIBRATION_TIME = (12, DataTypes.U32) # Calibration time + NUM_OF_CALIBRATION_RECORD_CONDUCTIVITY_FIELDS = (13, DataTypes.NONE) # Number of Calibration Record Conductivity Fields + +CalibRecordConductivityFields._str_list = { + # Official Name : Accepted strings + 'K_HIGH': [], + 'ALPHA_HIGH': [], + 'ETA_HIGH': [], + 'ZETA_HIGH': [], + 'K_LOW': [], + 'ALPHA_LOW': [], + 'ETA_LOW': [], + 'ZETA_LOW': [], + 'BETA': [], + 'DELTA': [], + 'RSRVD_1': [], + 'RSRVD_2': [], + 'CALIBRATION_TIME': [], + 'NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS': [], +} + + +@unique class CalibRecordSensorFields(RecordsBaseEnum): - FOURTH_ORDER_COEFF = (0, DataTypes.F32) # Sensor's Fourth order coefficient - THIRD_ORDER_COEFF = (1, DataTypes.F32) # Sensor's Third order coefficient - SECOND_ORDER_COEFF = (2, DataTypes.F32) # Sensor's Second order coefficient - GAIN = (3, DataTypes.F32) # Sensor's Gain - OFFSET = (4, DataTypes.F32) # Sensor's Offset - CALIBRATION_TIME = (5, DataTypes.U32) # Sensor's Calibration time - CRC = (6, DataTypes.U16) # Sensor's CRC - NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS = (7, DataTypes.NONE) # Number of Calibration Record Sensor's Fields + GAIN = (0, DataTypes.F32) # Sensor's Gain + OFFSET = (1, DataTypes.F32) # Sensor's Offset + CALIBRATION_TIME = (2, DataTypes.U32) # Sensor's Calibration time + NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS = (3, DataTypes.NONE) # Number of Calibration Record Sensor's Fields CalibRecordSensorFields._str_list = { # Official Name : Accepted strings - 'FORTH_ORDER_COEFF': [], - 'THIRD_ORDER_COEFF': [], - 'SECOND_ORDER_COEFF': [], 'GAIN': [], 'OFFSET': [], 'CALIBRATION_TIME': [], - 'CRC': [], 'NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS': [], } @@ -296,16 +318,14 @@ TOP_LEVEL_SN = (3, DataTypes.U08, 20) # Top level serial number MFG_LOCATION = (4, DataTypes.U08) # Manufacturing Location MFG_DATE = (5, DataTypes.U32) # Manufacturing Date - CRC = (6, DataTypes.U16) # CRC - NUM_OF_SYSTEM_RECORD_FIELDS = (7, DataTypes.NONE) # Number of System Record Fields + NUM_OF_SYSTEM_RECORD_FIELDS = (6, DataTypes.NONE) # Number of System Record Fields SystemRecordFields._str_list = { # Official Name : Accepted strings 'TOP_LEVEL_PN': ['pn', 'part number'], 'TOP_LEVEL_SN': ['sn', 'serial number'], 'MFG_LOCATION': ['location', 'manufacturing location'], 'MFG_DATE': ['date', 'manufacturing date'], - 'CRC': [], 'NUM_OF_SYSTEM_RECORD_FIELDS': [], } @@ -318,8 +338,7 @@ LAST_SERVICE_EPOCH_DATE = (3, DataTypes.U32) # DD last service date in epoch SERVICE_INTERVAL_SECONDS = (4, DataTypes.U32) # DD service interval in seconds LAST_RESET_TIME_EPOCH = (5, DataTypes.U32) # Last time the record was reset in epoch - CRC = (6, DataTypes.U16) # CRC - NUM_OF_SERVICE_RECORD_FIELDS = (7, DataTypes.NONE) # Number of Service Record Fields + NUM_OF_SERVICE_RECORD_FIELDS = (6, DataTypes.NONE) # Number of Service Record Fields ServiceRecordFields._str_list = { # Official Name : Accepted strings @@ -329,7 +348,6 @@ 'LAST_SERVICE_EPOCH_DATE': [], 'SERVICE_INTERVAL_SECONDS': [], 'LAST_RESET_TIME_EPOCH': [], - 'CRC': [], 'NUM_OF_SERVICE_RECORD_FIELDS': [], } @@ -380,8 +398,6 @@ i += 1 members[f'DIAL__{dial_pump.name}__{CalibRecordSensorFields.CALIBRATION_TIME.name}'] = (i, CalibRecordSensorFields.CALIBRATION_TIME.datatype()) i += 1 - members[f'DIAL__{dial_pump.name}__{CalibRecordSensorFields.CRC.name}'] = (i, CalibRecordSensorFields.CRC.datatype()) - i += 1 else: for field_name in CalibRecordSensorFields: if 'num_' in field_name.name.lower(): @@ -414,6 +430,14 @@ continue members[f'BLOOD_LEAK__{field_name.name}'] = (i, field_name.datatype()) i += 1 + for cond_sensor in DDConductivitySensorNames: + if 'num_' in cond_sensor.name.lower(): + continue + for field_name in CalibRecordConductivityFields: + if 'num_' in field_name.name.lower(): + continue + members[f'COND__{cond_sensor.name}__{field_name.name}'] = (i, field_name.datatype()) + i += 1 members[f'NUM_OF_CALIBRATION_RECORD_FIELDS'] = (i, DataTypes.NONE) # Enum creation @@ -428,34 +452,33 @@ @unique -class InstitutionalRecordFields(RecordsBaseEnum): - MIN_DIALYSATE_SYSTEM_FLOW_MLPM = (0, DataTypes.U32) # Min dialysate flow in mL/min - MAX_DIALYSATE_SYSTEM_FLOW_MLPM = (1, DataTypes.U32) # Max dialysate flow in mL/min - MIN_DIALYSATE_TEMP_C = (2, DataTypes.F32) # Min dialysate temperature in C - MAX_DIALYSATE_TEMP_C = (3, DataTypes.F32) # Max dialysate temperature in C - MIN_ACID_CONCENTRATE = (4, DataTypes.U32) # Min Acid concentrate - MAX_ACID_CONCENTRATE = (5, DataTypes.U32) # Max Acid concentrate - MIN_BICARB_CARTRIDGE_SIZE_G = (6, DataTypes.U32) # Min Bicarbonate cartridge size in grams - MAX_BICARB_CARTRIDGE_SIZE_G = (7, DataTypes.U32) # Max Bicarbonate cartridge size in grams - MIN_SODIUM_MEQPL = (8, DataTypes.U32) # Min sodium in mEq/L - MAX_SODIUM_MEQPL = (9, DataTypes.U32) # Max sodium in mEq/L - MIN_BICARBONATE_MEQPL = (10, DataTypes.U32) # Min bicarbonate in mEq/L - MAX_BICARBONATE_MEQPL = (11, DataTypes.U32) # Max bicarbonate in mEq/L - MIN_RO_REJECTION_RATIO_PCT = (12, DataTypes.U32) # Min RO rejection ratio in percent - DISINFECTION_FREQUENCY = (13, DataTypes.U32) # Disinfection days between cycles - DISINFECTION_CYCLE_TIME = (14, DataTypes.F32) # Disinfection Cycle Time - MIN_INLET_WATER_CIND_AKARN_LIMIT_USPCM = (15, DataTypes.F32) # Min inlet water conductivity alarm limit in uS/cm - MAX_INLET_WATER_CIND_AKARN_LIMIT_USPCM = (16, DataTypes.F32) # Max inlet water conductivity alarm limit in uS/cm - ACID_CONCENTRATE_JUG_SIZE_L = (17, DataTypes.F32) # acid concentrate jug size in Liters - MIN_ACID_ALARM_LIMIT_PCT = (18, DataTypes.F32) # Min acid alarm limit in percent - MIN_BICARB_ALARM_LIMIT_PCT = (19, DataTypes.F32) # Min bicarbonate alarm limit in percent - POST_TREAT_DRAIN_OPTION = (20, DataTypes.U32) # Dialysate Post Treatment Drain Option  - POST_TREAT_DRY_BICARB_OPTION = (21, DataTypes.U32) # Dry Bicarbonate Post Treatment Option  - CALIBRATION_TIME = (22, DataTypes.U32) # Calibration time in epoch. - CRC = (23, DataTypes.U16) # CRC - NUM_OF_INSTITUTIONAL_RECORD_FIELDS = (24, DataTypes.NONE) # Number of Institutional Record Fields +class InstitutionalRecordBasicFields(RecordsBaseEnum): + MIN_DIALYSATE_SYSTEM_FLOW_MLPM = (0, DataTypes.U32) # Min dialysate flow in mL/min + MAX_DIALYSATE_SYSTEM_FLOW_MLPM = (1, DataTypes.U32) # Max dialysate flow in mL/min + MIN_DIALYSATE_TEMP_C = (2, DataTypes.F32) # Min dialysate temperature in C + MAX_DIALYSATE_TEMP_C = (3, DataTypes.F32) # Max dialysate temperature in C + MIN_ACID_CONCENTRATE = (4, DataTypes.U32) # Min Acid concentrate + MAX_ACID_CONCENTRATE = (5, DataTypes.U32) # Max Acid concentrate + MIN_BICARB_CARTRIDGE_SIZE_G = (6, DataTypes.U32) # Min Bicarbonate cartridge size in grams + MAX_BICARB_CARTRIDGE_SIZE_G = (7, DataTypes.U32) # Max Bicarbonate cartridge size in grams + MIN_SODIUM_MEQPL = (8, DataTypes.U32) # Min sodium in mEq/L + MAX_SODIUM_MEQPL = (9, DataTypes.U32) # Max sodium in mEq/L + MIN_BICARBONATE_MEQPL = (10, DataTypes.U32) # Min bicarbonate in mEq/L + MAX_BICARBONATE_MEQPL = (11, DataTypes.U32) # Max bicarbonate in mEq/L + MIN_RO_REJECTION_RATIO_PCT = (12, DataTypes.F32) # Min RO rejection ratio in percent + DISINFECTION_FREQUENCY = (13, DataTypes.U32) # Disinfection days between cycles + DISINFECTION_CYCLE_TIME = (14, DataTypes.F32) # Disinfection Cycle Time + MIN_INLET_WATER_CIND_AKARN_LIMIT_USPCM = (15, DataTypes.F32) # Min inlet water conductivity alarm limit in uS/cm + MAX_INLET_WATER_CIND_AKARN_LIMIT_USPCM = (16, DataTypes.F32) # Max inlet water conductivity alarm limit in uS/cm + ACID_CONCENTRATE_JUG_SIZE_L = (17, DataTypes.F32) # acid concentrate jug size in Liters + MIN_ACID_ALARM_LIMIT_PCT = (18, DataTypes.F32) # Min acid alarm limit in percent + MIN_BICARB_ALARM_LIMIT_PCT = (19, DataTypes.F32) # Min bicarbonate alarm limit in percent + POST_TREAT_DRAIN_OPTION = (20, DataTypes.U32) # Dialysate Post Treatment Drain Option  + POST_TREAT_DRY_BICARB_OPTION = (21, DataTypes.U32) # Dry Bicarbonate Post Treatment Option  + CALIBRATION_TIME = (22, DataTypes.U32) # Calibration time in epoch. + NUM_OF_INSTITUTIONAL_RECORD_BASIC_FIELDS = (23, DataTypes.NONE) # Number of Institutional Record Basic Fields -InstitutionalRecordFields._str_list = { +InstitutionalRecordBasicFields._str_list = { # Official Name : Accepted strings 'MIN_DIALYSATE_SYSTEM_FLOW_MLPM': [], 'MAX_DIALYSATE_SYSTEM_FLOW_MLPM': [], @@ -478,12 +501,35 @@ 'POST_TREAT_DRAIN_OPTION': [], 'POST_TREAT_DRY_BICARB_OPTION': [], 'CALIBRATION_TIME': [], - 'CRC': [], + 'NUM_OF_INSTITUTIONAL_RECORD_BASIC_FIELDS': [], +} + + +@unique +class InstitutionalRecordAdvancedFields(RecordsBaseEnum): + CALIBRATION_TIME = (0, DataTypes.U32) # Calibration time in epoch. + NUM_OF_INSTITUTIONAL_RECORD_ADVANCED_FIELDS = (1, DataTypes.NONE) # Number of Institutional Record Advanced Fields + +InstitutionalRecordAdvancedFields._str_list = { + # Official Name : Accepted strings + 'CALIBRATION_TIME': [], 'NUM_OF_INSTITUTIONAL_RECORD_FIELDS': [], } @unique +class InstitutionalRecordAdditionalFields(RecordsBaseEnum): + CALIBRATION_TIME = (0, DataTypes.U32) # Calibration time in epoch. + NUM_OF_INSTITUTIONAL_RECORD_ADDITIONAL_FIELDS = (1, DataTypes.NONE) # Number of Institutional Record Additional Fields + +InstitutionalRecordAdditionalFields._str_list = { + # Official Name : Accepted strings + 'CALIBRATION_TIME': [], + 'NUM_OF_INSTITUTIONAL_RECORD_ADDITIONAL_FIELDS': [], +} + + +@unique class UsageInformationRecordFields(RecordsBaseEnum): RO_WATER_GEN_TOTAL_L = (0, DataTypes.F32) # Total RO water generated in liters. (Cannot be reset) RO_WATER_GEN_SINCE_LAST_SERVICE_L = (1, DataTypes.F32) # RO water generated since last treatment in liters @@ -492,8 +538,7 @@ LAST_HEAT_ACTIVE_COOL_COMPLETE_DATE_EPOCH = (4, DataTypes.U32) # Last heat disinfect active cool complete date in epoch. LAST_FILTER_FLUSH_COMPLETE_DATE_EPOCH = (5, DataTypes.U32) # Last filter flush complete date in epoch. LAST_RESET_TIME_EPOCH = (6, DataTypes.U32) # Last time the record was reset in epoch. - CRC = (7, DataTypes.U16) # CRC - NUM_OF_USAGE_INFO_RECORD_FIELDS = (8, DataTypes.NONE) # Number of Usage Information Record Fields + NUM_OF_USAGE_INFO_RECORD_FIELDS = (7, DataTypes.NONE) # Number of Usage Information Record Fields UsageInformationRecordFields._str_list = { # Official Name : Accepted strings @@ -504,6 +549,5 @@ 'LAST_HEAT_ACTIVE_COOL_COMPLETE_DATE_EPOCH': [], 'LAST_FILTER_FLUSH_COMPLETE_DATE_EPOCH': [], 'LAST_RESET_TIME_EPOCH': [], - 'CRC': [], 'NUM_OF_USAGE_INFO_RECORD_FIELDS': [], } Index: leahi_dialin/common/msg_ids.py =================================================================== diff -u -r81e359d6c7ced081bd4580ec3e6cc38939781c6a -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/common/msg_ids.py (.../msg_ids.py) (revision 81e359d6c7ced081bd4580ec3e6cc38939781c6a) +++ leahi_dialin/common/msg_ids.py (.../msg_ids.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -214,6 +214,71 @@ MSG_ID_FP_FILTER_FLUSH_DATA = 0xDD # FP Filter Flush broadcast data MSG_ID_FP_PERMEATE_FLUSH_DATA = 0xDE # FP Permeate Flush broadcast data + MSG_ID_UI_DD_NVM_GET_SYSTEM_RECORD_REQUEST = 0x100 # DD NVM Get System Record Request + MSG_ID_DD_UI_NVM_GET_SYSTEM_RECORD_RESPONSE = 0x101 # DD NVM Get System Record Response + MSG_ID_UI_DD_NVM_SET_SYSTEM_RECORD_REQUEST = 0x102 # DD NVM Set System Record Request + MSG_ID_DD_UI_NVM_SET_SYSTEM_RECORD_RESPONSE = 0x103 # DD NVM Set System Record Response + MSG_ID_UI_DD_NVM_GET_SERVICE_RECORD_REQUEST = 0x104 # DD NVM Get Service Record Request + MSG_ID_DD_UI_NVM_GET_SERVICE_RECORD_RESPONSE = 0x105 # DD NVM Get Service Record Response + MSG_ID_UI_DD_NVM_SET_SERVICE_RECORD_REQUEST = 0x106 # DD NVM Set Service Record Request + MSG_ID_DD_UI_NVM_SET_SERVICE_RECORD_RESPONSE = 0x107 # DD NVM Set Service Record Response + MSG_ID_UI_DD_NVM_GET_INSTIT_BASIC_RECORD_REQUEST = 0x108 # DD NVM Get Institutional Basic Record Request + MSG_ID_DD_UI_NVM_GET_INSTIT_BASIC_RECORD_RESPONSE = 0x109 # DD NVM Get Institutional Basic Record Response + MSG_ID_UI_DD_NVM_SET_INSTIT_BASIC_RECORD_REQUEST = 0x10A # DD NVM Set Institutional Basic Record Request + MSG_ID_DD_UI_NVM_SET_INSTIT_BASIC_RECORD_RESPONSE = 0x10B # DD NVM Set Institutional Basic Record Response + MSG_ID_UI_DD_NVM_GET_INSTIT_ADVANCED_RECORD_REQUEST = 0x10C # DD NVM Get Institutional Advanced Record Request + MSG_ID_DD_UI_NVM_GET_INSTIT_ADVANCED_RECORD_RESPONSE = 0x10D # DD NVM Get Institutional Advanced Record Response + MSG_ID_UI_DD_NVM_SET_INSTIT_ADVANCED_RECORD_REQUEST = 0x10E # DD NVM Get Institutional Advanced Record Request + MSG_ID_DD_UI_NVM_SET_INSTIT_ADVANCED_RECORD_RESPONSE = 0x10F # DD NVM Get Institutional Advanced Record Response + MSG_ID_UI_DD_NVM_GET_INSTIT_ADDITIONAL_RECORD_REQUEST = 0x110 # DD NVM Get Institutional Additional Record Request + MSG_ID_DD_UI_NVM_GET_INSTIT_ADDITIONAL_RECORD_RESPONSE = 0x111 # DD NVM Get Institutional Additional Record Response + MSG_ID_UI_DD_NVM_SET_INSTIT_ADDITIONAL_RECORD_REQUEST = 0x112 # DD NVM Set Institutional Additional Record Request + MSG_ID_DD_UI_NVM_SET_INSTIT_ADDITIONAL_RECORD_RESPONSE = 0x113 # DD NVM Set Institutional Additional Record Response + MSG_ID_UI_DD_NVM_GET_USAGE_INFO_RECORD_REQUEST = 0x114 # DD NVM Get Usage Info Record Request + MSG_ID_DD_UI_NVM_GET_USAGE_INFO_RECORD_RESPONSE = 0x115 # DD NVM Get Usage Info Record Response + MSG_ID_UI_DD_NVM_SET_USAGE_INFO_RECORD_REQUEST = 0x116 # DD NVM Set Usage Info Record Request + MSG_ID_DD_UI_NVM_SET_USAGE_INFO_RECORD_RESPONSE = 0x117 # DD NVM Set Usage Info Record Response + MSG_ID_UI_DD_NVM_GET_PRESSURE_SENSOR_CAL_RECORD_REQUEST = 0x118 # DD NVM Get Pressure Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_GET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE = 0x119 # DD NVM Get Pressure Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_REQUEST = 0x11A # DD NVM Set Pressure Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE = 0x11B # DD NVM Set Pressure Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_GET_TEMPERATURE_SENSOR_CAL_RECORD_REQUEST = 0x11C # DD NVM Get Temperature Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_GET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE = 0x11D # DD NVM Get Temperature Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_REQUEST = 0x11E # DD NVM Set Temperature Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE = 0x11F # DD NVM Set Temperature Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_GET_CONC_PUMP_CAL_RECORD_REQUEST = 0x120 # DD NVM Get Concentrate Pumps Calibration Record Request + MSG_ID_DD_UI_NVM_GET_CONC_PUMP_CAL_RECORD_RESPONSE = 0x121 # DD NVM Get Concentrate Pumps Calibration Record Response + MSG_ID_UI_DD_NVM_SET_CONC_PUMP_CAL_RECORD_REQUEST = 0x122 # DD NVM Set Concentrate Pumps Calibration Record Request + MSG_ID_DD_UI_NVM_SET_CONC_PUMP_CAL_RECORD_RESPONSE = 0x123 # DD NVM Set Concentrate Pumps Calibration Record Response + MSG_ID_UI_DD_NVM_GET_D12_PUMP_CAL_RECORD_REQUEST = 0x124 # DD NVM Get D12 Pump Calibration Record Request + MSG_ID_DD_UI_NVM_GET_D12_PUMP_CAL_RECORD_RESPONSE = 0x125 # DD NVM Get D12 Pump Calibration Record Response + MSG_ID_UI_DD_NVM_SET_D12_PUMP_CAL_RECORD_REQUEST = 0x126 # DD NVM Set D12 Pump Calibration Record Request + MSG_ID_DD_UI_NVM_SET_D12_PUMP_CAL_RECORD_RESPONSE = 0x127 # DD NVM Set D12 Pump Calibration Record Response + MSG_ID_UI_DD_NVM_GET_D48_PUMP_CAL_RECORD_REQUEST = 0x128 # DD NVM Get D48 Pump Calibration Record Request + MSG_ID_DD_UI_NVM_GET_D48_PUMP_CAL_RECORD_RESPONSE = 0x129 # DD NVM Get D48 Pump Calibration Record Response + MSG_ID_UI_DD_NVM_SET_D48_PUMP_CAL_RECORD_REQUEST = 0x12A # DD NVM Set D48 Pump Calibration Record Request + MSG_ID_DD_UI_NVM_SET_D48_PUMP_CAL_RECORD_RESPONSE = 0x12B # DD NVM Set D48 Pump Calibration Record Response + MSG_ID_UI_DD_NVM_GET_ACID_CONC_CAL_RECORD_REQUEST = 0x12C # DD NVM Get Acid Concentrates Calibration Record Request + MSG_ID_DD_UI_NVM_GET_ACID_CONC_CAL_RECORD_RESPONSE = 0x12D # DD NVM Get Acid Concentrates Calibration Record Response + MSG_ID_UI_DD_NVM_SET_ACID_CONC_CAL_RECORD_REQUEST = 0x12E # DD NVM Set Acid Concentrates Calibration Record Request + MSG_ID_DD_UI_NVM_SET_ACID_CONC_CAL_RECORD_RESPONSE = 0x12F # DD NVM Set Acid Concentrates Calibration Record Response + MSG_ID_UI_DD_NVM_GET_BICARB_CONC_CAL_RECORD_REQUEST = 0x130 # DD NVM Get Bicarbonate Concentrates Calibration Record Request + MSG_ID_DD_UI_NVM_GET_BICARB_CONC_CAL_RECORD_RESPONSE = 0x131 # DD NVM Get Bicarbonate Concentrates Calibration Record Response + MSG_ID_UI_DD_NVM_SET_BICARB_CONC_CAL_RECORD_REQUEST = 0x132 # DD NVM Set Bicarbonate Concentrates Calibration Record Request + MSG_ID_DD_UI_NVM_SET_BICARB_CONC_CAL_RECORD_RESPONSE = 0x133 # DD NVM Set Bicarbonate Concentrates Calibration Record Response + MSG_ID_UI_DD_NVM_GET_ACCEL_SENSOR_CAL_RECORD_REQUEST = 0x134 # DD NVM Get Accelerometers Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_GET_ACCEL_SENSOR_CAL_RECORD_RESPONSE = 0x135 # DD NVM Get Accelerometers Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_SET_ACCEL_SENSOR_CAL_RECORD_REQUEST = 0x136 # DD NVM Set Accelerometers Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_SET_ACCEL_SENSOR_CAL_RECORD_RESPONSE = 0x137 # DD NVM Set Accelerometers Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_GET_BLOOD_LEAK_SENSOR_CAL_RECORD_REQUEST = 0x138 # DD NVM Get Blood Leak Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_GET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE = 0x139 # DD NVM Get Blood Leak Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_SET_BLOOD_LEAK_SENSOR_CAL_RECORD_REQUEST = 0x13A # DD NVM Set Blood Leak Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_SET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE = 0x13B # DD NVM Set Blood Leak Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_GET_CONDUCTIVITY_SENSOR_CAL_RECORD_REQUEST = 0x13C # DD NVM Get Conductivity Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_GET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE = 0x13D # DD NVM Get Conductivity Sensor Calibration Record Response + MSG_ID_UI_DD_NVM_SET_CONDUCTIVITY_SENSOR_CAL_RECORD_REQUEST = 0x13E # DD NVM Set Conductivity Sensor Calibration Record Request + MSG_ID_DD_UI_NVM_SET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE = 0x13F # DD NVM Set Conductivity Sensor Calibration Record Response + MSG_ID_TESTER_LOGIN_REQUEST = 0x8000 # TD tester log-in MSG_ID_TD_SOFTWARE_RESET_REQUEST = 0x8001 # TD reset request MSG_ID_TD_SEND_TEST_CONFIGURATION = 0x8002 # TD send test configuration to Dialin Index: leahi_dialin/common/td_defs_proxy.py =================================================================== diff -u -r43f69b19f03145572d88f5f3c0cc739503c6d647 -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/common/td_defs_proxy.py (.../td_defs_proxy.py) (revision 43f69b19f03145572d88f5f3c0cc739503c6d647) +++ leahi_dialin/common/td_defs_proxy.py (.../td_defs_proxy.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -108,7 +108,7 @@ SystemRecordFields = generic_defs.SystemRecordFields ServiceRecordFields = generic_defs.ServiceRecordFields CalibrationRecordFields = generic_defs.get_calibration_record_fields() - InstitutionalRecordFields = generic_defs.InstitutionalRecordFields + InstitutionalRecordFields = generic_defs.InstitutionalRecordBasicFields UsageInformationRecordFields = generic_defs.UsageInformationRecordFields # Record support Index: leahi_dialin/dd/modules/blood_leak.py =================================================================== diff -u -rba415df9f8e76d6b0f21e8f69ba99346e42f7b09 -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/dd/modules/blood_leak.py (.../blood_leak.py) (revision ba415df9f8e76d6b0f21e8f69ba99346e42f7b09) +++ leahi_dialin/dd/modules/blood_leak.py (.../blood_leak.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -85,6 +85,7 @@ self.blood_leak_upper_range_drift_status = 0 self.blood_leak_time_elapsed_since_last_drift_zero_ms = 0 + self.blood_leak_emb_mode_cmds = {} for cmd in EmbModeCommands.__members__: # Initialize all the embedded mode commands self.blood_leak_emb_mode_cmds[cmd] = '' Index: leahi_dialin/dd/modules/records.py =================================================================== diff -u -r28a21f1f2ca4ef02e6d54bae30b738fddb7bdb3a -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/dd/modules/records.py (.../records.py) (revision 28a21f1f2ca4ef02e6d54bae30b738fddb7bdb3a) +++ leahi_dialin/dd/modules/records.py (.../records.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -8,827 +8,401 @@ # @file records.py # # @author (last) Zoltan Miskolci -# @date (last) 22-Jun-2026 +# @date (last) 04-Aug-2026 # @author (original) Zoltan Miskolci # @date (original) 04-May-2026 # ############################################################################ # Module imports from logging import Logger -from functools import partial -from time import sleep # Project imports -from leahi_dialin.common import dd_enum_repository, disp_enum_repository, fp_enum_repository -from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.dd.modules.records_get_responses import DDRecordsGetHandlers +from leahi_dialin.dd.modules.records_get_requests import DDRecordsGetRequests +from leahi_dialin.dd.modules.records_set_responses import DDRecordsSetHandlers +from leahi_dialin.dd.modules.records_set_requests import DDRecordsSetRequests +from leahi_dialin.common import dd_enum_repository +from leahi_dialin.common.msg_defs import RequestRejectReasons from leahi_dialin.common.msg_ids import MsgIds from leahi_dialin.common.override_templates import cmd_generic_override from leahi_dialin.protocols.CAN import CanMessenger, CanChannels -from leahi_dialin.utils.abstract_classes import AbstractSubSystem -from leahi_dialin.utils.base import publish -from leahi_dialin.utils.enums import DialinEnum -from leahi_dialin.utils.conversions import integer_to_bytearray, float_to_bytearray, byte_to_bytearray, unsigned_short_to_bytearray, string_to_bytearray +from leahi_dialin.utils.conversions import integer_to_bytearray -class DDRecords(AbstractSubSystem): +class DDRecords(DDRecordsGetHandlers, DDRecordsGetRequests, DDRecordsSetHandlers, DDRecordsSetRequests): """ DD interface containing pressure related commands. """ def __init__(self, can_interface: CanMessenger, logger: Logger): """ - @param can_interface: The CanMessenger object + The main record class to handle all the subclasses. + + :param can_interface: (CanMessenger) The CanMessenger object + :param logger: (Logger) The Logger object """ - super().__init__() self.can_interface = can_interface self.logger = logger - if self.can_interface is not None: - # Data Request Response messages - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SYSTEM_RECORD_RESPONSE.value, - function = self._handler_system_record_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SERVICE_RECORD_RESPONSE.value, - function = self._handler_service_record_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_PRESSURE_SENSOR_RESPONSE.value, - function = self._handler_calibration_record_pres_sensor_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_TEMP_SENSOR_RESPONSE.value, - function = self._handler_calibration_record_temp_sensor_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_CONC_PUMP_RESPONSE.value, - function = self._handler_calibration_record_conc_pump_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_D12_PUMP_RESPONSE.value, - function = self._handler_calibration_record_dial_pump_d12_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_D48_PUMP_RESPONSE.value, - function = self._handler_calibration_record_dial_pump_d48_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_ACID_CONCENTRATE_RESPONSE.value, - function = self._handler_calibration_record_acid_conc_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_BICARB_CONCENTRATE_RESPONSE.value, - function = self._handler_calibration_record_bicarb_conc_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_ACCEL_SENSOR_RESPONSE.value, - function = self._handler_calibration_record_accelerometer_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_CAL_BLOOD_LEAK_SENSOR_RESPONSE.value, - function = self._handler_calibration_record_blood_leak_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_INSTITUTIONAL_RECORD_RESPONSE.value, - function = self._handler_institutional_record_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_USAGE_INFO_RECORD_RESPONSE.value, - function = self._handler_usage_info_record_sync) - # Set Data Response messages - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_SYSTEM_RECORD_RESPONSE.value, - function = self._handler_system_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_SERVICE_RECORD_RESPONSE.value, - function = self._handler_service_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_PRESSURE_SENSOR_RESPONSE.value, - function = self._handler_cal_pressure_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_TEMP_SENSOR_RESPONSE.value, - function = self._handler_cal_temp_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_CONC_PUMP_RESPONSE.value, - function = self._handler_cal_conc_pump_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_D12_PUMP_RESPONSE.value, - function = self._handler_cal_d12_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_D48_PUMP_RESPONSE.value, - function = self._handler_cal_d48_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_ACID_CONCENTRATE_RESPONSE.value, - function = self._handler_cal_acid_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_BICARB_CONCENTRATE_RESPONSE.value, - function = self._handler_cal_bicarb_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_ACCEL_SENSOR_RESPONSE.value, - function = self._handler_cal_accel_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_CAL_BLOOD_LEAK_SENSOR_RESPONSE.value, - function = self._handler_cal_blood_leak_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_INSTITUTIONAL_RECORD_RESPONSE.value, - function = self._handler_institutional_rr_sync) - self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, - message_id = MsgIds.MSG_ID_DD_NVM_SET_USAGE_INFO_RECORD_RESPONSE.value, - function = self._handler_usage_info_rr_sync) + self.get_system_rec_timestamp = 0 #: The timestamp of the latest System Records message + self.get_system_rec_ack = False + self.get_system_rec_rr = RequestRejectReasons.REQUEST_REJECT_REASON_NONE + + self.system_records = { } + self.set_system_rec_rr_timestamp = 0 #: The timestamp of the latest Set System Reject Reason message + self.set_system_rec_ack = False + self.set_system_rec_rr = { } - self.system_records_timestamp = 0 #: The timestamp of the latest System Records message - self.system_set_rr_timestamp = 0 #: The timestamp of the latest Set System Reject Reason message - self.service_records_timestamp = 0 #: The timestamp of the latest Service Records message - self.service_set_rr_timestamp = 0 #: The timestamp of the latest Set Service Reject Reason message - self.calibration_records_timestamp = 0 #: The timestamp of the latest Calibration Records message - self.calibration_set_rr_timestamp = 0 #: The timestamp of the latest Set Calibration Reject Reason message - self.institutional_records_timestamp = 0 #: The timestamp of the latest Institutional Records message - self.institutional_set_rr_timestamp = 0 #: The timestamp of the latest Set Institutional Reject Reason message - self.usage_info_records_timestamp = 0 #: The timestamp of the latest Usage Information Records message - self.usage_info_set_rr_timestamp = 0 #: The timestamp of the latest Set Usage Information Reject Reason message + self.get_service_rec_timestamp = 0 #: The timestamp of the latest Service Records message + self.get_service_rec_ack = False + self.get_service_rec_rr = RequestRejectReasons.REQUEST_REJECT_REASON_NONE - self.system_records = { } #: The System Records data in dictionary format - self.system_records_ack = { } #: The Set System Records message acceptance - self.system_records_rr = { } #: The Set System Records message reject reason + self.service_records = { } - self.service_records = { } #: The Service Records data in dictionary format - self.service_records_ack = { } #: The Set Service Records message acceptance - self.service_records_rr = { } #: The Set Service Records message reject reason + self.set_service_rec_rr_timestamp = 0 #: The timestamp of the latest Set Service Reject Reason message + self.set_service_rec_ack = False + self.set_service_rec_rr = { } - self.calibration_records = { } #: The Calibration Records data in dictionary format - self.calibration_records_ack = { } #: The Set Calibration Records message acceptance - self.calibration_records_rr = { } #: The Set Calibration Records message reject reason + self.get_calibration_rec_timestamp = 0 #: The timestamp of the latest Calibration Records message + self.get_calibration_rec_ack = { } + self.get_calibration_rec_rr = { } - self.institutional_records = { } #: The Institutional Records data in dictionary format - self.institutional_records_ack = { } #: The Set Institutional Records message acceptance - self.institutional_records_rr = { } #: The Set Institutional Records message reject reason - + self.calibration_records = { } - self.usage_info_records = { } #: The Usage Information Records data in dictionary format - self.usage_info_ack = { } #: The Set Usage Information Records message acceptance - self.usage_info_rr = { } #: The Set Usage Information Records message reject reason + self.set_calibration_rec_rr_timestamp = 0 #: The timestamp of the latest Set Calibration Reject Reason message + self.set_calibration_rec_ack = { } + self.set_calibration_rec_rr = { } - for sys_record in dd_enum_repository.SystemRecordFields: - if 'num_' not in sys_record.name: - self.system_records[sys_record.name] = None + self.get_institutional_rec_timestamp = 0 #: The timestamp of the latest Institutional Records message + self.get_institutional_rec_ack = { } + self.get_institutional_rec_rr = { } - for serv_record in dd_enum_repository.ServiceRecordFields: - if 'num_' not in serv_record.name: - self.service_records[serv_record.name] = None + self.institutional_records = { } - for cal_record in dd_enum_repository.CalibrationRecordFields: - if 'num_' not in cal_record.name: - self.calibration_records[cal_record.name] = None + self.set_institutional_rec_rr_timestamp = 0 #: The timestamp of the latest Set Institutional Reject Reason message + self.set_institutional_rec_ack = False + self.set_institutional_rec_rr = { } - for inst_record in dd_enum_repository.InstitutionalRecordFields: - if 'num_' not in inst_record.name: - self.institutional_records[inst_record.name] = None + self.get_usage_info_rec_timestamp = 0 #: The timestamp of the latest Usage Information Records message + self.get_usage_info_rec_ack = False + self.get_usage_info_rec_rr = RequestRejectReasons.REQUEST_REJECT_REASON_NONE - for usage_record in dd_enum_repository.UsageInformationRecordFields: - if 'num_' not in usage_record.name: - self.usage_info_records[usage_record.name] = None + self.usage_info_records = { } + self.set_usage_info_rec_rr_timestamp = 0 #: The timestamp of the latest Set Usage Information Reject Reason message + self.set_usage_info_rec_ack = False + self.set_usage_info_rec_rr = { } -# ================================================= CAN Message Handler Methods ================================================= - @publish(["msg_id_dd_nvm_send_system_record_response", "system_records", "system_records_timestamp"]) - def _handler_system_record_sync(self, message, timestamp = 0.0): - """ - Handles published DD System Record data messages. DD System Records are captured - for reference. + # Calling the Sub classes: DDRecordsGetHandlers, DDRecordsGetRequests, DDRecordsSetHandlers, DDRecordsSetRequests + # Doing it after initializeing the parameters will make those parameters accessable to the sub classes + super().__init__() - @param message: published data message - @return: none - """ - record_list = [] - for member in dd_enum_repository.SystemRecordFields: - record_list.append((member.name, member.datatype(), member.multichar_length())) - self.process_into_dict(dict_to_update = self.system_records, - decoder_list = record_list, - message = message) - self.system_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_send_service_record_response", "service_records", "service_records_timestamp"]) - def _handler_service_record_sync(self, message, timestamp = 0.0): +# ============================================================ Properties ============================================================ + @property + def system_records(self) -> dict: """ - Handles published DD Service Record data messages. DD Service Records are captured - for reference. - - @param message: published data message - @return: none + The System Records data """ - record_list = [] - for member in dd_enum_repository.ServiceRecordFields: - record_list.append((member.name, member.datatype())) + return self._system_records - self.process_into_dict(dict_to_update = self.service_records, - decoder_list = record_list, - message = message) + @system_records.setter + def system_records(self, value): + self._system_records = value - self.service_records_timestamp = timestamp - - @publish(["msg_id_dd_nvm_cal_pressure_sensor_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_pres_sensor_sync(self, message, timestamp = 0.0): + @property + def service_records(self) -> dict: """ - Handles published DD Calibration Record Pressure Sensor Details data messages. - DD Calibration Records Pressure Sensor Details are captured for reference. - - @param message: published data message - @return: none + The Service Records data """ - # Get the sensor_id to identify the location of the payload - msg_list = [('sensor_id', DataTypes.U08)] - result = self.process_into_vars(decoder_list = msg_list, - message = message) - if int(result['sensor_id']) < dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value: - sensor_name = dd_enum_repository.DDPressureSensorNames(result['sensor_id']).name - else: - fp_sensor_id = int(result['sensor_id']) - dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value - sensor_name = fp_enum_repository.FPPressureSensorNames(fp_sensor_id).name + return self._service_records - record_list = [] - for member in dd_enum_repository.CalibRecordSensorFields: - if member == dd_enum_repository.CalibRecordSensorFields.NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS: - continue - entry_name = f'PRES__{sensor_name}__{member.name}' - record_list.append((entry_name, member.datatype())) + @service_records.setter + def service_records(self, value): + self._service_records = value - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.calibration_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_cal_temp_sensor_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_temp_sensor_sync(self, message, timestamp = 0.0): + @property + def calibration_records(self) -> dict: """ - Handles published DD Calibration Record Temperature Sensor Details data messages. - DD Calibration Records Temperature Sensor Details are captured for reference. - - @param message: published data message - @return: none + The Calibration Records data """ - # Get the sensor_id to identify the location of the payload - msg_list = [('sensor_id', DataTypes.U08)] - result = self.process_into_vars(decoder_list = msg_list, - message = message) - sensor_name = dd_enum_repository.DDTemperatureSensorNames(result['sensor_id']).name + return self._calibration_records - record_list = [] - for member in dd_enum_repository.CalibRecordSensorFields: - if member == dd_enum_repository.CalibRecordSensorFields.NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS: - continue - entry_name = f'TEMP__{sensor_name}__{member.name}' - record_list.append((entry_name, member.datatype())) + @calibration_records.setter + def calibration_records(self, value): + self._calibration_records = value - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.calibration_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_cal_conc_pump_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_conc_pump_sync(self, message, timestamp = 0.0): + @property + def institutional_records(self) -> dict: """ - Handles published DD Calibration Record Concentrate Pump Details data messages. - DD Calibration Records Concentrate Pump Details are captured for reference. - - @param message: published data message - @return: none + The Institutional Records data """ - # Get the sensor_id to identify the location of the payload - msg_list = [('sensor_id', DataTypes.U08)] - result = self.process_into_vars(decoder_list = msg_list, - message = message) - sensor_name = dd_enum_repository.DDConcentratePumpNames(result['sensor_id']).name + return self._institutional_records - record_list = [] - for member in dd_enum_repository.CalibRecordSensorFields: - if member == dd_enum_repository.CalibRecordSensorFields.NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS: - continue - entry_name = f'CONC__{sensor_name}__{member.name}' - record_list.append((entry_name, member.datatype())) + @institutional_records.setter + def institutional_records(self, value): + self._institutional_records = value - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.calibration_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_cal_d12_pump_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_dial_pump_d12_sync(self, message, timestamp = 0.0): + @property + def usage_info_records(self) -> dict: """ - Handles published DD Calibration Record Dialysate Pump D12 Details data messages. - DD Calibration Records Dialysate Pump D12 Details are captured for reference. - - @param message: published data message - @return: none + The Usage Information Records data """ - record_list = [] - record_list.append((f'DIAL__{dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name}__TARGET_SPEED', DataTypes.F32)) - record_list.append((f'DIAL__{dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name}__CALIBRATION_TIME', DataTypes.U32)) - record_list.append((f'DIAL__{dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name}__CRC', DataTypes.U16)) - # for member in dd_enum_repository.CalibRecordSensorFields: - # if member == dd_enum_repository.CalibRecordSensorFields.NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS: - # continue - # entry_name = f'DIAL__{dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name}__{member.name}' - # record_list.append((entry_name, member.datatype())) + return self._usage_info_records - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message) + @usage_info_records.setter + def usage_info_records(self, value): + self._usage_info_records = value - self.calibration_records_timestamp = timestamp - - @publish(["msg_id_dd_nvm_cal_d48_pump_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_dial_pump_d48_sync(self, message, timestamp = 0.0): + @property + def get_system_rec_ack(self) -> bool: """ - Handles published DD Calibration Record Dialysate Pump D48 Details data messages. - DD Calibration Records Dialysate Pump D48 Details are captured for reference. - - @param message: published data message - @return: none + The Get System Records message acceptance """ - record_list = [] - for member in dd_enum_repository.CalibRecordSensorFields: - if member == dd_enum_repository.CalibRecordSensorFields.NUM_OF_CALIBRATION_RECORD_SENSOR_FIELDS: - continue - entry_name = f'DIAL__{dd_enum_repository.DDDialysatePumpNames.D48_PUMP.name}__{member.name}' - record_list.append((entry_name, member.datatype())) + return self._get_system_rec_ack - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message) + @get_system_rec_ack.setter + def get_system_rec_ack(self, value): + self._get_system_rec_ack = value - self.calibration_records_timestamp = timestamp - - @publish(["msg_id_dd_nvm_cal_acid_concentrate_sensor", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_acid_conc_sync(self, message, timestamp = 0.0): + @property + def get_service_rec_ack(self) -> bool: """ - Handles published DD Calibration Record Acid Concentrate Details data messages. - DD Calibration Records Acid Concentrate Details are captured for reference. - - @param message: published data message - @return: none + The Get Service Records message acceptance """ - msg_list = [('sensor_id', DataTypes.U08)] - result = self.process_into_vars(decoder_list=msg_list, - message=message) - acid_type_name = disp_enum_repository.AcidTypes(result['sensor_id']).name + return self._get_service_rec_ack - record_list = [] - for member in dd_enum_repository.CalibRecordConcentrateFields: - if member == dd_enum_repository.CalibRecordConcentrateFields.NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS: - continue - record_list.append((f'ACID__{acid_type_name}__{member.name}', member.datatype())) + @get_service_rec_ack.setter + def get_service_rec_ack(self, value): + self._get_service_rec_ack = value - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.calibration_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_cal_bicarb_concentrate_sensor", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_bicarb_conc_sync(self, message, timestamp = 0.0): + @property + def get_calibration_rec_ack(self) -> dict: """ - Handles published DD Calibration Record Bicarb Concentrate Details data messages. - DD Calibration Records Bicarb Concentrate Details are captured for reference. - - @param message: published data message - @return: none + The Get Calibration Records message acceptance """ - msg_list = [('sensor_id', DataTypes.U08)] - result = self.process_into_vars(decoder_list=msg_list, - message=message) - bicarb_type_name = disp_enum_repository.BicarbTypes(result['sensor_id']).name + return self._get_calibration_rec_ack - record_list = [] - for member in dd_enum_repository.CalibRecordConcentrateFields: - if member == dd_enum_repository.CalibRecordConcentrateFields.NUM_OF_CALIBRATION_RECORD_CONCENTRATE_FIELDS: - continue - record_list.append((f'BICARB__{bicarb_type_name}__{member.name}', member.datatype())) + @get_calibration_rec_ack.setter + def get_calibration_rec_ack(self, value): + self._get_calibration_rec_ack = value - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.calibration_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_cal_accel_sensor_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_accelerometer_sync(self, message, timestamp = 0.0): + @property + def get_institutional_rec_ack(self) -> dict: """ - Handles published DD Calibration Record Accelerometer Details data messages. - DD Calibration Records Accelerometer Details are captured for reference. - - @param message: published data message - @return: none + The Get Institutional Records message acceptance """ - record_list = [] - for member in dd_enum_repository.CalibRecordAccelerometerFields: - if member == dd_enum_repository.CalibRecordAccelerometerFields.NUM_OF_CALIBRATION_RECORD_ACCELEROMETER_FIELDS: - continue - record_list.append((f'ACCEL__{member.name}', member.datatype())) + return self._get_institutional_rec_ack - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message) + @get_institutional_rec_ack.setter + def get_institutional_rec_ack(self, value): + self._get_institutional_rec_ack = value - self.calibration_records_timestamp = timestamp - - @publish(["msg_id_dd_nvm_cal_blood_leak_response", "calibration_records", "calibration_records_timestamp"]) - def _handler_calibration_record_blood_leak_sync(self, message, timestamp = 0.0): + @property + def get_usage_info_rec_ack(self) -> bool: """ - Handles published DD Calibration Record Blood Leak Details data messages. - DD Calibration Records Blood Leak Details are captured for reference. - - @param message: published data message - @return: none + The Get Usage Information Records message acceptance """ - record_list = [] - for member in dd_enum_repository.CalibRecordBloodLeakFields: - if member == dd_enum_repository.CalibRecordBloodLeakFields.NUM_OF_CALIBRATION_RECORD_BLOOD_LEAK_FIELDS: - continue - record_list.append((f'BLOOD_LEAK__{member.name}', member.datatype())) + return self._get_usage_info_rec_ack - self.process_into_dict(dict_to_update = self.calibration_records, - decoder_list = record_list, - message = message) + @get_usage_info_rec_ack.setter + def get_usage_info_rec_ack(self, value): + self._get_usage_info_rec_ack = value - self.calibration_records_timestamp = timestamp - - @publish(["msg_id_dd_nvm_institutional_record_response", "institutional_records", "institutional_records_timestamp"]) - def _handler_institutional_record_sync(self, message, timestamp = 0.0): + @property + def get_system_rec_rr(self) -> dict: """ - Handles published DD Institutional Record data messages. DD Institutional Records are captured - for reference. - - @param message: published data message - @return: none + The Get System Records Request reject reason data """ - msg_list = [('record_id', DataTypes.U08)] - results = self.process_into_vars(decoder_list = msg_list, - message = message) + return self._get_system_rec_rr - record_id = int(results['record_id']) - member = dd_enum_repository.InstitutionalRecordFields(record_id) - - record_list = [] - record_list.append((member.name, member.datatype())) + @get_system_rec_rr.setter + def get_system_rec_rr(self, value): + self._get_system_rec_rr = value - self.process_into_dict(dict_to_update = self.institutional_records, - decoder_list = record_list, - message = message, - start_from_byte = len(msg_list) * msg_list[0][1].size()) - self.institutional_records_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_usage_info_record_response", "usage_info_records", "usage_info_records_timestamp"]) - def _handler_usage_info_record_sync(self, message, timestamp = 0.0): + @property + def get_service_rec_rr(self) -> dict: """ - Handles published DD Usage Information Record data messages. DD Usage Information Records are captured - for reference. - - @param message: published data message - @return: none + The Get Service Records Request reject reason data """ - record_list = [] - for member in dd_enum_repository.UsageInformationRecordFields: - record_list.append((member.name, member.datatype())) + return self._get_service_rec_rr - self.process_into_dict(dict_to_update = self.usage_info_records, - decoder_list = record_list, - message = message) + @get_service_rec_rr.setter + def get_service_rec_rr(self, value): + self._get_service_rec_rr = value - self.usage_info_records_timestamp = timestamp - -# ================================================= Reject Reason Message Handler Methods ================================================= - @publish(["msg_id_dd_nvm_set_system_record_response", "system_records_ack", "system_records_rr", "system_set_rr_timestamp"]) - def _handler_system_rr_sync(self, message, timestamp = 0.0): + @property + def get_calibration_rec_rr(self) -> dict: """ - Handles published DD Set System Records Reject Reason data messages. DD Set System Records Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Get Calibration Records Request reject reason data """ - msg_list = [] - msg_list.append(('self.system_records_ack', DataTypes.BOOL)) - msg_list.append(('self.system_records_rr', DataTypes.U32)) + return self._get_calibration_rec_rr - self.process_into_vars(decoder_list = msg_list, - message = message) + @get_calibration_rec_rr.setter + def get_calibration_rec_rr(self, value): + self._get_calibration_rec_rr = value - self.system_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_service_record_response", "system_records_ack", "service_records_rr", "service_set_rr_timestamp"]) - def _handler_service_rr_sync(self, message, timestamp = 0.0): + @property + def get_institutional_rec_rr(self) -> dict: """ - Handles published DD Set Service Records Reject Reason data messages. DD Set Service Records Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Get Institutional Records Request reject reason data """ - msg_list = [] - msg_list.append(('self.service_records_ack', DataTypes.BOOL)) - msg_list.append(('self.service_records_rr', DataTypes.U32)) + return self._get_institutional_rec_rr - self.process_into_vars(decoder_list = msg_list, - message = message) + @get_institutional_rec_rr.setter + def get_institutional_rec_rr(self, value): + self._get_institutional_rec_rr = value - self.service_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_institutional_record_response", "institutional_records_rr", "institutional_set_rr_timestamp"]) - def _handler_institutional_rr_sync(self, message, timestamp = 0.0): + @property + def get_usage_info_rec_rr(self) -> dict: """ - Handles published DD Set Institutional Records Reject Reason data messages. DD Set Institutional Records Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Get Usage Information Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._get_usage_info_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if result['id'] not in self.institutional_records_rr: - self.institutional_records_rr[result['id']] = {} - self.institutional_records_rr[result['id']]['ack'] = result['ack'] - self.institutional_records_rr[result['id']]['rr'] = result['rr'] + @get_usage_info_rec_rr.setter + def get_usage_info_rec_rr(self, value): + self._get_usage_info_rec_rr = value - self.institutional_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_usage_info_record_response", "usage_info_ack", "usage_info_rr", "usage_info_set_rr_timestamp"]) - def _handler_usage_info_rr_sync(self, message, timestamp = 0.0): + @property + def set_system_rec_ack(self) -> bool: """ - Handles published DD Set Usage Information Records Reject Reason data messages. DD Set Usage Information Records Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set System Records message acceptance """ - msg_list = [] - msg_list.append(('self.usage_info_ack', DataTypes.BOOL)) - msg_list.append(('self.usage_info_rr', DataTypes.U32)) + return self._set_system_rec_ack - self.process_into_vars(decoder_list = msg_list, - message = message) + @set_system_rec_ack.setter + def set_system_rec_ack(self, value): + self._set_system_rec_ack = value - self.usage_info_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_cal_pressure_sensor_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_pressure_rr_sync(self, message, timestamp = 0.0): + @property + def set_service_rec_ack(self) -> bool: """ - Handles published DD Set Calibration Records for Pressure Sensor Reject Reason data messages.DD Set Calibration Records for Pressure Sensor Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Service Records message acceptance """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._set_service_rec_ack - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if 'pres' not in self.calibration_records_rr: - self.calibration_records_rr['pres'] = {} - if result['id'] not in self.calibration_records_rr: - self.calibration_records_rr['pres'][result['id']] = {} - self.calibration_records_rr['pres'][result['id']]['ack'] = result['ack'] - self.calibration_records_rr['pres'][result['id']]['rr'] = result['rr'] + @set_service_rec_ack.setter + def set_service_rec_ack(self, value): + self._set_service_rec_ack = value - self.calibration_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_cal_temp_sensor_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_temp_rr_sync(self, message, timestamp = 0.0): + @property + def set_calibration_rec_ack(self) -> dict: """ - Handles published DD Set Calibration Records for Temperature Sensor Reject Reason data messages.DD Set Calibration Records for Temperature Sensor Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Calibration Records message acceptance """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._set_calibration_rec_ack - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if 'temp' not in self.calibration_records_rr: - self.calibration_records_rr['temp'] = {} - if result['id'] not in self.calibration_records_rr: - self.calibration_records_rr['temp'][result['id']] = {} - self.calibration_records_rr['temp'][result['id']]['ack'] = result['ack'] - self.calibration_records_rr['temp'][result['id']]['rr'] = result['rr'] + @set_calibration_rec_ack.setter + def set_calibration_rec_ack(self, value): + self._set_calibration_rec_ack = value - self.calibration_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_cal_conc_pump_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_conc_pump_rr_sync(self, message, timestamp = 0.0): + @property + def set_institutional_rec_ack(self) -> dict: """ - Handles published DD Set Calibration Records for Concentrate Pump Reject Reason data messages.DD Set Calibration Records for Concentrate Pump Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Institutional Records message acceptance """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._set_institutional_rec_ack - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if 'conc' not in self.calibration_records_rr: - self.calibration_records_rr['conc'] = {} - if result['id'] not in self.calibration_records_rr: - self.calibration_records_rr['conc'][result['id']] = {} - self.calibration_records_rr['conc'][result['id']]['ack'] = result['ack'] - self.calibration_records_rr['conc'][result['id']]['rr'] = result['rr'] + @set_institutional_rec_ack.setter + def set_institutional_rec_ack(self, value): + self._set_institutional_rec_ack = value - self.calibration_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_cal_d12_pump_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_d12_rr_sync(self, message, timestamp = 0.0): + @property + def set_usage_info_rec_ack(self) -> bool: """ - Handles published DD Set Calibration Records for D12 Dialisate Pump Reject Reason data messages.DD Set Calibration Records for D12 Dialisate Pump Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Usage Information Records message acceptance """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) + return self._set_usage_info_rec_ack - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if 'dial' not in self.calibration_records_rr: - self.calibration_records_rr['dial'] = {} - if 'd12_pump' not in self.calibration_records_rr: - self.calibration_records_rr['dial']['d12_pump'] = {} - self.calibration_records_rr['dial']['d12_pump']['ack'] = result['ack'] - self.calibration_records_rr['dial']['d12_pump']['rr'] = result['rr'] + @set_usage_info_rec_ack.setter + def set_usage_info_rec_ack(self, value): + self._set_usage_info_rec_ack = value - self.calibration_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_cal_d48_pump_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_d48_rr_sync(self, message, timestamp = 0.0): + @property + def set_system_rec_rr(self) -> dict: """ - Handles published DD Set Calibration Records for D48 Dialisate Pump Reject Reason data messages.DD Set Calibration Records for D48 Dialisate Pump Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set System Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) + return self._set_system_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) - - if 'dial' not in self.calibration_records_rr: - self.calibration_records_rr['dial'] = {} - if 'd48_pump' not in self.calibration_records_rr: - self.calibration_records_rr['dial']['d48_pump'] = {} - self.calibration_records_rr['dial']['d48_pump']['ack'] = result['ack'] - self.calibration_records_rr['dial']['d48_pump']['rr'] = result['rr'] + @set_system_rec_rr.setter + def set_system_rec_rr(self, value): + self._set_system_rec_rr = value - self.calibration_set_rr_timestamp = timestamp - - @publish(["msg_id_dd_nvm_set_acid_concentrate_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_acid_rr_sync(self, message, timestamp = 0.0): + @property + def set_service_rec_rr(self) -> dict: """ - Handles published DD Set Calibration Records for Acid Concentrate Reject Reason data messages.DD Set Calibration Records for Acid Concentrate Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Service Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._set_service_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) + @set_service_rec_rr.setter + def set_service_rec_rr(self, value): + self._set_service_rec_rr = value - if 'acid' not in self.calibration_records_rr: - self.calibration_records_rr['acid'] = {} - if result['id'] not in self.calibration_records_rr: - self.calibration_records_rr['acid'][result['id']] = {} - self.calibration_records_rr['acid'][result['id']]['ack'] = result['ack'] - self.calibration_records_rr['acid'][result['id']]['rr'] = result['rr'] - self.calibration_set_rr_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_set_cal_bicarb_concentrate_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_bicarb_rr_sync(self, message, timestamp = 0.0): + @property + def set_calibration_rec_rr(self) -> dict: """ - Handles published DD Set Calibration Records for Bicarb Concentrate Reject Reason data messages.DD Set Calibration Records for Bicarb Concentrate Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Calibration Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) - msg_list.append(('id', DataTypes.U32)) + return self._set_calibration_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) + @set_calibration_rec_rr.setter + def set_calibration_rec_rr(self, value): + self._set_calibration_rec_rr = value - if 'bicarb' not in self.calibration_records_rr: - self.calibration_records_rr['bicarb'] = {} - if result['id'] not in self.calibration_records_rr: - self.calibration_records_rr['bicarb'][result['id']] = {} - self.calibration_records_rr['bicarb'][result['id']]['ack'] = result['ack'] - self.calibration_records_rr['bicarb'][result['id']]['rr'] = result['rr'] - self.calibration_set_rr_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_set_cal_accel_sensor_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_accel_rr_sync(self, message, timestamp = 0.0): + @property + def set_institutional_rec_rr(self) -> dict: """ - Handles published DD Set Calibration Records for Accelerometer Sensor Reject Reason data messages.DD Set Calibration Records for Accelerometer Sensor Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Institutional Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) + return self._set_institutional_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) + @set_institutional_rec_rr.setter + def set_institutional_rec_rr(self, value): + self._set_institutional_rec_rr = value - if 'accel' not in self.calibration_records_rr: - self.calibration_records_rr['accel'] = {} - self.calibration_records_rr['accel']['ack'] = result['ack'] - self.calibration_records_rr['accel']['rr'] = result['rr'] - self.calibration_set_rr_timestamp = timestamp - - - @publish(["msg_id_dd_nvm_set_cal_blood_leak_sensor_response", "calibration_records_rr", "calibration_set_rr_timestamp"]) - def _handler_cal_blood_leak_rr_sync(self, message, timestamp = 0.0): + @property + def set_usage_info_rec_rr(self) -> dict: """ - Handles published DD Set Calibration Records for Blood Leak Sensor Reject Reason data messages.DD Set Calibration Records for Blood Leak Sensor Reject Reason are captured - for reference. - - @param message: published data message - @return: none + The Set Usage Information Records Request reject reason data """ - msg_list = [] - msg_list.append(('ack', DataTypes.BOOL)) - msg_list.append(('rr', DataTypes.U32)) + return self._set_usage_info_rec_rr - result = self.process_into_vars(decoder_list = msg_list, - message = message) + @set_usage_info_rec_rr.setter + def set_usage_info_rec_rr(self, value): + self._set_usage_info_rec_rr = value - if 'blood_leak' not in self.calibration_records_rr: - self.calibration_records_rr['blood_leak'] = {} - self.calibration_records_rr['blood_leak']['ack'] = result['ack'] - self.calibration_records_rr['blood_leak']['rr'] = result['rr'] - self.calibration_set_rr_timestamp = timestamp - # ================================================= Go to Service Mode Method ================================================= def cmd_initiate_service_mode(self) -> int: """ @@ -852,628 +426,3 @@ override_text = f'set to {service_mode.name}', logger = self.logger, can_interface = self.can_interface) - - - -# ================================================= Request Records Methods ================================================= - def cmd_request_system_records(self) -> int: - """ - Constructs and sends a request for System Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = byte_to_bytearray(dd_enum_repository.RecordTypes.SYSTEM_RECORD.value) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_RECORD_REQUEST, - entity_name = f'DD System Record request', - override_text = '', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_request_service_records(self) -> int: - """ - Constructs and sends a request for Service Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = byte_to_bytearray(dd_enum_repository.RecordTypes.SERVICE_RECORD.value) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_RECORD_REQUEST, - entity_name = f'DD Service Record request', - override_text = '', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_request_calibration_records(self) -> int: - """ - Constructs and sends a request for Calibration Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = byte_to_bytearray(dd_enum_repository.RecordTypes.CALIBRATION_RECORD.value) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_RECORD_REQUEST, - entity_name = f'DD Calibration Record request', - override_text = '', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_request_institutional_records(self) -> int: - """ - Constructs and sends a request for Institutional Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = byte_to_bytearray(dd_enum_repository.RecordTypes.INSTITUTIONAL_RECORD.value) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_RECORD_REQUEST, - entity_name = f'DD Institutional Record request', - override_text = '', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_request_usage_information_records(self) -> int: - """ - Constructs and sends a request for Usage Information Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = byte_to_bytearray(dd_enum_repository.RecordTypes.USAGE_INFORMATION_RECORD.value) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_RECORD_REQUEST, - entity_name = f'DD Usage Information Record request', - override_text = '', - logger = self.logger, - can_interface = self.can_interface) - - - -# ================================================= Set Records Main Methods ================================================= - def cmd_set_system_records(self, - is_ro_featured: bool=False, - is_ro_featured_boost_pump: bool=False, - part_number: str='0000000000', - serial_number: str='00000000000000000000', - manufacturing_location: int=0, - manufacturing_date: int=0) -> int: - """ - Constructs and sends a command for setting the System Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - if len(part_number) != 10: - raise ValueError(f'part_number must be 10 characters, provided is: {len(part_number)}') - if len(serial_number) != 20: - raise ValueError(f'serial must be 20 characters, provided is: {len(serial_number)}') - - payload = integer_to_bytearray(is_ro_featured) - payload += integer_to_bytearray(is_ro_featured_boost_pump) - payload += string_to_bytearray(part_number) - payload += string_to_bytearray(serial_number) - payload += byte_to_bytearray(manufacturing_location) - payload += integer_to_bytearray(manufacturing_date) - payload += unsigned_short_to_bytearray(self.crc16(payload)) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_SYSTEM_RECORD_REQUEST, - entity_name = f'New DD System Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_set_service_records(self, - is_hdf_online: bool=False, - water_recovery: int=0, - service_loc: int=0, - last_service_date: int=0, - service_interval_sec: int=0, - last_reset_time: int=0) -> int: - """ - Constructs and sends a command for setting the Service Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = integer_to_bytearray(is_hdf_online) - payload += integer_to_bytearray(water_recovery) - payload += byte_to_bytearray(service_loc) - payload += integer_to_bytearray(last_service_date) - payload += integer_to_bytearray(service_interval_sec) - payload += integer_to_bytearray(last_reset_time) - payload += unsigned_short_to_bytearray(self.crc16(payload)) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_SERVICE_RECORD_REQUEST, - entity_name = f'New DD Service Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_set_calibration_records(self, calibration_records: dict={}) -> int: - """ - Constructs and sends a command for setting the Calibration Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @param calibration_records: (Dictionary) The stored and structured Calibration Records - @return: 1 if successful, zero otherwise - """ - msg_id_pairing = { - 'PRES': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_PRESSURE_SENSOR_REQUEST, - 'TEMP': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_TEMP_SENSOR_REQUEST, - 'CONC': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_CONC_PUMP_REQUEST, - 'DIAL': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D48_PUMP_REQUEST, - 'ACID': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_ACID_CONCENTRATE_REQUEST, - 'BICARB': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_BICARB_CONCENTRATE_REQUEST, - 'ACCEL': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_ACCEL_SENSOR_REQUEST, - 'BLOOD_LEAK': MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_BLOOD_LEAK_SENSOR_REQUEST, - } - # Make a dictionary to store all the send functions for later send - send_data = [] - checked = [] - for record_enum in dd_enum_repository.CalibrationRecordFields: - record_parts = record_enum.name.split('__') - group = record_parts[0] - - # If a message already sent, then just go to the next value - if 'NUM_' in group or \ - group in checked or \ - record_parts[1] in checked: - continue - - if group in ['PRES', 'TEMP', 'CONC', 'DIAL']: - # Set the sensor name - if group == 'PRES': - sensor = dd_enum_repository.DDPressureSensorNames.from_str(record_parts[1]) - if sensor is None: - sensor = fp_enum_repository.FPPressureSensorNames.from_str(record_parts[1]) - elif group == 'TEMP': - sensor = dd_enum_repository.DDTemperatureSensorNames.from_str(record_parts[1]) - elif group == 'CONC': - sensor = dd_enum_repository.DDConcentratePumpNames.from_str(record_parts[1]) - elif group == 'DIAL': - sensor = dd_enum_repository.DDDialysatePumpNames.from_str(record_parts[1]) - else: - sensor = 'UNKNOWN' - - # Set the arguments for the call - args = [] - kwargs = {} - target_speed_entry_name = f'{group}__{sensor.name}__TARGET_SPEED' - fourth_order_coeff_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.FOURTH_ORDER_COEFF.name}' - third_order_coeff_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.THIRD_ORDER_COEFF.name}' - second_order_coeff_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.SECOND_ORDER_COEFF.name}' - gain_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.GAIN.name}' - offset_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.OFFSET.name}' - calibration_time_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name}' - - kwargs['sensor_enum'] = sensor - if sensor == dd_enum_repository.DDDialysatePumpNames.D12_PUMP: - kwargs['msg_id'] = MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D12_PUMP_REQUEST - else: - kwargs['msg_id'] = msg_id_pairing[group] - - if target_speed_entry_name in calibration_records and calibration_records[target_speed_entry_name] is not None: - kwargs['dialysate_pump_target_speed'] = calibration_records[target_speed_entry_name] - - if fourth_order_coeff_entry_name in calibration_records and calibration_records[fourth_order_coeff_entry_name] is not None: - kwargs['fourth_order_coeff'] = calibration_records[fourth_order_coeff_entry_name] - - if third_order_coeff_entry_name in calibration_records and calibration_records[third_order_coeff_entry_name] is not None: - kwargs['third_order_coeff'] = calibration_records[third_order_coeff_entry_name] - - if second_order_coeff_entry_name in calibration_records and calibration_records[second_order_coeff_entry_name] is not None: - kwargs['second_order_coeff'] = calibration_records[second_order_coeff_entry_name] - - if gain_entry_name in calibration_records and calibration_records[gain_entry_name] is not None: - kwargs['gain'] = calibration_records[gain_entry_name] - - if offset_entry_name in calibration_records and calibration_records[offset_entry_name] is not None: - kwargs['offset'] = calibration_records[offset_entry_name] - - if calibration_time_entry_name in calibration_records and calibration_records[calibration_time_entry_name] is not None: - kwargs['calibration_time'] = calibration_records[calibration_time_entry_name] - - checked.append(record_parts[1]) - # Skip sending if dictionary is provided but all entry for the sensor was None (except sensor_enum and MSG_ID, because those are neccesary) - if calibration_records != {} and len(kwargs) == 2: - continue - - # Create the send data function - send_data.append(partial(self.cmd_set_calibration_records_sensor, *args, **kwargs)) - - elif group in ['ACID', 'BICARB']: - if group == 'ACID': - sensor = disp_enum_repository.AcidTypes.from_str(record_parts[1]) - elif group == 'BICARB': - sensor = disp_enum_repository.BicarbTypes.from_str(record_parts[1]) - else: - sensor = 'unknown' - - # Set the arguments for the call - args = [] - kwargs = {} - concentrate_mix_ratio_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name}' - volume_ml_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name}' - conductivity_uspcm_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name}' - temperature_c_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name}' - calibration_time_entry_name = f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name}' - - kwargs['sensor_enum'] = sensor - kwargs['msg_id'] = msg_id_pairing[group] - if concentrate_mix_ratio_entry_name in calibration_records and calibration_records[concentrate_mix_ratio_entry_name] is not None: - kwargs['concentrate_mix_ratio'] = calibration_records[concentrate_mix_ratio_entry_name] - - if volume_ml_entry_name in calibration_records and calibration_records[volume_ml_entry_name] is not None: - kwargs['volume_ml'] = calibration_records[volume_ml_entry_name] - - if conductivity_uspcm_entry_name in calibration_records and calibration_records[conductivity_uspcm_entry_name] is not None: - kwargs['conductivity_uspcm'] = calibration_records[conductivity_uspcm_entry_name] - - if temperature_c_entry_name in calibration_records and calibration_records[temperature_c_entry_name] is not None: - kwargs['temperature_c'] = calibration_records[temperature_c_entry_name] - - if calibration_time_entry_name in calibration_records and calibration_records[calibration_time_entry_name] is not None: - kwargs['calibration_time'] = calibration_records[calibration_time_entry_name] - - checked.append(record_parts[1]) - # Skip sending if dictionary is provided but all entry for the sensor was None (except MSG_ID, because that is neccesary) - if calibration_records != {} and len(kwargs) == 1: - continue - - # Store the function but do not execute it - send_data.append(partial(self.cmd_set_calibration_records_concentrate, *args, **kwargs)) - - elif group in ['ACCEL']: - # Set the arguments for the call - args = [] - kwargs = {} - accel_x_offset_entry_name = f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_X_OFFSET.name}' - accel_y_offset_entry_name = f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Y_OFFSET.name}' - accel_z_offset_entry_name = f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Z_OFFSET.name}' - calibration_time_entry_name = f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.CALIBRATION_TIME.name}' - - kwargs['msg_id'] = msg_id_pairing[group] - if accel_x_offset_entry_name in calibration_records and calibration_records[accel_x_offset_entry_name] is not None: - kwargs['accel_x_offset'] = calibration_records[accel_x_offset_entry_name] - - if accel_y_offset_entry_name in calibration_records and calibration_records[accel_y_offset_entry_name] is not None: - kwargs['accel_y_offset'] = calibration_records[accel_y_offset_entry_name] - - if accel_z_offset_entry_name in calibration_records and calibration_records[accel_z_offset_entry_name] is not None: - kwargs['accel_z_offset'] = calibration_records[accel_z_offset_entry_name] - - if calibration_time_entry_name in calibration_records and calibration_records[calibration_time_entry_name] is not None: - kwargs['calibration_time'] = calibration_records[calibration_time_entry_name] - - checked.append(group) - # Skip sending if dictionary is provided but all entry for the sensor was None (except MSG_ID, because that is neccesary) - if calibration_records != {} and len(kwargs) == 1: - continue - - # Store the function but do not execute it - send_data.append(partial(self.cmd_set_calibration_records_accelerometer, *args, **kwargs)) - - elif group in ['BLOOD_LEAK']: - # Set the arguments for the call - args = [] - kwargs = {} - set_point_entry_name = f'{group}__{dd_enum_repository.CalibRecordBloodLeakFields.SET_POINT.name}' - calibration_time_entry_name = f'{group}__{dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name}' - - kwargs['msg_id'] = msg_id_pairing[group] - if set_point_entry_name in calibration_records and calibration_records[set_point_entry_name] is not None: - kwargs['set_point'] = calibration_records[set_point_entry_name] - - if calibration_time_entry_name in calibration_records and calibration_records[calibration_time_entry_name] is not None: - kwargs['calibration_time'] = calibration_records[calibration_time_entry_name] - - checked.append(group) - # Skip sending if dictionary is provided but all entry for the sensor was None (except MSG_ID, because that is neccesary) - if calibration_records != {} and len(kwargs) == 1: - continue - - # Store the function but do not execute it - send_data.append(partial(self.cmd_set_calibration_records_blood_leak, *args, **kwargs)) - - # Execute the stored functions one by one - # Remove the ones that got 1 (successfully recieved) as response - # Retry the ones that are failed 2 more times - retry = 0 - while send_data != [] and retry < 3: - failed = [] - for func in send_data: - resp = func() - if resp == 1: - failed.append(func) - send_data = failed - retry += 1 - sleep(0.005) # Wait 50ms between sends - - - def cmd_set_institutional_records(self, institutional_records: dict={}) -> int: - """ - Constructs and sends a command for setting the Institutional Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @param institutional_records: (Dictionary) The stored and structured Institutional Records - @return: 1 if successful, zero otherwise - """ - # Make a dictionary to store all the send functions for later send - send_data = [] - for record_enum in dd_enum_repository.InstitutionalRecordFields: - # Set the enum_id to identify which parameter is being sent U08 - 1 byte - 0->255 !! - payload = byte_to_bytearray(record_enum.value) - - if record_enum in [dd_enum_repository.InstitutionalRecordFields.CRC, dd_enum_repository.InstitutionalRecordFields.NUM_OF_INSTITUTIONAL_RECORD_FIELDS]: - # Skip the Number of fields - continue - elif institutional_records == {}: - # Set default values if it's missing from the provided dictionary - if record_enum.datatype() in [DataTypes.U32, DataTypes.BOOL, DataTypes.S32, DataTypes.U16, DataTypes.U08, DataTypes.BOOL_U08]: - value = 0 - elif record_enum.datatype() in [DataTypes.F32]: - value = 0.0 - elif record_enum.name in institutional_records and institutional_records[record_enum.name] is not None: - # If record present in the dict and value is not None - value = institutional_records[record_enum.name] - else: - # If record is not present in the dict or it doesn't have value, skip sending it - continue - - if record_enum.datatype() in [DataTypes.U32, DataTypes.BOOL, DataTypes.S32]: - payload += integer_to_bytearray(value) - elif record_enum.datatype() in [DataTypes.F32]: - payload += float_to_bytearray(value) - elif record_enum.datatype() in [DataTypes.U16]: - payload += unsigned_short_to_bytearray(value) - elif record_enum.datatype() in [DataTypes.U08, DataTypes.BOOL_U08]: - payload += byte_to_bytearray(value) - - send_data.append(partial(cmd_generic_override, - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_INSTITUTIONAL_RECORD_REQUEST, - entity_name = f'DD Institutional Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface)) - - # Execute the stored functions one by one - # Remove the ones that got 1 (successfully recieved) as response - # Retry the ones that are failed 2 more times - retry = 0 - while send_data != [] and retry < 3: - failed = [] - for func in send_data: - resp = func() - if resp == 1: - failed.append(func) - send_data = failed - retry += 1 - sleep(0.005) # Wait 50ms between sends - - - def cmd_set_usage_info_records(self, - ro_water_gen_total_l: float=0.0, - ro_water_gen_since_last_serv_l: float=0.0, - last_basic_flush_date: int=0, - last_heat_disinfect_date: int=0, - last_heat_active_cool_date: int=0, - last_filter_flush_date: int=0, - last_reset_time: int=0) -> int: - """ - Constructs and sends a command for setting the Usage Information Records. - Constraints: - Must be logged into DD. - Must be in Service mode. - - @return: 1 if successful, zero otherwise - """ - payload = float_to_bytearray(ro_water_gen_total_l) - payload += float_to_bytearray(ro_water_gen_since_last_serv_l) - payload += integer_to_bytearray(last_basic_flush_date) - payload += integer_to_bytearray(last_heat_disinfect_date) - payload += integer_to_bytearray(last_heat_active_cool_date) - payload += integer_to_bytearray(last_filter_flush_date) - payload += integer_to_bytearray(last_reset_time) - payload += unsigned_short_to_bytearray(self.crc16(payload)) - - return cmd_generic_override( - payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_USAGE_INFO_RECORD_REQUEST, - entity_name = f'New DD Usage Information Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - -# ================================================= Set Records Support Methods ================================================= - def cmd_set_calibration_records_sensor(self, - sensor_enum: DialinEnum, - msg_id: MsgIds, - dialysate_pump_target_speed: float=0.0, - fourth_order_coeff: float=0.0, - third_order_coeff: float=0.0, - second_order_coeff: float=0.0, - gain: float=0.0, - offset: float=0.0, - calibration_time: int = 1) -> int: - if isinstance(sensor_enum, fp_enum_repository.FPPressureSensorNames): - payload_sensor = byte_to_bytearray(sensor_enum.value + dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value) - else: - payload_sensor = byte_to_bytearray(sensor_enum.value) - payload_content = b'' - if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D12_PUMP_REQUEST: - payload_content += float_to_bytearray(dialysate_pump_target_speed) - else: - payload_content += float_to_bytearray(fourth_order_coeff) - payload_content += float_to_bytearray(third_order_coeff) - payload_content += float_to_bytearray(second_order_coeff) - payload_content += float_to_bytearray(gain) - payload_content += float_to_bytearray(offset) - payload_content += integer_to_bytearray(calibration_time) - payload_content += unsigned_short_to_bytearray(self.crc16(payload_content)) - if msg_id in [MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D12_PUMP_REQUEST, MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D48_PUMP_REQUEST]: - payload = payload_content - else: - payload = payload_sensor + payload_content - - sensor_type = '' - if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_PRESSURE_SENSOR_REQUEST: - sensor_type = 'Pressure Sensor' - elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_TEMP_SENSOR_REQUEST: - sensor_type = 'Temperature Sensor' - elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_CONC_PUMP_REQUEST: - sensor_type = 'Concentrate Pump' - elif msg_id in [MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D12_PUMP_REQUEST, MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D48_PUMP_REQUEST]: - sensor_type = 'Dialysate Pump' - - return cmd_generic_override(payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = msg_id, - entity_name = f'DD {sensor_type} {sensor_enum.name} Calibration Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_set_calibration_records_concentrate(self, - sensor_enum: DialinEnum, - msg_id: MsgIds, - concentrate_mix_ratio: float=0.0, - volume_ml: float=0.0, - conductivity_uspcm: float=0.0, - temperature_c: float=0.0, - calibration_time: int = 1) -> int: - - payload_sensor = byte_to_bytearray(sensor_enum.value) - payload_content = float_to_bytearray(concentrate_mix_ratio) - payload_content += float_to_bytearray(volume_ml) - payload_content += float_to_bytearray(conductivity_uspcm) - payload_content += float_to_bytearray(temperature_c) - payload_content += integer_to_bytearray(calibration_time) - payload_content += unsigned_short_to_bytearray(self.crc16(payload_content)) - payload = payload_sensor + payload_content - - conc_type = '' - if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_ACID_CONCENTRATE_REQUEST: - conc_type = 'Acid' - elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_BICARB_CONCENTRATE_REQUEST: - conc_type = 'Bicarb' - - return cmd_generic_override(payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = msg_id, - entity_name = f'DD {conc_type} Concentrate Calibration Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - def cmd_set_calibration_records_accelerometer(self, - msg_id: MsgIds, - accel_x_offset: float=0.0, - accel_y_offset: float=0.0, - accel_z_offset: float=0.0, - calibration_time: int = 1) -> int: - - payload = float_to_bytearray(accel_x_offset) - payload += float_to_bytearray(accel_y_offset) - payload += float_to_bytearray(accel_z_offset) - payload += integer_to_bytearray(calibration_time) - payload += unsigned_short_to_bytearray(self.crc16(payload)) - - return cmd_generic_override(payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = msg_id, - entity_name = f'DD Accelerometer Calibration Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - - def cmd_set_calibration_records_blood_leak(self, - msg_id: MsgIds, - set_point: int=0, - calibration_time: int = 1) -> int: - - payload = unsigned_short_to_bytearray(set_point) - payload += integer_to_bytearray(calibration_time) - payload += unsigned_short_to_bytearray(self.crc16(payload)) - - return cmd_generic_override(payload = payload, - reset = None, - channel_id = CanChannels.dialin_to_dd_ch_id, - msg_id = msg_id, - entity_name = f'DD Blood Leak Calibration Record', - override_text = 'being set', - logger = self.logger, - can_interface = self.can_interface) - - - -# ================================================= Private Methods ================================================= Index: leahi_dialin/dd/modules/records_get_requests.py =================================================================== diff -u --- leahi_dialin/dd/modules/records_get_requests.py (revision 0) +++ leahi_dialin/dd/modules/records_get_requests.py (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -0,0 +1,440 @@ +########################################################################### +# +# Copyright (c) 2020-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 records_get_requests.py +# +# @author (last) Zoltan Miskolci +# @date (last) 04-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 04-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common import dd_enum_repository, disp_enum_repository, fp_enum_repository +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.common.override_templates import cmd_generic_override +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem +from leahi_dialin.utils.conversions import unsigned_integer_to_bytearray + + +class DDRecordsGetRequests(AbstractSubSystem): + """ + Part of the DD Records + """ + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the get handlers. + """ + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + # ================================================= Request Records Methods ================================================= + def cmd_request_system_records(self) -> int: + """ + Constructs and sends a request for System Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_SYSTEM_RECORD_REQUEST, + entity_name = f'DD System Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_service_records(self) -> int: + """ + Constructs and sends a request for Service Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_SERVICE_RECORD_REQUEST, + entity_name = f'DD Service Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_all_calibration_records(self) -> None: + """ + Constructs and sends a request for Calibration Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: None + """ + for pres_sensor in dd_enum_repository.DDPressureSensorNames: + self.cmd_request_calibration_pressure_record(pres_sensor.value) + for pres_sensor in fp_enum_repository.FPPressureSensorNames: + self.cmd_request_calibration_pressure_record(pres_sensor.value + dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value) + + for temp_sensor in dd_enum_repository.DDTemperatureSensorNames: + self.cmd_request_calibration_temperature_record(temp_sensor.value) + + for conc_pump in dd_enum_repository.DDConcentratePumpNames: + self.cmd_request_calibration_concentrate_record(conc_pump.value) + + self.cmd_request_calibration_dialysate_d12_record() + self.cmd_request_calibration_dialysate_d48_record() + + for acid_conc in disp_enum_repository.AcidTypes: + self.cmd_request_calibration_acid_record(acid_conc.value) + + for bicarb_conc in disp_enum_repository.BicarbTypes: + self.cmd_request_calibration_bicarb_record(bicarb_conc.value) + + self.cmd_request_calibration_accelerometer_record() + self.cmd_request_calibration_blood_leak_record() + + for cond_sensor in dd_enum_repository.DDConductivitySensorNames: + self.cmd_request_calibration_conductivity_record(cond_sensor.value) + + + def cmd_request_calibration_pressure_record(self, sensor_id: int) -> int: + """ + Constructs and sends a request for Pressure Sensor Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(sensor_id) + + # Get the name of the sensor + if sensor_id >= dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value: + sensor_name = fp_enum_repository.FPPressureSensorNames(sensor_id).name + else: + sensor_name = dd_enum_repository.DDPressureSensorNames(sensor_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_PRESSURE_SENSOR_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Pressure {sensor_name} sensor', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_temperature_record(self, sensor_id: int) -> int: + """ + Constructs and sends a request for Temperature Sensor Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(sensor_id) + + # Get the name of the sensor + sensor_name = dd_enum_repository.DDTemperatureSensorNames(sensor_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_TEMPERATURE_SENSOR_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Temparature {sensor_name} sensor', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_concentrate_record(self, pump_id: int) -> int: + """ + Constructs and sends a request for Concentrate Pump Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(pump_id) + + # Get the name of the sensor + pump_name = dd_enum_repository.DDConcentratePumpNames(pump_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_CONC_PUMP_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Concentrate {pump_name} pump', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_dialysate_d12_record(self) -> int: + """ + Constructs and sends a request for Dialysate D12 Pump Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_D12_PUMP_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Dialysate D12 pump', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_dialysate_d48_record(self) -> int: + """ + Constructs and sends a request for Dialysate D48 Pump Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_D48_PUMP_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Dialysate D48 pump', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_acid_record(self, conc_id: int) -> int: + """ + Constructs and sends a request for Acid Concentrate Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(conc_id) + + # Get the name of the sensor + conc_name = disp_enum_repository.AcidTypes(conc_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_ACID_CONC_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Acid concentrate: {conc_name}', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_bicarb_record(self, conc_id: int) -> int: + """ + Constructs and sends a request for Bicarb Concentrate Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(conc_id) + + # Get the name of the sensor + conc_name = disp_enum_repository.BicarbTypes(conc_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_BICARB_CONC_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Bicarb concentrate: {conc_name}', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_accelerometer_record(self) -> int: + """ + Constructs and sends a request for Accelerometer Sensor Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_ACCEL_SENSOR_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Accelerometer sensor', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_blood_leak_record(self) -> int: + """ + Constructs and sends a request for Blood Leak Sensor Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_BLOOD_LEAK_SENSOR_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Blood Leak sensor', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_calibration_conductivity_record(self, sensor_id: int) -> int: + """ + Constructs and sends a request for Conductivity Sensor Calibration Record. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = unsigned_integer_to_bytearray(sensor_id) + + # Get the name of the sensor + sensor_name = dd_enum_repository.DDConductivitySensorNames(sensor_id).name + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_CONDUCTIVITY_SENSOR_CAL_RECORD_REQUEST, + entity_name = f'DD Calibration Record request for Conductivity {sensor_name} sensor', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_all_institutional_records(self) -> int: + """ + Constructs and sends a request for All Institutional Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + resp_basic = self.cmd_request_institutional_basic_records() + resp_adv = self.cmd_request_institutional_advanced_records() + resp_add = self.cmd_request_institutional_additional_records() + return (resp_basic * 100) + (resp_adv * 10) + resp_add + + + def cmd_request_institutional_basic_records(self) -> int: + """ + Constructs and sends a request for Basic Institutional Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_INSTIT_BASIC_RECORD_REQUEST, + entity_name = f'DD Basic Institutional Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_institutional_advanced_records(self) -> int: + """ + Constructs and sends a request for Advanced Institutional Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_INSTIT_ADVANCED_RECORD_REQUEST, + entity_name = f'DD Advanced Institutional Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_institutional_additional_records(self) -> int: + """ + Constructs and sends a request for Additional Institutional Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_INSTIT_ADDITIONAL_RECORD_REQUEST, + entity_name = f'DD Additional Institutional Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_usage_information_records(self) -> int: + """ + Constructs and sends a request for Usage Information Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_GET_USAGE_INFO_RECORD_REQUEST, + entity_name = f'DD Usage Information Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) Index: leahi_dialin/dd/modules/records_get_responses.py =================================================================== diff -u --- leahi_dialin/dd/modules/records_get_responses.py (revision 0) +++ leahi_dialin/dd/modules/records_get_responses.py (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -0,0 +1,674 @@ +########################################################################### +# +# Copyright (c) 2020-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 records_get_responses.py +# +# @author (last) Zoltan Miskolci +# @date (last) 04-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 04-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common import dd_enum_repository, disp_enum_repository, fp_enum_repository +from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.common.msg_defs import RequestRejectReasons +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem, LocalVars +from leahi_dialin.utils.base import publish + + +class DDRecordsGetHandlers(AbstractSubSystem): + """ + Part of the DD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the get handlers. + """ + if self.can_interface is not None: + # Data Request Response messages + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_SYSTEM_RECORD_RESPONSE.value, + function = self._handler_system_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_SERVICE_RECORD_RESPONSE.value, + function = self._handler_service_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_pres_sensor_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_temp_sensor_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_CONC_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_conc_pump_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_D12_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_dial_pump_d12_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_D48_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_dial_pump_d48_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_ACID_CONC_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_acid_conc_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_BICARB_CONC_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_bicarb_conc_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_ACCEL_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_accelerometer_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_blood_leak_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_calibration_record_cond_sensor_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_BASIC_RECORD_RESPONSE.value, + function = self._handler_institutional_basic_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_ADVANCED_RECORD_RESPONSE.value, + function = self._handler_institutional_adv_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_ADDITIONAL_RECORD_RESPONSE.value, + function = self._handler_institutional_add_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_GET_USAGE_INFO_RECORD_RESPONSE.value, + function = self._handler_usage_info_record_sync) + + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + +# ================================================= CAN Message Handler Methods ================================================= + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_SYSTEM_RECORD_RESPONSE.name.lower(), "get_system_rec_ack", "get_system_rec_rr", "system_records", "get_system_rec_timestamp"]) + def _handler_system_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD System Record data messages. + DD System Records are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).get_system_rec_ack, DataTypes.BOOL)) + msg_list.append((type(self).get_system_rec_rr, DataTypes.U32)) + for member in dd_enum_repository.SystemRecordFields: + if member is not dd_enum_repository.SystemRecordFields.NUM_OF_SYSTEM_RECORD_FIELDS: + msg_list.append((self.system_records, member.name, member.datatype(), member.multichar_length())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_system_rec_rr, int): + self.get_system_rec_rr = RequestRejectReasons(self.get_system_rec_rr) + self.get_system_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_SERVICE_RECORD_RESPONSE.name.lower(), "get_service_rec_ack", "get_service_rec_rr", "service_records", "get_service_rec_timestamp"]) + def _handler_service_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD Service Record data messages. + DD Service Records are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).get_service_rec_ack, DataTypes.BOOL)) + msg_list.append((type(self).get_service_rec_rr, DataTypes.U32)) + for member in dd_enum_repository.ServiceRecordFields: + if member is not dd_enum_repository.ServiceRecordFields.NUM_OF_SERVICE_RECORD_FIELDS: + msg_list.append((self.system_records, member.name, member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_service_rec_rr, int): + self.get_service_rec_rr = RequestRejectReasons(self.get_service_rec_rr) + self.get_service_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_pres_sensor_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Pressure Sensor Details data messages. + DD Calibration Records Pressure Sensor Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + sensor_id = LocalVars('sensor_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.F32)) + msg_list.append((offset, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Pressure Sensor Name + if sensor_id.value < dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value: + sensor_name = dd_enum_repository.DDPressureSensorNames(sensor_id.value).name + else: + sensor_name = fp_enum_repository.FPPressureSensorNames(sensor_id.value - dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'PRES__{sensor_name}__{gain.name}'] = gain.value + self.calibration_records[f'PRES__{sensor_name}__{offset.name}'] = offset.value + self.calibration_records[f'PRES__{sensor_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'PRES__{sensor_name}'] = acceptance.value + self.get_calibration_rec_rr[f'PRES__{sensor_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_temp_sensor_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Temperature Sensor Details data messages. + DD Calibration Records Temperature Sensor Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + sensor_id = LocalVars('sensor_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.F32)) + msg_list.append((offset, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Temperature Sensor Name + sensor_name = dd_enum_repository.DDTemperatureSensorNames(sensor_id.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'TEMP__{sensor_name}__{gain.name}'] = gain.value + self.calibration_records[f'TEMP__{sensor_name}__{offset.name}'] = offset.value + self.calibration_records[f'TEMP__{sensor_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'TEMP__{sensor_name}'] = acceptance.value + self.get_calibration_rec_rr[f'TEMP__{sensor_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_CONC_PUMP_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_conc_pump_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Concentrate Pump Details data messages. + DD Calibration Records Concentrate Pump Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + sensor_id = LocalVars('sensor_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.F32)) + msg_list.append((offset, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Concentrate Pump Name + pump_name = dd_enum_repository.DDConcentratePumpNames(sensor_id.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'CONC__{pump_name}__{gain.name}'] = gain.value + self.calibration_records[f'CONC__{pump_name}__{offset.name}'] = offset.value + self.calibration_records[f'CONC__{pump_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'CONC__{pump_name}'] = acceptance.value + self.get_calibration_rec_rr[f'CONC__{pump_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_D12_PUMP_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_dial_pump_d12_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Dialysate Pump D12 Details data messages. + DD Calibration Records Dialysate Pump D12 Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + target_speed = LocalVars('TARGET_SPEED') + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((target_speed, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Dialysate Pump Name + pump_name = dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'DIAL__{pump_name}__{target_speed.name}'] = target_speed.value + self.calibration_records[f'DIAL__{pump_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'DIAL__{pump_name}'] = acceptance.value + self.get_calibration_rec_rr[f'DIAL__{pump_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_D48_PUMP_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_dial_pump_d48_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Dialysate Pump D48 Details data messages. + DD Calibration Records Dialysate Pump D48 Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((gain, DataTypes.F32)) + msg_list.append((offset, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Dialysate Pump Name + pump_name = dd_enum_repository.DDDialysatePumpNames.D48_PUMP.name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'DIAL__{pump_name}__{gain.name}'] = gain.value + self.calibration_records[f'DIAL__{pump_name}__{offset.name}'] = offset.value + self.calibration_records[f'DIAL__{pump_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'DIAL__{pump_name}'] = acceptance.value + self.get_calibration_rec_rr[f'DIAL__{pump_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_ACID_CONC_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_acid_conc_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Acid Concentrate Details data messages. + DD Calibration Records Acid Concentrate Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + conc_id = LocalVars('conc_id') + mix_ratio = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name) + volume = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name) + conductivity = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name) + temperature = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((conc_id, DataTypes.U32)) + msg_list.append((mix_ratio, DataTypes.F32)) + msg_list.append((volume, DataTypes.F32)) + msg_list.append((conductivity, DataTypes.F32)) + msg_list.append((temperature, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Acid Concentrate's Name + acid_name = disp_enum_repository.AcidTypes(conc_id.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'ACID__{acid_name}__{mix_ratio.name}'] = mix_ratio.value + self.calibration_records[f'ACID__{acid_name}__{volume.name}'] = volume.value + self.calibration_records[f'ACID__{acid_name}__{conductivity.name}'] = conductivity.value + self.calibration_records[f'ACID__{acid_name}__{temperature.name}'] = temperature.value + self.calibration_records[f'ACID__{acid_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'ACID__{acid_name}'] = acceptance.value + self.get_calibration_rec_rr[f'ACID__{acid_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_BICARB_CONC_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_bicarb_conc_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Bicarb Concentrate Details data messages. + DD Calibration Records Bicarb Concentrate Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + conc_id = LocalVars('conc_id') + mix_ratio = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name) + volume = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name) + conductivity = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name) + temperature = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((conc_id, DataTypes.U32)) + msg_list.append((mix_ratio, DataTypes.F32)) + msg_list.append((volume, DataTypes.F32)) + msg_list.append((conductivity, DataTypes.F32)) + msg_list.append((temperature, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Bicarb Concentrate's Name + bicarb_name = disp_enum_repository.AcidTypes(conc_id.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'BICARB__{bicarb_name}__{mix_ratio.name}'] = mix_ratio.value + self.calibration_records[f'BICARB__{bicarb_name}__{volume.name}'] = volume.value + self.calibration_records[f'BICARB__{bicarb_name}__{conductivity.name}'] = conductivity.value + self.calibration_records[f'BICARB__{bicarb_name}__{temperature.name}'] = temperature.value + self.calibration_records[f'BICARB__{bicarb_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'BICARB__{bicarb_name}'] = acceptance.value + self.get_calibration_rec_rr[f'BICARB__{bicarb_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_ACCEL_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_accelerometer_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Accelerometer Details data messages. + DD Calibration Records Accelerometer Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + accel_x = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_X_OFFSET.name) + accel_y = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Y_OFFSET.name) + accel_z = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Z_OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((accel_x, DataTypes.F32)) + msg_list.append((accel_y, DataTypes.F32)) + msg_list.append((accel_z, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'ACCEL__{accel_x.name}'] = accel_x.value + self.calibration_records[f'ACCEL__{accel_y.name}'] = accel_y.value + self.calibration_records[f'ACCEL__{accel_z.name}'] = accel_z.value + self.calibration_records[f'ACCEL__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'ACCEL'] = acceptance.value + self.get_calibration_rec_rr[f'ACCEL'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_blood_leak_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Blood Leak Details data messages. + DD Calibration Records Blood Leak Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + set_point = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.SET_POINT.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((set_point, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'BLOOD_LEAK__{set_point.name}'] = set_point.value + self.calibration_records[f'BLOOD_LEAK__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'BLOOD_LEAK'] = acceptance.value + self.get_calibration_rec_rr[f'BLOOD_LEAK'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "get_calibration_rec_ack", "get_calibration_rec_rr", "calibration_records", "get_calibration_rec_timestamp"]) + def _handler_calibration_record_cond_sensor_sync(self, message, timestamp = 0.0): + """ + Handles published DD Calibration Record Conductivity Sensors Details data messages. + DD Calibration RecordsConductivity Sensors Details are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + sensor_id = LocalVars('sensor_id') + k_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.K_HIGH.name) + alpha_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ALPHA_HIGH.name) + eta_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ETA_HIGH.name) + zeta_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ZETA_HIGH.name) + k_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.K_LOW.name) + alpha_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ALPHA_LOW.name) + eta_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ETA_LOW.name) + zeta_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ZETA_LOW.name) + beta = LocalVars(dd_enum_repository.CalibRecordConductivityFields.BETA.name) + delta = LocalVars(dd_enum_repository.CalibRecordConductivityFields.DELTA.name) + rsrvd_1 = LocalVars(dd_enum_repository.CalibRecordConductivityFields.RSRVD_1.name) + rsrvd_2 = LocalVars(dd_enum_repository.CalibRecordConductivityFields.RSRVD_2.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((k_high, DataTypes.F32)) + msg_list.append((alpha_high, DataTypes.F32)) + msg_list.append((eta_high, DataTypes.F32)) + msg_list.append((zeta_high, DataTypes.F32)) + msg_list.append((k_low, DataTypes.F32)) + msg_list.append((alpha_low, DataTypes.F32)) + msg_list.append((eta_low, DataTypes.F32)) + msg_list.append((zeta_low, DataTypes.F32)) + msg_list.append((beta, DataTypes.F32)) + msg_list.append((delta, DataTypes.F32)) + msg_list.append((rsrvd_1, DataTypes.F32)) + msg_list.append((rsrvd_2, DataTypes.F32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Conductivity Sensor Name + sensor_name = dd_enum_repository.DDConductivitySensorNames(sensor_id.value).name + + # Saving into the calibration data + if acceptance.value: + self.calibration_records[f'COND__{sensor_name}__{k_high.name}'] = k_high.value + self.calibration_records[f'COND__{sensor_name}__{alpha_high.name}'] = alpha_high.value + self.calibration_records[f'COND__{sensor_name}__{eta_high.name}'] = eta_high.value + self.calibration_records[f'COND__{sensor_name}__{zeta_high.name}'] = zeta_high.value + self.calibration_records[f'COND__{sensor_name}__{k_low.name}'] = k_low.value + self.calibration_records[f'COND__{sensor_name}__{alpha_low.name}'] = alpha_low.value + self.calibration_records[f'COND__{sensor_name}__{eta_low.name}'] = eta_low.value + self.calibration_records[f'COND__{sensor_name}__{zeta_low.name}'] = zeta_low.value + self.calibration_records[f'COND__{sensor_name}__{beta.name}'] = beta.value + self.calibration_records[f'COND__{sensor_name}__{delta.name}'] = delta.value + self.calibration_records[f'COND__{sensor_name}__{rsrvd_1.name}'] = rsrvd_1.value + self.calibration_records[f'COND__{sensor_name}__{rsrvd_2.name}'] = rsrvd_2.value + self.calibration_records[f'COND__{sensor_name}__{calibration_time.name}'] = calibration_time.value + else: + self.get_calibration_rec_ack[f'COND__{sensor_name}'] = acceptance.value + self.get_calibration_rec_rr[f'COND__{sensor_name}'] = RequestRejectReasons(reject_reason.value) + self.get_calibration_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_BASIC_RECORD_RESPONSE.name.lower(), "get_institutional_rec_ack", "get_institutional_rec_rr", "institutional_records", "get_institutional_rec_timestamp"]) + def _handler_institutional_basic_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD Institutional Record Basic details data messages. + DD Institutional Records are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + for member in dd_enum_repository.InstitutionalRecordBasicFields: + if member is not dd_enum_repository.InstitutionalRecordBasicFields.NUM_OF_INSTITUTIONAL_RECORD_BASIC_FIELDS: + msg_list.append((self.institutional_records, f'BASIC__{member.name}', member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_institutional_rec_rr, int): + self.get_institutional_rec_rr['BASIC'] = RequestRejectReasons(self.get_institutional_rec_rr) + self.get_institutional_rec_ack['BASIC'] = acceptance.value + self.get_institutional_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_ADVANCED_RECORD_RESPONSE.name.lower(), "get_institutional_rec_ack", "get_institutional_rec_rr", "institutional_records", "get_institutional_rec_timestamp"]) + def _handler_institutional_adv_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD Institutional Record Advanced details data messages. + DD Institutional Records are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + for member in dd_enum_repository.InstitutionalRecordAdvancedFields: + if member is not dd_enum_repository.InstitutionalRecordAdvancedFields.NUM_OF_INSTITUTIONAL_RECORD_ADVANCED_FIELDS: + msg_list.append((self.institutional_records, f'ADV__{member.name}', member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_institutional_rec_rr, int): + self.get_institutional_rec_rr['ADV'] = RequestRejectReasons(self.get_institutional_rec_rr) + self.get_institutional_rec_ack['ADV'] = acceptance.value + self.get_institutional_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_INSTIT_ADDITIONAL_RECORD_RESPONSE.name.lower(), "get_institutional_rec_ack", "get_institutional_rec_rr", "institutional_records", "get_institutional_rec_timestamp"]) + def _handler_institutional_add_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD Institutional Record Additional details data messages. + DD Institutional Records are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + reject_reason = LocalVars('reject_reason') + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((reject_reason, DataTypes.U32)) + for member in dd_enum_repository.InstitutionalRecordAdditionalFields: + if member is not dd_enum_repository.InstitutionalRecordAdditionalFields.NUM_OF_INSTITUTIONAL_RECORD_ADDITIONAL_FIELDS: + msg_list.append((self.institutional_records, f'ADD__{member.name}', member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_institutional_rec_rr, int): + self.get_institutional_rec_rr['ADD'] = RequestRejectReasons(self.get_institutional_rec_rr) + self.get_institutional_rec_ack['ADD'] = acceptance.value + self.get_institutional_rec_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_GET_BICARB_CONC_CAL_RECORD_RESPONSE.name.lower(), "get_usage_info_rec_ack", "get_usage_info_rec_rr", "usage_info_records", "get_usage_info_rec_timestamp"]) + def _handler_usage_info_record_sync(self, message, timestamp = 0.0): + """ + Handles published DD Usage Information Record data messages. + DD Usage Information Records are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).get_usage_info_rec_ack, DataTypes.BOOL)) + msg_list.append((type(self).get_usage_info_rec_rr, DataTypes.U32)) + for member in dd_enum_repository.UsageInformationRecordFields: + if member is not dd_enum_repository.UsageInformationRecordFields.NUM_OF_USAGE_INFO_RECORD_FIELDS: + msg_list.append((self.usage_info_records, member.name, member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_usage_info_rec_rr, int): + self.get_usage_info_rec_rr = RequestRejectReasons(self.get_usage_info_rec_rr) + self.get_usage_info_rec_timestamp = timestamp Index: leahi_dialin/dd/modules/records_set_requests.py =================================================================== diff -u --- leahi_dialin/dd/modules/records_set_requests.py (revision 0) +++ leahi_dialin/dd/modules/records_set_requests.py (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -0,0 +1,730 @@ +########################################################################### +# +# Copyright (c) 2020-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 records_set_requests.py +# +# @author (last) Zoltan Miskolci +# @date (last) 04-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 04-Aug-2026 +# +############################################################################ + +# Module imports +from functools import partial +from time import sleep + +# Project imports +from leahi_dialin.common import dd_enum_repository, disp_enum_repository, fp_enum_repository +from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.common.override_templates import cmd_generic_override +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem +from leahi_dialin.utils.enums import DialinEnum +from leahi_dialin.utils.conversions import integer_to_bytearray, float_to_bytearray, byte_to_bytearray, unsigned_short_to_bytearray, string_to_bytearray + + +class DDRecordsSetRequests(AbstractSubSystem): + """ + Part of the DD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the set requests. + """ + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + +# ================================================= Set Records Main Methods ================================================= + def cmd_set_system_records(self, + is_ro_featured: bool=False, + is_ro_featured_boost_pump: bool=False, + part_number: str='0000000000', + serial_number: str='00000000000000000000', + manufacturing_location: int=0, + manufacturing_date: int=0) -> int: + """ + Constructs and sends a command for setting the System Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + if len(part_number) != 10: + raise ValueError(f'part_number must be 10 characters, provided is: {len(part_number)}') + if len(serial_number) != 20: + raise ValueError(f'serial must be 20 characters, provided is: {len(serial_number)}') + + payload = integer_to_bytearray(is_ro_featured) + payload += integer_to_bytearray(is_ro_featured_boost_pump) + payload += string_to_bytearray(part_number) + payload += string_to_bytearray(serial_number) + payload += byte_to_bytearray(manufacturing_location) + payload += integer_to_bytearray(manufacturing_date) + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_SYSTEM_RECORD_REQUEST, + entity_name = f'New DD System Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_service_records(self, + is_hdf_online: bool=False, + water_recovery: int=0, + service_loc: int=0, + last_service_date: int=0, + service_interval_sec: int=0, + last_reset_time: int=0) -> int: + """ + Constructs and sends a command for setting the Service Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = integer_to_bytearray(is_hdf_online) + payload += integer_to_bytearray(water_recovery) + payload += byte_to_bytearray(service_loc) + payload += integer_to_bytearray(last_service_date) + payload += integer_to_bytearray(service_interval_sec) + payload += integer_to_bytearray(last_reset_time) + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_SERVICE_RECORD_REQUEST, + entity_name = f'New DD Service Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_calibration_records(self, calibration_records: dict={}) -> int: + """ + Constructs and sends a command for setting the Calibration Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @param calibration_records: (Dictionary) The stored and structured Calibration Records + @return: 1 if successful, zero otherwise + """ + msg_id_pairing = { + 'PRES': MsgIds.MSG_ID_UI_DD_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_REQUEST, + 'TEMP': MsgIds.MSG_ID_UI_DD_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_REQUEST, + 'CONC': MsgIds.MSG_ID_UI_DD_NVM_SET_CONC_PUMP_CAL_RECORD_REQUEST, + 'DIAL': MsgIds.MSG_ID_UI_DD_NVM_SET_D48_PUMP_CAL_RECORD_REQUEST, + 'ACID': MsgIds.MSG_ID_UI_DD_NVM_SET_ACID_CONC_CAL_RECORD_REQUEST, + 'BICARB': MsgIds.MSG_ID_UI_DD_NVM_SET_BICARB_CONC_CAL_RECORD_REQUEST, + 'ACCEL': MsgIds.MSG_ID_UI_DD_NVM_SET_ACCEL_SENSOR_CAL_RECORD_REQUEST, + 'BLOOD_LEAK': MsgIds.MSG_ID_UI_DD_NVM_SET_BLOOD_LEAK_SENSOR_CAL_RECORD_REQUEST, + 'COND': MsgIds.MSG_ID_UI_DD_NVM_SET_CONDUCTIVITY_SENSOR_CAL_RECORD_REQUEST, + } + # Make a dictionary to store all the send functions for later send + send_data = [] + checked = [] + for record_enum in dd_enum_repository.CalibrationRecordFields: + record_parts = record_enum.name.split('__') + group = record_parts[0] + + # If a message already sent, then just go to the next value + if 'NUM_' in group or \ + group in checked or \ + record_parts[1] in checked: + continue + + if group in ['PRES', 'TEMP', 'CONC', 'DIAL']: + # Set the sensor name + if group == 'PRES': + sensor = dd_enum_repository.DDPressureSensorNames.from_str(record_parts[1]) + if sensor is None: + sensor = fp_enum_repository.FPPressureSensorNames.from_str(record_parts[1]) + elif group == 'TEMP': + sensor = dd_enum_repository.DDTemperatureSensorNames.from_str(record_parts[1]) + elif group == 'CONC': + sensor = dd_enum_repository.DDConcentratePumpNames.from_str(record_parts[1]) + elif group == 'DIAL': + sensor = dd_enum_repository.DDDialysatePumpNames.from_str(record_parts[1]) + else: + sensor = 'UNKNOWN' + + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': 'target_speed', 'entry_name': f'{group}__{sensor.name}__TARGET_SPEED' }, + {'param_name': dd_enum_repository.CalibRecordSensorFields.GAIN.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.GAIN.name}' }, + {'param_name': dd_enum_repository.CalibRecordSensorFields.OFFSET.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.OFFSET.name}' }, + {'param_name': dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + kwargs['sensor_enum'] = sensor + if sensor == dd_enum_repository.DDDialysatePumpNames.D12_PUMP: + kwargs['msg_id'] = MsgIds.MSG_ID_UI_DD_NVM_SET_CAL_D12_PUMP_REQUEST + else: + kwargs['msg_id'] = msg_id_pairing[group] + for map in mapping: + if map['entry_name'] in calibration_records and calibration_records[map['entry_name']] is not None: + kwargs[map['param_name']] = calibration_records[map['entry_name']] + + checked.append(record_parts[1]) + # Skip sending if dictionary is provided but all entry for the sensor was None (except sensor_enum and MSG_ID, because those are neccesary) + if calibration_records != {} and len(kwargs) == 2: + continue + + # Create the send data function + send_data.append(partial(self.cmd_set_calibration_records_sensor, *args, **kwargs)) + + elif group in ['ACID', 'BICARB']: + if group == 'ACID': + conc = disp_enum_repository.AcidTypes.from_str(record_parts[1]) + elif group == 'BICARB': + conc = disp_enum_repository.BicarbTypes.from_str(record_parts[1]) + else: + conc = 'unknown' + + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name.lower(), 'entry_name': f'{group}__{conc.name}__{dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name}' }, + {'param_name': dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name.lower(), 'entry_name': f'{group}__{conc.name}__{dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name}' }, + {'param_name': dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name.lower(), 'entry_name': f'{group}__{conc.name}__{dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name}' }, + {'param_name': dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name.lower(), 'entry_name': f'{group}__{conc.name}__{dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name}' }, + {'param_name': dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{conc.name}__{dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + kwargs['conc_enum'] = conc + kwargs['msg_id'] = msg_id_pairing[group] + for map in mapping: + if map['entry_name'] in calibration_records and calibration_records[map['entry_name']] is not None: + kwargs[map['param_name']] = calibration_records[map['entry_name']] + + checked.append(record_parts[1]) + # Skip sending if dictionary is provided but all entry for the sensor was None (except conc_enum and MSG_ID, because those are neccesary) + if calibration_records != {} and len(kwargs) == 2: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_calibration_records_concentrate, *args, **kwargs)) + + elif group in ['ACCEL']: + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_X_OFFSET.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_X_OFFSET.name}' }, + {'param_name': dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Y_OFFSET.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Y_OFFSET.name}' }, + {'param_name': dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Z_OFFSET.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Z_OFFSET.name}' }, + {'param_name': dd_enum_repository.CalibRecordAccelerometerFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordAccelerometerFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + kwargs['msg_id'] = msg_id_pairing[group] + for map in mapping: + if map['entry_name'] in calibration_records and calibration_records[map['entry_name']] is not None: + kwargs[map['param_name']] = calibration_records[map['entry_name']] + + checked.append(group) + # Skip sending if dictionary is provided but all entry for the sensor was None (except MSG_ID, because that is neccesary) + if calibration_records != {} and len(kwargs) == 1: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_calibration_records_accelerometer, *args, **kwargs)) + + elif group in ['BLOOD_LEAK']: + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.CalibRecordBloodLeakFields.SET_POINT.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordBloodLeakFields.SET_POINT.name}' }, + {'param_name': dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + kwargs['msg_id'] = msg_id_pairing[group] + for map in mapping: + if map['entry_name'] in calibration_records and calibration_records[map['entry_name']] is not None: + kwargs[map['param_name']] = calibration_records[map['entry_name']] + + checked.append(group) + # Skip sending if dictionary is provided but all entry for the sensor was None (except MSG_ID, because that is neccesary) + if calibration_records != {} and len(kwargs) == 1: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_calibration_records_blood_leak, *args, **kwargs)) + + elif group in ['COND']: + sensor = dd_enum_repository.DDConductivitySensorNames.from_str(record_parts[1]) + + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.CalibRecordConductivityFields.K_HIGH.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.K_HIGH.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.K_LOW.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.K_LOW.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ALPHA_HIGH.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ALPHA_HIGH.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ALPHA_LOW.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ALPHA_LOW.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ETA_HIGH.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ETA_HIGH.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ETA_LOW.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ETA_LOW.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ZETA_HIGH.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ZETA_HIGH.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.ZETA_LOW.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.ZETA_LOW.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.BETA.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.BETA.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.DELTA.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.DELTA.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.RSRVD_1.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.RSRVD_1.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.RSRVD_2.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.RSRVD_2.name}' }, + {'param_name': dd_enum_repository.CalibRecordConductivityFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{sensor.name}__{dd_enum_repository.CalibRecordConductivityFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + kwargs['sensor_enum'] = sensor + kwargs['msg_id'] = msg_id_pairing[group] + for map in mapping: + if map['entry_name'] in calibration_records and calibration_records[map['entry_name']] is not None: + kwargs[map['param_name']] = calibration_records[map['entry_name']] + + checked.append(record_parts[1]) + # Skip sending if dictionary is provided but all entry for the sensor was None (except sensor_enum and MSG_ID, because those are neccesary) + if calibration_records != {} and len(kwargs) == 2: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_calibration_records_conductivity, *args, **kwargs)) + + # Execute the stored functions one by one + # Remove the ones that got 1 (successfully recieved) as response + # Retry the ones that are failed 2 more times + retry = 0 + while send_data != [] and retry < 3: + failed = [] + for func in send_data: + resp = func() + if resp == 1: + failed.append(func) + send_data = failed + retry += 1 + sleep(0.005) # Wait 50ms between sends + + + def cmd_set_institutional_records(self, institutional_records: dict={}) -> int: + """ + Constructs and sends a command for setting the Institutional Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @param institutional_records: (Dictionary) The stored and structured Institutional Records + @return: 1 if successful, zero otherwise + """ + + # Make a dictionary to store all the send functions for later send + send_data = [] + checked = [] + for record_enum in dd_enum_repository.InstitutionalRecordBasicFields: + record_parts = record_enum.name.split('__') + group = record_parts[0] + + if group in ['BASIC']: + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_DIALYSATE_SYSTEM_FLOW_MLPM.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_DIALYSATE_SYSTEM_FLOW_MLPM.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_DIALYSATE_SYSTEM_FLOW_MLPM.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_DIALYSATE_SYSTEM_FLOW_MLPM.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_DIALYSATE_TEMP_C.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_DIALYSATE_TEMP_C.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_DIALYSATE_TEMP_C.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_DIALYSATE_TEMP_C.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_ACID_CONCENTRATE.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_ACID_CONCENTRATE.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_ACID_CONCENTRATE.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_ACID_CONCENTRATE.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARB_CARTRIDGE_SIZE_G.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARB_CARTRIDGE_SIZE_G.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_BICARB_CARTRIDGE_SIZE_G.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_BICARB_CARTRIDGE_SIZE_G.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_SODIUM_MEQPL.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_SODIUM_MEQPL.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_SODIUM_MEQPL.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_SODIUM_MEQPL.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARBONATE_MEQPL.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARBONATE_MEQPL.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_BICARBONATE_MEQPL.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_BICARBONATE_MEQPL.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_RO_REJECTION_RATIO_PCT.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_RO_REJECTION_RATIO_PCT.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.DISINFECTION_FREQUENCY.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.DISINFECTION_FREQUENCY.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.DISINFECTION_CYCLE_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.DISINFECTION_CYCLE_TIME.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_INLET_WATER_CIND_AKARN_LIMIT_USPCM.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_INLET_WATER_CIND_AKARN_LIMIT_USPCM.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MAX_INLET_WATER_CIND_AKARN_LIMIT_USPCM.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MAX_INLET_WATER_CIND_AKARN_LIMIT_USPCM.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.ACID_CONCENTRATE_JUG_SIZE_L.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.ACID_CONCENTRATE_JUG_SIZE_L.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_ACID_ALARM_LIMIT_PCT.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_ACID_ALARM_LIMIT_PCT.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARB_ALARM_LIMIT_PCT.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.MIN_BICARB_ALARM_LIMIT_PCT.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.POST_TREAT_DRAIN_OPTION.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.POST_TREAT_DRAIN_OPTION.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.POST_TREAT_DRY_BICARB_OPTION.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.POST_TREAT_DRY_BICARB_OPTION.name}' }, + {'param_name': dd_enum_repository.InstitutionalRecordBasicFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordBasicFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + for map in mapping: + if map['entry_name'] in institutional_records and institutional_records[map['entry_name']] is not None: + kwargs[map['param_name']] = institutional_records[map['entry_name']] + + checked.append(group) + # Skip sending if dictionary is provided + if institutional_records != {}: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_institutional_records_basic, *args, **kwargs)) + + elif group in ['ADV']: + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.InstitutionalRecordAdvancedFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordAdvancedFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + for map in mapping: + if map['entry_name'] in institutional_records and institutional_records[map['entry_name']] is not None: + kwargs[map['param_name']] = institutional_records[map['entry_name']] + + checked.append(group) + # Skip sending if dictionary is provided + if institutional_records != {}: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_institutional_records_advanced, *args, **kwargs)) + + elif group in ['ADD']: + # Set the arguments for the call + args = [] + kwargs = {} + mapping = [ + {'param_name': dd_enum_repository.InstitutionalRecordAdditionalFields.CALIBRATION_TIME.name.lower(), 'entry_name': f'{group}__{dd_enum_repository.InstitutionalRecordAdditionalFields.CALIBRATION_TIME.name}' }, + ] + + # Building the kwargs parameter list + for map in mapping: + if map['entry_name'] in institutional_records and institutional_records[map['entry_name']] is not None: + kwargs[map['param_name']] = institutional_records[map['entry_name']] + + checked.append(group) + # Skip sending if dictionary is provided + if institutional_records != {}: + continue + + # Store the function but do not execute it + send_data.append(partial(self.cmd_set_institutional_records_additional, *args, **kwargs)) + + # Execute the stored functions one by one + # Remove the ones that got 1 (successfully recieved) as response + # Retry the ones that are failed 2 more times + retry = 0 + while send_data != [] and retry < 3: + failed = [] + for func in send_data: + resp = func() + if resp == 1: + failed.append(func) + send_data = failed + retry += 1 + sleep(0.005) # Wait 50ms between sends + + + def cmd_set_usage_info_records(self, + ro_water_gen_total_l: float=0.0, + ro_water_gen_since_last_serv_l: float=0.0, + last_basic_flush_date: int=0, + last_heat_disinfect_date: int=0, + last_heat_active_cool_date: int=0, + last_filter_flush_date: int=0, + last_reset_time: int=0) -> int: + """ + Constructs and sends a command for setting the Usage Information Records. + Constraints: + Must be logged into DD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = float_to_bytearray(ro_water_gen_total_l) + payload += float_to_bytearray(ro_water_gen_since_last_serv_l) + payload += integer_to_bytearray(last_basic_flush_date) + payload += integer_to_bytearray(last_heat_disinfect_date) + payload += integer_to_bytearray(last_heat_active_cool_date) + payload += integer_to_bytearray(last_filter_flush_date) + payload += integer_to_bytearray(last_reset_time) + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_USAGE_INFO_RECORD_REQUEST, + entity_name = f'New DD Usage Information Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + +# ================================================= Set Records Support Methods ================================================= + def cmd_set_calibration_records_sensor(self, + sensor_enum: DialinEnum, + msg_id: MsgIds, + target_speed: float=0.0, + gain: float=0.0, + offset: float=0.0, + calibration_time: int=1) -> int: + payload = b'' + # Add sensor index when it's not Dialysate pump + if msg_id not in [MsgIds.MSG_ID_UI_DD_NVM_SET_D12_PUMP_CAL_RECORD_REQUEST, MsgIds.MSG_ID_UI_DD_NVM_SET_D48_PUMP_CAL_RECORD_REQUEST]: + if isinstance(sensor_enum, fp_enum_repository.FPPressureSensorNames): + payload += byte_to_bytearray(sensor_enum.value + dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value) + else: + payload += byte_to_bytearray(sensor_enum.value) + + if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_D12_PUMP_CAL_RECORD_REQUEST: + payload += float_to_bytearray(target_speed) + else: + payload += float_to_bytearray(gain) + payload += float_to_bytearray(offset) + payload += integer_to_bytearray(calibration_time) + + # Get sensor type for the debug print + sensor_type = '' + if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_REQUEST: + sensor_type = 'Pressure Sensor' + elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_REQUEST: + sensor_type = 'Temperature Sensor' + elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_CONC_PUMP_CAL_RECORD_REQUEST: + sensor_type = 'Concentrate Pump' + elif msg_id in [MsgIds.MSG_ID_UI_DD_NVM_SET_D12_PUMP_CAL_RECORD_REQUEST, MsgIds.MSG_ID_UI_DD_NVM_SET_D48_PUMP_CAL_RECORD_REQUEST]: + sensor_type = 'Dialysate Pump' + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = msg_id, + entity_name = f'DD {sensor_type} {sensor_enum.name} Calibration Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_calibration_records_concentrate(self, + conc_enum: DialinEnum, + msg_id: MsgIds, + concentrate_mix_ratio: float=0.0, + full_bottle_volume_ml: float=0.0, + conductivity_uspcm: float=0.0, + bottle_temperature_c: float=0.0, + calibration_time: int=1) -> int: + + payload = byte_to_bytearray(conc_enum.value) + payload += float_to_bytearray(concentrate_mix_ratio) + payload += float_to_bytearray(full_bottle_volume_ml) + payload += float_to_bytearray(conductivity_uspcm) + payload += float_to_bytearray(bottle_temperature_c) + payload += integer_to_bytearray(calibration_time) + + # Get concentrate type for the debug print + conc_type = '' + if msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_ACID_CONC_CAL_RECORD_REQUEST: + conc_type = 'Acid' + elif msg_id == MsgIds.MSG_ID_UI_DD_NVM_SET_BICARB_CONC_CAL_RECORD_REQUEST: + conc_type = 'Bicarb' + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = msg_id, + entity_name = f'DD {conc_type} {conc_enum.name} Concentrate Calibration Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_calibration_records_accelerometer(self, + msg_id: MsgIds, + accel_x_offset: float=0.0, + accel_y_offset: float=0.0, + accel_z_offset: float=0.0, + calibration_time: int=1) -> int: + + payload = float_to_bytearray(accel_x_offset) + payload += float_to_bytearray(accel_y_offset) + payload += float_to_bytearray(accel_z_offset) + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = msg_id, + entity_name = f'DD Accelerometer Calibration Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + + def cmd_set_calibration_records_blood_leak(self, + msg_id: MsgIds, + set_point: int=0, + calibration_time: int=1) -> int: + + payload = integer_to_bytearray(set_point) + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = msg_id, + entity_name = f'DD Blood Leak Calibration Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_calibration_records_conductivity(self, + msg_id: MsgIds, + sensor_enum: DialinEnum, + k_high: float=4.0, + k_low: float=4.0, + alpha_high: float=0.02, + alpha_low: float=0.02, + eta_high: float=1.0, + eta_low: float=1.0, + zeta_high: float=1.0, + zeta_low: float=0.0, + beta_high: float=1.0, + delta_low: float=0.0, + rsrvd_1: float=0.0, + rsrvd_2: float=0.0, + calibration_time: int=1) -> int: + + payload = integer_to_bytearray(sensor_enum.value) + payload += float_to_bytearray(k_high) + payload += float_to_bytearray(alpha_high) + payload += float_to_bytearray(eta_high) + payload += float_to_bytearray(zeta_high) + payload += float_to_bytearray(k_low) + payload += float_to_bytearray(alpha_low) + payload += float_to_bytearray(eta_low) + payload += float_to_bytearray(zeta_low) + payload += float_to_bytearray(beta_high) + payload += float_to_bytearray(delta_low) + payload += float_to_bytearray(rsrvd_1) + payload += float_to_bytearray(rsrvd_2) + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = msg_id, + entity_name = f'DD Conductivity {sensor_enum.name} Calibration Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_institutional_records_basic(self, + min_dialysate_system_flow_mlpm: int=0, + max_dialysate_system_flow_mlpm: int=0, + min_dialysate_temp_c: float=0.0, + max_dialysate_temp_c: float=0.0, + min_acid_concentrate: int=0, + max_acid_concentrate: int=0, + min_bicarb_cartridge_size_g: int=0, + max_bicarb_cartridge_size_g: int=0, + min_sodium_meqpl: int=0, + max_sodium_meqpl: int=0, + min_bicarbonate_meqpl: int=0, + max_bicarbonate_meqpl: int=0, + min_ro_rejection_ratio_pct: float=0.0, + disinfection_frequency: int=0, + disinfection_cycle_time: float=0.0, + min_inlet_water_cind_akarn_limit_uspcm: float=0.0, + max_inlet_water_cind_akarn_limit_uspcm: float=0.0, + acid_concentrate_jug_size_l: float=0.0, + min_acid_alarm_limit_pct: float=0.0, + min_bicarb_alarm_limit_pct: float=0.0, + post_treat_drain_option: int=0, + post_treat_dry_bicarb_option: int=0, + calibration_time: int=1) -> int: + + payload = integer_to_bytearray(min_dialysate_system_flow_mlpm) + payload += integer_to_bytearray(max_dialysate_system_flow_mlpm) + payload += integer_to_bytearray(min_dialysate_temp_c) + payload += integer_to_bytearray(max_dialysate_temp_c) + payload += integer_to_bytearray(min_acid_concentrate) + payload += integer_to_bytearray(max_acid_concentrate) + payload += integer_to_bytearray(min_bicarb_cartridge_size_g) + payload += integer_to_bytearray(max_bicarb_cartridge_size_g) + payload += integer_to_bytearray(min_sodium_meqpl) + payload += integer_to_bytearray(max_sodium_meqpl) + payload += integer_to_bytearray(min_bicarbonate_meqpl) + payload += integer_to_bytearray(max_bicarbonate_meqpl) + payload += float_to_bytearray(min_ro_rejection_ratio_pct) + payload += integer_to_bytearray(disinfection_frequency) + payload += float_to_bytearray(disinfection_cycle_time) + payload += float_to_bytearray(min_inlet_water_cind_akarn_limit_uspcm) + payload += float_to_bytearray(max_inlet_water_cind_akarn_limit_uspcm) + payload += float_to_bytearray(acid_concentrate_jug_size_l) + payload += float_to_bytearray(min_acid_alarm_limit_pct) + payload += float_to_bytearray(min_bicarb_alarm_limit_pct) + payload += integer_to_bytearray(post_treat_drain_option) + payload += integer_to_bytearray(post_treat_dry_bicarb_option) + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_INSTIT_BASIC_RECORD_REQUEST, + entity_name = f'DD Institutional Basic Records', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_institutional_records_advanced(self, + calibration_time: int=1) -> int: + payload = b'' + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_INSTIT_ADVANCED_RECORD_REQUEST, + entity_name = f'DD Institutional Advanced Records', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_institutional_records_additional(self, + calibration_time: int=1) -> int: + + payload = b'' + payload += integer_to_bytearray(calibration_time) + + return cmd_generic_override(payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + msg_id = MsgIds.MSG_ID_UI_DD_NVM_SET_INSTIT_ADDITIONAL_RECORD_REQUEST, + entity_name = f'DD Institutional Additional Records', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) Index: leahi_dialin/dd/modules/records_set_responses.py =================================================================== diff -u --- leahi_dialin/dd/modules/records_set_responses.py (revision 0) +++ leahi_dialin/dd/modules/records_set_responses.py (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -0,0 +1,643 @@ +########################################################################### +# +# Copyright (c) 2020-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 records_set_responses.py +# +# @author (last) Zoltan Miskolci +# @date (last) 04-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 04-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common import dd_enum_repository, disp_enum_repository, fp_enum_repository +from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.common.msg_defs import RequestRejectReasons +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem, LocalVars +from leahi_dialin.utils.base import publish + + +class DDRecordsSetHandlers(AbstractSubSystem): + """ + Part of the DD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the set handlers. + """ + if self.can_interface is not None: + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_SYSTEM_RECORD_RESPONSE.value, + function = self._handler_set_system_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_SERVICE_RECORD_RESPONSE.value, + function = self._handler_set_service_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_pressure_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_temp_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_CONC_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_conc_pump_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_D12_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_dial_d12_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_D48_PUMP_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_dial_d48_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_ACID_CONC_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_acid_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_BICARB_CONC_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_bicarb_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_ACCEL_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_accel_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_blood_leak_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE.value, + function = self._handler_set_calib_conductivity_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_BASIC_RECORD_RESPONSE.value, + function = self._handler_set_institutional_rec_basic_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_ADVANCED_RECORD_RESPONSE.value, + function = self._handler_set_institutional_rec_advanced_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_ADDITIONAL_RECORD_RESPONSE.value, + function = self._handler_set_institutional_rec_additional_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.dd_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_DD_UI_NVM_SET_USAGE_INFO_RECORD_RESPONSE.value, + function = self._handler_set_usage_info_rec_rr_sync) + + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + +# ================================================= Reject Reason Message Handler Methods ================================================= + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_SYSTEM_RECORD_RESPONSE.name.lower(), "set_system_rec_ack", "set_system_rec_rr", "set_system_rec_rr_timestamp"]) + def _handler_set_system_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set System Records Reject Reason data messages. + DD Set System Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_system_rec_ack, DataTypes.BOOL)) + for sys_rec in dd_enum_repository.SystemRecordFields: + msg_list.append((self.set_system_rec_rr, sys_rec, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for sys_rec in self.set_system_rec_rr: + if isinstance(self.set_system_rec_rr[sys_rec], int): + self.set_system_rec_rr[sys_rec] = RequestRejectReasons(self.set_system_rec_rr[sys_rec]) + self.set_system_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_SERVICE_RECORD_RESPONSE.name.lower(), "set_service_rec_ack", "set_service_rec_rr", "set_service_rec_rr_timestamp"]) + def _handler_set_service_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Service Records Reject Reason data messages. + DD Set Service Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_service_rec_ack, DataTypes.BOOL)) + for ser_rec in dd_enum_repository.ServiceRecordFields: + msg_list.append((self.set_service_rec_rr, ser_rec, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for ser_rec in self.set_service_rec_rr: + if isinstance(self.set_service_rec_rr[ser_rec], int): + self.set_service_rec_rr[ser_rec] = RequestRejectReasons(self.set_service_rec_rr[ser_rec]) + self.set_service_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_BASIC_RECORD_RESPONSE.name.lower(), "set_institutional_rec_ack", "set_institutional_rec_rr", "set_institutional_rec_rr_timestamp"]) + def _handler_set_institutional_rec_basic_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Basic Institutional Records Reject Reason data messages. + DD Set Institutional Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_institutional_rec_ack, DataTypes.BOOL)) + for inst_rec in dd_enum_repository.InstitutionalRecordBasicFields: + msg_list.append((self.set_institutional_rec_rr, f'BASIC__{inst_rec}', DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for inst_rec in self.set_institutional_rec_rr: + if self.set_institutional_rec_rr[inst_rec].startswith('BASIC__') and isinstance(self.set_institutional_rec_rr[inst_rec], int): + self.set_institutional_rec_rr[inst_rec] = RequestRejectReasons(self.set_institutional_rec_rr[inst_rec]) + self.set_institutional_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_ADVANCED_RECORD_RESPONSE.name.lower(), "set_institutional_rec_ack", "set_institutional_rec_rr", "set_institutional_rec_rr_timestamp"]) + def _handler_set_institutional_rec_advanced_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Advanced Institutional Records Reject Reason data messages. + DD Set Institutional Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_institutional_rec_ack, DataTypes.BOOL)) + for inst_rec in dd_enum_repository.InstitutionalRecordAdvancedFields: + msg_list.append((self.set_institutional_rec_rr, f'ADV__{inst_rec}', DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for inst_rec in self.set_institutional_rec_rr: + if self.set_institutional_rec_rr[inst_rec].startswith('ADV__') and isinstance(self.set_institutional_rec_rr[inst_rec], int): + self.set_institutional_rec_rr[inst_rec] = RequestRejectReasons(self.set_institutional_rec_rr[inst_rec]) + self.set_institutional_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_INSTIT_ADDITIONAL_RECORD_RESPONSE.name.lower(), "set_institutional_rec_ack", "set_institutional_rec_rr", "set_institutional_rec_rr_timestamp"]) + def _handler_set_institutional_rec_additional_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Additional Institutional Records Reject Reason data messages. + DD Set Institutional Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_institutional_rec_ack, DataTypes.BOOL)) + for inst_rec in dd_enum_repository.InstitutionalRecordAdditionalFields: + msg_list.append((self.set_institutional_rec_rr, f'ADD__{inst_rec}', DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for inst_rec in self.set_institutional_rec_rr: + if self.set_institutional_rec_rr[inst_rec].startswith('ADD__') and isinstance(self.set_institutional_rec_rr[inst_rec], int): + self.set_institutional_rec_rr[inst_rec] = RequestRejectReasons(self.set_institutional_rec_rr[inst_rec]) + self.set_institutional_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_USAGE_INFO_RECORD_RESPONSE.name.lower(), "set_usage_info_rec_ack", "set_usage_info_rec_rr", "set_usage_info_rec_rr_timestamp"]) + def _handler_set_usage_info_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Usage Information Records Reject Reason data messages. + DD Set Usage Information Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_usage_info_rec_ack, DataTypes.BOOL)) + for info_rec in dd_enum_repository.UsageInformationRecordFields: + msg_list.append((self.set_usage_info_rec_rr, info_rec, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for info_rec in self.set_usage_info_rec_rr: + if isinstance(self.set_usage_info_rec_rr[info_rec], int): + self.set_usage_info_rec_rr[info_rec] = RequestRejectReasons(self.set_usage_info_rec_rr[info_rec]) + self.set_usage_info_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_PRESSURE_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_pressure_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Pressure Sensor Reject Reason data messages. + DD Set Calibration Records for Pressure Sensor Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + sensor_id = LocalVars('sensor_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.U32)) + msg_list.append((offset, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Sensor Name + if sensor_id.value < dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value: + sensor_name = dd_enum_repository.DDPressureSensorNames(sensor_id.value).name + else: + sensor_name = fp_enum_repository.FPPressureSensorNames(sensor_id.value - dd_enum_repository.DDPressureSensorNames.NUM_OF_PRESSURE_SENSORS.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'PRES__{sensor_name}'] = acceptance.value + self.set_calibration_rec_rr[f'PRES__{sensor_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'PRES__{sensor_name}__{gain.name}'] = RequestRejectReasons(gain.value) + self.set_calibration_rec_rr[f'PRES__{sensor_name}__{offset.name}'] = RequestRejectReasons(offset.value) + self.set_calibration_rec_rr[f'PRES__{sensor_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_TEMPERATURE_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_temp_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Temperature Sensor Reject Reason data messages. + DD Set Calibration Records for Temperature Sensor Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + sensor_id = LocalVars('sensor_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.U32)) + msg_list.append((offset, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Sensor Name + sensor_name = dd_enum_repository.DDTemperatureSensorNames(sensor_id.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'TEMP__{sensor_name}'] = acceptance.value + self.set_calibration_rec_rr[f'TEMP__{sensor_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'TEMP__{sensor_name}__{gain.name}'] = RequestRejectReasons(gain.value) + self.set_calibration_rec_rr[f'TEMP__{sensor_name}__{offset.name}'] = RequestRejectReasons(offset.value) + self.set_calibration_rec_rr[f'TEMP__{sensor_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_CONC_PUMP_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_conc_pump_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Concentrate Pump Reject Reason data messages. + DD Set Calibration Records for Concentrate Pump Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + pump_id = LocalVars('pump_id') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((pump_id, DataTypes.U32)) + msg_list.append((gain, DataTypes.U32)) + msg_list.append((offset, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Sensor Name + pump_name = dd_enum_repository.DDConcentratePumpNames(pump_id.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'CONC__{pump_name}'] = acceptance.value + self.set_calibration_rec_rr[f'CONC__{pump_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'CONC__{pump_name}__{gain.name}'] = RequestRejectReasons(gain.value) + self.set_calibration_rec_rr[f'CONC__{pump_name}__{offset.name}'] = RequestRejectReasons(offset.value) + self.set_calibration_rec_rr[f'CONC__{pump_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_D12_PUMP_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_dial_d12_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for D12 Dialisate Pump Reject Reason data messages. + DD Set Calibration Records for D12 Dialisate Pump Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + target_speed = LocalVars('TARGET_SPEED') + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((target_speed, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + pump_name = dd_enum_repository.DDDialysatePumpNames.D12_PUMP.name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'DIAL__{pump_name}'] = acceptance.value + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{target_speed.name}'] = RequestRejectReasons(target_speed.value) + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_D48_PUMP_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_dial_d48_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for D48 Dialisate Pump Reject Reason data messages. + DD Set Calibration Records for D48 Dialisate Pump Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + gain = LocalVars(dd_enum_repository.CalibRecordSensorFields.GAIN.name) + offset = LocalVars(dd_enum_repository.CalibRecordSensorFields.OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordSensorFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((gain, DataTypes.U32)) + msg_list.append((offset, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + pump_name = dd_enum_repository.DDDialysatePumpNames.D48_PUMP.name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'DIAL__{pump_name}'] = acceptance.value + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{gain.name}'] = RequestRejectReasons(gain.value) + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{offset.name}'] = RequestRejectReasons(offset.value) + self.set_calibration_rec_rr[f'DIAL__{pump_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_ACID_CONC_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_acid_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Acid Concentrate Reject Reason data messages. + DD Set Calibration Records for Acid Concentrate Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + conc_id = LocalVars('conc_id') + mix_ratio = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name) + volume = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name) + conductivity = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name) + temperature = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((conc_id, DataTypes.U32)) + msg_list.append((mix_ratio, DataTypes.U32)) + msg_list.append((volume, DataTypes.U32)) + msg_list.append((conductivity, DataTypes.U32)) + msg_list.append((temperature, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Acid Concentrate's Name + acid_name = disp_enum_repository.AcidTypes(conc_id.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'ACID__{acid_name}'] = acceptance.value + self.set_calibration_rec_rr[f'ACID__{acid_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'ACID__{acid_name}__{mix_ratio.name}'] = RequestRejectReasons(mix_ratio.value) + self.set_calibration_rec_rr[f'ACID__{acid_name}__{volume.name}'] = RequestRejectReasons(volume.value) + self.set_calibration_rec_rr[f'ACID__{acid_name}__{conductivity.name}'] = RequestRejectReasons(conductivity.value) + self.set_calibration_rec_rr[f'ACID__{acid_name}__{temperature.name}'] = RequestRejectReasons(temperature.value) + self.set_calibration_rec_rr[f'ACID__{acid_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_BICARB_CONC_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_bicarb_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Bicarb Concentrate Reject Reason data messages. + DD Set Calibration Records for Bicarb Concentrate Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + conc_id = LocalVars('conc_id') + mix_ratio = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONCENTRATE_MIX_RATIO.name) + volume = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.FULL_BOTTLE_VOLUME_ML.name) + conductivity = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CONDUCTIVITY_USPCM.name) + temperature = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.BOTTLE_TEMPERATURE_C.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordConcentrateFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((conc_id, DataTypes.U32)) + msg_list.append((mix_ratio, DataTypes.U32)) + msg_list.append((volume, DataTypes.U32)) + msg_list.append((conductivity, DataTypes.U32)) + msg_list.append((temperature, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Acid Concentrate's Name + acid_name = disp_enum_repository.BicarbTypes(conc_id.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'BICARB__{acid_name}'] = acceptance.value + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{mix_ratio.name}'] = RequestRejectReasons(mix_ratio.value) + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{volume.name}'] = RequestRejectReasons(volume.value) + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{conductivity.name}'] = RequestRejectReasons(conductivity.value) + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{temperature.name}'] = RequestRejectReasons(temperature.value) + self.set_calibration_rec_rr[f'BICARB__{acid_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_ACCEL_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_accel_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Accelerometer Sensor Reject Reason data messages. + DD Set Calibration Records for Accelerometer Sensor Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + accel_x = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_X_OFFSET.name) + accel_y = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Y_OFFSET.name) + accel_z = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.ACCEL_Z_OFFSET.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordAccelerometerFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((accel_x, DataTypes.U32)) + msg_list.append((accel_y, DataTypes.U32)) + msg_list.append((accel_z, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Saving into the calibration data + self.set_calibration_rec_ack[f'ACCEL'] = acceptance.value + self.set_calibration_rec_rr[f'ACCEL__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'ACCEL__{accel_x.name}'] = RequestRejectReasons(accel_x.value) + self.set_calibration_rec_rr[f'ACCEL__{accel_y.name}'] = RequestRejectReasons(accel_y.value) + self.set_calibration_rec_rr[f'ACCEL__{accel_z.name}'] = RequestRejectReasons(accel_z.value) + self.set_calibration_rec_rr[f'ACCEL__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_BLOOD_LEAK_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_blood_leak_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Blood Leak Sensor Reject Reason data messages. + DD Set Calibration Records for Blood Leak Sensor Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + set_point = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.SET_POINT.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((set_point, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Saving into the calibration data + self.set_calibration_rec_ack[f'BLOOD_LEAK'] = acceptance.value + self.set_calibration_rec_rr[f'BLOOD_LEAK__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'BLOOD_LEAK__{set_point.name}'] = RequestRejectReasons(set_point.value) + self.set_calibration_rec_rr[f'BLOOD_LEAK__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + + + @publish([MsgIds.MSG_ID_DD_UI_NVM_SET_CONDUCTIVITY_SENSOR_CAL_RECORD_RESPONSE.name.lower(), "set_calibration_rec_ack", "set_calibration_rec_rr", "set_calibration_rec_rr_timestamp"]) + def _handler_set_calib_conductivity_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published DD Set Calibration Records for Conductivity Sensor Reject Reason data messages. + DD Set Calibration Records for Conductivity Sensor Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + acceptance = LocalVars('acceptance') + global_rr = LocalVars('GLOBAL') + sensor_id = LocalVars('sensor_id') + k_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.K_HIGH.name) + alpha_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ALPHA_HIGH.name) + eta_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ETA_HIGH.name) + zeta_high = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ZETA_HIGH.name) + k_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.K_LOW.name) + alpha_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ALPHA_LOW.name) + eta_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ETA_LOW.name) + zeta_low = LocalVars(dd_enum_repository.CalibRecordConductivityFields.ZETA_LOW.name) + beta = LocalVars(dd_enum_repository.CalibRecordConductivityFields.BETA.name) + delta = LocalVars(dd_enum_repository.CalibRecordConductivityFields.DELTA.name) + rsrvd_1 = LocalVars(dd_enum_repository.CalibRecordConductivityFields.RSRVD_1.name) + rsrvd_2 = LocalVars(dd_enum_repository.CalibRecordConductivityFields.RSRVD_2.name) + calibration_time = LocalVars(dd_enum_repository.CalibRecordBloodLeakFields.CALIBRATION_TIME.name) + + msg_list = [] + msg_list.append((acceptance, DataTypes.BOOL)) + msg_list.append((global_rr, DataTypes.U32)) + msg_list.append((sensor_id, DataTypes.U32)) + msg_list.append((k_high, DataTypes.U32)) + msg_list.append((alpha_high, DataTypes.U32)) + msg_list.append((eta_high, DataTypes.U32)) + msg_list.append((zeta_high, DataTypes.U32)) + msg_list.append((k_low, DataTypes.U32)) + msg_list.append((alpha_low, DataTypes.U32)) + msg_list.append((eta_low, DataTypes.U32)) + msg_list.append((zeta_low, DataTypes.U32)) + msg_list.append((beta, DataTypes.U32)) + msg_list.append((delta, DataTypes.U32)) + msg_list.append((rsrvd_1, DataTypes.U32)) + msg_list.append((rsrvd_2, DataTypes.U32)) + msg_list.append((calibration_time, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Get the Conductivity Sensor Name + sensor_name = dd_enum_repository.DDConductivitySensorNames(sensor_id.value).name + + # Saving into the calibration data + self.set_calibration_rec_ack[f'COND__{sensor_name}'] = acceptance.value + self.set_calibration_rec_rr[f'COND__{sensor_name}__{global_rr.name}'] = RequestRejectReasons(global_rr.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{k_high.name}'] = RequestRejectReasons(k_high.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{alpha_high.name}'] = RequestRejectReasons(alpha_high.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{eta_high.name}'] = RequestRejectReasons(eta_high.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{zeta_high.name}'] = RequestRejectReasons(zeta_high.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{k_low.name}'] = RequestRejectReasons(k_low.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{alpha_low.name}'] = RequestRejectReasons(alpha_low.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{eta_low.name}'] = RequestRejectReasons(eta_low.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{zeta_low.name}'] = RequestRejectReasons(zeta_low.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{beta.name}'] = RequestRejectReasons(beta.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{delta.name}'] = RequestRejectReasons(delta.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{rsrvd_1.name}'] = RequestRejectReasons(rsrvd_1.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{rsrvd_2.name}'] = RequestRejectReasons(rsrvd_2.value) + self.set_calibration_rec_rr[f'COND__{sensor_name}__{calibration_time.name}'] = RequestRejectReasons(calibration_time.value) + + self.set_calibration_rec_rr_timestamp = timestamp + Index: leahi_dialin/utils/abstract_classes.py =================================================================== diff -u -r4c11f61e1e328407ed98a1b81a3e8b0adb278bd5 -r436742844a3fbbb6a3b0bc81dc87bc6385c3e368 --- leahi_dialin/utils/abstract_classes.py (.../abstract_classes.py) (revision 4c11f61e1e328407ed98a1b81a3e8b0adb278bd5) +++ leahi_dialin/utils/abstract_classes.py (.../abstract_classes.py) (revision 436742844a3fbbb6a3b0bc81dc87bc6385c3e368) @@ -52,14 +52,13 @@ class AbstractSubSystem: @abstractmethod - def __init__(self): + def __init__(self, *args, **kwargs): """ Initialization function for the sub system # The abstract base class requires all abstract methods are overridden by children classes """ self._observers = [] self._datetime_fmt = "%m.%d.%Y_%I.%M.%S.%f" - pass def attach(self, observer: AbstractObserver): @@ -113,6 +112,16 @@ key_1 = decode_details[1] if len(decode_details) >= base_list_length + 1 else None key_2 = decode_details[2] if len(decode_details) >= base_list_length + 2 else None key_3 = decode_details[3] if len(decode_details) >= base_list_length + 3 else None + + # If it's referencing an earlier entry, change the key in the dictionary to that value + # Example sensor_id = 0 and key_1 is 'sensor_id' instead of the key being 'sensor_id', it will be replaced with 0 + if key_1 is not None and key_1 in result: + key_1 = result[key_1] + if key_2 is not None and key_2 in result: + key_2 = result[key_2] + if key_3 is not None and key_3 in result: + key_3 = result[key_3] + end_pos = start_pos + datatype.size() if debug: print(f'Len: {len(decode_details)}')