pw_web#
Pigweed AI summary: Pigweed provides an NPM package with modules to build web apps for Pigweed devices. The package includes a basic React app that demonstrates using the npm package. To install the package in a web application, you can use the command "npm install --save pigweedjs". After installing, you can import modules from pigweedjs in your code. If you don't want to set up a bundler, you can also load Pigweed directly in your HTML page by including the script tag with
Pigweed provides an NPM package with modules to build web apps for Pigweed devices.
Also included is a basic React app that demonstrates using the npm package.
Getting Started#
Pigweed AI summary: To get started with Pigweed, you can install it in your web application by using a bundler and running the command "npm install --save pigweedjs". After installation, you can import modules from Pigweed in your code. Alternatively, if you don't want to set up a bundler, you can directly load Pigweed in your HTML page by including the script tag "<script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script>". Another way
Installation#
Pigweed AI summary: To install pigweedjs in your web application, you can use a bundler and run the command "npm install --save pigweedjs". After installation, you can import modules from pigweedjs using the syntax "import { pw_rpc, pw_tokenizer, Device, WebSerial } from 'pigweedjs'". Alternatively, if you don't want to set up a bundler, you can directly load Pigweed in your HTML page by including the script tag "<script src="https://
If you have a bundler set up, you can install pigweedjs
in your web application by:
$ npm install --save pigweedjs
After installing, you can import modules from pigweedjs
in this way:
import { pw_rpc, pw_tokenizer, Device, WebSerial } from 'pigweedjs';
Import Directly in HTML#
Pigweed AI summary: You can import Pigweed directly in your HTML page by adding the following script tags to your code: <script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script> <script> const { pw_rpc, pw_hdlc, Device, WebSerial } = Pigweed; </script>
If you don’t want to set up a bundler, you can also load Pigweed directly in your HTML page by:
<script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script>
<script>
const { pw_rpc, pw_hdlc, Device, WebSerial } from Pigweed;
</script>
Getting Started#
Pigweed AI summary: The paragraph describes the process of getting started with Pigweed, a development platform. It suggests building and running the pw_system demo on a STM32F429I Discovery board. It also mentions the availability of a Device API that simplifies common tasks and provides an example of connecting to a device and calling an RPC service. The paragraph further explains the use of pw_log_rpc for logging and pw_tokenizer for tokenizing strings. It provides an example of streaming logs using the Device API and mentions the requirement
Easiest way to get started is to build pw_system demo and run it on a STM32F429I Discovery board. Discovery board is Pigweed’s primary target for development. Refer to target documentation for instructions on how to build the demo and try things out.
pigweedjs
provides a Device
API which simplifies common tasks. Here is
an example to connect to device and call EchoService.Echo
RPC service.
<h1>Hello Pigweed</h1>
<button onclick="connect()">Connect</button>
<button onclick="echo()">Echo RPC</button>
<br /><br />
<code></code>
<script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script>
<script src="https://unpkg.com/pigweedjs/dist/protos/collection.umd.js"></script>
<script>
const { Device } = Pigweed;
const { ProtoCollection } = PigweedProtoCollection;
const device = new Device(new ProtoCollection());
async function connect(){
await device.connect();
}
async function echo(){
const [status, response] = await device.rpcs.pw.rpc.EchoService.Echo("Hello");
document.querySelector('code').innerText = "Response: " + response;
}
</script>
pw_system demo uses pw_log_rpc
; an RPC-based logging solution. pw_system
also uses pw_tokenizer to tokenize strings and save device space. Below is an
example that streams logs using the Device
API.
<h1>Hello Pigweed</h1>
<button onclick="connect()">Connect</button>
<br /><br />
<code></code>
<script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script>
<script src="https://unpkg.com/pigweedjs/dist/protos/collection.umd.js"></script>
<script>
const { Device, pw_tokenizer } = Pigweed;
const { ProtoCollection } = PigweedProtoCollection;
const tokenDBCsv = `...` // Load token database here
const device = new Device(new ProtoCollection());
const detokenizer = new pw_tokenizer.Detokenizer(tokenDBCsv);
async function connect(){
await device.connect();
const call = device.rpcs.pw.log.Logs.Listen((msg) => {
msg.getEntriesList().forEach((entry) => {
const frame = entry.getMessage();
const detokenized = detokenizer.detokenizeUint8Array(frame);
document.querySelector('code').innerHTML += detokenized + "<br/>";
});
})
}
</script>
The above example requires a token database in CSV format. You can generate one
from the pw_system’s .elf
file by running:
$ pw_tokenizer/py/pw_tokenizer/database.py create \
--database db.csv out/stm32f429i_disc1_stm32cube.size_optimized/obj/pw_system/bin/system_example.elf
You can then load this CSV in JavaScript using fetch()
or by just copying
the contents into the tokenDBCsv
variable in the above example.
Modules#
Pigweed AI summary: The "Modules" section of the documentation explains the "Device" class, which is a helper API used to connect to a device over serial and call RPCs easily. To initialize the device, a "ProtoCollection" instance is needed, which can be generated from ".proto" files using "pw_proto_compiler". The "Device" class reads all the fields in the "Request" proto of each RPC method in the provided ProtoCollection and generates a JavaScript function that accepts those fields as arguments. These
Device#
Pigweed AI summary: The Device class is an API that helps connect to a device over serial and call RPCs easily. To initialize the device, a ProtoCollection instance is needed, which can be generated from a .proto file using pw_proto_compiler. The Device class reads all the fields in the Request proto of each RPC method in the ProtoCollection and generates a JavaScript function that accepts all the fields as arguments. These functions are then available under rpcs.* namespaced by their package name. The Device class has a public
Device class is a helper API to connect to a device over serial and call RPCs easily.
To initialize device, it needs a ProtoCollection
instance. pigweedjs
includes a default one which you can use to get started, you can also generate
one from your own .proto
files using pw_proto_compiler
.
Device
goes through all RPC methods in the provided ProtoCollection. For
each RPC, it reads all the fields in Request
proto and generates a
JavaScript function that accepts all the fields as it’s arguments. It then makes
this function available under rpcs.*
namespaced by its package name.
Device has following public API:
constructor(ProtoCollection, WebSerialTransport <optional>, rpcAddress <optional>)
connect()
- Shows browser’s WebSerial connection dialog and let’s user make device selectionrpcs.*
- Device API enumerates all RPC services and methods present in the provided proto collection and makes them available as callable functions underrpcs
. Example: If provided proto collection includes Pigweed’s Echo service ie.pw.rpc.EchoService.Echo
, it can be triggered by callingdevice.rpcs.pw.rpc.EchoService.Echo("some message")
. The functions return aPromise
that resolves an array with status and response.
WebSerialTransport#
Pigweed AI summary: The WebSerialTransport class is a helper class included in the WebSerial library. It allows for connecting to WebSerial and listening for serial data. The example usage provided demonstrates how to use the WebSerialTransport class to connect to a device, listen for HDLC frames, decode them, and print the decoded data to the console. Finally, it shows how to disconnect from the device.
To help with connecting to WebSerial and listening for serial data, a helper
class is also included under WebSerial.WebSerialTransport
. Here is an
example usage:
import { WebSerial, pw_hdlc } from 'pigweedjs';
const transport = new WebSerial.WebSerialTransport();
const decoder = new pw_hdlc.Decoder();
// Present device selection prompt to user
await transport.connect();
// Or connect to an existing `SerialPort`
// await transport.connectPort(port);
// Listen and decode HDLC frames
transport.chunks.subscribe((item) => {
const decoded = decoder.process(item);
for (const frame of decoded) {
if (frame.address === 1) {
const decodedLine = new TextDecoder().decode(frame.data);
console.log(decodedLine);
}
}
});
// Later, close all streams and close the port.
transport.disconnect();
Individual Modules#
Pigweed AI summary: This paragraph lists the Pigweed modules included in the NPM package, which are pw_hdlc, pw_rpc, pw_tokenizer, and pw_transfer. Each module is linked to its respective documentation page.
Following Pigweed modules are included in the NPM package:
Web Console#
Pigweed AI summary: Pigweed has a web console that showcases the use of pigweedjs in a React-based web app. The console includes a log viewer and a REPL with autocomplete. To run the console locally, navigate to the pw_web/webconsole directory, install npm, and run npm run dev.
Pigweed includes a web console that demonstrates pigweedjs usage in a React-based web app. Web console includes a log viewer and a REPL that supports autocomplete. Here’s how to run the web console locally:
$ cd pw_web/webconsole
$ npm install
$ npm run dev
Log viewer component#
Pigweed AI summary: The NPM package includes a log viewer component that can be embedded in any webapp. It works with Pigweed's RPC stack and supports defining your own log source. The component consists of the component itself and a log source. There are examples provided for using a mock log source and an RPC log source. To create a custom log source, you can extend the abstract LogSource class and emit logEntry events. After creating your custom log source object, you can pass it to the createLogViewer
The NPM package also includes a log viewer component that can be embedded in any webapp. The component works with Pigweed’s RPC stack out-of-the-box but also supports defining your own log source.
The component is composed of the component itself and a log source. Here is a simple example app that uses a mock log source:
<div id="log-viewer-container"></div>
<script src="https://unpkg.com/pigweedjs/dist/logging.umd.js"></script>
<script>
const { createLogViewer, MockLogSource } = PigweedLogging;
const logSource = new MockLogSource();
const containerEl = document.querySelector(
'#log-viewer-container'
);
let unsubscribe = createLogViewer(logSource, containerEl);
logSource.start(); // Start producing mock logs
</script>
The code above will render a working log viewer that just streams mock log entries.
It also comes with an RPC log source with support for detokenization. Here is an example app using that:
<div id="log-viewer-container"></div>
<script src="https://unpkg.com/pigweedjs/dist/index.umd.js"></script>
<script src="https://unpkg.com/pigweedjs/dist/protos/collection.umd.js"></script>
<script src="https://unpkg.com/pigweedjs/dist/logging.umd.js"></script>
<script>
const { Device, pw_tokenizer } = Pigweed;
const { ProtoCollection } = PigweedProtoCollection;
const { createLogViewer, PigweedRPCLogSource } = PigweedLogging;
const device = new Device(new ProtoCollection());
const logSource = new PigweedRPCLogSource(device, "CSV TOKEN DB HERE");
const containerEl = document.querySelector(
'#log-viewer-container'
);
let unsubscribe = createLogViewer(logSource, containerEl);
</script>
Custom Log Source#
Pigweed AI summary: You can create a custom log source by extending the LogSource class and emitting logEntry events. The example provided shows how to define a MockLogSource that emits logEntry events with severity, timestamp, and other fields. After creating your custom log source, you can pass it to the createLogViewer() function. The PigweedRPCLogSource implementation is provided as a reference.
You can define a custom log source that works with the log viewer component by just extending the abstract LogSource class and emitting the logEntry events like this:
import { LogSource, LogEntry, Severity } from 'pigweedjs/logging';
export class MockLogSource extends LogSource {
constructor(){
super();
// Do any initializations here
// ...
// Then emit logs
const log1: LogEntry = {
}
this.emitEvent('logEntry', {
severity: Severity.INFO,
timestamp: new Date(),
fields: [
{ key: 'severity', value: severity }
{ key: 'timestamp', value: new Date().toISOString() },
{ key: 'source', value: "LEFT SHOE" },
{ key: 'message', value: "Running mode activated." }
]
});
}
}
After this, you just need to pass your custom log source object to createLogViewer(). See implementation of PigweedRPCLogSource for reference.