1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_console-embedding: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker=============== 4*61c4878aSAndroid Build Coastguard WorkerEmbedding Guide 5*61c4878aSAndroid Build Coastguard Worker=============== 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_console 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker------------- 10*61c4878aSAndroid Build Coastguard WorkerUsing embed() 11*61c4878aSAndroid Build Coastguard Worker------------- 12*61c4878aSAndroid Build Coastguard Worker``pw console`` is invoked by calling ``PwConsoleEmbed().embed()`` in your 13*61c4878aSAndroid Build Coastguard Workerown Python script. For a complete example of an embedded device console script see 14*61c4878aSAndroid Build Coastguard Worker:bdg-link-primary-line:`pw_system/py/pw_system/console.py <https://cs.pigweed.dev/pigweed/+/main:pw_system/py/pw_system/console.py>`. 15*61c4878aSAndroid Build Coastguard Worker 16*61c4878aSAndroid Build Coastguard Worker.. automodule:: pw_console.embed 17*61c4878aSAndroid Build Coastguard Worker :members: PwConsoleEmbed 18*61c4878aSAndroid Build Coastguard Worker :undoc-members: 19*61c4878aSAndroid Build Coastguard Worker :show-inheritance: 20*61c4878aSAndroid Build Coastguard Worker 21*61c4878aSAndroid Build Coastguard Worker.. _module-pw_console-embedding-logstore: 22*61c4878aSAndroid Build Coastguard Worker 23*61c4878aSAndroid Build Coastguard Worker.. autoclass:: pw_console.log_store.LogStore 24*61c4878aSAndroid Build Coastguard Worker :members: __init__ 25*61c4878aSAndroid Build Coastguard Worker :undoc-members: 26*61c4878aSAndroid Build Coastguard Worker :show-inheritance: 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker.. _module-pw_console-embedding-plugins: 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard WorkerAdding Plugins 31*61c4878aSAndroid Build Coastguard Worker============== 32*61c4878aSAndroid Build Coastguard WorkerUser plugin instances are created before starting-up and passed to the Pigweed 33*61c4878aSAndroid Build Coastguard WorkerConsole embed instance. Typically, a console is started by creating a 34*61c4878aSAndroid Build Coastguard Worker``PwConsoleEmbed()`` instance, calling customization functions, then calling 35*61c4878aSAndroid Build Coastguard Worker``.embed()`` as shown in `Using embed()`_. Adding plugins functions similarly by 36*61c4878aSAndroid Build Coastguard Workercalling ``add_top_toolbar``, ``add_bottom_toolbar``, 37*61c4878aSAndroid Build Coastguard Worker``add_floating_window_plugin`` or ``add_window_plugin``. For example: 38*61c4878aSAndroid Build Coastguard Worker 39*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard Worker # Create plugin instances 42*61c4878aSAndroid Build Coastguard Worker user_toolbar1 = DeviceStatusToolbar(device=client.client.channel(1)) 43*61c4878aSAndroid Build Coastguard Worker user_toolbar2 = BandwithToolbar() 44*61c4878aSAndroid Build Coastguard Worker user_device_window = CustomWindowPlugin() 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard Worker console = PwConsoleEmbed( 47*61c4878aSAndroid Build Coastguard Worker global_vars=local_variables, 48*61c4878aSAndroid Build Coastguard Worker loggers={ 49*61c4878aSAndroid Build Coastguard Worker 'Device Logs': [logging.getLogger('rpc_device')], 50*61c4878aSAndroid Build Coastguard Worker 'Host Logs': [logging.getLogger()], 51*61c4878aSAndroid Build Coastguard Worker }, 52*61c4878aSAndroid Build Coastguard Worker ... 53*61c4878aSAndroid Build Coastguard Worker ) 54*61c4878aSAndroid Build Coastguard Worker 55*61c4878aSAndroid Build Coastguard Worker # Add toolbar plugins 56*61c4878aSAndroid Build Coastguard Worker console.add_top_toolbar(user_toolbar1) 57*61c4878aSAndroid Build Coastguard Worker console.add_bottom_toolbar(user_toolbar2) 58*61c4878aSAndroid Build Coastguard Worker 59*61c4878aSAndroid Build Coastguard Worker # Add Window plugins 60*61c4878aSAndroid Build Coastguard Worker console.add_window_plugin(user_device_window) 61*61c4878aSAndroid Build Coastguard Worker 62*61c4878aSAndroid Build Coastguard Worker # Start the console 63*61c4878aSAndroid Build Coastguard Worker console.embed() 64*61c4878aSAndroid Build Coastguard Worker 65*61c4878aSAndroid Build Coastguard Worker------------------- 66*61c4878aSAndroid Build Coastguard WorkerAdding Log Metadata 67*61c4878aSAndroid Build Coastguard Worker------------------- 68*61c4878aSAndroid Build Coastguard Worker``pw_console`` can display log messages in a table with justified columns for 69*61c4878aSAndroid Build Coastguard Workermetadata fields provided by :ref:`module-pw_log_tokenized`. 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard WorkerIt is also possible to manually add values that should be displayed in columns 72*61c4878aSAndroid Build Coastguard Workerusing the ``extra`` keyword argument when logging from Python. See the `Python's 73*61c4878aSAndroid Build Coastguard Workerlogging documentation`_ for how ``extra`` works. A dict of name, value pairs can 74*61c4878aSAndroid Build Coastguard Workerbe passed in as the ``extra_metadata_fields`` variable. For example, the 75*61c4878aSAndroid Build Coastguard Workerfollowing code will create a log message with two custom columns titled 76*61c4878aSAndroid Build Coastguard Worker``module`` and ``timestamp``. 77*61c4878aSAndroid Build Coastguard Worker 78*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 79*61c4878aSAndroid Build Coastguard Worker 80*61c4878aSAndroid Build Coastguard Worker import logging 81*61c4878aSAndroid Build Coastguard Worker 82*61c4878aSAndroid Build Coastguard Worker LOG = logging.getLogger('log_source_1') 83*61c4878aSAndroid Build Coastguard Worker 84*61c4878aSAndroid Build Coastguard Worker LOG.info( 85*61c4878aSAndroid Build Coastguard Worker 'Hello there!', 86*61c4878aSAndroid Build Coastguard Worker extra={ 87*61c4878aSAndroid Build Coastguard Worker 'extra_metadata_fields': { 88*61c4878aSAndroid Build Coastguard Worker 'module': 'cool', 89*61c4878aSAndroid Build Coastguard Worker 'timestamp': 1.2345, 90*61c4878aSAndroid Build Coastguard Worker } 91*61c4878aSAndroid Build Coastguard Worker } 92*61c4878aSAndroid Build Coastguard Worker ) 93*61c4878aSAndroid Build Coastguard Worker 94*61c4878aSAndroid Build Coastguard Worker--------------------- 95*61c4878aSAndroid Build Coastguard WorkerDebugging Serial Data 96*61c4878aSAndroid Build Coastguard Worker--------------------- 97*61c4878aSAndroid Build Coastguard Worker``pw_console`` is often used to communicate with devices using `pySerial 98*61c4878aSAndroid Build Coastguard Worker<https://pythonhosted.org/pyserial/>`_ or 99*61c4878aSAndroid Build Coastguard Worker``pw_console.socket_client.SocketClient``. To monitor the raw data flowing over 100*61c4878aSAndroid Build Coastguard Workerthe wire, ``pw_console`` provides simple wrappers for pySerial and socket client 101*61c4878aSAndroid Build Coastguard Workerinstances that log data for each read and write call. 102*61c4878aSAndroid Build Coastguard Worker 103*61c4878aSAndroid Build Coastguard WorkerLogging data with PySerial 104*61c4878aSAndroid Build Coastguard Worker========================== 105*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 106*61c4878aSAndroid Build Coastguard Worker 107*61c4878aSAndroid Build Coastguard Worker # Instead of 'import serial' use this import: 108*61c4878aSAndroid Build Coastguard Worker from pw_console.pyserial_wrapper import SerialWithLogging 109*61c4878aSAndroid Build Coastguard Worker 110*61c4878aSAndroid Build Coastguard Worker serial_device = SerialWithLogging('/dev/ttyUSB0', 115200, timeout=1) 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard WorkerLogging data with sockets 113*61c4878aSAndroid Build Coastguard Worker========================= 114*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 115*61c4878aSAndroid Build Coastguard Worker 116*61c4878aSAndroid Build Coastguard Worker from pw_console.socket_client import SocketClientWithLogging 117*61c4878aSAndroid Build Coastguard Worker 118*61c4878aSAndroid Build Coastguard Worker # Name resolution with explicit port 119*61c4878aSAndroid Build Coastguard Worker serial_device = SocketClientWithLogging('localhost:1234') 120*61c4878aSAndroid Build Coastguard Worker # Name resolution with default port. 121*61c4878aSAndroid Build Coastguard Worker serial_device = SocketClientWithLogging('pigweed.dev') 122*61c4878aSAndroid Build Coastguard Worker # Link-local IPv6 address with explicit port. 123*61c4878aSAndroid Build Coastguard Worker serial_device = SocketClientWithLogging('[fe80::100%enp1s0]:1234') 124*61c4878aSAndroid Build Coastguard Worker # Link-local IPv6 address with default port. 125*61c4878aSAndroid Build Coastguard Worker serial_device = SocketClientWithLogging('[fe80::100%enp1s0]') 126*61c4878aSAndroid Build Coastguard Worker # IPv4 address with port. 127*61c4878aSAndroid Build Coastguard Worker serial_device = SocketClientWithLogging('1.2.3.4:5678') 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker.. tip:: 130*61c4878aSAndroid Build Coastguard Worker The ``SocketClient`` takes an optional callback called when a disconnect is 131*61c4878aSAndroid Build Coastguard Worker detected. The ``pw_system`` console provides an example reconnect routine. 132*61c4878aSAndroid Build Coastguard Worker 133*61c4878aSAndroid Build Coastguard WorkerWith the above examples each ``serial_device.read`` and ``write`` call will 134*61c4878aSAndroid Build Coastguard Workercreate a log message to the ``pw_console.serial_debug_logger`` Python 135*61c4878aSAndroid Build Coastguard Workerlogger. This logger can then be included as a log window pane in the 136*61c4878aSAndroid Build Coastguard Worker``PwConsoleEmbed()`` call. 137*61c4878aSAndroid Build Coastguard Worker 138*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard Worker import logging 141*61c4878aSAndroid Build Coastguard Worker from pw_console import PwConsoleEmbed 142*61c4878aSAndroid Build Coastguard Worker 143*61c4878aSAndroid Build Coastguard Worker console = PwConsoleEmbed( 144*61c4878aSAndroid Build Coastguard Worker global_vars=globals(), 145*61c4878aSAndroid Build Coastguard Worker local_vars=locals(), 146*61c4878aSAndroid Build Coastguard Worker loggers={ 147*61c4878aSAndroid Build Coastguard Worker 'Host Logs': [ 148*61c4878aSAndroid Build Coastguard Worker # Root Python logger 149*61c4878aSAndroid Build Coastguard Worker logging.getLogger(''), 150*61c4878aSAndroid Build Coastguard Worker # Your current Python package logger. 151*61c4878aSAndroid Build Coastguard Worker logging.getLogger(__package__) 152*61c4878aSAndroid Build Coastguard Worker ], 153*61c4878aSAndroid Build Coastguard Worker 'Device Logs': [ 154*61c4878aSAndroid Build Coastguard Worker logging.getLogger('usb_gadget') 155*61c4878aSAndroid Build Coastguard Worker ], 156*61c4878aSAndroid Build Coastguard Worker 'Serial Debug': [ 157*61c4878aSAndroid Build Coastguard Worker # New log window to display serial read and writes 158*61c4878aSAndroid Build Coastguard Worker logging.getLogger('pw_console.serial_debug_logger') 159*61c4878aSAndroid Build Coastguard Worker ], 160*61c4878aSAndroid Build Coastguard Worker }, 161*61c4878aSAndroid Build Coastguard Worker app_title='CoolConsole', 162*61c4878aSAndroid Build Coastguard Worker ) 163*61c4878aSAndroid Build Coastguard Worker # Then run the console with: 164*61c4878aSAndroid Build Coastguard Worker console.embed() 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker.. figure:: images/serial_debug.svg 167*61c4878aSAndroid Build Coastguard Worker :alt: Serial debug pw_console screenshot. 168*61c4878aSAndroid Build Coastguard Worker 169*61c4878aSAndroid Build Coastguard Worker Screenshot of issuing an Echo RPC with serial debug logging. 170*61c4878aSAndroid Build Coastguard Worker 171*61c4878aSAndroid Build Coastguard Worker 172*61c4878aSAndroid Build Coastguard Worker.. _Python's logging documentation: https://docs.python.org/3/library/logging.html#logging.Logger.debug 173*61c4878aSAndroid Build Coastguard Worker 174*61c4878aSAndroid Build Coastguard Worker.. _module-pw_console-embedding-ipython: 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard Worker------------------------------ 177*61c4878aSAndroid Build Coastguard WorkerEmbeddeding other interpreters 178*61c4878aSAndroid Build Coastguard Worker------------------------------ 179*61c4878aSAndroid Build Coastguard WorkerThe Pigweed console is optimized for use with Pigweed, but other embedded Python 180*61c4878aSAndroid Build Coastguard Workerinterpreters may be used to interact with Pigweed devices. Popular options 181*61c4878aSAndroid Build Coastguard Workerinclude `IPython <https://ipython.org/>`_ and `bpython 182*61c4878aSAndroid Build Coastguard Worker<https://bpython-interpreter.org/>`_. 183*61c4878aSAndroid Build Coastguard Worker 184*61c4878aSAndroid Build Coastguard WorkerEmbedding IPython is similar to embedding ``pw_console``. After ``import 185*61c4878aSAndroid Build Coastguard WorkerIPython``, call ``IPython.start_ipython()`` with the set of variables to expose 186*61c4878aSAndroid Build Coastguard Workerin the console. See `Embedding IPython 187*61c4878aSAndroid Build Coastguard Worker<https://ipython.readthedocs.io/en/stable/interactive/reference.html#embedding>`_ 188*61c4878aSAndroid Build Coastguard Workerfor details. 189*61c4878aSAndroid Build Coastguard Worker 190*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 191*61c4878aSAndroid Build Coastguard Worker 192*61c4878aSAndroid Build Coastguard Worker IPython.start_ipython( 193*61c4878aSAndroid Build Coastguard Worker argv=[], 194*61c4878aSAndroid Build Coastguard Worker display_banner=False, 195*61c4878aSAndroid Build Coastguard Worker user_ns=local_variables, 196*61c4878aSAndroid Build Coastguard Worker ) 197*61c4878aSAndroid Build Coastguard Worker return 198