ruby-macrodroid 0.9.0 → 0.9.5
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/ruby-macrodroid.rb +11 -278
- data/lib/ruby-macrodroid/actions.rb +221 -39
- data/lib/ruby-macrodroid/base.rb +109 -15
- data/lib/ruby-macrodroid/constraints.rb +25 -5
- data/lib/ruby-macrodroid/macro.rb +466 -95
- data/lib/ruby-macrodroid/triggers.rb +33 -15
- metadata +2 -2
- metadata.gz.sig +0 -0
data/lib/ruby-macrodroid/base.rb
CHANGED
@@ -7,7 +7,95 @@
|
|
7
7
|
# MacroObject
|
8
8
|
#
|
9
9
|
|
10
|
+
module ObjectX
|
11
|
+
|
12
|
+
def action_to_object(ap, e, item, macro)
|
13
|
+
|
14
|
+
debug = $debug
|
15
|
+
|
16
|
+
puts 'inside action_to_object: item.xml: ' + item.xml if debug
|
17
|
+
|
18
|
+
if item.element('description') then
|
19
|
+
|
20
|
+
item.xpath('description').map do |description|
|
21
|
+
|
22
|
+
inner_lines = description.text.to_s.strip.lines
|
23
|
+
puts 'inner_lines: ' + inner_lines.inspect if debug
|
24
|
+
|
25
|
+
action = if e.text.to_s.strip.empty? then
|
26
|
+
inner_lines.shift.strip
|
27
|
+
else
|
28
|
+
e.text.strip
|
29
|
+
end
|
30
|
+
|
31
|
+
puts 'action: ' + action.inspect if debug
|
32
|
+
|
33
|
+
r = ap.find_action action
|
34
|
+
puts 'r: ' + r.inspect if debug
|
35
|
+
puts 'description: ' + description.xml.inspect if debug
|
36
|
+
#o = r[0].new([description, self]) if r
|
37
|
+
index = macro.actions.length
|
38
|
+
macro.add Action.new
|
39
|
+
o = object_create(r[0],[description, macro]) if r
|
40
|
+
macro.actions[index] = o
|
41
|
+
puts 'after o' if debug
|
42
|
+
o
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
else
|
47
|
+
|
48
|
+
action = e.text.strip
|
49
|
+
puts 'action: ' + action.inspect if $debug
|
50
|
+
r = ap.find_action action
|
51
|
+
|
52
|
+
a = e.xpath('item/*')
|
53
|
+
|
54
|
+
h = if a.any? then
|
55
|
+
a.map {|node| [node.name.to_sym, node.text.to_s]}.to_h
|
56
|
+
else
|
57
|
+
{}
|
58
|
+
end
|
59
|
+
puts 'h: ' + h.inspect if $debug
|
60
|
+
|
61
|
+
#r = ap.find_action action
|
62
|
+
#r[0].new(h.merge(macro: self)) if r
|
63
|
+
o = object_create(r[0], h.merge(macro: macro)) if r
|
64
|
+
macro.add o
|
65
|
+
o
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
10
71
|
|
72
|
+
def object_create(klass, *args)
|
73
|
+
|
74
|
+
begin
|
75
|
+
klass.new(*args)
|
76
|
+
rescue
|
77
|
+
raise MacroError, klass.to_s + ': ' + ($!).to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def varify(label, value='')
|
82
|
+
|
83
|
+
type = VAR_TYPES[value.class.to_s.to_sym]
|
84
|
+
|
85
|
+
h = {
|
86
|
+
boolean_value: false,
|
87
|
+
decimal_value: 0.0,
|
88
|
+
int_value: 0,
|
89
|
+
name: label,
|
90
|
+
string_value: '',
|
91
|
+
type: type[0]
|
92
|
+
}
|
93
|
+
h[type[1]] = value
|
94
|
+
h
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
11
99
|
|
12
100
|
class MacroObject
|
13
101
|
using ColouredText
|
@@ -34,19 +122,7 @@ class MacroObject
|
|
34
122
|
|
35
123
|
def to_h()
|
36
124
|
|
37
|
-
|
38
|
-
|
39
|
-
h2 = h.inject({}) do |r,x|
|
40
|
-
puts 'x: ' + x.inspect if @debug
|
41
|
-
key, value = x
|
42
|
-
puts 'key: ' + key.inspect if @debug
|
43
|
-
new_key = key.to_s.gsub(/\w_\w/){|x| x[0] + x[-1].upcase}
|
44
|
-
new_key = new_key.prepend 'm_' unless @list.include? new_key
|
45
|
-
new_key = 'm_SIGUID' if new_key == 'm_siguid'
|
46
|
-
r.merge(new_key => value)
|
47
|
-
end
|
48
|
-
|
49
|
-
h2.merge('m_classType' => self.class.to_s)
|
125
|
+
hashify(@h)
|
50
126
|
|
51
127
|
end
|
52
128
|
|
@@ -98,13 +174,31 @@ class MacroObject
|
|
98
174
|
|
99
175
|
def object(h={})
|
100
176
|
|
101
|
-
puts ('inside object h:' + h.inspect).debug if
|
177
|
+
puts ('inside object h:' + h.inspect).debug if $debug
|
102
178
|
klass = Object.const_get h[:class_type]
|
103
179
|
puts klass.inspect.highlight if $debug
|
104
180
|
|
105
181
|
klass.new h
|
106
182
|
|
107
|
-
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def hashify(h)
|
188
|
+
|
189
|
+
h2 = h.inject({}) do |r,x|
|
190
|
+
puts 'x: ' + x.inspect if $debug
|
191
|
+
key, value = x
|
192
|
+
puts 'key: ' + key.inspect if $debug
|
193
|
+
new_key = key.to_s.gsub(/\w_\w/){|x| x[0] + x[-1].upcase}
|
194
|
+
new_key = new_key.prepend 'm_' unless @list.include? new_key
|
195
|
+
new_key = 'm_SIGUID' if new_key == 'm_siguid'
|
196
|
+
new_val = value.is_a?(Hash) ? hashify(value) : value
|
197
|
+
r.merge(new_key => new_val)
|
198
|
+
end
|
199
|
+
|
200
|
+
h2.merge('m_classType' => self.class.to_s)
|
201
|
+
end
|
108
202
|
|
109
203
|
end
|
110
204
|
|
@@ -794,6 +794,13 @@ class MacroDroidVariableConstraint < Constraint
|
|
794
794
|
|
795
795
|
def initialize(h={})
|
796
796
|
|
797
|
+
if h[:loperand] then
|
798
|
+
h[:variable] = {}
|
799
|
+
h[:variable][:name] = h[:loperand]
|
800
|
+
h[:variable][:type] = 2
|
801
|
+
h[:string_value] = h[:roperand]
|
802
|
+
end
|
803
|
+
|
797
804
|
options = {
|
798
805
|
|
799
806
|
:enable_regex=>false,
|
@@ -825,11 +832,24 @@ class MacroDroidVariableConstraint < Constraint
|
|
825
832
|
|
826
833
|
def to_s(colour: false, indent: 0)
|
827
834
|
|
828
|
-
|
829
|
-
|
830
|
-
|
835
|
+
a = [:int_greater_than, :int_less_than, :int_not_equal,
|
836
|
+
:string_equal].zip(['>','<','!=', '='])
|
837
|
+
operator = a.find {|label,_| @h[label]}.last
|
838
|
+
|
839
|
+
var = @h[:variable]
|
840
|
+
|
841
|
+
type = case var[:type]
|
842
|
+
when 0 # boolean
|
843
|
+
:boolean_value
|
844
|
+
when 1 # integer
|
845
|
+
:int_value
|
846
|
+
when 2 # string
|
847
|
+
:string_value
|
848
|
+
when 3 # decimal
|
849
|
+
:decimal_Value
|
850
|
+
end
|
831
851
|
|
832
|
-
@s = "%s %s %s" % [@h[:variable][:name], operator, @h[
|
852
|
+
@s = "%s %s %s" % [@h[:variable][:name], operator, @h[type]]
|
833
853
|
super()
|
834
854
|
end
|
835
855
|
|
@@ -888,7 +908,7 @@ class TriggerThatInvokedConstraint < Constraint
|
|
888
908
|
|
889
909
|
def initialize(h={})
|
890
910
|
|
891
|
-
puts ('h: ' + h.inspect).green
|
911
|
+
puts ('h: ' + h.inspect).green if $debug
|
892
912
|
@trigger = h[:macro].triggers.find {|x| x.siguid == h[:si_guid_that_invoked] }
|
893
913
|
|
894
914
|
options = {
|
@@ -3,6 +3,10 @@
|
|
3
3
|
|
4
4
|
# This file contains the following classes:
|
5
5
|
#
|
6
|
+
# ## Nlp classes
|
7
|
+
#
|
8
|
+
# TriggersNlp ActionsNlp ConstraintsNlp
|
9
|
+
#
|
6
10
|
# ## Macro class
|
7
11
|
#
|
8
12
|
# Macro
|
@@ -12,15 +16,397 @@
|
|
12
16
|
VAR_TYPES = {
|
13
17
|
String: [2, :string_value],
|
14
18
|
TrueClass: [0, :boolean_value],
|
15
|
-
|
19
|
+
FalseClass: [0, :boolean_value],
|
16
20
|
Integer: [1, :int_value],
|
17
21
|
Float: [3, :decimal_value]
|
18
22
|
}
|
19
23
|
|
20
24
|
|
25
|
+
|
26
|
+
class TriggersNlp
|
27
|
+
include AppRoutes
|
28
|
+
|
29
|
+
def initialize(macro=nil)
|
30
|
+
|
31
|
+
super()
|
32
|
+
params = {macro: macro}
|
33
|
+
triggers(params)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def triggers(params)
|
38
|
+
|
39
|
+
# e.g. at 7:30pm daily
|
40
|
+
get /^(?:at )?(\d+:\d+(?:[ap]m)?) daily/i do |time, days|
|
41
|
+
[TimerTrigger, {time: time,
|
42
|
+
days: %w(Mon Tue Wed Thu Fri Sat Sun).join(', ')}]
|
43
|
+
end
|
44
|
+
|
45
|
+
get /^(?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)/i do |time, days|
|
46
|
+
[TimerTrigger, {time: time, days: days}]
|
47
|
+
end
|
48
|
+
|
49
|
+
# time.is? 'at 18:30pm on Mon or Tue'
|
50
|
+
get /^time.is\? ['"](?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)['"]/i do |time, days|
|
51
|
+
[TimerTrigger, {time: time, days: days.gsub(' or ',', ')}]
|
52
|
+
end
|
53
|
+
|
54
|
+
get /^shake[ _]device\??$/i do
|
55
|
+
[ShakeDeviceTrigger, {}]
|
56
|
+
end
|
57
|
+
|
58
|
+
get /^Flip Device (.*)$/i do |motion|
|
59
|
+
facedown = motion =~ /Face Up (?:->|to) Face Down/i
|
60
|
+
[FlipDeviceTrigger, {face_down: facedown }]
|
61
|
+
end
|
62
|
+
|
63
|
+
get /^flip_device_down\?$/i do
|
64
|
+
[FlipDeviceTrigger, {face_down: true }]
|
65
|
+
end
|
66
|
+
|
67
|
+
get /^flip_device_up\?$/i do
|
68
|
+
[FlipDeviceTrigger, {face_down: false }]
|
69
|
+
end
|
70
|
+
|
71
|
+
get /^Failed Login Attempt$/i do
|
72
|
+
[FailedLoginTrigger, {}]
|
73
|
+
end
|
74
|
+
|
75
|
+
get /^failed_login?$/i do
|
76
|
+
[FailedLoginTrigger, {}]
|
77
|
+
end
|
78
|
+
|
79
|
+
get /^Geofence (Entry|Exit) \(([^\)]+)/i do |direction, name|
|
80
|
+
enter_area = direction.downcase.to_sym == :entry
|
81
|
+
[GeofenceTrigger, {name: name, enter_area: enter_area}]
|
82
|
+
end
|
83
|
+
|
84
|
+
get /^location (entered|exited) \(([^\)]+)/i do |direction, name|
|
85
|
+
enter_area = direction.downcase.to_sym == :entered
|
86
|
+
[GeofenceTrigger, {name: name, enter_area: enter_area}]
|
87
|
+
end
|
88
|
+
|
89
|
+
# eg. Proximity Sensor (Near)
|
90
|
+
#
|
91
|
+
get /^Proximity Sensor \(([^\)]+)\)/i do |distance|
|
92
|
+
|
93
|
+
[ProximityTrigger, {distance: distance}]
|
94
|
+
end
|
95
|
+
|
96
|
+
# eg. Proximity near
|
97
|
+
#
|
98
|
+
get /^Proximity (near|far|slow wave|fast wave)/i do |distance|
|
99
|
+
|
100
|
+
[ProximityTrigger, {distance: distance}]
|
101
|
+
end
|
102
|
+
|
103
|
+
get /^WebHook \(Url\)/i do
|
104
|
+
[WebHookTrigger, params]
|
105
|
+
end
|
106
|
+
|
107
|
+
get /^WebHook/i do
|
108
|
+
[WebHookTrigger, params]
|
109
|
+
end
|
110
|
+
|
111
|
+
get /^wh/i do
|
112
|
+
[WebHookTrigger, params]
|
113
|
+
end
|
114
|
+
|
115
|
+
# MacroDroid specific ---------------------------------------------------------------
|
116
|
+
|
117
|
+
get /^EmptyTrigger$/i do
|
118
|
+
[EmptyTrigger, params]
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
alias find_trigger run_route
|
124
|
+
|
125
|
+
def to_s(colour: false)
|
126
|
+
'TriggersNlp ' + @h.inspect
|
127
|
+
end
|
128
|
+
|
129
|
+
alias to_summary to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
class ActionsNlp
|
133
|
+
include AppRoutes
|
134
|
+
|
135
|
+
def initialize(macro=nil)
|
136
|
+
|
137
|
+
super()
|
138
|
+
params = {macro: macro}
|
139
|
+
actions(params)
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
def actions(params)
|
144
|
+
|
145
|
+
# e.g. message popup: hello world!
|
146
|
+
get /^message popup: (.*)/i do |msg|
|
147
|
+
[ToastAction, {msg: msg}]
|
148
|
+
end
|
149
|
+
|
150
|
+
# e.g. Popup Message 'hello world!'
|
151
|
+
get /^Popup[ _]Message ['"]([^'"]+)/i do |msg|
|
152
|
+
[ToastAction, {msg: msg}]
|
153
|
+
end
|
154
|
+
|
155
|
+
# e.g. Popup Message\n hello world!
|
156
|
+
get /^Popup Message\n\s+(.*)/im do |msg|
|
157
|
+
[ToastAction, {msg: msg}]
|
158
|
+
end
|
159
|
+
|
160
|
+
# e.g. Popup Message
|
161
|
+
get /^Popup Message$/i do
|
162
|
+
[ToastAction, {}]
|
163
|
+
end
|
164
|
+
|
165
|
+
# e.g. say current time
|
166
|
+
get /^say current[ _]time/i do
|
167
|
+
[SayTimeAction, {}]
|
168
|
+
end
|
169
|
+
|
170
|
+
get /^Torch :?(.*)/i do |onoffstate|
|
171
|
+
state = %w(on off toggle).index onoffstate.downcase
|
172
|
+
[CameraFlashLightAction, {state: state}]
|
173
|
+
end
|
174
|
+
|
175
|
+
get /^Take Picture/i do
|
176
|
+
[TakePictureAction, {}]
|
177
|
+
end
|
178
|
+
|
179
|
+
get /^take_picture/i do
|
180
|
+
[TakePictureAction, {}]
|
181
|
+
end
|
182
|
+
|
183
|
+
# -- DEVICE ACTIONS ------------------------------------------------------
|
184
|
+
|
185
|
+
get /^Speak text \(([^\)]+)\)/i do |text|
|
186
|
+
[SpeakTextAction, {text: text}]
|
187
|
+
end
|
188
|
+
|
189
|
+
get /^Speak text ['"]([^'"]+)/i do |text|
|
190
|
+
[SpeakTextAction, {text: text}]
|
191
|
+
end
|
192
|
+
|
193
|
+
get /^Speak text$/i do |text|
|
194
|
+
[SpeakTextAction, {}]
|
195
|
+
end
|
196
|
+
|
197
|
+
get /^Vibrate \(([^\)]+)/i do |pattern|
|
198
|
+
[VibrateAction, {pattern: pattern}]
|
199
|
+
end
|
200
|
+
|
201
|
+
get /^Vibrate$/i do |pattern|
|
202
|
+
[VibrateAction, {pattern: 'short buzz'}]
|
203
|
+
end
|
204
|
+
|
205
|
+
# e.g. Display Notification: Hi there: This is the body of the message
|
206
|
+
get /^Display Notification: ([^:]+): [^$]+$/i do |subject, text|
|
207
|
+
[NotificationAction, {subject: subject, text: text}]
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
# e.g. Enable Wifi
|
212
|
+
get /^(Enable|Disable) Wifi$/i do |raw_state|
|
213
|
+
|
214
|
+
state = raw_state.downcase.to_sym == :enable ? 0 : 1
|
215
|
+
[SetWifiAction, {state: state}]
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
# e.g. Play: Altair
|
220
|
+
get /^Play: (.*)$/i do |name|
|
221
|
+
|
222
|
+
[PlaySoundAction, {file_path: name}]
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
# e.g. Launch Settings
|
227
|
+
get /^Launch (.*)$/i do |application|
|
228
|
+
|
229
|
+
h = {
|
230
|
+
application_name: application,
|
231
|
+
package_to_launch: 'com.android.' + application.downcase
|
232
|
+
}
|
233
|
+
[LaunchActivityAction, h]
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
# e.g. HTTP GET http://someurl.com/something
|
238
|
+
get /^HTTP GET ([^$]+)$/i do |url|
|
239
|
+
|
240
|
+
[OpenWebPageAction, url_to_open: url]
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
get /^HTTP GET$/i do
|
245
|
+
|
246
|
+
[OpenWebPageAction, {}]
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
# e.g. webhook entered_kitchen
|
251
|
+
#
|
252
|
+
get /(?:webhook|HTTP GET) ([^$]+)$/i do |s|
|
253
|
+
key = s =~ /^http/ ? :url_to_open : :identifier
|
254
|
+
[OpenWebPageAction, {key => s}]
|
255
|
+
end
|
256
|
+
|
257
|
+
#
|
258
|
+
get /^WebHook \(Url\)/i do
|
259
|
+
[OpenWebPageAction, params]
|
260
|
+
end
|
261
|
+
|
262
|
+
# e.g. webhook entered_kitchen
|
263
|
+
#
|
264
|
+
get /^webhook$/i do
|
265
|
+
[OpenWebPageAction, params]
|
266
|
+
end
|
267
|
+
|
268
|
+
# -- Location ---------------------------------------------------------
|
269
|
+
|
270
|
+
get /^Force Location Update$/i do
|
271
|
+
[ForceLocationUpdateAction, params]
|
272
|
+
end
|
273
|
+
|
274
|
+
get /^Share Location$/i do
|
275
|
+
[ShareLocationAction, params]
|
276
|
+
end
|
277
|
+
|
278
|
+
#a: Keep Device Awake Screen On Until Disabled
|
279
|
+
#
|
280
|
+
get /Keep Device Awake Screen On Until Disabled/i do
|
281
|
+
[KeepAwakeAction, {enabled: true, permanent: true, screen_option: 0}]
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
#a: Keep Device Awake Screen On 1h 1m 1s
|
286
|
+
#
|
287
|
+
get /Keep Device Awake Screen On ([^$]+)/i do |duration|
|
288
|
+
|
289
|
+
a = duration.split.map(&:to_i)
|
290
|
+
secs = Subunit.new(units={minutes:60, hours:60, seconds: 60}, a).to_i
|
291
|
+
|
292
|
+
h = {
|
293
|
+
permanent: true, screen_option: 0, seconds_to_stay_awake_for: secs
|
294
|
+
}
|
295
|
+
[KeepAwakeAction, h]
|
296
|
+
end
|
297
|
+
|
298
|
+
get /Keep Device Awake$/i do
|
299
|
+
[KeepAwakeAction, params]
|
300
|
+
end
|
301
|
+
|
302
|
+
#a: Disable Keep Awake
|
303
|
+
#
|
304
|
+
get /Disable Keep Awake/i do
|
305
|
+
[KeepAwakeAction, {enabled: false, screen_option: 0}]
|
306
|
+
end
|
307
|
+
|
308
|
+
#e.g a: if Airplane mode enabled
|
309
|
+
#
|
310
|
+
get /if (.*)/i do
|
311
|
+
[IfConditionAction, {}]
|
312
|
+
end
|
313
|
+
|
314
|
+
get /End If/i do
|
315
|
+
[EndIfAction, {}]
|
316
|
+
end
|
317
|
+
|
318
|
+
# -- MacroDroid Specific ------------------------------------------------
|
319
|
+
#
|
320
|
+
get /^Set Variable$/i do
|
321
|
+
[SetVariableAction, {}]
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
alias find_action run_route
|
327
|
+
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
class ConstraintsNlp
|
332
|
+
include AppRoutes
|
333
|
+
|
334
|
+
def initialize()
|
335
|
+
|
336
|
+
super()
|
337
|
+
params = {}
|
338
|
+
constraints(params)
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
def constraints(params)
|
343
|
+
|
344
|
+
# Device State
|
345
|
+
|
346
|
+
get /^Device (locked|unlocked)/i do |state|
|
347
|
+
[DeviceLockedConstraint, {locked: state.downcase == 'locked'}]
|
348
|
+
end
|
349
|
+
|
350
|
+
get /^airplane mode (.*)/i do |state|
|
351
|
+
[AirplaneModeConstraint, {enabled: (state =~ /^enabled|on$/i) == 0}]
|
352
|
+
end
|
353
|
+
|
354
|
+
#
|
355
|
+
|
356
|
+
# -- MacroDroid specific -----------------------------------------------------------------------
|
357
|
+
|
358
|
+
get /^(\w+) (=) (\[?\w+\]?)/i do |loperand, operator, roperand|
|
359
|
+
|
360
|
+
h = {
|
361
|
+
loperand: loperand,
|
362
|
+
operator: operator,
|
363
|
+
roperand: roperand
|
364
|
+
}
|
365
|
+
|
366
|
+
[MacroDroidVariableConstraint, h]
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
# -- Sensors -----------------------------------
|
371
|
+
#
|
372
|
+
get /^Light Sensor (Less|Greater) than (50.0)lx/i do |operator, val|
|
373
|
+
|
374
|
+
level, option = operator.downcase == 'less' ? [-1,0] : [1,1]
|
375
|
+
|
376
|
+
h = {
|
377
|
+
light_level: level,
|
378
|
+
light_level_float: val,
|
379
|
+
option: option
|
380
|
+
}
|
381
|
+
|
382
|
+
[LightLevelConstraint, h]
|
383
|
+
end
|
384
|
+
|
385
|
+
get /^Proximity Sensor: (Near|Far)/i do |distance|
|
386
|
+
[ProximitySensorConstraint, {near: distance.downcase == 'near'}]
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
# -- Screen and Speaker ---------------------------
|
391
|
+
#
|
392
|
+
get /^Screen (On|Off)/i do |state|
|
393
|
+
[ScreenOnOffConstraint, {screen_on: state.downcase == 'on'}]
|
394
|
+
end
|
395
|
+
|
396
|
+
end
|
397
|
+
|
398
|
+
alias find_constraint run_route
|
399
|
+
|
400
|
+
end
|
401
|
+
|
402
|
+
|
403
|
+
class MacroError < Exception
|
404
|
+
end
|
405
|
+
|
21
406
|
class Macro
|
22
407
|
using ColouredText
|
23
408
|
using Params
|
409
|
+
include ObjectX
|
24
410
|
|
25
411
|
attr_reader :local_variables, :triggers, :actions, :constraints,
|
26
412
|
:guid, :deviceid
|
@@ -34,12 +420,14 @@ class Macro
|
|
34
420
|
|
35
421
|
puts 'inside Macro#initialize' if @debug
|
36
422
|
|
37
|
-
@local_variables, @triggers, @actions, @constraints =
|
423
|
+
@local_variables, @triggers, @actions, @constraints = {}, [], [], []
|
38
424
|
@h = {}
|
39
425
|
|
40
426
|
end
|
41
427
|
|
42
428
|
def add(obj)
|
429
|
+
puts 'inside add; ' + obj.inspect if @debug
|
430
|
+
puts '@actions: ' + @actions.inspect if @debug
|
43
431
|
|
44
432
|
if obj.kind_of? Trigger then
|
45
433
|
|
@@ -61,9 +449,13 @@ class Macro
|
|
61
449
|
end
|
62
450
|
|
63
451
|
def to_h()
|
452
|
+
|
453
|
+
a = @local_variables.map do |k,v|
|
454
|
+
varify(k,v).to_camelcase.map{|key,value| ['m_' + key, value]}.to_h
|
455
|
+
end
|
64
456
|
|
65
457
|
h = {
|
66
|
-
local_variables:
|
458
|
+
local_variables: a,
|
67
459
|
m_trigger_list: @triggers.map(&:to_h),
|
68
460
|
m_action_list: @actions.map(&:to_h),
|
69
461
|
m_category: @category,
|
@@ -73,7 +465,7 @@ class Macro
|
|
73
465
|
m_excludeLog: false,
|
74
466
|
m_GUID: guid(),
|
75
467
|
m_isOrCondition: false,
|
76
|
-
m_enabled:
|
468
|
+
m_enabled: true,
|
77
469
|
m_descriptionOpen: false,
|
78
470
|
m_headingColor: 0
|
79
471
|
}
|
@@ -98,7 +490,7 @@ class Macro
|
|
98
490
|
if h[:local_variables].any? and h[:local_variables].first.any? then
|
99
491
|
|
100
492
|
@local_variables = h[:local_variables].map do |var|
|
101
|
-
|
493
|
+
|
102
494
|
val = case var[:type]
|
103
495
|
when 0 # boolean
|
104
496
|
var[:boolean_value]
|
@@ -117,7 +509,7 @@ class Macro
|
|
117
509
|
|
118
510
|
# fetch the triggers
|
119
511
|
@triggers = h[:trigger_list].map do |trigger|
|
120
|
-
puts 'trigger: ' + trigger.inspect
|
512
|
+
puts 'trigger: ' + trigger.inspect if @debug
|
121
513
|
#exit
|
122
514
|
object(trigger.to_snake_case)
|
123
515
|
|
@@ -196,25 +588,23 @@ class Macro
|
|
196
588
|
|
197
589
|
@title = node.text('macro') || node.attributes[:name]
|
198
590
|
|
199
|
-
|
591
|
+
d = node.element('description')
|
592
|
+
|
593
|
+
if d then
|
200
594
|
|
201
|
-
|
595
|
+
desc = []
|
596
|
+
desc << d.text.strip
|
202
597
|
|
203
|
-
|
204
|
-
|
205
|
-
elsif v.downcase == 'true'
|
206
|
-
true
|
207
|
-
elsif v.downcase == 'false'
|
208
|
-
false
|
209
|
-
elsif v.to_i.to_s == v
|
210
|
-
v.to_i
|
211
|
-
else
|
212
|
-
v
|
598
|
+
if d.element('item/description') then
|
599
|
+
desc << d.text('item/description').strip
|
213
600
|
end
|
214
601
|
|
215
|
-
|
602
|
+
@description = desc.join("\n")
|
603
|
+
|
216
604
|
end
|
217
605
|
|
606
|
+
node.xpath('variable').each {|e| set_var(*e.text.to_s.split(/: */,2)) }
|
607
|
+
|
218
608
|
#@description = node.attributes[:description]
|
219
609
|
|
220
610
|
tp = TriggersNlp.new(self)
|
@@ -245,7 +635,8 @@ class Macro
|
|
245
635
|
|
246
636
|
r = tp.find_trigger trigger
|
247
637
|
puts 'r: ' + r.inspect if @debug
|
248
|
-
o = r[0].new([description, self]) if r
|
638
|
+
#o = r[0].new([description, self]) if r
|
639
|
+
o = object_create(r[0], [description, self]) if r
|
249
640
|
puts 'after o' if @debug
|
250
641
|
o
|
251
642
|
|
@@ -265,7 +656,12 @@ class Macro
|
|
265
656
|
end
|
266
657
|
|
267
658
|
r = tp.find_trigger trigger
|
268
|
-
r[0].new(h) if r
|
659
|
+
#r[0].new(h) if r
|
660
|
+
if r then
|
661
|
+
object_create(r[0], h)
|
662
|
+
else
|
663
|
+
raise MacroError, 'App-routes: Trigger "' + trigger + '" not found'
|
664
|
+
end
|
269
665
|
|
270
666
|
end
|
271
667
|
|
@@ -273,70 +669,42 @@ class Macro
|
|
273
669
|
|
274
670
|
trigger = e.text.strip
|
275
671
|
r = tp.find_trigger trigger
|
276
|
-
r[0].new(r[1]) if r
|
672
|
+
#r[0].new(r[1]) if r
|
673
|
+
|
674
|
+
if r then
|
675
|
+
object_create(r[0],r[1])
|
676
|
+
else
|
677
|
+
raise MacroError, 'App-routes: Trigger "' + trigger + '" not found'
|
678
|
+
end
|
277
679
|
|
278
680
|
end
|
279
681
|
|
682
|
+
|
280
683
|
end
|
684
|
+
|
685
|
+
|
281
686
|
|
282
687
|
ap = ActionsNlp.new self
|
283
688
|
|
284
|
-
|
689
|
+
node.xpath('action').each do |e|
|
285
690
|
|
286
691
|
puts 'action e: ' + e.xml.inspect if @debug
|
287
692
|
puts 'e.text ' + e.text if @debug
|
288
693
|
|
289
694
|
item = e.element('item')
|
695
|
+
|
290
696
|
if item then
|
291
697
|
|
292
|
-
|
293
|
-
|
294
|
-
item.xpath('description').map do |description|
|
295
|
-
|
296
|
-
inner_lines = description.text.to_s.strip.lines
|
297
|
-
puts 'inner_lines: ' + inner_lines.inspect if @debug
|
298
|
-
|
299
|
-
action = if e.text.to_s.strip.empty? then
|
300
|
-
inner_lines.shift.strip
|
301
|
-
else
|
302
|
-
e.text.strip
|
303
|
-
end
|
304
|
-
|
305
|
-
puts 'action: ' + action.inspect if @debug
|
306
|
-
|
307
|
-
r = ap.find_action action
|
308
|
-
puts 'r: ' + r.inspect if @debug
|
309
|
-
o = r[0].new([description, self]) if r
|
310
|
-
puts 'after o' if @debug
|
311
|
-
o
|
312
|
-
|
313
|
-
end
|
314
|
-
|
315
|
-
else
|
316
|
-
|
317
|
-
action = e.text.strip
|
318
|
-
r = ap.find_action action
|
319
|
-
|
320
|
-
a = e.xpath('item/*')
|
321
|
-
|
322
|
-
h = if a.any? then
|
323
|
-
a.map {|node| [node.name.to_sym, node.text.to_s]}.to_h
|
324
|
-
else
|
325
|
-
{}
|
326
|
-
end
|
327
|
-
|
328
|
-
r = ap.find_action action
|
329
|
-
r[0].new(h) if r
|
330
|
-
|
331
|
-
end
|
698
|
+
action_to_object(ap, e, item, self)
|
332
699
|
|
333
700
|
else
|
334
701
|
|
335
702
|
action = e.text.strip
|
336
703
|
r = ap.find_action action
|
337
|
-
r[0].new(r[1]) if r
|
704
|
+
#r[0].new(r[1]) if r
|
705
|
+
self.add object_create(r[0],r[1]) if r
|
338
706
|
|
339
|
-
end
|
707
|
+
end
|
340
708
|
|
341
709
|
end
|
342
710
|
|
@@ -347,9 +715,7 @@ class Macro
|
|
347
715
|
r = cp.find_constraint e.text
|
348
716
|
puts 'found constraint ' + r.inspect if @debug
|
349
717
|
|
350
|
-
if r
|
351
|
-
r[0].new(r[1])
|
352
|
-
end
|
718
|
+
object_create(r[0], r[1]) if r
|
353
719
|
|
354
720
|
end
|
355
721
|
|
@@ -394,6 +760,30 @@ class Macro
|
|
394
760
|
def set_env()
|
395
761
|
@triggers.each(&:set_env)
|
396
762
|
end
|
763
|
+
|
764
|
+
def set_var(label, v='')
|
765
|
+
|
766
|
+
value = if v.to_f.to_s == v
|
767
|
+
v.to_f
|
768
|
+
elsif v.downcase == 'true'
|
769
|
+
true
|
770
|
+
elsif v.downcase == 'false'
|
771
|
+
false
|
772
|
+
elsif v.to_i.to_s == v
|
773
|
+
v.to_i
|
774
|
+
else
|
775
|
+
v
|
776
|
+
end
|
777
|
+
|
778
|
+
if not @local_variables.has_key? label.to_sym then
|
779
|
+
@local_variables.merge!({label.to_sym => value})
|
780
|
+
end
|
781
|
+
|
782
|
+
if @debug then
|
783
|
+
puts ("before varify; label: %s value: %s" % [label, value]).debug
|
784
|
+
end
|
785
|
+
varify(label, value)
|
786
|
+
end
|
397
787
|
|
398
788
|
def to_pc()
|
399
789
|
|
@@ -441,6 +831,7 @@ EOF
|
|
441
831
|
a << @triggers.map do |x|
|
442
832
|
|
443
833
|
puts 'x: ' + x.inspect if @debug
|
834
|
+
raise 'Macro#to_s trigger cannot be nil' if x.nil?
|
444
835
|
|
445
836
|
s =-x.to_s(colour: colour)
|
446
837
|
puts 's: ' + s.inspect if @debug
|
@@ -587,44 +978,24 @@ EOF
|
|
587
978
|
|
588
979
|
puts ('inside object h:' + h.inspect).debug if @debug
|
589
980
|
klass = Object.const_get h[:class_type]
|
590
|
-
puts klass.inspect.highlight if
|
981
|
+
puts klass.inspect.highlight if @debug
|
591
982
|
|
592
983
|
if klass == GeofenceTrigger then
|
593
|
-
puts 'GeofenceTrigger found'.highlight if
|
984
|
+
puts 'GeofenceTrigger found'.highlight if @debug
|
594
985
|
GeofenceTrigger.new(h, geofences: @geofences)
|
595
986
|
else
|
596
|
-
puts 'before klass'
|
987
|
+
puts 'before klass' if @debug
|
597
988
|
h2 = h.merge( macro: self)
|
598
|
-
puts 'h2: ' + h2.inspect
|
989
|
+
puts 'h2: ' + h2.inspect if @debug
|
599
990
|
r = klass.new h2
|
600
|
-
puts 'r:' + r.inspect
|
991
|
+
puts 'r:' + r.inspect if @debug
|
601
992
|
r
|
602
993
|
|
603
994
|
end
|
604
995
|
|
605
996
|
end
|
606
997
|
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
local_variables.map do |key, value|
|
611
|
-
|
612
|
-
puts 'value ' + value.class.to_s.to_sym.inspect
|
613
|
-
puts 'VAR_TYPES: ' + VAR_TYPES.inspect
|
614
|
-
type = VAR_TYPES[value.class.to_s.to_sym]
|
615
|
-
puts 'type: ' + type.inspect
|
616
|
-
h = {
|
617
|
-
boolean_value: false,
|
618
|
-
decimal_value: 0.0,
|
619
|
-
int_value: 0,
|
620
|
-
name: key,
|
621
|
-
string_value: '',
|
622
|
-
type: type[0]
|
623
|
-
}
|
624
|
-
h[type[1]] = value
|
625
|
-
h
|
626
|
-
end
|
627
|
-
|
628
|
-
end
|
998
|
+
|
999
|
+
|
629
1000
|
|
630
1001
|
end
|