remotedroid 0.4.1 → 0.5.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,157 @@
1
+ module RemoteDroid
2
+
3
+ class Client
4
+ using ColouredText
5
+
6
+ def initialize(host='127.0.0.1')
7
+ @drb = OneDrb::Client.new host: host, port: '5777'
8
+ end
9
+
10
+ def control
11
+ @drb.control
12
+ end
13
+
14
+ def export(s)
15
+ @drb.export(s)
16
+ end
17
+
18
+ def invoke(s, *args)
19
+ @drb.invoke(s, *args)
20
+ end
21
+
22
+ def macros()
23
+ @drb.macros
24
+ end
25
+
26
+ def query(id=nil)
27
+
28
+ return @drb.query unless id
29
+ t = Time.now
30
+ h = @drb.query(id)
31
+ h.merge({latency: (Time.now - t).round(3)})
32
+
33
+ end
34
+
35
+ def update(key, val)
36
+ @drb.update key.to_sym, val
37
+ end
38
+
39
+ def store()
40
+ @drb.store
41
+ end
42
+
43
+ # -- helpful methods -----------------
44
+
45
+ def battery()
46
+ query.battery
47
+ end
48
+
49
+ def cell_tower()
50
+ query.cell_tower
51
+ end
52
+
53
+ def disable(macro)
54
+ control.disable macro
55
+ end
56
+
57
+ def enable(macro)
58
+ control.enable macro
59
+ end
60
+
61
+ def hotspot(state=nil)
62
+ control.hotspot state
63
+ end
64
+
65
+ def location()
66
+ query.location
67
+ end
68
+
69
+ def location_watch(refresh: '1 minute', interval: refresh,
70
+ duration: '30 minutes')
71
+
72
+
73
+ d = ChronicDuration.parse(duration)
74
+ seconds = ChronicDuration.parse(interval)
75
+ puts ("monitoring location every %s for %s" % [interval, duration]).info
76
+
77
+ Thread.new do
78
+
79
+ t = Time.now + d
80
+
81
+ begin
82
+
83
+ query.location
84
+ sleep seconds
85
+
86
+ end until Time.now >= t
87
+
88
+ end
89
+
90
+ end
91
+
92
+ def photo()
93
+ take_picture
94
+ end
95
+
96
+ def say(text)
97
+ control.speak_text text
98
+ end
99
+
100
+ def say_time()
101
+ control.say_time
102
+ end
103
+
104
+ alias saytime say_time
105
+
106
+ def screen(state=nil)
107
+ control.screen state
108
+ end
109
+
110
+ def screen_on()
111
+ screen :on
112
+ end
113
+
114
+ def screen_off()
115
+ screen :off
116
+ end
117
+
118
+ def stay_awake()
119
+ control.stay_awake
120
+ end
121
+
122
+ def stay_awake_off()
123
+ control.stay_awake_off
124
+ end
125
+
126
+ def take_picture(ftp_src: nil, fileout: '.')
127
+
128
+ #screen.on
129
+ r = query.take_picture
130
+
131
+ if ftp_src then
132
+
133
+ # give the device a second to write the image to file
134
+ sleep 1
135
+
136
+ credentials, dir = ftp_src.match(/(ftp:\/\/[^\/]+)\/([^$]+)/).captures
137
+ ftp = MyMediaFTP.new(credentials)
138
+ ftp.cd dir
139
+ filename = ftp.ls.sort_by {|x| x[:ctime]}.last[:name]
140
+ ftp.cp filename, fileout
141
+
142
+ end
143
+
144
+ end
145
+
146
+ alias take_photo take_picture
147
+
148
+ def torch()
149
+ control.torch
150
+ end
151
+
152
+ def vibrate
153
+ control.vibrate
154
+ end
155
+
156
+ end
157
+ end
@@ -0,0 +1,194 @@
1
+ module RemoteDroid
2
+
3
+ class Control
4
+
5
+ def initialize(dev=nil, deviceid: dev, remote_url: nil, debug: false)
6
+
7
+ @deviceid, @remote_url, @debug = deviceid, remote_url, debug
8
+
9
+ end
10
+
11
+ def bluetooth()
12
+ @bluetooth
13
+ end
14
+
15
+ def camera_flash_light(options={})
16
+ http_exec 'camera-flash-light', options
17
+ end
18
+
19
+ def disable(macro)
20
+ http_exec 'disable-macro', {name: macro}
21
+ end
22
+
23
+ def enable(macro)
24
+ http_exec 'enable-macro', {name: macro}
25
+ end
26
+
27
+ def hotspot(state=nil)
28
+
29
+ if state then
30
+ http_exec 'hotspot', {enable: state == :enable}
31
+ else
32
+
33
+ def self.enable()
34
+ http_exec 'hotspot', {enable: true}
35
+ end
36
+
37
+ def self.on()
38
+ self.enable
39
+ end
40
+
41
+ def self.disable()
42
+ http_exec 'hotspot', {enable: false}
43
+ end
44
+
45
+ def self.off()
46
+ self.disable
47
+ end
48
+
49
+ self
50
+
51
+ end
52
+ end
53
+
54
+ def http_exec(command, options={})
55
+
56
+ url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
57
+
58
+ if options and options.any? then
59
+ h = options
60
+ url += '?' + \
61
+ URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
62
+ end
63
+
64
+ s = open(url).read
65
+
66
+ end
67
+
68
+ def location(options={})
69
+ http_exec 'location'
70
+ end
71
+
72
+ def say_current_time(options={})
73
+ http_exec 'say-current-time'
74
+ end
75
+
76
+ alias say_time say_current_time
77
+
78
+ def screen(state=nil)
79
+
80
+ if state then
81
+ http_exec 'screen', {on: state == :on}
82
+ else
83
+
84
+ def self.on()
85
+ http_exec 'screen', {on: true}
86
+ end
87
+
88
+ def self.off()
89
+ http_exec 'screen', {on: false}
90
+ end
91
+
92
+ self
93
+
94
+ end
95
+ end
96
+
97
+ def share_location(options={})
98
+ http_exec 'share-location'
99
+ end
100
+
101
+ def speak_text(obj)
102
+
103
+ options = case obj
104
+ when String
105
+ {text: obj}
106
+ when Hash
107
+ obj
108
+ end
109
+
110
+ http_exec 'speak-text', options
111
+ end
112
+
113
+ alias say speak_text
114
+
115
+ def stay_awake(options={})
116
+ http_exec 'stay-awake', options
117
+ end
118
+
119
+ def stay_awake_off(options={})
120
+ http_exec 'stay-awake-off', options
121
+ end
122
+
123
+ def take_picture(options={})
124
+ http_exec 'take-picture', options
125
+ end
126
+
127
+ alias take_photo take_picture
128
+
129
+
130
+ def toast(options={})
131
+ http_exec :toast, options
132
+ end
133
+
134
+ def torch(options={})
135
+ http_exec :torch
136
+ end
137
+
138
+ def vibrate(options={})
139
+ http_exec :vibrate
140
+ end
141
+
142
+
143
+ def write(s)
144
+
145
+ d = MacroDroid.new(RD_MACROS, deviceid: @deviceid,
146
+ remote_url: @remote_url, debug: false)
147
+
148
+ a = d.macros.select do |macro|
149
+
150
+ macro.triggers.find {|trigger| trigger.is_a? WebHookTrigger }.nil?
151
+
152
+ end
153
+ puts 'a: ' + a.length.inspect
154
+
155
+ aux_macros = %w(Disable Enable).map do |state|
156
+
157
+ rows = a[1..-1].map do |macro|
158
+
159
+ " Else If name = #{macro.title}
160
+ #{state} macro
161
+ #{macro.title}"
162
+ end
163
+
164
+ "
165
+ m: #{state} macro
166
+ v: name
167
+ t: webhook
168
+ a:
169
+ If name = #{a[0].title}
170
+ #{state} macro
171
+ #{a[0].title}
172
+ #{rows.join("\n")}
173
+ End If
174
+ " end
175
+
176
+ puts aux_macros.join
177
+ d.import aux_macros.join
178
+
179
+ # disable the non-webhook triggers by default
180
+ a.each(&:disable)
181
+
182
+ d.export s
183
+ puts 'exported to ' + s
184
+
185
+ end
186
+
187
+ alias export write
188
+
189
+ def method_missing2(method_name, *args)
190
+ http_exec(method_name, args.first)
191
+ end
192
+
193
+ end
194
+ end
@@ -0,0 +1,150 @@
1
+ module RemoteDroid
2
+
3
+ class Controller
4
+
5
+ attr_reader :model, :control
6
+ attr_accessor :title, :macros, :store
7
+
8
+ def initialize(mcs, model=MODEL, deviceid: nil, debug: false)
9
+
10
+ @debug = debug
11
+ @syslog = []
12
+
13
+ @control = Control.new(deviceid)
14
+ @macros = mcs.macros
15
+
16
+ if model then
17
+ @model = Model.new(model)
18
+ end
19
+
20
+ @store = {}
21
+ @query = Query.new(self)
22
+
23
+ # enable the required triggers on the Android device
24
+ #
25
+ names = @macros.map {|x| x.triggers.first.type}.uniq
26
+ #@control.enable names.first.to_s.gsub('_',' ')
27
+ puts 'Enabling ' + names.join(',')
28
+
29
+ Thread.new do
30
+ names.each do |title|
31
+ @control.enable title.to_s.gsub('_',' ')
32
+ sleep 0.8
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ def export(s)
39
+ @macros = MacroDroid.new(s).macros
40
+ end
41
+
42
+ def invoke(name, options={})
43
+
44
+ if @control.respond_to? name.to_sym then
45
+ @control.method(name.to_sym).call(options)
46
+ else
47
+ @control.http_exec name.to_sym, options
48
+ end
49
+ end
50
+
51
+ # Object Property (op)
52
+ # Helpful for accessing properites in dot notation
53
+ # e.g. op.livingroom.light.switch = 'off'
54
+ #
55
+ def op()
56
+ @model.op
57
+ end
58
+
59
+ def query(id=nil)
60
+
61
+ return @query unless id
62
+
63
+ @store[id] = nil
64
+
65
+ sys = %i(accelerometer_rotation)
66
+
67
+ global = [:airplane_mode_on, :bluetooth_on, :cell_on, :device_name, \
68
+ :usb_mass_storage_enabled, :wifi_on]
69
+
70
+ secure = %i(bluetooth_name flashlight_enabled)
71
+
72
+
73
+ # send http request via macrodroid.com API
74
+
75
+ if id.downcase.to_sym == :location then
76
+ @control.http_exec id
77
+ elsif sys.include? id
78
+ @control.http_exec :'query-setting-system', {qvar: id}
79
+ elsif global.include? id
80
+ @control.http_exec :'query-setting-global', {qvar: id}
81
+ elsif secure.include? id
82
+ @control.http_exec :'query-setting-secure', {qvar: id}
83
+ elsif id.downcase.to_sym == :'take-picture'
84
+ @control.http_exec id
85
+ else
86
+ @control.http_exec :query, {qvar: id}
87
+ end
88
+
89
+ # wait for the local variable to be updated
90
+ # timeout after 5 seoncds
91
+ t = Time.now
92
+
93
+ begin
94
+ sleep 1
95
+ end until @store[id] or Time.now > t + 10
96
+
97
+ return {warning: 'HTTP response timeout'} if Time.now > t+5
98
+
99
+ return @store[id]
100
+
101
+
102
+ end
103
+
104
+ def request(s)
105
+ @model.request s
106
+ end
107
+
108
+
109
+ def trigger(name, detail={time: Time.now})
110
+
111
+ macros = @macros.select do |macro|
112
+
113
+ puts 'macro: ' + macro.inspect if @debug
114
+
115
+ # fetch the associated properties from the model if possible and
116
+ # merge them into the detail.
117
+ #
118
+ valid_trigger = macro.match?(name, detail, @model.op)
119
+
120
+ puts 'valid_trigger: ' + valid_trigger.inspect if @debug
121
+
122
+ if valid_trigger then
123
+ @syslog << [Time.now, :trigger, name]
124
+ @syslog << [Time.now, :macro, macro.title]
125
+ end
126
+
127
+ valid_trigger
128
+
129
+ end
130
+
131
+ puts 'macros: ' + macros.inspect if @debug
132
+
133
+ macros.flat_map(&:run)
134
+ end
135
+
136
+ alias trigger_fired trigger
137
+
138
+ def update(id, val)
139
+
140
+ key = if %i(location take-picture).include? id
141
+ id
142
+ else
143
+ val.keys.first.to_sym
144
+ end
145
+
146
+ @store[key] = val
147
+ end
148
+
149
+ end
150
+ end