remotedroid 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bc29943617484d1dd660a519cf38b3eb0658d69c8a2cadadc92f1f8fa7b036f
4
- data.tar.gz: 9b529677442b0905636fddd8d0b985df57f0115d6b5861b958749917886bcdb3
3
+ metadata.gz: ec97faa80816c99a0b7beed8f4274c90f9b3015d6a0db1586a520e3167849351
4
+ data.tar.gz: 73734010ed7db6576c84988d909ca21aed08e8561b7a9e55e3d657bcdabd0b33
5
5
  SHA512:
6
- metadata.gz: efadc0c0d423e937603ade768551e8796d8d6061dbdc2cfaee3c2d4fa11befb711da2d9fc157a898969cfbe5c8b05106f4db212ee4d2f36e67f94d87f1345e2a
7
- data.tar.gz: 43e65afff822006b49452d3633d2bc05e42c1cbdbe76fd3b264c8761426fad724085972be1b88376953d00ab0cd6d9bfccf2ae52e9f86f8ac55192f050f0d9e6
6
+ metadata.gz: a493dc47aa1c0cbe51c87e7189f1504eb0734088f6ae679da563fee60ea8ae45c4225d1f77909bfb91266b78f81614c89bdba6dec1dfaabedf5c3da0be1bc33e
7
+ data.tar.gz: 8ff28ae91aaccf51919732e516c3915c136acf8be4511b0acfad80ef44447ee5e4b35796003ba0a010da4ed7559674caff94786434e9ba83811cff56e828af75
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -8,11 +8,16 @@ require 'app-routes'
8
8
  require 'sps-sub'
9
9
  require 'ruby-macrodroid'
10
10
 
11
+ # PASTE_START
11
12
 
12
13
  # Here's what's available so far:
13
14
  #
14
15
  # # Triggers
15
16
  #
17
+ # ## Device Events
18
+ #
19
+ # * screen on
20
+ #
16
21
  # ## Sensors
17
22
  #
18
23
  # * proximity (near)
@@ -22,6 +27,14 @@ require 'ruby-macrodroid'
22
27
  #
23
28
  # # Actions
24
29
  #
30
+ # ## Camera/Photo
31
+ #
32
+ # * Take Picture
33
+ #
34
+ # ## Connectivity
35
+ #
36
+ # * Enable HotSpot
37
+ #
25
38
  # ## Date/Time
26
39
  #
27
40
  # * Say Current Time
@@ -36,6 +49,10 @@ require 'ruby-macrodroid'
36
49
  #
37
50
  # * Share Location
38
51
  #
52
+ # ## MacroDroid specific
53
+ #
54
+ # * Disable Macro
55
+ #
39
56
  # ## Media
40
57
  #
41
58
  # * Play sound (Doda)
@@ -44,6 +61,10 @@ require 'ruby-macrodroid'
44
61
  #
45
62
  # * Popup Message
46
63
  #
64
+ # ## Screen
65
+ #
66
+ # * Keep Device Awake
67
+ # * Screen On
47
68
  #
48
69
 
49
70
  # Variables which can be queried
@@ -125,6 +146,42 @@ m: play doda
125
146
  t: webhook
126
147
  a: play: Doda
127
148
 
149
+ m: Screen
150
+ v: on: false
151
+ t: WebHook
152
+ a:
153
+ If on = True
154
+ Screen On
155
+ Else
156
+ Screen Off
157
+ End If
158
+
159
+ m: Hotspot
160
+ v: enable: false
161
+ t: WebHook
162
+ a:
163
+ If enable = True
164
+ Enable Hotspot
165
+ Else
166
+ Disable Hotspot
167
+ End If
168
+
169
+ m: Take Picture
170
+ t: webhook
171
+ a:
172
+ Take Picture
173
+ Rear Facing
174
+ a: wait 2 seconds
175
+ a: webhook
176
+
177
+ m: stay awake
178
+ t: webhook
179
+ a: stay awake
180
+
181
+ m: stay awake off
182
+ t: webhook
183
+ a: stay awake off
184
+
128
185
  m: Share location
