class TimeTerminatedInterface(StreamInterface): """ A simple device where commands are terminated by a timeout. This demonstrates how to implement devices that do not have standard terminators and where a command is considered terminated after a certain time delay of not receiving more data. To interact with this device, you must switch telnet into char mode, or use netcat with special tty settings: $ telnet host port ^] telnet> mode char [type command and wait] $ stty -icanon && nc host port hello world! foobar! The following commands are available: - ``hello ``: Reply with "world!" - ``foo``: Replay with "bar!" - ``P``: Returns the device parameter - ``P=something``: Set parameter to specified value """ commands = { # Space as \x20 represents a custom 'terminator' for this command only # However, waiting for the timeout still applies Cmd("say_world", pattern=scanf("hello\x20")), Cmd("say_bar", pattern=scanf("foo")), Var("param", read_pattern=scanf("P"), write_pattern=scanf("P=%d")), } # An empty in_terminator triggers "timeout mode" # Otherwise, a ReadTimeout is considered an error. in_terminator = "" out_terminator = "\r\n" # Unusually long, for easier manual entry readtimeout = 2500 def handle_error(self, request, error): return "An error occurred: " + repr(error)
class ExampleMotorStreamInterface(StreamInterface): """ TCP-stream based example motor interface This motor simulation can be controlled via telnet: $ telnet host port Where the host and port-parameter are part of the dynamically created documentation for a concrete device instance. The motor starts moving immediately when a new target position is set. Once it's moving, it has to be stopped to receive a new target, otherwise an error is generated. """ commands = { Cmd('get_status', regex(r'^S\?$')), # explicit regex Cmd('get_position', r'^P\?$'), # implicit regex Cmd('get_target', r'^T\?$'), Cmd('set_target', scanf('T=%f')), # scanf format specification Cmd('stop', r'^H$', return_mapping=lambda x: 'T={},P={}'.format(x[0], x[1])), } in_terminator = '\r\n' out_terminator = '\r\n' def get_status(self): """Returns the status of the device, which is one of 'idle' or 'moving'.""" return self.device.state def get_position(self): """Returns the current position in mm.""" return self.device.position def get_target(self): """Returns the current target in mm.""" return self.device.target def set_target(self, new_target): """ Sets the new target in mm, the movement starts immediately. If the value is outside the interval [0, 250] or the motor is already moving, an error is returned, otherwise the new target is returned.""" try: self.device.target = new_target return 'T={}'.format(new_target) except RuntimeError: return 'err: not idle' except ValueError: return 'err: not 0<=T<=250'