wattsense-api-client 0.1.1 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7db2bbe58ae6d16bbe60630795b5f1b13d119866d7343ea4d506aed144913a30
4
- data.tar.gz: c04db780c6fa6bfadce50b46c65340b3010a9a314c3e035d517ba34ce0eda8af
3
+ metadata.gz: 5daf0eaf6d4b0cf53130c41d76935d044e77b67b287ab967899b4e818f6514a8
4
+ data.tar.gz: c441a7ff79cd7ac7d9f46ceccb1e5e036ee3101de3693c9d75e28ec07b034954
5
5
  SHA512:
6
- metadata.gz: e92463cc37db1ba3cba7937b3a6a1e8d8ba23097a6cd19d2a6d8e08cf81652e7b8ab1bc65af7322ceed5832d35dd7ee8aabb42c4799d75d780e39132b26e7513
7
- data.tar.gz: b012f3522c3e5695b791612ad2fbbab8eea792fe7820d2fc5fbffef44421fb9f8a0a5ee17d580583f2c70c2b1837523a7497c39b98622bb63d2d10dd2599a3e2
6
+ metadata.gz: ff389d81d92bfdbe45301865939c6a7c0776c5644ab7156f621f5810d1fb6ce3f2fb3e8512c3b2e954ee47970b2210b295716a20f4fbb907e507010b369cf5f8
7
+ data.tar.gz: 40990a3e454113c02bb27a122be74a67470c63c56fbe8371ba36feec67b308fac5a630e3a1bc2e88b735c4c93b491db885a1ae33082be01d3d5338a00c4935dd
@@ -21,8 +21,27 @@ class HttpRequester
21
21
  # HTTP GET method
22
22
  #
23
23
  # TODO: document
24
- def get(path, &before_req_callback)
25
- do_request(::Net::HTTP::Get.new(uri_from_path(path)), before_req_callback)
24
+ def get(path, query_parameters = nil, &before_req_callback)
25
+ uri = uri_from_path_and_query_parameters(path, query_parameters)
26
+ do_request(::Net::HTTP::Get.new(uri), before_req_callback)
27
+ end
28
+
29
+ # HTTP POST method
30
+ #
31
+ # TODO: document
32
+ def post(path, payload, &before_req_callback)
33
+ req = ::Net::HTTP::Post.new(uri_from_path_and_query_parameters(path))
34
+ req.body = payload
35
+ do_request(req, before_req_callback)
36
+ end
37
+
38
+ # HTTP POST method
39
+ #
40
+ # TODO: document
41
+ def put(path, payload, &before_req_callback)
42
+ req = ::Net::HTTP::Put.new(uri_from_path_and_query_parameters(path))
43
+ req.body = payload
44
+ do_request(req, before_req_callback)
26
45
  end
27
46
 
28
47
  private
@@ -37,7 +56,9 @@ class HttpRequester
37
56
  end
38
57
  end
39
58
 
40
- def uri_from_path(path)
41
- URI("#{@base_url}/#{path}")
59
+ def uri_from_path_and_query_parameters(path, query_parameters = nil)
60
+ uri = URI("#{@base_url}/#{path}")
61
+ uri.query = ::URI.encode_www_form(query_parameters) if query_parameters
62
+ uri
42
63
  end
43
64
  end
@@ -5,6 +5,9 @@
5
5
  #++
6
6
  # frozen_string_literal: true
7
7
 
8
+ require 'openssl'
9
+ require 'base64'
10
+
8
11
  module WattSenseApi
9
12
  module V1
10
13
  # This module gather all the necessary elements for ClientV1 ability to authenticate to the
@@ -19,8 +22,15 @@ module WattSenseApi
19
22
  #
20
23
  # @param api_key [String] The api's credential key
21
24
  # @param api_secret [String] The api's credential secret
22
- def api_key_authentication(_api_key, _api_secret)
23
- raise(::WattSenseApi::NotImplementedError, 'Please use (username, password) couple for now.')
25
+ def api_key_authentication(api_key, api_secret)
26
+ @auth_block =
27
+ lambda do |request|
28
+ time = now_in_ms
29
+ to_sign = to_sign_from_request(request, time)
30
+ signed = ::OpenSSL::HMAC.digest('SHA512', api_secret, to_sign.join("\n"))
31
+ request['X-API-Auth'] = "#{api_key}:#{::Base64.strict_encode64(signed)}"
32
+ request['X-API-Timestamp'] = time.to_s
33
+ end
24
34
  end
25
35
 
26
36
  # This method allows to use username/password credentials with HTTP Basic user authentication
@@ -31,6 +41,21 @@ module WattSenseApi
31
41
  def basic_user_authentication(username, password)
32
42
  @auth_block = ->(request) { request.basic_auth(username, password) }
33
43
  end
