Esempio n. 1
0
    def _sendCommand(self, cmd):
        """
        cmd (str): command to be sent to Power Control unit.
        returns (str): answer received from the Power Control unit
        raises:
            IOError: if an ERROR is returned by the Power Control firmware.
        """
        cmd = (cmd + "\n").encode('latin1')
        with self._ser_access:
            logging.debug("Sending command %s" % to_str_escape(cmd))
            self._serial.write(cmd)

            ans = b''
            char = None
            while char != b'\n':
                char = self._serial.read()
                if not char:
                    logging.error("Timeout after receiving %s",
                                  to_str_escape(ans))
                    # TODO: See how you should handle a timeout before you raise
                    # an HWError
                    raise HwError(
                        "Power Control Unit connection timeout. "
                        "Please turn off and on the power to the box.")
                # Handle ERROR coming from Power control unit firmware
                ans += char

            logging.debug("Received answer %s", to_str_escape(ans))
            ans = ans.decode('latin1')
            if ans.startswith("ERROR"):
                raise PowerControlError(ans.split(' ', 1)[1])

            return ans.rstrip()
Esempio n. 2
0
    def _sendCommand(self, cmd):
        """
        cmd (str): command to be sent to device (without the CR)
        returns (str): answer received from the device (without \n or \r)
        raises:
            DPSSError: if an ERROR is returned by the device.
        """
        cmd = cmd + "\r"
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            self._serial.write(cmd.encode('latin1'))

            ans = b''
            while ans[-2:] != b'\r\n':
                char = self._serial.read()
                if not char:
                    raise IOError("Timeout after receiving %s" %
                                  to_str_escape(ans))
                ans += char

            logging.debug("Received answer %s", to_str_escape(ans))

            # TODO: check for other error answer?
            # Normally the device either answers OK, or a value, for commands finishing with a "?"
            if ans.startswith("Syntax error"):
                raise DPSSError(ans)

            return ans.decode('latin1').rstrip()
Esempio n. 3
0
    def _decodeMessage(self, msg):
        '''
        Decodes a message sent to the device and writes appropriate responses to
          the output buffer.
        msg: a string input message
        '''
        msg = msg.strip()  # clean whitespace from message

        if msg == b'':  # Empty message
            logging.warning('%s: Empty message received', self.name)
            return

        if msg == b":SYST:ERR?":  # Error query
            logging.debug('%s: Error state requested: %d', self.name,
                          self._error_state)
            if self._error_state:
                self._output_buffer += b'113,"Invalid command"\n'
            else:
                self._output_buffer += b'0,"No error"\n'
        elif msg == b"*IDN?":  # Request identifier command
            self._output_buffer += b'SimRigol\n'
            logging.debug('%s: Return identifier', self.name)
        elif re.match(b":SOUR(1|2):FREQ?", msg):
            self._output_buffer += b'%E\n' % (self._frequency, )
        elif re.match(b":OUTP(1|2) ON", msg):  # Channel 1 on command
            self._error_state = False
            logging.debug('%s: Set output on', self.name)
        elif re.match(b":OUTP(1|2) OFF", msg):  # Channel 1 off command
            self._error_state = False
            logging.debug('%s: Set output off', self.name)
        elif re.match(b":SOUR(1|2):APPL:SQU",
                      msg):  # Apply square wave command
            # Try to unpack the command to see if the format is correct
            try:
                cmd, para = msg.split(b" ")
                frequency, amplitude_pp, dc_bias, phase_shift = [
                    float(s) for s in para.split(b',')
                ]
                self._frequency = frequency
                logging.debug(
                    '%s: Set square wave %f Hz, %f Vpp, %f V bias, %f degrees',
                    self.name, frequency, amplitude_pp, dc_bias, phase_shift)
            except TypeError:  # could not unpack message
                self._error_state = True
                logging.exception('%s: Error Setting square wave %s',
                                  self.name, to_str_escape(msg))
        elif re.match(b":SOUR(1|2):FUNC:SQU:DCYC", msg):  # Duty cycle setting
            # Try to unpack the command to see if the format is correct
            try:
                cmd, para = msg.split(b" ")
                logging.debug('%s: Setting duty cycle to %f %%', self.name,
                              float(para))
            except TypeError:  # could not unpack message
                self._error_state = True
                logging.exception('%s: Error Setting duty cycle %s', self.name,
                                  to_str_escape(msg))
        else:
            self._error_state = True
            logging.exception('%s: Error state set for message: %s', self.name,
                              to_str_escape(msg))
