airthings 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b3a228c29713880c209f13d44ffc0deca3e8dbf517b15ccf10e5f1631632160d
4
+ data.tar.gz: 4ba1f36b8848bfef3c08d17e5ea8f64f539107a65a01a0c22e56f4424055376a
5
+ SHA512:
6
+ metadata.gz: e847bc6791c8b97c6bbb35967473cab6a60101bcef29444cd9675d2cca93d62093f0a191ddaff5a3df6c8f085e9eb2deb29ccee418aa06f76c57ead30b956fd9
7
+ data.tar.gz: 6bc7eb7ad55001a20e6a6988b58fe9e05698eb35d063aa2f8de4911f87ef2205bce6e38a9700544f25673dddbeb6d9b53ba2459617ffbb37b83954256dcf8929
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "airthings"
5
+ require "airthings/oauth2"
6
+ require "homie-mqtt"
7
+ require "optparse"
8
+
9
+ refresh = 60.0
10
+
11
+ options = OptionParser.new do |opts|
12
+ opts.banner = "Usage: airthings_mqtt_bridge ID SECRET MQTT_URI [options]"
13
+
14
+ opts.on("--refresh-interval=INTERVAL", "Refresh interval (default 60s)") { |v| refresh = v.to_f }
15
+ opts.on("-h", "--help", "Prints this help") do
16
+ puts opts
17
+ exit
18
+ end
19
+ end
20
+
21
+ options.parse!
22
+
23
+ unless ARGV.length == 3
24
+ puts options
25
+ exit 1
26
+ end
27
+
28
+ Airthings.configure do |config|
29
+ config.id = ARGV[0]
30
+ config.secret = ARGV[1]
31
+ end
32
+
33
+ api_instance = Airthings::DevicesApi.new
34
+
35
+ homie = MQTT::Homie::Device.new("airthings", "Airthings Devices", mqtt: { uri: ARGV[2], reconnect_limit: 3 })
36
+
37
+ INVERTED_ATTRIBUTE_MAP = Airthings::SingleSampleData.attribute_map.invert.freeze
38
+ ATTRIBUTE_UNITS = {
39
+ battery: "%",
40
+ co2: "ppm",
41
+ humidity: "%",
42
+ pressure: "mbar",
43
+ radon_short_term_avg: "mBq",
44
+ rssi: "dB",
45
+ temp: "°C",
46
+ voc: "ppb",
47
+ outdoor_temp: "°C",
48
+ outdoor_humidity: "%",
49
+ outdoor_pressure: "mbar"
50
+ }.freeze
51
+
52
+ devices = api_instance.devices_list.devices
53
+ devices.each do |device|
54
+ next if device.sensors.empty?
55
+
56
+ samples = api_instance.device_samples_latest_values(device.id).data
57
+ node = homie.node(device.id, device.device_type, device.device_type)
58
+ device.sensors.each do |sensor|
59
+ method = INVERTED_ATTRIBUTE_MAP[sensor.to_sym]
60
+ value = samples.send(method)
61
+ node.property(method.to_s.tr("_", "-"), sensor, value.class.name.downcase.to_sym, value,
62
+ unit: ATTRIBUTE_UNITS[method])
63
+ end
64
+ end
65
+
66
+ homie.publish
67
+
68
+ loop do
69
+ devices.each do |device|
70
+ next if device.sensors.empty?
71
+
72
+ samples = api_instance.device_samples_latest_values(device.id).data
73
+ homie.mqtt.batch_publish do
74
+ node = homie[device.id]
75
+ device.sensors.each do |sensor|
76
+ method = INVERTED_ATTRIBUTE_MAP[sensor.to_sym]
77
+ property = node[method.to_s.tr("_", "-")]
78
+ property.value = samples.send(method)
79
+ end
80
+ end
81
+ end
82
+
83
+ sleep refresh
84
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ # #Airthings API
4
+ #
5
+ # No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
6
+ #
7
+ # The version of the OpenAPI document: v1
8
+ #
9
+ # Generated by: https://openapi-generator.tech
10
+ # OpenAPI Generator version: 6.2.0
11
+ #
12
+
13
+ require "cgi"
14
+
15
+ module Airthings
16
+ class DevicesApi
17
+ attr_accessor :api_client
18
+
19
+ def initialize(api_client = ApiClient.default)
20
+ @api_client = api_client
21
+ end
22
+
23
+ # Get info about a specific Device
24
+ # @param serial_number [String]
25
+ # @param [Hash] opts the optional parameters
26
+ # @option opts [String] :organization_id
27
+ # @option opts [String] :user_group_id
28
+ # @return [GetDeviceDetailedResponse]
29
+ def device_info(serial_number, opts = {})
30
+ data, _status_code, _headers = device_info_with_http_info(serial_number, opts)
31
+ data
32
+ end
33
+
34
+ # Get info about a specific Device
35
+ # @param serial_number [String]
36
+ # @param [Hash] opts the optional parameters
37
+ # @option opts [String] :organization_id
38
+ # @option opts [String] :user_group_id
39
+ # @return [Array<(GetDeviceDetailedResponse, Integer, Hash)>] GetDeviceDetailedResponse data, response status code and response headers
40
+ def device_info_with_http_info(serial_number, opts = {})
41
+ @api_client.config.logger.debug "Calling API: DevicesApi.device_info ..." if @api_client.config.debugging
42
+ # verify the required parameter 'serial_number' is set
43
+ if @api_client.config.client_side_validation && serial_number.nil?
44
+ raise ArgumentError, "Missing the required parameter 'serial_number' when calling DevicesApi.device_info"
45
+ end
46
+
47
+ # resource path
48
+ local_var_path = "/devices/{serialNumber}".sub("{serialNumber}", CGI.escape(serial_number.to_s))
49
+
50
+ # query parameters
51
+ query_params = opts[:query_params] || {}
52
+ query_params[:organizationId] = opts[:organization_id] unless opts[:organization_id].nil?
53
+ query_params[:userGroupId] = opts[:user_group_id] unless opts[:user_group_id].nil?
54
+
55
+ # header parameters
56
+ header_params = opts[:header_params] || {}
57
+ # HTTP header 'Accept' (if needed)
58
+ header_params["Accept"] = @api_client.select_header_accept(["application/json"])
59
+
60
+ # form parameters
61
+ form_params = opts[:form_params] || {}
62
+
63
+ # http body (model)
64
+ post_body = opts[:debug_body]
65
+
66
+ # return_type
67
+ return_type = opts[:debug_return_type] || "GetDeviceDetailedResponse"
68
+
69
+ # auth_names
70
+ auth_names = opts[:debug_auth_names] || ["AirthingsAccounts"]
71
+
72
+ new_options = opts.merge(
73
+ operation: :"DevicesApi.device_info",
74
+ header_params: header_params,
75
+ query_params: query_params,
76
+ form_params: form_params,
77
+ body: post_body,
78
+ auth_names: auth_names,
79
+ return_type: return_type
80
+ )
81
+
82
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
83
+ if @api_client.config.debugging
84
+ @api_client.config.logger.debug "API called: DevicesApi#device_info\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
85
+ end
86
+ [data, status_code, headers]
87
+ end
88
+
89
+ # Get latest Samples belonging to a specific Device (latest segment)
90
+ # @param serial_number [String]
91
+ # @param [Hash] opts the optional parameters
92
+ # @option opts [String] :organization_id
93
+ # @option opts [String] :user_group_id
94
+ # @return [SingleSampleResponse]
95
+ def device_samples_latest_values(serial_number, opts = {})
96
+ data, _status_code, _headers = device_samples_latest_values_with_http_info(serial_number, opts)
97
+ data
98
+ end
99
+
100
+ # Get latest Samples belonging to a specific Device (latest segment)
101
+ # @param serial_number [String]
102
+ # @param [Hash] opts the optional parameters
103
+ # @option opts [String] :organization_id
104
+ # @option opts [String] :user_group_id
105
+ # @return [Array<(SingleSampleResponse, Integer, Hash)>] SingleSampleResponse data, response status code and response headers
106
+ def device_samples_latest_values_with_http_info(serial_number, opts = {})
107
+ if @api_client.config.debugging
108
+ @api_client.config.logger.debug "Calling API: DevicesApi.device_samples_latest_values ..."
109
+ end
110
+ # verify the required parameter 'serial_number' is set
111
+ if @api_client.config.client_side_validation && serial_number.nil?
112
+ raise ArgumentError, "Missing the required parameter 'serial_number' when calling DevicesApi.device_samples_latest_values"
113
+ end
114
+
115
+ # resource path
116
+ local_var_path = "/devices/{serialNumber}/latest-samples".sub("{serialNumber}", CGI.escape(serial_number.to_s))
117
+
118
+ # query parameters
119
+ query_params = opts[:query_params] || {}
120
+ query_params[:organizationId] = opts[:organization_id] unless opts[:organization_id].nil?
121
+ query_params[:userGroupId] = opts[:user_group_id] unless opts[:user_group_id].nil?
122
+
123
+ # header parameters
124
+ header_params = opts[:header_params] || {}
125
+ # HTTP header 'Accept' (if needed)
126
+ header_params["Accept"] = @api_client.select_header_accept(["application/json"])
127
+
128
+ # form parameters
129
+ form_params = opts[:form_params] || {}
130
+
131
+ # http body (model)
132
+ post_body = opts[:debug_body]
133
+
134
+ # return_type
135
+ return_type = opts[:debug_return_type] || "SingleSampleResponse"
136
+
137
+ # auth_names
138
+ auth_names = opts[:debug_auth_names] || ["AirthingsAccounts"]
139
+
140
+ new_options = opts.merge(
141
+ operation: :"DevicesApi.device_samples_latest_values",
142
+ header_params: header_params,
143
+ query_params: query_params,
144
+ form_params: form_params,
145
+ body: post_body,
146
+ auth_names: auth_names,
147
+ return_type: return_type
148
+ )
149
+
150
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
151
+ if @api_client.config.debugging
152
+ @api_client.config.logger.debug "API called: DevicesApi#device_samples_latest_values\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
153
+ end
154
+ [data, status_code, headers]
155
+ end
156
+
157
+ # Get Devices belonging to the Account
158
+ # @param [Hash] opts the optional parameters
159
+ # @option opts [Boolean] :show_inactive (default to false)
160
+ # @option opts [String] :organization_id
161
+ # @option opts [String] :user_group_id
162
+ # @return [GetDevicesResponse]
163
+ def devices_list(opts = {})
164
+ data, _status_code, _headers = devices_list_with_http_info(opts)
165
+ data
166
+ end
167
+
168
+ # Get Devices belonging to the Account
169
+ # @param [Hash] opts the optional parameters
170
+ # @option opts [Boolean] :show_inactive (default to false)
171
+ # @option opts [String] :organization_id
172
+ # @option opts [String] :user_group_id
173
+ # @return [Array<(GetDevicesResponse, Integer, Hash)>] GetDevicesResponse data, response status code and response headers
174
+ def devices_list_with_http_info(opts = {})
175
+ @api_client.config.logger.debug "Calling API: DevicesApi.devices_list ..." if @api_client.config.debugging
176
+ # resource path
177
+ local_var_path = "/devices"
178
+
179
+ # query parameters
180
+ query_params = opts[:query_params] || {}
181
+ query_params[:showInactive] = opts[:show_inactive] unless opts[:show_inactive].nil?
182
+ query_params[:organizationId] = opts[:organization_id] unless opts[:organization_id].nil?
183
+ query_params[:userGroupId] = opts[:user_group_id] unless opts[:user_group_id].nil?
184
+
185
+ # header parameters
186
+ header_params = opts[:header_params] || {}
187
+ # HTTP header 'Accept' (if needed)
188
+ header_params["Accept"] = @api_client.select_header_accept(["application/json"])
189
+
190
+ # form parameters
191
+ form_params = opts[:form_params] || {}
192
+
193
+ # http body (model)
194
+ post_body = opts[:debug_body]
195
+
196
+ # return_type
197
+ return_type = opts[:debug_return_type] || "GetDevicesResponse"
198
+
199
+ # auth_names
200
+ auth_names = opts[:debug_auth_names] || ["AirthingsAccounts"]
201
+
202
+ new_options = opts.merge(
203
+ operation: :"DevicesApi.devices_list",
204
+ header_params: header_params,
205
+ query_params: query_params,
206
+ form_params: form_params,
207
+ body: post_body,
208
+ auth_names: auth_names,
209
+ return_type: return_type
210
+ )
211
+
212
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
213
+ if @api_client.config.debugging
214
+ @api_client.config.logger.debug "API called: DevicesApi#devices_list\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
215
+ end
216
+ [data, status_code, headers]
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ # #Airthings API
4
+ #
5
+ # No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
6
+ #
7
+ # The version of the OpenAPI document: v1
8
+ #
9
+ # Generated by: https://openapi-generator.tech
10
+ # OpenAPI Generator version: 6.2.0
11
+ #
12
+
13
+ require "cgi"
14
+
15
+ module Airthings
16
+ class LocationsApi
17
+ attr_accessor :api_client
18
+
19
+ def initialize(api_client = ApiClient.default)
20
+ @api_client = api_client
21
+ end
22
+
23
+ # Get info about a specific Location
24
+ # @param location_id [String]
25
+ # @param [Hash] opts the optional parameters
26
+ # @option opts [Boolean] :show_inactive (default to false)
27
+ # @option opts [String] :organization_id
28
+ # @option opts [String] :user_group_id
29
+ # @return [GetLocationResponse]
30
+ def location_info(location_id, opts = {})
31
+ data, _status_code, _headers = location_info_with_http_info(location_id, opts)
32
+ data
33
+ end
34
+
35
+ # Get info about a specific Location
36
+ # @param location_id [String]
37
+ # @param [Hash] opts the optional parameters
38
+ # @option opts [Boolean] :show_inactive (default to false)
39
+ # @option opts [String] :organization_id
40
+ # @option opts [String] :user_group_id
41
+ # @return [Array<(GetLocationResponse, Integer, Hash)>] GetLocationResponse data, response status code and response headers
42
+ def location_info_with_http_info(location_id, opts = {})
43
+ @api_client.config.logger.debug "Calling API: LocationsApi.location_info ..." if @api_client.config.debugging
44
+ # verify the required parameter 'location_id' is set
45
+ if @api_client.config.client_side_validation && location_id.nil?
46
+ raise ArgumentError, "Missing the required parameter 'location_id' when calling LocationsApi.location_info"
47
+ end
48
+
49
+ # resource path
50
+ local_var_path = "/locations/{locationId}".sub("{locationId}", CGI.escape(location_id.to_s))
51
+
52
+ # query parameters
53
+ query_params = opts[:query_params] || {}
54
+ query_params[:showInactive] = opts[:show_inactive] unless opts[:show_inactive].nil?
55
+ query_params[:organizationId] = opts[:organization_id] unless opts[:organization_id].nil?
56
+ query_params[:userGroupId] = opts[:user_group_id] unless opts[:user_group_id].nil?
57
+
58
+ # header parameters
59
+ header_params = opts[:header_params] || {}
60
+ # HTTP header 'Accept' (if needed)
61
+ header_params["Accept"] = @api_client.select_header_accept(["application/json"])
62
+
63
+ # form parameters
64
+ form_params = opts[:form_params] || {}
65
+
66
+ # http body (model)
67
+ post_body = opts[:debug_body]
68
+
69
+ # return_type
70
+ return_type = opts[:debug_return_type] || "GetLocationResponse"
71
+
72
+ # auth_names
73
+ auth_names = opts[:debug_auth_names] || ["AirthingsAccounts"]
74
+
75
+ new_options = opts.merge(
76
+ operation: :"LocationsApi.location_info",
77
+ header_params: header_params,
78
+ query_params: query_params,
79
+ form_params: form_params,
80
+ body: post_body,
81
+ auth_names: auth_names,
82
+ return_type: return_type
83
+ )
84
+
85
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
86
+ if @api_client.config.debugging
87
+ @api_client.config.logger.debug "API called: LocationsApi#location_info\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
88
+ end
89
+ [data, status_code, headers]
90
+ end
91
+
92
+ # Get all added Locations
93
+ # @param [Hash] opts the optional parameters
94
+ # @option opts [String] :organization_id
95
+ # @option opts [String] :user_group_id
96
+ # @return [GetLocationsResponse]
97
+ def locations_list(opts = {})
98
+ data, _status_code, _headers = locations_list_with_http_info(opts)
99
+ data
100
+ end
101
+
102
+ # Get all added Locations
103
+ # @param [Hash] opts the optional parameters
104
+ # @option opts [String] :organization_id
105
+ # @option opts [String] :user_group_id
106
+ # @return [Array<(GetLocationsResponse, Integer, Hash)>] GetLocationsResponse data, response status code and response headers
107
+ def locations_list_with_http_info(opts = {})
108
+ @api_client.config.logger.debug "Calling API: LocationsApi.locations_list ..." if @api_client.config.debugging
109
+ # resource path
110
+ local_var_path = "/locations"
111
+
112
+ # query parameters
113
+ query_params = opts[:query_params] || {}
114
+ query_params[:organizationId] = opts[:organization_id] unless opts[:organization_id].nil?
115
+ query_params[:userGroupId] = opts[:user_group_id] unless opts[:user_group_id].nil?
116
+
117
+ # header parameters
118
+ header_params = opts[:header_params] || {}
119
+ # HTTP header 'Accept' (if needed)
120
+ header_params["Accept"] = @api_client.select_header_accept(["application/json"])
121
+
122
+ # form parameters
123
+ form_params = opts[:form_params] || {}
124
+
125
+ # http body (model)
126
+ post_body = opts[:debug_body]
127
+
128
+ # return_type
129
+ return_type = opts[:debug_return_type] || "GetLocationsResponse"
130
+
131
+ # auth_names
132
+ auth_names = opts[:debug_auth_names] || ["AirthingsAccounts"]
133
+
134
+ new_options = opts.merge(
135
+ operation: :"LocationsApi.locations_list",
136
+ header_params: header_params,
137
+ query_params: query_params,
138
+ form_params: form_params,
139
+ body: post_body,
140
+ auth_names: auth_names,
141
+ return_type: return_type
142
+ )
143
+
144
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
145
+ if @api_client.config.debugging
146
+ @api_client.config.logger.debug "API called: LocationsApi#locations_list\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
147
+ end
148
+ [data, status_code, headers]
149
+ end
150
+ end
151
+ end