Package: serialhub
serialhub<<==-- Try it NOW,conveniently pre-installedin a JupyterLab on mybinder.org(Serial communication requires a browser with Web Serial API such as Chrome/Edge, see below)This is a custom IPython/Jupyter widget for use in JupyterLab.  It allowsserial communicationfrom python code running in a notebook, even when hosted in the cloud (via JupyterHub, for example).  Anend userserial device is accessed indirectly via a web browser's implementation of theWeb Serial API(MUST be present to be useful).  As of 2021, theWeb Serial Specispresent ONLY in recent Google Chrome & Microsoft Edgebrowsers.  Consider checkingthis browser support matrixin case of future implementation in other browsers.Project Goals and high-level descriptionWARNING: This Widget extension isstill in early developmentand taking shape.Any component, class, method, etc. may be renamed or re-designed, as these early versions progress.  Versions in the 0.0.xx series may be partially non-functional at times, as the code matures from infancy!  Hoping to reach 0.1.xx maturity soon, feel free to help via feedback, issues, complaints, etc. :)Enable python code running in a python3 kernel of a Jupyter notebook to connect, read & write data, etc. with a serial device presenton the end users' computers.  This "backend" python code/ipykernel may, therefore, be hosted via cloud/server in an online JupyterHub, etc.  The backend code initiates display of the "SerialHubPort" custom IPython Widget in a notebook cell, with which the user then initiates the serial connection.  The backend can optionally set a filter based on USB Vendor and Product codes, to narrow the list of serial ports presented to the user.  It can also specifiy serial port options (such as baudRate, parity, etc.)beforethe port is opened by the user.The frontend JavaScript portion of the widget detects if the Web Serial API is supported in the user's browser, and presents a BUTTON used to initiate the opening of a serial port.  Note that the Web Serial API requires the initial "request" for a serial port to beinitiated by explicit user action, such as a click.  This was a key motivation for implementing serialhub as avisible"DOM widget" to be used in a notebook cell.  The widget also presents diagnostic data/statistics on read & written data.  Inbound serial data read by the frontend is relayed to the backend code (which can report it via a callback function).  Data written by the backend is relayed to the frontend as custom widget messages, and then written to the browser's serial port connection and ultimately the end user's serial device.  The frontend treats all data as strictly "binary", so that the backend (python code) is fully responsible for text encodings of the streams (ascii, UTF-8, etc), as would be the case with direct serial device communication.A helper serialhub.SerialIO class may be used to translate the callback-based widget communications into a readable & writable (but not seekable) io.RawIOBase binary stream.  This is intended to help existing code to use a more familiar interface, if desired, at the cost of buffering recv/reads from the client (which the SerialIO class implements).  This class implementsa fewhelper methods to mimick a small subset of "pyserial" style access, though it only strictly implements the io.RawIOBase interface.The inspiration for this project was a to allow educational projects using physical serail devices to be hosted in a cloud environment.  The specifics of that use case, talking to code running in an Arduino-style device while hosted in a shared JupyterHub server, have the most influence on the goals of this extension.  Nonetheless, attempts are/will be made to provide for other/generic use cases.InstallationWithin your JupyterLab environment, install the "labextension" via "pip":pipinstallserialhub(The above can be done within a running Terminal or Notebook, but should be followed by python kernel restart and browser refresh to load the newly added extension)The "serialhub" widget should then show up with "OK" status in the list of current JupyterLab extensions:jupyterlabextensionlistThe widget aims to remain useable in "Classic notebook" environments as well, though testing is focused on use within modern JupyterLab notebooks.  See "Caveats" below.CaveatsIf not present in your jupyterlab, you might need jupyterlab-manager?  (Perhaps when running a rather old JupyterLab version???)jupyterlabextensioninstall@jupyter-widgets/jupyterlab-managerIf you are using as a classic nbextension with Jupyter Notebook 5.2 or earlier,
you may also need to enable the nbextension:jupyternbextensionenable--py[--sys-prefix|--user|--system]serialhubNOTE:  There were some NPM versions of the widget in the past which are NOT to be used.Only use a "pip" style installof serialhub (or "conda" if the extension becomes available on conda-forge in the future)!  Thedepricatedserialhub "node packages" were never useful anyway, asNPM cannot install the required python backend portion of the plugin.Post-installationAfter installation (or upgrade) into arunningJupyter environment you will need torestart a running ipykernel and also refresh the webpagein your browser.  This latter manual step ensures that the JavaScript portion is loaded into your browser (happens at page load, not later).  This is the case, especially if you are an unprivileged end user of a running JupyterLab/JupyterHub in which the admin has NOT pre-installed the serialhub extension.  Manual refreshing is not necessary in the "Binder" environment (see the Binder badge at top of the project README), which has a pre-installeddevelopmentversion of the plugin already active before the JupyterLab itself loads up.Using "SerialHub"Please refer to the introduction.ipynb or firsttest.ipynb in the examples directory.  Using the extension involves constructing and rendering an instance of the serialhub.SerialHubPort() widget into a notebook cell.  The end-user must then perform a click on the "connect button" of the widget and select a serial port to open.  Once the user connects up the frontend, the backend can begin sending serial data and should be receiving the data as well (relayed via the frontend).A more formal description of the widget and helper classes will be developedafterit's features and implementation have stabilized to a mature status.