Esempio n. 4
0
    def _sendQuery(self, cmd):
        """
        cmd (byte str): command to be sent to device
        returns (str): answer received from the device
        raise:
            IOError if no answer is returned in time
        """
        with self._net_access:
            logging.debug("Sending: %s", to_str_escape(cmd))
            self._socket.sendall(cmd + b'\r\n')

            ans = b''
            # TODO: Possibility that multiple replies will be contained within one packet
            # Might have to add this functionality
            while ans[-2:] != b"\r\n":
                try:
                    ans += self._socket.recv(4096)
                except socket.timeout:
                    # this is ok. Just means the server didn't send anything.
                    # Keep listening
                    logging.warning("Socket timeout on message %s",
                                    to_str_escape(cmd))

            logging.debug("Received: %s", to_str_escape(ans))

            return ans.strip().decode("latin1")
Esempio n. 5
0
    def _sendQuery(self, cmd):
        """
        cmd (byte str): command to be sent to device (without the LF, but with the ?)
        returns (byte str): answer received from the device (without \n or \r)
        raise:
            IOError if no answer is returned in time
        """
        cmd = cmd + b"\n"
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            self._serial.write(cmd)

            self._serial.timeout = 1
            ans = b''
            while ans[-1:] != b'\n':
                char = self._serial.read()
                if not char:
                    raise IOError("Timeout after receiving %s" %
                                  to_str_escape(ans))
                ans += char

            logging.debug("Received answer %s", to_str_escape(ans))

            time.sleep(0.05)  # prevent overloading the device with messages
            return ans.strip()
Esempio n. 6
0
 def _setValue(self, com, val=None):
     """
     Write a value (str)
     com (str): 3 characters command
     val (None or str): value to set
     raise:
         IOError if problem decoding the answer or timeout
         OXXError: if the device is unhappy (eg, unknown command, out of range)
     """
     if val is None:
         val = ""
     ans = self.acc.sendCommand("%s%s%s" % (com, self._com_chan, val))
     if not ans.startswith(com):
         raise IOError("Expected answer to start with %s but got %s" %
                       (com, to_str_escape(ans)))
     status = ans[len(com) + len(self._com_chan):]
     if not status:
         logging.warning("Answer too short after setting %s: %s", com,
                         to_str_escape(ans))
     elif status[0] == "x":
         raise OXXError("Failed to set %s to %s" % (com, val))
     elif status[0] == ">":
         pass
     else:
         logging.warning("Unexpected answer after setting %s: %s", com,
                         to_str_escape(ans))
Esempio n. 7
0
    def sendCommand(self, com):
        """
        Send a command which does not expect any report back
        com (string): command to send (not including the ? and the \r)
        return (string): the report without prefix ("!") nor carriage return.
        """
        assert (len(com) <= 50)
        full_com = ("?" + com + "\r").encode('latin1')
        logging.debug("Sending: '%s'", to_str_escape(full_com))
        self._serial.write(full_com)

        # ensure everything is received, before expecting an answer
        self._serial.flush()

        # Read lines per line until it's an answer (!)
        while True:
            line = self.readMessage()
            if line[0] == "$":  # ad-hoc message => we don't care
                logging.debug("Skipping ad-hoc message '%s'",
                              to_str_escape(line))
            else:
                break

        if not line[0] == "!":
            raise IOError("Answer prefix (!) not found.")
        if line.startswith("!UK"):  # !UK or !UK[n]
            raise OXXError("Unknown command (%s)." % to_str_escape(com))

        return line[1:]
