foscam-ruby 0.0.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.
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