예제 #1
0
def main():
    init_logging()

    transport = SerialTransport()
    c = Pytelemetry(transport)

    options = dict()
    options['port'] = "COM20"
    options['baudrate'] = 115200

    transport.connect(options)
    #c.subscribe(None, printer)

    bad_frame = bytearray(b'0700736f6d65746f70696300626f6f7961613ecc')
    c.api._decode_frame(bad_frame)

    c.publish('sometopic','booyaa','string')

    timeout = time.time() + 3

    while True:
        c.update()
        if time.time() > timeout:
            break

    transport.disconnect()
    print("Done.")
예제 #2
0
def test_unexisting_type():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)

    c.publish('sometopic',12,'int323')
    assert t.queue.qsize() == 0
예제 #3
0
def test_unexisting_type():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)

    with pytest.raises(IndexError):
        c.publish('sometopic',12,'int323')
    assert t.queue.qsize() == 0
예제 #4
0
def test_unexisting_type():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)

    with pytest.raises(IndexError):
        c.publish('sometopic', 12, 'int323')
    assert t.queue.qsize() == 0
예제 #5
0
def test_serial_stats():
    # Setup
    t = SerialTransport()
    t.driver = driverMock()
    c = Pytelemetry(t)

    stats = t.stats()

    assert stats['rx_bytes'] == 0
    assert stats['rx_chunks'] == 0
    assert stats['tx_bytes'] == 0
    assert stats['tx_chunks'] == 0

    c.publish('foo', 'bar', 'string')

    stats = t.stats()

    assert stats['rx_bytes'] == 0
    assert stats['rx_chunks'] == 0
    assert stats['tx_bytes'] == 13
    assert stats['tx_chunks'] == 1

    c.update()

    stats = t.stats()

    assert stats['rx_bytes'] == 13
    assert stats[
        'rx_chunks'] == 13  # TODO : For now data read byte after byter. To replace by read in bulk
    assert stats['tx_bytes'] == 13
    assert stats['tx_chunks'] == 1

    c.publish('fooqux', -32767, 'int16')

    stats = t.stats()

    assert stats['rx_bytes'] == 13
    assert stats['rx_chunks'] == 13
    assert stats['tx_bytes'] == 13 + 15
    assert stats['tx_chunks'] == 2

    c.update()

    stats = t.stats()

    assert stats['rx_bytes'] == 13 + 15
    assert stats['rx_chunks'] == 13 + 15
    assert stats['tx_bytes'] == 13 + 15
    assert stats['tx_chunks'] == 2

    t.resetStats()

    stats = t.stats()

    assert stats['rx_bytes'] == 0
    assert stats['rx_chunks'] == 0
    assert stats['tx_bytes'] == 0
    assert stats['tx_chunks'] == 0
예제 #6
0
def test_wrong_type():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)

    with pytest.raises(Exception) as excinfo:
        c.publish('sometopic', 12, 'string')
    # TODO : Assert exception
    assert t.queue.qsize() == 0
예제 #7
0
def test_wrong_type():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)

    with pytest.raises(Exception) as excinfo:
        c.publish('sometopic',12,'string')
    # TODO : Assert exception
    assert t.queue.qsize() == 0
예제 #8
0
def test_hardcoded():
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data"])
    c.subscribe('sometopic ',cb)

    # Apply hardcoded frame directly generated by the c library
    #        SOF  head  sometopic..................................... eol 12457........  crc.....  eof
    t.write([247, 6, 0, 115, 111, 109, 101, 116, 111, 112, 105, 99, 32, 0, 169, 48, 0, 0, 111, 249, 127])
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with('sometopic ',12457, None)
예제 #9
0
def test_serial_stats():
    # Setup
    t = SerialTransport()
    t.driver = driverMock()
    c = Pytelemetry(t)

    stats = t.stats()

    assert stats["rx_bytes"] == 0
    assert stats["rx_chunks"] == 0
    assert stats["tx_bytes"] == 0
    assert stats["tx_chunks"] == 0

    c.publish("foo", "bar", "string")

    stats = t.stats()

    assert stats["rx_bytes"] == 0
    assert stats["rx_chunks"] == 0
    assert stats["tx_bytes"] == 13
    assert stats["tx_chunks"] == 1

    c.update()

    stats = t.stats()

    assert stats["rx_bytes"] == 13
    assert stats["rx_chunks"] == 13  # TODO : For now data read byte after byter. To replace by read in bulk
    assert stats["tx_bytes"] == 13
    assert stats["tx_chunks"] == 1

    c.publish("fooqux", -32767, "int16")

    stats = t.stats()

    assert stats["rx_bytes"] == 13
    assert stats["rx_chunks"] == 13
    assert stats["tx_bytes"] == 13 + 15
    assert stats["tx_chunks"] == 2

    c.update()

    stats = t.stats()

    assert stats["rx_bytes"] == 13 + 15
    assert stats["rx_chunks"] == 13 + 15
    assert stats["tx_bytes"] == 13 + 15
    assert stats["tx_chunks"] == 2

    t.resetStats()

    stats = t.stats()

    assert stats["rx_bytes"] == 0
    assert stats["rx_chunks"] == 0
    assert stats["tx_bytes"] == 0
    assert stats["tx_chunks"] == 0
