remotedroid 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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'