129
186
  t:
130
187
  WebHook
@@ -137,7 +194,16 @@ a:
137
194
  HTTP GET
138
195
  identifier: location
139
196
  coords: [lv=coords]
197
+ cell: [cell_id]
198
+ ssid: [ssid]
199
+ alt: [last_loc_alt]
200
+ time: [last_loc_age_timestamp]
201
+ mph: [last_loc_speed_mph]
202
+ kph: [last_loc_speed_kmh]
203
+ device: [device_model]
204
+ battery: [battery]
140
205
  type: query
206
+
141
207
 
142
208
  m: query
143
209
  t: WebHook
@@ -190,510 +256,19 @@ a:
190
256
  webhook
191
257
  identifier: proximity
192
258
  option: 0
193
-
194
- EOF
195
-
196
- module RemoteDroid
197
-
198
- class Model
199
- include AppRoutes
200
-
201
- def initialize(obj=nil, root: 'device1', debug: false)
202
-
203
- super()
204
- @root, @debug = root, debug
205
- @location = nil
206
-
207
- if obj then
208
-
209
- s = obj.strip
210
-
211
- puts 's: ' + s.inspect if @debug
212
-
213
- if s[0] == '<' or s.lines[1][0..1] == ' ' then
214
-
215
- puts 'before easydom' if @debug
216
-
217
- s2 = if s.lines[1][0..1] == ' ' then
218
-
219
- lines = s.lines.map do |line|
220
- line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
221
- end
222
-
223
- lines.join
224
-
225
- else
226
- s
227
- end
228
-
229
- @ed = EasyDom.new(s2)
230
- else
231
- build(s, root: root)
232
- end
233
-
234
- end
235
-
236
- end
237
-
238
- def build(raw_requests, root: @root)
239
-
240
- @ed = EasyDom.new(debug: false, root: root)
241
- raw_requests.lines.each {|line| request(line) }
242
-
243
- end
244
-
245
-
246
- def get_thing(h)
247
-
248
- h[:thing].gsub!(/ /,'_')
249
-
250
- if not h.has_key? :location then
251
- location = false
252
- h[:location] = find_path(h[:thing])
253
- else
254
- location = true
255
- end
256
-
257
- puts 'h: ' + h.inspect if @debug
258
-
259
- a = []
260
- a += h[:location].split(/ /)
261
- a << h[:thing]
262
- status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
263
-
264
- if location then
265
- "The %s %s is %s." % [h[:location], h[:thing], status]
266
- else
267
- "%s is %s." % [h[:thing].capitalize, status]
268
- end
269
-
270
- end
271
-
272
- # Object Property (op)
273
- # Helpful for accessing properites in dot notation
274
- # e.g. op.livingroom.light.switch = 'off'
275
- #
276
- def op()
277
- @ed
278
- end
279
-
280
- def query(s)
281
- @ed.e.element(s)
282
- end
283
-
284
- # request accepts a string in plain english
285
- # e.g. request 'switch the livingroom light on'
286
- #
287
- def request(s)
288
-
289
- params = {request: s}
290
- requests(params)
291
- h = find_request(s)
292
-
293
- method(h.first[-1]).call(h).gsub(/_/,' ')
294
-
295
- end
296
-
297
- def set_thing(h)
298
-
299
- h[:thing].gsub!(/ /,'_')
300
- h[:location] = find_path(h[:thing]) unless h.has_key? :location
301
-
302
- a = []
303
- a += h[:location].split(/ /)
304
- a << h[:thing]
305
-
306
- a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
307
-
308
- end
309
-
310
- def to_sliml(level: 0)
311
-
312
- s = @ed.to_sliml
313
-
314
- return s if level.to_i > 0
315
-
316
- lines = s.lines.map do |line|
317
-
318
- line.sub(/\{[^\}]+\}/) do |x|
319
-
320
- a = x.scan(/\w+: +[^ ]+/)
321
- if a.length == 1 and x[/switch:/] then
322
-
323
- val = x[/(?<=switch: ) *["']([^"']+)/,1]
324
- 'is ' + val
325
- else
326
- x
327
- end
328
-
329
- end
330
- end
331
-
332
- lines.join
333
-
334
- end
335
-
336
- def to_xml(options=nil)
337
- @ed.xml(pretty: true).gsub(' style=\'\'','')
338
- end
339
-
340
- alias xml to_xml
341
-
342
- # to_xml() is the preferred method
343
-
344
- protected
345
-
346
- def requests(params)
347
-
348
- # e.g. switch the livingroom gas_fire off
349
- #
350
- get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
351
- {type: :set_thing, action: 'switch=', location: location, thing: device, value: onoff}
352
- end
353
-
354
- # e.g. switch the gas _fire off
355
- #
356
- get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
357
- {type: :set_thing, action: 'switch=', thing: device, value: onoff}
358
- end
359
-
360
- # e.g. is the livingroom gas_fire on?
361
- #
362
- get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
363
- {type: :get_thing, action: 'switch', location: location, thing: device}
364
- end
365
-
366
- # e.g. enable airplane mode
367
- #
368
- get /((?:dis|en)able) ([^$]+)$/ do |state, service|
369
- {type: :set_thing, action: 'switch=', thing: service, value: state + 'd'}
370
- end
371
-
372
- # e.g. switch airplane mode off
373
- #
374
- get /switch (.*) (on|off)/ do |service, rawstate|
375
-
376
- state = rawstate == 'on' ? 'enabled' : 'disabled'
377
- {type: :set_thing, action: 'switch=', thing: service, value: state}
378
-
379
- end
380
-
381
- # e.g. is airplane mode enabed?
382
- #
383
- get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
384
- {type: :get_thing, action: 'switch', thing: service.gsub(/ /,'_')}
385
- end
386
-
387
- # e.g. is the gas_fire on?
388
- #
389
- get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
390
- location = find_path(device)
391
- {type: :get_thing, action: 'switch', location: location, thing: device}
392
- end
393
-
394
- # e.g. fetch the livingroom temperature reading
395
- #
396
- get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
397
- {type: :get_thing, action: 'reading', location: location, thing: device}
398
- end
399
-
400
- # e.g. fetch the temperature reading
401
- #
402
- get /fetch the ([^ ]+) +(?:reading)$/ do |device|
403
- location = find_path(device)
404
- {type: :get_thing, action: 'reading', location: location, thing: device}
405
- end
406
-
407
- end
408
-
409
- private
410
-
411
- def find_path(s)
412
- puts 'find_path s: ' + s.inspect if @debug
413
- found = query('//'+ s)
414
- return unless found
415
- a = found.backtrack.to_xpath.split('/')
416
- a[1..-2].join(' ')
417
- end
418
-
419
- alias find_request run_route
420
-
421
- end
422
-
423
- class Controller
424
-
425
- attr_reader :model, :control
426
- attr_accessor :title, :macros, :store
427
-
428
- def initialize(mcs, model=MODEL, deviceid: nil, debug: false)
429
-
430
- @debug = debug
431
- @syslog = []
432
-
433
- @control = Control.new(deviceid)
434
- @macros = mcs.macros
435
-
436
- if model then
437
- @model = Model.new(model)
438
- end
439
-
440
- @store = {}
441
- @query = Query.new(self)
442
-
443
- end
444
-
445
- def export(s)
446
- @macros = MacroDroid.new(s).macros
447
- end
448
-
449
- def invoke(name, options={})
450
-
451
- if @control.respond_to? name.to_sym then
452
- @control.method(name.to_sym).call(options)
453
- else
454
- @control.http_exec name.to_sym, options
455
- end
456
- end
457
-
458
- # Object Property (op)
459
- # Helpful for accessing properites in dot notation
460
- # e.g. op.livingroom.light.switch = 'off'
461
- #
462
- def op()
463
- @model.op
464
- end
465
-
466
- def query(id=nil)
467
-
468
- return @query unless id
469
-
470
- @store[id] = nil
471
-
472
- sys = %i(accelerometer_rotation)
473
-
474
- global = [:airplane_mode_on, :bluetooth_on, :cell_on, :device_name, \
475
- :usb_mass_storage_enabled, :wifi_on]
476
-
477
- secure = %i(bluetooth_name flashlight_enabled)
478
-
479
-
480
- # send http request via macrodroid.com API
481
-
482
- if id.downcase.to_sym == :location then
483
- @control.http_exec id
484
- elsif sys.include? id
485
- @control.http_exec :'query-setting-system', {qvar: id}
486
- elsif global.include? id
487
- @control.http_exec :'query-setting-global', {qvar: id}
488
- elsif secure.include? id
489
- @control.http_exec :'query-setting-secure', {qvar: id}
490
- else
491
- @control.http_exec :query, {qvar: id}
492
- end
493
-
494
- # wait for the local variable to be updated
495
- # timeout after 5 seoncds
496
- t = Time.now
497
-
498
- begin
499
- sleep 1
500
- end until @store[id] or Time.now > t + 5
501
-
502
- return {warning: 'HTTP response timeout'} if Time.now > t+5
503
-
504
- return @store[id]
505
-
506
-
507
- end
508
-
509
- def request(s)
510
- @model.request s
511
- end
512
-
513
259
 
514
- def trigger(name, detail={time: Time.now})
515
-
516
- macros = @macros.select do |macro|
517
-
518
- puts 'macro: ' + macro.inspect if @debug
519
-
520
- # fetch the associated properties from the model if possible and
521
- # merge them into the detail.
522
- #
523
- valid_trigger = macro.match?(name, detail, @model.op)
524
-
525
- puts 'valid_trigger: ' + valid_trigger.inspect if @debug
526
-
527
- if valid_trigger then
528
- @syslog << [Time.now, :trigger, name]
529
- @syslog << [Time.now, :macro, macro.title]
530
- end
531
-
532
- valid_trigger
533
-
534
- end
535
-
536
- puts 'macros: ' + macros.inspect if @debug
537
-
538
- macros.flat_map(&:run)
539
- end
540
-
541
- alias trigger_fired trigger
542
-
543
- def update(id, val)
544
- key = id == :location ? id : val.keys.first.to_sym
545
- @store[key] = val
546
- end
547
-
548
-
549
- end
550
-
551
- class Service
552
- def initialize(callback)
553
- @callback = callback
554
- end
555
- end
556
-
557
- class Bluetooth
558
- def enable()
559
- end
560
- end
561
-
562
- class Toast < Service
563
-
564
- def invoke()
565
- @callback.call :toast
566
- end
567
-
568
- end
569
-
570
- class Torch < Service
571
-
572
- def toggle()
573
- @callback.http_exec :torch
574
- end
575
-
576
- end
260
+ m: Power connected
261
+ t: Power Connected: Any
262
+ a: webhook
577
263
 
578
- class Control
579
-
580
- def initialize(dev=nil, deviceid: dev, remote_url: nil, debug: false)
581
-
582
- @deviceid, @remote_url, @debug = deviceid, remote_url, debug
583
- @torch = Torch.new(self)
584
- end
585
-
586
- def bluetooth()
587
- @bluetooth
588
- end
589
-
590
- def camera_flash_light(options={})
591
- http_exec 'camera-flash-light', options
592
- end
593
-
594
- def http_exec(command, options={})
595
-
596
- url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
597
-
598
- if options and options.any? then
599
- h = options
600
- url += '?' + \
601
- URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
602
- end
603
-
604
- s = open(url).read
605
-
606
- end
607
-
608
- def location(options={})
609
- http_exec 'location'
610
- end
611
-
612
- def say_current_time(options={})
613
- http_exec 'say-current-time'
614
- end
615
-
616
- alias say_time say_current_time
617
-
618
- def share_location(options={})
619
- http_exec 'share-location'
620
- end
621
-
622
- def speak_text(obj)
623
-
624
- options = case obj
625
- when String
626
- {text: obj}
627
- when Hash
628
- obj
629
- end
630
-
631
- http_exec 'speak-text', options
632
- end
633
-
634
- alias say speak_text
635
-
636
- def toast(options={})
637
- http_exec :toast, options
638
- end
639
-
640
- def torch(options={})
641
- http_exec :torch
642
- end
643
-
644
- def vibrate(options={})
645
- http_exec :vibrate
646
- end
264
+ m: screen on off
265
+ t: screen on
266
+ a: webhook
647
267
 
268
+ EOF
648
269
 
649
- def write(s)
650
-
651
- MacroDroid.new(RD_MACROS, deviceid: @deviceid,
652
- remote_url: @remote_url, debug: @debug).export s
653
-
654
- end
655
-
656
- alias export write
657
-
658
- def method_missing2(method_name, *args)
659
- http_exec(method_name, args.first)
660
- end
661
-
662
- end
663
-
664
- class Query
665
-
666
- def initialize(callback)
667
- @callback = callback
668
- end
669
-
670
- def battery()
671
- q(:battery).to_i
672
- end
673
-
674
- def current_brightness()
675
- q(:current_brightness).to_i
676
- end
677
270
 
678
- alias brightness current_brightness
679
-
680
- def cell_id()
681
- q(:cell_id)
682
- end
683
-
684
- alias cell_tower cell_id
685
-
686
- def ip()
687
- q(:ip)
688
- end
689
-
690
- private
691
-
692
- def q(id)
693
- @callback.query(id)[id]
694
- end
695
-
696
- end
271
+ module RemoteDroid
697
272
 
698
273
  class Server
699
274
 
@@ -710,44 +285,7 @@ module RemoteDroid
710
285
  end
711
286
 
712
287
  end
713
-
714
- class Client
715
-
716
- def initialize(host='127.0.0.1')
717
- @drb = OneDrb::Client.new host: host, port: '5777'
718
- end
719
-
720
- def control
721
- @drb.control
722
- end
723
-
724
- def export(s)
725
- @drb.export(s)
726
- end
727
288
 
728
- def invoke(s, *args)
729
- @drb.invoke(s, *args)
730
- end
731
-
732
- def query(id=nil)
733
-
734
- return @drb.query unless id
735
- t = Time.now
736
- h = @drb.query(id)
737
- h.merge({latency: (Time.now - t).round(3)})
738
-
739
- end
740
-
741
- def update(key, val)
742
- @drb.update key.to_sym, val
743
- end
744
-
745
- def store()
746
- @drb.store
747
- end
748
-
749
- end
750
-
751
289
  class TriggerSubscriber < SPSSub
752
290
 
753
291
  def initialize(host: 'sps.home', drb_host: '127.0.0.1')
@@ -803,6 +341,7 @@ module RemoteDroid
803
341
  super(topic: topic) do |msg|
804
342
 
805
343
  json, id = msg.split(/:\s+/,2).reverse
344
+
806
345
  h = JSON.parse(json, symbolize_names: true)
807
346
  id ||= h.keys.first
808
347
  @remote.update id.to_sym, h
@@ -813,3 +352,12 @@ module RemoteDroid
813
352
 
814
353
  end
815
354
  end
355
+
356
+ # PASTE_END
357
+
358
+
359
+ require 'remotedroid/model'
360
+ require 'remotedroid/query'
361
+ require 'remotedroid/control'
362
+ require 'remotedroid/controller'
363
+ require 'remotedroid/client'