예제 #10
0
def test_topic_contains_space_both_ends():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data", "opts"])
    c.subscribe(' topicwithspaces ', cb)

    c.publish(' topicwithspaces ', 1234567, 'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with(' topicwithspaces ', 1234567, None)
예제 #11
0
def main():
    init_logging()

    transport = SerialTransport()
    c = Pytelemetry(transport)

    options = dict()
    options['port'] = "COM20"
    options['baudrate'] = 115200

    transport.connect(options)
    #c.subscribe(None, printer)

    bad_frame = bytearray(b'0700736f6d65746f70696300626f6f7961613ecc')
    c.api._decode_frame(bad_frame)

    c.publish('sometopic', 'booyaa', 'string')

    timeout = time.time() + 3

    while True:
        c.update()
        if time.time() > timeout:
            break

    transport.disconnect()
    print("Done.")
예제 #12
0
    def __init__(self, transport=None, stdout=None):
        # cmd Initialization and configuration
        cmd.Cmd.__init__(self, stdout=stdout)
        self.intro = 'pytelemetry terminal started.' \
                 + ' (type help for a list of commands.)'
        self.prompt = ':> '
        self.file = None

        # pytelemetry setup
        if not transport:
            self.transport = transports.SerialTransport()
        else:
            self.transport = transport
        self.telemetry = Pytelemetry(self.transport)

        self.topics = Topics()
        self.plots = []
        self.plotsLock = Lock()
        self.runner = Runner(self.transport, self.telemetry, self.plots,
                             self.plotsLock, self.topics)

        self.telemetry.subscribe(None, self.topics.process)

        self.types_lookup = {
            '--s': 'string',
            '--u8': 'uint8',
            '--u16': 'uint16',
            '--u32': 'uint32',
            '--i8': 'int8',
            '--i16': 'int16',
            '--i32': 'int32',
            '--f32': 'float32'
        }
        logger.info("Module path : %s" %
                    os.path.dirname(os.path.realpath(__file__)))
        try:
            logger.info("Module version : %s" % __version__)
        except:
            logger.warning("Module version : not found.")
예제 #13
0
def test_topic_contains_space_both_ends():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data","opts"])
    c.subscribe(' topicwithspaces ',cb)

    c.publish(' topicwithspaces ',1234567,'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with(' topicwithspaces ',1234567,None)
예제 #14
0
def test_hardcoded():
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data"])
    c.subscribe('sometopic ', cb)

    # Apply hardcoded frame directly generated by the c library
    #        SOF  head  sometopic..................................... eol 12457........  crc.....  eof
    t.write([
        247, 6, 0, 115, 111, 109, 101, 116, 111, 112, 105, 99, 32, 0, 169, 48,
        0, 0, 111, 249, 127
    ])
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with('sometopic ', 12457, None)
예제 #15
0
    def __init__(self, transport=None, stdout=None):
        # cmd Initialization and configuration
        cmd.Cmd.__init__(self,stdout=stdout)
        self.intro = 'pytelemetry terminal started.' \
                 + ' (type help for a list of commands.)'
        self.prompt = ':> '
        self.file = None

        # pytelemetry setup
        if not transport:
            self.transport = transports.SerialTransport()
        else:
            self.transport = transport
        self.telemetry = Pytelemetry(self.transport)

        self.topics = Topics()
        self.plots = []
        self.plotsLock = Lock()
        self.runner = Runner(self.transport,
                             self.telemetry,
                             self.plots,
                             self.plotsLock,
                             self.topics)

        self.telemetry.subscribe(None,self.topics.process)

        self.types_lookup = {'--s'    :  'string',
                             '--u8'   :  'uint8',
                             '--u16'  :  'uint16',
                             '--u32'  :  'uint32',
                             '--i8'   :  'int8',
                             '--i16'  :  'int16',
                             '--i32'  :  'int32',
                             '--f32'  :  'float32'}
        logger.info("Module path : %s" % os.path.dirname(os.path.realpath(__file__)))
        try:
            logger.info("Module version : %s" % __version__)
        except:
            logger.warning("Module version : not found.")
예제 #16
0
def test_protocol_stats():
    t = transportMock()
    p = Pytelemetry(t)

    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 0
    assert measures["rx_corrupted_crc"] == 0
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # Add a frame inside the transport queue
    t.write(bytearray.fromhex("f70700666f6f0062617247027f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 0
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # replaced CRC '4702' by '4701' to corrupt crc
    t.write(bytearray.fromhex("f70700666f6f0062617247017f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 1
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # replaced byte n3 '00' by '10' to corrupt crc
    t.write(bytearray.fromhex("f70710666f6f0062617247027f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    #crc = crc16(bytearray.fromhex("0900666f6f00626172"))
    #print(crc)
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Replaced header from 0700 to 0900 to corrupt it. Crc is valid to not discard
    t.write(bytearray.fromhex("f70900666f6f006261725fc57f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    #crc = crc16(bytearray.fromhex("0700666f6f01626172"))
    #print(crc)
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Removed EOL. Crc is valid to not discard
    t.write(bytearray.fromhex("f70700666f6f0162617224417f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 1
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # Impossible to detect corrupted payload of type string because length is unkown. One more reason to store framesize inside frame

    # Use a frame of type u32 instead
    #crc = crc16(bytearray.fromhex("03006b6c6d6f707100ffffff"))
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Corruped payload by removing third & fourth hex number from end. Crc will pass
    #
    t.write(bytearray.fromhex("f703006b6c6d6f707100fffffff2dd7f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 1
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 1
    assert measures["tx_encoded_frames"] == 0

    topmeasures = p.stats()

    assert measures["rx_decoded_frames"] == topmeasures['protocol']["rx_decoded_frames"]
    assert measures["rx_corrupted_crc"] == topmeasures['protocol']["rx_corrupted_crc"]
    assert measures["rx_corrupted_header"] == topmeasures['protocol']["rx_corrupted_header"]
    assert measures["rx_corrupted_eol"] == topmeasures['protocol']["rx_corrupted_eol"]
    assert measures["rx_corrupted_topic"] == topmeasures['protocol']["rx_corrupted_topic"]
    assert measures["rx_corrupted_payload"] == topmeasures['protocol']["rx_corrupted_payload"]
    assert measures["tx_encoded_frames"] == topmeasures['protocol']["tx_encoded_frames"]

    p.publish("boo", 123, "uint8")

    # get measurements
    measures = p.stats()

    assert measures['protocol']["rx_decoded_frames"] == 1
    assert measures['protocol']["rx_corrupted_crc"] == 2
    assert measures['protocol']["rx_corrupted_header"] == 1
    assert measures['protocol']["rx_corrupted_eol"] == 1
    assert measures['protocol']["rx_corrupted_topic"] == 0
    assert measures['protocol']["rx_corrupted_payload"] == 1
    assert measures['protocol']["tx_encoded_frames"] == 1

    measures = p.api.delimiter.stats()

    assert measures["rx_processed_bytes"] > 0
    assert measures["rx_discarded_bytes"] == 0
    assert measures["rx_escaped_bytes"] == 0
    assert measures["rx_complete_frames"] > 0
    assert measures["rx_uncomplete_frames"] == 0
    assert measures["tx_processed_bytes"] > 0
    assert measures["tx_encoded_frames"] > 0
    assert measures["tx_escaped_bytes"] == 0

    p.resetStats()
    measures = p.stats()

    assert measures['protocol']["rx_decoded_frames"] == 0
    assert measures['protocol']["rx_corrupted_crc"] == 0
    assert measures['protocol']["rx_corrupted_header"] == 0
    assert measures['protocol']["rx_corrupted_eol"] == 0
    assert measures['protocol']["rx_corrupted_topic"] == 0
    assert measures['protocol']["rx_corrupted_payload"] == 0
    assert measures['protocol']["tx_encoded_frames"] == 0

    assert measures['framing']["rx_processed_bytes"] == 0
    assert measures['framing']["rx_discarded_bytes"] == 0
    assert measures['framing']["rx_escaped_bytes"] == 0
    assert measures['framing']["rx_complete_frames"] == 0
    assert measures['framing']["rx_uncomplete_frames"] == 0
    assert measures['framing']["tx_processed_bytes"] == 0
    assert measures['framing']["tx_encoded_frames"] == 0
    assert measures['framing']["tx_escaped_bytes"] == 0
예제 #17
0
def test_end_to_end_string():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data","opts"])
    default_cb = mock.Mock(spec=["topic","data","opts"])
    c.subscribe('sometopic',cb)
    c.subscribe(None,default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic','someMessage','string')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with('sometopic','someMessage',None)

    # test default callback
    c.publish('othertopic','otherMessage','string')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    default_cb.assert_called_once_with('othertopic','otherMessage',None)
예제 #18
0
def test_end_to_end_uints():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data", "opts"])
    default_cb = mock.Mock(spec=["topic", "data", "opts"])
    c.subscribe('sometopic', cb)
    c.subscribe(None, default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 255, 'uint8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 255, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 65535, 'uint16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 65535, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 4294967295, 'uint32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 4294967295, None)
예제 #19
0
def test_end_to_end_uints():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data","opts"])
    default_cb = mock.Mock(spec=["topic","data","opts"])
    c.subscribe('sometopic',cb)
    c.subscribe(None,default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',255,'uint8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',255,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',65535,'uint16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',65535,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',4294967295,'uint32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',4294967295,None)
예제 #20
0
class Application(cmd.Cmd):
    def __init__(self, transport=None, stdout=None):
        # cmd Initialization and configuration
        cmd.Cmd.__init__(self, stdout=stdout)
        self.intro = 'pytelemetry terminal started.' \
                 + ' (type help for a list of commands.)'
        self.prompt = ':> '
        self.file = None

        # pytelemetry setup
        if not transport:
            self.transport = transports.SerialTransport()
        else:
            self.transport = transport
        self.telemetry = Pytelemetry(self.transport)

        self.topics = Topics()
        self.plots = []
        self.plotsLock = Lock()
        self.runner = Runner(self.transport, self.telemetry, self.plots,
                             self.plotsLock, self.topics)

        self.telemetry.subscribe(None, self.topics.process)

        self.types_lookup = {
            '--s': 'string',
            '--u8': 'uint8',
            '--u16': 'uint16',
            '--u32': 'uint32',
            '--i8': 'int8',
            '--i16': 'int16',
            '--i32': 'int32',
            '--f32': 'float32'
        }
        logger.info("Module path : %s" %
                    os.path.dirname(os.path.realpath(__file__)))
        try:
            logger.info("Module version : %s" % __version__)
        except:
            logger.warning("Module version : not found.")

    def emptyline(self):
        pass  # Override default behavior to repeat last command if empty input

    @docopt_cmd
    def do_serial(self, arg):
        """
List serial ports or connect to one of them.

Usage: serial ((-l | --list) | <port> [options])

Options:
-b X, --bauds X         Connection speed in bauds  [default: 9600]
        """
        if arg['--list'] or arg['-l']:
            self.stdout.write("Available COM ports:\n")
            for port, desc, hid in list_ports.comports():
                self.stdout.write("%s \t %s\n" % (port, desc))
            return

        try:
            self.runner.disconnect()
            logger.warn("User requested connect without desconnecting first.")
        except (IOError, AttributeError) as e:
            logger.warn(
                "Already disconnected. Continuing happily. E : {0}".format(e))
            pass

        self.topics.clear()
        logger.info("Cleared all topics for new session.")

        self.transport.resetStats(averaging_window=10)
        self.runner.resetStats()
        self.telemetry.resetStats()
        logger.info("Cleared all stats for new session.")

        try:
            b = int(arg['--bauds'])
            self.runner.connect(arg['<port>'], b)
        except IOError as e:
            self.stdout.write(
                "Failed to connect to {0} at {1} (bauds).\n".format(
                    arg['<port>'], b))

            logger.warn(
                "Failed to connect to {0} at {1} (bauds). E : \n".format(
                    arg['<port>'], b, e))
        else:
            s = "Connected to {0} at {1} (bauds).\n".format(arg['<port>'], b)
            self.stdout.write(s)
            logger.info(s)

    @docopt_cmd
    def do_print(self, arg):
        """
Prints X last received samples from <topic>.

Usage: print <topic> [options]

Options:
-a, --all        Display all received samples under <topic>
-l X, --limit X  Display X last received samples under <topic> [default: 1]

        """
        topic = arg['<topic>']
        if not self.topics.exists(topic):
            s = "Topic '{0}' unknown. Type 'ls' to list all available topics.\n".format(
                topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        try:
            if arg['--all']:
                amount = 0  # 0 is understood as 'return all samples' by self.topics.samples()
            else:
                amount = int(arg['--limit'])
        except:
            s = "Could not cast --limit = '{0}' to integer. Using 1.\n".format(
                arg['--limit'])
            self.stdout.write(s)
            logger.warn(s)
            amount = 1

        s = self.topics.samples(topic, amount)

        if s is not None:
            for i in s:
                self.stdout.write("{0}\n".format(i))
        else:
            logger.error(
                "Could not retrieve {0} sample(s) under topic '{1}'.\n".format(
                    amount, topic))

    @docopt_cmd
    def do_ls(self, arg):
        """
Prints available topics. Topics are basically labels under which data is available (for display, plot, etc).
Data can come from remote source (a connected embedded device) or the command-line interface itself (reception speed, etc).

Without flags, prints a list of remote topics.

Usage: ls [options]

Options:
-c, --cli       Prints all CLI topics. Use this to display topics for monitoring reception speed, errors amount, etc.
        """
        if arg['--cli']:
            for topic in self.topics.ls(source='cli'):
                self.stdout.write("%s\n" % topic)
            return

        for topic in self.topics.ls(source='remote'):
            self.stdout.write("%s\n" % topic)

    @docopt_cmd
    def do_plot(self, arg):
        """
Plots <topic> in a graph window.

Usage: plot <topic>
        """

        topic = arg['<topic>']

        if not self.topics.exists(topic):
            s = "Topic '{0}' unknown. Type 'ls' to list all available topics.\n".format(
                topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        if self.topics.intransfer(topic):
            s = "Topic '{0}' already plotting.\n".format(topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        has_indexes = self.topics.has_indexed_data(arg['<topic>'])

        if has_indexes:
            plotType = PlotType.indexed
            transferType = "indexed"
        else:
            plotType = PlotType.linear
            transferType = "linear"

        p = Superplot(topic, plotType)
        q, ctrl = p.start()

        # Protect self.plots from modifications from the runner thread
        self.plotsLock.acquire()

        self.plots.append({
            'topic': topic,
            'plot': p,  # Plot handler
            'queue': q,  # Data queue
            'ctrl': ctrl  # Plot control pipe
        })

        self.plotsLock.release()

        self.topics.transfer(topic, q, transfer_type=transferType)

        s = "Plotting '{0}' in mode [{1}].\n".format(topic, transferType)
        logger.info(s)
        self.stdout.write(s)

    @docopt_cmd
    def do_pub(self, arg):
        """
Publishes a (value | string) on <topic>.

Usage: pub (--u8 | --u16 | --u32 | --i8 | --i16 | --i32 | --f32 | --s) <topic> <value>
        """

        if arg['--f32']:
            arg['<value>'] = float(arg['<value>'])
        elif not arg['--s']:
            try:
                arg['<value>'] = int(arg['<value>'])
            except:
                # User most likely entered a float with an integer flag
                inter = float(arg['<value>'])
                rounded = int(inter)

                if isclose(inter, rounded):
                    arg['<value>'] = rounded
                else:
                    s = "Aborted : Wrote decimal number ({0}) with integer flag.".format(
                        arg['<value>'])
                    self.stdout.write(s + "\n")
                    logger.warning(s)
                    return

        subset = {
            k: arg[k]
            for k in ("--u8", "--u16", "--u32", "--i8", "--i16", "--i32",
                      "--f32", "--s")
        }

        valtype = None
        for i, k in subset.items():
            if k:
                valtype = self.types_lookup[i]

        if not valtype:
            logger.error("Payload type [{0}] unkown.".format(arg))
            return

        try:
            self.telemetry.publish(arg['<topic>'], arg['<value>'], valtype)
        except SerialTimeoutException as e:
            self.stdout.write("Pub failed. Connection most likely terminated.")
            logger.error(
                "Pub failed. Connection most likely terminated. exception : %s"
                % e)
            return
        except AttributeError as e:
            self.stdout.write(
                "Pub failed because you are not connected to any device. Connect first using `serial` command."
            )
            logger.warning(
                "Trying to publish while not connected. exception : %s" % e)
            return

        s = "Published on topic '{0}' : {1} [{2}]".format(
            arg['<topic>'], arg['<value>'], valtype)
        self.stdout.write(s + "\n")
        logger.info(s)

    @docopt_cmd
    def do_count(self, arg):
        """
Prints a count of received samples for each topic.

Usage: count
        """
        for topic in self.topics.ls():
            self.stdout.write("{0} : {1}\n".format(topic,
                                                   self.topics.count(topic)))

    @docopt_cmd
    def do_disconnect(self, arg):
        """
Disconnects from any open connection.

Usage: disconnect
        """
        try:
            self.runner.disconnect()
            self.stdout.write("Disconnected.\n")
            logger.info("Disconnected.")

            measures = self.transport.stats()

            for key, item in measures.items():
                logger.info("Raw IO : %s : %s" % (key, item))

            measures = self.runner.stats()

            for key, item in measures.items():
                logger.info("IO speeds : %s : %s" % (key, item))

            measures = self.telemetry.stats()

            for key, item in measures['framing'].items():
                logger.info("Framing : %s : %s" % (key, item))

            for key, item in measures['protocol'].items():
                logger.info("Protocol : %s : %s" % (key, item))

            logger.info("Logged session statistics.")

        except:
            logger.warn("Already disconnected. Continuing happily.")

    @docopt_cmd
    def do_info(self, arg):
        """
Prints out cli.py full path, module version.

Usage: info
        """
        self.stdout.write("- CLI path : %s\n" %
                          os.path.dirname(os.path.realpath(__file__)))
        try:
            self.stdout.write("- version : %s\n" % __version__)
        except:
            self.stdout.write("- version : not found.\n")

    @docopt_cmd
    def do_stats(self, arg):
        """
Displays different metrics about the active transport (ex : serial port).
This allows you to know if for instance corrupted frames are received, what fraction
of the maximum baudrate is being used, etc.

Usage: stats
        """
        measures = self.transport.stats()

        self.stdout.write("Raw IO:\n")
        for key, item in measures.items():
            self.stdout.write("\t%s : %s\n" % (key, item))

        measures = self.runner.stats()

        self.stdout.write("IO speeds:\n")
        for key, item in measures.items():
            self.stdout.write("\t%s : %s\n" % (key, item))

        measures = self.telemetry.stats()

        self.stdout.write("Framing:\n")
        for key, item in measures['framing'].items():
            self.stdout.write("\t%s : %s\n" % (key, item))

        self.stdout.write("Protocol:\n")
        for key, item in measures['protocol'].items():
            self.stdout.write("\t%s : %s\n" % (key, item))

    def do_quit(self, arg):
        """
Exits the terminal application.

Usage: quit
        """
        self.runner.terminate()
        self.do_disconnect("")
        self.stdout.write("Good Bye!\n")
        logger.info("Application quit.")
        exit()
예제 #21
0
def test_end_to_end_ints():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data", "opts"])
    default_cb = mock.Mock(spec=["topic", "data", "opts"])
    c.subscribe('sometopic', cb)
    c.subscribe(None, default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 127, 'int8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 127, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', -127, 'int8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', -127, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 32767, 'int16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 32767, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', -32767, 'int16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', -32767, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 2147483647, 'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 2147483647, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', -2147483647, 'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', -2147483647, None)
예제 #22
0
import runner
from pytelemetry import Pytelemetry
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = Pytelemetry(transport)
app = runner.Runner(transport, telemetry)


def printer(topic, data, options):
    if options:
        print(topic, '[', options['index'], "] : ", data)
    else:
        print(topic, " : ", data)


options = dict()
port = "COM20"
bauds = 115200

app.connect(port, bauds)

print("Connected.")

telemetry.subscribe(None, printer)
telemetry.publish('bar', 1354, 'int32')
time.sleep(3)

app.terminate()
print("Done.")
예제 #23
0
def test_end_to_end_floats():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data", "opts"])
    default_cb = mock.Mock(spec=["topic", "data", "opts"])
    c.subscribe('sometopic', cb)
    c.subscribe(None, default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 0.0, 'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic', 0.0, None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 3.4028234e38, 'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    assert abs(cb.call_args[0][1] - 3.4028234e38) <= max(
        1e-7 * max(abs(cb.call_args[0][1]), abs(3.4028234e38)), 0.0)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', -3.4028234e38, 'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    assert abs(cb.call_args[0][1] - (-3.4028234e38)) <= max(
        1e-7 * max(abs(cb.call_args[0][1]), abs(-3.4028234e38)), 0.0)
예제 #24
0
import tkinter as tk
from pytelemetry import Pytelemetry
import pytelemetry.transports.serialtransport as transports

pressedKeys = dict()
direction = 0
throttle = 0

# Configure pytelemetry
transport = transports.SerialTransport()
telemetry = Pytelemetry(transport)

def clear():
    global pressedKey
    global direction
    global throttle
    pressedKeys['Up'] = False
    pressedKeys['Down'] = False
    pressedKeys['Left'] = False
    pressedKeys['Right'] = False
    direction = 0
    throttle = 0

def onKeyPress(event):
    global pressedKey
    pressedKeys[event.keysym] = True

def onKeyRelease(event):
    global pressedKey
    pressedKeys[event.keysym] = False
예제 #25
0
def test_protocol_stats():
    t = transportMock()
    p = Pytelemetry(t)

    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 0
    assert measures["rx_corrupted_crc"] == 0
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # Add a frame inside the transport queue
    t.write(bytearray.fromhex("f70700666f6f0062617247027f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 0
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # replaced CRC '4702' by '4701' to corrupt crc
    t.write(bytearray.fromhex("f70700666f6f0062617247017f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 1
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # replaced byte n3 '00' by '10' to corrupt crc
    t.write(bytearray.fromhex("f70710666f6f0062617247027f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 0
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    #crc = crc16(bytearray.fromhex("0900666f6f00626172"))
    #print(crc)
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Replaced header from 0700 to 0900 to corrupt it. Crc is valid to not discard
    t.write(bytearray.fromhex("f70900666f6f006261725fc57f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 0
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    #crc = crc16(bytearray.fromhex("0700666f6f01626172"))
    #print(crc)
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Removed EOL. Crc is valid to not discard
    t.write(bytearray.fromhex("f70700666f6f0162617224417f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 1
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 0
    assert measures["tx_encoded_frames"] == 0

    # Impossible to detect corrupted payload of type string because length is unkown. One more reason to store framesize inside frame

    # Use a frame of type u32 instead
    #crc = crc16(bytearray.fromhex("03006b6c6d6f707100ffffff"))
    #crc = struct.pack("<H",crc)
    #print(crc.hex())

    # Corruped payload by removing third & fourth hex number from end. Crc will pass
    #
    t.write(bytearray.fromhex("f703006b6c6d6f707100fffffff2dd7f"))
    # update to read the new frame
    p.update()
    # get measurements
    measures = p.api.stats()

    assert measures["rx_decoded_frames"] == 1
    assert measures["rx_corrupted_crc"] == 2
    assert measures["rx_corrupted_header"] == 1
    assert measures["rx_corrupted_eol"] == 1
    assert measures["rx_corrupted_topic"] == 0
    assert measures["rx_corrupted_payload"] == 1
    assert measures["tx_encoded_frames"] == 0

    topmeasures = p.stats()

    assert measures["rx_decoded_frames"] == topmeasures['protocol'][
        "rx_decoded_frames"]
    assert measures["rx_corrupted_crc"] == topmeasures['protocol'][
        "rx_corrupted_crc"]
    assert measures["rx_corrupted_header"] == topmeasures['protocol'][
        "rx_corrupted_header"]
    assert measures["rx_corrupted_eol"] == topmeasures['protocol'][
        "rx_corrupted_eol"]
    assert measures["rx_corrupted_topic"] == topmeasures['protocol'][
        "rx_corrupted_topic"]
    assert measures["rx_corrupted_payload"] == topmeasures['protocol'][
        "rx_corrupted_payload"]
    assert measures["tx_encoded_frames"] == topmeasures['protocol'][
        "tx_encoded_frames"]

    p.publish("boo", 123, "uint8")

    # get measurements
    measures = p.stats()

    assert measures['protocol']["rx_decoded_frames"] == 1
    assert measures['protocol']["rx_corrupted_crc"] == 2
    assert measures['protocol']["rx_corrupted_header"] == 1
    assert measures['protocol']["rx_corrupted_eol"] == 1
    assert measures['protocol']["rx_corrupted_topic"] == 0
    assert measures['protocol']["rx_corrupted_payload"] == 1
    assert measures['protocol']["tx_encoded_frames"] == 1

    measures = p.api.delimiter.stats()

    assert measures["rx_processed_bytes"] > 0
    assert measures["rx_discarded_bytes"] == 0
    assert measures["rx_escaped_bytes"] == 0
    assert measures["rx_complete_frames"] > 0
    assert measures["rx_uncomplete_frames"] == 0
    assert measures["tx_processed_bytes"] > 0
    assert measures["tx_encoded_frames"] > 0
    assert measures["tx_escaped_bytes"] == 0

    p.resetStats()
    measures = p.stats()

    assert measures['protocol']["rx_decoded_frames"] == 0
    assert measures['protocol']["rx_corrupted_crc"] == 0
    assert measures['protocol']["rx_corrupted_header"] == 0
    assert measures['protocol']["rx_corrupted_eol"] == 0
    assert measures['protocol']["rx_corrupted_topic"] == 0
    assert measures['protocol']["rx_corrupted_payload"] == 0
    assert measures['protocol']["tx_encoded_frames"] == 0

    assert measures['framing']["rx_processed_bytes"] == 0
    assert measures['framing']["rx_discarded_bytes"] == 0
    assert measures['framing']["rx_escaped_bytes"] == 0
    assert measures['framing']["rx_complete_frames"] == 0
    assert measures['framing']["rx_uncomplete_frames"] == 0
    assert measures['framing']["tx_processed_bytes"] == 0
    assert measures['framing']["tx_encoded_frames"] == 0
    assert measures['framing']["tx_escaped_bytes"] == 0
예제 #26
0
def test_end_to_end_floats():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data","opts"])
    default_cb = mock.Mock(spec=["topic","data","opts"])
    c.subscribe('sometopic',cb)
    c.subscribe(None,default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',0.0,'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',0.0,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',3.4028234e38,'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    assert abs(cb.call_args[0][1] - 3.4028234e38) <= max(1e-7 * max(abs(cb.call_args[0][1]), abs(3.4028234e38)), 0.0)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',-3.4028234e38,'float32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    assert abs(cb.call_args[0][1] - (-3.4028234e38)) <= max(1e-7 * max(abs(cb.call_args[0][1]), abs(-3.4028234e38)), 0.0)
예제 #27
0
# --------- Import modules ---------- #
from pytelemetry import Pytelemetry
from pytelemetry.transports.serialtransport import *
import time
import socket
import json

# ---- Global Variables ---- #

# load envVariable.json
with open('./envVariable.json') as f:
    jsonFile = json.load(f)
config = json.loads(json.dumps(jsonFile))
transport = SerialTransport()
c = Pytelemetry(transport)

"""
*
* Function Name: 	init_port_forward
* Input: 		test boolean
* Output: 		None
* Logic: 		Initialises socket server, that communicates with js client
* Example Call:		int_port_forward()
*
"""
def init_port_forward(test=False):
    print("starting port from server")
    HOST = '127.0.0.1'  # Standard loopback interface address (localhost)
    # Port to listen on (non-privileged ports are > 1023)
    PORT = config["telemetrySocketPort"]
예제 #28
0
def test_end_to_end_ints():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic","data","opts"])
    default_cb = mock.Mock(spec=["topic","data","opts"])
    c.subscribe('sometopic',cb)
    c.subscribe(None,default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',127,'int8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',127,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',-127,'int8')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',-127,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',32767,'int16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',32767,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',-32767,'int16')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',-32767,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',2147483647,'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',2147483647,None)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic',-2147483647,'int32')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_with('sometopic',-2147483647,None)
예제 #29
0
class Application (cmd.Cmd):
    def __init__(self, transport=None, stdout=None):
        # cmd Initialization and configuration
        cmd.Cmd.__init__(self,stdout=stdout)
        self.intro = 'pytelemetry terminal started.' \
                 + ' (type help for a list of commands.)'
        self.prompt = ':> '
        self.file = None

        # pytelemetry setup
        if not transport:
            self.transport = transports.SerialTransport()
        else:
            self.transport = transport
        self.telemetry = Pytelemetry(self.transport)

        self.topics = Topics()
        self.plots = []
        self.plotsLock = Lock()
        self.runner = Runner(self.transport,
                             self.telemetry,
                             self.plots,
                             self.plotsLock,
                             self.topics)

        self.telemetry.subscribe(None,self.topics.process)

        self.types_lookup = {'--s'    :  'string',
                             '--u8'   :  'uint8',
                             '--u16'  :  'uint16',
                             '--u32'  :  'uint32',
                             '--i8'   :  'int8',
                             '--i16'  :  'int16',
                             '--i32'  :  'int32',
                             '--f32'  :  'float32'}
        logger.info("Module path : %s" % os.path.dirname(os.path.realpath(__file__)))
        try:
            logger.info("Module version : %s" % __version__)
        except:
            logger.warning("Module version : not found.")

    def emptyline(self):
        pass # Override default behavior to repeat last command if empty input

    @docopt_cmd
    def do_serial(self, arg):
        """
List serial ports or connect to one of them.

Usage: serial ((-l | --list) | <port> [options])

Options:
-b X, --bauds X         Connection speed in bauds  [default: 9600]
        """
        if arg['--list'] or arg['-l']:
            self.stdout.write("Available COM ports:\n")
            for port,desc,hid in list_ports.comports():
                self.stdout.write("%s \t %s\n" % (port,desc))
            return

        try:
            self.runner.disconnect()
            logger.warn("User requested connect without desconnecting first.")
        except (IOError,AttributeError) as e:
            logger.warn("Already disconnected. Continuing happily. E : {0}"
                         .format(e))
            pass

        self.topics.clear()
        logger.info("Cleared all topics for new session.")

        self.transport.resetStats(averaging_window=10)
        self.runner.resetStats()
        self.telemetry.resetStats()
        logger.info("Cleared all stats for new session.")

        try:
            b = int(arg['--bauds'])
            self.runner.connect(arg['<port>'],b)
        except IOError as e:
            self.stdout.write("Failed to connect to {0} at {1} (bauds).\n"
                    .format(arg['<port>'],b))

            logger.warn("Failed to connect to {0} at {1} (bauds). E : \n"
                          .format(arg['<port>'],b,e))
        else:
            s = "Connected to {0} at {1} (bauds).\n".format(arg['<port>'],b)
            self.stdout.write(s)
            logger.info(s)

    @docopt_cmd
    def do_print(self, arg):
        """
Prints X last received samples from <topic>.

Usage: print <topic> [options]

Options:
-a, --all        Display all received samples under <topic>
-l X, --limit X  Display X last received samples under <topic> [default: 1]

        """
        topic = arg['<topic>']
        if not self.topics.exists(topic):
            s = "Topic '{0}' unknown. Type 'ls' to list all available topics.\n".format(topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        try:
            if arg['--all']:
                amount = 0 # 0 is understood as 'return all samples' by self.topics.samples()
            else:
                amount = int(arg['--limit'])
        except:
            s = "Could not cast --limit = '{0}' to integer. Using 1.\n".format(arg['--limit'])
            self.stdout.write(s)
            logger.warn(s)
            amount = 1

        s = self.topics.samples(topic,amount)

        if s is not None:
            for i in s:
                self.stdout.write("{0}\n".format(i))
        else:
            logger.error("Could not retrieve {0} sample(s) under topic '{1}'.\n".format(amount,topic))

    @docopt_cmd
    def do_ls(self, arg):
        """
Prints available topics. Topics are basically labels under which data is available (for display, plot, etc).
Data can come from remote source (a connected embedded device) or the command-line interface itself (reception speed, etc).

Without flags, prints a list of remote topics.

Usage: ls [options]

Options:
-c, --cli       Prints all CLI topics. Use this to display topics for monitoring reception speed, errors amount, etc.
        """
        if arg['--cli']:
            for topic in self.topics.ls(source='cli'):
                self.stdout.write("%s\n" % topic)
            return

        for topic in self.topics.ls(source='remote'):
            self.stdout.write("%s\n" % topic)


    @docopt_cmd
    def do_plot(self, arg):
        """
Plots <topic> in a graph window.

Usage: plot <topic>
        """

        topic = arg['<topic>']

        if not self.topics.exists(topic):
            s = "Topic '{0}' unknown. Type 'ls' to list all available topics.\n".format(topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        if self.topics.intransfer(topic):
            s = "Topic '{0}' already plotting.\n".format(topic)
            self.stdout.write(s)
            logger.warn(s)
            return

        has_indexes = self.topics.has_indexed_data(arg['<topic>'])

        if has_indexes:
            plotType = PlotType.indexed
            transferType = "indexed"
        else:
            plotType = PlotType.linear
            transferType = "linear"

        p = Superplot(topic,plotType)
        q, ctrl = p.start()

        # Protect self.plots from modifications from the runner thread
        self.plotsLock.acquire()

        self.plots.append({
            'topic': topic,
            'plot': p,     # Plot handler
            'queue': q,    # Data queue
            'ctrl': ctrl   # Plot control pipe
        })

        self.plotsLock.release()

        self.topics.transfer(topic,q, transfer_type=transferType)

        s = "Plotting '{0}' in mode [{1}].\n".format(topic,transferType)
        logger.info(s)
        self.stdout.write(s)

    @docopt_cmd
    def do_pub(self, arg):
        """
Publishes a (value | string) on <topic>.

Usage: pub (--u8 | --u16 | --u32 | --i8 | --i16 | --i32 | --f32 | --s) <topic> <value>
        """

        if arg['--f32']:
            arg['<value>'] = float(arg['<value>'])
        elif not arg['--s']:
            try:
                arg['<value>'] = int(arg['<value>'])
            except:
                # User most likely entered a float with an integer flag
                inter = float(arg['<value>'])
                rounded = int(inter)

                if isclose(inter,rounded):
                    arg['<value>'] = rounded
                else:
                    s = "Aborted : Wrote decimal number ({0}) with integer flag.".format(arg['<value>'])
                    self.stdout.write(s + "\n")
                    logger.warning(s)
                    return


        subset = {k: arg[k] for k in ("--u8","--u16","--u32","--i8","--i16","--i32","--f32","--s")}

        valtype = None
        for i, k in subset.items():
            if k:
                valtype = self.types_lookup[i]

        if not valtype:
            logger.error(
                "Payload type [{0}] unkown."
                .format(arg))
            return

        try:
            self.telemetry.publish(arg['<topic>'],arg['<value>'],valtype)
        except SerialTimeoutException as e:
            self.stdout.write("Pub failed. Connection most likely terminated.")
            logger.error("Pub failed. Connection most likely terminated. exception : %s" % e)
            return
        except AttributeError as e:
            self.stdout.write("Pub failed because you are not connected to any device. Connect first using `serial` command.")
            logger.warning("Trying to publish while not connected. exception : %s" % e)
            return

        s = "Published on topic '{0}' : {1} [{2}]".format(arg['<topic>'], arg['<value>'],valtype)
        self.stdout.write(s + "\n")
        logger.info(s)

    @docopt_cmd
    def do_count(self, arg):
        """
Prints a count of received samples for each topic.

Usage: count
        """
        for topic in self.topics.ls():
            self.stdout.write("{0} : {1}\n".format(topic, self.topics.count(topic)))

    @docopt_cmd
    def do_disconnect(self, arg):
        """
Disconnects from any open connection.

Usage: disconnect
        """
        try:
            self.runner.disconnect()
            self.stdout.write("Disconnected.\n")
            logger.info("Disconnected.")

            measures = self.transport.stats()

            for key,item in measures.items():
                logger.info("Raw IO : %s : %s" % (key,item))

            measures = self.runner.stats()

            for key,item in measures.items():
                logger.info("IO speeds : %s : %s" % (key,item))

            measures = self.telemetry.stats()

            for key,item in measures['framing'].items():
                logger.info("Framing : %s : %s" % (key,item))

            for key,item in measures['protocol'].items():
                logger.info("Protocol : %s : %s" % (key,item))

            logger.info("Logged session statistics.")


        except:
            logger.warn("Already disconnected. Continuing happily.")

    @docopt_cmd
    def do_info(self, arg):
        """
Prints out cli.py full path, module version.

Usage: info
        """
        self.stdout.write("- CLI path : %s\n" % os.path.dirname(os.path.realpath(__file__)))
        try:
            self.stdout.write("- version : %s\n" % __version__)
        except:
            self.stdout.write("- version : not found.\n")

    @docopt_cmd
    def do_stats(self, arg):
        """
Displays different metrics about the active transport (ex : serial port).
This allows you to know if for instance corrupted frames are received, what fraction
of the maximum baudrate is being used, etc.

Usage: stats
        """
        measures = self.transport.stats()

        self.stdout.write("Raw IO:\n")
        for key,item in measures.items():
            self.stdout.write("\t%s : %s\n" % (key,item))

        measures = self.runner.stats()

        self.stdout.write("IO speeds:\n")
        for key,item in measures.items():
            self.stdout.write("\t%s : %s\n" % (key,item))

        measures = self.telemetry.stats()

        self.stdout.write("Framing:\n")
        for key,item in measures['framing'].items():
            self.stdout.write("\t%s : %s\n" % (key,item))

        self.stdout.write("Protocol:\n")
        for key,item in measures['protocol'].items():
            self.stdout.write("\t%s : %s\n" % (key,item))

    def do_quit(self, arg):
        """
Exits the terminal application.

Usage: quit
        """
        self.runner.terminate()
        self.do_disconnect("")
        self.stdout.write("Good Bye!\n")
        logger.info("Application quit.")
        exit()
예제 #30
0
import runner
from pytelemetry import Pytelemetry
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = Pytelemetry(transport)
app = runner.Runner(transport,telemetry)

def printer(topic, data, options):
    if options:
        print(topic,'[',options['index'],"] : ", data)
    else:
        print(topic," : ", data)
options = dict()
port = "COM20"
bauds = 115200

app.connect(port,bauds)

print("Connected.")

telemetry.subscribe(None, printer)
telemetry.publish('bar',1354,'int32')
time.sleep(3)

app.terminate()
print("Done.")
예제 #31
0
def test_end_to_end_string():
    # Setup
    t = transportMock()
    c = Pytelemetry(t)
    cb = mock.Mock(spec=["topic", "data", "opts"])
    default_cb = mock.Mock(spec=["topic", "data", "opts"])
    c.subscribe('sometopic', cb)
    c.subscribe(None, default_cb)

    # testing callback subscribed to topic
    assert t.queue.qsize() == 0
    c.publish('sometopic', 'someMessage', 'string')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    cb.assert_called_once_with('sometopic', 'someMessage', None)

    # test default callback
    c.publish('othertopic', 'otherMessage', 'string')
    assert t.queue.qsize() > 0
    c.update()
    assert t.queue.qsize() == 0
    default_cb.assert_called_once_with('othertopic', 'otherMessage', None)