botvac 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 54cc8a85f652eb06c58b8df33abd1ebad8521a3d
4
+ data.tar.gz: 5462bcce82def5447f40955da15dd2adc4901106
5
+ SHA512:
6
+ metadata.gz: 071f771d5b2927a1c62a0ac25355307c30946cf12d1be3ecac0af09b54232f0a3ff05786963d42026372967a7bd0a29249855428b326f15936a4fc3c2593e1eb
7
+ data.tar.gz: 25a0a2fe541e62b834eabb589ed58d6a2e92e66a198e0153eb7090be3a45dbc250b9c98964d6922d9035d6213becedaf9bef0bbebfb00f3694a738d673b0c2f1
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ Kayakoapi.java
2
+ Kayakoapi.class
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ # A sample Gemfile
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,94 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ botvac (0.1.0)
5
+ faraday
6
+ faraday_middleware
7
+ rack
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.4.0)
13
+ coderay (1.1.0)
14
+ crack (0.4.2)
15
+ safe_yaml (~> 1.0.0)
16
+ diff-lcs (1.2.5)
17
+ faraday (0.9.2)
18
+ multipart-post (>= 1.2, < 3)
19
+ faraday_middleware (0.10.0)
20
+ faraday (>= 0.7.4, < 0.10)
21
+ ffi (1.9.10)
22
+ formatador (0.2.5)
23
+ guard (2.13.0)
24
+ formatador (>= 0.2.4)
25
+ listen (>= 2.7, <= 4.0)
26
+ lumberjack (~> 1.0)
27
+ nenv (~> 0.1)
28
+ notiffany (~> 0.0)
29
+ pry (>= 0.9.12)
30
+ shellany (~> 0.0)
31
+ thor (>= 0.18.1)
32
+ guard-compat (1.2.1)
33
+ guard-rspec (4.6.4)
34
+ guard (~> 2.1)
35
+ guard-compat (~> 1.1)
36
+ rspec (>= 2.99.0, < 4.0)
37
+ hashdiff (0.2.3)
38
+ listen (3.0.5)
39
+ rb-fsevent (>= 0.9.3)
40
+ rb-inotify (>= 0.9)
41
+ lumberjack (1.0.10)
42
+ method_source (0.8.2)
43
+ multipart-post (2.0.0)
44
+ nenv (0.2.0)
45
+ notiffany (0.0.8)
46
+ nenv (~> 0.1)
47
+ shellany (~> 0.0)
48
+ pry (0.10.3)
49
+ coderay (~> 1.1.0)
50
+ method_source (~> 0.8.1)
51
+ slop (~> 3.4)
52
+ rack (1.6.4)
53
+ rake (10.5.0)
54
+ rb-fsevent (0.9.7)
55
+ rb-inotify (0.9.5)
56
+ ffi (>= 0.5.0)
57
+ rspec (3.4.0)
58
+ rspec-core (~> 3.4.0)
59
+ rspec-expectations (~> 3.4.0)
60
+ rspec-mocks (~> 3.4.0)
61
+ rspec-core (3.4.1)
62
+ rspec-support (~> 3.4.0)
63
+ rspec-expectations (3.4.0)
64
+ diff-lcs (>= 1.2.0, < 2.0)
65
+ rspec-support (~> 3.4.0)
66
+ rspec-mocks (3.4.1)
67
+ diff-lcs (>= 1.2.0, < 2.0)
68
+ rspec-support (~> 3.4.0)
69
+ rspec-support (3.4.1)
70
+ safe_yaml (1.0.4)
71
+ shellany (0.0.1)
72
+ slop (3.6.0)
73
+ thor (0.19.1)
74
+ timecop (0.8.0)
75
+ webmock (1.22.3)
76
+ addressable (>= 2.3.6)
77
+ crack (>= 0.3.2)
78
+ hashdiff
79
+
80
+ PLATFORMS
81
+ ruby
82
+
83
+ DEPENDENCIES
84
+ botvac!
85
+ bundler (>= 1.6.2)
86
+ guard-rspec
87
+ pry
88
+ rake (~> 10.0)
89
+ rspec
90
+ timecop
91
+ webmock
92
+
93
+ BUNDLED WITH
94
+ 1.11.2
data/Guardfile ADDED
@@ -0,0 +1,22 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard :rspec, cmd: 'rspec' do
19
+ watch(%r{^spec/.+_spec\.rb$})
20
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
21
+ watch('spec/spec_helper.rb') { "spec" }
22
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2016 Lars Brillert
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
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # Botvac
2
+
3
+ This is an unofficial API client which can help you
4
+ to interact with the Neato cloudservices which are
5
+ used to control you Neato Connected vaccum robot.
6
+
7
+ ## Disclaimer
8
+
9
+ As this is an official client to the API which required
10
+ to reverse the HTTP Authentication mechanism used by
11
+ Neato things are topic to be unstable and maybe unreliable.
12
+
13
+ Please don't blame me :) Just drink a beer and relax, things
14
+ will maybe work out in the future ... and maybe not.
15
+
16
+ ## Usage
17
+
18
+ Add the gem into your project using `bundler`
19
+
20
+
21
+ gem 'botvac'
22
+
23
+ ### Creating a new robot
24
+
25
+ In order to crate a new robot, you'll need to figure out
26
+ the correct serial (easy) and the associated secret (less easy).
27
+
28
+ The serial number of your robot is likly to be shown somewhere
29
+ in your Android/iOS application.
30
+
31
+ The current process to figure out the robots secret is more
32
+ cumbersome, as it requires you to sniff the traffic between
33
+ you smartphone and the neato servers. Looks out for a
34
+ request to
35
+
36
+ https://beehive.neatocloud.com/dashboard
37
+
38
+ which will hold all necessary data :)
39
+
40
+ I'll add a more convinent way to obtain this in
41
+ future versions.
42
+
43
+ Once you have the serial and secret create a new robot object
44
+
45
+ mrrobot = Botvac::Robot.new(<serial>, <secret>)
46
+
47
+ Congratulatins, you can now inteact with your robot!!!
48
+
49
+ mrrobot.get_robot_state
50
+
51
+ Will give you some basic information about the status of
52
+ your connected robot.
53
+
54
+ There's more to discover! Currently there's all this avalivale:
55
+
56
+ * start_cleaning
57
+ * pause_cleaning
58
+ * stop_cleaning
59
+ * send_to_base
60
+ * get_robot_state
61
+ * disable_schedule
62
+ * enable_schedule
63
+ * get_schedule
64
+
65
+ The method names should give you an idea what the specific action will
66
+ cause. Still this is not all, but that's what there for the moment.
67
+
68
+ ## Web Server
69
+
70
+ Botvac ships with a ultra basic web server which can be used to let
71
+ the robot easily interact with differnt systems just with calling
72
+ a HTTP endpoint.
73
+
74
+ rackup -r 'botvac/web' -b "run Botvac::Web.new"
75
+
76
+ The environemnt variables `SERIAL` and `SECRET` are
77
+ mandatory to set!
78
+
79
+ curl http://localhost:9292/get_robot_state
80
+
81
+ Will make the action start. To trigger other activities, just
82
+ change the requested URL to one of the above method names.
83
+
84
+ ## Contributing
85
+
86
+ 1. Fork it ( http://github.com/<my-github-username>/botvac/fork )
87
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
88
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
89
+ 4. Push to the branch (`git push origin my-new-feature`)
90
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/botvac.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'botvac/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "botvac"
8
+ spec.version = Botvac::VERSION
9
+ spec.authors = ["Lars Brillert"]
10
+ spec.email = ["lars@railslove.com"]
11
+ spec.summary = %q{talk to your botvac connected robot}
12
+ spec.description = <<-description
13
+ Botvac allows you to interact with the Neato cloud service
14
+ which controls your robot without making use of the Android/iOS
15
+ application.
16
+ description
17
+
18
+ spec.homepage = "https://github.com/kangguru/botvac"
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0")
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency "faraday"
27
+ spec.add_dependency "faraday_middleware"
28
+ spec.add_dependency "rack"
29
+
30
+ spec.add_development_dependency "bundler", ">= 1.6.2"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec"
33
+ spec.add_development_dependency "pry"
34
+ spec.add_development_dependency "webmock"
35
+ spec.add_development_dependency "guard-rspec"
36
+ spec.add_development_dependency "timecop"
37
+ end
@@ -0,0 +1,28 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIE3DCCA8SgAwIBAgIJALHphD11lrmHMA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD
3
+ VQQGEwJVUzELMAkGA1UECBMCQ0ExDzANBgNVBAcTBk5ld2FyazEbMBkGA1UEChMS
4
+ TmVhdG8gUm9ib3RpY3MgSW5jMRcwFQYDVQQLEw5DbG91ZCBTZXJ2aWNlczEZMBcG
5
+ A1UEAxQQKi5uZWF0b2Nsb3VkLmNvbTEmMCQGCSqGSIb3DQEJARYXY2xvdWRAbmVh
6
+ dG9yb2JvdGljcy5jb20wHhcNMTUwNDIxMTA1OTA4WhcNNDUwNDEzMTA1OTA4WjCB
7
+ pDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQ8wDQYDVQQHEwZOZXdhcmsxGzAZ
8
+ BgNVBAoTEk5lYXRvIFJvYm90aWNzIEluYzEXMBUGA1UECxMOQ2xvdWQgU2Vydmlj
9
+ ZXMxGTAXBgNVBAMUECoubmVhdG9jbG91ZC5jb20xJjAkBgkqhkiG9w0BCQEWF2Ns
10
+ b3VkQG5lYXRvcm9ib3RpY3MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
11
+ CgKCAQEAur0WFcJ2YvnL3dtXJFv3lfCQtELLHVcux88tH7HN/FTeUvCqdleDNv4S
12
+ mXWgxVOdUUuhV885wppYyXNzDDrwCyjPmYj0m1EZ4FqTCcjFmk+xdEJsPsKPgRt5
13
+ QqaO0CA/T7dcIhT/PtQnJtcjn6E6vt2JLhsLz9OazadwjvdkejmfrOL643FGxsIP
14
+ 8hu3+JINcfxnmff85zshe0yQH5yIYkmQGUPQz061T6mMzFrED/hx9zDpiB1mfkUm
15
+ uG3rBVcZWtrdyMvqB9LB1vqKgcCRANVg5S0GKpySudFlHOZjekXwBsZ+E6tW53qx
16
+ hvlgmlxX80aybYC5hQaNSQBaV9N4lwIDAQABo4IBDTCCAQkwHQYDVR0OBBYEFM3g
17
+ l7v7HP6zQgF90eHIl9coH6jhMIHZBgNVHSMEgdEwgc6AFM3gl7v7HP6zQgF90eHI
18
+ l9coH6jhoYGqpIGnMIGkMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExDzANBgNV
19
+ BAcTBk5ld2FyazEbMBkGA1UEChMSTmVhdG8gUm9ib3RpY3MgSW5jMRcwFQYDVQQL
20
+ Ew5DbG91ZCBTZXJ2aWNlczEZMBcGA1UEAxQQKi5uZWF0b2Nsb3VkLmNvbTEmMCQG
21
+ CSqGSIb3DQEJARYXY2xvdWRAbmVhdG9yb2JvdGljcy5jb22CCQCx6YQ9dZa5hzAM
22
+ BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQB93p+MUmKH+MQI3pEVvPUW
23
+ y+VDB5qt1spE5J0awVwUzhQ7QXkEqgFfOk0kzufvxdha9wz+05E1glQ8l5CzlATu
24
+ kA7V5OsygYB+TgqjvhfFHkSI6TJ8OlKcAJuZ2yQE8s2+LVo92NLwpooZLA6BCahn
25
+ fX+rzmo6b4ylhyX98Tm3upINNH3whV355PJFgk74fw9N7U6cFlBrqXXssKOse2D2
26
+ xY65IK7OQxSq5K5OPFLwN3h/eURo5kwl7jhpJhJbFL4I46OkpgqWHxQEqSxQnS0d
27
+ AC62ApwWkm42i0/DGODms2tnGL/DaCiTkgEE+8EEF9kfvQDtMoUDNvIkl7Vvm914
28
+ -----END CERTIFICATE-----
@@ -0,0 +1,87 @@
1
+ require "openssl"
2
+ require "json"
3
+ require "faraday"
4
+ require 'faraday_middleware'
5
+
6
+ module Botvac
7
+ class Robot
8
+ attr_accessor :serial, :secret
9
+
10
+ def initialize(serial, secret)
11
+ self.serial = serial
12
+ self.secret = secret
13
+ end
14
+
15
+ def start_cleaning
16
+ connection.post("messages", JSON.dump(
17
+ {
18
+ reqId: "1",
19
+ cmd: "startCleaning",
20
+ params: {
21
+ category: 2,
22
+ mode: 2,
23
+ modifier: 2
24
+ }
25
+ }
26
+ )).body
27
+ end
28
+
29
+ def pause_cleaning
30
+ connection.post("messages", JSON.dump({ reqId: "1",cmd: "pauseCleaning" })).body
31
+ end
32
+
33
+ def stop_cleaning
34
+ connection.post("messages", JSON.dump({ reqId: "1",cmd: "stopCleaning" })).body
35
+ end
36
+
37
+ def send_to_base
38
+ connection.post("messages", JSON.dump({ reqId: "1",cmd: "sendToBase" })).body
39
+ end
40
+
41
+ def get_robot_state
42
+ connection.post("messages", JSON.dump({ reqId: "1", cmd: "getRobotState" })).body
43
+ end
44
+
45
+ def enable_schedule
46
+ connection.post("messages", JSON.dump({ reqId: "1", cmd: "enableSchedule" })).body
47
+ end
48
+
49
+ def disable_schedule
50
+ connection.post("messages", JSON.dump({ reqId: "1", cmd: "disableSchedule"})).body
51
+ end
52
+
53
+ def get_schedule
54
+ connection.post("messages", JSON.dump({ reqId: "1", cmd: "getSchedule" })).body
55
+ end
56
+
57
+ protected
58
+
59
+ class Hmac < Faraday::Middleware
60
+ def initialize(app, options = {})
61
+ super(app)
62
+ @digest = OpenSSL::Digest.new('sha256')
63
+ @serial = options[:serial].downcase
64
+ @secret = options[:secret]
65
+ end
66
+
67
+ def call(env)
68
+ "#{Time.now.gmtime.strftime("%a, %d %h %Y %H:%M:%S")} GMT".tap do |date|
69
+ hmac = OpenSSL::HMAC.hexdigest(@digest, @secret, [@serial, date, env['body']].join("\n"))
70
+ env[:request_headers]['Date']= date
71
+ env[:request_headers]['Authorization']= "NEATOAPP #{hmac}"
72
+ end
73
+
74
+ @app.call(env)
75
+ end
76
+ end
77
+
78
+ def connection
79
+ @connection ||= Faraday.new(ssl: { ca_file: File.join(File.dirname(__FILE__), '..', '..', 'cert', 'neatocloud.com.crt') }) do |faraday|
80
+ faraday.url_prefix= "#{Botvac::ENDPOINT}/vendors/neato/robots/#{self.serial}/"
81
+ faraday.use Hmac, { serial: self.serial, secret: self.secret }
82
+ faraday.headers["Accept"]= 'application/vnd.neato.nucleo.v1'
83
+ faraday.adapter Faraday.default_adapter
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Botvac
2
+ VERSION = "0.1.0"
3
+ end
data/lib/botvac/web.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'botvac'
2
+
3
+ module Botvac
4
+ class Web
5
+ def call(env)
6
+ if supported_actions.include?(env["REQUEST_PATH"][1..-1])
7
+ [200, {'Content-Type' => 'application/json'}, [robot.send(env["REQUEST_PATH"][1..-1])]]
8
+ else
9
+ [404, {'Content-Type' => 'application/json'}, ['{}']]
10
+ end
11
+ end
12
+
13
+ def supported_actions
14
+ %w(start_cleaning pause_cleaning stop_cleaning send_to_base get_robot_state disable_schedule enable_schedule get_schedule)
15
+ end
16
+
17
+ def robot
18
+ @robot ||= Botvac::Robot.new(ENV['SERIAL'], ENV['SECRET'])
19
+ end
20
+ end
21
+ end
data/lib/botvac.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "botvac/version"
2
+ require "botvac/robot"
3
+
4
+ module Botvac
5
+ ENDPOINT = 'https://nucleo.neatocloud.com'
6
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ describe Botvac::Robot::Hmac do
4
+ subject do
5
+ described_class.new(
6
+ double('app', call: {}),
7
+ serial: "OPS39348-C0BCB237AC0F",
8
+ secret: "702FA35268D2792B2AAF9510B47756D8",
9
+ )
10
+ end
11
+
12
+ let(:env) { { request_headers: {}, 'body' => '{"reqId":"1","cmd":"getRobotState"}' } }
13
+
14
+ it 'adds the HMAC signature to the authorization header' do
15
+ Timecop.freeze(Time.parse("Tue, 09 Feb 2016 18:06:56 GMT")) do
16
+ expect{ subject.call(env) }.to change{ env[:request_headers]['Authorization'] }.to include("f93e6a50c3134706ae875adfabc9a14f0cc61e1b11b111499b4e6eeb1f69da70")
17
+ end
18
+ end
19
+
20
+ it 'sets the date header' do
21
+ Timecop.freeze(Time.parse("Tue, 09 Feb 2016 18:06:56 GMT")) do
22
+ expect{ subject.call(env) }.to change{ env[:request_headers]['Date'] }.to("Tue, 09 Feb 2016 18:06:56 GMT")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rspec'
5
+ require 'botvac'
6
+ require 'webmock/rspec'
7
+ require 'timecop'
8
+ require 'rspec/matchers' # req by equivalent-xml custom matcher `be_equivalent_to`
9
+
10
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+ # rspec-expectations config goes here. You can use an alternate
14
+ # assertion/expectation library such as wrong or the stdlib/minitest
15
+ # assertions if you prefer.
16
+ config.expect_with :rspec do |expectations|
17
+ # This option will default to `true` in RSpec 4. It makes the `description`
18
+ # and `failure_message` of custom matchers include text for helper methods
19
+ # defined using `chain`, e.g.:
20
+ # be_bigger_than(2).and_smaller_than(4).description
21
+ # # => "be bigger than 2 and smaller than 4"
22
+ # ...rather than:
23
+ # # => "be bigger than 2"
24
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
25
+ end
26
+
27
+ # rspec-mocks config goes here. You can use an alternate test double
28
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
29
+ config.mock_with :rspec do |mocks|
30
+ # Prevents you from mocking or stubbing a method that does not exist on
31
+ # a real object. This is generally recommended, and will default to
32
+ # `true` in RSpec 4.
33
+ mocks.verify_partial_doubles = true
34
+ end
35
+
36
+ config.order = :random
37
+
38
+ Kernel.srand config.seed
39
+
40
+ if config.files_to_run.one?
41
+ config.default_formatter = 'doc'
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: botvac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lars Brillert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.6.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.6.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: timecop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: |
154
+ Botvac allows you to interact with the Neato cloud service
155
+ which controls your robot without making use of the Android/iOS
156
+ application.
157
+ email:
158
+ - lars@railslove.com
159
+ executables: []
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - ".gitignore"
164
+ - Gemfile
165
+ - Gemfile.lock
166
+ - Guardfile
167
+ - LICENSE.txt
168
+ - README.md
169
+ - Rakefile
170
+ - botvac.gemspec
171
+ - cert/neatocloud.com.crt
172
+ - lib/botvac.rb
173
+ - lib/botvac/robot.rb
174
+ - lib/botvac/version.rb
175
+ - lib/botvac/web.rb
176
+ - spec/botvac/robot_spec.rb
177
+ - spec/spec_helper.rb
178
+ homepage: https://github.com/kangguru/botvac
179
+ licenses:
180
+ - MIT
181
+ metadata: {}
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubyforge_project:
198
+ rubygems_version: 2.5.1
199
+ signing_key:
200
+ specification_version: 4
201
+ summary: talk to your botvac connected robot
202
+ test_files:
203
+ - spec/botvac/robot_spec.rb
204
+ - spec/spec_helper.rb