blob: 2b953f3fe34dab6fee704c9f841ee4b59e69e2bc [file] [log] [blame]
Niko Sohmerse92516c2024-03-23 18:40:30 -07001import {ByteBuffer} from 'flatbuffers'
2import {Connection} from '../../aos/network/www/proxy'
3import {Status, ApplicationStatus, State, LastStopReason, FileState} from '../../aos/starter/starter_generated'
4
5const NODES = ['/orin1', '/imu', '/roborio'];
6
7export class StarterHandler {
8 private statuses = new Map<string, ApplicationStatus[]>();
9
10 private statusList: HTMLElement =
11 (document.getElementById('status_list') as HTMLElement);
12
13 constructor(private readonly connection: Connection) {
14 for (const node in NODES) {
15 this.connection.addConfigHandler(() => {
16 this.connection.addHandler(
17 NODES[node] + '/aos', 'aos.starter.Status', (data) => {
18 this.handleStatus(data, NODES[node]);
19 });
20 });
21 }
22 }
23
24 private handleStatus(data: Uint8Array, node: string): void {
25 const fbBuffer = new ByteBuffer(data);
26 const status: Status = Status.getRootAsStatus(fbBuffer);
27
28 const temp: ApplicationStatus[] = new Array(status.statusesLength());
29
30 for (let i = 0; i < status.statusesLength(); i++) {
31 temp[i] = status.statuses(i);
32 }
33
34 this.statuses.set(node, temp);
35 }
36
37 setStateColor(div: HTMLElement): void {
38 div.className = '';
39 switch (div.innerHTML) {
40 case 'WAITING':
41 div.classList.add('yellow');
42 break;
43 case 'STARTING':
44 div.classList.add('yellowgreen');
45 break;
46 case 'RUNNING':
47 div.classList.add('lightgreen');
48 break;
49 case 'STOPPING':
50 div.classList.add('lightcoral');
51 break;
52 case 'STOPPED':
53 div.classList.add('lightcoral');
54 break;
55 }
56 }
57
58 setFileStateColor(div: HTMLElement): void {
59 div.className = '';
60 switch (div.innerHTML) {
61 case 'NOT_RUNNING':
62 div.classList.add('lightgreen');
63 break;
64 case 'NO_CHANGE':
65 div.classList.add('lightgreen');
66 break;
67 case 'CHANGED_DURING_STARTUP':
68 div.classList.add('lightcoral');
69 break;
70 case 'CHANGED':
71 div.classList.add('lightcoral');
72 break;
73 }
74 }
75
76 private populateStatusList() : void {
77 this.clearStatusList();
78
79 const ELEMENTS: string[] = [
80 'name',
81 'node',
82 'state',
83 'last_exit_code',
84 'pid',
85 // 'id',
86 'last_start_time',
87 'last_stop_reason',
88 // 'process_info',
89 // 'has_active_timing_report',
90 'file_state'
91 ];
92
93 // This is to add the field names as the top row
94 //---------------------------------------------------
95 const row = document.createElement('div');
96 row.className = "column_names";
97
98 for (const e in ELEMENTS) {
99 const element = document.createElement('div');
100 element.className = ELEMENTS[e];
101 element.innerHTML = ELEMENTS[e].toUpperCase();
102 element.style.fontWeight = 'bold';
103 row.appendChild(element);
104 }
105
106 this.statusList.appendChild(row);
107 //---------------------------------------------------
108
109 for (const node in NODES) {
110 const currentStatus = this.statuses.get(NODES[node]);
111
112 if (currentStatus) {
113 currentStatus.forEach(status => {
114 const row = document.createElement('div');
115 row.className = status.name();
116
117 for (const e in ELEMENTS) {
118 const element = document.createElement('div');
119 element.className = ELEMENTS[e];
120
121 switch (element.className) {
122 case 'name':
123 element.innerHTML = status.name();
124 break;
125 case 'node':
126 element.innerHTML = NODES[node];
127 break;
128 case 'state':
129 element.innerHTML = State[status.state()];
130 this.setStateColor(element);
131 break;
132 case 'last_exit_code':
133 element.innerHTML = status.lastExitCode().toString();
134 break;
135 case 'pid':
136 element.innerHTML = status.pid().toString();
137 break;
138 case 'last_start_time':
139 element.innerHTML = Number(status.lastStartTime() / 1000000000n).toString() + ' sec';
140 break;
141 case 'last_stop_reason':
142 element.innerHTML = LastStopReason[status.lastStopReason()];
143 break;
144 case 'file_state':
145 element.innerHTML = FileState[status.fileState()];
146 this.setFileStateColor(element);
147 break;
148 default:
149 element.innerHTML = "NA";
150 break;
151 }
152 row.appendChild(element);
153 }
154
155 this.statusList.appendChild(row);
156 })
157 }
158 }
159 }
160
161 private clearStatusList(): void {
162 if (!this.statusList) {
163 return;
164 }
165
166 while (this.statusList.firstChild) {
167 this.statusList.removeChild(this.statusList.firstChild);
168 }
169 }
170
171 draw(): void {
172 if (this.statuses) {
173 this.populateStatusList();
174 }
175
176 window.requestAnimationFrame(() => this.draw());
177 }
178}