remotedroid 0.4.4 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,211 @@
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 fill_clipboard(text)
76
+ control.fill_clipboard clipboard: text
77
+ end
78
+
79
+ alias copy fill_clipboard
80
+
81
+ def hotspot(state=nil)
82
+ control.hotspot state
83
+ end
84
+
85
+ def launch_activity(app='')
86
+ control.launch_activity(app)
87
+ end
88
+
89
+ alias launch launch_activity
90
+
91
+ def location()
92
+ query.location
93
+ end
94
+
95
+ def location_watch(refresh: '1 minute', interval: refresh,
96
+ duration: '30 minutes')
97
+
98
+
99
+ d = ChronicDuration.parse(duration)
100
+ seconds = ChronicDuration.parse(interval)
101
+ puts ("monitoring location every %s for %s" % [interval, duration]).info
102
+
103
+ Thread.new do
104
+
105
+ t = Time.now + d
106
+
107
+ begin
108
+
109
+ query.location
110
+ sleep seconds
111
+
112
+ end until Time.now >= t
113
+
114
+ end
115
+
116
+ end
117
+
118
+ def ip()
119
+ query.ip
120
+ end
121
+
122
+ def next()
123
+ control_media(option='Next')
124
+ end
125
+
126
+ def pause()
127
+ control_media(option='Pause')
128
+ end
129
+
130
+ def play()
131
+ control_media(option='Play')
132
+ end
133
+
134
+ def play_pause()
135
+ control_media(option='Play/Pause')
136
+ end
137
+
138
+ def photo()
139
+ take_picture
140
+ end
141
+
142
+ def previous()
143
+ control_media(option='Previous')
144
+ end
145
+
146
+ def say(text)
147
+ control.speak_text text
148
+ end
149
+
150
+ def say_time()
151
+ control.say_time
152
+ end
153
+
154
+ alias saytime say_time
155
+
156
+ def screen(state=nil)
157
+ control.screen state
158
+ end
159
+
160
+ def screen_on()
161
+ screen :on
162
+ end
163
+
164
+ def screen_off()
165
+ screen :off
166
+ end
167
+
168
+ def stay_awake()
169
+ control.stay_awake
170
+ end
171
+
172
+ def stay_awake_off()
173
+ control.stay_awake_off
174
+ end
175
+
176
+ def stop()
177
+ control_media(option='Stop')
178
+ end
179
+
180
+ def take_picture(ftp_src: nil, fileout: '.')
181
+
182
+ #screen.on
183
+ r = query.take_picture
184
+
185
+ if ftp_src then
186
+
187
+ # give the device a second to write the image to file
188
+ sleep 1
189
+
190
+ credentials, dir = ftp_src.match(/(ftp:\/\/[^\/]+)\/([^$]+)/).captures
191
+ ftp = MyMediaFTP.new(credentials)
192
+ ftp.cd dir
193
+ filename = ftp.ls.sort_by {|x| x[:ctime]}.last[:name]
194
+ ftp.cp filename, fileout
195
+
196
+ end
197
+
198
+ end
199
+
200
+ alias take_photo take_picture
201
+
202
+ def torch()
203
+ control.torch
204
+ end
205
+
206
+ def vibrate
207
+ control.vibrate
208
+ end
209
+
210
+ end
211
+ end
@@ -0,0 +1,211 @@
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 fill_clipboard(options={})
32
+ http_exec 'fill-clipboard', options
33
+ end
34
+
35
+ def force_macro_run(options={})
36
+ http_exec option[:macro_name].downcase.gsub(/ /,'-')
37
+ end
38
+
39
+ def hotspot(state=nil)
40
+
41
+ if state then
42
+ http_exec 'hotspot', {enable: state == :enable}
43
+ else
44
+
45
+ def self.enable()
46
+ http_exec 'hotspot', {enable: true}
47
+ end
48
+
49
+ def self.on()
50
+ self.enable
51
+ end
52
+
53
+ def self.disable()
54
+ http_exec 'hotspot', {enable: false}
55
+ end
56
+
57
+ def self.off()
58
+ self.disable
59
+ end
60
+
61
+ self
62
+
63
+ end
64
+ end
65
+
66
+ def http_exec(command, options={})
67
+
68
+ url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
69
+
70
+ if options and options.any? then
71
+ h = options
72
+ url += '?' + \
73
+ URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
74
+ end
75
+
76
+ s = open(url).read
77
+
78
+ end
79
+
80
+ def launch_activity(options={})
81
+ app = options[:app].downcase.gsub(/ /,'-')
82
+ http_exec 'launch-' + app
83
+ end
84
+
85
+ def location(options={})
86
+ http_exec 'location'
87
+ end
88
+
89
+ def say_current_time(options={})
90
+ http_exec 'say-current-time'
91
+ end
92
+
93
+ alias say_time say_current_time
94
+
95
+ def screen(state=nil)
96
+
97
+ if state then
98
+ http_exec 'screen', {on: state == :on}
99
+ else
100
+
101
+ def self.on()
102
+ http_exec 'screen', {on: true}
103
+ end
104
+
105
+ def self.off()
106
+ http_exec 'screen', {on: false}
107
+ end
108
+
109
+ self
110
+
111
+ end
112
+ end
113
+
114
+ def share_location(options={})
115
+ http_exec 'share-location'
116
+ end
117
+
118
+ def speak_text(obj)
119
+
120
+ options = case obj
121
+ when String
122
+ {text: obj}
123
+ when Hash
124
+ obj
125
+ end
126
+
127
+ http_exec 'speak-text', options
128
+ end
129
+
130
+ alias say speak_text
131
+
132
+ def stay_awake(options={})
133
+ http_exec 'stay-awake', options
134
+ end
135
+
136
+ def stay_awake_off(options={})
137
+ http_exec 'stay-awake-off', options
138
+ end
139
+
140
+ def take_picture(options={})
141
+ http_exec 'take-picture', options
142
+ end
143
+
144
+ alias take_photo take_picture
145
+
146
+
147
+ def toast(options={})
148
+ http_exec :toast, options
149
+ end
150
+
151
+ def torch(options={})
152
+ http_exec :torch
153
+ end
154
+
155
+ def vibrate(options={})
156
+ http_exec :vibrate
157
+ end
158
+
159
+
160
+ def write(s)
161
+
162
+ d = MacroDroid.new(RD_MACROS, deviceid: @deviceid,
163
+ remote_url: @remote_url, debug: false)
164
+
165
+ a = d.macros.select do |macro|
166
+
167
+ macro.triggers.find {|trigger| trigger.is_a? WebHookTrigger }.nil?
168
+
169
+ end
170
+ puts 'a: ' + a.length.inspect
171
+
172
+ aux_macros = %w(Disable Enable).map do |state|
173
+
174
+ rows = a[1..-1].map do |macro|
175
+
176
+ " Else If name = #{macro.title}
177
+ #{state} macro
178
+ #{macro.title}"
179
+ end
180
+
181
+ "
182
+ m: #{state} macro
183
+ v: name
184
+ t: webhook
185
+ a:
186
+ If name = #{a[0].title}
187
+ #{state} macro
188
+ #{a[0].title}
189
+ #{rows.join("\n")}
190
+ End If
191
+ " end
192
+
193
+ puts aux_macros.join
194
+ d.import aux_macros.join
195
+
196
+ # disable the non-webhook triggers by default
197
+ a.each(&:disable)
198
+
199
+ d.export s
200
+ puts 'exported to ' + s
201
+
202
+ end
203
+
204
+ alias export write
205
+
206
+ def method_missing2(method_name, *args)
207
+ http_exec(method_name, args.first)
208
+ end
209
+
210
+ end
211
+ 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