Index: leahi_dialin/fp/modules/events.py =================================================================== diff -u -r27cd8e0e7b47617083e8c12f73306f0ba648e687 -r9a4413f84d7a0cfc1b43a9a5eff5c53c139a0883 --- leahi_dialin/fp/modules/events.py (.../events.py) (revision 27cd8e0e7b47617083e8c12f73306f0ba648e687) +++ leahi_dialin/fp/modules/events.py (.../events.py) (revision 9a4413f84d7a0cfc1b43a9a5eff5c53c139a0883) @@ -51,27 +51,27 @@ message_id = MsgIds.MSG_ID_FP_OP_MODE_DATA.value, function = self._handler_fp_op_mode_sync) - self.fp_events_timestamp = 0.0 #: The timestamp of the last Event message - self.fp_event_op_mode = 0 #: The new Operation Mode value - self.fp_event_sub_mode = 0 #: The new Operation Sub-Mode value - self.fp_event_op_mode_timestamp = 0.0 #: The timestamp of the last Operation Mode change message + self.events_timestamp = 0.0 #: The timestamp of the last Event message + self.op_mode = 0 #: The new Operation Mode value + self.sub_mode = 0 #: The new Operation Sub-Mode value + self.event_op_mode_timestamp = 0.0 #: The timestamp of the last Operation Mode change message # Dictionary of the mode as key and the sub mode states enum class as the value - self._fp_op_mode_2_sub_mode = {fp_enum_repository.FPOpModes.MODE_FAUL.name: fp_enum_repository.FPFaultStates, - fp_enum_repository.FPOpModes.MODE_SERV.name: fp_enum_repository.FPServiceStates, - fp_enum_repository.FPOpModes.MODE_INIT.name: fp_enum_repository.FPPostStates, - fp_enum_repository.FPOpModes.MODE_STAN.name: fp_enum_repository.FPStandbyStates, - fp_enum_repository.FPOpModes.MODE_PRE_GENP.name: fp_enum_repository.FPPreGenPermeateStates, - fp_enum_repository.FPOpModes.MODE_GENP.name: fp_enum_repository.FPGenPermeateStates, - fp_enum_repository.FPOpModes.MODE_DPGP.name: fp_enum_repository.FPPreGenPDefStates, - fp_enum_repository.FPOpModes.MODE_DEGP.name: fp_enum_repository.FPGenPermeateDefStates, - fp_enum_repository.FPOpModes.MODE_NLEG.name: fp_enum_repository.FPNotLegalStates} + self._op_mode_2_sub_mode = {fp_enum_repository.FPOpModes.MODE_FAUL.name: fp_enum_repository.FPFaultStates, + fp_enum_repository.FPOpModes.MODE_SERV.name: fp_enum_repository.FPServiceStates, + fp_enum_repository.FPOpModes.MODE_INIT.name: fp_enum_repository.FPPostStates, + fp_enum_repository.FPOpModes.MODE_STAN.name: fp_enum_repository.FPStandbyStates, + fp_enum_repository.FPOpModes.MODE_PRE_GENP.name: fp_enum_repository.FPPreGenPermeateStates, + fp_enum_repository.FPOpModes.MODE_GENP.name: fp_enum_repository.FPGenPermeateStates, + fp_enum_repository.FPOpModes.MODE_DPGP.name: fp_enum_repository.FPPreGenPDefStates, + fp_enum_repository.FPOpModes.MODE_DEGP.name: fp_enum_repository.FPGenPermeateDefStates, + fp_enum_repository.FPOpModes.MODE_NLEG.name: fp_enum_repository.FPNotLegalStates} # Loop through the list of the FP events enums and initial the event dictionary. Each event is a key in the # dictionary and the value is a list. - self._fp_event_dictionary = dict() + self._event_dictionary = dict() for event in fp_enum_repository.FPEventList: - self._fp_event_dictionary[fp_enum_repository.FPEventList(event).name] = [] + self._event_dictionary[fp_enum_repository.FPEventList(event).name] = [] def get_fp_nth_event(self, event_id, event_number=0): @@ -83,14 +83,14 @@ @returns the requested FP event number """ - list_length = len(self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name]) + list_length = len(self._event_dictionary[fp_enum_repository.FPEventList(event_id).name]) if list_length == 0: event = [] elif event_number > list_length: - event = self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name][list_length - 1] + event = self._event_dictionary[fp_enum_repository.FPEventList(event_id).name][list_length - 1] else: - event = self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name][list_length - event_number - 1] + event = self._event_dictionary[fp_enum_repository.FPEventList(event_id).name][list_length - event_number - 1] return event @@ -101,8 +101,8 @@ @returns none """ - for key in self._fp_event_dictionary: - self._fp_event_dictionary[key].clear() + for key in self._event_dictionary: + self._event_dictionary[key].clear() def get_fp_events(self, event_id, number_of_events=1): @@ -117,23 +117,23 @@ list_of_events = [] # If there are not enough event lists send all the events that are available - if len(self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name]) <= number_of_events: - list_of_events = self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name] + if len(self._event_dictionary[fp_enum_repository.FPEventList(event_id).name]) <= number_of_events: + list_of_events = self._event_dictionary[fp_enum_repository.FPEventList(event_id).name] else: # Get the all the events - complete_list = self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name] + complete_list = self._event_dictionary[fp_enum_repository.FPEventList(event_id).name] # Since the last are located at the end of the list, iterate backwards for the defined # event messages for i in range(len(complete_list) - 1, len(complete_list) - number_of_events - 1, -1): list_of_events.append(complete_list[i]) if number_of_events == 0: - list_of_events = self._fp_event_dictionary[fp_enum_repository.FPEventList(event_id).name] + list_of_events = self._event_dictionary[fp_enum_repository.FPEventList(event_id).name] return list_of_events - @publish(["msg_id_fp_event", "fp_events_timestamp", '_fp_event_dictionary']) + @publish(["msg_id_fp_event", "events_timestamp", '_event_dictionary']) def _handler_events_sync(self, message, timestamp=0.0): """ Handles published events message @@ -146,10 +146,10 @@ op_mode = 0 sub_mode = 0 sub_state = 0 - current_sub_tuple = [] event_id = struct.unpack(DataTypes.U32.unpack_attrib(), bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] + # Convert the event ID to enum compensated_event_id = event_id - dd_enum_repository.DDEventList.NUM_OF_DD_EVENT_IDS.value event_enum = fp_enum_repository.FPEventList(compensated_event_id) @@ -159,6 +159,9 @@ # Get the data type - irrelevant event_data_type_1 = struct.unpack(DataTypes.U32.unpack_attrib(), bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] + # For debug reasons get the full second byte + event_data_1 = struct.unpack(DataTypes(event_data_type_1).unpack_attrib(), bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3]))[0] # Opmode data is compressed into the 4 byte op_mode = struct.unpack(DataTypes.U08.unpack_attrib(), bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.START_POS_FIELD_3+1]))[0] @@ -197,81 +200,87 @@ # Check if the event state name is sub mode change. elif event_enum is fp_enum_repository.FPEventList.FP_EVENT_SUB_MODE_CHANGE: - # Get the length of the list of the op mode list - op_list_len = len(self._fp_event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_OP_MODE_CHANGE.name]) - # Get the last tuple of the op mode - # It is a list of tuples that each tuple is (timestamp, event type, prev op mode, current op mode) - if op_list_len != 0: - last_op_tuple = self._fp_event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_OP_MODE_CHANGE.name][-1] - else: - # No op mode event has been received before the submode event was received. Use broadcast messages to - # determine current op mode. Previous mode can not be known - last_op_tuple = (current_timestamp, - fp_enum_repository.FPEventList.FP_EVENT_OP_MODE_CHANGE.name, self.UNKNOWN_STATE, - fp_enum_repository.FPOpModes(self.fp_event_op_mode).name) - # Get the current and previous operation modes of the last tuple in the list of the sub modes - # i.e. (timestamp, event type, prev, current) - prev_op_mode_name = last_op_tuple[-1] - prev_op_mode_timestamp = datetime.strptime(last_op_tuple[0], '%Y-%m-%d %H:%M:%S.%f') + # Get the Op Mode Change messages + op_modes_list = self._event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_OP_MODE_CHANGE.name] + + # If there are Op mode change messages, use it to determine the operation mode for the current submode change + if len(op_modes_list) != 0: + # Get the Sub Mode Change messages + sub_mode_list = self._event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_SUB_MODE_CHANGE.name] + last_op_mode_message = op_modes_list[-1] - sub_mode_list_len = len(self._fp_event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_SUB_MODE_CHANGE.name]) + # Check if this is not the very first Sub Mode Change message + if len(sub_mode_list != 0): + # Get the timestamps of the last messages of both list for comparison + prev_op_mode_timestamp = datetime.strptime(last_op_mode_message[0], '%Y-%m-%d %H:%M:%S.%f') + prev_sub_mode_timestamp = datetime.strptime(sub_mode_list[-1][0], '%Y-%m-%d %H:%M:%S.%f') - if sub_mode_list_len != 0: - # Get the tuple prior to the last tuple and get its previous and current operation modes - current_sub_tuple = self._fp_event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_SUB_MODE_CHANGE.name][ - sub_mode_list_len - 1] + # In case the Op Mode Change is older then the previous Sub Mode Change, + # use the current Op Mode from the previous Op Mode Change message for both data + if prev_op_mode_timestamp <= prev_sub_mode_timestamp: + event_data_1 = self._op_mode_2_sub_mode[last_op_mode_message[3]] + event_data_2 = self._op_mode_2_sub_mode[last_op_mode_message[3]] + + # In case the Op Mode Change is newer then the previous Sub Mode Change, + # use the operation mode informations from the last Op Mode Change message + else: + event_data_1 = self._op_mode_2_sub_mode[last_op_mode_message[2]] + event_data_2 = self._op_mode_2_sub_mode[last_op_mode_message[3]] + + # In case this is the very first Sub Mode Change message, + # use the operation mode informations from the last Op Mode Change message + else: + event_data_1 = self._op_mode_2_sub_mode[last_op_mode_message[2]] + event_data_2 = self._op_mode_2_sub_mode[last_op_mode_message[3]] - current_sub_mode_timestamp = datetime.strptime(current_sub_tuple[0], '%Y-%m-%d %H:%M:%S.%f') + # In case there are no Op Mode Change messages, use the Operations States messages + # to identify the Op Modes for the Sub Modes else: - current_sub_mode_timestamp = 0 + # Get the Operation Status Change messages + op_status_list = self._event_dictionary[fp_enum_repository.FPEventList.FP_EVENT_OPERATION_STATUS.name] + + data_2_found = False + event_1_op_mode = self.UNKNOWN_STATE + event_2_op_mode = self.UNKNOWN_STATE - # Get the class of the states enums of the current operation mode that is running - current_sub_mode_enum_class = self._fp_op_mode_2_sub_mode[prev_op_mode_name] - - # Check if the operation modes of the two tuples match - # i.e. last = (timestamp, event type, prev, current) and one before = (timestamp, event type, prev, current) - # If the prev and current match respectively, it means the current operation mode has not changed so the - # operation mode states can be converted from the current sub mode enum class - if current_sub_mode_timestamp != 0: - if prev_op_mode_timestamp <= current_sub_mode_timestamp: - event_data_1 = current_sub_mode_enum_class(event_data_1).name - event_data_2 = current_sub_mode_enum_class(event_data_2).name - - elif prev_op_mode_timestamp > current_sub_mode_timestamp: - # If the previous and current of the last two tuples do not match, then an operation mode transition - # has occurred and the previous state is converted from the previous class and the current op mode - # is converted from current operation states enum class. - # i.e last = (timestamp, event type, 3, 8) and one before = (timestamp, event type, 8, 3) - # previous and current do not match so in the last type (timestamp, event type, 8, 3) the prev state - # should be from op mode 8 and the current state should be from op mode 3 - previous_op_mode = last_op_tuple[-2] - if previous_op_mode != FPEvents.UNKNOWN_STATE: - previous_sub_mode_enum_class = self._fp_op_mode_2_sub_mode[previous_op_mode] - event_data_1 = previous_sub_mode_enum_class(event_data_1).name - # Unknown previous state. Display value instead of name. + # Go through the list starting from the back + for i in range(len(op_status_list) - 1, -1, -1): + op_status_msg = op_status_list[i] + + # Look for a match for event_data_2 + if not data_2_found: + if op_status_msg[2] == event_data_2: + event_2_op_mode = fp_enum_repository.FPOpModes(op_status_msg[1]).name + data_2_found = True + + # Look for a match for event_data_1 after event_data_2 is found + # Criteria is that the opmode, submode pair can't be the same as the one found for event_data_2 else: - event_data_1 = str(event_data_1) - event_data_2 = current_sub_mode_enum_class(event_data_2).name - else: - if event_data_2 != 0: - event_data_1 = current_sub_mode_enum_class(event_data_1).name - event_data_2 = current_sub_mode_enum_class(event_data_2).name - else: - previous_sub_mode = current_sub_tuple[len(current_sub_tuple) - 2] - previous_sub_mode_enum_class = self._fp_op_mode_2_sub_mode[previous_sub_mode] - event_data_1 = previous_sub_mode_enum_class(event_data_1).name - event_data_2 = current_sub_mode_enum_class(event_data_2).name + if op_status_msg[2] == event_data_1 and \ + (op_status_msg[2] != event_data_2 or fp_enum_repository.FPOpModes(op_status_msg[1]).name != event_2_op_mode): + event_1_op_mode = fp_enum_repository.FPOpModes(op_status_msg[1]).name + + # If op mode for event_data_2 found but not found for event_data_1 and run out of operation states + # assume it's the start of the unit start up and the going to standby is not logged yet + if event_2_op_mode != self.UNKNOWN_STATE and event_1_op_mode == self.UNKNOWN_STATE: + event_1_op_mode = fp_enum_repository.FPOpModes.MODE_STAN.name + + # Update the event_data values + event_data_1 = self._op_mode_2_sub_mode[event_1_op_mode] + event_data_2 = self._op_mode_2_sub_mode[event_2_op_mode] + + # Update the tuple event_tuple = (current_timestamp, event_enum.name, event_data_1, event_data_2) elif event_enum is fp_enum_repository.FPEventList.FP_EVENT_OPERATION_STATUS: event_tuple = (current_timestamp, op_mode, sub_mode, sub_state) # Update event dictionary - self._fp_event_dictionary[event_enum.name].append(event_tuple) - self.fp_events_timestamp = timestamp + self._event_dictionary[event_enum.name].append(event_tuple) + self.events_timestamp = timestamp - @publish(["msg_id_fp_op_mode_data", "fp_event_op_mode_timestamp", "fp_event_op_mode", "fp_event_sub_mode"]) + @publish(["msg_id_fp_op_mode_data", "event_op_mode_timestamp", "op_mode", "sub_mode"]) def _handler_fp_op_mode_sync(self, message, timestamp=0.0): """ Handles published FP operation mode messages. Current FP operation mode @@ -281,9 +290,9 @@ @return: None """ msg_list = [] - msg_list.append(('self.fp_event_op_mode', DataTypes.U32)) - msg_list.append(('self.fp_event_sub_mode', DataTypes.U32)) + msg_list.append(('self.op_mode', DataTypes.U32)) + msg_list.append(('self.sub_mode', DataTypes.U32)) self.process_into_vars(decoder_list = msg_list, message = message) - self.fp_event_op_mode_timestamp = timestamp + self.event_op_mode_timestamp = timestamp