""" Implementation of the MKS ASCII Protocol as specified in "ASCII Protocol V1.8.pdf" """ from __future__ import absolute_import __author__ = "Georg Schlisio 0: break time.sleep(1) tries -= 1 if tries == 0: logging.error(f"Connection not successfully established: received no greeting. Exiting.") exit(201) message = self.down_queue.pop(0) assert message.type == "MKSRGA", f"Unexpected message type: {message.type}" assert message.parms[message.type] in ("Single", "Multi"), f"Unexpected connection type: {message.parms[message.type]}" assert message.parms[message.type] == "Single", f"Connection to QMS Servers of type 'Multi' is not supported." # To support this, implement the commands "Sensors" and "Select" assert "Protocol_Revision" in message.parms assert "Min_Compatibility" in message.parms self._remote_protocol_version = float(message.parms["Protocol_Revision"]) self._remote_min_protocol_version = float(message.parms["Min_Compatibility"]) if self._remote_min_protocol_version > self._protocol_version: logging.error(f"Version mismatches: remote requires V{self._remote_min_protocol_version} but we have only V{self._protocol_version}, exiting") exit(202) def _disconnect(self): """ Terminate connection :return: """ # send message "Release" self._s.send(composer(mtype="Release")) # TODO: replace sleep with actual check for "Release Ok" time.sleep(2) self._s.close() self._connected = False def _check_for_messages(self): """ Read socket buffer, parse messages and enqueue them into the message queue :return: """ rawinput = self._s.recv(4096).decode("ASCII").split("\r\r") if len(rawinput) > 1: logging.info(f"found {len(rawinput) - 1} messages") for i in range(len(rawinput) - 1): self.down_queue.put(ParseMessage(rawinput[i])) class MKSOperator(): _target_state = "run" _current_protocol_version = 1 _commands = { # controlling message formatting "FormatWithTab": {"type": "Controlling message formatting", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AcceptProtocol": {"type": "Controlling message formatting", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.5}, # sensor information commands "Sensors": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "Select": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SensorState": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "Info": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "EGains": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "InletInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "RFInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MultiplierInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DetectorInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "FilamentInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "TotalPressureInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "AnalogInputInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "AnalogOutputInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DigitalInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "RolloverInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CirrusInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_Info": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "Sensor": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceAlignmentInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceResolutionInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceTuningInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DiagnosticInputInfo": {"type": "Sensor Information Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "Control": {"type": "Gaining control of a sensor", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "Release": {"type": "Gaining control of a sensor", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, # sensor control commands "FilamentControl": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "FilamentSelect": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "FilamentOnTime": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AddAnalog": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AddBarchart": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AddPeakJump": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AddSinglePeak": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementAccuracy": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementAddMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementChangeMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementDetectorIndex": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementEGainIndex": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementFilterMode": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementPointsPerPeak": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementRemoveMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementSourceIndex": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementRolloverCorrection": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementZeroBeamOff": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementZeroBufferDepth": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementZeroBufferMode": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementZeroReTrigger": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementZeroMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MultiplierProtect": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "RunDiagnostics": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SetTotalPressure": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "TotalPressureCalFactor": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "TotalPressureCalDate": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CalibrationOptions": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "DetectorFactor": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "DetectorCalDate": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DetectorVoltage": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "InletFactor": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ScanAdd": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ScanStart": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ScanStop": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ScanResume": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ScanRestart": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.3}, "MeasurementSelect": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementStartMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementEndMass": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementMultSkipAutoProtect": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MeasurementMultSkipMassAdd": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MeasurementMultSkipMassRemove": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MeasurementMultSkipMassRemoveAll": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MeasurementRemoveAll": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MeasurementRemove": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceIonEnergy": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceEmission": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceExtract": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceElectronEnergy": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceLowMassResolution": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceLowMassAlignment": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceHighMassAlignment": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "SourceHighMassResolution": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "AnalogInputAverageCount": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AnalogInputEnable": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AnalogInputInterval": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AnalogOutput": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AudioFrequency": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AudioMode": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CirrusCapillaryHeater": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CirrusHeater": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CirrusPump": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "CirrusValvePosition": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DigitalMaxPB67OnTime": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DigitalOutput": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_DateMsg": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_Flush": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_Inlet": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_MassMethodContribution": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_Pressures": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "PECal_Select": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RolloverScaleFactor": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RolloverVariables": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCAlarm": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCCloseAllValves": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCHeater": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCPump": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCValveControl": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCValveMode": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "SaveChanges": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "StartDegas": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "StopDegas": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "SourceAlignmentCopyToAll": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceAlignmentUpdate": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceAlignmentRemove": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceResolutionCopyToAll": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceResolutionUpdate": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourceResolutiontRemove": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "SourcePoleBias": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DiagnosticInputAverageCount": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DiagnosticInputEnable": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DiagnosticInputInterval": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "InletSelect": {"type": "Sensor Control Commands", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.7}, # asynchronous sensor notifications "MKSRGA": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "FilamentStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "FilamentTimeRemaining": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "StartingScan": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "StartingMeasurement": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "ZeroReading": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "MassReading": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MultAutoSkip": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.4}, "MultiplierStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "RFTripState": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1}, "InletChange": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "AnalogInput": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "TotalPressure": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, "DigitalPortChange": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCPumpStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCHeaterStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCValveStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCInterlocks": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCStatus": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "RVCDigitalInput": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "LinkDown": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "VSCEvent": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DegasReading": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.2}, "DiagnosticInput": {"type": "Asynchronous Sensor Notifications", "description": "", "action": NotImplementedError, "expected_response": "", "from_version": 1.6}, } def __init__(self, up_queue:queue.SimpleQueue, down_queue:queue.SimpleQueue, command_actions:dict = {}): #raise NotImplementedError() self.up_queue = up_queue self.down_queue = down_queue # default pre-set actions self.register_command_actions({ "FormatWithTab": self._message_tab_formatting, "AcceptProtocol": self._current_protocol_version}) # update actions provided by user self.register_command_actions(command_actions) def run(self): while self._target_state == "run": message = self.down_queue.get(block=True, timeout=None) self._digest(message) def register_command_actions(self, actions:dict): """ Register actions for Protocol commands :param actions: dict, where the key is the command name and value is the callable. The callable must accept one argument (the message) :return: Nothing """ for command in actions: if command not in self._commands: logging.warning(f"Unknown command: {command}. Ignoring.") continue if self._commands[command]["from_version"] > self._current_protocol_version: logging.warning(f"Unsupported command {command} for our version {self._current_protocol_version}. Ignoring.") continue assert hasattr(command, "__call__") self._commands[command]["action"] = actions[command] def _digest_command(self, message): """ Receive Message and act upon it :param message: :return: :raises: """ assert isinstance(message, ParseMessage) if message.type not in self._commands: logging.error(f"Received unknown message type: {message.type}") raise NotImplementedError() try: self._commands[message.type].action(message) except NotImplementedError as e: logging.warning("Received unimplemented message {message.type} with content {message.body}") except Exception as e: logging.warning(f"Error during digestion of {message.type}: {e}") def _set_protocol_version(self, message): """ :param message: :return: """ assert message.type == "AcceptProtocol" raise NotImplementedError() def _message_tab_formatting(self, message): class ProtocolVersionError(Exception): raise NotImplementedError("TODO") # TODO if __name__ == "__main__": print(sys.version_info) # use https://docs.python.org/3/library/queue.html#queue.SimpleQueue q = queue.SimpleQueue() # producer: MKS_ASCII_Protocol instance # consumer: yet-to-write # launch both in separate threads (https://docs.python.org/3/library/threading.html) and have them communicating via queue p = MKSListener(ip="127.0.0.1") p.run()