Esempio n. 8
0
    def _sendCommand(self, cmd):
        """
        cmd (byte str): command to be sent to PMT Control unit.
        returns (byte str): answer received from the PMT Control unit
        raises:
            PMTControlError: if an ERROR is returned by the PMT Control firmware.
            HwError: in case the of connection timeout
        """
        cmd = cmd + b"\n"
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            try:
                self._serial.write(cmd)
            except IOError:
                logging.warn("Failed to send command to PMT Control firmware, "
                             "trying to reconnect.")
                if self._recovering:
                    raise
                else:
                    self._tryRecover()
                    # send command again
                    logging.debug(
                        "Sending command %s again after auto-reconnect" %
                        to_str_escape(cmd))
                    return self._sendCommand(cmd[:-1])  # cmd without \n

            ans = b''
            char = None
            while char != b'\n':
                try:
                    char = self._serial.read()
                except IOError:
                    logging.warn("Failed to read from PMT Control firmware, "
                                 "trying to reconnect.")
                    if self._recovering:
                        raise
                    else:
                        self._tryRecover()
                        # don't send command again
                        raise IOError(
                            "Failed to read from PMT Control firmware, "
                            "restarted serial connection.")

                if not char:
                    logging.error("Timeout after receiving %s",
                                  to_str_escape(ans))
                    # TODO: See how you should handle a timeout before you raise
                    # an HWError
                    raise HwError(
                        "PMT Control Unit connection timeout. "
                        "Please turn off and on the power to the box.")
                # Handle ERROR coming from PMT control unit firmware
                ans += char

            logging.debug("Received answer %s", to_str_escape(ans))
            if ans.startswith(b"ERROR"):
                raise PMTControlError(ans.split(b' ', 1)[1])

            return ans.rstrip()
Esempio n. 9
0
    def _parseMessage(self, msg):
        """
        msg (str): the message to parse (without the \r)
        return None: self._output_buf is updated if necessary
        """
        logging.debug("SIM: parsing %s", to_str_escape(msg))
        m = re.match(br"(?P<com>\*?[A-Za-z:]+\??)\W*(?P<args>.*)", msg)
        if not m:
            logging.error("Received unexpected message %s", msg)
            return

        com = m.group("com").upper()

        if m.group("args"):
            args = m.group("args").strip()
        else:
            args = None

        logging.debug("SIM: decoded message as %s %s", to_str_escape(com), args)

        # decode the command
        if com == b"*IDN?":
            self._sendAnswer(b"KEITHLEY INSTRUMENTS INC.,MODEL 6485,123456,C01   Sep 27 2017 12:22:00/A02  /J")
        elif com == b"*CLS":
            pass
        elif com == b"*STB?":
            self._sendAnswer(b"0")  # It's all fine
        elif com == b"STAT:QUE?":
            if not self._errorq:
                self._sendAnswer(b"0,\"No error\"")
            else:
                err = self._errorq.pop(0)
                self._sendAnswer(b"%d,\"Error %d\"" % (err, err))
        elif com == b"CONF:CURR":
            pass
        elif com == b":CURR:RANG:AUTO":
            pass
        elif com == b"SYST:LFR?":
            self._sendAnswer(b"%g" % self._lfr)
        elif com == b":NPLC?":
            self._sendAnswer(b"%g" % self._nplc)
        elif com == b":NPLC":
            if not args:
                self._addError(6)
            else:
                self._nplc = float(args)
        elif com in (b"MEAS:CURR?", b"READ?"):
            dur = (self._nplc / self._lfr) * 3 + 0.01
            time.sleep(dur)
            ts = time.time() - self._time_start
            val = random.uniform(-1e-9, 1e-9)
            self._sendAnswer(b"%EA,%E,%E" % (val, ts, 0))
        else:
            logging.warning(b"SIM: Unsupported instruction %s", to_str_escape(com))
            # TODO: add an error to the queue
            self._addError(1)
