1#![deny(rust_2018_compatibility, rust_2018_idioms, unsafe_code)]
12
13use base64::{prelude::*, DecodeError};
14use mint::Point2;
15use rgb::RGB8;
16use serde::{Deserialize, Serialize};
17use std::{num::NonZeroU16, path::PathBuf};
18
19#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
21pub enum Event {
22 Handshake {
23 version: i32,
24 extensions: Vec<String>,
25 },
26 ScreenDraw {
27 command: DrawCommand,
28 color: Color,
29 clip_region: Rect,
31 },
32 ScreenScroll {
33 location: ScrollLocation,
34 lines: i32,
35 background: Color,
36 clip_region: Rect,
38 },
39 ScreenClear {
40 color: Color,
41 clip_region: Rect,
43 },
44 ScreenDoubleBufferMode {
45 enable: bool,
46 },
47 ScreenRender,
48 VCodeSig(VCodeSig),
49 Ready,
50 Exited,
51 Serial(SerialData),
52 DeviceUpdate {
53 status: DeviceStatus,
54 port: Port,
55 },
56 Battery(Battery),
57 RobotPose {
58 x: f64,
59 y: f64,
60 },
61 RobotState(RobotState),
62 Log {
63 level: LogLevel,
64 message: String,
65 },
66 VEXLinkConnect {
67 port: SmartPort,
68 id: String,
69 mode: LinkMode,
70 r#override: bool,
71 },
72 VEXLinkDisconnect {
73 port: SmartPort,
74 },
75 TextMetricsRequest {
76 text: V5Text,
77 },
78}
79
80#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
82pub enum Command {
83 Handshake {
84 version: i32,
85 extensions: Vec<String>,
86 },
87 Touch {
88 pos: Point2<i32>,
89 event: TouchEvent,
90 },
91 ControllerUpdate(Option<ControllerUpdate>, Option<ControllerUpdate>),
92 USD {
93 root: Option<PathBuf>,
94 },
95 VEXLinkOpened {
96 port: SmartPort,
97 mode: LinkMode,
98 },
99 VEXLinkClosed {
100 port: SmartPort,
101 },
102 CompetitionMode(CompetitionMode),
103 ConfigureDevice {
104 port: Port,
105 device: Device,
106 },
107 AdiInput {
108 port: AdiPort,
109 voltage: f64,
110 },
111 StartExecution,
112 SetBatteryCapacity {
113 capacity: f64,
114 },
115 SetTextMetrics {
116 text: V5Text,
117 metrics: TextMetrics,
118 },
119 Serial(SerialData),
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
123pub struct SerialData {
124 pub channel: u32,
125 pub data: String,
126}
127
128impl SerialData {
129 pub fn new(channel: u32, bytes: &[u8]) -> Self {
130 Self {
131 channel,
132 data: BASE64_STANDARD.encode(bytes),
133 }
134 }
135
136 pub fn to_bytes(&self) -> Result<Vec<u8>, DecodeError> {
137 BASE64_STANDARD.decode(&self.data)
138 }
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
142pub struct CompetitionMode {
143 pub enabled: bool,
144 pub connected: bool,
145 pub mode: CompMode,
146 pub is_competition: bool,
147}
148
149impl Default for CompetitionMode {
150 fn default() -> Self {
151 Self {
152 enabled: true,
153 connected: false,
154 mode: CompMode::Driver,
155 is_competition: false,
156 }
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
162pub struct VCodeSig(pub String);
163
164impl VCodeSig {
165 pub fn new(bytes: &[u8]) -> Self {
166 Self(BASE64_STANDARD.encode(bytes))
167 }
168
169 pub fn to_bytes(&self) -> Result<Vec<u8>, DecodeError> {
170 BASE64_STANDARD.decode(&self.0)
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
176#[non_exhaustive]
177pub enum Device {
178 Motor {
179 physical_gearset: MotorGearset,
180 moment_of_inertia: f64,
181 },
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
186#[non_exhaustive]
187pub struct RobotState;
188
189#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
191pub enum DrawCommand {
192 Fill {
193 shape: Shape,
194 },
195 Stroke {
196 shape: Shape,
197 },
198 CopyBuffer {
199 top_left: Point2<i32>,
200 bottom_right: Point2<i32>,
201 stride: NonZeroU16,
202 buffer: String,
204 },
205 Write {
206 text: V5Text,
207 location: TextLocation,
208 opaque: bool,
209 background: Color,
210 },
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
214pub enum TextLocation {
215 Coordinates { point: Point2<i32> },
216 Line { line: i32 },
217}
218
219impl Default for TextLocation {
220 fn default() -> Self {
221 Self::Coordinates {
222 point: Point2 { x: 0, y: 0 },
223 }
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
228pub enum ScrollLocation {
229 Line {
230 line: i32,
231 },
232 Rectangle {
233 top_left: Point2<i32>,
234 bottom_right: Point2<i32>,
235 },
236}
237
238#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
239pub struct V5Text {
240 pub data: String,
241 pub font_family: V5FontFamily,
242 pub font_size: V5FontSize,
243}
244
245#[derive(
246 Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord,
247)]
248pub enum V5FontFamily {
249 #[default]
250 UserMono,
251 TimerMono,
252}
253
254#[derive(
255 Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord,
256)]
257pub enum V5FontSize {
258 Small,
259 #[default]
260 Normal,
261 Large,
262}
263
264#[derive(
265 Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord,
266)]
267pub struct TextMetrics {
268 pub width: usize,
269 pub height: usize,
270}
271
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
274pub enum Shape {
275 Rectangle {
276 top_left: Point2<i32>,
277 bottom_right: Point2<i32>,
278 },
279 Circle {
280 center: Point2<i32>,
281 radius: u16,
282 },
283 Pixel {
284 pos: Point2<i32>,
285 },
286 Line {
287 start: Point2<i32>,
288 end: Point2<i32>,
289 },
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
294#[non_exhaustive]
295pub enum DeviceStatus {
296 Motor {
297 velocity: f64,
298 reversed: bool,
299 power_draw: f64,
300 torque_output: f64,
301 flags: i32,
302 position: f64,
303 target_position: f64,
304 voltage: f64,
305 gearset: MotorGearset,
306 brake_mode: MotorBrakeMode,
307 },
308}
309
310#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
312pub enum MotorGearset {
313 Red,
314 Green,
315 Blue,
316}
317
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
320pub enum MotorBrakeMode {
321 Coast,
322 Brake,
323 Hold,
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
328pub enum LinkMode {
329 Manager,
330 Worker,
331}
332
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
335pub enum TouchEvent {
336 Released,
337 Pressed,
338 Held,
339}
340
341#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
343pub enum Port {
344 Smart(SmartPort),
345 Adi(AdiPort),
346}
347
348#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
350pub struct SmartPort(pub u8);
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
354pub struct AdiPort(pub u8);
355
356#[derive(
358 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default,
359)]
360pub enum CompMode {
361 Auto,
362 #[default]
363 Driver,
364}
365
366#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
368pub enum LogLevel {
369 Trace,
370 Info,
371 Warn,
372 Error,
373}
374
375#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
377pub struct Battery {
378 pub voltage: f64,
379 pub current: f64,
380 pub capacity: f64,
381}
382
383#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
385pub enum ControllerUpdate {
386 Raw(ControllerState),
389 UUID(String),
391}
392
393#[derive(
395 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default,
396)]
397pub struct ControllerState {
398 pub axis1: i32,
399 pub axis2: i32,
400 pub axis3: i32,
401 pub axis4: i32,
402 pub button_l1: bool,
403 pub button_l2: bool,
404 pub button_r1: bool,
405 pub button_r2: bool,
406 pub button_up: bool,
407 pub button_down: bool,
408 pub button_left: bool,
409 pub button_right: bool,
410 pub button_x: bool,
411 pub button_b: bool,
412 pub button_y: bool,
413 pub button_a: bool,
414 pub button_sel: bool,
415 pub battery_level: i32,
416 pub button_all: bool,
417 pub flags: i32,
418 pub battery_capacity: i32,
419}
420
421#[derive(
422 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default,
423)]
424pub struct Color(pub u32);
425
426impl From<RGB8> for Color {
427 fn from(rgb: RGB8) -> Self {
428 Self(u32::from_be_bytes([0, rgb.r, rgb.g, rgb.b]))
429 }
430}
431
432impl From<Color> for RGB8 {
433 fn from(color: Color) -> Self {
434 let [_, r, g, b] = color.0.to_be_bytes();
435 RGB8 { r, g, b }
436 }
437}
438
439#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
440pub struct Rect {
441 pub top_left: Point2<i32>,
442 pub bottom_right: Point2<i32>,
443}