Skip to content

Commit

Permalink
Start work on documenting the CLI (#18)
Browse files Browse the repository at this point in the history
* Start work on documenting the CLI

* Rework device commands

* Finish CLI docs
  • Loading branch information
jamesmunns authored Jan 21, 2025
1 parent 93bb766 commit 7174c0d
Show file tree
Hide file tree
Showing 9 changed files with 695 additions and 373 deletions.
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
- [Using Simulated Devices](./tutorial/100-simulator.md)
- [Starting Simulated Devices](./tutorial/101-start.md)
- [The Poststation User Interface](./tutorial/102-tui.md)
- [The `poststation-cli` tool](./tutorial/103-cli.md)
- [Using an RP2040](./tutorial/200-rp2040.md)
Binary file modified book/src/tutorial/102-endpoints.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified book/src/tutorial/102-topics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion book/src/tutorial/102-tui.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The Endpoints page is broken into two parts, the **Types** section, and the

#### The "Endpoints (by path)" section

The current page shows that the simulator device supports five endpoints.
The current page shows that the simulator device supports six endpoints.

The first endpoint, `postcard-rpc/ping` is an endpoint built in to all
postcard-rpc devices. This endpoint takes a `u32`, or 32-bit unsigned
Expand Down Expand Up @@ -104,6 +104,10 @@ that has an attached color LED. We can see that this endpoint does not
return any data, though we will still get an "empty" response from the
device as a confirmation.

The sixth endpoint, `simulator/status_led/get`, takes no data, but returns
the currently set value. In the simulator, this starts with all zero values,
and will retain the last value set by the `simulator/status_led/set` endpoint.

We can see some more information about the types mentioned in these endpoints
in the section above.

Expand Down
212 changes: 212 additions & 0 deletions book/src/tutorial/103-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# The poststation-cli tool

For this next section, we'll use the Command Line Interface tool,
`poststation-cli`. Make sure that:

1. You've [installed](../installation-utils.md) the CLI tool
2. Your poststation server **is still running** with a simulator device

In a new window, we can verify that we can connect to the server by running
the "list devices" command:

```sh
$ poststation-cli ls

# Devices

| serial | name | interface | connected |
| :--------------- | ---------: | :-------- | :-------- |
| 563BF78B6A56DF04 | QUIRKY-344 | usb | yes |

```

This prints out a table of the devices currently known by `poststation`.

We can see the same simulator device from the previous chapter, and it is also
showing as currently connected.

## Top level commands

You can print help with `poststation-cli --help`:

```sh
$ poststation-cli --help
A CLI tool for poststation

Usage: poststation-cli [OPTIONS] <COMMAND>

Commands:
ls List devices
folder Show paths for configuration, database storage, and the CA certificate for external usage
device Interact with a specific device
help Print this message or the help of the given subcommand(s)

Options:
-s, --server <SERVER_ADDR> A path to the server. Defaults to `127.0.0.1:51837`
--insecure When set, a plaintext connection will be made with the server
--timings Print timing information
-h, --help Print help
-V, --version Print version
```

We've seen the output of `ls` already, we'll now focus on the `device` command, which
is the primary way of interacting with connected devices.

## The `device` command

We can see all of the `device` subcommands with `--help`:

```sh
$ poststation-cli device --help
Interact with a specific device

Usage: poststation-cli device [SERIAL] <COMMAND>

Commands:
types View all types used for communicating with a given device
endpoints View all endpoints available for communicating with a given device
topics-out View all topics published by a given device
topics-in View all topics handled by a given device
logs View the most recent logs from a given device
logs-range View the selected range of logs from a given device
proxy Proxy message to device endpoint
publish Publish a topic message to a device
listen Listen to a given "topic-out" path from a device
help Print this message or the help of the given subcommand(s)

Arguments:
[SERIAL] Device Serial Number or Name. Can be set via POSTSTATION_SERIAL env var

Options:
-h, --help Print help
```

Here we can fully interact with our device:

* `types` will print the types known to the device on all endpoints/topics
* `endpoints` will print information about the device's endpoints
* `topics-out` will print all topics sent TO the client FROM the server
* `topics-in` will print all topics sent TO the server FROM the client
* `logs` will print the most recent logs, and `logs-range` can be used to print
a specific range of logs
* `proxy` is used to send an endpoint request and get the response from the device
* `publish` is used to send a `topics-in` message to the device
* `listen` is used to receive `topics-out` messages from the device

### Common patterns

These device commands each take a common "kinds" of arguments.

#### Serial Number

We will need to specify what device we want to interact with. We can use the
full serial number of our device, in hex format:

```sh
$ poststation-cli device 563BF78B6A56DF04 endpoints

Endpoints offered by device 563BF78B6A56DF04

* 'postcard-rpc/ping' => async fn(u32) -> u32
* 'postcard-rpc/schemas/get' => async fn(()) -> SchemaTotals
* 'poststation/unique_id/get' => async fn(()) -> u64
* 'simulator/picoboot/reset' => async fn(())
* 'simulator/status_led/set' => async fn(Rgb8)
* 'simulator/status_led/get' => async fn(()) -> Rgb8
```

However for convenience, the CLI also supports "fuzzy" matching, on part of
the serial number, or on part of the short name.

For example, we can also use the last four digits of the serial number:

```sh
$ poststation-cli device DF04 types

Types used by device 563BF78B6A56DF04

* struct Key([u8; 8])
* struct Rgb8 { r: u8, g: u8, b: u8 }
* enum OwnedSchemaData { Type(Schema), Endpoint{ path: String, request_key: Key, response_key: Key}, Topic{ path: String, key: Key, direction: TopicDirection} }
* [u8; 8]
* struct Temperature { temp: f64 }
* enum TopicDirection { ToServer, ToClient }
* struct SchemaTotals { types_sent: u32, endpoints_sent: u32, topics_in_sent: u32, topics_out_sent: u32, errors: u32 }
```
Or we can use part of the short name, "QUIRKY-344":
```sh
$ poststation-cli device quirky topics-out

Topics offered by device 563BF78B6A56DF04

* 'postcard-rpc/schema/data' => Channel<OwnedSchemaData>
* 'postcard-rpc/logging' => Channel<String>
* 'simulator/temperature' => Channel<Temperature>
```
#### Path
When we need to specify the path, we can also use "fuzzy" matching. For example,
instead of using `simulator/status_led/get`, we can just say `led/get`:
```sh
$ poststation-cli device quirky proxy led/get '{}'
Response: '{"b":30,"g":20,"r":10}'
```
However if we aren't specific enough, then we will get an error instead:
```sh
$ poststation-cli device quirky proxy led
Given 'led', found:
* 'simulator/status_led/set' => async fn(Rgb8)
* 'simulator/status_led/get' => async fn(()) -> Rgb8
Error: Too many matches, be more specific!
```
#### Values
Since `postcard` is a binary format, the CLI will automatically translate all
messages to and from JSON, to make it possible to type on the command line.
As we saw above with `device quirky proxy led/get`, the CLI printed out:
```json
{"b":30,"g":20,"r":10}
```
If we want to send a command, we will also need to provide JSON. You may
want to use single quotes on your shell, to avoid needing to escape `"`
double quotes.
```sh
$ poststation-cli device quirky proxy led/set '{"r": 20, "g": 30, "b": 40}'
Response: 'null'
```
If an endpoint or topic-in takes `()` as a value, we can also omit the value
entirely. For example, these two commands do the same thing:
```sh
$ poststation-cli device quirky proxy led/get '{}'
Response: '{"b":30,"g":20,"r":10}'
$ poststation-cli device quirky proxy led/get
Response: '{"b":30,"g":20,"r":10}'
```
Don't forget that JSON requires keys to be strings! If you forget this, you'll
get an error when poststation trys to convert this:
```sh
$ poststation-cli device quirky proxy led/set '{r: 20, g: 30, b: 40}'
Error: 'Dynamic("provided JSON does not match the expected schema for this endpoint")'
```
## Next up
In the next section, we'll explore using the SDK crate, `poststation-sdk`.
61 changes: 61 additions & 0 deletions tools/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tools/poststation-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ license = "MIT OR Apache-2.0"
anyhow = "1.0.89"
clap = { version = "4.5.19", features = ["derive"] }
directories = "5.0.1"
rand = "0.8.5"
serde_json = "1.0.128"

[dependencies.postcard-rpc]
Expand Down
Loading

0 comments on commit 7174c0d

Please sign in to comment.