示例#1
0
    def _dispatch_message(self, message):
        if not message:
            return None

        data_splits = message.split('|')
        header_type = data_splits[0]
        if len(data_splits) <= 1:
            self._log.log_message(LogLevel.Warning(), 'message is not valid')
            return None

        success = self._is_message_valid(message, header_type)

        if not success:
            self.error_count += 1

            if self.error_count == MAX_ERROR_COUNT:
                raise Exception('max error count is reached')

            self._log.log_message(LogLevel.Warning(),
                                  f'message: "{message}" could not be parsed')

            return None

        self.error_count = 0
        if self._is_command(header_type):
            return self._dispatch_command(data_splits)
        else:
            return self._dispatch_response(data_splits)
示例#2
0
    async def receive(self, request):
        ws = web.WebSocketResponse(heartbeat=1.0)
        await ws.prepare(request)

        connection_id = str(uuid.uuid1())
        ws_connection = WebSocketConnection(ws, connection_id)
        self._websockets.add(ws_connection)

        await self._send_connection_id_to_ws(ws, connection_id)

        # master should propagate the available settings each time a page reloaded
        # or new websocket connection is required
        self.handle_new_connection(connection_id)
        await self.send_configuration(self._app['master_app'].configuration, ws_connection)

        self._log.log_message(LogLevel.Debug(), 'websocket connection opened.')

        try:
            async for msg in ws:
                if msg.type == WSMsgType.TEXT:
                    self.handle_client_message(msg.data)
                elif msg.type == WSMsgType.ERROR:
                    self._log.log_message(LogLevel.Error(), f'ws connection closed with exception: {ws.exception()}')
        finally:
            pass

        self._discard_ws_connection_if_needed()
示例#3
0
    def on_cmd_message(self, message):
        try:
            data = json.loads(message.decode('utf-8'))
            assert data['type'] == 'cmd'
            cmd = data['command']
            sites = data['sites']

            self.log.log_message(LogLevel.Debug(), f'received command: {cmd}')

            if self.site_id not in sites:
                self.log.log_message(
                    LogLevel.Warning(),
                    f'ignoring TestApp cmd for other sites {sites} (current site_id is {self.site_id})'
                )
                return

            to_exec_command = self.commands.get(cmd)
            if to_exec_command is None:
                self.log.log_message(LogLevel.Warning(),
                                     'received command not found')
                return

            to_exec_command(data)

        except Exception as e:
            self._statemachine.error(str(e))
示例#4
0
 def wrapped_callback():
     try:
         cb(*args, **kwargs)
     except Exception as e:
         if self._statemachine is not None:
             self.logger.log_message(LogLevel.Error(), e)
             self.logger.log_message(LogLevel.Error(), 'exception in mqtt callback')
             self._statemachine.fail(str(e))
         else:
             raise
    def _send_set_log_level(self):
        level = {
            LogLevel.Debug(): 'Debug',
            LogLevel.Info(): 'Info',
            LogLevel.Warning(): 'Warning',
            LogLevel.Error(): 'Error',
        }[self.loglevel]

        self.log.log_message(LogLevel.Info(), f'set loglevel to {level}')
        self.connectionHandler.send_set_log_level(self.loglevel)
示例#6
0
    def _execute_cmd_init(self):
        self.logger.log_message(LogLevel.Debug(), 'COMMAND: init')
        # ToDo: How should we perform the selftest?
        self.logger.log_message(LogLevel.Info(), 'running self test...')
        selftest_result = self._sequencer_instance.init()
        self.logger.log_message(LogLevel.Info(), f'self test completed: {selftest_result}')

        self.send_status("IDLE")

        # TODO: how to report positive init command results? we could also write the testresult
        # self.publish_result(selftest_result, "<insert init result data here>")
        # note that currently once "init" failed the status will not be restored to ALIVE
        if not selftest_result:
            self._mqtt.publish_status(TheTestAppStatusAlive.INITFAIL, {'state': self._statemachine.state, 'payload': {'state': self._statemachine.state, 'message': 'selftest is failed'}})
    def does_handler_id_exist(self, param_data: dict):
        if not (param_data.get("HANDLER_PROBER") == self.device_handler):
            self.log.log_message(LogLevel.Warning(),
                                 'HANDLER name does not match')
            return False

        return True
    def is_lot_number_valid(self, param_data: dict, lot_number):
        if not (param_data.get("LOTNUMBER") == lot_number):
            self.log.log_message(LogLevel.Warning(),
                                 'lot number could not be found')
            return False

        return True
