airthings 1.0.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
+ 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