Esempio n. 10
0
    def _sendCommand(self, cmd):
        """
        :param cmd: (bytes) command to be sent to the hardware
        :returns: (str) response
        """
        cmd += EOL
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            try:
                self._serial.write(cmd)
            # TODO: what kind of exception is raised? Needs to be more specific.
            except:
                logging.warning("Failed to read from PMT Control firmware, "
                                "trying to reconnect.")
                if self._recovering:
                    raise
                else:
                    self._tryRecover()
                    # don't send command again
                    raise IOError("Failed to read from PMT Control firmware, "
                                  "restarted serial connection.")

            resp = b""
            while resp[-len(EOL):] != EOL:
                try:
                    char = self._serial.read()
                # TODO: what kind of exception is raised? Needs to be more specific.
                except:
                    logging.warning("Failed to read from PMT Control firmware, "
                                    "trying to reconnect.")
                    if self._recovering:
                        raise
                    else:
                        self._tryRecover()
                        # don't send command again
                        raise IOError("Failed to read from PMT Control firmware, "
                                      "restarted serial connection.")
                if not char:
                    raise IOError("Timeout after receiving %s" % to_str_escape(resp))
                else:
                    resp += char
            logging.debug("Received response %s", to_str_escape(resp))

            # Check response (command should be echoed back)
            if not resp.startswith(cmd[:-len(EOL)-1]):
                raise IOError("Response starts with %s != %s" % (to_str_escape(resp[:len(cmd)]), cmd))
            if b"_??_" in resp:
                raise ValueError("Received response %s, command %s not understood." % (to_str_escape(resp), cmd))
            if b"!" in resp:
                raise PMDError(0, to_str_escape(resp))
            # Format:
            #    * for query with response: <cmd>:<ret><EOL> (will return <ret>)
            #    * for set command without response: <cmd><EOL> (will return "")
            return resp[len(cmd) + 1 - len(EOL):-len(EOL)].decode("latin1")
Esempio n. 11
0
    def _SendCmd(self, cmd):
        """
        Send query/order to device
        cmd: valid query command for Remcon SEM
        returns str if successful, otherwise raises error
        """
        cmd = cmd + self.eol
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            self._serial.write(cmd)

            # Acknowledge
            ack = self._serial.read()  # valid/invalid
            if ack not in (RS_VALID, RS_INVALID):
                raise IOError(
                    "Acknowledge sign is expected, received '%s' instead." %
                    ack)
            ans = ack

            # EOL
            while ans[-len(self.eol):] != self.eol:
                char = self._serial.read()
                if not char:
                    raise IOError("Timeout after receiving %s" %
                                  to_str_escape(ans))
                else:
                    ans += char
            logging.debug("Received answer %s", to_str_escape(ans))

            # Status
            stat = self._serial.read()  # Success/fail
            ans = stat

            # Value
            while ans[-len(self.eol):] != self.eol:
                char = self._serial.read()
                if not char:
                    raise IOError("Timeout after receiving %s" %
                                  to_str_escape(ans))
                else:
                    ans += char
            logging.debug("Received answer %s", to_str_escape(ans))

            value = ans[1:-len(self.eol)]
            if stat == RS_SUCCESS:
                return value
            elif stat == RS_FAIL:
                raise RemconError(
                    int(value),
                    "Error %s after receiving command %s." % (int(value), cmd))
            else:
                raise IOError(
                    "Status sign is expected, received '%s' instead." % stat)
