waterfurnace_aurora 0.1.1 → 0.3.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/exe/aurora_fetch +26 -0
- data/{bin → exe}/aurora_mock +23 -20
- data/{bin → exe}/aurora_monitor +20 -18
- data/exe/aurora_mqtt_bridge +189 -0
- data/{bin → exe}/registers.yml +0 -0
- data/lib/aurora/abc_client.rb +64 -42
- data/lib/aurora/core_ext/string.rb +10 -0
- data/lib/aurora/iz2_zone.rb +38 -52
- data/lib/aurora/modbus/server.rb +22 -15
- data/lib/aurora/modbus/slave.rb +27 -20
- data/lib/aurora/registers.rb +216 -205
- data/lib/aurora/thermostat.rb +57 -0
- data/lib/aurora/version.rb +3 -1
- data/lib/aurora.rb +9 -6
- data/lib/waterfurnace_aurora.rb +3 -1
- metadata +29 -24
- data/bin/aurora_fetch +0 -25
- data/bin/aurora_mqtt_bridge +0 -289
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 353f714b82fb803a5a816781e39f1e952fea04485fa09d32f36f363b003bcfd3
|
4
|
+
data.tar.gz: 70b12365ae3f13cfca0fd70104d552efee6b520985e2844795a480130ae42929
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40937d99b2c3cc6044f6ddfda7ef3c8e789192e31e7ca47e5057f18c4deeb5b33a745bcef155a0c78bc35ce598f631e5d3a9bbbb18bb3b739d0aab7c4b87e2c7
|
7
|
+
data.tar.gz: 4c7e83279bce76b4baa09d74b5b56394822405694fbcecc3b8674caedb9eef9e0baeea518305e1268ac39c719e411010c9d78c00ab1cccb9b0378763b0809873
|
data/exe/aurora_fetch
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "aurora"
|
5
|
+
require "ccutrer-serialport"
|
6
|
+
require "uri"
|
7
|
+
|
8
|
+
uri = URI.parse(ARGV[0])
|
9
|
+
|
10
|
+
args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
11
|
+
require "net/telnet/rfc2217"
|
12
|
+
[Net::Telnet::RFC2217.new("Host" => uri.host,
|
13
|
+
"Port" => uri.port || 23,
|
14
|
+
"baud" => 19_200,
|
15
|
+
"parity" => Net::Telnet::RFC2217::EVEN)]
|
16
|
+
else
|
17
|
+
[CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
|
18
|
+
end
|
19
|
+
|
20
|
+
client = ModBus::RTUClient.new(*args)
|
21
|
+
client.debug = true
|
22
|
+
slave = client.with_slave(1)
|
23
|
+
|
24
|
+
registers = slave.holding_registers[ARGV[1].to_i]
|
25
|
+
|
26
|
+
puts registers.inspect
|
data/{bin → exe}/aurora_mock
RENAMED
@@ -1,21 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
4
|
+
require "aurora"
|
5
|
+
require "ccutrer-serialport"
|
6
|
+
require "uri"
|
7
|
+
require "yaml"
|
7
8
|
|
8
9
|
uri = URI.parse(ARGV[0])
|
9
10
|
|
10
11
|
args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
else
|
17
|
-
|
18
|
-
end
|
12
|
+
require "net/telnet/rfc2217"
|
13
|
+
[Net::Telnet::RFC2217.new("Host" => uri.host,
|
14
|
+
"Port" => uri.port || 23,
|
15
|
+
"baud" => 19_200,
|
16
|
+
"parity" => Net::Telnet::RFC2217::EVEN)]
|
17
|
+
else
|
18
|
+
[CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
|
19
|
+
end
|
19
20
|
|
20
21
|
port = ARGV[1]&.to_i || 502
|
21
22
|
|
@@ -27,13 +28,13 @@ slave2 = server1.with_slave(2)
|
|
27
28
|
server2 = ModBus::TCPServer.new(port)
|
28
29
|
slave255 = server2.with_slave(255)
|
29
30
|
|
30
|
-
r = slave1.holding_registers = slave2.holding_registers = slave255.holding_registers = Array.new(
|
31
|
+
r = slave1.holding_registers = slave2.holding_registers = slave255.holding_registers = Array.new(31_473, 0)
|
31
32
|
|
32
33
|
# prepopulate some data
|
33
|
-
registers = YAML.
|
34
|
+
registers = YAML.safe_load(File.read(File.expand_path("registers.yml", __dir__)))
|
34
35
|
registers.each { |(k, v)| r[k] = v }
|
35
36
|
|
36
|
-
server1.request_callback =
|
37
|
+
server1.request_callback = lambda { |uid, func, req|
|
37
38
|
if func == 68
|
38
39
|
puts "===== no idea to #{uid}: #{req.inspect}"
|
39
40
|
elsif func == 67
|
@@ -45,12 +46,13 @@ server1.request_callback = ->(uid, func, req) do
|
|
45
46
|
registers = Range.new(req[:addr], req[:addr] + req[:quant] - 1).zip(req[:val]).to_h
|
46
47
|
puts Aurora.print_registers(registers)
|
47
48
|
elsif [3, 65, 66].include?(func)
|
49
|
+
# no output
|
48
50
|
else
|
49
51
|
puts "**** new func #{func}"
|
50
52
|
end
|
51
|
-
|
53
|
+
}
|
52
54
|
|
53
|
-
server1.response_callback =
|
55
|
+
server1.response_callback = lambda { |uid, func, res, req|
|
54
56
|
if func == 3 && res.is_a?(Array) && req
|
55
57
|
unless req[:quant] == res.length
|
56
58
|
puts "wrong number of results"
|
@@ -78,12 +80,13 @@ server1.response_callback = ->(uid, func, res, req) do
|
|
78
80
|
registers = req.zip(res).to_h
|
79
81
|
puts Aurora.print_registers(registers)
|
80
82
|
elsif [16, 67, 68].include?(func)
|
83
|
+
# no output
|
81
84
|
else
|
82
85
|
puts "**** new func #{func}"
|
83
86
|
end
|
84
|
-
|
87
|
+
}
|
85
88
|
|
86
89
|
server2.start
|
87
90
|
server1.send(:serve, server1.instance_variable_get(:@sp))
|
88
|
-
#server1.start
|
89
|
-
loop {}
|
91
|
+
# server1.start
|
92
|
+
loop { nil }
|
data/{bin → exe}/aurora_monitor
RENAMED
@@ -1,27 +1,28 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
4
|
+
require "aurora"
|
5
|
+
require "ccutrer-serialport"
|
6
|
+
require "socket"
|
7
|
+
require "uri"
|
7
8
|
|
8
9
|
uri = URI.parse(ARGV[0])
|
9
10
|
|
10
11
|
args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
else
|
17
|
-
|
18
|
-
end
|
12
|
+
require "net/telnet/rfc2217"
|
13
|
+
[Net::Telnet::RFC2217.new("Host" => uri.host,
|
14
|
+
"Port" => uri.port || 23,
|
15
|
+
"baud" => 19_200,
|
16
|
+
"parity" => Net::Telnet::RFC2217::EVEN)]
|
17
|
+
else
|
18
|
+
[CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
|
19
|
+
end
|
19
20
|
|
20
21
|
server = ModBus::RTUServer.new(*args)
|
21
22
|
server.promiscuous = true
|
22
23
|
server.debug = true
|
23
24
|
|
24
|
-
server.request_callback =
|
25
|
+
server.request_callback = lambda { |uid, func, req|
|
25
26
|
if func == 68
|
26
27
|
puts "===== no idea to #{uid}: #{req.inspect}"
|
27
28
|
elsif func == 67
|
@@ -33,12 +34,13 @@ server.request_callback = ->(uid, func, req) do
|
|
33
34
|
registers = Range.new(req[:addr], req[:addr] + req[:quant] - 1).zip(req[:val]).to_h
|
34
35
|
puts Aurora.print_registers(registers)
|
35
36
|
elsif [3, 65, 66].include?(func)
|
37
|
+
# no output
|
36
38
|
else
|
37
39
|
puts "**** new func #{func}"
|
38
40
|
end
|
39
|
-
|
41
|
+
}
|
40
42
|
|
41
|
-
server.response_callback =
|
43
|
+
server.response_callback = lambda { |uid, func, res, req|
|
42
44
|
if func == 3 && res.is_a?(Array) && req
|
43
45
|
unless req[:quant] == res.length
|
44
46
|
puts "wrong number of results"
|
@@ -66,11 +68,11 @@ server.response_callback = ->(uid, func, res, req) do
|
|
66
68
|
registers = req.zip(res).to_h
|
67
69
|
puts Aurora.print_registers(registers)
|
68
70
|
elsif [16, 67, 68].include?(func)
|
71
|
+
# no output
|
69
72
|
else
|
70
73
|
puts "**** new func #{func}"
|
71
74
|
end
|
72
|
-
|
75
|
+
}
|
73
76
|
|
74
|
-
require 'byebug'
|
75
77
|
server.send(:serve, server.instance_variable_get(:@sp))
|
76
|
-
loop {}
|
78
|
+
loop { nil }
|
@@ -0,0 +1,189 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "aurora"
|
5
|
+
require "homie-mqtt"
|
6
|
+
require "ccutrer-serialport"
|
7
|
+
require "uri"
|
8
|
+
require "aurora/core_ext/string"
|
9
|
+
|
10
|
+
uri = URI.parse(ARGV[0])
|
11
|
+
mqtt_uri = ARGV[1]
|
12
|
+
|
13
|
+
args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
14
|
+
require "net/telnet/rfc2217"
|
15
|
+
[Net::Telnet::RFC2217.new("Host" => uri.host,
|
16
|
+
"Port" => uri.port || 23,
|
17
|
+
"baud" => 19_200,
|
18
|
+
"parity" => Net::Telnet::RFC2217::EVEN)]
|
19
|
+
else
|
20
|
+
[CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
|
21
|
+
end
|
22
|
+
|
23
|
+
slave = ModBus::RTUClient.new(*args).with_slave(1)
|
24
|
+
abc = Aurora::ABCClient.new(slave)
|
25
|
+
|
26
|
+
class MQTTBridge
|
27
|
+
def initialize(abc, homie)
|
28
|
+
@abc = abc
|
29
|
+
@homie = homie
|
30
|
+
@mutex = Mutex.new
|
31
|
+
|
32
|
+
@homie.instance_variable_set(:@block, lambda do |topic, value|
|
33
|
+
@mutex.synchronize do
|
34
|
+
case topic
|
35
|
+
when /\$modbus$/
|
36
|
+
query = value.split(",").map do |addr|
|
37
|
+
case addr
|
38
|
+
when "known"
|
39
|
+
Aurora::REGISTER_NAMES.keys
|
40
|
+
when /^(\d+)\.\.(\d+)$/
|
41
|
+
Regexp.last_match(1).to_i..Regexp.last_match(2).to_i
|
42
|
+
else
|
43
|
+
addr.to_i
|
44
|
+
end
|
45
|
+
end
|
46
|
+
queries = Aurora.normalize_ranges(query)
|
47
|
+
registers = {}
|
48
|
+
queries.each do |subquery|
|
49
|
+
registers.merge!(@abc.modbus_slave.read_multiple_holding_registers(*subquery))
|
50
|
+
end
|
51
|
+
result = Aurora.print_registers(registers)
|
52
|
+
@homie.mqtt.publish("#{@homie.topic}/$modbus/response", result, retain: false, qos: 1)
|
53
|
+
when %r{\$modbus/(\d+)$}
|
54
|
+
register = Regexp.last_match(1).to_i
|
55
|
+
value = case value
|
56
|
+
when /\d+/
|
57
|
+
value.to_i
|
58
|
+
when /0x(\d+)/
|
59
|
+
Regexp.last_match(1).to_i(16)
|
60
|
+
end
|
61
|
+
@abc.modbus_slave.holding_registers[register] = value if value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
rescue StandardError => e
|
65
|
+
puts "failed processing message: #{e}\n#{e.backtrace}"
|
66
|
+
end)
|
67
|
+
|
68
|
+
publish_basic_attributes
|
69
|
+
|
70
|
+
loop do
|
71
|
+
begin
|
72
|
+
@mutex.synchronize do
|
73
|
+
@abc.refresh
|
74
|
+
%i[compressor_speed
|
75
|
+
current_mode
|
76
|
+
dhw_water_temperature
|
77
|
+
entering_air_temperature
|
78
|
+
fan_speed
|
79
|
+
leaving_air_temperature
|
80
|
+
leaving_water_temperature
|
81
|
+
outdoor_temperature
|
82
|
+
relative_humidity
|
83
|
+
waterflow
|
84
|
+
fp1
|
85
|
+
fp2
|
86
|
+
compressor_watts
|
87
|
+
blower_watts
|
88
|
+
aux_heat_watts
|
89
|
+
loop_pump_watts
|
90
|
+
total_watts].each do |property|
|
91
|
+
@homie_abc[property.to_s.tr("_", "-")].value = @abc.public_send(property)
|
92
|
+
end
|
93
|
+
|
94
|
+
@abc.zones.each do |z|
|
95
|
+
homie_zone = @homie["zone#{z.zone_number}"]
|
96
|
+
homie_zone.each do |property|
|
97
|
+
property.value = z.public_send(property.id.tr("-", "_"))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
rescue => e
|
102
|
+
puts "got garbage: #{e}; #{e.backtrace}"
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
sleep(5)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def publish_basic_attributes
|
110
|
+
@homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
|
111
|
+
node.property("compressor-speed", "Compressor Speed", :integer, @abc.compressor_speed, format: 0..1)
|
112
|
+
node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
|
113
|
+
format: %w[lockout standby blower h1 h2 c1 c2 eh1 eh2])
|
114
|
+
node.property("dhw-water-temperature", "DHW Water Temperature", :float, @abc.dhw_water_temperature, unit: "ºF")
|
115
|
+
node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
|
116
|
+
unit: "ºF")
|
117
|
+
node.property("entering-water-temperature", "Entering Water Temperature", :float,
|
118
|
+
@abc.entering_water_temperature, unit: "ºF")
|
119
|
+
node.property("fan-speed", "Fan Speed", :integer, @abc.fan_speed, format: 0..11)
|
120
|
+
node.property("leaving-air-temperature", "Leaving Air Temperature", :float, @abc.leaving_air_temperature,
|
121
|
+
unit: "ºF")
|
122
|
+
node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
|
123
|
+
unit: "ºF")
|
124
|
+
node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
|
125
|
+
node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
|
126
|
+
format: 0..100)
|
127
|
+
node.property("waterflow", "Waterflow", :float, unit: "gpm")
|
128
|
+
node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
|
129
|
+
node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
|
130
|
+
%i[compressor blower aux_heat loop_pump total].each do |component|
|
131
|
+
component = "#{component}_watts"
|
132
|
+
node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
|
133
|
+
@abc.public_send(component), unit: "W")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
@abc.zones.each do |zone|
|
138
|
+
type = zone.is_a?(Aurora::IZ2Zone) ? "IntelliZone 2 Zone" : "Thermostat"
|
139
|
+
@homie.node("zone#{zone.zone_number}", "Zone #{zone.zone_number}", type) do |node|
|
140
|
+
allowed_modes = %w[off auto cool heat]
|
141
|
+
allowed_modes << "eheat" if !zone.respond_to?(:zone_number) || zone.zone_number == 1
|
142
|
+
node.property("target-mode", "Target Heating/Cooling Mode", :enum, zone.target_mode,
|
143
|
+
format: allowed_modes) do |value, property|
|
144
|
+
@mutex.synchronize { property.value = zone.target_mode = value.to_sym }
|
145
|
+
end
|
146
|
+
if zone.respond_to?(:current_mode) # TODO: implement for non-IZ2
|
147
|
+
node.property("current-mode", "Current Heating/Cooling Mode Requested", :enum, zone.current_mode,
|
148
|
+
format: %w[standby h1 h2 h3 c1 c2])
|
149
|
+
end
|
150
|
+
node.property("target-fan-mode", "Target Fan Mode", :enum, zone.target_fan_mode,
|
151
|
+
format: %w[auto continuous intermittent]) do |value, property|
|
152
|
+
@mutex.synchronize { property.value = zone.target_fan_mode = value.to_sym }
|
153
|
+
end
|
154
|
+
if zone.respond_to?(:current_fan_mode) # TODO: implement for non-IZ2
|
155
|
+
node.property("current-fan-mode", "Current Fan Status", :boolean, zone.current_fan_mode)
|
156
|
+
node.property("fan-intermittent-on", "Fan Intermittent Mode On Duration", :enum, zone.fan_intermittent_on,
|
157
|
+
unit: "M", format: %w[0 5 10 15 20]) do |value, property|
|
158
|
+
@mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
|
159
|
+
end
|
160
|
+
node.property("fan-intermittent-off", "Fan Intermittent Mode Off Duration", :enum, zone.fan_intermittent_on,
|
161
|
+
unit: "M", format: %w[0 5 10 15 20 25 30 35 40]) do |value, property|
|
162
|
+
@mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
if zone.is_a?(Aurora::IZ2Zone)
|
166
|
+
node.property("priority", "Zone Priority", :enum, zone.priority, format: %w[economy comfort])
|
167
|
+
node.property("size", "Size", :enum, zone.size, format: %w[0 25 45 70])
|
168
|
+
node.property("normalized-size", "Normalized Size", :integer, zone.normalized_size, unit: "%", format: 0..100)
|
169
|
+
end
|
170
|
+
node.property("ambient-temperature", "Ambient Temperature", :float, zone.ambient_temperature, unit: "ºF")
|
171
|
+
node.property("heating-target-temperature", "Heating Target Temperature", :integer,
|
172
|
+
zone.heating_target_temperature, unit: "ºF", format: 40..90) do |value, property|
|
173
|
+
@mutex.synchronize { property.value = zone.heating_target_temperature = value }
|
174
|
+
end
|
175
|
+
node.property("cooling-target-temperature", "Cooling Target Temperature", :integer,
|
176
|
+
zone.cooling_target_temperature, unit: "ºF", format: 54..99) do |value, property|
|
177
|
+
@mutex.synchronize { property.value = zone.cooling_target_temperature = value }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# direct access to modbus registers for debugging purposes
|
183
|
+
@homie.mqtt.subscribe("#{@homie.topic}/$modbus")
|
184
|
+
@homie.mqtt.subscribe("#{@homie.topic}/$modbus/+")
|
185
|
+
@homie.publish
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
MQTTBridge.new(abc, MQTT::Homie::Device.new("aurora", "Aurora MQTT Bridge", mqtt: mqtt_uri))
|
data/{bin → exe}/registers.yml
RENAMED
File without changes
|
data/lib/aurora/abc_client.rb
CHANGED
@@ -1,39 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Aurora
|
2
4
|
class ABCClient
|
3
5
|
attr_reader :modbus_slave,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
6
|
+
:zones,
|
7
|
+
:current_mode,
|
8
|
+
:fan_speed,
|
9
|
+
:entering_air_temperature,
|
10
|
+
:relative_humidity,
|
11
|
+
:leaving_air_temperature,
|
12
|
+
:leaving_water_temperature,
|
13
|
+
:entering_water_temperature,
|
14
|
+
:dhw_water_temperature,
|
15
|
+
:waterflow,
|
16
|
+
:compressor_speed,
|
17
|
+
:outdoor_temperature,
|
18
|
+
:fp1,
|
19
|
+
:fp2,
|
20
|
+
:compressor_watts,
|
21
|
+
:blower_watts,
|
22
|
+
:aux_heat_watts,
|
23
|
+
:loop_pump_watts,
|
24
|
+
:total_watts
|
18
25
|
|
19
26
|
def initialize(modbus_slave)
|
20
27
|
@modbus_slave = modbus_slave
|
21
28
|
@modbus_slave.read_retry_timeout = 15
|
22
29
|
@modbus_slave.read_retries = 2
|
23
30
|
iz2_zone_count = @modbus_slave.holding_registers[483]
|
24
|
-
|
31
|
+
# TODO: better detect IZ2/Non-IZ2
|
32
|
+
@zones = if iz2_zone_count > 1
|
33
|
+
(0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
|
34
|
+
else
|
35
|
+
[Thermostat.new(self)]
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
39
|
def refresh
|
28
|
-
registers_to_read = [19..20, 30, 344, 740..741, 900, 1110..1111, 1114, 1117, 3027,
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
registers_to_read = [19..20, 30, 344, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027, 31_003]
|
41
|
+
if zones.first.is_a?(IZ2Zone)
|
42
|
+
zones.each_with_index do |_z, i|
|
43
|
+
base1 = 21_203 + i * 9
|
44
|
+
base2 = 31_007 + i * 3
|
45
|
+
base3 = 31_200 + i * 3
|
46
|
+
registers_to_read << (base1..(base1 + 1))
|
47
|
+
registers_to_read << (base2..(base2 + 2))
|
48
|
+
registers_to_read << base3
|
49
|
+
end
|
50
|
+
else
|
51
|
+
registers_to_read << 745..747
|
37
52
|
end
|
38
53
|
|
39
54
|
registers = @modbus_slave.holding_registers[*registers_to_read]
|
@@ -48,35 +63,42 @@ module Aurora
|
|
48
63
|
@dhw_water_temperature = registers[1114]
|
49
64
|
@waterflow = registers[1117]
|
50
65
|
@compressor_speed = registers[3027]
|
51
|
-
@outdoor_temperature = registers[
|
66
|
+
@outdoor_temperature = registers[31_003]
|
52
67
|
@fp1 = registers[19]
|
53
68
|
@fp2 = registers[20]
|
54
69
|
@locked_out = registers[1117]
|
70
|
+
@compressor_watts = registers[1147]
|
71
|
+
@blower_watts = registers[1149]
|
72
|
+
@aux_heat_watts = registers[1151]
|
73
|
+
@loop_pump_watts = registers[1165]
|
74
|
+
@total_watts = registers[1153]
|
55
75
|
|
56
76
|
outputs = registers[30]
|
57
|
-
if outputs.include?(:lockout)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
77
|
+
@current_mode = if outputs.include?(:lockout)
|
78
|
+
:lockout
|
79
|
+
elsif outputs.include?(:cc2)
|
80
|
+
outputs.include?(:rv) ? :c2 : :h2
|
81
|
+
elsif outputs.include?(:cc)
|
82
|
+
outputs.include?(:rv) ? :c1 : :h1
|
83
|
+
elsif outputs.include?(:eh2)
|
84
|
+
:eh2
|
85
|
+
elsif outputs.include?(:eh1)
|
86
|
+
:eh1
|
87
|
+
elsif outputs.include?(:blower)
|
88
|
+
:blower
|
89
|
+
else
|
90
|
+
:standby
|
91
|
+
end
|
72
92
|
|
73
|
-
|
93
|
+
zones.each do |z|
|
74
94
|
z.refresh(registers)
|
75
95
|
end
|
76
96
|
end
|
77
97
|
|
78
98
|
def inspect
|
79
|
-
"#<Aurora::ABCClient #{(instance_variables - [:@modbus_slave]).map
|
99
|
+
"#<Aurora::ABCClient #{(instance_variables - [:@modbus_slave]).map do |iv|
|
100
|
+
"#{iv}=#{instance_variable_get(iv).inspect}"
|
101
|
+
end.join(', ')}>"
|
80
102
|
end
|
81
103
|
end
|
82
104
|
end
|