1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
.. _module-pw_console-embedding:
===============
Embedding Guide
===============
-------------
Using embed()
-------------
``pw console`` is invoked by calling ``PwConsoleEmbed().embed()`` in your
own Python script. For a complete example of an embedded device console script see
:bdg-link-primary-line:`pw_system/py/pw_system/console.py <https://cs.pigweed.dev/pigweed/+/main:pw_system/py/pw_system/console.py>`.
.. automodule:: pw_console.embed
:members: PwConsoleEmbed
:undoc-members:
:show-inheritance:
.. _module-pw_console-embedding-logstore:
.. autoclass:: pw_console.log_store.LogStore
:members: __init__
:undoc-members:
:show-inheritance:
.. _module-pw_console-embedding-plugins:
Adding Plugins
==============
User plugin instances are created before starting-up and passed to the Pigweed
Console embed instance. Typically, a console is started by creating a
``PwConsoleEmbed()`` instance, calling customization functions, then calling
``.embed()`` as shown in `Using embed()`_. Adding plugins functions similarly by
calling ``add_top_toolbar``, ``add_bottom_toolbar``,
``add_floating_window_plugin`` or ``add_window_plugin``. For example:
.. code-block:: python
# Create plugin instances
user_toolbar1 = DeviceStatusToolbar(device=client.client.channel(1))
user_toolbar2 = BandwithToolbar()
user_device_window = CustomWindowPlugin()
console = PwConsoleEmbed(
global_vars=local_variables,
loggers={
'Device Logs': [logging.getLogger('rpc_device')],
'Host Logs': [logging.getLogger()],
},
...
)
# Add toolbar plugins
console.add_top_toolbar(user_toolbar1)
console.add_bottom_toolbar(user_toolbar2)
# Add Window plugins
console.add_window_plugin(user_device_window)
# Start the console
console.embed()
-------------------
Adding Log Metadata
-------------------
``pw_console`` can display log messages in a table with justified columns for
metadata fields provided by :ref:`module-pw_log_tokenized`.
It is also possible to manually add values that should be displayed in columns
using the ``extra`` keyword argument when logging from Python. See the `Python's
logging documentation`_ for how ``extra`` works. A dict of name, value pairs can
be passed in as the ``extra_metadata_fields`` variable. For example, the
following code will create a log message with two custom columns titled
``module`` and ``timestamp``.
.. code-block:: python
import logging
LOG = logging.getLogger('log_source_1')
LOG.info(
'Hello there!',
extra={
'extra_metadata_fields': {
'module': 'cool',
'timestamp': 1.2345,
}
}
)
---------------------
Debugging Serial Data
---------------------
``pw_console`` is often used to communicate with devices using `pySerial
<https://pythonhosted.org/pyserial/>`_ or
``pw_console.socket_client.SocketClient``. To monitor the raw data flowing over
the wire, ``pw_console`` provides simple wrappers for pySerial and socket client
instances that log data for each read and write call.
Logging data with PySerial
==========================
.. code-block:: python
# Instead of 'import serial' use this import:
from pw_console.pyserial_wrapper import SerialWithLogging
serial_device = SerialWithLogging('/dev/ttyUSB0', 115200, timeout=1)
Logging data with sockets
=========================
.. code-block:: python
from pw_console.socket_client import SocketClientWithLogging
serial_device = SocketClientWithLogging('localhost:1234')
.. tip::
The ``SocketClient`` takes an optional callback called when a disconnect is
detected. The ``pw_system`` console provides an example reconnect routine.
With the above examples each ``serial_device.read`` and ``write`` call will
create a log message to the ``pw_console.serial_debug_logger`` Python
logger. This logger can then be included as a log window pane in the
``PwConsoleEmbed()`` call.
.. code-block:: python
import logging
from pw_console import PwConsoleEmbed
console = PwConsoleEmbed(
global_vars=globals(),
local_vars=locals(),
loggers={
'Host Logs': [
# Root Python logger
logging.getLogger(''),
# Your current Python package logger.
logging.getLogger(__package__)
],
'Device Logs': [
logging.getLogger('usb_gadget')
],
'Serial Debug': [
# New log window to display serial read and writes
logging.getLogger('pw_console.serial_debug_logger')
],
},
app_title='CoolConsole',
)
# Then run the console with:
console.embed()
.. figure:: images/serial_debug.svg
:alt: Serial debug pw_console screenshot.
Screenshot of issuing an Echo RPC with serial debug logging.
.. _Python's logging documentation: https://docs.python.org/3/library/logging.html#logging.Logger.debug
|