netatmo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +169 -0
  4. data/lib/netatmo.rb +20 -0
  5. data/lib/netatmo/administrative.rb +23 -0
  6. data/lib/netatmo/air_care/home_coach.rb +25 -0
  7. data/lib/netatmo/battery_status/battery_status.rb +34 -0
  8. data/lib/netatmo/battery_status/indoor_battery_status.rb +16 -0
  9. data/lib/netatmo/battery_status/outdoor_battery_status.rb +16 -0
  10. data/lib/netatmo/battery_status/wind_gauge_battery_status.rb +16 -0
  11. data/lib/netatmo/client.rb +98 -0
  12. data/lib/netatmo/dashboard_data/co2.rb +29 -0
  13. data/lib/netatmo/dashboard_data/health_index.rb +34 -0
  14. data/lib/netatmo/dashboard_data/humidity.rb +29 -0
  15. data/lib/netatmo/dashboard_data/noise.rb +29 -0
  16. data/lib/netatmo/dashboard_data/pressure.rb +43 -0
  17. data/lib/netatmo/dashboard_data/rain.rb +35 -0
  18. data/lib/netatmo/dashboard_data/temperature.rb +35 -0
  19. data/lib/netatmo/dashboard_data/wind.rb +33 -0
  20. data/lib/netatmo/place.rb +21 -0
  21. data/lib/netatmo/user.rb +13 -0
  22. data/lib/netatmo/util/battery_status.rb +9 -0
  23. data/lib/netatmo/util/device_type.rb +14 -0
  24. data/lib/netatmo/util/feel_like.rb +9 -0
  25. data/lib/netatmo/util/health_index.rb +9 -0
  26. data/lib/netatmo/util/pressureunit.rb +9 -0
  27. data/lib/netatmo/util/temp_trend.rb +9 -0
  28. data/lib/netatmo/util/unit.rb +9 -0
  29. data/lib/netatmo/util/wifi_status.rb +9 -0
  30. data/lib/netatmo/util/windunit.rb +9 -0
  31. data/lib/netatmo/version.rb +5 -0
  32. data/lib/netatmo/weather/base_station.rb +61 -0
  33. data/lib/netatmo/weather/battery_device.rb +24 -0
  34. data/lib/netatmo/weather/device.rb +121 -0
  35. data/lib/netatmo/weather/indoor_module.rb +20 -0
  36. data/lib/netatmo/weather/outdoor_module.rb +19 -0
  37. data/lib/netatmo/weather/rain_gauge.rb +15 -0
  38. data/lib/netatmo/weather/station_data.rb +19 -0
  39. data/lib/netatmo/weather/wifi_status.rb +34 -0
  40. data/lib/netatmo/weather/wind_gauge.rb +15 -0
  41. data/lib/netatmo_inflector.rb +24 -0
  42. metadata +224 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5afa0ba31f1da59d10c3b91a68679e21abef496ee5cd34ca0e235f5db43f948d