Esempio n. 12
0
    def sendQueryCommand(self, cmd):
        """
        Sends one command, and expect a reply
        cmd (str): command to send, including the ?
        returns:
            ans (str): response of the driver
        raises:
            IOError: if problem with sending/receiving data over the connection
        """
        if not self._is_connected:
            raise IOError("Device %s not connected." % (self._host, ))

        msg = ("%s\n" % cmd).encode('ascii')
        logging.debug("Sending command %s", to_str_escape(msg))

        with self._net_access:
            self.socket.sendall(msg)

            # read the answer
            end_time = time.time() + 0.5
            ans = b""
            while True:
                try:
                    data = self.socket.recv(4096)
                except socket.timeout:
                    raise IOError("Controller %s timed out after %s" %
                                  (self._host, to_str_escape(msg)))

                if not data:
                    logging.debug("Received empty message")

                ans += data
                # does it look like we received a full answer?
                if b"\n" in ans:
                    break

                if time.time() > end_time:
                    raise IOError("Controller %s timed out after %s" %
                                  (self._host, to_str_escape(msg)))
                time.sleep(0.01)

        logging.debug("Received: %s", to_str_escape(ans))

        ans, left = ans.split(b"\n", 1)  # remove the end of line characters
        if left:
            logging.error("Received too much data, will discard the end: %s",
                          to_str_escape(left))
        ans = ans.decode('latin1')
        return ans
Esempio n. 13
0
    def _ReadMessage(self, timeout=None):
        """
        Reads the next message
        timeout (0 < float): maximum time to wait for the message
        return:
             mid (int): message ID
             data (bytes): bytes 3&4 or the data of the message
        raise:
           IOError: if failed to send or receive message
        """
        old_timeout = self._serial.timeout
        if timeout is not None:
            # Should be only for the first byte, but doing it for the first 6
            # should rarely matter
            self._serial.timeout = timeout
        try:
            # read the first (required) 6 bytes
            msg = b""
            for i in range(6):
                char = self._serial.read()  # empty if timeout
                if not char:
                    raise IOError(
                        "Controller timed out, after receiving '%s'" %
                        to_str_escape(msg))

                msg += char
        finally:
            self._serial.timeout = old_timeout

        mid = struct.unpack("<H", msg[0:2])[0]
        if not (ord(msg[4:5]) & 0x80):  # short message
            logging.debug("Received: '%s'",
                          ", ".join("%02X" % c for c in bytearray(msg)))
            return mid, msg[2:4]

        # long message
        length = struct.unpack("<H", msg[2:4])[0]
        for i in range(length):
            char = self._serial.read()  # empty if timeout
            if not char:
                raise IOError("Controller timed out, after receiving '%s'" %
                              to_str_escape(msg))

            msg += char

        logging.debug("Received: '%s'",
                      ", ".join("%02X" % c for c in bytearray(msg)))
        return mid, msg[6:]
Esempio n. 14
0
    def GetSpecInfo(self):
        """
        Return:
            wavelength (float): in meters
            power (float): theoretical maximum power (W)
            subdev (set of int): subdevices available
        """
        ans = self._getValue("GSI")
        # Expects something like:
        # GSI [m63] (optional) int (wl in nm) § int (power in mW)
        try:
            m = re.match(r"(\[m(?P<mdev>\d+)])?(?P<wl>\d+)\xa7(?P<power>\d+)",
                         ans)
            mdev = m.group("mdev")
            if mdev is None:
                mdev = 0  # None if no mdev bitmask
            else:
                mdev = int(mdev)
            wl = int(m.group("wl")) * 1e-9  # m
            power = int(m.group("power")) * 1e-3  # W
        except Exception:
            raise ValueError("Failed to decode spec info answer '%s'" %
                             to_str_escape(ans))

        # Convert the bitmask into a set of int
        subdev = set()
        n = 1
        while mdev:
            if mdev & 0x1:
                subdev.add(n)
            n += 1
            mdev >>= 1

        return wl, power, subdev
Esempio n. 15
0
    def readMessage(self):
        """
        Reads one message from the device (== any character until \r)
        return str: the message (raw, without the ending \r)
        raise: IOError in case of timeout
        """
        line = b""
        char = self._serial.read()  # empty if timeout
        while char and char != b"\r":
            # FIXME: it seems that flushing the input doesn't work. It's
            # still possible to receives 0's at the beginning.
            # This is a kludge to workaround that
            if not line and char == b"\x00":
                logging.debug("Discarding null byte")
                char = b""

            # normal char
            line += char
            char = self._serial.read()
        logging.debug("Received: '%s'", to_str_escape(line))

        # Check it's a valid answer
        if not char:  # should always finish by a "\r"
            raise IOError("Controller timeout.")

        return line.decode('latin1')
