Skip to content

Commit 7174c0d

Browse files
authored
Start work on documenting the CLI (#18)
* Start work on documenting the CLI * Rework device commands * Finish CLI docs
1 parent 93bb766 commit 7174c0d

File tree

9 files changed

+695
-373
lines changed

9 files changed

+695
-373
lines changed

book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
- [Using Simulated Devices](./tutorial/100-simulator.md)
1111
- [Starting Simulated Devices](./tutorial/101-start.md)
1212
- [The Poststation User Interface](./tutorial/102-tui.md)
13+
- [The `poststation-cli` tool](./tutorial/103-cli.md)
1314
- [Using an RP2040](./tutorial/200-rp2040.md)

book/src/tutorial/102-endpoints.png

5.91 KB
Loading

book/src/tutorial/102-topics.png

-41.3 KB
Loading

book/src/tutorial/102-tui.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ The Endpoints page is broken into two parts, the **Types** section, and the
7474

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

77-
The current page shows that the simulator device supports five endpoints.
77+
The current page shows that the simulator device supports six endpoints.
7878

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

107+
The sixth endpoint, `simulator/status_led/get`, takes no data, but returns
108+
the currently set value. In the simulator, this starts with all zero values,
109+
and will retain the last value set by the `simulator/status_led/set` endpoint.
110+
107111
We can see some more information about the types mentioned in these endpoints
108112
in the section above.
109113

book/src/tutorial/103-cli.md

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# The poststation-cli tool
2+
3+
For this next section, we'll use the Command Line Interface tool,
4+
`poststation-cli`. Make sure that:
5+
6+
1. You've [installed](../installation-utils.md) the CLI tool
7+
2. Your poststation server **is still running** with a simulator device
8+
9+
In a new window, we can verify that we can connect to the server by running
10+
the "list devices" command:
11+
12+
```sh
13+
$ poststation-cli ls
14+
15+
# Devices
16+
17+
| serial | name | interface | connected |
18+
| :--------------- | ---------: | :-------- | :-------- |
19+
| 563BF78B6A56DF04 | QUIRKY-344 | usb | yes |
20+
21+
```
22+
23+
This prints out a table of the devices currently known by `poststation`.
24+
25+
We can see the same simulator device from the previous chapter, and it is also
26+
showing as currently connected.
27+
28+
## Top level commands
29+
30+
You can print help with `poststation-cli --help`:
31+
32+
```sh
33+
$ poststation-cli --help
34+
A CLI tool for poststation
35+
36+
Usage: poststation-cli [OPTIONS] <COMMAND>
37+
38+
Commands:
39+
ls List devices
40+
folder Show paths for configuration, database storage, and the CA certificate for external usage
41+
device Interact with a specific device
42+
help Print this message or the help of the given subcommand(s)
43+
44+
Options:
45+
-s, --server <SERVER_ADDR> A path to the server. Defaults to `127.0.0.1:51837`
46+
--insecure When set, a plaintext connection will be made with the server
47+
--timings Print timing information
48+
-h, --help Print help
49+
-V, --version Print version
50+
```
51+
52+
We've seen the output of `ls` already, we'll now focus on the `device` command, which
53+
is the primary way of interacting with connected devices.
54+
55+
## The `device` command
56+
57+
We can see all of the `device` subcommands with `--help`:
58+
59+
```sh
60+
$ poststation-cli device --help
61+
Interact with a specific device
62+
63+
Usage: poststation-cli device [SERIAL] <COMMAND>
64+
65+
Commands:
66+
types View all types used for communicating with a given device
67+
endpoints View all endpoints available for communicating with a given device
68+
topics-out View all topics published by a given device
69+
topics-in View all topics handled by a given device
70+
logs View the most recent logs from a given device
71+
logs-range View the selected range of logs from a given device
72+
proxy Proxy message to device endpoint
73+
publish Publish a topic message to a device
74+
listen Listen to a given "topic-out" path from a device
75+
help Print this message or the help of the given subcommand(s)
76+
77+
Arguments:
78+
[SERIAL] Device Serial Number or Name. Can be set via POSTSTATION_SERIAL env var
79+
80+
Options:
81+
-h, --help Print help
82+
```
83+
84+
Here we can fully interact with our device:
85+
86+
* `types` will print the types known to the device on all endpoints/topics
87+
* `endpoints` will print information about the device's endpoints
88+
* `topics-out` will print all topics sent TO the client FROM the server
89+
* `topics-in` will print all topics sent TO the server FROM the client
90+
* `logs` will print the most recent logs, and `logs-range` can be used to print
91+
a specific range of logs
92+
* `proxy` is used to send an endpoint request and get the response from the device
93+
* `publish` is used to send a `topics-in` message to the device
94+
* `listen` is used to receive `topics-out` messages from the device
95+
96+
### Common patterns
97+
98+
These device commands each take a common "kinds" of arguments.
99+
100+
#### Serial Number
101+
102+
We will need to specify what device we want to interact with. We can use the
103+
full serial number of our device, in hex format:
104+
105+
```sh
106+
$ poststation-cli device 563BF78B6A56DF04 endpoints
107+
108+
Endpoints offered by device 563BF78B6A56DF04
109+
110+
* 'postcard-rpc/ping' => async fn(u32) -> u32
111+
* 'postcard-rpc/schemas/get' => async fn(()) -> SchemaTotals
112+
* 'poststation/unique_id/get' => async fn(()) -> u64
113+
* 'simulator/picoboot/reset' => async fn(())
114+
* 'simulator/status_led/set' => async fn(Rgb8)
115+
* 'simulator/status_led/get' => async fn(()) -> Rgb8
116+
```
117+
118+
However for convenience, the CLI also supports "fuzzy" matching, on part of
119+
the serial number, or on part of the short name.
120+
121+
For example, we can also use the last four digits of the serial number:
122+
123+
```sh
124+
$ poststation-cli device DF04 types
125+
126+
Types used by device 563BF78B6A56DF04
127+
128+
* struct Key([u8; 8])
129+
* struct Rgb8 { r: u8, g: u8, b: u8 }
130+
* enum OwnedSchemaData { Type(Schema), Endpoint{ path: String, request_key: Key, response_key: Key}, Topic{ path: String, key: Key, direction: TopicDirection} }
131+
* [u8; 8]
132+
* struct Temperature { temp: f64 }
133+
* enum TopicDirection { ToServer, ToClient }
134+
* struct SchemaTotals { types_sent: u32, endpoints_sent: u32, topics_in_sent: u32, topics_out_sent: u32, errors: u32 }
135+
```
136+
137+
Or we can use part of the short name, "QUIRKY-344":
138+
139+
```sh
140+
$ poststation-cli device quirky topics-out
141+
142+
Topics offered by device 563BF78B6A56DF04
143+
144+
* 'postcard-rpc/schema/data' => Channel<OwnedSchemaData>
145+
* 'postcard-rpc/logging' => Channel<String>
146+
* 'simulator/temperature' => Channel<Temperature>
147+
```
148+
149+
#### Path
150+
151+
When we need to specify the path, we can also use "fuzzy" matching. For example,
152+
instead of using `simulator/status_led/get`, we can just say `led/get`:
153+
154+
```sh
155+
$ poststation-cli device quirky proxy led/get '{}'
156+
Response: '{"b":30,"g":20,"r":10}'
157+
```
158+
159+
However if we aren't specific enough, then we will get an error instead:
160+
161+
```sh
162+
$ poststation-cli device quirky proxy led
163+
Given 'led', found:
164+
165+
* 'simulator/status_led/set' => async fn(Rgb8)
166+
* 'simulator/status_led/get' => async fn(()) -> Rgb8
167+
168+
Error: Too many matches, be more specific!
169+
```
170+
171+
#### Values
172+
173+
Since `postcard` is a binary format, the CLI will automatically translate all
174+
messages to and from JSON, to make it possible to type on the command line.
175+
176+
As we saw above with `device quirky proxy led/get`, the CLI printed out:
177+
178+
```json
179+
{"b":30,"g":20,"r":10}
180+
```
181+
182+
If we want to send a command, we will also need to provide JSON. You may
183+
want to use single quotes on your shell, to avoid needing to escape `"`
184+
double quotes.
185+
186+
```sh
187+
$ poststation-cli device quirky proxy led/set '{"r": 20, "g": 30, "b": 40}'
188+
Response: 'null'
189+
```
190+
191+
If an endpoint or topic-in takes `()` as a value, we can also omit the value
192+
entirely. For example, these two commands do the same thing:
193+
194+
```sh
195+
$ poststation-cli device quirky proxy led/get '{}'
196+
Response: '{"b":30,"g":20,"r":10}'
197+
198+
$ poststation-cli device quirky proxy led/get
199+
Response: '{"b":30,"g":20,"r":10}'
200+
```
201+
202+
Don't forget that JSON requires keys to be strings! If you forget this, you'll
203+
get an error when poststation trys to convert this:
204+
205+
```sh
206+
$ poststation-cli device quirky proxy led/set '{r: 20, g: 30, b: 40}'
207+
Error: 'Dynamic("provided JSON does not match the expected schema for this endpoint")'
208+
```
209+
210+
## Next up
211+
212+
In the next section, we'll explore using the SDK crate, `poststation-sdk`.

tools/Cargo.lock

+61
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/poststation-cli/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ license = "MIT OR Apache-2.0"
1212
anyhow = "1.0.89"
1313
clap = { version = "4.5.19", features = ["derive"] }
1414
directories = "5.0.1"
15+
rand = "0.8.5"
1516
serde_json = "1.0.128"
1617

1718
[dependencies.postcard-rpc]

0 commit comments

Comments
 (0)