4
+ data.tar.gz: 572df5b1e1fced24e36023d4cf9a210ce057df459942917193dad8331c32bc0c
5
+ SHA512:
6
+ metadata.gz: f762ee09437e403a2ec4737a31f933c8c8980b3db8d167383b552f26b6ad26db083565ac1f697b60b7db65a8a7740445f7d12875123df0df7943c9d0f670b4b3
7
+ data.tar.gz: 3a1cb2e6420c2b2ba96428d1064f8f3354d77405a88b6452dfcf45a5358bdebf778048a1acf9fbf39c96677b959622b8ce43321b461e46152cb1b2899afb309c
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Marco Roth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,169 @@
1
+ # Netatmo
2
+
3
+ Ruby API Wrapper for the [Netatmo API](https://dev.netatmo.com/apidocumentation/).
4
+
5
+ ![Build Status](https://github.com/marcoroth/netatmo-ruby/workflows/Build/badge.svg)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'netatmo'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install netatmo
22
+
23
+ ## Usage
24
+
25
+ ### Environment variables
26
+
27
+ | Name | Description |
28
+ |---------------------------|------------------------|
29
+ | `NETATMO_CLIENT_ID` | Your app client_id |
30
+ | `NETATMO_CLIENT_SECRET` | Your app client_secret |
31
+ | `NETATMO_CLIENT_USERNAME` | User address email |
32
+ | `NETATMO_CLIENT_PASSWORD` | User password |
33
+
34
+ ### Creating a client
35
+
36
+ To create a Netatmo client you can either set the required environment variables or pass the credentials via a config block to the initialize method.
37
+
38
+ ```ruby
39
+ # if you configured the required ENV variables
40
+ client = Netatmo::Client.new
41
+
42
+ # or if you want to provide the required credentials
43
+ client = Netatmo::Client.new do |config|
44
+ config.client_id = '10acb39bc818e5789'
45
+ config.client_secret = '10dsfxyzbkzva'
46
+ config.username = 'user@email.address'
47
+ config.password = 'UserPassword'
48
+ end
49
+
50
+ ```
51
+
52
+ ### Endpoint `/getstationdata`
53
+
54
+ `get_station_data` Returns all weather stations you have read access to.
55
+
56
+ ```ruby
57
+ station_data = client.get_station_data
58
+ # => #<Netatmo::Weather::StationData @devices=[...] @user=#<Netatmo::User> ...>
59
+
60
+ ```
61
+
62
+ #### Devices
63
+
64
+ You can access the base stations in the `devices` array.
65
+
66
+ ```ruby
67
+ station_data.devices
68
+
69
+ # => [
70
+ # #<Netatmo::Weather::BaseStation @id="00:11:22:00:11:22", @modules=[...] ...>,
71
+ # #<Netatmo::Weather::BaseStation @id="12:23:34:45:56:67", @modules=[...] ...>
72
+ # ]
73
+
74
+ ```
75
+
76
+
77
+
78
+ ```ruby
79
+ base_station = station_data.devices.first
80
+ # => #<Netatmo::Weather::BaseStation @id="00:11:22:00:11:22", @code="NAMain", @data_types=["Temperature", "CO2", "Humidity", "Noise", "Pressure"], @modules=[...]>
81
+
82
+ ```
83
+
84
+ #### Modules
85
+
86
+ All to this base station connected modules are accessible in the `modules` array.
87
+
88
+ ```ruby
89
+ base_station.modules
90
+ # => [
91
+ # #<Netatmo::Weather::OutdoorModule @code="NAModule1", @data_types=["Temperature", "Humidity"], ...>,
92
+ # #<Netatmo::Weather::WindGauge @code="NAModule2", @data_types=["Wind"], ...>,
93
+ # #<Netatmo::Weather::IndoorModule @code="NAModule4", @data_types=["Temperature", "CO2", "Humidity"], ...>,
94
+ # #<Netatmo::Weather::RainGauge @code="NAModule3", @data_types=["Rain"], ...>
95
+ # ]
96
+ ```
97
+
98
+ ```ruby
99
+ outdoor = base_station.modules.first
100
+
101
+ # => #<Netatmo::Weather::OutdoorModule
102
+ # @id="11:22:33:44:55:66",
103
+ # @code="NAModule1",
104
+ # @data_types=["Temperature", "Humidity"],
105
+ # @module_name="Module",
106
+ # @reachable=true,
107
+ # @firmware=44,
108
+ # @last_setup=2014-12-24 21:57:28 +0100,
109
+ # @last_message=2020-02-11 10:49:33 +0100,
110
+ # @last_seen=2020-02-11 10:49:27 +0100,
111
+ # @rf_status=66,
112
+ # @battery_vp=5440,
113
+ # @battery_percent=77,
114
+ # @battery_status=#<Netatmo::BatteryStatus::OutdoorBatteryStatus @value=5440>,
115
+ # @humidity=#<Netatmo::DashboardData::Humidity @time=2020-02-11 10:48:36 +0100, @value=62.0, @unit="%">,
116
+ # @temperature=#<Netatmo::DashboardData::Temperature @time=2020-02-11 10:48:36 +0100, @value=13.6, @min=7.6,
117
+ # @max=13.6, @min_date=2020-02-11 07:12:25 +0100, @max_date=2020-02-11 10:48:36 +0100,
118
+ # @trend=#<Netatmo::Util::TempTrend @value=1>,
119
+ # @unit="°C">
120
+ # >
121
+ ```
122
+
123
+ #### Data Types
124
+
125
+ You can ask the module if it provides certain data types.
126
+
127
+ ```ruby
128
+ outdoor.temperature?
129
+ # => true
130
+ ```
131
+
132
+ ```ruby
133
+ outdoor.noise?
134
+ # => false
135
+ ```
136
+
137
+ If the data type is supported you can access the values.
138
+
139
+ ```ruby
140
+ outdoor.temperature
141
+ # => #<Netatmo::DashboardData::Temperature @value=13.6, @min=7.6, @max=13.6, @unit="°C", @time=2020-02-11 10:48:36 +0100, @trend=#<Netatmo::Util::TempTrend @value=1>, ...>
142
+ ```
143
+
144
+ #### Values
145
+
146
+ If you want to get a hash of all the available data types on the module you use the `values` method.
147
+
148
+ ```ruby
149
+ outdoor.values
150
+ # => {
151
+ # :humidity=>#<Netatmo::DashboardData::Humidity ...>,
152
+ # :temperature=>#<Netatmo::DashboardData::Temperature ...
153
+ # }
154
+
155
+ ```
156
+
157
+ ## Development
158
+
159
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
160
+
161
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
162
+
163
+ ## Contributing
164
+
165
+ Bug reports and pull requests are welcome on GitHub at https://github.com/marcoroth/netatmo-ruby.
166
+
167
+ ## License
168
+
169
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'netatmo/version'
4
+ require 'netatmo_inflector'
5
+
6
+ require 'zeitwerk'
7
+ require 'byebug'
8
+ require 'dotenv'
9
+ require 'easy_enum'
10
+
11
+ Dotenv.load
12
+
13
+ @loader = Zeitwerk::Loader.for_gem
14
+ @loader.inflector = NetatmoInflector.new
15
+ @loader.enable_reloading
16
+ @loader.setup
17
+
18
+ module Netatmo
19
+ class Error < StandardError; end
20
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Netatmo
4
+ class Administrative
5
+ attr_accessor :unit
6
+ attr_accessor :windunit
7
+ attr_accessor :pressureunit
8
+ attr_accessor :lang
9
+ attr_accessor :reg_locale
10
+ attr_accessor :country
11
+ attr_accessor :feel_like
12
+
13
+ def initialize(data)
14
+ self.unit = Netatmo::Util::Unit.value(data['unit'])
15
+ self.windunit = Netatmo::Util::Windunit.value(data['windunit'])
16
+ self.pressureunit = Netatmo::Util::Pressureunit.value(data['pressureunit'])
17
+ self.feel_like = Netatmo::Util::FeelLike.value(data['feel_like_algo'])
18
+ self.lang = data['lang']
19
+ self.reg_locale = data['reg_locale']
20
+ self.country = data['country']
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Netatmo
4
+ module AirCare
5
+ class HomeCoach < Netatmo::Weather::BaseStation
6
+ attr_accessor :health_index
7
+
8
+ # DeviceType: NHC
9
+ def initialize(data)
10
+ super(data)
11
+
12
+ self.health_index = Netatmo::DashboardData::HealthIndex.new(data['dashboard_data'])
13
+ end
14
+
15
+ def name
16
+ module_name
17
+ end
18
+
19
+ def data
20
+ d = super
21
+ d << health_index if health_index?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Netatmo
6
+ module BatteryStatus
7
+ class BatteryStatus
8
+ extend Forwardable
9
+
10
+ attr_accessor :type
11
+ attr_accessor :value
12
+
13
+ class << self
14
+ attr_accessor :status_values
15
+ end
16
+
17
+ self.status_values = {}
18
+
19
+ def initialize(value)
20
+ self.value = value
21
+ end
22
+
23
+ def status
24
+ self.class.status_values.each do |key, range|
25
+ return Netatmo::Util::BatteryStatus.key(key) if range.cover? value
26
+ end
27
+
28
+ nil
29
+ end
30
+
31
+ def_delegators :status, :max?, :full?, :high?, :medium?, :low?, :very_low?
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Netatmo
4
+ module BatteryStatus
5
+ class IndoorBatteryStatus < BatteryStatus
6
+ self.status_values = {
7
+ very_low: 0..4559,
8
+ low: 4560..4919,
9
+ medium: 4920..5279,
10
+ high: 5280..5639,
11
+ full: 5640..5999,
12
+ max: 6000..6000
13
+ }.freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Netatmo
4
+ module BatteryStatus
5
+ class OutdoorBatteryStatus < BatteryStatus
6
+ self.status_values = {
7
+ very_low: 0..3999,
8
+ low: 4000..4499,
9
+ medium: 4500..4999,
10
+ high: 5000..5499,
11
+ full: 5500..5999,
12
+ max: 6000..6000
13
+ }.freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Netatmo
4
+ module BatteryStatus
5
+ class WindGaugeBatteryStatus < BatteryStatus
6
+ self.status_values = {
7
+ very_low: 0..4359,
8
+ low: 4360..4769,
9
+ medium: 4770..5179,
10
+ high: 5180..5589,
11
+ full: 5590..5999,
12
+ max: 6000..6000
13
+ }.freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'json'
5
+
6
+ module Netatmo
7
+ class Client
8
+ BASE_URL = 'https://api.netatmo.net'
9
+ attr_accessor :access_token, :refresh_token, :expires_at
10
+ Config = Struct.new(:client_id, :client_secret, :username, :password, :base_url)
11
+
12
+ def initialize(&config_block)
13
+ if block_given?
14
+ config_block.call config
15
+ else
16
+ config
17
+ end
18
+
19
+ authenticate
20
+ end
21
+
22
+ def configure(&config_block)
23
+ config_block.call config if block_given?
24
+ config
25
+ end
26
+
27
+ def config
28
+ @config ||= Config.new(
29
+ ENV['NETATMO_CLIENT_ID'],
30
+ ENV['NETATMO_CLIENT_SECRET'],
31
+ ENV['NETATMO_USERNAME'],
32
+ ENV['NETATMO_PASSWORD'],
33
+ BASE_URL
34
+ )
35
+ end
36
+
37
+ def authenticate
38
+ if @access_token && @expires_at > Time.now
39
+ true
40
+ else
41
+ fetch_token
42
+ end
43
+ end
44
+
45
+ def fetch_token
46
+ response = if @refresh_token
47
+ connection.post '/oauth2/token' do |request|
48
+ request.body = {
49
+ grant_type: :refresh_token,
50
+ refresh_token: @refresh_token,
51
+ client_id: config.client_id,
52
+ client_secret: config.client_secret
53
+ }
54
+ end
55
+ else
56
+ connection.post '/oauth2/token' do |request|
57
+ request.body = {
58
+ grant_type: :password,
59
+ client_id: config.client_id,
60
+ client_secret: config.client_secret,
61
+ username: config.username,
62
+ password: config.password,
63
+ scope: 'read_station'
64
+ }
65
+ end
66
+ end
67
+ store_token(response)
68
+ end
69
+
70
+ # rubocop:disable Naming/AccessorMethodName
71
+ def get_station_data
72
+ response = connection.get('/api/getstationsdata', access_token: @access_token)
73
+
74
+ raise 'Unauthenticated' unless response.status == 200
75
+
76
+ Netatmo::Weather::StationData.new(JSON.parse(response.body)['body'])
77
+ end
78
+ # rubocop:enable Naming/AccessorMethodName
79
+
80
+ private
81
+
82
+ def connection
83
+ @connection ||= Faraday::Connection.new(url: config.base_url) do |builder|
84
+ builder.request :url_encoded
85
+ builder.adapter :net_http
86
+ end
87
+ end
88
+
89
+ def store_token(response)
90
+ return unless response.status == 200
91
+
92
+ data = JSON.parse(response.body)
93
+ @access_token = data['access_token']
94
+ @refresh_token = data['refresh_token']
95
+ @expires_at = Time.now + data['expires_in']
96
+ end
97
+ end
98
+ end