Esempio n. 16
0
    def _listen(self):
        '''
        This method runs in a separate thread and listens for messages sent to the device via IP sockets
        '''
        # Listen for incoming connections
        self.socket.listen(1)

        while not self._shutdown_flag.is_set():
            # Wait for a connection
            logging.debug('%s: Waiting for a connection', self.name)
            connection, client_address = self.socket.accept()  # this function blocks until a connection is received.
            try:
                logging.debug('%s: Connection from : %s', self.name, client_address)

                # Receive the data in small chunks and retransmit it
                while True:
                    data = connection.recv(4096)    # read from the socket

                    if data:
                        data = data.strip()
                        # determine a command
                        for line in data.splitlines():
                            logging.debug('%s: Received: %s' % (self.name, to_str_escape(line)))
                            self._decodeMessage(line)
                            time.sleep(0.105) # wait a little before responding
                            self._sendBuffer(connection)
                    else:
                        # no more data to receive
                        break
            finally:
                # Clean up the connection
                connection.close()
Esempio n. 17
0
 def _sendOrder(self, cmd):
     """
     cmd (str): command to be sent to device (without the CR)
     """
     cmd = (cmd + "\r").encode('ascii')
     with self._ser_access:
         logging.debug("Sending command %s", to_str_escape(cmd))
         self._serial.write(cmd)
Esempio n. 18
0
 def _sendOrder(self, cmd):
     """
     cmd (byte str): command to be sent to device (without the CR)
     """
     cmd = cmd + b"\r"
     with self._ser_access:
         logging.debug("Sending command %s", to_str_escape(cmd))
         self._serial.write(cmd)
Esempio n. 19
0
    def _sendQuery(self, com):
        """
        Send a command which expects an answer
        com (byte string): command to send (not including the ? and the \r)
        return (byte string): the answer without newline and suffix ("> ")
        raises
            IOError: if there is a timeout
            TLFWError: if the hardware reports an error
        """
        # TODO: handle IOError and automatically try to reconnect (cf LLE)

        assert isinstance(com, bytes), 'com argument needs to be a byte string'
        assert (len(com) <= 50)  # commands cannot be long
        full_com = com + b"\r"
        with self._ser_access:
            logging.debug("Sending: '%s'", to_str_escape(full_com))
            self._serial.write(full_com)

            # ensure everything is received, before expecting an answer
            self._serial.flush()

            # Read until end of answer
            line = b""
            while True:
                char = self._serial.read()  # empty if timeout
                if not char:  # should always finish by a "> "
                    raise IOError("Controller timeout, after receiving '%s'" %
                                  to_str_escape(line))

                # normal char
                line += char
                if line[-2:] == b"> ":
                    break

            logging.debug("Received: '%s'", to_str_escape(line))

        # remove echo + suffix + new line
        line = line[len(full_com):-2].rstrip(b"\r")

        # if it's an error message => raise an error
        m = re.match(self.re_err, line)
        if m:
            err = m.group(1)
            raise TLFWError("Device rejected command '%s': %s" % (com, err))

        return line
