1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use super::Color;
/// Colored text fragment.
#[derive(Debug, Serialize, Deserialize)]
pub struct ColoredText {
/// The text to display.
#[serde(rename = "t")]
pub text: String,
/// The color of the text.
#[serde(rename = "c")]
pub color: Color,
}
/// Text (basic or colored).
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Text {
Text(String),
ColoredText(Vec<ColoredText>),
}
impl From<String> for Text {
fn from(text: String) -> Self {
Text::Text(text)
}
}
impl From<&str> for Text {
fn from(text: &str) -> Self {
Text::Text(text.to_string())
}
}
/// Text case.
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq)]
#[repr(u8)]
pub enum TextCase {
Global = 0,
Upper = 1,
Unchanged = 2,
}
/// Icon position.
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq)]
#[repr(u8)]
pub enum PushIcon {
/// 0 = Icon doesn't move.
NoMove = 0,
/// 1 = Icon moves with text and will not appear again.
MoveOnceWithText = 1,
/// 2 = Icon moves with text but appears again when the text starts to scroll again.
MoveWithText = 2,
}
/// App lifetime mode.
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq)]
#[repr(u8)]
pub enum LifetimeMode {
/// Deletes the app after the given time.
Delete = 0,
/// Marks the app as stale after the given time with a red border.
MarkStale = 1,
}
/// Overlay effect name.
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OverlayEffect {
Clear,
Snow,
Rain,
Drizzle,
Storm,
Thunder,
Frost,
}
/// Effect settings.
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EffectSetting {
speed: u8,
palette: String,
blend: bool,
}
/// Effect definition.
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Effect {
effect: String,
effect_settings: EffectSetting,
}
/// Awtix3 notification definition.
///
/// Reference : <https://blueforcer.github.io/awtrix3/#/api?id=custom-apps-and-notifications>
#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Notification {
/// The text to display. Keep in mind the font does not have a fixed size
/// and `I` uses less space than `W``. This facts affects when text will
/// start scrolling
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<Text>,
/// Changes the Uppercase setting.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_case: Option<TextCase>,
/// Draw the text on top.
#[serde(skip_serializing_if = "Option::is_none")]
pub top_text: Option<bool>,
/// Sets an offset for the x position of a starting text.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_offset: Option<u16>,
/// Centers a short, non-scrollable text.
#[serde(skip_serializing_if = "Option::is_none")]
pub center: Option<bool>,
/// The text, bar or line color.
#[serde(skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
/// Colorizes the text in a gradient of two given colors
#[serde(skip_serializing_if = "Option::is_none")]
pub gradient: Option<Vec<u8>>,
/// Blinks the text in an given interval in ms, not compatible with
/// gradient or rainbow
#[serde(skip_serializing_if = "Option::is_none")]
pub blink_text: Option<u16>,
/// Fades the text on and off in an given interval, not compatible with
/// gradient or rainbow
#[serde(skip_serializing_if = "Option::is_none")]
pub fade_text: Option<u16>,
/// Sets a background color.
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<Color>,
/// Fades each letter in the text differently through the entire RGB
/// spectrum.
#[serde(skip_serializing_if = "Option::is_none")]
pub rainbow: Option<bool>,
/// The icon ID or filename (without extension) to display on the app. You
/// can also send a 8x8 jpg as Base64 String
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<String>,
/// Icon position
#[serde(skip_serializing_if = "Option::is_none")]
pub push_icon: Option<PushIcon>,
/// Sets how many times the text should be scrolled through the matrix
/// before the app ends.
#[serde(skip_serializing_if = "Option::is_none")]
pub repeat: Option<i8>,
/// Sets how long the app or notification should be displayed.
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u16>,
/// Set it to true, to hold your notification on top until you press the
/// middle button or dismiss it via HomeAssistant. This key only belongs
/// to notification.
#[serde(skip_serializing_if = "Option::is_none")]
pub hold: Option<bool>,
/// The filename of your RTTTL ringtone file placed in the MELODIES folder
/// (without extension). Or the 4 digit number of your MP3 if youre using
/// a DFplayer
#[serde(skip_serializing_if = "Option::is_none")]
pub sound: Option<String>,
/// Allows to send the RTTTL sound string with the json.
#[serde(skip_serializing_if = "Option::is_none")]
pub rtttl: Option<String>,
/// Loops the sound or rtttl as long as the notification is running.
#[serde(skip_serializing_if = "Option::is_none")]
pub loop_sound: Option<bool>,
/// Draws a bargraph. Without icon maximum 16 values, with icon 11 values.
#[serde(skip_serializing_if = "Option::is_none")]
pub bar: Option<Vec<u8>>,
/// Draws a linechart. Without icon maximum 16 values, with icon 11 values.
#[serde(skip_serializing_if = "Option::is_none")]
pub line: Option<Vec<u8>>,
/// Enables or disables autoscaling for bar and linechart.
#[serde(skip_serializing_if = "Option::is_none")]
pub autoscale: Option<bool>,
/// Shows a progress bar. Value can be 0-100.
#[serde(skip_serializing_if = "Option::is_none")]
pub progress: Option<u8>,
/// The color of the progress bar.
#[serde(skip_serializing_if = "Option::is_none", rename = "progressC")]
pub progress_color: Option<Color>,
/// The color of the progress bar background.
#[serde(skip_serializing_if = "Option::is_none", rename = "progressBC")]
pub progress_background: Option<Color>,
// /// Array of drawing instructions. Each object represents a drawing
// /// command. See the drawing instructions below.
// // pub draw: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stack: Option<bool>,
/// If the Matrix is off, the notification will wake it up for the time
/// of the notification.
#[serde(skip_serializing_if = "Option::is_none")]
pub wakeup: Option<bool>,
/// Disables the text scrolling.
#[serde(skip_serializing_if = "Option::is_none")]
pub no_scroll: Option<bool>,
/// Allows forwarding a notification to other awtrix devices. Use the
/// MQTT prefix for MQTT and IP addresses for HTTP.
#[serde(skip_serializing_if = "Option::is_none")]
pub clients: Option<Vec<String>>,
/// Modifies the scroll speed. Enter a percentage value of the original
/// scroll speed.
#[serde(skip_serializing_if = "Option::is_none")]
pub scroll_speed: Option<u8>,
/// Shows an effect as background.The effect can be removed by
/// sending an empty string for effect
#[serde(skip_serializing_if = "Option::is_none")]
pub effect: Option<String>,
/// Changes color and speed of the effect.
#[serde(skip_serializing_if = "Option::is_none")]
pub effect_settings: Option<EffectSetting>,
/// Set the effect overlay (cannot be used with global overlays).
#[serde(skip_serializing_if = "Option::is_none")]
pub overlay: Option<OverlayEffect>,
}
/// Awtrix3 app.
///
/// Reference : <https://blueforcer.github.io/awtrix3/#/api?id=custom-apps-and-notifications>
#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct App {
/// The text to display. Keep in mind the font does not have a fixed size
/// and `I` uses less space than `W``. This facts affects when text will
/// start scrolling
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<Text>,
/// Changes the Uppercase setting.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_case: Option<TextCase>,
/// Draw the text on top.
#[serde(skip_serializing_if = "Option::is_none")]
pub top_text: Option<bool>,
/// Sets an offset for the x position of a starting text.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_offset: Option<u16>,
/// Centers a short, non-scrollable text.
#[serde(skip_serializing_if = "Option::is_none")]
pub center: Option<bool>,
/// The text, bar or line color.
#[serde(skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
/// Colorizes the text in a gradient of two given colors
#[serde(skip_serializing_if = "Option::is_none")]
pub gradient: Option<Vec<u8>>,
/// Blinks the text in an given interval in ms, not compatible with
/// gradient or rainbow
#[serde(skip_serializing_if = "Option::is_none")]
pub blink_text: Option<u16>,
/// Fades the text on and off in an given interval, not compatible with
/// gradient or rainbow
#[serde(skip_serializing_if = "Option::is_none")]
pub fade_text: Option<u16>,
/// Sets a background color.
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<Color>,
/// Fades each letter in the text differently through the entire RGB
/// spectrum.
#[serde(skip_serializing_if = "Option::is_none")]
pub rainbow: Option<bool>,
/// The icon ID or filename (without extension) to display on the app. You
/// can also send a 8x8 jpg as Base64 String
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<String>,
/// Icon position
#[serde(skip_serializing_if = "Option::is_none")]
pub push_icon: Option<PushIcon>,
/// Sets how many times the text should be scrolled through the matrix
/// before the app ends.
#[serde(skip_serializing_if = "Option::is_none")]
pub repeat: Option<i8>,
/// Sets how long the app or notification should be displayed.
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u16>,
/// Draws a bargraph. Without icon maximum 16 values, with icon 11 values.
#[serde(skip_serializing_if = "Option::is_none")]
pub bar: Option<Vec<u8>>,
/// Draws a linechart. Without icon maximum 16 values, with icon 11 values.
#[serde(skip_serializing_if = "Option::is_none")]
pub line: Option<Vec<u8>>,
/// Enables or disables autoscaling for bar and linechart.
#[serde(skip_serializing_if = "Option::is_none")]
pub autoscale: Option<bool>,
/// Shows a progress bar. Value can be 0-100.
#[serde(skip_serializing_if = "Option::is_none")]
pub progress: Option<u8>,
/// The color of the progress bar.
#[serde(skip_serializing_if = "Option::is_none", rename = "progressC")]
pub progress_color: Option<Color>,
/// The color of the progress bar background.
#[serde(skip_serializing_if = "Option::is_none", rename = "progressBC")]
pub progress_background: Option<Color>,
/// Defines the position of your custom page in the loop, starting at 0 for
/// the first position. This will only apply with your first push. This
/// function is experimental.
#[serde(skip_serializing_if = "Option::is_none")]
pub pos: Option<u8>,
// /// Array of drawing instructions. Each object represents a drawing
// /// command. See the drawing instructions below.
// // pub draw: Option<Vec<u8>>,
/// Removes the custom app when there is no update after the given time
/// in seconds.
#[serde(skip_serializing_if = "Option::is_none")]
pub lifetime: Option<u32>,
/// App lifetime mode
#[serde(skip_serializing_if = "Option::is_none")]
pub lifetime_mode: Option<LifetimeMode>,
/// Disables the text scrolling.
#[serde(skip_serializing_if = "Option::is_none")]
pub no_scroll: Option<bool>,
/// Allows forwarding a notification to other awtrix devices. Use the
/// MQTT prefix for MQTT and IP addresses for HTTP.
#[serde(skip_serializing_if = "Option::is_none")]
pub clients: Option<Vec<String>>,
/// Modifies the scroll speed. Enter a percentage value of the original
/// scroll speed.
#[serde(skip_serializing_if = "Option::is_none")]
pub scroll_speed: Option<u8>,
/// Shows an effect as background.The effect can be removed by
/// sending an empty string for effect
#[serde(skip_serializing_if = "Option::is_none")]
pub effect: Option<String>,
/// Changes color and speed of the effect.
#[serde(skip_serializing_if = "Option::is_none")]
pub effect_settings: Option<EffectSetting>,
/// Saves your custom app into flash and reloads it after boot.
/// Avoid this for custom apps with high update frequencies
/// because the ESP's flash memory has limited write cycles.
#[serde(skip_serializing_if = "Option::is_none")]
pub save: Option<bool>,
/// Sets an effect overlay (cannot be used with global overlays).
#[serde(skip_serializing_if = "Option::is_none")]
pub overlay: Option<OverlayEffect>,
}
#[derive(Debug, Serialize, Deserialize)]
pub(super) struct AppSwitch {
pub name: String,
}