44
+
45
+ # @return [Integer] Time now in ms since Epoch
46
+ def now_in_ms
47
+ now = ::Time.now
48
+ now.tv_sec * 1000 + now.tv_usec / 1_000
49
+ end
50
+
51
+ # @return [String] Message to sign
52
+ def to_sign_from_request(request, time)
53
+ to_sign = [request.method, request.uri.path]
54
+ to_sign.push(request.uri.query) if request.uri.query
55
+ to_sign.push(request.body) if request.body
56
+ to_sign << time.to_s
57
+ to_sign
58
+ end
34
59
  end
35
60
  end
36
61
  end
@@ -11,6 +11,8 @@ require 'http_requester'
11
11
  require 'watt_sense_api/v1/authentication'
12
12
  require 'watt_sense_api/v1/organization'
13
13
  require 'watt_sense_api/v1/user_management'
14
+ require 'watt_sense_api/v1/device_information'
15
+ require 'watt_sense_api/v1/properties_measurements'
14
16
 
15
17
  module WattSenseApi
16
18
  module V1
@@ -20,6 +22,8 @@ module WattSenseApi
20
22
  include ::WattSenseApi::V1::Authentication
21
23
  include ::WattSenseApi::V1::Organization
22
24
  include ::WattSenseApi::V1::UserManagement
25
+ include ::WattSenseApi::V1::DeviceInformation
26
+ include ::WattSenseApi::V1::PropertiesMeasurements
23
27
 
24
28
  # You can create a client V1 with both user's credentials or api creddentials.
25
29
  #
@@ -44,7 +48,16 @@ module WattSenseApi
44
48
  'Please give one of either couples: (api_key, api_secret) or (username, password)'
45
49
  )
46
50
  end
47
- super(::WattSenseApi::V1::BASE_URL, auth_callback: @auth_block)
51
+ super(::WattSenseApi::V1::BASE_URL, auth_callback: @auth_block, headers_callback: headers_callback)
52
+ end
53
+
54
+ private
55
+
56
+ def headers_callback
57
+ lambda do |req|
58
+ req['Accept'] = 'application/json'
59
+ req['Content-Type'] = 'application/json'
60
+ end
48
61
  end
49
62
  end
50
63
  end
@@ -0,0 +1,61 @@
1
+ #--
2
+ # Copyright (C) 2021 - Octopus Lab SAS
3
+ # All rights are described by the GPLv3 license present in the file /LICENSE available in the
4
+ # original repository of this file or [here](https://www.gnu.org/licenses/gpl-3.0.fr.html).
5
+ #++
6
+ # frozen_string_literal: true
7
+
8
+ require 'net/http'
9
+ require 'json'
10
+
11
+ module WattSenseApi
12
+ module V1
13
+ # This module gather all the methods to deal with [Device Information](https://api.wattsense.com/#tag/Device-Information).
14
+ #
15
+ # In WattSense Api, the Wattsense Box is designated as device in all this API.
16
+ module DeviceInformation
17
+ # List all your devices
18
+ #
19
+ # @note: filters not implemented yet.
20
+ #
21
+ # @return [Array<Hash>] The devices information as a Hash in an Array.
22
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPSuccess with a body)
23
+ def devices
24
+ response = get('devices')
25
+ raise(::WattSenseApi::HTTPError, response) unless response.is_a?(::Net::HTTPSuccess)
26
+
27
+ return [] if response.is_a?(::Net::HTTPNoContent)
28
+
29
+ ::JSON.parse(response.body)
30
+ end
31
+
32
+ # Get the information of the specified one
33
+ #
34
+ # @param deviceId [String] The ID of the device which you seek the informations
35
+ #
36
+ # @return [Hash] The device information as a Hash when id is not nil.
37
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPSuccess with a body)
38
+ def device(id)
39
+ response = get("devices/#{id}")
40
+ raise(::WattSenseApi::HTTPError, response) unless response.is_a?(::Net::HTTPSuccess) && !response.body&.empty?
41
+
42
+ ::JSON.parse(response.body)
43
+ end
44
+
45
+ # Activate a device
46
+ #
47
+ # @note No check implemented nor tests.
48
+ #
49
+ # @param params [Hash] Parameters as expected by WattSense documentation.
50
+ #
51
+ # @return [Hash] The device information as a Hash
52
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPSuccess with a body)
53
+ def device_activate(params)
54
+ response = post('devices', params)
55
+ raise(::WattSenseApi::HTTPError, response) unless response.is_a?(::Net::HTTPSuccess) && !response.body&.empty?
56
+
57
+ ::JSON.parse(response.body)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,69 @@
1
+ #--
2
+ # Copyright (C) 2021 - Octopus Lab SAS
3
+ # All rights are described by the GPLv3 license present in the file /LICENSE available in the
4
+ # original repository of this file or [here](https://www.gnu.org/licenses/gpl-3.0.fr.html).
5
+ #++
6
+ # frozen_string_literal: true
7
+
8
+ require 'net/http'
9
+ require 'json'
10
+
11
+ module WattSenseApi
12
+ module V1
13
+ # This module gather all the methods to deal with [Properties Measurements](https://api.wattsense.com/#tag/Properties-Measurements)
14
+ module PropertiesMeasurements
15
+ # Get the specified device's properties list with values.
16
+ #
17
+ # @see https://api.wattsense.com/#operation/listDevicePropertiesValues API documentation
18
+ #
19
+ # @param device_id [String] The device id
20
+ #
21
+ # @return [Array<Hash>|NilClass] Array of the properties' values or nil if your device is not configured
22
+ # and/or has no properties.
23
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPSuccess with a body)
24
+ def device_properties(device_id)
25
+ response = get("devices/#{device_id}/properties")
26
+ return ::JSON.parse(response.body) if response.is_a?(::Net::HTTPOK)
27
+
28
+ return if response.is_a?(::Net::HTTPNoContent)
29
+
30
+ raise(::WattSenseApi::HTTPError, response)
31
+ end
32
+
33
+ # Get a specified device's property to a given value.
34
+ #
35
+ # @see https://api.wattsense.com/#operation/getPropertyMeasurement API documentation
36
+ #
37
+ # @param device_id [String] The device id
38
+ # @param property_id [String] The property id or slug for which we ask the latest value
39
+ #
40
+ # @return [Hash|NilClass] Hash of the property's latest value (nil if property is unreachable)
41
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPAccepted with a body)
42
+ def device_property(device_id, property_id)
43
+ response = get("devices/#{device_id}/properties/#{property_id}")
44
+ return ::JSON.parse(response.body) if response.is_a?(::Net::HTTPOK)
45
+
46
+ return if response.is_a?(::Net::HTTPNoContent)
47
+
48
+ raise(::WattSenseApi::HTTPError, response)
49
+ end
50
+
51
+ # Set a specified device's property to a given value.
52
+ #
53
+ # @see https://api.wattsense.com/#operation/setPropertyValue API documentation
54
+ #
55
+ # @param device_id [String] The device id
56
+ # @param property_id [String] The property id or slug for which we ask to set the value
57
+ # @param body [Hash] The body of the request. Hash that will be transformed to json.
58
+ #
59
+ # @return [Hash] Hash of the resulted action.
60
+ # @raise [::WattSenseApi::HTTPError] when server response is not as expected (HTTPAccepted with a body)
61
+ def device_property_set(device_id, property_id, body)
62
+ response = put("devices/#{device_id}/properties/#{property_id}", body.to_json)
63
+ return ::JSON.parse(response.body) if response.is_a?(::Net::HTTPAccepted)
64
+
65
+ raise(::WattSenseApi::HTTPError, response)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -6,6 +6,6 @@
6
6
  # frozen_string_literal: true