Esempio n. 20
0
    def _processCommand(self, com):
        """
        process the command, and put the result in the output buffer
        com (str): command
        """
        logging.debug("Simulator received command %s", to_str_escape(com))
        out = None
        try:
            if com == b"*idn?":
                out = b"THORLABS FW102C/FW212C Fake Filter Wheel version 1.01"
            elif com.endswith(b"?"):
                name = com[:-1]
                val = self._state[name]
                out = b"%d" % val
            elif com.startswith(b"pos="):
                val = int(com[4:])
                if not 1 <= val <= self._state[b"pcount"]:
                    raise ValueError("%d" % val)

                # simulate a move
                curpos = self._state[b"pos"]
                p1, p2 = sorted([val, curpos])
                dist = min(p2 - p1, (6 + p1) - p2)
                if self._state[b"speed"] == 0:
                    dur = 2
                else:
                    dur = 1
                time.sleep(dist * dur)
                self._state[b"pos"] = val
                # no output
            else:
                # TODO: set of speed, trig, sensors,
                logging.debug("Command '%s' unknown", to_str_escape(com))
                raise KeyError("%s" % to_str_escape(com))
        except ValueError:
            out = b"Command error CMD_ARG_INVALID\n"
        except KeyError:
            out = b"Command error CMD_NOT_DEFINED\n"

        # add the response end
        if out is None:
            out = b""
        else:
            out += b"\r"
        out += b"> "
        self._output_buf += out
Esempio n. 21
0
    def _sendGetCommand(self, com, prefix="", suffix="\r\n\x03"):
        # Should normally never be called
        assert (len(com) <= 10)
        assert (len(prefix) <= 2)
        com = com.encode('latin1')
        logging.debug("Sending: %s", to_str_escape(com))
        self.serial.write(com)

        return ""
Esempio n. 22
0
    def _parseMessage(self, msg):
        """
        msg (str): the message to parse (without the \r)
        return None: self._output_buf is updated if necessary
        """
        logging.debug("SIM: parsing %s", to_str_escape(msg))
        msg = msg.decode(
            "latin1").strip()  # remove leading and trailing whitespace
        msg = "".join(msg.split())  # remove all space characters

        if msg == "*ESR?":  # error status register
            self._sendAnswer(b"%d" % (self._status_byte, ))
        elif msg == "*CLS":
            self._status_byte = POWER_ON
        elif msg == "*IDN?":
            self._sendAnswer(b"LSCI,MODEL335,fake,0.0")
        elif re.match('LOCK', msg):
            pass
        # Query setpoint
        elif re.match('SETP\?', msg):
            self._sendAnswer(b"+%.3f" % (self._setpoint, ))
        # set setpoint
        elif re.match("SETP", msg):
            vals = msg[4:].split(',')
            self._setpoint = float(vals[1])
        # Query heating range
        elif re.match('RANGE\?', msg):
            self._sendAnswer(b"%d" % (self._heating, ))
        # set heating range
        elif re.match("RANGE", msg):
            vals = msg[5:].split(',')
            self._heating = int(vals[1])
        # Query temperature
        elif re.match('KRDG\?', msg):
            # send temperature with some noise
            if os.path.exists(
                    os.path.join(model.BASE_DIRECTORY, "temp_increase.txt")):
                logging.info(
                    "Simulator set to increase temperature by 1 deg each reading"
                )
                self._temperature += 1
                self._sendAnswer(b"+%.3f" % (self._temperature))
            else:
                self._sendAnswer(
                    b"+%.3f" %
                    (self._temperature + random.uniform(-0.1, 0.1), ))
                if self._heating:
                    if self._temperature < self._setpoint:  # heating is enabled
                        self._temperature += 0.05 * self._heating  # simulate heating
                    else:
                        self._temperature -= 0.1
                else:  # no heating so no temperature control
                    # maintain stable temperature
                    if self._temperature > STABLE_TEMPERATURE:
                        self._temperature -= 0.1  # cool off with no heating
        else:
            self._status_byte |= COMMAND_ERROR
Esempio n. 23
0
 def _sendBuffer(self, connection):
     '''
     Transmit the contents of the output buffer over the connection
     connection: an active accepted socket connection
     '''
     if self._output_buffer:  # check if there is data in the buffer
         connection.sendall(self._output_buffer)
         logging.debug('%s: Sending transmission: %s', self.name,
                       to_str_escape(self._output_buffer))
         self._output_buffer = b''  # clear the buffer
