remotedroid 0.4.4 → 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: 4599f668ded4ccead69bcab55ac94e081027b1054b4053ee2cb2f142303a7b01
4
- data.tar.gz: cdbcb98bab0dd3df0d8252892ce5c44c7ed26332803a89292357b04f2f26a9e4
3
+ metadata.gz: ec97faa80816c99a0b7beed8f4274c90f9b3015d6a0db1586a520e3167849351
4
+ data.tar.gz: 73734010ed7db6576c84988d909ca21aed08e8561b7a9e55e3d657bcdabd0b33
5
5
  SHA512:
6
- metadata.gz: 636856536a64d87445c01d3e2b320ccf0fbfed713a6ba4384a19947b182f33bee281a6ae1e191237ed5f74e0995c6460f21108cb4a578b6ea406ecab0921b0c9
7
- data.tar.gz: a650ca4d116ccba5251cd1e9f489587d8ebd5f33c7e8c106a8e59c0817187511d26d2d01aac92d88b27ee0efb07b9cad9eb4a6d7da0abace184f174550a3762e
6
+ metadata.gz: a493dc47aa1c0cbe51c87e7189f1504eb0734088f6ae679da563fee60ea8ae45c4225d1f77909bfb91266b78f81614c89bdba6dec1dfaabedf5c3da0be1bc33e
7
+ data.tar.gz: 8ff28ae91aaccf51919732e516c3915c136acf8be4511b0acfad80ef44447ee5e4b35796003ba0a010da4ed7559674caff94786434e9ba83811cff56e828af75
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -8,6 +8,7 @@ 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
  #
@@ -48,6 +49,10 @@ require 'ruby-macrodroid'
48
49
  #
49
50
  # * Share Location
50
51
  #
52
+ # ## MacroDroid specific
53
+ #
54
+ # * Disable Macro
55
+ #
51
56
  # ## Media
52
57
  #
53
58
  # * Play sound (Doda)
@@ -189,7 +194,16 @@ a:
189
194
  HTTP GET
190
195
  identifier: location
191
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]
192
205
  type: query
206
+
193
207
 
194
208
  m: query
195
209
  t: WebHook
@@ -253,607 +267,8 @@ a: webhook
253
267
 
254
268
  EOF
255
269
 
256
- =begin
257
- m: Screen
258
- v: on: true
259
- t: WebHook
260
- a:
261
- If on = true
262
- Screen On
263
- Else
264
- Screen Off
265
- End If
266
-
267
- =end
268
270
 
269
271
  module RemoteDroid
