mushy 0.7.0 → 0.13.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.
- checksums.yaml +4 -4
- data/lib/mushy.rb +10 -3
- data/lib/mushy/flow.rb +14 -1
- data/lib/mushy/flux.rb +4 -5
- data/lib/mushy/fluxs/collection.rb +33 -15
- data/lib/mushy/fluxs/global_variables.rb +39 -0
- data/lib/mushy/fluxs/pdf.rb +2 -2
- data/lib/mushy/fluxs/read_json.rb +28 -0
- data/lib/mushy/fluxs/screenshot.rb +2 -2
- data/lib/mushy/fluxs/sense_hat_environmental_sensors.rb +56 -0
- data/lib/mushy/fluxs/sense_hat_led_matrix.rb +283 -0
- data/lib/mushy/fluxs/simple_python_program.rb +36 -0
- data/lib/mushy/fluxs/write_json.rb +29 -0
- data/lib/mushy/masher.rb +9 -1
- data/lib/mushy/runner.rb +6 -4
- data/mushy.gemspec +1 -1
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85eb693e91e6a27ab2943d07ab5d4a7d3544c958793aac1830a3d03a81d98001
|
4
|
+
data.tar.gz: be51f8e5b94fb4184c1e8f7ba037de1a5ae9901a0fd7ace4fc85e6cc182a864b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bc9319d1c55c581d91377c28ec526ec2215c66962eae0723cfa47eaca5599d6a5bebc439ce423864c37544e6b6250354235f14dddb182c370836c9a289ddd66
|
7
|
+
data.tar.gz: '08efdce27c2820c503ef940224c9b27da0d4c88f11d3f837d50ca1ba99f062de019b1143dc4a3d5bf575b1789b9218c913315570ef00d82b7173c0cbbaa8299a'
|
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 = [
|
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
|
-
.
|
9
|
-
.
|
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/mushy/flow.rb
CHANGED
@@ -17,15 +17,28 @@ module Mushy
|
|
17
17
|
.flatten
|
18
18
|
end
|
19
19
|
|
20
|
+
def adjust_data data
|
21
|
+
fluxs
|
22
|
+
.select { |x| x.respond_to? :adjust_data }
|
23
|
+
.reduce(data) { |t, i| i.adjust_data t }
|
24
|
+
end
|
25
|
+
|
20
26
|
def self.build_flux record
|
21
27
|
type = record[:type] || record['type'] || record[:flux] || record['flux'] || 'Flux'
|
22
28
|
flux = Object.const_get("Mushy::#{type}").new
|
23
29
|
flux.id = record[:id] || record['id'] || flux.id
|
24
30
|
flux.type = type
|
25
31
|
flux.config = SymbolizedHash.new(record[:config] || record['config'])
|
32
|
+
flux.flow = Mushy::Flow.new
|
26
33
|
flux
|
27
34
|
end
|
28
35
|
|
36
|
+
def build_flux record
|
37
|
+
Mushy::Flow.build_flux(record).tap do |flux|
|
38
|
+
flux.flow = self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
29
42
|
def self.parse data
|
30
43
|
data = JSON.parse data
|
31
44
|
|
@@ -34,7 +47,7 @@ module Mushy
|
|
34
47
|
|
35
48
|
flow = new
|
36
49
|
|
37
|
-
flow.fluxs = data_fluxs.map { |s| build_flux s }
|
50
|
+
flow.fluxs = data_fluxs.map { |s| flow.build_flux s }
|
38
51
|
|
39
52
|
fluxs_with_parent_ids = flow.fluxs.reduce({}) { |t, i| t[i.id] = []; t }
|
40
53
|
data_fluxs.map { |r| fluxs_with_parent_ids[r['id']] = r['parents'] || [] }
|
data/lib/mushy/flux.rb
CHANGED
@@ -8,6 +8,7 @@ module Mushy
|
|
8
8
|
attr_accessor :subscribed_to
|
9
9
|
attr_accessor :config
|
10
10
|
attr_accessor :masher
|
11
|
+
attr_accessor :flow
|
11
12
|
|
12
13
|
def initialize
|
13
14
|
guard
|
@@ -39,20 +40,18 @@ module Mushy
|
|
39
40
|
|
40
41
|
incoming_event = SymbolizedHash.new(incoming_event) if incoming_event.is_a?(Hash)
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
incoming_split = masher.mash(config, event)[:incoming_split]
|
43
|
+
incoming_split = masher.mash(config, incoming_event)[:incoming_split]
|
45
44
|
config_considering_an_imcoming_split = config
|
46
45
|
.reject { |x, _| incoming_split && x.to_s == 'join' }
|
47
46
|
.reduce({}) { |t, i| t[i[0]] = i[1]; t }
|
48
47
|
|
49
|
-
events = incoming_split ? incoming_event[incoming_split] : [
|
48
|
+
events = incoming_split ? incoming_event[incoming_split] : [incoming_event]
|
50
49
|
|
51
50
|
results = events.map { |e| execute_single_event e, config_considering_an_imcoming_split }
|
52
51
|
|
53
52
|
return results.first unless incoming_split
|
54
53
|
|
55
|
-
results = join_these_results([results].flatten,
|
54
|
+
results = join_these_results([results].flatten, incoming_event, config[:join]) if config[:join]
|
56
55
|
|
57
56
|
results.flatten
|
58
57
|
end
|
@@ -2,8 +2,6 @@ module Mushy
|
|
2
2
|
|
3
3
|
class Collection < Flux
|
4
4
|
|
5
|
-
attr_accessor :collection
|
6
|
-
|
7
5
|
def self.details
|
8
6
|
{
|
9
7
|
name: 'Collection',
|
@@ -11,9 +9,14 @@ module Mushy
|
|
11
9
|
config: {
|
12
10
|
id: {
|
13
11
|
description: 'The path to the unique id in the body of the element.',
|
14
|
-
type: '
|
15
|
-
value: {
|
12
|
+
type: 'text',
|
13
|
+
value: '{{id}}',
|
16
14
|
},
|
15
|
+
collection_name: {
|
16
|
+
description: 'The name of the collection to interact with.',
|
17
|
+
type: 'text',
|
18
|
+
value: 'records',
|
19
|
+
},
|
17
20
|
operation: {
|
18
21
|
description: 'Perform this operation.',
|
19
22
|
type: 'select',
|
@@ -24,31 +27,26 @@ module Mushy
|
|
24
27
|
}
|
25
28
|
end
|
26
29
|
|
27
|
-
def initialize
|
28
|
-
self.collection = {}
|
29
|
-
super
|
30
|
-
end
|
31
|
-
|
32
30
|
def process event, config
|
33
31
|
self.send(config[:operation].to_sym, event, config)
|
34
32
|
end
|
35
33
|
|
36
34
|
def get_the_id event, config
|
37
|
-
|
35
|
+
config[:id]
|
38
36
|
end
|
39
37
|
|
40
38
|
def all event, config
|
41
|
-
|
39
|
+
the_collection(config).values
|
42
40
|
end
|
43
41
|
|
44
42
|
def delete event, config
|
45
|
-
|
43
|
+
the_collection(config).delete get_the_id(event, config)
|
46
44
|
event[config[:operation_performed]] = 'deleted' if config[:operation_performed]
|
47
45
|
event
|
48
46
|
end
|
49
47
|
|
50
48
|
def upsert event, config
|
51
|
-
if
|
49
|
+
if the_collection(config)[get_the_id(event, config)]
|
52
50
|
update event, config
|
53
51
|
else
|
54
52
|
insert event, config
|
@@ -56,18 +54,38 @@ module Mushy
|
|
56
54
|
end
|
57
55
|
|
58
56
|
def update event, config
|
59
|
-
item =
|
57
|
+
item = the_collection(config)[get_the_id(event, config)]
|
60
58
|
event.each { |k, v| item[k] = v } if item
|
61
59
|
event[config[:operation_performed]] = (item ? 'updated' : 'not exist') if config[:operation_performed]
|
62
60
|
event
|
63
61
|
end
|
64
62
|
|
65
63
|
def insert event, config
|
66
|
-
|
64
|
+
the_collection(config)[get_the_id(event, config)] = event
|
67
65
|
event[config[:operation_performed]] = 'inserted' if config[:operation_performed]
|
68
66
|
event
|
69
67
|
end
|
70
68
|
|
69
|
+
def the_collection config
|
70
|
+
Mushy::Collection.guard_the_flow self.flow
|
71
|
+
the_collection_name = config[:collection_name]
|
72
|
+
|
73
|
+
get_the_collection the_collection_name
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_the_collection name
|
77
|
+
found_collection = self.flow.collection_data[name]
|
78
|
+
return found_collection if found_collection
|
79
|
+
self.flow.collection_data[name] = SymbolizedHash.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.guard_the_flow flow
|
83
|
+
return if flow.respond_to?(:collection_data)
|
84
|
+
|
85
|
+
flow.instance_eval { class << self; self end }.send(:attr_accessor, :collection_data)
|
86
|
+
flow.collection_data = {}
|
87
|
+
end
|
88
|
+
|
71
89
|
end
|
72
90
|
|
73
91
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Mushy
|
2
|
+
|
3
|
+
class GlobalVariables < Flux
|
4
|
+
|
5
|
+
attr_accessor :state
|
6
|
+
|
7
|
+
def self.details
|
8
|
+
{
|
9
|
+
name: 'GlobalVariables',
|
10
|
+
description: 'Add global variables.',
|
11
|
+
config: {
|
12
|
+
values: {
|
13
|
+
description: 'Provide key/value pairs that will be set as global variables.',
|
14
|
+
label: 'Variables',
|
15
|
+
type: 'keyvalue',
|
16
|
+
value: {},
|
17
|
+
},
|
18
|
+
},
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
super
|
24
|
+
self.state = SymbolizedHash.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def adjust_data data
|
28
|
+
state.merge data
|
29
|
+
end
|
30
|
+
|
31
|
+
def process event, config
|
32
|
+
values = config[:values] || SymbolizedHash.new
|
33
|
+
state.merge! values
|
34
|
+
event
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/mushy/fluxs/pdf.rb
CHANGED
@@ -4,8 +4,8 @@ module Mushy
|
|
4
4
|
|
5
5
|
def self.details
|
6
6
|
details = Browser.details
|
7
|
-
details[
|
8
|
-
details[
|
7
|
+
details[:name] = 'Pdf'
|
8
|
+
details[:description] = 'Turn a URL into a PDF.'
|
9
9
|
|
10
10
|
details[:config][:path] = {
|
11
11
|
description: 'The path of the PDF file to save.',
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Mushy
|
4
|
+
|
5
|
+
class ReadJson < Flux
|
6
|
+
|
7
|
+
def self.details
|
8
|
+
{
|
9
|
+
name: 'ReadJson',
|
10
|
+
description: 'Read JSON and output it as an event.',
|
11
|
+
config: {
|
12
|
+
json: {
|
13
|
+
description: 'The JSON contents that will be returned as an event.',
|
14
|
+
type: 'text',
|
15
|
+
value: 'json',
|
16
|
+
},
|
17
|
+
},
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def process event, config
|
22
|
+
return nil unless config[:json].to_s != ''
|
23
|
+
JSON.parse config[:json]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -4,8 +4,8 @@ module Mushy
|
|
4
4
|
|
5
5
|
def self.details
|
6
6
|
details = Browser.details
|
7
|
-
details[
|
8
|
-
details[
|
7
|
+
details[:name] = 'Screenshot'
|
8
|
+
details[:description] = 'Take a screenshot of the browser.'
|
9
9
|
|
10
10
|
details[:config].merge!(Mushy::WriteFile.file_saving_config.tap do |x|
|
11
11
|
x[x.keys.first][:value] = 'file.jpg'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Mushy
|
2
|
+
|
3
|
+
class SenseHatEnvironmentalSensors < SimplePythonProgram
|
4
|
+
|
5
|
+
def self.details
|
6
|
+
{
|
7
|
+
name: 'SenseHatEnvironmentalSensors',
|
8
|
+
description: 'Pull values from the Sense HAT environmental sensors.',
|
9
|
+
config: Mushy::SimplePythonProgram.default_config,
|
10
|
+
}.tap do |c|
|
11
|
+
measurements
|
12
|
+
.sort_by { |x| default_measurements.include?(x) ? 0 : 1 }
|
13
|
+
.each do |measurement|
|
14
|
+
c[:config][measurement] = {
|
15
|
+
description: "Pull #{measurement}.",
|
16
|
+
type: 'boolean',
|
17
|
+
shrink: true,
|
18
|
+
value: default_measurements.include?(measurement) ? 'true' : '',
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.measurements
|
25
|
+
[
|
26
|
+
:humidity,
|
27
|
+
:temperature,
|
28
|
+
:temperature_from_humidity,
|
29
|
+
:temperature_from_pressure,
|
30
|
+
:pressure,
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.default_measurements
|
35
|
+
[:humidity, :temperature, :pressure]
|
36
|
+
end
|
37
|
+
|
38
|
+
def python_program event, config
|
39
|
+
values = self.class.measurements
|
40
|
+
.select { |x| config[x] == 'true' }
|
41
|
+
.reduce({}) { |t, i| t[i] = "get_#{i}"; t}
|
42
|
+
.map { |m| "\"#{m[0]}\": sense.#{m[1]}()" }
|
43
|
+
.join(',')
|
44
|
+
|
45
|
+
<<PYTHON
|
46
|
+
from sense_hat import SenseHat
|
47
|
+
import json
|
48
|
+
sense = SenseHat()
|
49
|
+
value = json.dumps({#{values}})
|
50
|
+
print(value)
|
51
|
+
PYTHON
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -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,36 @@
|
|
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 process event, config
|
13
|
+
|
14
|
+
lines = python_program(event, config)
|
15
|
+
.split('\n')
|
16
|
+
.map { |x| x.rstrip }
|
17
|
+
.select { |x| x && x != '' }
|
18
|
+
.map { |x| x.gsub('"', '\"') }
|
19
|
+
|
20
|
+
config[:command] = "python -c \"#{lines.join(';')}\""
|
21
|
+
|
22
|
+
result = super event, config
|
23
|
+
|
24
|
+
return nil unless result[:success]
|
25
|
+
|
26
|
+
adjust SymbolizedHash.new(JSON.parse(result[:text])), event, config
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def adjust data, event, config
|
31
|
+
data
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
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/masher.rb
CHANGED
@@ -45,7 +45,15 @@ module Mushy
|
|
45
45
|
segments = key.split '.'
|
46
46
|
|
47
47
|
segments.each do |segment|
|
48
|
-
|
48
|
+
if segment.include?('[') && segment.include?(']')
|
49
|
+
the_splits = segment.split('[')
|
50
|
+
segment = the_splits[0]
|
51
|
+
index = the_splits[1].sub(']', '')
|
52
|
+
data = data.is_a?(Hash) ? (data[segment] || data[segment.to_sym]) : (data ? data.send(segment.to_sym) : nil)
|
53
|
+
data = data[index.to_i]
|
54
|
+
else
|
55
|
+
data = data.is_a?(Hash) ? (data[segment] || data[segment.to_sym]) : (data ? data.send(segment.to_sym) : nil)
|
56
|
+
end
|
49
57
|
end
|
50
58
|
|
51
59
|
data
|
data/lib/mushy/runner.rb
CHANGED
@@ -12,7 +12,7 @@ module Mushy
|
|
12
12
|
run = find_run flux, flow
|
13
13
|
starting_event = build_event event_data, flow.id, run.id, flux.id
|
14
14
|
|
15
|
-
events = run_event_with_flux starting_event, flux
|
15
|
+
events = run_event_with_flux starting_event, flux, flow
|
16
16
|
|
17
17
|
while events.any?
|
18
18
|
events = events.map { |e| runner.run_event_in_flow e, flow }.flatten
|
@@ -23,12 +23,14 @@ module Mushy
|
|
23
23
|
|
24
24
|
def run_event_in_flow event, flow
|
25
25
|
flow.fluxs_for(event)
|
26
|
-
.map { |s| runner.run_event_with_flux event, s }
|
26
|
+
.map { |s| runner.run_event_with_flux event, s, flow }
|
27
27
|
.flatten
|
28
28
|
end
|
29
29
|
|
30
|
-
def run_event_with_flux event, flux
|
31
|
-
|
30
|
+
def run_event_with_flux event, flux, flow
|
31
|
+
data = event.data
|
32
|
+
data = flow.adjust_data data
|
33
|
+
[flux.execute(data)]
|
32
34
|
.flatten
|
33
35
|
.reject { |x| x.nil? }
|
34
36
|
.map { |x| x.is_a?(Hash) ? build_event(x, event.flow_id, event.run_id, flux.id) : x }
|
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.
|
7
|
+
s.version = '0.13.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.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darren Cauthon
|
@@ -194,6 +194,7 @@ files:
|
|
194
194
|
- lib/mushy/fluxs/format.rb
|
195
195
|
- lib/mushy/fluxs/get.rb
|
196
196
|
- lib/mushy/fluxs/git_log.rb
|
197
|
+
- lib/mushy/fluxs/global_variables.rb
|
197
198
|
- lib/mushy/fluxs/interval.rb
|
198
199
|
- lib/mushy/fluxs/ls.rb
|
199
200
|
- lib/mushy/fluxs/parse_html.rb
|
@@ -202,10 +203,15 @@ files:
|
|
202
203
|
- lib/mushy/fluxs/pwd.rb
|
203
204
|
- lib/mushy/fluxs/read_csv.rb
|
204
205
|
- lib/mushy/fluxs/read_file.rb
|
206
|
+
- lib/mushy/fluxs/read_json.rb
|
205
207
|
- lib/mushy/fluxs/screenshot.rb
|
208
|
+
- lib/mushy/fluxs/sense_hat_environmental_sensors.rb
|
209
|
+
- lib/mushy/fluxs/sense_hat_led_matrix.rb
|
210
|
+
- lib/mushy/fluxs/simple_python_program.rb
|
206
211
|
- lib/mushy/fluxs/smtp.rb
|
207
212
|
- lib/mushy/fluxs/times.rb
|
208
213
|
- lib/mushy/fluxs/write_file.rb
|
214
|
+
- lib/mushy/fluxs/write_json.rb
|
209
215
|
- lib/mushy/masher.rb
|
210
216
|
- lib/mushy/run.rb
|
211
217
|
- lib/mushy/runner.rb
|