cocoro 0.1.0 → 0.2.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 +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +1 -0
- data/lib/cocoro/client.rb +41 -33
- data/lib/cocoro/device.rb +21 -0
- data/lib/cocoro/error.rb +12 -0
- data/lib/cocoro/status.rb +11 -21
- data/lib/cocoro/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fc40cbd13bb06a8555da9d6939190793b159fd06ffe8d651cfa9cb5350bac62
|
4
|
+
data.tar.gz: 6042dfbba25e20371af33af4ef6942948c3c13271426fc3328ea831b4f13ac54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82d9251f028fc3d265a81764f72bd725558b7fb6ca98a87752070af04a74a5625f3330cef4d5c0199d4158be9eb37c58443e9530ac2ec90ee5e540ab043eaddc
|
7
|
+
data.tar.gz: e42598903d675c80ac8e934358f937a0242b271edb61dadab77dfdb9132448f15416282d3670c6888aad2933d200bf08f949c0e7b76a34bb4b076a3f633afb76
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
data/lib/cocoro/client.rb
CHANGED
@@ -27,6 +27,8 @@ module Cocoro
|
|
27
27
|
DEFAULT_RESULT_CHECK_INTERVAL = 0.7 # seconds
|
28
28
|
DEFAULT_RESULT_CHECK_MAX_ATTEMPTS = 20
|
29
29
|
|
30
|
+
attr_accessor :logger
|
31
|
+
|
30
32
|
def initialize(app_secret:, terminal_app_id_key:, logger: nil)
|
31
33
|
@app_secret = app_secret
|
32
34
|
@terminal_app_id_key = terminal_app_id_key
|
@@ -56,25 +58,17 @@ module Cocoro
|
|
56
58
|
body,
|
57
59
|
{}
|
58
60
|
)
|
61
|
+
rescue Faraday::Error
|
62
|
+
raise Cocoro::ServerError
|
59
63
|
end
|
60
64
|
|
61
65
|
def devices
|
62
|
-
response =
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
json["box"].flat_map do |box|
|
67
|
-
box["echonetData"].map do |data|
|
68
|
-
Cocoro::Device.new(
|
69
|
-
client: self,
|
70
|
-
box_id: box["boxId"],
|
71
|
-
device_id: data["deviceId"],
|
72
|
-
echonet_node: data["echonetNode"],
|
73
|
-
echonet_object: data["echonetObject"],
|
74
|
-
name: data["labelData"]["name"]
|
75
|
-
)
|
76
|
-
end
|
66
|
+
response = handle_server_errors do
|
67
|
+
@client.get(
|
68
|
+
"setting/boxInfo?appSecret=#{CGI.escape(@app_secret)}&mode=other"
|
69
|
+
)
|
77
70
|
end
|
71
|
+
Cocoro::Device.parse_box_info(response.body["box"], self)
|
78
72
|
end
|
79
73
|
|
80
74
|
def device_status(device:)
|
@@ -84,9 +78,11 @@ module Cocoro
|
|
84
78
|
echonetNode: device.echonet_node,
|
85
79
|
echonetObject: device.echonet_object
|
86
80
|
}.map { |k, v| [k, CGI.escape(v)].join("=") }
|
87
|
-
response =
|
88
|
-
|
89
|
-
|
81
|
+
response = handle_server_errors do
|
82
|
+
@client.get(
|
83
|
+
"control/deviceStatus?#{query_params.join("&")}"
|
84
|
+
)
|
85
|
+
end
|
90
86
|
json = response.body
|
91
87
|
Cocoro::Status.new(json["deviceStatus"]["status"])
|
92
88
|
end
|
@@ -118,17 +114,19 @@ module Cocoro
|
|
118
114
|
appSecret: @app_secret,
|
119
115
|
boxId: device.box_id
|
120
116
|
}.map { |k, v| [k, CGI.escape(v)].join("=") }
|
121
|
-
response =
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
117
|
+
response = handle_server_errors do
|
118
|
+
@client.post(
|
119
|
+
"control/deviceControl?#{query_params.join("&")}",
|
120
|
+
controlList: [
|
121
|
+
{
|
122
|
+
deviceId: device.device_id,
|
123
|
+
echonetNode: device.echonet_node,
|
124
|
+
echonetObject: device.echonet_object,
|
125
|
+
status: changes
|
126
|
+
}
|
127
|
+
]
|
128
|
+
)
|
129
|
+
end
|
132
130
|
response.body["controlList"].first["id"]
|
133
131
|
end
|
134
132
|
|
@@ -137,15 +135,25 @@ module Cocoro
|
|
137
135
|
appSecret: @app_secret,
|
138
136
|
boxId: device.box_id
|
139
137
|
}.map { |k, v| [k, CGI.escape(v)].join("=") }
|
140
|
-
response =
|
141
|
-
|
142
|
-
|
143
|
-
|
138
|
+
response = handle_server_errors do
|
139
|
+
@client.post(
|
140
|
+
"control/controlResult?#{query_params.join("&")}",
|
141
|
+
resultList: [{ id: request_id }]
|
142
|
+
)
|
143
|
+
end
|
144
144
|
result = response.body["resultList"].first
|
145
145
|
@logger.info("Status: #{result["status"]}")
|
146
146
|
raise Cocoro::Error, "Error code: #{result["errorCode"]}" if result["status"] == "error"
|
147
147
|
|
148
148
|
result
|
149
149
|
end
|
150
|
+
|
151
|
+
def handle_server_errors(&block)
|
152
|
+
block.call
|
153
|
+
rescue Faraday::UnauthorizedError, Faraday::ForbiddenError
|
154
|
+
raise Cocoro::AuthError
|
155
|
+
rescue Faraday::Error
|
156
|
+
raise Cocoro::ServerError
|
157
|
+
end
|
150
158
|
end
|
151
159
|
end
|
data/lib/cocoro/device.rb
CHANGED
@@ -11,8 +11,29 @@ module Cocoro
|
|
11
11
|
:echonet_node,
|
12
12
|
:echonet_object,
|
13
13
|
:name,
|
14
|
+
:type,
|
15
|
+
:maker,
|
16
|
+
:model,
|
14
17
|
keyword_init: true
|
15
18
|
) do
|
19
|
+
def self.parse_box_info(box_info, client)
|
20
|
+
box_info.flat_map do |box|
|
21
|
+
box["echonetData"].map do |data|
|
22
|
+
new(
|
23
|
+
client: client,
|
24
|
+
box_id: box["boxId"],
|
25
|
+
device_id: data["deviceId"],
|
26
|
+
echonet_node: data["echonetNode"],
|
27
|
+
echonet_object: data["echonetObject"],
|
28
|
+
name: data["labelData"]["name"],
|
29
|
+
type: data["labelData"]["deviceType"],
|
30
|
+
maker: data["maker"],
|
31
|
+
model: data["model"]
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
16
37
|
def status
|
17
38
|
@status || fetch_status!
|
18
39
|
end
|
data/lib/cocoro/error.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Cocoro
|
4
|
+
# Base error class
|
4
5
|
class Error < StandardError
|
5
6
|
end
|
7
|
+
|
8
|
+
# Any non-200 response from the API
|
9
|
+
#
|
10
|
+
# That includes 400 responses which seems to be happening
|
11
|
+
# occasionally without any fault on the client side.
|
12
|
+
class ServerError < Cocoro::Error
|
13
|
+
end
|
14
|
+
|
15
|
+
# 401 or 403 error
|
16
|
+
class AuthError < Cocoro::ServerError
|
17
|
+
end
|
6
18
|
end
|
data/lib/cocoro/status.rb
CHANGED
@@ -9,23 +9,21 @@ module Cocoro
|
|
9
9
|
temperature: ["F1", 4, 1], # °C
|
10
10
|
humidity: ["F1", 5, 1], # %
|
11
11
|
total_air_cleaned: ["F1", 22, 4], # m^3
|
12
|
-
pm25: ["F1", 28, 2], # ug/m^3
|
13
|
-
|
14
|
-
smell: ["F2", 15, 1], # 0/33/66/100 (100=dirty)
|
12
|
+
pm25: ["F1", 28, 2], # ug/m^3, only last 9 bits are important
|
13
|
+
odor: ["F2", 15, 1], # 0/33/66/100 (100=dirty)
|
15
14
|
dust: ["F2", 16, 1], # 0/25/50/75/100 (100=dirty)
|
16
|
-
|
17
|
-
f2unknown19: ["F2", 19, 1],
|
15
|
+
overall_dirtiness: ["F2", 18, 1], # 0/25/50/75/100 (100=dirty)
|
18
16
|
enough_water: ["F2", 20, 1],
|
19
17
|
light_detected: ["F2", 21, 1],
|
20
18
|
air_volume: ["F3", 5, 1],
|
21
19
|
power_on: ["F3", 14, 1],
|
22
|
-
humidifier_on: ["F3", 16, 1]
|
23
|
-
f3unknown20: ["F3", 20, 1]
|
20
|
+
humidifier_on: ["F3", 16, 1]
|
24
21
|
}.freeze
|
25
22
|
VALUES = {
|
26
23
|
enough_water: { 0 => false, 255 => true },
|
27
24
|
light_detected: { 0 => false, 255 => true },
|
28
25
|
air_volume: {
|
26
|
+
0 => nil,
|
29
27
|
16 => "auto",
|
30
28
|
17 => "night",
|
31
29
|
19 => "pollen",
|
@@ -41,7 +39,7 @@ module Cocoro
|
|
41
39
|
|
42
40
|
BOOLEAN_FIELDS = %i[enough_water light_detected power_on humidifier_on].freeze
|
43
41
|
NON_BOOLEAN_FIELDS = %i[
|
44
|
-
temperature humidity total_air_cleaned pm25
|
42
|
+
temperature humidity total_air_cleaned pm25 odor dust overall_dirtiness air_volume
|
45
43
|
].freeze
|
46
44
|
|
47
45
|
def initialize(array_of_status_data)
|
@@ -56,12 +54,9 @@ module Cocoro
|
|
56
54
|
define_method(field) { read_value(field) }
|
57
55
|
end
|
58
56
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
.keys
|
63
|
-
.select { |key| key.to_s =~ /unknown/ }
|
64
|
-
.map { |key| [key, read_value(key)] }
|
57
|
+
def to_h
|
58
|
+
(BOOLEAN_FIELDS + NON_BOOLEAN_FIELDS)
|
59
|
+
.map { |f| [f, read_value(f)] }
|
65
60
|
.to_h
|
66
61
|
.merge(
|
67
62
|
f1: read_binary_status("F1"),
|
@@ -70,13 +65,6 @@ module Cocoro
|
|
70
65
|
)
|
71
66
|
end
|
72
67
|
|
73
|
-
def to_h
|
74
|
-
(BOOLEAN_FIELDS + NON_BOOLEAN_FIELDS)
|
75
|
-
.map { |f| [f, read_value(f)] }
|
76
|
-
.to_h
|
77
|
-
.merge(unknowns)
|
78
|
-
end
|
79
|
-
|
80
68
|
protected
|
81
69
|
|
82
70
|
def read_value(name)
|
@@ -87,6 +75,8 @@ module Cocoro
|
|
87
75
|
number = hex_code[(byte_offset - 1) * 2, byte_length * 2].to_i(16)
|
88
76
|
if VALUES[name]&.key?(number)
|
89
77
|
VALUES[name][number]
|
78
|
+
elsif name == :pm25
|
79
|
+
number & ((2**9) - 1) # last 9 bits only
|
90
80
|
else
|
91
81
|
number
|
92
82
|
end
|
data/lib/cocoro/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomasz Szczęśniak-Szlagowski
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: '0'
|
161
161
|
requirements: []
|
162
|
-
rubygems_version: 3.
|
162
|
+
rubygems_version: 3.1.6
|
163
163
|
signing_key:
|
164
164
|
specification_version: 4
|
165
165
|
summary: An unofficial Cocoro Air client
|