foscam-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +10 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/foscam-ruby.gemspec +34 -0
  9. data/lib/foscam-ruby.rb +8 -0
  10. data/lib/foscam/client.rb +425 -0
  11. data/lib/foscam/version.rb +3 -0
  12. data/spec/fixtures/vcr/foscam_camera_control_brightness.yml +42 -0
  13. data/spec/fixtures/vcr/foscam_camera_control_contrast.yml +42 -0
  14. data/spec/fixtures/vcr/foscam_camera_control_mode.yml +42 -0
  15. data/spec/fixtures/vcr/foscam_camera_control_orientation.yml +42 -0
  16. data/spec/fixtures/vcr/foscam_camera_control_resolution.yml +42 -0
  17. data/spec/fixtures/vcr/foscam_comm_write.yml +42 -0
  18. data/spec/fixtures/vcr/foscam_decoder_control.yml +42 -0
  19. data/spec/fixtures/vcr/foscam_get_camera_params.yml +52 -0
  20. data/spec/fixtures/vcr/foscam_get_forbidden.yml +84 -0
  21. data/spec/fixtures/vcr/foscam_get_misc.yml +66 -0
  22. data/spec/fixtures/vcr/foscam_get_params.yml +428 -0
  23. data/spec/fixtures/vcr/foscam_get_status.yml +68 -0
  24. data/spec/fixtures/vcr/foscam_reboot.yml +42 -0
  25. data/spec/fixtures/vcr/foscam_restore_factory.yml +42 -0
  26. data/spec/fixtures/vcr/foscam_set_alarm.yml +42 -0
  27. data/spec/fixtures/vcr/foscam_set_alias.yml +42 -0
  28. data/spec/fixtures/vcr/foscam_set_datetime.yml +42 -0
  29. data/spec/fixtures/vcr/foscam_set_ddns.yml +40 -0
  30. data/spec/fixtures/vcr/foscam_set_decoder.yml +42 -0
  31. data/spec/fixtures/vcr/foscam_set_forbidden.yml +40 -0
  32. data/spec/fixtures/vcr/foscam_set_ftp.yml +42 -0
  33. data/spec/fixtures/vcr/foscam_set_mail.yml +40 -0
  34. data/spec/fixtures/vcr/foscam_set_misc.yml +105 -0
  35. data/spec/fixtures/vcr/foscam_set_network.yml +40 -0
  36. data/spec/fixtures/vcr/foscam_set_pppoe.yml +42 -0
  37. data/spec/fixtures/vcr/foscam_set_upnp.yml +42 -0
  38. data/spec/fixtures/vcr/foscam_set_user2.yml +40 -0
  39. data/spec/fixtures/vcr/foscam_set_user3.yml +40 -0
  40. data/spec/fixtures/vcr/foscam_set_user4.yml +40 -0
  41. data/spec/fixtures/vcr/foscam_set_user5.yml +40 -0
  42. data/spec/fixtures/vcr/foscam_set_user6.yml +40 -0
  43. data/spec/fixtures/vcr/foscam_set_user7.yml +40 -0
  44. data/spec/fixtures/vcr/foscam_set_user8.yml +40 -0
  45. data/spec/fixtures/vcr/foscam_set_wifi.yml +40 -0
  46. data/spec/fixtures/vcr/foscam_snapshot.yml +236 -0
  47. data/spec/fixtures/vcr/foscam_upgrade_firmware.yml +40 -0
  48. data/spec/fixtures/vcr/foscam_upgrade_htmls.yml +40 -0
  49. data/spec/foscam/client_spec.rb +1269 -0
  50. data/spec/spec_helper.rb +24 -0
  51. metadata +301 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OWNmYzk4ZTEyZGZkMDJmNzUzMTZiNTg0M2EzYzBhYmExMDIyMGRhOA==
