remotedroid 0.4.3 → 0.5.3

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