Esempio n. 24
0
    def _sendGetCommand(self, com, prefix="", suffix="\r\n\x03"):
        """
        Send a command and return its report
        com (string): the command to send
        prefix (string): the prefix to the report,
            it will be removed from the return value
        suffix (string): the suffix of the report. Read will continue until it 
            is found or there is a timeout. It is removed from the return value.  
        return (string): the report without prefix nor newline
        """
        assert (len(com) <= 10)
        assert (len(prefix) <= 2)
        com = com.encode('latin1')
        logging.debug("Sending: %s", to_str_escape(com))
        self.serial.write(com)

        char = self.serial.read()  # empty if timeout
        report = char
        while char and not report.endswith(suffix):
            char = self.serial.read()
            report += char

        if not char:
            if not self._try_recover:
                raise IOError("PI controller %d timeout." % self.address)

            success = self.recoverTimeout()
            if success:
                logging.warning("PI controller %d timeout, but recovered.",
                                self.address)
                # TODO try to send again the command
            else:
                raise IOError("PI controller %d timeout, not recovered." %
                              self.address)

        logging.debug("Receive: %s", to_str_escape(report))
        if not report.startswith(prefix):
            raise IOError("Report prefix unexpected after '%s': '%s'." %
                          (com, report))

        report = report.decode(
            'latin1') if sys.version_info[0] >= 3 else report
        return report.lstrip(prefix).rstrip(suffix)
Esempio n. 25
0
    def recv(self, size=1):
        if not self._output_buf:
            # simulate timeout
            time.sleep(self.timeout)
            raise socket.timeout("No data after %g s" % (self.timeout,))

        ret = self._output_buf[:size]
        self._output_buf = self._output_buf[len(ret):]
        logging.debug("SIM: Sending %s", to_str_escape(ret))
        return ret
Esempio n. 26
0
    def _sendSetCommand(self, com):
        """
        Send a command which does not expect any report back
        com (string): command to send (including the \r if necessary)
        """
        for sc in com.split(","):
            assert (len(sc) < 10)

        com = com.encode('latin1')
        logging.debug("Sending: %s", to_str_escape(com))
        self.serial.write(com)
Esempio n. 27
0
    def _flushInput(self):
        """
        Ensure there is no more data queued to be read on the bus (=serial port)
        """
        with self._ser_access:
            self._serial.flush()
            self._serial.flushInput()

            # Shouldn't be necessary, but just in case
            skipped = self._serial.read(1000) # More than 1000 chars => give up
            logging.debug("Skipping input %s", to_str_escape(skipped))
Esempio n. 28
0
 def flushInput(self):
     """
     Ensure there is no more data queued to be read on the bus (=serial port)
     """
     self._serial.flush()
     self._serial.flushInput()
     while True:
         data = self._serial.read(100)
         if len(data) < 100:
             break
         logging.debug("Flushing data %s", to_str_escape(data))
Esempio n. 29
0
 def IsMotionDone(self, axis):
     """
     Check whether the axis is in motion 
     axis (1<=int<=4): axis number
     return (bool): False if in motion, True if motion is finished
     """
     resp = self._sendQueryCommand(b"MD", axis=axis)
     if resp == b"0": # motion in progress
         return False
     elif resp == b"1": # no motion
         return True
     else:
         raise IOError("Failed to decode answer about motion '%s'" % 
                       to_str_escape(resp))
Esempio n. 30
0
    def _sendQuery(self, cmd):
        """
        cmd (byte str): command to be sent to device (without the CR, but with the ?)
        returns (str): answer received from the device (without \n or \r)
        raise:
            IOError if no answer is returned in time
        """
        cmd = cmd + b"\r"
        with self._ser_access:
            logging.debug("Sending command %s", to_str_escape(cmd))
            self._serial.write(cmd)

            self._serial.timeout = 1
            ans = b''
            while ans[-1:] != b'\r':
                char = self._serial.read()
                if not char:
                    raise IOError("Timeout after receiving %s" %
                                  to_str_escape(ans))
                ans += char

            logging.debug("Received answer %s", to_str_escape(ans))

            return ans.strip().decode("latin1")