ruby-macrodroid 0.7.7 → 0.8.1

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,148 @@
1
+ # file: ruby-macrodroid/base.rb
2
+
3
+ # This file contains the following classes:
4
+ #
5
+ # ## Object class
6
+ #
7
+ # MacroObject
8
+ #
9
+
10
+
11
+ module Params
12
+
13
+ refine Hash do
14
+
15
+ # turns keys from camelCase into snake_case
16
+
17
+ def to_snake_case(h=self)
18
+
19
+ h.inject({}) do |r, x|
20
+
21
+ key, value = x
22
+ #puts 'value: ' + value.inspect
23
+
24
+ val = if value.is_a?(Hash) then
25
+ to_snake_case(value)
26
+ elsif value.is_a?(Array) and value.first.is_a? Hash
27
+ value.map {|row| to_snake_case(row)}
28
+ else
29
+ value
30
+ end
31
+
32
+ r.merge key.to_s.sub(/^m_/,'').gsub(/[A-Z][a-z]/){|x| '_' +
33
+ x.downcase}.gsub(/[a-z][A-Z]/){|x| x[0] + '_' + x[1].downcase}\
34
+ .downcase.to_sym => val
35
+
36
+ end
37
+ end
38
+
39
+ # turns keys from snake_case to CamelCase
40
+ def to_camel_case(h=self)
41
+
42
+ h.inject({}) do |r,x|
43
+
44
+ key, value = x
45
+
46
+ val = if value.is_a?(Hash) then
47
+ to_camel_case(value)
48
+ elsif value.is_a?(Array) and value.first.is_a? Hash
49
+ value.map {|row| to_camel_case(row)}
50
+ else
51
+ value
52
+ end
53
+
54
+ r.merge({key.to_s.gsub(/(?<!^m)_[a-z]/){|x| x[-1].upcase} => val})
55
+ end
56
+
57
+ end
58
+
59
+
60
+ end
61
+
62
+ end
63
+
64
+ class MacroObject
65
+ using ColouredText
66
+
67
+ attr_reader :type, :siguid
68
+ attr_accessor :options
69
+
70
+ def initialize(h={})
71
+
72
+ $env ||= {}
73
+
74
+ @attributes = %i(constraint_list is_or_condition is_disabled siguid)
75
+ @h = {constraint_list: [], is_or_condition: false,
76
+ is_disabled: false, siguid: nil}.merge(h)
77
+ @list = []
78
+
79
+ # fetch the class name and convert from camelCase to snake_eyes
80
+ @type = self.class.to_s.sub(/Trigger|Action$/,'')\
81
+ .gsub(/\B[A-Z][a-z]/){|x| '_' + x.downcase}\
82
+ .gsub(/[a-z][A-Z]/){|x| x[0] + '_' + x[1].downcase}\
83
+ .downcase.to_sym
84
+ @constraints = []
85
+ end
86
+
87
+ def to_h()
88
+
89
+ h = @h
90
+
91
+ h2 = h.inject({}) do |r,x|
92
+ puts 'x: ' + x.inspect if @debug
93
+ key, value = x
94
+ puts 'key: ' + key.inspect if @debug
95
+ new_key = key.to_s.gsub(/\w_\w/){|x| x[0] + x[-1].upcase}
96
+ new_key = new_key.prepend 'm_' unless @list.include? new_key
97
+ new_key = 'm_SIGUID' if new_key == 'm_siguid'
98
+ r.merge(new_key => value)
99
+ end
100
+
101
+ h2.merge('m_classType' => self.class.to_s)
102
+
103
+ end
104
+
105
+ def siguid()
106
+ @h[:siguid]
107
+ end
108
+
109
+ def to_s(colour: false)
110
+
111
+ h = @h.clone
112
+ h.delete :macro
113
+ @s ||= "#<%s %s>" % [self.class, h.inspect]
114
+ operator = @h[:is_or_condition] ? 'OR' : 'AND'
115
+ constraints = @constraints.map \
116
+ {|x| x.to_summary(colour: colour)}.join(" %s " % operator)
117
+
118
+ @s + constraints
119
+
120
+ end
121
+
122
+ alias to_summary to_s
123
+
124
+ protected
125
+
126
+ def filter(options, h)
127
+
128
+ (h.keys - (options.keys + @attributes.to_a)).each {|key| h.delete key }
129
+ return h
130
+
131
+ end
132
+
133
+ def uuid()
134
+ UUID.new.generate
135
+ end
136
+
137
+ def object(h={})
138
+
139
+ puts ('inside object h:' + h.inspect).debug if @debug
140
+ klass = Object.const_get h[:class_type]
141
+ puts klass.inspect.highlight if $debug
142
+
143
+ klass.new h
144
+
145
+ end
146
+
147
+ end
148
+
@@ -0,0 +1,1558 @@
1
+ # file: ruby-macrodroid/constraints.rb
2
+
3
+ # This file contains the following classes:
4
+ #
5
+ #
6
+ # ## Trigger classes
7
+ #
8
+ # Trigger WebHookTrigger WifiConnectionTrigger
9
+ # ApplicationInstalledRemovedTrigger ApplicationLaunchedTrigger
10
+ # BatteryLevelTrigger BatteryTemperatureTrigger PowerButtonToggleTrigger
11
+ # ExternalPowerTrigger CallActiveTrigger IncomingCallTrigger
12
+ # OutgoingCallTrigger CallEndedTrigger CallMissedTrigger IncomingSMSTrigger
13
+ # WebHookTrigger WifiConnectionTrigger BluetoothTrigger HeadphonesTrigger
14
+ # SignalOnOffTrigger UsbDeviceConnectionTrigger WifiSSIDTrigger
15
+ # CalendarTrigger TimerTrigger StopwatchTrigger DayTrigger
16
+ # RegularIntervalTrigger DeviceEventsTrigger AirplaneModeTrigger
17
+ # AutoSyncChangeTrigger DayDreamTrigger DockTrigger FailedLoginTrigger
18
+ # GPSEnabledTrigger MusicPlayingTrigger DeviceUnlockedTrigger
19
+ # AutoRotateChangeTrigger ClipboardChangeTrigger BootTrigger
20
+ # IntentReceivedTrigger NotificationTrigger ScreenOnOffTrigger
21
+ # SilentModeTrigger WeatherTrigger GeofenceTrigger SunriseSunsetTrigger
22
+ # SensorsTrigger ActivityRecognitionTrigger ProximityTrigger
23
+ # ShakeDeviceTrigger FlipDeviceTrigger OrientationTrigger
24
+ # FloatingButtonTrigger ShortcutTrigger VolumeButtonTrigger
25
+ # MediaButtonPressedTrigger SwipeTrigger
26
+ #
27
+
28
+
29
+ class Trigger < MacroObject
30
+ using Params
31
+
32
+ attr_reader :constraints
33
+
34
+ def initialize(h={})
35
+ super({fakeIcon: 0}.merge(h))
36
+ @list << 'fakeIcon'
37
+
38
+ # fetch the constraints
39
+ @constraints = @h[:constraint_list].map do |constraint|
40
+ object(constraint.to_snake_case)
41
+ end
42
+
43
+ end
44
+
45
+ def match?(detail={}, model=nil)
46
+
47
+ # only match where the key exists in the trigger object
48
+ detail.select {|k,v| @h.include? k }.all? {|key,value| @h[key] == value}
49
+
50
+ end
51
+
52
+ end
53
+
54
+
55
+
56
+
57
+ # Category: Applications
58
+ #
59
+ # Also known as Wifi State Change
60
+ #
61
+ # wifi_state options:
62
+ # 0 - Wifi Enabled
63
+ # 1 - Wifi Disabled
64
+ # 2 - Connected to network
65
+ # ssid_list options:
66
+ # ["Any Network"]
67
+ # ["some Wifi SSID"] - 1 or more SSID can be supplied
68
+ # 3 - Disconnected from network
69
+ # ssid_list options:
70
+ # ["Any Network"]
71
+ # ["some Wifi SSID"] - 1 or more SSID can be supplied
72
+
73
+ class WifiConnectionTrigger < Trigger
74
+
75
+ def initialize(h={})
76
+
77
+ options = {
78
+ ssid_list: [""],
79
+ wifi_state: 2
80
+ }
81
+
82
+ super(options.merge h)
83
+
84
+ end
85
+
86
+ def to_s(colour: false)
87
+ 'WifiConnectionTrigger ' + @h.inspect
88
+ end
89
+
90
+ alias to_summary to_s
91
+ end
92
+
93
+ # Category: Applications
94
+ #
95
+ class ApplicationInstalledRemovedTrigger < Trigger
96
+
97
+ def initialize(h={})
98
+
99
+ options = {
100
+ application_name_list: [],
101
+ package_name_list: [],
102
+ installed: true,
103
+ application_option: 0,
104
+ updated: false
105
+ }
106
+
107
+ super(options.merge h)
108
+
109
+ end
110
+
111
+ def to_s(colour: false)
112
+ 'ApplicationInstalledRemovedTrigger ' + @h.inspect
113
+ end
114
+
115
+ alias to_summary to_s
116
+ end
117
+
118
+ # Category: Applications
119
+ #
120
+ class ApplicationLaunchedTrigger < Trigger
121
+
122
+ def initialize(h={})
123
+
124
+ options = {
125
+ application_name_list: ["Chrome"],
126
+ package_name_list: ["com.android.chrome"],
127
+ launched: true
128
+ }
129
+
130
+ super(options.merge h)
131
+
132
+ end
133
+
134
+ def to_s(colour: false)
135
+ 'ApplicationLaunchedTrigger ' + @h.inspect
136
+ end
137
+
138
+ alias to_summary to_s
139
+ end
140
+
141
+ # Category: Battery/Power
142
+ #
143
+ class BatteryLevelTrigger < Trigger
144
+
145
+ def initialize(h={})
146
+
147
+ options = {
148
+ battery_level: 50,
149
+ decreases_to: true,
150
+ option: 0
151
+ }
152
+
153
+ super(options.merge h)
154
+
155
+ end
156
+
157
+ def to_s(colour: false)
158
+ operator = @h[:decreases_to] ? '<=' : '>='
159
+ "Battery %s %s%%" % [operator, @h[:battery_level]]
160
+ end
161
+
162
+ end
163
+
164
+ # Category: Battery/Power
165
+ #
166
+ class BatteryTemperatureTrigger < Trigger
167
+
168
+ def initialize(h={})
169
+
170
+ options = {
171
+ decreases_to: true,
172
+ option: 0,
173
+ temperature: 30
174
+ }
175
+
176
+ super(options.merge h)
177
+
178
+ end
179
+
180
+ def to_s(colour: false)
181
+ 'BatteryTemperatureTrigger ' + @h.inspect
182
+ end
183
+
184
+ alias to_summary to_s
185
+ end
186
+
187
+ # Category: Battery/Power
188
+ #
189
+ class PowerButtonToggleTrigger < Trigger
190
+
191
+ def initialize(h={})
192
+
193
+ options = {
194
+ num_toggles: 3
195
+ }
196
+
197
+ super(options.merge h)
198
+
199
+ end
200
+
201
+ def to_s(colour: false)
202
+ 'PowerButtonToggleTrigger ' + @h.inspect
203
+ end
204
+
205
+ alias to_summary to_s
206
+ end
207
+
208
+
209
+ # Category: Battery/Power
210
+ #
211
+ class ExternalPowerTrigger < Trigger
212
+
213
+ def initialize(h={})
214
+
215
+ options = {
216
+ power_connected_options: [true, true, true],
217
+ has_set_usb_option: true,
218
+ power_connected: true,
219
+ has_set_new_power_connected_options: true
220
+ }
221
+
222
+ super(options.merge h)
223
+
224
+ end
225
+
226
+ def to_s(colour: false)
227
+
228
+ return 'Power Disconnected' unless @h[:power_connected]
229
+
230
+ status = 'Power Connectd'
231
+ options = if @h[:power_connected_options].all? then
232
+ 'Any'
233
+ else
234
+
235
+ a = ['Wired (Fast Charge)', 'Wireless', 'Wired (Slow Charge)']
236
+ @h[:power_connected_options].map.with_index {|x,i| x ? i : nil}\
237
+ .compact.map {|i| a[i] }.join(' + ')
238
+
239
+ end
240
+
241
+ "%s: %s" % [status, options]
242
+
243
+ end
244
+
245
+ alias to_summary to_s
246
+
247
+ end
248
+
249
+ # Category: Call/SMS
250
+ #
251
+ class CallActiveTrigger < Trigger
252
+
253
+ def initialize(h={})
254
+
255
+ options = {
256
+ contact_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}],
257
+ secondary_class_type: 'CallActiveTrigger',
258
+ signal_on: true
259
+ }
260
+
261
+ super(options.merge h)
262
+
263
+ end
264
+
265
+ def to_s(colour: false)
266
+ 'CallActiveTrigger ' + @h.inspect
267
+ end
268
+
269
+ alias to_summary to_s
270
+ end
271
+
272
+ # Category: Call/SMS
273
+ #
274
+ class IncomingCallTrigger < Trigger
275
+
276
+ def initialize(h={})
277
+
278
+ options = {
279
+ incoming_call_from_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}],
280
+ group_id_list: [],
281
+ group_name_list: [],
282
+ option: 0,
283
+ phone_number_exclude: false
284
+ }
285
+
286
+ super(options.merge h)
287
+
288
+ end
289
+
290
+ def to_s(colour: false)
291
+ caller = @h[:incoming_call_from_list].map {|x| "%s" % x[:name]}.join(', ')
292
+ "Call Incoming [%s]" % caller
293
+ end
294
+
295
+ alias to_summary to_s
296
+ end
297
+
298
+ # Category: Call/SMS
299
+ #
300
+ class OutgoingCallTrigger < Trigger
301
+
302
+ def initialize(h={})
303
+
304
+ options = {
305
+ outgoing_call_to_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}],
306
+ group_id_list: [],
307
+ group_name_list: [],
308
+ option: 0,
309
+ phone_number_exclude: false
310
+ }
311
+
312
+ super(options.merge h)
313
+
314
+ end
315
+
316
+ def to_s(colour: false)
317
+ 'OutgoingCallTrigger ' + @h.inspect
318
+ end
319
+
320
+ alias to_summary to_s
321
+ end
322
+
323
+ # Category: Call/SMS
324
+ #
325
+ class CallEndedTrigger < Trigger
326
+
327
+ def initialize(h={})
328
+
329
+ options = {
330
+ contact_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}],
331
+ group_id_list: [],
332
+ group_name_list: [],
333
+ option: 0,
334
+ phone_number_exclude: false
335
+ }
336
+
337
+ super(options.merge h)
338
+
339
+ end
340
+
341
+ def to_s(colour: false)
342
+ 'CallEndedTrigger ' + @h.inspect
343
+ end
344
+
345
+ alias to_summary to_s
346
+ end
347
+
348
+ # Category: Call/SMS
349
+ #
350
+ class CallMissedTrigger < Trigger
351
+
352
+ def initialize(h={})
353
+
354
+ options = {
355
+ contact_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}]
356
+ }
357
+
358
+ super(options.merge h)
359
+
360
+ end
361
+
362
+ def to_s(colour: false)
363
+ 'CallMissedTrigger ' + @h.inspect
364
+ end
365
+
366
+ alias to_summary to_s
367
+ end
368
+
369
+ # Category: Call/SMS
370
+ #
371
+ class IncomingSMSTrigger < Trigger
372
+
373
+ def initialize(h={})
374
+
375
+ options = {
376
+ sms_from_list: [{:m_id=>"-2", :m_lookupKey=>"-2", :m_name=>"[Any Number]"}],
377
+ group_id_list: [],
378
+ group_name_list: [],
379
+ sms_content: '',
380
+ option: 0,
381
+ excludes: false,
382
+ exact_match: false,
383
+ enable_regex: false,
384
+ sms_number_exclude: false
385
+ }
386
+
387
+ super(options.merge h)
388
+
389
+ end
390
+
391
+ def to_s(colour: false)
392
+ 'IncomingSMSTrigger ' + @h.inspect
393
+ end
394
+
395
+ alias to_summary to_s
396
+ end
397
+
398
+ # Category: Connectivity
399
+ #
400
+ class WebHookTrigger < Trigger
401
+
402
+ def initialize(h={})
403
+
404
+ options = {
405
+ identifier: ''
406
+ }
407
+
408
+ super(options.merge h)
409
+
410
+ end
411
+
412
+ def to_s(colour: false)
413
+
414
+ url = "https://trigger.macrodroid.com/%s/%s" % \
415
+ [@h[:macro].deviceid, @h[:identifier]]
416
+ @s = 'WebHook (Url)' + "\n " + url
417
+ super()
418
+
419
+ end
420
+
421
+ alias to_summary to_s
422
+ end
423
+
424
+ # Category: Connectivity
425
+ #
426
+ class WifiConnectionTrigger < Trigger
427
+
428
+ def initialize(h={})
429
+
430
+ options = {
431
+ ssid_list: [],
432
+ wifi_state: 0
433
+ }
434
+
435
+ super(options.merge h)
436
+
437
+ end
438
+
439
+ def to_s(colour: false)
440
+ access_point = @h[:ssid_list].first
441
+ 'Connected to network ' + access_point
442
+ end
443
+
444
+ alias to_summary to_s
445
+ end
446
+
447
+ # Category: Connectivity
448
+ #
449
+ class BluetoothTrigger < Trigger
450
+
451
+ def initialize(h={})
452
+
453
+ options = {
454
+ device_name: 'Any Device',
455
+ bt_state: 0,
456
+ any_device: false
457
+ }
458
+
459
+ super(options.merge h)
460
+
461
+ end
462
+
463
+ def to_s(colour: false)
464
+ 'BluetoothTrigger ' + @h.inspect
465
+ end
466
+
467
+ alias to_summary to_s
468
+ end
469
+
470
+ # Category: Connectivity
471
+ #
472
+ class HeadphonesTrigger < Trigger
473
+
474
+ def initialize(h={})
475
+
476
+ options = {
477
+ headphones_connected: true,
478
+ mic_option: 0
479
+ }
480
+
481
+ super(options.merge h)
482
+
483
+ end
484
+
485
+ def to_s(colour: false)
486
+ 'HeadphonesTrigger ' + @h.inspect
487
+ end
488
+
489
+ alias to_summary to_s
490
+ end
491
+
492
+ # Category: Connectivity
493
+ #
494
+ class SignalOnOffTrigger < Trigger
495
+
496
+ def initialize(h={})
497
+
498
+ options = {
499
+ signal_on: true
500
+ }
501
+
502
+ super(options.merge h)
503
+
504
+ end
505
+
506
+ def to_s(colour: false)
507
+ 'SignalOnOffTrigger ' + @h.inspect
508
+ end
509
+
510
+ alias to_summary to_s
511
+ end
512
+
513
+ # Category: Connectivity
514
+ #
515
+ class UsbDeviceConnectionTrigger < Trigger
516
+
517
+ def initialize(h={})
518
+
519
+ options = {
520
+ option: 0
521
+ }
522
+
523
+ super(options.merge h)
524
+
525
+ end
526
+
527
+ def to_s(colour: false)
528
+ 'UsbDeviceConnectionTrigger ' + @h.inspect
529
+ end
530
+
531
+ alias to_summary to_s
532
+ end
533
+
534
+ # Category: Connectivity
535
+ #
536
+ # Also known as Wifi SSID Transition
537
+ #
538
+ # options:
539
+ # in_range: true | false
540
+ # wifi_cell_info: {display_name: "some Wifi SSID",
541
+ # ssid: "some Wifi SSID"} - 1 or more allowed
542
+ #
543
+ class WifiSSIDTrigger < Trigger
544
+
545
+ def initialize(h={})
546
+
547
+ options = {
548
+ wifi_cell_info_list: [{:display_name=>"", :ssid=>""}],
549
+ ssid_list: [],
550
+ in_range: true
551
+ }
552
+
553
+ super(options.merge h)
554
+
555
+ end
556
+
557
+ def to_h()
558
+
559
+ h = super()
560
+ val = h[:m_inRange]
561
+
562
+ h[:m_InRange] = val
563
+ h.delete :m_inRange
564
+
565
+ return h
566
+
567
+ end
568
+
569
+ def to_s(colour: false)
570
+ 'WifiSSIDTrigger ' + @h.inspect
571
+ end
572
+
573
+ alias to_summary to_s
574
+ end
575
+
576
+ # Category: Date/Time
577
+ #
578
+ class CalendarTrigger < Trigger
579
+
580
+ def initialize(h={})
581
+
582
+ options = {
583
+ title_text: '',
584
+ detail_text: '',
585
+ calendar_name: 'Contacts',
586
+ calendar_id: '3',
587
+ availability: 0,
588
+ check_in_advance: false,
589
+ advance_time_seconds: 0,
590
+ event_start: true,
591
+ ignore_all_day: false,
592
+ negative_advance_check: false,
593
+ enable_regex: false
594
+ }
595
+
596
+ super(options.merge h)
597
+
598
+ end
599
+
600
+ def to_s(colour: false)
601
+ 'CalendarTrigger ' + @h.inspect
602
+ end
603
+
604
+ alias to_summary to_s
605
+ end
606
+
607
+ # Category: Date/Time
608
+ #
609
+ class TimerTrigger < Trigger
610
+ using ColouredText
611
+
612
+
613
+ def initialize(h={})
614
+
615
+ puts 'TimerTrigger h: ' + h.inspect if $debug
616
+
617
+ if h[:days] then
618
+
619
+ days = [false] * 7
620
+
621
+ h[:days].split(/, */).each do |x|
622
+
623
+ r = Date::DAYNAMES.grep /#{x}/i
624
+ i = Date::DAYNAMES.index(r.first)
625
+ days[i-1] = true
626
+
627
+ end
628
+
629
+ h[:days_of_week] = days
630
+
631
+ end
632
+
633
+ if h[:time] then
634
+
635
+ t = Time.parse(h[:time])
636
+ h[:hour], h[:minute] = t.hour, t.min
637
+
638
+ end
639
+
640
+ #puts ('h: ' + h.inspect).debug
641
+
642
+ @options = {
643
+ alarm_id: uuid(),
644
+ days_of_week: [false, false, false, false, false, false, false],
645
+ minute: 10,
646
+ hour: 7,
647
+ use_alarm: false
648
+ }
649
+
650
+ #super(options.merge filter(options, h))
651
+ super(@options.merge h)
652
+
653
+ end
654
+
655
+ def match?(detail={time: $env[:time]}, model=nil)
656
+
657
+ time() == detail[:time]
658
+
659
+ end
660
+
661
+ # sets the environmental conditions for this trigger to fire
662
+ #
663
+ def set_env()
664
+ $env[:time] = time()
665
+ end
666
+
667
+ def to_pc()
668
+ "time.is? '%s'" % self.to_s.gsub(',', ' or')
669
+ end
670
+
671
+ def to_s(colour: false)
672
+
673
+ dow = @h[:days_of_week]
674
+
675
+ wd = Date::ABBR_DAYNAMES
676
+ a = (wd[1..-1] << wd.first)
677
+
678
+ a2 = dow.map.with_index.to_a
679
+ start = a2.find {|x,i| x}.last
680
+ r = a2[start..-1].take_while {|x,i| x == true}
681
+ r2 = a2[start..-1].select {|x,i| x}
682
+
683
+ days = if r == r2 then
684
+
685
+ x1, x2 = a2[start].last, a2[r.length-1].last
686
+
687
+ if (x2 - x1) >= 2 then
688
+ "%s-%s" % [a[x1],a[x2]]
689
+ else
690
+ a.zip(dow).select {|_,b| b}.map(&:first).join(', ')
691
+ end
692
+ else
693
+ a.zip(dow).select {|_,b| b}.map(&:first).join(', ')
694
+ end
695
+
696
+ time = Time.parse("%s:%s" % [@h[:hour], @h[:minute]]).strftime("%H:%M")
697
+
698
+ "%s %s" % [time, days]
699
+ end
700
+
701
+ alias to_summary to_s
702
+
703
+ private
704
+
705
+ def time()
706
+
707
+ a = @h[:days_of_week].clone
708
+ a.unshift a.pop
709
+
710
+ dow = a.map.with_index {|x, i| x ? i : nil }.compact.join(',')
711
+ s = "%s %s * * %s" % [@h[:minute], @h[:hour], dow]
712
+ recent_time = ($env && $env[:time]) ? $env[:time] : Time.now
713
+ ChronicCron.new(s, recent_time).to_time
714
+
715
+ end
716
+
717
+ end
718
+
719
+ # Category: Date/Time
720
+ #
721
+ class StopwatchTrigger < Trigger
722
+
723
+ def initialize(h={})
724
+
725
+ options = {
726
+ stopwatch_name: 'timer1',
727
+ seconds: 240
728
+ }
729
+
730
+ super(options.merge h)
731
+
732
+ end
733
+
734
+ def to_s(colour: false)
735
+ 'StopwatchTrigger ' + @h.inspect
736
+ end
737
+
738
+ alias to_summary to_s
739
+ end
740
+
741
+ # Category: Date/Time
742
+ #
743
+ # Also known as Day of Week/Month
744
+ #
745
+ # month_of_year equal to 0 means it occurs every month
746
+ # day_of_week starts with a Monday (value is 0)
747
+ #
748
+ class DayTrigger < Trigger
749
+
750
+ def initialize(h={})
751
+
752
+ options = {
753
+ alarm_id: uuid(),
754
+ hour: 9,
755
+ minute: 0,
756
+ month_of_year: 0,
757
+ option: 0,
758
+ day_of_week: 2,
759
+ day_of_month: 0,
760
+ use_alarm: false
761
+ }
762
+
763
+ super(options.merge h)
764
+
765
+ end
766
+
767
+ def to_s(colour: false)
768
+ 'DayTrigger ' + @h.inspect
769
+ end
770
+
771
+ alias to_summary to_s
772
+ end
773
+
774
+ # Category: Date/Time
775
+ #
776
+ # Regular Interval
777
+ #
778
+ class RegularIntervalTrigger < Trigger
779
+
780
+ def initialize(h={})
781
+
782
+ options = {
783
+ ignore_reference_start_time: false,
784
+ minutes: 0,
785
+ seconds: 7200,
786
+ start_hour: 9,
787
+ start_minute: 10,
788
+ use_alarm: false
789
+ }
790
+
791
+ super(options.merge h)
792
+
793
+ end
794
+
795
+ def to_s(colour: false)
796
+
797
+ interval = Subunit.new(units={minutes:60, hours:60}, \
798
+ seconds: @h[:seconds]).strfunit("%c")
799
+ 'Regular Interval ' + "\n Interval: " + interval
800
+
801
+ end
802
+
803
+ alias to_summary to_s
804
+ end
805
+
806
+ class DeviceEventsTrigger < Trigger
807
+
808
+ def initialize(h={})
809
+ super(h)
810
+ @group = 'device_events'
811
+ end
812
+
813
+ end
814
+
815
+ # Category: Device Events
816
+ #
817
+ # Airplane Mode Changed
818
+ #
819
+ # options:
820
+ # Airplane Mode Enabled
821
+ # Airplane Mode Disabled
822
+ #
823
+ # shorthand example:
824
+ # airplanemode: enabled
825
+ #
826
+ class AirplaneModeTrigger < DeviceEventsTrigger
827
+
828
+ def initialize(h={})
829
+
830
+ options = {
831
+ airplane_mode_enabled: true
832
+ }
833
+
834
+ super(options.merge h)
835
+
836
+ end
837
+
838
+ def to_s(colour: false)
839
+ 'AirplaneModeTrigger ' + @h.inspect
840
+ end
841
+
842
+ alias to_summary to_s
843
+ end
844
+
845
+ # Category: Device Events
846
+ #
847
+ class AutoSyncChangeTrigger < DeviceEventsTrigger
848
+
849
+ def initialize(h={})
850
+
851
+ options = {
852
+ option: 0
853
+ }
854
+
855
+ super(options.merge h)
856
+
857
+ end
858
+
859
+ def to_s(colour: false)
860
+ 'AutoSyncChangeTrigger ' + @h.inspect
861
+ end
862
+
863
+ alias to_summary to_s
864
+ end
865
+
866
+ # Category: Device Events
867
+ #
868
+ class DayDreamTrigger < DeviceEventsTrigger
869
+
870
+ def initialize(h={})
871
+
872
+ options = {
873
+ day_dream_enabled: true
874
+ }
875
+
876
+ super(options.merge h)
877
+
878
+ end
879
+
880
+ def to_s(colour: false)
881
+ 'DayDreamTrigger ' + @h.inspect
882
+ end
883
+
884
+ alias to_summary to_s
885
+ end
886
+
887
+ # Category: Device Events
888
+ #
889
+ class DockTrigger < DeviceEventsTrigger
890
+
891
+ def initialize(h={})
892
+
893
+ options = {
894
+ dock_type: 0
895
+ }
896
+
897
+ super(options.merge h)
898
+
899
+ end
900
+
901
+ def to_s(colour: false)
902
+ 'DockTrigger ' + @h.inspect
903
+ end
904
+
905
+ alias to_summary to_s
906
+ end
907
+
908
+ # Category: Device Events
909
+ #
910
+ class FailedLoginTrigger < DeviceEventsTrigger
911
+
912
+ def initialize(h={})
913
+
914
+ options = {
915
+ num_failures: 1
916
+ }
917
+
918
+ super(options.merge h)
919
+
920
+ end
921
+
922
+ def to_pc()
923
+ 'failed_login?'
924
+ end
925
+
926
+ def to_s(colour: false)
927
+ 'Failed Login Attempt'
928
+ end
929
+ end
930
+
931
+ # Category: Device Events
932
+ #
933
+ class GPSEnabledTrigger < DeviceEventsTrigger
934
+
935
+ def initialize(h={})
936
+
937
+ options = {
938
+ gps_mode_enabled: true
939
+ }
940
+
941
+ super(options.merge h)
942
+
943
+ end
944
+
945
+ def to_s(colour: false)
946
+ 'GPSEnabledTrigger ' + @h.inspect
947
+ end
948
+
949
+ alias to_summary to_s
950
+ end
951
+
952
+ # Category: Device Events
953
+ #
954
+ class MusicPlayingTrigger < DeviceEventsTrigger
955
+
956
+ def initialize(h={})
957
+
958
+ options = {
959
+ option: 0
960
+ }
961
+
962
+ super(options.merge h)
963
+
964
+ end
965
+
966
+ def to_s(colour: false)
967
+ 'MusicPlayingTrigger ' + @h.inspect
968
+ end
969
+
970
+ alias to_summary to_s
971
+ end
972
+
973
+
974
+ # Category: Device Events
975
+ #
976
+ class DeviceUnlockedTrigger < DeviceEventsTrigger
977
+
978
+ def initialize(h={})
979
+
980
+ options = {
981
+ }
982
+
983
+ super(options.merge h)
984
+
985
+ end
986
+
987
+ def to_s(colour: false)
988
+ 'Screen Unlocked'
989
+ end
990
+
991
+ alias to_summary to_s
992
+
993
+ end
994
+
995
+ # Category: Device Events
996
+ #
997
+ class AutoRotateChangeTrigger < DeviceEventsTrigger
998
+
999
+ def initialize(h={})
1000
+
1001
+ options = {
1002
+ option: 0
1003
+ }
1004
+
1005
+ super(options.merge h)
1006
+
1007
+ end
1008
+
1009
+ def to_s(colour: false)
1010
+ 'AutoRotateChangeTrigger ' + @h.inspect
1011
+ end
1012
+
1013
+ alias to_summary to_s
1014
+ end
1015
+
1016
+ # Category: Device Events
1017
+ #
1018
+ class ClipboardChangeTrigger < DeviceEventsTrigger
1019
+
1020
+ def initialize(h={})
1021
+
1022
+ options = {
1023
+ text: '',
1024
+ enable_regex: false
1025
+ }
1026
+
1027
+ super(options.merge h)
1028
+
1029
+ end
1030
+
1031
+ def to_s(colour: false)
1032
+ 'ClipboardChangeTrigger ' + @h.inspect
1033
+ end
1034
+
1035
+ alias to_summary to_s
1036
+ end
1037
+
1038
+ # Category: Device Events
1039
+ #
1040
+ class BootTrigger < DeviceEventsTrigger
1041
+
1042
+ def initialize(h={})
1043
+
1044
+ options = {
1045
+ }
1046
+
1047
+ super(options.merge h)
1048
+
1049
+ end
1050
+
1051
+ def to_s(colour: false)
1052
+ 'BootTrigger ' + @h.inspect
1053
+ end
1054
+
1055
+ alias to_summary to_s
1056
+ end
1057
+
1058
+ # Category: Device Events
1059
+ #
1060
+ class IntentReceivedTrigger < DeviceEventsTrigger
1061
+
1062
+ def initialize(h={})
1063
+
1064
+ options = {
1065
+ action: '',
1066
+ extra_params: [],
1067
+ extra_value_patterns: [],
1068
+ extra_variables: [],
1069
+ enable_regex: false
1070
+ }
1071
+
1072
+ super(options.merge h)
1073
+
1074
+ end
1075
+
1076
+ def to_s(colour: false)
1077
+ 'IntentReceivedTrigger ' + @h.inspect
1078
+ end
1079
+
1080
+ alias to_summary to_s
1081
+ end
1082
+
1083
+ # Category: Device Events
1084
+ #
1085
+ class NotificationTrigger < DeviceEventsTrigger
1086
+
1087
+ def initialize(h={})
1088
+
1089
+ options = {
1090
+ text_content: '',
1091
+ package_name_list: ["Any Application"],
1092
+ application_name_list: ["Any Application"],
1093
+ exclude_apps: false,
1094
+ ignore_ongoing: true,
1095
+ option: 0,
1096
+ exact_match: false,
1097
+ excludes: false,
1098
+ sound_option: 0,
1099
+ supress_multiples: true,
1100
+ enable_regex: false
1101
+ }
1102
+
1103
+ super(options.merge h)
1104
+
1105
+ end
1106
+
1107
+ def to_s(colour: false)
1108
+ s = (@h[:package_name_list] + @h[:application_name_list]).uniq.join(', ')
1109
+ 'Notification Received ' + "\n Any Content (%s)" % s
1110
+ end
1111
+
1112
+ alias to_summary to_s
1113
+ end
1114
+
1115
+ # Category: Device Events
1116
+ #
1117
+ class ScreenOnOffTrigger < DeviceEventsTrigger
1118
+
1119
+ def initialize(h={})
1120
+
1121
+ options = {
1122
+ screen_on: true
1123
+ }
1124
+
1125
+ super(options.merge h)
1126
+
1127
+ end
1128
+
1129
+ def to_s(colour: false)
1130
+ 'Screen ' + (@h[:screen_on] ? 'On' : 'Off')
1131
+ end
1132
+
1133
+ alias to_summary to_s
1134
+
1135
+ end
1136
+
1137
+ # Category: Device Events
1138
+ #
1139
+ class SilentModeTrigger < DeviceEventsTrigger
1140
+
1141
+ def initialize(h={})
1142
+
1143
+ options = {
1144
+ silent_enabled: true
1145
+ }
1146
+
1147
+ super(options.merge h)
1148
+
1149
+ end
1150
+
1151
+ def to_s(colour: false)
1152
+ 'SilentModeTrigger ' + @h.inspect
1153
+ end
1154
+
1155
+ alias to_summary to_s
1156
+ end
1157
+
1158
+ # Category: Location
1159
+ #
1160
+ class WeatherTrigger < Trigger
1161
+
1162
+ def initialize(h={})
1163
+
1164
+ options = {
1165
+ humidity_above: true,
1166
+ humidity_value: 50,
1167
+ option: 4,
1168
+ temp_below: true,
1169
+ temp_celcius: true,
1170
+ temperature: 0,
1171
+ weather_condition: 0,
1172
+ wind_speed_above: true,
1173
+ wind_speed_value: 0,
1174
+ wind_speed_value_mph: 0
1175
+ }
1176
+
1177
+ super(options.merge h)
1178
+
1179
+ end
1180
+
1181
+ def to_s(colour: false)
1182
+ 'WeatherTrigger ' + @h.inspect
1183
+ end
1184
+
1185
+ alias to_summary to_s
1186
+ end
1187
+
1188
+ # Category: Location
1189
+ #
1190
+ class GeofenceTrigger < Trigger
1191
+
1192
+ def initialize( h={}, geofences: {})
1193
+
1194
+ if h[:name] then
1195
+ puts ('geofences2: ' + geofences.inspect) if $debug
1196
+ found = geofences.find {|x| x.name.downcase == h[:name].downcase}
1197
+ h[:geofence_id] = found.id if found
1198
+
1199
+ end
1200
+
1201
+ options = {
1202
+ update_rate_text: '5 Minutes',
1203
+ geofence_id: '',
1204
+ geofence_update_rate_minutes: 5,
1205
+ trigger_from_unknown: false,
1206
+ enter_area: true
1207
+ }
1208
+
1209
+ super(options.merge filter(options, h))
1210
+ @geofences = geofences
1211
+
1212
+ end
1213
+
1214
+ def to_s(colour: false)
1215
+
1216
+ if $debug then
1217
+ puts ' @geofences: ' + @geofences.inspect
1218
+ puts '@h: ' + @h.inspect
1219
+ puts '@h[:geofence_id]: ' + @h[:geofence_id].inspect
1220
+ end
1221
+
1222
+ direction = @h[:enter_area] ? 'Entry' : 'Exit'
1223
+
1224
+ found = @geofences.find {|x| x.id == @h[:geofence_id]}
1225
+ puts 'found: ' + found.inspect if @debug
1226
+ label = found ? found.name : 'error: name not found'
1227
+
1228
+ "Geofence %s (%s)" % [direction, label]
1229
+
1230
+ end
1231
+
1232
+ end
1233
+
1234
+ # Category: Location
1235
+ #
1236
+ class SunriseSunsetTrigger < Trigger
1237
+
1238
+ def initialize(h={})
1239
+
1240
+ options = {
1241
+ option: 0,
1242
+ time_adjust_seconds: 0
1243
+ }
1244
+
1245
+ super(options.merge h)
1246
+
1247
+ end
1248
+
1249
+ def to_s(colour: false)
1250
+ 'SunriseSunsetTrigger ' + @h.inspect
1251
+ end
1252
+
1253
+ alias to_summary to_s
1254
+ end
1255
+
1256
+
1257
+ class SensorsTrigger < Trigger
1258
+
1259
+ def initialize(h={})
1260
+ super(h)
1261
+ @group = 'sensors'
1262
+ end
1263
+
1264
+ end
1265
+
1266
+ # Category: Sensors
1267
+ #
1268
+ class ActivityRecognitionTrigger < SensorsTrigger
1269
+
1270
+ def initialize(h={})
1271
+
1272
+ options = {
1273
+ confidence_level: 50,
1274
+ selected_index: 1
1275
+ }
1276
+
1277
+ super(options.merge h)
1278
+
1279
+ @activity = ['In Vehicle', 'On Bicycle', 'Running', 'Walking', 'Still']
1280
+
1281
+ end
1282
+
1283
+ def to_s(colour: false)
1284
+ activity = @activity[@h[:selected_index]]
1285
+ 'Activity - ' + activity
1286
+ end
1287
+
1288
+ def to_summary(colour: false)
1289
+
1290
+ activity = @activity[@h[:selected_index]]
1291
+ s = if activity.length > 10 then
1292
+ activity[0..7] + '..'
1293
+ else
1294
+ activity
1295
+ end
1296
+
1297
+ 'Activity - ' + s
1298
+
1299
+ end
1300
+
1301
+ end
1302
+
1303
+ # Category: Sensors
1304
+ #
1305
+ class ProximityTrigger < SensorsTrigger
1306
+
1307
+ def initialize(h={})
1308
+
1309
+ if h[:distance] then
1310
+
1311
+ case h[:distance].to_sym
1312
+ when :near
1313
+ options[:near] = true
1314
+ end
1315
+ end
1316
+
1317
+ options = {
1318
+ near: true,
1319
+ selected_option: 0
1320
+ }
1321
+
1322
+ super(options.merge h)
1323
+
1324
+ end
1325
+
1326
+ def to_s(colour: false)
1327
+
1328
+ distance = if @h[:near] then
1329
+ 'Near'
1330
+ else
1331
+ 'Far'
1332
+ end
1333
+
1334
+ "Proximity Sensor (%s)" % distance
1335
+ end
1336
+
1337
+ alias to_summary to_s
1338
+
1339
+ end
1340
+
1341
+ # Category: Sensors
1342
+ #
1343
+ class ShakeDeviceTrigger < SensorsTrigger
1344
+
1345
+ def initialize(h={})
1346
+
1347
+ options = {
1348
+ }
1349
+
1350
+ super(options.merge h)
1351
+
1352
+ end
1353
+
1354
+ def to_pc()
1355
+ 'shake_device?'
1356
+ end
1357
+
1358
+ def to_s(colour: false)
1359
+ 'Shake Device'
1360
+ end
1361
+
1362
+ end
1363
+
1364
+ # Category: Sensors
1365
+ #
1366
+ # options:
1367
+ # Face Up -> Face Down
1368
+ # Face Down -> Face Up
1369
+ # Any -> Face Down
1370
+ #
1371
+ class FlipDeviceTrigger < SensorsTrigger
1372
+
1373
+ def initialize(h={})
1374
+
1375
+ options = {
1376
+ any_start: false,
1377
+ face_down: true,
1378
+ work_with_screen_off: false
1379
+ }
1380
+
1381
+ super(options.merge h)
1382
+
1383
+ end
1384
+
1385
+ def to_pc()
1386
+ @h[:face_down] ? 'flip_device_down?' : 'flip_device_up?'
1387
+ end
1388
+
1389
+ def to_s(colour: false)
1390
+
1391
+ action = @h[:face_down] ? 'Face Up -> Face Down' : 'Face Down -> Face Up'
1392
+ 'Flip Device ' + action
1393
+ end
1394
+
1395
+ end
1396
+
1397
+ # Category: Sensors
1398
+ #
1399
+ class OrientationTrigger < SensorsTrigger
1400
+
1401
+ def initialize(h={})
1402
+
1403
+ options = {
1404
+ check_orientation_alive: true,
1405
+ option: 0
1406
+ }
1407
+
1408
+ super(options.merge h)
1409
+
1410
+ end
1411
+
1412
+ def to_s(colour: false)
1413
+ 'OrientationTrigger ' + @h.inspect
1414
+ end
1415
+
1416
+ alias to_summary to_s
1417
+ end
1418
+
1419
+ # Category: User Input
1420
+ #
1421
+ class FloatingButtonTrigger < Trigger
1422
+
1423
+ def initialize(h={})
1424
+
1425
+ options = {
1426
+ image_resource_id: 0,
1427
+ icon_bg_color: -9079435,
1428
+ alpha: 100,
1429
+ padding: 20,
1430
+ force_location: false,
1431
+ show_on_lock_screen: false,
1432
+ size: 0,
1433
+ transparent_background: false,
1434
+ x_location: 0,
1435
+ y_location: 0
1436
+ }
1437
+
1438
+ super(options.merge h)
1439
+
1440
+ end
1441
+
1442
+ def to_s(colour: false)
1443
+ 'Floating Button'
1444
+ end
1445
+
1446
+ alias to_summary to_s
1447
+ end
1448
+
1449
+ # Category: User Input
1450
+ #
1451
+ class ShortcutTrigger < Trigger
1452
+
1453
+ def initialize(h={})
1454
+
1455
+ options = {
1456
+ }
1457
+
1458
+ super(options.merge h)
1459
+
1460
+ end
1461
+
1462
+ def to_s(colour: false)
1463
+ 'ShortcutTrigger ' + @h.inspect
1464
+ end
1465
+
1466
+ alias to_summary to_s
1467
+ end
1468
+
1469
+ # Category: User Input
1470
+ #
1471
+ class VolumeButtonTrigger < Trigger
1472
+
1473
+ def initialize(h={})
1474
+
1475
+ options = {
1476
+ dont_change_volume: true,
1477
+ monitor_option: 1,
1478
+ not_configured: false,
1479
+ option: 0
1480
+ }
1481
+
1482
+ super(options.merge h)
1483
+
1484
+ end
1485
+
1486
+ def to_s(colour: false)
1487
+
1488
+ a = [
1489
+ 'Volume Up',
1490
+ 'Volume Down',
1491
+ 'Volume Up - Long Press',
1492
+ 'Volume Down - Long Press'
1493
+ ]
1494
+
1495
+ lines = [a[@h[:option]]]
1496
+ lines << ' ' + (@h[:dont_change_volume] ? 'Retain Previous Volume' : 'Update Volume')
1497
+ @s = lines.join("\n")
1498
+ end
1499
+
1500
+ def to_summary(colour: false)
1501
+ a = [
1502
+ 'Volume Up',
1503
+ 'Volume Down',
1504
+ 'Volume Up - Long Press',
1505
+ 'Volume Down - Long Press'
1506
+ ]
1507
+
1508
+ lines = [a[@h[:option]]]
1509
+ lines << (@h[:dont_change_volume] ? 'Retain Previous Volume' : 'Update Volume')
1510
+ @s = lines.join(": ")
1511
+ end
1512
+
1513
+ end
1514
+
1515
+ # Category: User Input
1516
+ #
1517
+ class MediaButtonPressedTrigger < Trigger
1518
+
1519
+ def initialize(h={})
1520
+
1521
+ options = {
1522
+ option: 'Single Press',
1523
+ cancel_press: false
1524
+ }
1525
+
1526
+ super(options.merge h)
1527
+
1528
+ end
1529
+
1530
+ def to_s(colour: false)
1531
+ 'MediaButtonPressedTrigger ' + @h.inspect
1532
+ end
1533
+
1534
+ alias to_summary to_s
1535
+ end
1536
+
1537
+ # Category: User Input
1538
+ #
1539
+ class SwipeTrigger < Trigger
1540
+
1541
+ def initialize(h={})
1542
+
1543
+ options = {
1544
+ swipe_start_area: 0,
1545
+ swipe_motion: 0,
1546
+ cleared: true
1547
+ }
1548
+
1549
+ super(options.merge h)
1550
+
1551
+ end
1552
+
1553
+ def to_s(colour: false)
1554
+ 'SwipeTrigger ' + @h.inspect
1555
+ end
1556
+
1557
+ alias to_summary to_s
1558
+ end