mushy 0.9.0 → 0.14.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.
@@ -0,0 +1,283 @@
1
+ module Mushy
2
+
3
+ class SenseHatLedMatrix < SimplePythonProgram
4
+
5
+ def self.details
6
+ {
7
+ name: 'SenseHatLedMatrix',
8
+ description: 'Interface with the LED Matrix.',
9
+ config: Mushy::SimplePythonProgram.default_config.tap do |config|
10
+ config[:get_pixels] = {
11
+ description: 'Specify the pixels you want returned as events. Use "all" to return all 64, 3,3 to return x:3 y:3, or "none" to return none.',
12
+ type: 'text',
13
+ shrink: true,
14
+ value: 'all',
15
+ }
16
+ config[:set_pixel] = {
17
+ description: 'Set a single pixel to the RGB color.',
18
+ type: 'text',
19
+ shrink: true,
20
+ value: '',
21
+ }
22
+ config[:set_pixels] = {
23
+ description: 'An array of multiple pixels to set. The records must have coordinates and rgb values, just like what comes out of the get pixels call.',
24
+ type: 'text',
25
+ shrink: true,
26
+ value: '',
27
+ }
28
+ config[:rgb] = {
29
+ description: 'The RGB value as a comma-delimited list. Leave blank to not set a color.',
30
+ type: 'text',
31
+ shrink: true,
32
+ value: '',
33
+ }
34
+ config[:background_color] = {
35
+ description: 'The RGB of the background, which is used in some API calls.',
36
+ type: 'text',
37
+ shrink: true,
38
+ value: '',
39
+ }
40
+ config[:clear] = {
41
+ description: 'The RGB color to apply to the entire grid.',
42
+ type: 'text',
43
+ shrink: true,
44
+ value: '',
45
+ }
46
+ config[:show_letter] = {
47
+ description: 'Show a single letter on the grid. Uses Rgb and Background Color.',
48
+ type: 'text',
49
+ shrink: true,
50
+ value: '',
51
+ }
52
+ config[:show_message] = {
53
+ description: 'Scroll a message across the grid. Uses Rgb and Background Color.',
54
+ type: 'text',
55
+ shrink: true,
56
+ value: '',
57
+ }
58
+ config[:load_image] = {
59
+ description: 'Load a 8x8 image.',
60
+ type: 'text',
61
+ shrink: true,
62
+ value: '',
63
+ }
64
+ config[:set_rotation] = {
65
+ description: 'Rotate the image by these degrees.',
66
+ type: 'select',
67
+ options: ['', '0', '90', '180', '270'],
68
+ shrink: true,
69
+ value: '',
70
+ }
71
+ config[:redraw] = {
72
+ description: 'Redraw.',
73
+ type: 'boolean',
74
+ shrink: true,
75
+ value: '',
76
+ }
77
+ config[:low_light] = {
78
+ description: 'Use the low light to turn down the brightness.',
79
+ type: 'boolean',
80
+ shrink: true,
81
+ value: '',
82
+ }
83
+ config[:flip_h] = {
84
+ description: 'Flips the image horizontally.',
85
+ type: 'boolean',
86
+ shrink: true,
87
+ value: '',
88
+ }
89
+ config[:flip_v] = {
90
+ description: 'Flips the image vertically.',
91
+ type: 'boolean',
92
+ shrink: true,
93
+ value: '',
94
+ }
95
+ config[:target] = {
96
+ description: 'The target of these commands. "hat" is a SenseHAT plugged into your Raspberry Pi, and "emu" is the SenseHAT emulator. Defaults to "hat".',
97
+ type: 'select',
98
+ options: ['', 'hat' , 'emu'],
99
+ shrink: true,
100
+ value: '',
101
+ }
102
+ end
103
+ }
104
+ end
105
+
106
+ def python_program event, config
107
+
108
+ commands = [
109
+ :set_pixel_code_from,
110
+ :set_pixels_code_from,
111
+ :clear_pixels_code_from,
112
+ :show_letters_code_from,
113
+ :show_message_code_from,
114
+ :load_images_code_from,
115
+ :set_rotation_code_from,
116
+ :low_light_code_from,
117
+ :flip_h_code_from,
118
+ :flip_v_code_from,
119
+ ].map { |x| self.send x, event, config }
120
+ .select { |x| x.to_s != '' }
121
+ .join("\n")
122
+
123
+ hat = config[:target] == 'emu' ? 'sense_emu' : 'sense_hat'
124
+
125
+ <<PYTHON
126
+ from #{hat} import SenseHat
127
+ import json
128
+ sense = SenseHat()
129
+ #{commands}
130
+ value = json.dumps({"all": #{get_pixels_code_from(event, config)}})
131
+ print(value)
132
+ PYTHON
133
+ end
134
+
135
+ def adjust data, event, config
136
+ limit = 8
137
+
138
+ coordinates = coordinates_from config[:get_pixels]
139
+
140
+ records = coordinates ? [data[:all]] : data[:all]
141
+
142
+ results = records.each_with_index.map do |item, index|
143
+ {
144
+ x: index % limit,
145
+ y: index / limit,
146
+ r: item[0],
147
+ g: item[1],
148
+ b: item[2],
149
+ }
150
+ end
151
+
152
+ if coordinates
153
+ results[0][:x] = coordinates[:x]
154
+ results[0][:y] = coordinates[:y]
155
+ end
156
+
157
+ results.each do |record|
158
+ record[:coordinate] = "#{record[:x]},#{record[:y]}"
159
+ record[:rgb] = "#{record[:r]},#{record[:g]},#{record[:b]}"
160
+ end
161
+
162
+ results
163
+ end
164
+
165
+ def rgb_from config
166
+ color_split = config.to_s.split ','
167
+ return nil unless color_split.count == 3
168
+ return [:r, :g, :b].each_with_index
169
+ .reduce({}) { |t, i| t[i[0]] = color_split[i[1]].to_s.to_i ; t}
170
+ end
171
+
172
+ def coordinates_from config
173
+ coordinate_split = config.to_s.split ','
174
+ return nil unless coordinate_split.count == 2
175
+ return [:x, :y].each_with_index
176
+ .reduce({}) { |t, i| t[i[0]] = coordinate_split[i[1]].to_s.to_i ; t}
177
+ end
178
+
179
+ def set_pixel_code_from event, config
180
+ rgb = rgb_from config[:rgb]
181
+ set_pixel_coordinates = coordinates_from config[:set_pixel]
182
+ return '' unless rgb
183
+ return '' unless set_pixel_coordinates
184
+
185
+ turn_these_to_pixels([ {
186
+ coordinate: "#{set_pixel_coordinates[:x]},#{set_pixel_coordinates[:y]}",
187
+ rgb: "#{rgb[:r]},#{rgb[:g]},#{rgb[:b]}",
188
+ } ])
189
+ end
190
+
191
+ def set_pixels_code_from event, config
192
+ return '' unless config[:set_pixels]
193
+ turn_these_to_pixels config[:set_pixels]
194
+ end
195
+
196
+ def turn_these_to_pixels values
197
+ options = [:coordinate, :rgb]
198
+ values.map do |pixel|
199
+ options.reduce({}) { |t, i| t[i] = pixel[i].split(',') ; t}
200
+ end.map do |pixel|
201
+ "sense.set_pixel(#{pixel[:coordinate][0]}, #{pixel[:coordinate][1]}, [#{pixel[:rgb][0]}, #{pixel[:rgb][1]}, #{pixel[:rgb][2]}])"
202
+ end.join("\n")
203
+ end
204
+
205
+ def clear_pixels_code_from event, config
206
+ clear = rgb_from config[:clear]
207
+ return '' unless clear
208
+ "sense.clear(#{clear[:r]}, #{clear[:g]}, #{clear[:b]})"
209
+ end
210
+
211
+ def show_letters_code_from event, config
212
+ return '' if config[:show_letter].to_s == ''
213
+
214
+ rgb = rgb_from config[:rgb]
215
+ background_color = rgb_from config[:background_color]
216
+
217
+ args = ["\"#{config[:show_letter]}\""]
218
+ args << "text_colour=[#{rgb[:r]}, #{rgb[:g]}, #{rgb[:b]}]" if rgb
219
+ args << "back_colour=[#{background_color[:r]}, #{background_color[:g]}, #{background_color[:b]}]" if background_color
220
+ "sense.show_letter(#{args.join(',')})"
221
+ end
222
+
223
+ def show_message_code_from event, config
224
+ return '' if config[:show_message].to_s == ''
225
+
226
+ rgb = rgb_from config[:rgb]
227
+ background_color = rgb_from config[:background_color]
228
+
229
+ args = ["\"#{config[:show_message]}\""]
230
+ args << "text_colour=[#{rgb[:r]}, #{rgb[:g]}, #{rgb[:b]}]" if rgb
231
+ args << "back_colour=[#{background_color[:r]}, #{background_color[:g]}, #{background_color[:b]}]" if background_color
232
+ "sense.show_message(#{args.join(',')})"
233
+ end
234
+
235
+ def load_images_code_from event, config
236
+ return '' if config[:load_image].to_s == ''
237
+
238
+ args = ["\"#{config[:load_image]}\""]
239
+ args << config[:redraw].to_s.capitalize if config[:redraw].to_s != ''
240
+ "sense.load_image(#{args.join(',')})"
241
+ end
242
+
243
+ def set_rotation_code_from event, config
244
+ return '' if config[:set_rotation].to_s == ''
245
+ args = ["#{config[:set_rotation]}"]
246
+ args << config[:redraw].to_s.capitalize if config[:redraw].to_s != ''
247
+ "sense.set_rotation(#{args.join(',')})"
248
+ end
249
+
250
+ def low_light_code_from event, config
251
+ return '' if config[:low_light].to_s == ''
252
+ "sense.low_light = #{config[:low_light].capitalize}"
253
+ end
254
+
255
+ def flip_h_code_from event, config
256
+ return '' unless config[:flip_h].to_s == 'true'
257
+ args = []
258
+ args << config[:redraw].to_s.capitalize if config[:redraw].to_s != ''
259
+ "sense.flip_h(#{args.join(',')})"
260
+ end
261
+
262
+ def flip_v_code_from event, config
263
+ return '' unless config[:flip_v].to_s == 'true'
264
+ args = []
265
+ args << config[:redraw].to_s.capitalize if config[:redraw].to_s != ''
266
+ "sense.flip_v(#{args.join(',')})"
267
+ end
268
+
269
+ def get_pixels_code_from event, config
270
+ get_pixel_coordinates = coordinates_from config[:get_pixels]
271
+
272
+ if get_pixel_coordinates
273
+ "sense.get_pixel(#{get_pixel_coordinates[:x]}, #{get_pixel_coordinates[:y]})"
274
+ elsif config[:get_pixels].to_s.downcase == 'all'
275
+ 'sense.get_pixels()'
276
+ else
277
+ '[]'
278
+ end
279
+ end
280
+
281
+ end
282
+
283
+ end
@@ -0,0 +1,40 @@
1
+ module Mushy
2
+
3
+ class SimplePythonProgram < Bash
4
+
5
+ def self.default_config
6
+ Mushy::Bash.details[:config].tap do |config|
7
+ config.delete :command
8
+ config.delete :directory
9
+ end
10
+ end
11
+
12
+ def self.details
13
+ nil
14
+ end
15
+
16
+ def process event, config
17
+
18
+ lines = python_program(event, config)
19
+ .split('\n')
20
+ .map { |x| x.rstrip }
21
+ .select { |x| x && x != '' }
22
+ .map { |x| x.gsub('"', '\"') }
23
+
24
+ config[:command] = "python -c \"#{lines.join(';')}\""
25
+
26
+ result = super event, config
27
+
28
+ return nil unless result[:success]
29
+
30
+ adjust SymbolizedHash.new(JSON.parse(result[:text])), event, config
31
+
32
+ end
33
+
34
+ def adjust data, event, config
35
+ data
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,29 @@
1
+ require 'csv'
2
+
3
+ module Mushy
4
+
5
+ class WriteJson < Flux
6
+
7
+ def self.details
8
+ {
9
+ name: 'WriteJson',
10
+ description: 'Write the incoming event as JSON.',
11
+ config: {
12
+ key: {
13
+ description: 'The key of the outgoing field that will contain the JSON.',
14
+ type: 'text',
15
+ value: 'json',
16
+ },
17
+ },
18
+ }
19
+ end
20
+
21
+ def process event, config
22
+ {
23
+ config[:key] => event.to_json
24
+ }
25
+ end
26
+
27
+ end
28
+
29
+ end
data/lib/mushy.rb CHANGED
@@ -3,9 +3,16 @@ require 'symbolized'
3
3
 
4
4
  Dir[File.dirname(__FILE__) + '/mushy/*.rb'].each { |f| require f }
5
5
 
6
- important_flux_files = ['bash', 'browser'].map { |x| "#{x}.rb" }
6
+ important_flux_files = [
7
+ 'bash',
8
+ 'browser',
9
+ 'simple_python_program',
10
+ ].map { |x| "#{x}.rb" }
11
+
7
12
  Dir[File.dirname(__FILE__) + '/mushy/fluxs/*.rb']
8
- .sort_by { |f| important_flux_files.any? { |x| f.end_with?(x) } ? 0 : 1 }
9
- .each { |f| require f }
13
+ .map { |x| [x, important_flux_files.find_index(x.split("\/")[-1]) || 9999999] }
14
+ .sort_by { |x| x[1] }
15
+ .map { |x| x[0] }
16
+ .each { |f| require f }
10
17
 
11
18
  Dir[File.dirname(__FILE__) + '/mushy/builder/*.rb'].each { |f| require f }
data/lib/site.rb CHANGED
@@ -8,6 +8,11 @@ get '/' do
8
8
  Mushy::Builder::Index.file
9
9
  end
10
10
 
11
+ get '/bulma.css' do
12
+ content_type :css
13
+ Mushy::Builder::Bulma.file
14
+ end
15
+
11
16
  get '/dark.css' do
12
17
  content_type :css
13
18
  Mushy::Builder::Dark.file
data/mushy.gemspec CHANGED
@@ -4,7 +4,7 @@ require 'mushy/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'mushy'
7
- s.version = '0.9.0'
7
+ s.version = '0.14.0'
8
8
  s.date = '2020-11-23'
9
9
  s.summary = 'Process streams of work using common modules.'
10
10
  s.description = 'This tool assists in the creation and processing of workflows.'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mushy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Cauthon
@@ -175,6 +175,7 @@ files:
175
175
  - lib/mushy.rb
176
176
  - lib/mushy/builder/api.rb
177
177
  - lib/mushy/builder/axios.rb
178
+ - lib/mushy/builder/bulma.rb
178
179
  - lib/mushy/builder/dark.rb
179
180
  - lib/mushy/builder/index.rb
180
181
  - lib/mushy/builder/vue.rb
@@ -203,10 +204,15 @@ files:
203
204
  - lib/mushy/fluxs/pwd.rb
204
205
  - lib/mushy/fluxs/read_csv.rb
205
206
  - lib/mushy/fluxs/read_file.rb
207
+ - lib/mushy/fluxs/read_json.rb
206
208
  - lib/mushy/fluxs/screenshot.rb
209
+ - lib/mushy/fluxs/sense_hat_environmental_sensors.rb
210
+ - lib/mushy/fluxs/sense_hat_led_matrix.rb
211
+ - lib/mushy/fluxs/simple_python_program.rb
207
212
  - lib/mushy/fluxs/smtp.rb
208
213
  - lib/mushy/fluxs/times.rb
209
214
  - lib/mushy/fluxs/write_file.rb
215
+ - lib/mushy/fluxs/write_json.rb
210
216
  - lib/mushy/masher.rb
211
217
  - lib/mushy/run.rb
212
218
  - lib/mushy/runner.rb