270
-
271
- class Model
272
- include AppRoutes
273
-
274
- def initialize(obj=nil, root: 'device1', debug: false)
275
-
276
- super()
277
- @root, @debug = root, debug
278
- @location = nil
279
-
280
- if obj then
281
-
282
- s = obj.strip
283
-
284
- puts 's: ' + s.inspect if @debug
285
-
286
- if s[0] == '<' or s.lines[1][0..1] == ' ' then
287
-
288
- puts 'before easydom' if @debug
289
-
290
- s2 = if s.lines[1][0..1] == ' ' then
291
-
292
- lines = s.lines.map do |line|
293
- line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
294
- end
295
-
296
- lines.join
297
-
298
- else
299
- s
300
- end
301
-
302
- @ed = EasyDom.new(s2)
303
- else
304
- build(s, root: root)
305
- end
306
-
307
- end
308
-
309
- end
310
-
311
- def build(raw_requests, root: @root)
312
-
313
- @ed = EasyDom.new(debug: false, root: root)
314
- raw_requests.lines.each {|line| request(line) }
315
-
316
- end
317
-
318
-
319
- def get_thing(h)
320
-
321
- h[:thing].gsub!(/ /,'_')
322
-
323
- if not h.has_key? :location then
324
- location = false
325
- h[:location] = find_path(h[:thing])
326
- else
327
- location = true
328
- end
329
-
330
- puts 'h: ' + h.inspect if @debug
331
-
332
- a = []
333
- a += h[:location].split(/ /)
334
- a << h[:thing]
335
- status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
336
-
337
- if location then
338
- "The %s %s is %s." % [h[:location], h[:thing], status]
339
- else
340
- "%s is %s." % [h[:thing].capitalize, status]
341
- end
342
-
343
- end
344
-
345
- # Object Property (op)
346
- # Helpful for accessing properites in dot notation
347
- # e.g. op.livingroom.light.switch = 'off'
348
- #
349
- def op()
350
- @ed
351
- end
352
-
353
- def query(s)
354
- @ed.e.element(s)
355
- end
356
-
357
- # request accepts a string in plain english
358
- # e.g. request 'switch the livingroom light on'
359
- #
360
- def request(s)
361
-
362
- params = {request: s}
363
- requests(params)
364
- h = find_request(s)
365
-
366
- method(h.first[-1]).call(h).gsub(/_/,' ')
367
-
368
- end
369
-
370
- def set_thing(h)
371
-
372
- h[:thing].gsub!(/ /,'_')
373
- h[:location] = find_path(h[:thing]) unless h.has_key? :location
374
-
375
- a = []
376
- a += h[:location].split(/ /)
377
- a << h[:thing]
378
-
379
- a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
380
-
381
- end
382
-
383
- def to_sliml(level: 0)
384
-
385
- s = @ed.to_sliml
386
-
387
- return s if level.to_i > 0
388
-
389
- lines = s.lines.map do |line|
390
-
391
- line.sub(/\{[^\}]+\}/) do |x|
392
-
393
- a = x.scan(/\w+: +[^ ]+/)
394
- if a.length == 1 and x[/switch:/] then
395
-
396
- val = x[/(?<=switch: ) *["']([^"']+)/,1]
397
- 'is ' + val
398
- else
399
- x
400
- end
401
-
402
- end
403
- end
404
-
405
- lines.join
406
-
407
- end
408
-
409
- def to_xml(options=nil)
410
- @ed.xml(pretty: true).gsub(' style=\'\'','')
411
- end
412
-
413
- alias xml to_xml
414
-
415
- # to_xml() is the preferred method
416
-
417
- protected
418
-
419
- def requests(params)
420
-
421
- # e.g. switch the livingroom gas_fire off
422
- #
423
- get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
424
- {type: :set_thing, action: 'switch=', location: location, thing: device, value: onoff}
425
- end
426
-
427
- # e.g. switch the gas _fire off
428
- #
429
- get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
430
- {type: :set_thing, action: 'switch=', thing: device, value: onoff}
431
- end
432
-
433
- # e.g. is the livingroom gas_fire on?
434
- #
435
- get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
436
- {type: :get_thing, action: 'switch', location: location, thing: device}
437
- end
438
-
439
- # e.g. enable airplane mode
440
- #
441
- get /((?:dis|en)able) ([^$]+)$/ do |state, service|
442
- {type: :set_thing, action: 'switch=', thing: service, value: state + 'd'}
443
- end
444
-
445
- # e.g. switch airplane mode off
446
- #
447
- get /switch (.*) (on|off)/ do |service, rawstate|
448
-
449
- state = rawstate == 'on' ? 'enabled' : 'disabled'
450
- {type: :set_thing, action: 'switch=', thing: service, value: state}
451
-
452
- end
453
-
454
- # e.g. is airplane mode enabed?
455
- #
456
- get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
457
- {type: :get_thing, action: 'switch', thing: service.gsub(/ /,'_')}
458
- end
459
-
460
- # e.g. is the gas_fire on?
461
- #
462
- get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
463
- location = find_path(device)
464
- {type: :get_thing, action: 'switch', location: location, thing: device}
465
- end
466
-
467
- # e.g. fetch the livingroom temperature reading
468
- #
469
- get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
470
- {type: :get_thing, action: 'reading', location: location, thing: device}
471
- end
472
-
473
- # e.g. fetch the temperature reading
474
- #
475
- get /fetch the ([^ ]+) +(?:reading)$/ do |device|
476
- location = find_path(device)
477
- {type: :get_thing, action: 'reading', location: location, thing: device}
478
- end
479
-
480
- end
481
-
482
- private
483
-
484
- def find_path(s)
485
- puts 'find_path s: ' + s.inspect if @debug
486
- found = query('//'+ s)
487
- return unless found
488
- a = found.backtrack.to_xpath.split('/')
489
- a[1..-2].join(' ')
490
- end
491
-
492
- alias find_request run_route
493
-
494
- end
495
-
496
- class Controller
497
-
498
- attr_reader :model, :control
499
- attr_accessor :title, :macros, :store
500
-
501
- def initialize(mcs, model=MODEL, deviceid: nil, debug: false)
502
-
503
- @debug = debug
504
- @syslog = []
505
-
506
- @control = Control.new(deviceid)
507
- @macros = mcs.macros
508
-
509
- if model then
510
- @model = Model.new(model)
511
- end
512
-
513
- @store = {}
514
- @query = Query.new(self)
515
-
516
- end
517
-
518
- def export(s)
519
- @macros = MacroDroid.new(s).macros
520
- end
521
-
522
- def invoke(name, options={})
523
-
524
- if @control.respond_to? name.to_sym then
525
- @control.method(name.to_sym).call(options)
526
- else
527
- @control.http_exec name.to_sym, options
528
- end
529
- end
530
-
531
- # Object Property (op)
532
- # Helpful for accessing properites in dot notation
533
- # e.g. op.livingroom.light.switch = 'off'
534
- #
535
- def op()
536
- @model.op
537
- end
538
-
539
- def query(id=nil)
540
-
541
- return @query unless id
542
-
543
- @store[id] = nil
544
-
545
- sys = %i(accelerometer_rotation)
546
-
547
- global = [:airplane_mode_on, :bluetooth_on, :cell_on, :device_name, \
548
- :usb_mass_storage_enabled, :wifi_on]
549
-
550
- secure = %i(bluetooth_name flashlight_enabled)
551
-
552
-
553
- # send http request via macrodroid.com API
554
-
555
- if id.downcase.to_sym == :location then
556
- @control.http_exec id
557
- elsif sys.include? id
558
- @control.http_exec :'query-setting-system', {qvar: id}
559
- elsif global.include? id
560
- @control.http_exec :'query-setting-global', {qvar: id}
561
- elsif secure.include? id
562
- @control.http_exec :'query-setting-secure', {qvar: id}
563
- elsif id.downcase.to_sym == :'take-picture'
564
- @control.http_exec id
565
- else
566
- @control.http_exec :query, {qvar: id}
567
- end
568
-
569
- # wait for the local variable to be updated
570
- # timeout after 5 seoncds
571
- t = Time.now
572
-
573
- begin
574
- sleep 1
575
- end until @store[id] or Time.now > t + 10
576
-
577
- return {warning: 'HTTP response timeout'} if Time.now > t+5
578
-
579
- return @store[id]
580
-
581
-
582
- end
583
-
584
- def request(s)
585
- @model.request s
586
- end
587
-
588
-
589
- def trigger(name, detail={time: Time.now})
590
-
591
- macros = @macros.select do |macro|
592
-
593
- puts 'macro: ' + macro.inspect if @debug
594
-
595
- # fetch the associated properties from the model if possible and
596
- # merge them into the detail.
597
- #
598
- valid_trigger = macro.match?(name, detail, @model.op)
599
-
600
- puts 'valid_trigger: ' + valid_trigger.inspect if @debug
601
-
602
- if valid_trigger then
603
- @syslog << [Time.now, :trigger, name]
604
- @syslog << [Time.now, :macro, macro.title]
605
- end
606
-
607
- valid_trigger
608
-
609
- end
610
-
611
- puts 'macros: ' + macros.inspect if @debug
612
-
613
- macros.flat_map(&:run)
614
- end
615
-
616
- alias trigger_fired trigger
617
-
618
- def update(id, val)
619
-
620
- key = if %i(location take-picture).include? id
621
- id
622
- else
623
- val.keys.first.to_sym
624
- end
625
-
626
- @store[key] = val
627
- end
628
-
629
- end
630
-
631
- class Service
632
- def initialize(callback)
633
- @callback = callback
634
- end
635
- end
636
-
637
- class Bluetooth
638
- def enable()
639
- end
640
- end
641
-
642
- class Toast < Service
643
-
644
- def invoke()
645
- @callback.call :toast
646
- end
647
-
648
- end
649
-
650
- class Torch < Service
651
-
652
- def toggle()
653
- @callback.http_exec :torch
654
- end
655
-
656
- end
657
-
658
- class ControlHelper
659
-
660
- def initialize(callback)
661
- @callback
662
- end
663
- end
664
-
665
- class Control
666
-
667
- def initialize(dev=nil, deviceid: dev, remote_url: nil, debug: false)
668
-
669
- @deviceid, @remote_url, @debug = deviceid, remote_url, debug
670
- @torch = Torch.new(self)
671
- end
672
-
673
- def bluetooth()
674
- @bluetooth
675
- end
676
-
677
- def camera_flash_light(options={})
678
- http_exec 'camera-flash-light', options
679
- end
680
-
681
- def hotspot(state=nil)
682
-
683
- if state then
684
- http_exec 'hotspot', {enable: state == :enable}
685
- else
686
-
687
- def self.enable()
688
- http_exec 'hotspot', {enable: true}
689
- end
690
-
691
- def self.on()
692
- self.enable
693
- end
694
-
695
- def self.disable()
696
- http_exec 'hotspot', {enable: false}
697
- end
698
-
699
- def self.off()
700
- self.disable
701
- end
702
-
703
- self
704
-
705
- end
706
- end
707
-
708
- def http_exec(command, options={})
709
-
710
- url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
711
-
712
- if options and options.any? then
713
- h = options
714
- url += '?' + \
715
- URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
716
- end
717
-
718
- s = open(url).read
719
-
720
- end
721
-
722
- def location(options={})
723
- http_exec 'location'
724
- end
725
-
726
- def say_current_time(options={})
727
- http_exec 'say-current-time'
728
- end
729
-
730
- alias say_time say_current_time
731
-
732
- def screen(state=nil)
733
-
734
- if state then
735
- http_exec 'screen', {on: state == :on}
736
- else
737
-
738
- def self.on()
739
- http_exec 'screen', {on: true}
740
- end
741
-
742
- def self.off()
743
- http_exec 'screen', {on: false}
744
- end
745
-
746
- self
747
-
748
- end
749
- end
750
-
751
- def share_location(options={})
752
- http_exec 'share-location'
753
- end
754
-
755
- def speak_text(obj)
756
-
757
- options = case obj
758
- when String
759
- {text: obj}
760
- when Hash
761
- obj
762
- end
763
-
764
- http_exec 'speak-text', options
765
- end
766
-
767
- alias say speak_text
768
-
769
- def stay_awake(options={})
770
- http_exec 'stay-awake', options
771
- end
772
-
773
- def stay_awake_off(options={})
774
- http_exec 'stay-awake-off', options
775
- end
776
-
777
- def take_picture(options={})
778
- http_exec 'take-picture', options
779
- end
780
-
781
- alias take_photo take_picture
782
-
783
-
784
- def toast(options={})
785
- http_exec :toast, options
786
- end
787
-
788
- def torch(options={})
789
- http_exec :torch
790
- end
791
-
792
- def vibrate(options={})
793
- http_exec :vibrate
794
- end
795
-
796
-
797
- def write(s)
798
-
799
- MacroDroid.new(RD_MACROS, deviceid: @deviceid,
800
- remote_url: @remote_url, debug: @debug).export s
801
-
802
- end
803
-
804
- alias export write
805
-
806
- def method_missing2(method_name, *args)
807
- http_exec(method_name, args.first)
808
- end
809
-
810
- end
811
-
812
- class Query
813
-
814
- def initialize(callback)
815
- @callback = callback
816
- end
817
-
818
- def airplane_mode_enabled?()
819
- q(:airplane_mode_on).to_i > 0
820
- end
821
-
822
- def battery()
823
- q(:battery).to_i
824
- end
825
-
826
- def current_brightness()
827
- q(:current_brightness).to_i
828
- end
829
-
830
- alias brightness current_brightness
831
-
832
- def cell_id()
833
- q(:cell_id)
834
- end
835
-
836
- alias cell_tower cell_id
837
-
838
- def ip()
839
- q(:ip)
840
- end
841
-
842
- def location()
843
- @callback.query(:location)[:coords]
844
- end
845
-
846
- def take_picture()
847
- @callback.query(:'take-picture')
848
- end
849
-
850
- private
851
-
852
- def q(id)
853
- @callback.query(id)[id]
854
- end
855
-
856
- end
857
272
 
858
273
  class Server
859
274
 
@@ -870,127 +285,7 @@ module RemoteDroid
870
285
  end
871
286
 
872
287
  end
873
-
874
- class Client
875
288
 
876
- def initialize(host='127.0.0.1')
877
- @drb = OneDrb::Client.new host: host, port: '5777'
878
- end
879
-
880
- def control
881
- @drb.control
882
- end
883
-
884
- def export(s)
885
- @drb.export(s)
886
- end
887
-
888
- def invoke(s, *args)
889
- @drb.invoke(s, *args)
890
- end
891
-
892
- def query(id=nil)
893
-
894
- return @drb.query unless id
895
- t = Time.now
896
- h = @drb.query(id)
897
- h.merge({latency: (Time.now - t).round(3)})
898
-
899
- end
900
-
901
- def update(key, val)
902
- @drb.update key.to_sym, val
903
- end
904
-
905
- def store()
906
- @drb.store
907
- end
908
-
909
- # -- helpful methods -----------------
910
-
911
- def battery()
912
- query.battery
913
- end
914
-
915
- def cell_tower()
916
- query.cell_tower
917
- end
918
-
919
- def hotspot(state=nil)
920
- control.hotspot state
921
- end
922
-
923
- def location()
924
- query.location
925
- end
926
-
927
- def photo()
928
- take_picture
929
- end
930
-
931
- def say(text)
932
- control.speak_text text
933
- end
934
-
935
- def say_time()
936
- control.say_time
937
- end
938
-
939
- alias saytime say_time
940
-
941
- def screen(state=nil)
942
- control.screen state
943
- end
944
-
945
- def screen_on()
946
- screen :on
947
- end
948
-
949
- def screen_off()
950
- screen :off
951
- end
952
-
953
- def stay_awake()
954
- control.stay_awake
955
- end
956
-
957
- def stay_awake_off()
958
- control.stay_awake_off
959
- end
960
-
961
- def take_picture(ftp_src: nil, fileout: '.')
962
-
963
- #screen.on
964
- r = query.take_picture
965
-
966
- if ftp_src then
967
-
968
- # the sleep statement will be replaced in the near future,
969
- # but it's fine to demonstrate it works
970
- #sleep 8
971
-
972
- credentials, dir = ftp_src.match(/(ftp:\/\/[^\/]+)\/([^$]+)/).captures
973
- ftp = MyMediaFTP.new(credentials)
974
- ftp.cd dir
975
- filename = ftp.ls.sort_by {|x| x[:ctime]}.last[:name]
976
- ftp.cp filename, fileout
977
-
978
- end
979
-
980
- end
981
-
982
- alias take_photo take_picture
983
-
984
- def torch()
985
- control.torch
986
- end
987
-
988
- def vibrate
989
- control.vibrate
990
- end
991
-
992
- end
993
-
994
289
  class TriggerSubscriber < SPSSub
995
290
 
996
291
  def initialize(host: 'sps.home', drb_host: '127.0.0.1')
@@ -1057,3 +352,12 @@ module RemoteDroid
1057
352
 
1058
353
  end
1059
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'