示例#9
0
    def receive(self, timeout_ms):
        self.sock.settimeout(timeout_ms)
        buffer = BytesIO()
        while True:
            # read exactly one line from the socket:
            received = select.select([self.sock], [], [], timeout_ms / 1000.0)
            if not received[0]:  # timeout!
                return ""

            data = self.sock.recv(255)

            if len(data) == 0:
                # We return NO data in case of a connectionloss,
                # which is basically the same as a timeout.
                # We'll try to reconnect on the next send. Doing this
                # here makes no sense, as we probably have missed parts
                # of the packet we were trying to receive anyway.
                self.connected = False
                self._log.log_message(LogLevel.Warning(),
                                      "Lost connection to DCS6k")
                return ""

            buffer.write(data)
            buffer.seek(0)
            for line in buffer:
                return line

            # If we got here, we did not receive a complete line yet, so we
            # move the file pointer to the end and keep on receiving.
            buffer.seek(0, 2)
    def dispatch_testapp_message(self, topic, msg):
        siteid = self.__extract_siteid_from_testapp_topic(topic)
        if siteid is None:
            # Hacky: To limit the number of routs we subscribed to # on control, thus we get served
            # the messages in cmd as well, which don't have a siteid in the topicname. To avoid
            # confusing logmessage we return early in that case:
            if "cmd" in topic:
                return
            self.log.log_message(
                LogLevel.Warning(),
                f'unexpected message on testapp topic {topic}: extracting siteid failed'
            )
            return

        if "testresult" in topic:
            self.status_consumer.on_testapp_testresult_changed(siteid, msg)
        elif "testsummary" in topic:
            self.status_consumer.on_testapp_testsummary_changed(msg)
        elif "io-control" in topic:
            assert 'type' in msg
            assert msg['type'] == 'io-control-request'
            assert 'periphery_type' in msg
            assert 'ioctl_name' in msg
            assert 'parameters' in msg
            self.status_consumer.on_testapp_resource_changed(siteid, msg)
        elif "status" in topic:
            self.status_consumer.on_testapp_status_changed(siteid, msg)
        elif "log" in topic:
            self.status_consumer.on_log_message(siteid, msg)
        else:
            assert False
示例#11
0
    def dispatch_testapp_message(self, topic, msg):
        siteid = self.__extract_siteid_from_testapp_topic(topic)
        if siteid is None:
            self.log.log_message(
                LogLevel.Warning(), 'unexpected message on testapp topic ' /
                + f'"{topic}": extracting siteid failed')
            return

        if "testresult" in topic:
            self.status_consumer.on_testapp_testresult_changed(siteid, msg)
        elif "testsummary" in topic:
            self.status_consumer.on_testapp_testsummary_changed(msg)
        elif "peripherystate" in topic:
            assert 'type' in msg
            assert msg['type'] == 'io-control-request'
            assert 'periphery_type' in msg
            assert 'ioctl_name' in msg
            assert 'parameters' in msg
            self.status_consumer.on_testapp_resource_changed(siteid, msg)
        elif "status" in topic:
            self.status_consumer.on_testapp_status_changed(siteid, msg)
        elif "log" in topic:
            self.status_consumer.on_log_message(siteid, msg)
        elif "binsettings" in topic:
            self.status_consumer.on_testapp_bininfo_message(siteid, msg)
        else:
            assert False
 def on_handler_command_message(self, msg: dict):
     cmd = msg.get('type')
     payload = msg.get('payload')
     try:
         {
             'load':
             lambda param_data: self.load_command(param_data),
             'next':
             lambda param_data: self.next(param_data),
             'unload':
             lambda param_data: self.unload(param_data),
             'reset':
             lambda param_data: self.reset(param_data),
             'identify':
             lambda param_data: self._send_tester_identification(param_data
                                                                 ),
             'get-state':
             lambda param_data: self._send_tester_state(param_data),
         }[cmd](payload)
     except KeyError:
         self.log.log_message(LogLevel.Error(),
                              f'Failed to execute command: {cmd}')
     except MachineError:
         self.on_error(
             f'cannot trigger command "{cmd}" from state "{self.fsm.model.state}"'
         )
示例#13
0
    def get_test_information(self, param_data: dict):
        for _, value in param_data.get("STATION").items():
            if self.does_device_id_exist(value):
                return self.remove_digit_from_keys(value)

        self.log.log_message(LogLevel.Warning(), 'device information in station section are missed')
        return None
示例#14
0
 def on_message(self, client, userdata, message):
     try:
         result = self.on_request(message.payload)
         result_json = json.dumps(result)
         self.mqtt_client.publish(f"ate/{self.device_id}/{self.actuator_type}/io-control/response", result_json)
     except json.JSONDecodeError as error:
         self._log.log_message(LogLevel.Error(), f'{error}')
 def dispatch_command(self, json_data):
     cmd = json_data.get('command')
     try:
         {
             'load':
             lambda param_data: self.load_command(param_data),
             'next':
             lambda param_data: self.next(param_data),
             'unload':
             lambda param_data: self.unload(param_data),
             'reset':
             lambda param_data: self.reset(param_data),
             'usersettings':
             lambda param_data: self.usersettings_command(param_data),
             'getresults':
             lambda param_data: self._handle_command_with_response(
                 param_data),
             'getlogs':
             lambda param_data: self._handle_command_with_response(
                 param_data),
             'getlogfile':
             lambda param_data: self._handle_command_with_response(
                 param_data),
             'setloglevel':
             lambda param_data: self.setloglevel(param_data),
         }[cmd](json_data)
     except Exception as e:
         self.log.log_message(LogLevel.Error(),
                              f'Failed to execute command {cmd}: {e}')
    def does_file_exist(self):
        if not os.path.exists(self.fullpath):
            self.log.log_message(LogLevel.Error(),
                                 f'file not found: {self.fullpath}')
            return False

        return True
    def publish_state(self, site_id=None, param_data=None):
        if self.prev_state == self.state:
            return

        self.prev_state = self.state
        self.log.log_message(LogLevel.Info(), f'Master state is {self.state}')
        self.connectionHandler.publish_state(self.external_state)
    def __get_config_parameters(self, config: dict, parameters: List[str]) -> Optional[str]:
        for param in parameters:
            if config.get(param) is None:
                self.log.log_message(LogLevel.Error(), f"failed to get '{param}' parameter")
                return None

        return config
