tassello 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +23 -2
- package/dist/server/server.js +4 -0
- package/dist/server/session.d.ts +2 -0
- package/dist/server/session.js +6 -0
- package/dist/server/system.d.ts +40 -0
- package/dist/server/system.js +606 -0
- package/dist/server/system_format.d.ts +51 -0
- package/dist/server/system_format.js +264 -0
- package/dist/shared/protocol.d.ts +17 -2
- package/dist/shared/system.d.ts +113 -0
- package/dist/shared/system.js +45 -0
- package/dist/types/client/connection.d.ts +2 -1
- package/dist/types/client/icons.d.ts +1 -0
- package/dist/types/client/sdk/index.d.ts +2 -1
- package/dist/types/shared/protocol.d.ts +17 -2
- package/dist/types/shared/system.d.ts +113 -0
- package/dist/www/assets/Joystick.js +1 -1
- package/dist/www/assets/RobotModelView.js +1 -1
- package/dist/www/assets/TerminalView.js +2 -2
- package/dist/www/assets/dialogs.js +1 -1
- package/dist/www/assets/icons.js +1 -1
- package/dist/www/assets/index.css +1 -1
- package/dist/www/assets/index.js +48 -47
- package/dist/www/assets/shared/tassello-sdk.js +1 -1
- package/docs/plugins.md +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ change the plugin API (`tassello/sdk`, `tassello/server`, `tassello/vite`), as n
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
- System Monitor widget: the robot's computer, every second. The CPU's load, of each core (those
|
|
9
|
+
offline too), their frequencies and the load average; the memory, its cache and the swap; the
|
|
10
|
+
temperatures of the thermal zones and hwmon chips, by chip with their hottest, against their
|
|
11
|
+
own limits; the fans; a Raspberry Pi's throttling (under-voltage, frequency capped, throttled,
|
|
12
|
+
soft temperature limit, now and since boot); the GPUs: a Jetson's (devfreq), NVIDIA's
|
|
13
|
+
(`nvidia-smi`), AMD's (amdgpu); the power rails: a Jetson's INA3221 (L4T 32's too), hwmon's
|
|
14
|
+
power sensors, Intel's RAPL when readable; the disks' traffic and busy time, and the file
|
|
15
|
+
systems' space; the networks' traffic, of the device's own interfaces or those chosen. Charts
|
|
16
|
+
of the last 5 minutes, kept by the server, with the values at the pointer (or the arrow keys).
|
|
17
|
+
The board, its OS, uptime, and a Jetson's L4T release and power mode.
|
|
18
|
+
- Plugins: `connection.subscribeSystem`, and the types of `src/shared/system.ts`.
|
|
8
19
|
- Rosbags widget: the robot's rosbags, as `ros2 bag` makes and reads them. A folder's bags, the
|
|
9
20
|
newest first, with their time span, size, storage and compression, and each topic's type,
|
|
10
21
|
count and rate, from their `metadata.yaml` (Humble's and Jazzy's), else from their files (a
|
package/README.md
CHANGED
|
@@ -13,8 +13,9 @@ and plugins add more.
|
|
|
13
13
|
images, command buttons, a systemd application manager, a behavior tree inspector and
|
|
14
14
|
editor, the ROS log of every node, the robot's diagnostics, its topics, services and actions
|
|
15
15
|
as the `ros2` command line shows them, its nodes' parameters, its rosbags (recorded, listed,
|
|
16
|
-
downloaded and played back), a file manager, a terminal,
|
|
17
|
-
joined, connections switched, the robot as an access point
|
|
16
|
+
downloaded and played back), a file manager, a terminal, its networks (Wi-Fi
|
|
17
|
+
joined, connections switched, the robot as an access point), and its computer: CPU, memory,
|
|
18
|
+
temperatures, a Raspberry Pi's throttling, a Jetson's GPU and power, disks and networks.
|
|
18
19
|
- **Plugins**: widgets of your own, with server-side code if they need it, as npm or ROS packages.
|
|
19
20
|
- **One process**: a ROS 2 node in Node.js. Nothing to install on the robot but Node.js.
|
|
20
21
|
|
|
@@ -136,6 +137,7 @@ after the others on the devices already arranged.
|
|
|
136
137
|
| **Rosbags** | The robot's rosbags, as `ros2 bag` makes and reads them: those of a folder, the newest first, with when, how long and how big, their storage and compression, each topic's type, count and rate (`ros2 bag info`); downloaded, deleted, or played on the robot's topics (`ros2 bag play`: paused, sought, sped up, looped, some topics only). New ones recorded (`ros2 bag record`): topics chosen from the graph, all of them, or matching an expression, with rosbag2's options: the storage (MCAP, SQLite) and its preset, a new file by size or duration, compression of each file or message. Every page sees the recordings and the playback, the behavior tree inspectors' too |
|
|
137
138
|
| **File Manager** | The robot's files: folders unfolded in place, places (home, the ROS workspaces, bookmarks) and the disks' free space, an entry's details and permissions, what takes a folder's space. Make, rename, cut, copy, paste, drag onto folders, delete, download (folders as `.tar.gz`) and upload (drop files and folders onto it). Text files edited in tabs as gedit does: highlighting, search and replace, undo; images and PGM maps shown |
|
|
138
139
|
| **Terminal** | A shell on the robot, or a command (`htop`, `tmux attach`), in a full terminal: colours, full screen programs, the mouse. It outlives the page: reloaded, reconnected or shown again, it is as it was. On touch screens, the keys phones lack, as Termux has them: Esc, Tab, Ctrl, Alt, Home, End, the arrows, Page Up and Down, and while typing the terminal fills the screen above the on-screen keyboard |
|
|
140
|
+
| **System Monitor** | The robot's computer, as top, sensors and a Jetson's jtop show it: the CPU's load, of each core, and their frequencies; the memory and swap; the temperatures by chip, and the fans; a Raspberry Pi's throttling (under-voltage, capped frequency, now and since boot); the GPUs (a Jetson's, NVIDIA's, AMD's) and the power rails (a Jetson's); the disks' traffic and space; the networks' traffic. With charts of the last 5 minutes |
|
|
139
141
|
| **Networking** | The robot's networks, through NetworkManager, as a phone's settings show them: the Wi-Fi networks in range, joined with their password; the connections saved, switched between, edited (their addresses by DHCP or static), forgotten; the robot as an access point, its network shared by a QR code; the interfaces, their state and addresses. Asks before a change that would cut the page off from the robot |
|
|
140
142
|
|
|
141
143
|
Their properties (topics, frames, speeds, colours, ...) are edited in the side panel of edit mode.
|
|
@@ -466,6 +468,21 @@ Notes on some of them:
|
|
|
466
468
|
Without it, the widget says the networks cannot be changed. *Share…* reads the passwords with
|
|
467
469
|
`nmcli --show-secrets`, which needs the same right; those a desktop's keyring keeps cannot be
|
|
468
470
|
read.
|
|
471
|
+
- **System Monitor** reads `/proc` and `/sys` every second, for every page at once, while one
|
|
472
|
+
shows it, and keeps the last 5 minutes for the charts (a page opened later has them at once).
|
|
473
|
+
The temperatures are the kernel's thermal zones and its hwmon chips' sensors (the chips that
|
|
474
|
+
are a thermal zone again, once), grouped by chip with the hottest of each; a sensor is hot from
|
|
475
|
+
its own limits (else 80 °C), and critical at its own critical (else 95 °C). A **Raspberry Pi**'s
|
|
476
|
+
throttling is its firmware's (`get_throttled` in `/sys`, else `vcgencmd get_throttled`): under-
|
|
477
|
+
voltage, frequency capped, throttled, soft temperature limit, now and since boot. A **Jetson**'s
|
|
478
|
+
GPU is devfreq's (its load and clock), its power the INA3221's rails (`VDD_IN` the whole
|
|
479
|
+
board's), its L4T release and power mode (`nvpmodel -q`) are shown with the board. NVIDIA's
|
|
480
|
+
GPUs are read with `nvidia-smi` every 2 s, AMD's from amdgpu's files; an Intel CPU's package
|
|
481
|
+
power from RAPL, if its counters are readable (root's only, since Linux 5.10). Cores taken
|
|
482
|
+
offline (a Jetson's power modes) show as such. The disks are the whole ones (not partitions,
|
|
483
|
+
loop devices, device mapper or RAID), their space the File Manager's; the networks are the
|
|
484
|
+
device's own interfaces (not docker's bridges, VPN clients' tunnels: their traffic is the
|
|
485
|
+
devices' too), or those of its *interfaces* (`wlan0, tun*`). Each section can be hidden.
|
|
469
486
|
|
|
470
487
|
## Plugins
|
|
471
488
|
|
|
@@ -517,6 +534,7 @@ own pages only too: those whose origin is the host they reached (the `Host` head
|
|
|
517
534
|
├─ python3: the terminals' pseudo-terminals
|
|
518
535
|
├─ nmcli: the networks (NetworkManager)
|
|
519
536
|
├─ ros2 bag: rosbags recorded and played
|
|
537
|
+
├─ /proc, /sys, nvidia-smi: the system monitor
|
|
520
538
|
└─ the plugins' server sides
|
|
521
539
|
```
|
|
522
540
|
|
|
@@ -554,6 +572,9 @@ Safety and bandwidth are the server's concern:
|
|
|
554
572
|
one recording per folder, for every page (the behavior tree inspectors' among them), one
|
|
555
573
|
playback. A folder of bags is read once for every page showing it, every 2 s, a bag's metadata
|
|
556
574
|
again only when its files change; the recordings' sizes every second.
|
|
575
|
+
- The system monitor's sensors are read once for every page, every second while one watches and
|
|
576
|
+
for 30 s after the last leaves; they are looked for again every 30 s (USB ones come and go).
|
|
577
|
+
Each page gets a sample a second, about 4 KB.
|
|
557
578
|
- The File Manager's folders are read again every 3 s, and answered "unchanged" while they are;
|
|
558
579
|
the largest are listed in part (5,000 entries), and only the rows in sight are drawn. Uploads
|
|
559
580
|
and downloads are streamed, folders archived by `tar` as they are sent; saves replace files at
|
package/dist/server/server.js
CHANGED
|
@@ -33,6 +33,7 @@ import { Rosbags } from './rosbags.js';
|
|
|
33
33
|
import { Rosout } from './rosout.js';
|
|
34
34
|
import { Session } from './session.js';
|
|
35
35
|
import { FrameStreams } from './streams.js';
|
|
36
|
+
import { SystemMonitor } from './system.js';
|
|
36
37
|
import { SystemdServices } from './systemd.js';
|
|
37
38
|
import { Teleop } from './teleop.js';
|
|
38
39
|
import { Terminals } from './terminals.js';
|
|
@@ -112,6 +113,7 @@ export async function startServer(options) {
|
|
|
112
113
|
const diagnostics = new Diagnostics(node, logger);
|
|
113
114
|
const terminals = new Terminals(logger);
|
|
114
115
|
const networking = new Networking(logger);
|
|
116
|
+
const system = new SystemMonitor(logger);
|
|
115
117
|
// Next to the panels
|
|
116
118
|
const uploadsDir = path.join(path.dirname(panelsDir), 'images');
|
|
117
119
|
const rosbags = new Rosbags(ros, logger);
|
|
@@ -171,6 +173,7 @@ export async function startServer(options) {
|
|
|
171
173
|
actions,
|
|
172
174
|
parameters,
|
|
173
175
|
rosbags,
|
|
176
|
+
system,
|
|
174
177
|
plugins: host,
|
|
175
178
|
hostname: os.hostname(),
|
|
176
179
|
}, ownPage(req.headers), req.socket.localAddress ?? null);
|
|
@@ -207,6 +210,7 @@ export async function startServer(options) {
|
|
|
207
210
|
systemd.stopAll();
|
|
208
211
|
terminals.stopAll();
|
|
209
212
|
networking.stopAll();
|
|
213
|
+
system.stop();
|
|
210
214
|
// Stops the robot if a page was driving it, while the node still runs
|
|
211
215
|
for (const session of sessions) {
|
|
212
216
|
session.close();
|
package/dist/server/session.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { Rosbags } from './rosbags.ts';
|
|
|
20
20
|
import type { RosGraph } from './ros_graph.ts';
|
|
21
21
|
import type { Rosout } from './rosout.ts';
|
|
22
22
|
import type { FrameStreams } from './streams.ts';
|
|
23
|
+
import type { SystemMonitor } from './system.ts';
|
|
23
24
|
import type { SystemdServices } from './systemd.ts';
|
|
24
25
|
import type { Teleop } from './teleop.ts';
|
|
25
26
|
import type { Terminals } from './terminals.ts';
|
|
@@ -52,6 +53,7 @@ export interface SessionServices {
|
|
|
52
53
|
actions: Actions;
|
|
53
54
|
parameters: Parameters;
|
|
54
55
|
rosbags: Rosbags;
|
|
56
|
+
system: SystemMonitor;
|
|
55
57
|
plugins: PluginHost;
|
|
56
58
|
hostname: string;
|
|
57
59
|
}
|
package/dist/server/session.js
CHANGED
|
@@ -468,6 +468,12 @@ export class Session {
|
|
|
468
468
|
case 'bags.action':
|
|
469
469
|
this.answer(message.id, Promise.resolve().then(() => services.rosbags.act(checkBagsRequest(message.request), this.ownPage)));
|
|
470
470
|
return;
|
|
471
|
+
case 'system.subscribe': {
|
|
472
|
+
const id = subscriptionId(message.id);
|
|
473
|
+
this.unsubscribe(id);
|
|
474
|
+
this.subscriptions.set(id, services.system.watch((update) => this.send({ type: 'system', id, ...update })));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
471
477
|
case 'action.subscribe': {
|
|
472
478
|
const id = subscriptionId(message.id);
|
|
473
479
|
this.unsubscribe(id);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SystemUpdate } from '../shared/protocol.ts';
|
|
2
|
+
import { type Logger } from './util.ts';
|
|
3
|
+
export type SystemUpdateBody = Omit<SystemUpdate, 'type' | 'id'>;
|
|
4
|
+
type Listener = (update: SystemUpdateBody) => void;
|
|
5
|
+
export declare class SystemMonitor {
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private readonly listeners;
|
|
8
|
+
private readonly history;
|
|
9
|
+
private info;
|
|
10
|
+
private infoJson;
|
|
11
|
+
private infoAt;
|
|
12
|
+
private space;
|
|
13
|
+
private spaceJson;
|
|
14
|
+
private spaceAt;
|
|
15
|
+
private sensors;
|
|
16
|
+
private sensorsAt;
|
|
17
|
+
private previous;
|
|
18
|
+
private latest;
|
|
19
|
+
private nvidia;
|
|
20
|
+
private vcgencmd;
|
|
21
|
+
private underVoltageSeen;
|
|
22
|
+
private timer;
|
|
23
|
+
private linger;
|
|
24
|
+
private running;
|
|
25
|
+
private ticking;
|
|
26
|
+
constructor(logger: Logger);
|
|
27
|
+
watch(listener: Listener): () => void;
|
|
28
|
+
stop(): void;
|
|
29
|
+
private send;
|
|
30
|
+
private tick;
|
|
31
|
+
private refresh;
|
|
32
|
+
private sample;
|
|
33
|
+
private temperatures;
|
|
34
|
+
private fans;
|
|
35
|
+
private frequencies;
|
|
36
|
+
private power;
|
|
37
|
+
private gpus;
|
|
38
|
+
private throttled;
|
|
39
|
+
}
|
|
40
|
+
export {};
|