7
7
 
8
8
  module WattSenseApi
9
- VERSION = '0.1.1'
9
+ VERSION = '0.3.1'
10
10
  public_constant :VERSION
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wattsense-api-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roland Laurès
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-17 00:00:00.000000000 Z
11
+ date: 2021-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -17,7 +17,7 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.14'
20
- type: :runtime
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
@@ -31,7 +31,7 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.10'
34
- type: :runtime
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
@@ -45,7 +45,7 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 1.20.0
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -59,7 +59,7 @@ dependencies:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '2.4'
62
- type: :runtime
62
+ type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
@@ -73,7 +73,7 @@ dependencies:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.21.2
76
- type: :runtime
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
@@ -87,7 +87,7 @@ dependencies:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0.9'
90
- type: :runtime
90
+ type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
@@ -107,14 +107,20 @@ files:
107
107
  - lib/watt_sense_api/v1.rb
108
108
  - lib/watt_sense_api/v1/authentication.rb
109
109
  - lib/watt_sense_api/v1/client.rb
110
+ - lib/watt_sense_api/v1/device_information.rb
110
111
  - lib/watt_sense_api/v1/organization.rb
112
+ - lib/watt_sense_api/v1/properties_measurements.rb
111
113
  - lib/watt_sense_api/v1/user_management.rb
112
114
  - lib/watt_sense_api/version.rb
113
115
  - lib/wattsense-api-client.rb
114
116
  homepage: https://rubygems.org/gems/wattsense-api-client
115
117
  licenses:
116
118
  - GPL v3
117
- metadata: {}
119
+ metadata:
120
+ bug_tracker_uri: https://gitlab.com/octopuslab-public/wattsense-api-client/-/issues
121
+ changelog_uri: https://gitlab.com/octopuslab-public/wattsense-api-client/-/blob/main/CHANGELOG.md
122
+ documentation_uri: https://octopuslab-public.gitlab.io/wattsense-api-client/0.3.1
123
+ homepage_uri: https://gitlab.com/octopuslab-public/wattsense-api-client
118
124
  post_install_message:
119
125
  rdoc_options: []
120
126
  require_paths: