awtrix_control 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3ab9bbb11f50ef16f44802afcddacd4ed0735a3183c232e44629ebf180ed580
4
+ data.tar.gz: 37127243a83f3057591f1cf6c74054c25329a50badf1a4f166f0084c474f6c1c
5
+ SHA512:
6
+ metadata.gz: 4c96a251e9df3890cfa8bfb95448b246cd61f19f2ad0d9abb66af7eb893086cbd4d15363651f0697f7785b4d4c28ce02d4ad2112602178a073cc4164a5ef32c5
7
+ data.tar.gz: 78f63a8565721667c6b038948e1f081aa1da58b29af5b4b018f7025e586ac105fb478b9f5da75b094eb4ed444e4538e28734fc962f03022499f30af053a337bd
@@ -0,0 +1,471 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'request'
4
+
5
+ module AwtrixControl
6
+ class App
7
+ include AwtrixControl
8
+ attr_accessor :name, :payload
9
+
10
+ # Payload attributes with their types and camelCase keys:
11
+ ATTRIBUTES = {
12
+ text: { key: 'text' },
13
+ text_case: { key: 'textCase', default: 0 },
14
+ top_text: { key: 'topText', default: false },
15
+ text_offset: { key: 'textOffset', default: 0 },
16
+ center_text: { key: 'center', default: true },
17
+ text_color: { key: 'color' },
18
+ text_gradient: { key: 'gradient' },
19
+ blink_text: { key: 'blinkText' },
20
+ fade_text: { key: 'fadeText' },
21
+ background_color: { key: 'background' },
22
+ rainbow_effect: { key: 'rainbow' },
23
+ icon: { key: 'icon' },
24
+ push_icon: { key: 'pushIcon', default: 0 },
25
+ repeat_text: { key: 'repeat', default: -1 },
26
+ display_duration: { key: 'duration', default: 5 },
27
+ hold_notification: { key: 'hold', default: false },
28
+ sound: { key: 'sound' },
29
+ rtttl_sound: { key: 'rtttl' },
30
+ loop_sound: { key: 'loopSound', default: false },
31
+ bar_chart: { key: 'bar' },
32
+ line_chart: { key: 'line' },
33
+ auto_scale: { key: 'autoScale', default: true },
34
+ progress_bar: { key: 'progress', default: -1 },
35
+ progress_bar_color: { key: 'progressC', default: -1 },
36
+ progress_bar_background_color: { key: 'progressBC', default: -1 },
37
+ position: { key: 'pos' },
38
+ draw_commands: { key: 'draw' },
39
+ lifetime: { key: 'lifetime', default: 0 },
40
+ lifetime_mode: { key: 'lifetimeMode', default: 0 },
41
+ stack_notifications: { key: 'stack', default: true },
42
+ wakeup_display: { key: 'wakeup', default: false },
43
+ disable_scroll: { key: 'noScroll', default: false },
44
+ forward_clients: { key: 'clients' },
45
+ scroll_speed: { key: 'scrollSpeed', default: 100 },
46
+ background_effect: { key: 'effect' },
47
+ background_effect_settings: { key: 'effectSettings' },
48
+ save_app: { key: 'save' },
49
+ overlay_effect: { key: 'overlay' }
50
+ }.freeze
51
+
52
+ LIFETIME_MODE_OPTIONS = {
53
+ destroy: 0,
54
+ stale: 1
55
+ }.freeze
56
+
57
+ PUSH_ICON_OPTIONS = {
58
+ fixed: 0,
59
+ scroll_once: 1,
60
+ loop: 2,
61
+ }.freeze
62
+
63
+ TEXT_CASES = {
64
+ default: 0,
65
+ upcase: 1,
66
+ as_is: 2
67
+ }.freeze
68
+
69
+ # Initializes a new App instance.
70
+ #
71
+ # @param name [Symbol, String] the name of the app. Must be unique within the device, or the app will be overwritten
72
+ # @param payload [Hash, nil] the payload for the app
73
+ # @param device [Device, nil] the device to associate the app with
74
+ def initialize(name, payload: nil, device: nil)
75
+ @name = name
76
+ device << self if device
77
+ @payload = payload || default_payload
78
+ end
79
+
80
+ # Pushes the app to the associated device.
81
+ def push
82
+ return if @device.nil?
83
+ @device.push_app(self)
84
+ end
85
+
86
+ # Define getters for each attribute in ATTRIBUTES.
87
+ ATTRIBUTES.each do |method_name, options|
88
+ awtrix_attribute = options[:key]
89
+ define_method(method_name) do
90
+ payload[awtrix_attribute]
91
+ end
92
+ end
93
+
94
+ # Sets the autoscale attribute.
95
+ #
96
+ # @param value [Boolean] whether to autoscale the bar or line chart.
97
+ def autoscale=(value)
98
+ @payload[method_to_awtrix_key(:auto_scale)] = !!value
99
+ end
100
+
101
+ # Sets the background color.
102
+ #
103
+ # @param value [String, Symbol, Array<Integer>] the color to set the background to
104
+ # String: A hex color code
105
+ # Symbol: A color name. Must be a key in COLOR_MAPPINGS
106
+ # Array: An array of 3 integers representing the RGB values of the color
107
+ def background_color=(value)
108
+ @payload[method_to_awtrix_key(:background_color)] = normalize_color(value)
109
+ end
110
+
111
+ # Sets the background effect.
112
+ #
113
+ # @param value [String] the effect to apply to the background
114
+ def background_effect=(value)
115
+ @payload[method_to_awtrix_key(:background_effect)] = value
116
+ end
117
+
118
+ # Sets the background effect settings.
119
+ #
120
+ # @param value [Hash] the settings for the background effect
121
+ def background_effect_settings=(value)
122
+ @payload[method_to_awtrix_key(:background_effect_settings)] = value
123
+ end
124
+
125
+ # Sets the bar chart values.
126
+ #
127
+ # @param value [Array<Integer>] an array of integers to represent each bar
128
+ def bar_chart=(value)
129
+ @payload[method_to_awtrix_key(:bar_chart)] = value
130
+ end
131
+
132
+ # Sets the blink text frequency.
133
+ #
134
+ # @param value [Integer] the frequency (in ms) at which the text should blink
135
+ def blink_text=(value)
136
+ @payload[method_to_awtrix_key(:blink_text)] = value.to_i
137
+ end
138
+
139
+ # Gets the blink text frequency.
140
+ #
141
+ # @return [Integer] the frequency (in ms) at which the text should blink
142
+ def blink_text
143
+ @payload[method_to_awtrix_key(:blink_text)].to_i
144
+ end
145
+
146
+ # Sets whether to center the text.
147
+ #
148
+ # @param value [Boolean] whether to center the text
149
+ def center_text=(value)
150
+ @payload[method_to_awtrix_key(:center_text)] = value
151
+ end
152
+
153
+ # Returns the default payload.
154
+ #
155
+ # @return [Hash] the default payload
156
+ def default_payload
157
+ @default_payload ||=
158
+ ATTRIBUTES.each_with_object({}) do |(method_name, options), hash|
159
+ hash[options[:key]] = options[:default] if options.key?(:default)
160
+ end
161
+ end
162
+
163
+ # Deletes the app from the associated device.
164
+ def delete
165
+ @device&.delete_app(self)
166
+ end
167
+
168
+ # Gets the associated device.
169
+ #
170
+ # @return [Device, nil] the associated device
171
+ def device
172
+ @device
173
+ end
174
+
175
+ # Sets the associated device.
176
+ #
177
+ # @param new_device [Device] the new device to associate the app with
178
+ def device=(new_device)
179
+ @device.delete_app(self.name) if @device
180
+ @device = new_device
181
+
182
+ new_device << self
183
+ end
184
+
185
+ # Sets whether to disable text scrolling.
186
+ #
187
+ # @param value [Boolean] whether to disable text scrolling
188
+ def disable_scroll=(value)
189
+ @payload[method_to_awtrix_key(:disable_scroll)] = !!value
190
+ end
191
+
192
+ # Sets the display duration.
193
+ #
194
+ # @param value [Integer] for how long (in seconds) the notification should be shown
195
+ def display_duration=(value)
196
+ @payload[method_to_awtrix_key(:display_duration)] = value.to_i
197
+ end
198
+
199
+ # Sets the drawing commands.
200
+ #
201
+ # @param value [Array] array of drawing instructions
202
+ def draw_commands=(value)
203
+ @payload[method_to_awtrix_key(:draw_commands)] = value
204
+ end
205
+
206
+ # Sets the fade text frequency.
207
+ #
208
+ # @param value [Integer] the frequency (in ms) at which the text should fade in and out
209
+ def fade_text=(value)
210
+ @payload[method_to_awtrix_key(:fade_text)] = value.to_i
211
+ end
212
+
213
+ # Gets the fade text frequency.
214
+ #
215
+ # @return [Integer] the frequency (in ms) at which the text should fade in and out
216
+ def fade_text
217
+ @payload[method_to_awtrix_key(:fade_text)].to_i
218
+ end
219
+
220
+ # Sets the forward clients.
221
+ #
222
+ # @param value [Array<String>] an array of IP addresses of other devices to forward notifications to
223
+ def forward_clients=(value)
224
+ @payload[method_to_awtrix_key(:forward_clients)] = value
225
+ end
226
+
227
+ # Sets whether to hold the notification.
228
+ #
229
+ # @param value [Boolean] whether to hold the notification
230
+ def hold_notification=(value)
231
+ @payload[method_to_awtrix_key(:hold_notification)] = !!value
232
+ end
233
+
234
+ # Sets the icon.
235
+ #
236
+ # @param value [String] the icon ID or filename (without extension) to display on the app
237
+ def icon=(value)
238
+ @payload[method_to_awtrix_key(:icon)] = value
239
+ end
240
+
241
+ # Sets the lifetime.
242
+ #
243
+ # @param value [Integer] the time in seconds after which the app should be removed if no update is received
244
+ def lifetime=(value)
245
+ @payload[method_to_awtrix_key(:lifetime)] = value.to_i
246
+ end
247
+
248
+ # Sets the lifetime mode.
249
+ #
250
+ # @param value [Symbol, Integer] the lifetime mode to use
251
+ # Symbol options: :destroy, :stale
252
+ # Integer options: 0, 1
253
+ def lifetime_mode=(value)
254
+ @payload[method_to_awtrix_key(:lifetime_mode)] = LIFETIME_MODE_OPTIONS[value] || value
255
+ end
256
+
257
+ # Gets the lifetime mode.
258
+ #
259
+ # @return [Symbol, nil] the lifetime mode
260
+ def lifetime_mode
261
+ LIFETIME_MODE_OPTIONS.key(@payload[method_to_awtrix_key(:lifetime_mode)])
262
+ end
263
+
264
+ # Sets the line chart values.
265
+ #
266
+ # @param value [Array<Integer>] an array of integers to represent the line chart
267
+ def line_chart=(value)
268
+ @payload[method_to_awtrix_key(:line_chart)] = value
269
+ end
270
+
271
+ # Sets whether to loop the sound.
272
+ #
273
+ # @param value [Boolean] whether to loop the sound as long as the notification is shown
274
+ def loop_sound=(value)
275
+ @payload[method_to_awtrix_key(:loop_sound)] = !!value
276
+ end
277
+
278
+ # Sets the overlay effect.
279
+ #
280
+ # @param value [String] the effect to apply as an overlay
281
+ def overlay_effect=(value)
282
+ @payload[method_to_awtrix_key(:overlay_effect)] = value
283
+ end
284
+
285
+ # Sets the position of the app in the loop.
286
+ #
287
+ # @param value [Integer] the position of the app in the loop (starting at 0)
288
+ def position=(value)
289
+ @payload[method_to_awtrix_key(:position)] = value
290
+ end
291
+
292
+ # Sets the progress bar value.
293
+ #
294
+ # @param value [Integer] a value between 0 and 100 to set the progress bar to
295
+ def progress_bar=(value)
296
+ @payload[method_to_awtrix_key(:progress_bar)] = value.to_i
297
+ end
298
+
299
+ # Sets the progress bar background color.
300
+ #
301
+ # @param value [String, Symbol, Array<Integer>] the color to set the progress bar background to
302
+ def progress_bar_background_color=(value)
303
+ @payload[method_to_awtrix_key(:progress_bar_background_color)] = normalize_color(value)
304
+ end
305
+
306
+ # Sets the progress bar color.
307
+ #
308
+ # @param value [String, Symbol, Array<Integer>] the color to set the progress bar to
309
+ def progress_bar_color=(value)
310
+ @payload[method_to_awtrix_key(:progress_bar_color)] = normalize_color(value)
311
+ end
312
+
313
+ # Sets the push icon behavior.
314
+ #
315
+ # @param value [Symbol, Integer] a symbol defining the push icon behavior:
316
+ # :fixed, :scroll_once, :loop
317
+ # Or an integer between 0 and 2 representing the above symbols
318
+ def push_icon=(value)
319
+ @payload[method_to_awtrix_key(:push_icon)] = PUSH_ICON_OPTIONS[value] || value
320
+ end
321
+
322
+ # Gets the push icon behavior.
323
+ #
324
+ # @return [Symbol, nil] the push icon behavior
325
+ def push_icon
326
+ PUSH_ICON_OPTIONS.key(@payload[method_to_awtrix_key(:push_icon)])
327
+ end
328
+
329
+ # Sets whether to enable the rainbow effect.
330
+ #
331
+ # @param value [Boolean] whether to enable the rainbow effect
332
+ def rainbow_effect=(value)
333
+ @payload[method_to_awtrix_key(:rainbow_effect)] = !!value
334
+ end
335
+
336
+ # Sets the repeat text value.
337
+ #
338
+ # @param value [Integer] the number of times to repeat the text
339
+ def repeat_text=(value)
340
+ @payload[method_to_awtrix_key(:repeat_text)] = value.to_i
341
+ end
342
+
343
+ # Sets the RTTTL sound.
344
+ #
345
+ # @param value [String] a RTTTL string to play as a sound
346
+ def rtttl_sound=(value)
347
+ @payload[method_to_awtrix_key(:rtttl_sound)] = value
348
+ end
349
+
350
+ # Sets whether to save the app.
351
+ #
352
+ # @param value [Boolean] whether to save the app into flash memory
353
+ def save_app=(value)
354
+ @payload[method_to_awtrix_key(:save_app)] = !!value
355
+ end
356
+
357
+ # Sets the scroll speed.
358
+ #
359
+ # @param value [Integer] the new scroll speed, as a percentage of the original scroll speed
360
+ def scroll_speed=(value)
361
+ @payload[method_to_awtrix_key(:scroll_speed)] = value.to_i
362
+ end
363
+
364
+ # Sets whether to stack notifications.
365
+ #
366
+ # @param value [Boolean] whether to stack the notification
367
+ def stack_notifications=(value)
368
+ @payload[method_to_awtrix_key(:stack_notifications)] = !!value
369
+ end
370
+
371
+ # Sets the sound.
372
+ #
373
+ # @param value [String] the filename of the RTTTL ringtone file or the 4-digit number of the MP3
374
+ def sound=(value)
375
+ @payload[method_to_awtrix_key(:sound)] = value
376
+ end
377
+
378
+ # Sets the text.
379
+ #
380
+ # @param value [String] the text to display
381
+ def text=(value)
382
+ @payload[method_to_awtrix_key(:text)] = value
383
+ end
384
+
385
+ # Sets the text case.
386
+ #
387
+ # @param value [Symbol, Integer] the text case to use
388
+ # Symbol options: :default, :upcase, :as_is
389
+ # Integer options: 0, 1, 2
390
+ def text_case=(value)
391
+ @payload[method_to_awtrix_key(:text_case)] = TEXT_CASES[value] || value
392
+ end
393
+
394
+ # Gets the text case.
395
+ #
396
+ # @return [Symbol, nil] the text case
397
+ def text_case
398
+ TEXT_CASES.key(@payload[method_to_awtrix_key(:text_case)])
399
+ end
400
+
401
+ # Sets the text color.
402
+ #
403
+ # @param value [String, Symbol, Array<Integer>] the color to set the text to
404
+ # String: A hex color code
405
+ # Symbol: A color name. Must be a key in COLOR_MAPPINGS
406
+ # Array: An array of 3 integers representing the RGB values of the color
407
+ def text_color=(value)
408
+ @payload[method_to_awtrix_key(:text_color)] = normalize_color(value)
409
+ end
410
+
411
+ # Sets the text gradient.
412
+ #
413
+ # @param gradient [Hash] a hash with keys :from and :to, each with a color value
414
+ # String: A hex color code
415
+ # Symbol: A color name. Must be a key in COLOR_MAPPINGS
416
+ # Array: An array of 3 integers representing the RGB values of the color
417
+ def text_gradient=(gradient)
418
+ from = normalize_color(gradient[:from])
419
+ to = normalize_color(gradient[:to])
420
+ @payload[method_to_awtrix_key(:text_gradient)] = [from, to]
421
+ end
422
+
423
+ # Gets the text gradient.
424
+ #
425
+ # @return [Hash] a hash with keys :from and :to, each with a color value
426
+ def text_gradient
427
+ raw_gradient = @payload[method_to_awtrix_key(:text_gradient)]
428
+ return { from: nil, to: nil } if raw_gradient.nil?
429
+ {
430
+ from: raw_gradient[0],
431
+ to: raw_gradient[1]
432
+ }
433
+ end
434
+
435
+ # Sets the text offset.
436
+ #
437
+ # @param value [Integer] the offset for the x position of a starting text
438
+ def text_offset=(value)
439
+ @payload[method_to_awtrix_key(:text_offset)] = value
440
+ end
441
+
442
+ # Sets whether to draw the text on top.
443
+ #
444
+ # @param value [Boolean] whether to draw the text on top
445
+ def top_text=(value)
446
+ @payload[method_to_awtrix_key(:top_text)] = value
447
+ end
448
+
449
+ # Sets the text case to uppercase.
450
+ def upcase
451
+ @payload[method_to_awtrix_key(:text_case)] = 1
452
+ end
453
+
454
+ # Sets whether to wake up the display for the notification.
455
+ #
456
+ # @param value [Boolean] whether to wake up the display for the notification
457
+ def wakeup_display=(value)
458
+ @payload[method_to_awtrix_key(:wakeup_display)] = !!value
459
+ end
460
+
461
+ private
462
+
463
+ # Converts a method name to its corresponding Awtrix key.
464
+ #
465
+ # @param method_name [Symbol] the method name
466
+ # @return [String] the corresponding Awtrix key
467
+ def method_to_awtrix_key(method_name)
468
+ ATTRIBUTES[method_name][:key]
469
+ end
470
+ end
471
+ end
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'request'
4
+
5
+ module AwtrixControl
6
+ # The Device class is used to manage the apps on an Awtrix device.
7
+ # The apps are stored in a registry within the device, so you can refer to them by name.
8
+ # Note that there is no synchronization between devices or between device and device.
9
+ # E.g. If you instantiate 2 devices for the same device, they will not be aware of each other and apps could collide,
10
+ # or race conditions could occur.
11
+ class Device
12
+ include AwtrixControl
13
+
14
+ INDICATOR_INDEX = { top: 1, center: 2, bottom: 3 }.freeze
15
+
16
+ attr_reader :apps, :host
17
+
18
+ # Initializes a new Device instance.
19
+ #
20
+ # @param host [String] the IP address or hostname of the Awtrix device
21
+ def initialize(host)
22
+ @host = host
23
+ @apps = {}
24
+ end
25
+
26
+ # Adds an app to the device.
27
+ #
28
+ # @param app [App] the app to add
29
+ # @return [App] the added app
30
+ def <<(app)
31
+ @apps[app.name] = app
32
+ app.device = self unless app.device == self
33
+ app
34
+ end
35
+
36
+ # Retrieves an app by name.
37
+ #
38
+ # @param name [String] the name of the app
39
+ # @return [App, nil] the app if found, otherwise nil
40
+ def [](name)
41
+ @apps[name]
42
+ end
43
+
44
+ # Retrieves the effects from the device.
45
+ #
46
+ # @return [Hash] the effects
47
+ def effects
48
+ get('effects')
49
+ end
50
+
51
+ # Sets the indicator on the device.
52
+ #
53
+ # @param location [Symbol] The location of the indicator to render.
54
+ # Must be a key in INDICATOR_INDEX (:top, :center, :bottom)
55
+ # @param color [String, Array, Symbol] the color to set the indicator to.
56
+ # String: A HEX string representing the color
57
+ # Array: An array of 3 integers representing the RGB values of the color
58
+ # Symbol: A symbol representing the color. Must be a key in COLOR_MAPPINGS
59
+ # @param effect [Symbol, nil] the effect to apply (e.g., :blink, :pulse)
60
+ # @param frequency [Integer, nil] the frequency of the effect
61
+ def indicator(location, color = :white, effect: nil, frequency: nil)
62
+ payload = {}
63
+ payload[:color] = AwtrixControl::COLOR_MAPPINGS[color] || color
64
+ payload[:blink] = frequency || 500 if effect == :blink
65
+ payload[:fade] = frequency || 2000 if effect == :pulse
66
+ index = INDICATOR_INDEX[location]
67
+ post("indicator#{index.to_i}", payload)
68
+ end
69
+
70
+ # Retrieves the current loop state.
71
+ #
72
+ # @return [Hash] the current loop state, as a Hash of apps and their current index.
73
+ # @example
74
+ # device.loop
75
+ # { "Hello" => 1, "Time" => 0, "World" => 2 }
76
+ def loop
77
+ JSON.parse(get('loop'))
78
+ end
79
+
80
+ # Creates a new app and adds it to the device.
81
+ #
82
+ # @param name [String] the name of the app
83
+ # @param payload [Hash] additional payload for the app
84
+ # @return [App] the created app
85
+ def new_app(name, **payload)
86
+ app = payload.empty? ? App.new(name, device: self) : App.new(name, payload:, device: self)
87
+ self << app
88
+ app
89
+ end
90
+
91
+ # Sends a notification to the device.
92
+ #
93
+ # @param text [String] the notification text
94
+ # @param payload [Hash] additional payload for the notification
95
+ def notify(text, **payload)
96
+ payload[:color] = normalize_color(payload[:color] || :white)
97
+ post('notify', { text: }.merge(payload))
98
+ end
99
+
100
+ # Sets the power state of the device.
101
+ #
102
+ # @param switch [Boolean] the power state to set
103
+ # Note that this only turns off the display, not the device itself
104
+ def power(switch)
105
+ post('power', { power: switch })
106
+ end
107
+
108
+ # Removes an indicator from the device.
109
+ #
110
+ # @param location [Symbol] the location of the indicator to remove
111
+ def remove_indicator(location)
112
+ indicator(location, :black)
113
+ end
114
+
115
+ # Removes all indicators from the device.
116
+ def remove_indicators
117
+ INDICATOR_INDEX.each_key { |location| remove_indicator(location) }
118
+ end
119
+
120
+ # Resets the device.
121
+ def reset
122
+ sleep(1)
123
+ end
124
+
125
+ # Plays an RTTTL string on the device.
126
+ #
127
+ # @param rtttl_string [String] the RTTTL string to play
128
+ def rtttl(rtttl_string)
129
+ post('rtttl', rtttl_string)
130
+ end
131
+
132
+ # Retrieves the screen state from the device.
133
+ #
134
+ # @return [Hash] the screen state
135
+ def screen
136
+ get('screen')
137
+ end
138
+
139
+ # Puts the device to sleep.
140
+ #
141
+ # @param seconds [Integer] the number of seconds to sleep
142
+ # If no seconds are provided, the device will sleep indefinitely
143
+ def sleep(seconds = 0)
144
+ payload = (seconds.to_i > 0 ? { sleep: seconds.to_i } : {})
145
+ post('sleep', **payload)
146
+ end
147
+
148
+ # Plays a sound on the device.
149
+ #
150
+ # @param name [String] the name of the sound to play
151
+ def sound(name)
152
+ post('sound', { sound: name })
153
+ end
154
+
155
+ # Retrieves the device statistics.
156
+ #
157
+ # @return [Hash] the device statistics
158
+ def stats
159
+ get('stats')
160
+ end
161
+
162
+ # Retrieves the transitions from the device.
163
+ #
164
+ # @return [Hash] the transitions
165
+ def transitions
166
+ get('transitions')
167
+ end
168
+
169
+ # Deletes an app from the device.
170
+ #
171
+ # @param app_name [String, Symbol] the app name to delete
172
+ def delete_app(app_name)
173
+ post('custom', {}, { name: app_name })
174
+ @apps.delete(app_name)
175
+ end
176
+
177
+ # Deletes all apps from the device.
178
+ def delete_all_apps
179
+ loop.each_key { |app_name| delete_app(app_name) }
180
+ @apps = {}
181
+ end
182
+
183
+ # Pushes an app to the device, or updates an existing one.
184
+ #
185
+ # @param app_name [Symbol, String] the app name to push
186
+ def push_app(app_name)
187
+ registered_app = @apps[app_name]
188
+ return unless registered_app
189
+
190
+ post('custom',
191
+ { name: registered_app.name }.merge(registered_app.payload),
192
+ { name: registered_app.name })
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+
6
+ module AwtrixControl
7
+ module Request
8
+ private
9
+
10
+ def get(path)
11
+ uri = uri(path)
12
+ http = Net::HTTP.new(uri.host, uri.port)
13
+ request = Net::HTTP::Get.new(uri)
14
+ response = http.request(request)
15
+ response.body
16
+ end
17
+
18
+ def post(path, payload = {}, query_params = {})
19
+ uri = uri(path, query_params)
20
+ http = Net::HTTP.new(uri.host, uri.port)
21
+ request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
22
+ request.body = payload.to_json
23
+ response = http.request(request)
24
+ response.body
25
+ end
26
+
27
+ def uri(path, query_params = {})
28
+ query_params = query_params.map { |k, v| "#{k}=#{v}" }.join('&')
29
+ query_params = "?#{query_params}" unless query_params.empty?
30
+ URI("http://#{host}/api/#{path}#{query_params}")
31
+ end
32
+ end
33
+ end