示例#19
0
    def is_station_valid(self, param_data: dict):
        for _, value in param_data.items():
            if self.does_device_id_exist(value):
                return True

        self.log.log_message(LogLevel.Warning(), 'device id mismatch in station section')
        return False
示例#20
0
    def does_device_id_exist(self, param_data: dict):
        for key, value in param_data.items():
            if key == 'TESTER' or re.match(r'TESTER\d', key) is not None:
                if self.device_id == value:
                    return True

        self.log.log_message(LogLevel.Warning(), 'tester could not be found')
        return False
示例#21
0
    def publish_current_state(self, info):
        self._conhandler.publish_state(self.state, self._error_message)

        if self.prev_state != self.state:
            self.log.log_message(LogLevel.Info(),
                                 f'control state is: {self.state}')

        self.prev_state = self.state
示例#22
0
    def _execute_cmd_next(self, job_data: Optional[dict]):
        self.logger.log_message(LogLevel.Debug(), 'COMMAND: next')

        self.send_status("TESTING")
        result = self._sequencer_instance.run(self._execution_policy, job_data)
        self.send_status("IDLE")

        self.send_testresult(result)
示例#23
0
    def decode_payload(self, payload_bytes):
        try:
            payload = json.loads(payload_bytes)
            return payload
        except json.JSONDecodeError as error:
            self.log.log_message(LogLevel.Error(), f'{error}')

        return None
示例#24
0
    def on_reset(self, _):
        try:
            if self.process:
                self._terminate()
        except Exception as e:
            self.log.log_message(LogLevel.Error(),
                                 f"could not terminate testapp properly: {e}")

        self.to_idle(_)
示例#25
0
    def __init__(self, configuration, comm):
        self._mqtt = None
        self._log = Logger('handler', self._mqtt)
        loglevel = LogLevel.Warning() if configuration.get('loglevel') is None else configuration['loglevel']
        self._log.set_logger_level(loglevel)
        self.comm = comm

        self._get_configuration(configuration)
        self._machine = HandlerStateMachine()
    def on_cmd_message(self, message):
        payload = self.decode_message(message)

        to_exec_command = self.commands.get(payload.get("value"))
        if to_exec_command is None:
            self.log.log_message(LogLevel.Warning(),
                                 'received command not found')
            return False

        return to_exec_command()
    def apply_configuration(self, configuration: dict):
        try:
            self.configuredSites = configuration['sites']
            # Sanity check for bad configurations:
            if len(self.configuredSites) == 0:
                self.log.log_message(LogLevel.Error(),
                                     'Master got no sites assigned')
                sys.exit()

            self.device_id = configuration['device_id']
            self.broker_host = configuration['broker_host']
            self.broker_port = configuration['broker_port']
            self.enableTimeouts = configuration['enable_timeouts']
            self.handler_id = configuration['Handler']
            self.env = configuration['environment']
        except KeyError as e:
            self.log.log_message(LogLevel.Error(),
                                 f'Master got invalid configuration: {e}')
            sys.exit()
示例#28
0
 def handle_uncaught_exceptions_from_executor(f):
     try:
         f.result()
     except Exception:
         self.logger.log_message(LogLevel.Error(), "executor exception")
         # TODO: we probably don't want to keep running if any
         #       exception escaped. using os._exit may not be
         #       the best way to do this (because no cleanup/io
         #       flushing at all)
         os._exit(1)
 def send_load_test_to_all_sites(self, testapp_params):
     topic = f'ate/{self.device_id}/Control/cmd'
     params = {
         'type': 'cmd',
         'command': 'loadTest',
         'testapp_params': testapp_params,
         'sites': self.sites,
     }
     self.log.log_message(LogLevel.Info(), 'Send LoadLot to sites...')
     self.mqtt.publish(topic, json.dumps(params), 0, False)
示例#30
0
 def _get_configuration(self, configuration):
     try:
         self.handler_type = configuration['handler_type']
         self.handler_id = configuration['handler_id']
         self.device_ids = configuration['device_ids']
         self.broker = configuration['broker_host']
         self.broker_port = configuration['broker_port']
     except KeyError as e:
         self._log.log_message(LogLevel.Error(), f'Handler got invalid configuration: {e}')
         raise