5
+ data.tar.gz: !binary |-
6
+ N2NlYzQ3N2JiYjNkNmYxMzc5OGViZGFjNjVkMDI1OGU0NzI4MWVlYQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NGIyYmM5ZGVhZjAwMzk3ZTU0ZGQzOGQ5ZDJmZTBkNGVkNGIyY2RkYTM1Yjk4
10
+ ZTc5YzVjM2IyZTIzMzRhNzdlNzZjMWZlOGVkYjBiM2Y0NGE5YjE3OGEwYmYx
11
+ YTIzNjcxYWJmYjVjNTllMjMxMWE3ZDAyNzNkYzJiNjE2ZjE3NDU=
12
+ data.tar.gz: !binary |-
13
+ NjFhMWNlZWI3YzE3OTdjNDU4OGY0NWYxMmVmOTE0YWVmZjI0NzA1YjE2Mjc0
14
+ Y2ZmMmFhNGRlNDAzZjU4OTA5ODEyMTBkNjhjZmM0NzJiYzYxN2U1NWFlMTY0
15
+ NmEyZWVmZGNjNzgxN2M4NTE5N2VjYTgwZjkwMmViMTNkN2M3YzA=
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in foscam-ruby.gemspec
4
+ gemspec
@@ -0,0 +1,10 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+
5
+ guard 'rspec' do
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+ end
10
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Chris Waddington
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Foscam::Ruby
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'foscam-ruby'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install foscam-ruby
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'foscam/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "foscam-ruby"
8
+ spec.version = Foscam::VERSION
9
+ spec.authors = ["Chris Waddington"]
10
+ spec.email = ["cwadding@gmail.com"]
11
+ spec.description = %q{A ruby client for the foscam SDK.}
12
+ spec.summary = %q{A ruby client for the foscam SDK.}
13
+ spec.homepage = "https://github.com/cwadding/foscam-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'faraday'
22
+ spec.add_dependency 'mini_magick'
23
+ spec.add_dependency 'active_support'
24
+ spec.add_dependency 'i18n'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency 'rspec'#, '~> 2.10.0'
29
+ spec.add_development_dependency 'guard'
30
+ spec.add_development_dependency 'guard-rspec'
31
+ spec.add_development_dependency 'rb-fsevent'
32
+ spec.add_development_dependency 'vcr'
33
+ spec.add_development_dependency 'webmock'
34
+ end
@@ -0,0 +1,8 @@
1
+ require "foscam/version"
2
+ require "faraday"
3
+ require "mini_magick"
4
+ require "active_support/all"
5
+
6
+ module Foscam
7
+ autoload :Client, 'foscam/client'
8
+ end
@@ -0,0 +1,425 @@
1
+ module Foscam
2
+
3
+ DDNS_STATUS = {
4
+ 0 => "No Action",
5
+ 1 => "It's connecting...",
6
+ 2 => "Can't connect to the Server",
7
+ 3 => "Dyndns Succeed",
8
+ 4 => "DynDns Failed: Dyndns.org Server Error",
9
+ 5 => "DynDns Failed: Incorrect User or Password",
10
+ 6 => "DynDns Failed: Need Credited User",
11
+ 7 => "DynDns Failed: Illegal Host Format",
12
+ 8 => "DynDns Failed: The Host Does not Exist",
13
+ 9 => "DynDns Failed: The Host Does not Belong to You",
14
+ 10 => "DynDns Failed: Too Many or Too Few Hosts",
15
+ 11 => "DynDns Failed: The Host is Blocked for Abusing",
16
+ 12 => "DynDns Failed: Bad Reply from Server",
17
+ 13 => "DynDns Failed: Bad Reply from Server",
18
+ 14 => "Oray Failed: Bad Reply from Server",
19
+ 15 => "Oray Failed: Incorrect User or Password",
20
+ 16 => "Oray Failed: Incorrect Hostname",
21
+ 17 => "Oray Succeed"
22
+ }
23
+
24
+ UPNP_STATUS = {
25
+ 0 => "No Action",
26
+ 1 => "Succeed",
27
+ 2 => "Device System Error",
28
+ 3 => "Errors in Network Communication",
29
+ 4 => "Errors in Chat with UPnP Device",
30
+ 5 => "Rejected by UPnP Device, Maybe Port Conflict"
31
+ }
32
+
33
+ ALARM_STATUS = {
34
+ 0 => "No alarm",
35
+ 1 => "Motion alarm",
36
+ 2 => "Input Alarm"
37
+ }
38
+
39
+ CAMERA_PARAMS_MODE = {
40
+ 0 => "50hz",
41
+ 1 => "60hz",
42
+ 2 => "outdoor"
43
+ }
44
+ CAMERA_CONTROL_MODE = CAMERA_PARAMS_MODE.inject({}){|memo,(k,v)| memo[v.to_sym] = k; memo}
45
+
46
+ CAMERA_PARAMS_ORIENTATION = {
47
+ 0 => "default",
48
+ 1 => "flip",
49
+ 2 => "mirror",
50
+ 3 => "flip+mirror"
51
+ }
52
+
53
+ CAMERA_CONTROL_ORIENTATION = CAMERA_PARAMS_ORIENTATION.inject({}){|memo,(k,v)| memo[v.to_sym] = k; memo}
54
+
55
+ CAMERA_PARAMS_RESOLUTION = {
56
+ 8 => "qvga",
57
+ 32 => "vga"
58
+ }
59
+
60
+ CAMERA_CONTROL_RESOLUTION = CAMERA_PARAMS_RESOLUTION.inject({}){|memo,(k,v)| memo[v.to_sym] = k; memo}
61
+
62
+ CAMERA_CONTROLS = {
63
+ resolution: 0,
64
+ brightness: 1,
65
+ contrast: 2,
66
+ mode: 3,
67
+ flip: 5
68
+ }
69
+
70
+ DECODER_CONTROLS = {
71
+ up: 0,
72
+ stop_up: 1,
73
+ down: 2,
74
+ stop_down: 3,
75
+ left: 4,
76
+ stop_left: 5,
77
+ right: 6,
78
+ stop_right: 7,
79
+ center: 25,
80
+ vertical_patrol: 26,
81
+ stop_vertical_patrol: 27,
82
+ horizon_patrol: 28,
83
+ stop_horizon_patrol: 29,
84
+ io_output_high: 94,
85
+ io_output_low: 95,
86
+ }
87
+
88
+ USER_PERMISSIONS = {
89
+ 0 => :visitor,
90
+ 1 => :operator,
91
+ 2 => :administrator
92
+ }
93
+
94
+ PTZ_AUTO_PATROL_TYPE = {
95
+ 0 => :none,
96
+ 1 => :horizontal,
97
+ 2 => :vertical,
98
+ 3 => :"horizontal+vertical"
99
+ }
100
+ PTZ_AUTO_PATROL_TYPE_ID = PTZ_AUTO_PATROL_TYPE.invert
101
+
102
+ LED_MODE = {
103
+ 0 => :mode1,
104
+ 1 => :mode2,
105
+ 2 => :disabled
106
+ }
107
+ LED_MODE_ID = LED_MODE.invert
108
+ DECODER_BAUD = {
109
+ 9 => :B1200,
110
+ 11 => :B2400,
111
+ 12 => :B4800,
112
+ 13 => :B9600,
113
+ 14 => :B19200,
114
+ 15 => :B38400,
115
+ 4097 => :B57600,
116
+ 4098 => :B115200
117
+ }
118
+
119
+ DECODER_BAUD_ID = DECODER_BAUD.invert
120
+
121
+
122
+ class Client
123
+
124
+ attr_accessor :url, :username, :password, :connection
125
+
126
+ def initialize(args = {})
127
+ @url = args.delete(:url)
128
+ @username = args.delete(:username)
129
+ @password = args.delete(:password)
130
+ connect(@url, @username, @password)
131
+ end
132
+
133
+ def connect(url, username = nil, password = nil)
134
+ @url = url
135
+ @username = username
136
+ @password = password
137
+ @connection = Faraday.new( url: @url) unless @url.nil?
138
+ @connection.basic_auth(@username, @password) unless @username.nil? && @password.nil?
139
+ end
140
+
141
+ def snapshot
142
+ response = @connection.get('snapshot.cgi')
143
+ response.success? ? ::MiniMagick::Image.read(response.body) : nil
144
+ end
145
+
146
+ def get_status
147
+ response = @connection.get('get_status.cgi')
148
+ response = response.success? ? parse_response(response) : {}
149
+ unless response.empty?
150
+ response[:ddns_status] = DDNS_STATUS[response[:ddns_status].to_i]
151
+ response[:upnp_status] = UPNP_STATUS[response[:upnp_status].to_i]
152
+ response[:alarm_status] = ALARM_STATUS[response[:alarm_status].to_i]
153
+ response[:now] = DateTime.strptime(response[:now],'%s')
154
+ end
155
+ response
156
+ end
157
+
158
+ def get_camera_params
159
+ response = @connection.get('get_camera_params.cgi')
160
+ response = response.success? ? parse_response(response) : {}
161
+ unless response.empty?
162
+ response[:flip] = CAMERA_PARAMS_ORIENTATION[response[:flip].to_i]
163
+ response[:mode] = CAMERA_PARAMS_MODE[response[:mode].to_i]
164
+ response[:resolution] = CAMERA_PARAMS_RESOLUTION[response[:resolution].to_i]
165
+ [:brightness, :contrast].each {|field| response[field] = response[field].to_i}
166
+ end
167
+ response
168
+ end
169
+
170
+ def decoder_control(action)
171
+ case action
172
+ when Symbol || String
173
+ action_id = DECODER_CONTROLS[action.to_sym]
174
+ else
175
+ action_id = action
176
+ end
177
+ response = @connection.get("decoder_control.cgi?command=#{action_id}")
178
+ response.success?
179
+ end
180
+
181
+ def camera_control(params)
182
+ params.all? do |key, value|
183
+ # validation
184
+ case key
185
+ when :resolution
186
+ case value
187
+ when Integer
188
+ throw "invalid parameter value" unless [8,32].include?(value)
189
+ when String || Symbol
190
+ throw "invalid parameter value" unless ["vga","qvga"].include?(value.to_s.downcase)
191
+ if value.to_s.downcase == "vga"
192
+ value = 32
193
+ elsif value.to_s.downcase == "qvga"
194
+ value = 8
195
+ end
196
+ else
197
+ throw "invalid parameter value type"
198
+ end
199
+ when :brightness
200
+ throw "invalid parameter value" if value.to_i < 0 || value.to_i > 255
201
+ when :contrast
202
+ throw "invalid parameter value" if value.to_i < 0 || value.to_i > 6
203
+ when :mode
204
+ case value
205
+ when Integer
206
+ throw "invalid parameter value" if value.to_i < 0 || value.to_i > 2
207
+ when Symbol || String
208
+ throw "invalid parameter value" unless CAMERA_CONTROL_MODE.keys.include?(value.to_s.downcase.to_sym)
209
+ value = CAMERA_CONTROL_MODE[value.to_s.downcase.to_sym]
210
+ else
211
+ throw "invalid parameter value type"
212
+ end
213
+ when :flip
214
+ case value
215
+ when Integer
216
+ throw "invalid parameter value" if value.to_i < 0 || value.to_i > 3
217
+ when String || Symbol
218
+ throw "invalid parameter value" unless CAMERA_CONTROL_ORIENTATION.keys.include?(value.to_s.downcase.to_sym)
219
+ value = CAMERA_CONTROL_ORIENTATION[value.to_s.downcase.to_sym]
220
+ else
221
+ throw "invalid parameter value type"
222
+ end
223
+ else
224
+ throw "invalid parameter"
225
+ end
226
+
227
+ response = @connection.get("camera_control.cgi?param=#{CAMERA_CONTROLS[key.to_sym]}&value=#{value}")
228
+ response.success?
229
+ end
230
+ end
231
+
232
+ def reboot
233
+ response = @connection.get("reboot.cgi")
234
+ response.success?
235
+ end
236
+
237
+ def restore_factory
238
+ response = @connection.get("restore_factory.cgi")
239
+ response.success?
240
+ end
241
+
242
+ def get_params
243
+ response = @connection.get("get_params.cgi")
244
+ response = response.success? ? parse_response(response) : {}
245
+ unless response.empty?
246
+ response[:now] = DateTime.strptime(response[:now],'%s')
247
+ [:ntp_enable, :wifi_enable, :pppoe_enable, :upnp_enable, :alarm_schedule_enable, :ftp_schedule_enable].each do |field|
248
+ response[field] = response[field].to_i > 0
249
+ end
250
+ [:ftp_schedule_sun_0, :ftp_schedule_sun_1, :ftp_schedule_sun_2,
251
+ :ftp_schedule_mon_0, :ftp_schedule_mon_1, :ftp_schedule_mon_2,
252
+ :ftp_schedule_tue_0, :ftp_schedule_tue_1, :ftp_schedule_tue_2,
253
+ :ftp_schedule_wed_0, :ftp_schedule_wed_1, :ftp_schedule_wed_2,
254
+ :ftp_schedule_thu_0, :ftp_schedule_thu_1, :ftp_schedule_thu_2,
255
+ :ftp_schedule_fri_0, :ftp_schedule_fri_1, :ftp_schedule_fri_2,
256
+ :ftp_schedule_sat_0, :ftp_schedule_sat_1, :ftp_schedule_sat_2,
257
+ :alarm_schedule_sun_0, :alarm_schedule_sun_1, :alarm_schedule_sun_2,
258
+ :alarm_schedule_mon_0, :alarm_schedule_mon_1, :alarm_schedule_mon_2,
259
+ :alarm_schedule_tue_0, :alarm_schedule_tue_1, :alarm_schedule_tue_2,
260
+ :alarm_schedule_wed_0, :alarm_schedule_wed_1, :alarm_schedule_wed_2,
261
+ :alarm_schedule_thu_0, :alarm_schedule_thu_1, :alarm_schedule_thu_2,
262
+ :alarm_schedule_fri_0, :alarm_schedule_fri_1, :alarm_schedule_fri_2,
263
+ :alarm_schedule_sat_0, :alarm_schedule_sat_1, :alarm_schedule_sat_2,
264
+ :daylight_savings_time, :ddns_proxy_port, :ftp_port, :mail_port, :port, :dev2_port, :dev3_port, :dev4_port, :dev5_port, :dev6_port, :dev7_port, :dev8_port, :dev9_port].each do |field|
265
+ response[field] = response[field].to_i
266
+ end
267
+ [:user1_pri, :user2_pri, :user3_pri, :user4_pri, :user5_pri, :user6_pri, :user7_pri, :user8_pri].each do |key|
268
+ response[key] = USER_PERMISSIONS[response[key].to_i]
269
+ end
270
+ end
271
+ response
272
+ end
273
+
274
+ def upgrade_firmware
275
+ response = @connection.post("upgrade_firmware.cgi")
276
+ end
277
+
278
+ def upgrade_htmls
279
+ response = @connection.post("upgrade_htmls.cgi")
280
+ end
281
+
282
+ def set_alias(name)
283
+ throw "invalid parameter value" if name.length > 20
284
+ response = @connection.get("set_alias.cgi?alias=#{name}")
285
+ response.success?
286
+ end
287
+
288
+ def set_datetime(params)
289
+ # Extract the time zone
290
+ throw "invalid parameter value" if params.has_key?(:ntp_svr) && params[:ntp_svr].length > 64
291
+ response = @connection.get("set_datetime.cgi?#{params.to_query}")
292
+ response.success?
293
+ end
294
+
295
+ def set_users(params)
296
+ [:user1, :pwd1, :user2, :pwd2, :user3, :pwd3, :user4, :pwd4, :user5, :pwd5, :user6, :pwd6, :user7, :pwd7, :user8, :pwd8].each do |key|
297
+ throw "invalid parameter value" if params.has_key?(key) && params[key].length > 12
298
+ end
299
+ response = @connection.get("set_users.cgi?#{params.to_query}")
300
+ response.success?
301
+ end
302
+
303
+ # def set_devices(params)
304
+ # response = @connection.get("set_devices.cgi?#{params.to_query}")
305
+ # end
306
+
307
+ def set_network(params)
308
+ response = @connection.get("set_network.cgi?#{params.to_query}")
309
+ response.success?
310
+ end
311
+
312
+ def set_wifi(params)
313
+ response = @connection.get("set_wifi.cgi?#{params.to_query}")
314
+ response.success?
315
+ end
316
+
317
+ def set_pppoe(params)
318
+ throw "invalid parameter value" if params.has_key?(:user) && params[:user].length > 20
319
+ throw "invalid parameter value" if params.has_key?(:pwd) && params[:pwd].length > 20
320
+ response = @connection.get("set_pppoe.cgi?#{params.to_query}")
321
+ response.success?
322
+ end
323
+
324
+ def set_upnp(flag)
325
+ response = @connection.get("set_upnp.cgi?enable=#{handle_boolean(flag)}")
326
+ response.success?
327
+ end
328
+
329
+ def set_ddns(params)
330
+ throw "invalid parameter value" if params.has_key?(:user) && params[:user].length > 20
331
+ throw "invalid parameter value" if params.has_key?(:pwd) && params[:pwd].length > 20
332
+ throw "invalid parameter value" if params.has_key?(:host) && params[:host].length > 40
333
+ response = @connection.get("set_ddns.cgi?#{params.to_query}")
334
+ response.success?
335
+ end
336
+
337
+ def set_ftp(params)
338
+ response = @connection.get("set_ftp.cgi?#{params.to_query}")
339
+ response.success?
340
+ end
341
+
342
+ def set_mail(params)
343
+ throw "invalid parameter value" if params.has_key?(:user) && params[:user].length > 20
344
+ throw "invalid parameter value" if params.has_key?(:pwd) && params[:pwd].length > 20
345
+ [:sender, :receiver1, :receiver2, :receiver3, :receiver4].each do |key|
346
+ throw "invalid parameter value" if params.has_key?(key) && params[key].length > 40
347
+ end
348
+ response = @connection.get("set_mail.cgi?#{params.to_query}")
349
+ response.success?
350
+ end
351
+
352
+ def set_alarm(params)
353
+ response = @connection.get("set_alarm.cgi?#{params.to_query}")
354
+ response.success?
355
+ end
356
+
357
+ def comm_write(params)
358
+ response = @connection.get("comm_write.cgi?#{params.to_query}")
359
+ response.success?
360
+ end
361
+
362
+ def set_forbidden(params)
363
+ response = @connection.get("set_forbidden.cgi?#{params.to_query}")
364
+ response.success?
365
+ end
366
+
367
+ def get_forbidden
368
+ response = @connection.get("get_forbidden.cgi")
369
+ response.success? ? parse_response(response) : {}
370
+ end
371
+
372
+ def set_misc(params)
373
+ url_params = params.clone
374
+ [:ptz_patrol_rate, :ptz_patrol_up_rate, :ptz_patrol_down_rate, :ptz_patrol_left_rate, :ptz_patrol_right_rate].each do |key|
375
+ throw "invalid parameter value" if (url_params.has_key?(key) && (url_params[key].to_i < 0 || url_params[key].to_i > 100))
376
+ end
377
+ [:ptz_auto_patrol_interval, :ptz_patrol_h_rounds, :ptz_patrol_v_rounds].each do |key|
378
+ throw "invalid parameter value" if url_params.has_key?(key) && url_params[key].to_i < 0
379
+ end
380
+ [:ptz_disable_preset, :ptz_preset_onstart, :ptz_center_onstart].each do |key|
381
+ url_params[key] = handle_boolean(url_params[key]) if url_params.has_key?(key)
382
+ end
383
+ url_params[:led_mode] = LED_MODE_ID[url_params[:led_mode]] if url_params[:led_mode].is_a?(String) || url_params[:led_mode].is_a?(Symbol)
384
+ url_params[:ptz_auto_patrol_type] = PTZ_AUTO_PATROL_TYPE_ID[url_params[:ptz_auto_patrol_type]] if url_params[:ptz_auto_patrol_type].is_a?(String) || url_params[:ptz_auto_patrol_type].is_a?(Symbol)
385
+ response = @connection.get("set_misc.cgi?#{url_params.to_query}")
386
+ response.success?
387
+ end
388
+
389
+ def get_misc
390
+ response = @connection.get("get_misc.cgi")
391
+ response = response.success? ? parse_response(response) : {}
392
+ unless response.empty?
393
+ [:ptz_disable_preset, :ptz_preset_onstart, :ptz_center_onstart].each do |field|
394
+ response[field] = response[field].to_i > 0
395
+ end
396
+ [:ptz_auto_patrol_interval, :ptz_patrol_h_rounds, :ptz_patrol_v_rounds, :ptz_patrol_rate, :ptz_patrol_up_rate, :ptz_patrol_down_rate, :ptz_patrol_left_rate, :ptz_patrol_right_rate].each do |field|
397
+ response[field] = response[field].to_i
398
+ end
399
+ response[:led_mode] = LED_MODE[response[:led_mode].to_i]
400
+ response[:ptz_auto_patrol_type] = PTZ_AUTO_PATROL_TYPE[response[:ptz_auto_patrol_type].to_i]
401
+ response
402
+ end
403
+ response
404
+ end
405
+
406
+ def set_decoder(baud)
407
+ baud = DECODER_BAUD_ID[baud.to_sym] if baud.is_a?(String) || baud.is_a?(Symbol)
408
+ response = @connection.get("set_decoder.cgi?baud=#{baud}")
409
+ response.success?
410
+ end
411
+
412
+ private
413
+
414
+ def parse_response(response)
415
+ response.body.scan(/var (\w+)=([^;]+);[\s+]?/).inject({}) do | params, pair |
416
+ params.merge(pair.first.to_sym => pair.last.gsub(/'/, ''))
417
+ end
418
+ end
419
+
420
+ def handle_boolean(flag)
421
+ flag ? 1 : 0
422
+ end
423
+
424
+ end
425
+ end