waterfurnace_aurora 0.3.13 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a92c5ae13a08cf060e3c7f23613cc1302e20af0bc4bc7c77c610936bea48c2b5
4
- data.tar.gz: 914c7c6371755e06524e063b5eb6820ca63f67844713d4d396cd08559fa62cc6
3
+ metadata.gz: 290c5d09deda24b527dbe0b1a00e93481c0951a38ef0be40b36cfd5fb33a4e4a
4
+ data.tar.gz: 33b16f155897683cc0b9a3c915bc3edeb2cb78e869cbfbc7246bd1da01abac71
5
5
  SHA512:
6
- metadata.gz: 384657c10727cf0a955cf4a4db5270d8ee021629e40c0dee65170e22206e3b0c21c85da2beade4f02143cdd5ff8d5631d5429c6a2957b96d933a3476cf83078c
7
- data.tar.gz: 6ea98c0cd77e83158d8313a851b0fa155cc6ee7a042aa338abb27c3c57cec543017b1ab97953aedf11d4645fedd5a6423c35b2c4f75fae6c768cfd1d5e47635d
6
+ metadata.gz: 82efe304dfc3a00670c8b80b6c27aa304a0eab0f36ff108b7b1bc046b0d3fdd8c28ca028d7995c8910a8216dccd4e756bb0eadf8efd1c9ff9c0cfbd8a157cab0
7
+ data.tar.gz: 47f9d992e4bac6d79bdf514edbf987f48ea367cfd85d9fe8e7d3bcd63396093b7cebb077aaf7d7332c8208926e14ff9b833520bf7b197ce496d2d57de8f80354
data/exe/aurora_fetch CHANGED
@@ -28,28 +28,10 @@ unless ARGV.length == 2
28
28
  exit 1
29
29
  end
30
30
 
31
- uri = URI.parse(ARGV[0])
32
-
33
- args = case uri.scheme
34
- when "tcp"
35
- require "socket"
36
- [TCPSocket.new(uri.host, uri.port)]
37
- when "telnet", "rfc2217"
38
- require "net/telnet/rfc2217"
39
- [Net::Telnet::RFC2217.new(uri.host,
40
- port: uri.port || 23,
41
- baud: 19_200,
42
- parity: :even)]
43
- else
44
- [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
45
- end
46
-
47
- client = ModBus::RTUClient.new(*args)
48
- client.logger = Logger.new($stdout)
49
- client.logger.level = debug_modbus ? :debug : :warn
50
-
51
- slave = client.with_slave(1)
52
- abc = Aurora::ABCClient.new(slave)
31
+ abc = Aurora::ABCClient.new(ARGV[0])
32
+ abc.modbus_slave.logger = Logger.new($stdout)
33
+ abc.modbus_slave.logger.level = debug_modbus ? :debug : :warn
34
+
53
35
  registers = abc.query_registers(ARGV[1])
54
36
 
55
37
  if yaml
data/exe/aurora_mock CHANGED
@@ -2,29 +2,29 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "aurora"
5
- require "ccutrer-serialport"
6
5
  require "uri"
7
6
  require "yaml"
8
7
 
9
8
  uri = URI.parse(ARGV[0])
10
9
 
11
- args = case uri.scheme
12
- when "tcp"
13
- require "socket"
14
- [TCPSocket.new(uri.host, uri.port)]
15
- when "telnet", "rfc2217"
16
- require "net/telnet/rfc2217"
17
- [Net::Telnet::RFC2217.new(uri.host,
18
- port: uri.port || 23,
19
- baud: 19_200,
20
- parity: :even)]
21
- else
22
- [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
23
- end
10
+ io = case uri.scheme
11
+ when "tcp"
12
+ require "socket"
13
+ TCPSocket.new(uri.host, uri.port)
14
+ when "telnet", "rfc2217"
15
+ require "net/telnet/rfc2217"
16
+ Net::Telnet::RFC2217.new(uri.host,
17
+ port: uri.port || 23,
18
+ baud: 19_200,
19
+ parity: :even)
20
+ else
21
+ require "ccutrer-serialport"
22
+ CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)
23
+ end
24
24
 
25
25
  port = ARGV[1]&.to_i || 502
26
26
 
27
- server1 = ModBus::RTUServer.new(*args)
27
+ server1 = ModBus::RTUServer.new(io)
28
28
  server1.logger = Logger.new($stdout, :debug)
29
29
  # AID Tool queries slave 1, AWL queries slave 2; just use both
30
30
  slave1 = server1.with_slave(1)
@@ -35,7 +35,7 @@ slave255 = server2.with_slave(255)
35
35
  r = slave1.holding_registers = slave2.holding_registers = slave255.holding_registers = Array.new(31_473, 0)
36
36
 
37
37
  # prepopulate some data
38
- registers = YAML.safe_load(File.read(File.expand_path("registers.yml", __dir__)))
38
+ registers = YAML.safe_load(File.read(ARGV[2]))
39
39
  registers.each { |(k, v)| r[k] = v }
40
40
 
41
41
  server1.request_callback = lambda { |uid, func, req|
data/exe/aurora_monitor CHANGED
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "aurora"
5
- require "ccutrer-serialport"
6
5
  require "logger"
7
6
  require "optparse"
8
7
  require "socket"
@@ -10,7 +9,7 @@ require "uri"
10
9
 
11
10
  diff_only = debug_modbus = ignore_awl_heartbeat = ignore_sensors = false
12
11
 
13
- OptionParser.new do |opts|
12
+ options = OptionParser.new do |opts|
14
13
  opts.banner = "Usage: aurora_monitor /path/to/serial/port [options]"
15
14
 
16
15
  opts.on("-q", "--quiet",
@@ -27,7 +26,14 @@ OptionParser.new do |opts|
27
26
  puts opts
28
27
  exit
29
28
  end
30
- end.parse!
29
+ end
30
+
31
+ options.parse!
32
+
33
+ unless ARGV.length == 2
34
+ puts options
35
+ exit 1
36
+ end
31
37
 
32
38
  uri = URI.parse(ARGV[0])
33
39
 
@@ -36,21 +42,22 @@ last_registers = {}
36
42
  SENSOR_REGISTERS = [16, 19, 20, 740, 900, 1109, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117, 1134, 1147, 1149, 1151,
37
43
  1153, 1165].freeze
38
44
 
39
- args = case uri.scheme
40
- when "tcp"
41
- require "socket"
42
- [TCPSocket.new(uri.host, uri.port)]
43
- when "telnet", "rfc2217"
44
- require "net/telnet/rfc2217"
45
- [Net::Telnet::RFC2217.new(uri.host,
46
- port: uri.port || 23,
47
- baud: 19_200,
48
- parity: :even)]
49
- else
50
- [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
51
- end
52
-
53
- server = ModBus::RTUServer.new(*args)
45
+ io = case uri.scheme
46
+ when "tcp"
47
+ require "socket"
48
+ TCPSocket.new(uri.host, uri.port)
49
+ when "telnet", "rfc2217"
50
+ require "net/telnet/rfc2217"
51
+ Net::Telnet::RFC2217.new(uri.host,
52
+ port: uri.port || 23,
53
+ baud: 19_200,
54
+ parity: :even)
55
+ else
56
+ require "ccutrer-serialport"
57
+ CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)
58
+ end
59
+
60
+ server = ModBus::RTUServer.new(io)
54
61
  server.promiscuous = true
55
62
  server.logger = Logger.new($stdout)
56
63
  server.logger.level = debug_modbus ? :debug : :warn
@@ -5,27 +5,34 @@ require "aurora"
5
5
  require "homie-mqtt"
6
6
  require "ccutrer-serialport"
7
7
  require "uri"
8
+ require "optparse"
9
+ require "yaml"
8
10
  require "aurora/core_ext/string"
9
11
 
10
- uri = URI.parse(ARGV[0])
12
+ debug_modbus = false
13
+
14
+ options = OptionParser.new do |opts|
15
+ opts.banner = "Usage: aurora_mqtt_bridge /path/to/serial/port [options]"
16
+
17
+ opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
18
+ opts.on("-h", "--help", "Prints this help") do
19
+ puts opts
20
+ exit
21
+ end
22
+ end
23
+
24
+ options.parse!
25
+
26
+ unless ARGV.length == 2
27
+ puts options
28
+ exit 1
29
+ end
30
+
11
31
  mqtt_uri = ARGV[1]
12
32
 
13
- args = case uri.scheme
14
- when "tcp"
15
- require "socket"
16
- [TCPSocket.new(uri.host, uri.port)]
17
- when "telnet", "rfc2217"
18
- require "net/telnet/rfc2217"
19
- [Net::Telnet::RFC2217.new(uri.host,
20
- port: uri.port || 23,
21
- baud: 19_200,
22
- parity: :even)]
23
- else
24
- [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
25
- end
26
-
27
- slave = ModBus::RTUClient.new(*args).with_slave(1)
28
- abc = Aurora::ABCClient.new(slave)
33
+ abc = Aurora::ABCClient.new(ARGV[0])
34
+ abc.modbus_slave.logger = Logger.new($stdout)
35
+ abc.modbus_slave.logger.level = debug_modbus ? :debug : :warn
29
36
 
30
37
  class MQTTBridge
31
38
  def initialize(abc, homie)
@@ -67,20 +74,30 @@ class MQTTBridge
67
74
  begin
68
75
  @mutex.synchronize do
69
76
  @abc.refresh
70
- @homie_abc.each do |property|
71
- property.value = @abc.public_send(property.id.tr("-", "_"))
72
- end
73
-
74
- @abc.faults.each_with_index do |fault_count, i|
75
- @faults["e#{i + 1}"].value = fault_count
76
- end
77
77
 
78
+ components = { @homie_abc => @abc,
79
+ @blower => @abc.blower,
80
+ @pump => @abc.pump }
78
81
  @abc.zones.each_with_index do |z, idx|
79
82
  homie_zone = @homie["zone#{idx + 1}"]
80
- homie_zone.each do |property|
81
- property.value = z.public_send(property.id.tr("-", "_"))
83
+ components[homie_zone] = z
84
+ end
85
+
86
+ components.each do |(node, object)|
87
+ node.each do |property|
88
+ property.value = object.public_send(property.id.tr("-", "_"))
82
89
  end
83
90
  end
91
+
92
+ if @abc.dhw?
93
+ @dhw["enabled"].value = @abc.dhw_enabled
94
+ @dhw["water-temperature"].value = @abc.dhw_water_temperature
95
+ @dhw["set-point"].value = @abc.dhw_setpoint
96
+ end
97
+
98
+ @abc.faults.each_with_index do |fault_count, i|
99
+ @faults["e#{i + 1}"].value = fault_count
100
+ end
84
101
  end
85
102
  rescue => e
86
103
  warn "got garbage: #{e}; #{e.backtrace}"
@@ -92,15 +109,14 @@ class MQTTBridge
92
109
 
93
110
  def publish_basic_attributes
94
111
  @homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
95
- node.property("compressor-speed", "Compressor Speed", :integer, @abc.compressor_speed, format: 0..1)
112
+ node.property("compressor-speed", "Compressor Speed", :integer, @abc.compressor_speed,
113
+ format: @abc.vs_drive? ? 0..12 : 0..2)
96
114
  node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
97
- format: %w[lockout standby blower h1 h2 c1 c2 eh1 eh2])
98
- node.property("dhw-water-temperature", "DHW Water Temperature", :float, @abc.dhw_water_temperature, unit: "ºF")
115
+ format: %w[lockout standby blower heating cooling eh1 eh2 emergency waiting dehumidify])
99
116
  node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
100
117
  unit: "ºF")
101
118
  node.property("entering-water-temperature", "Entering Water Temperature", :float,
102
119
  @abc.entering_water_temperature, unit: "ºF")
103
- node.property("fan-speed", "Fan Speed", :integer, @abc.fan_speed, format: 0..11)
104
120
  node.property("leaving-air-temperature", "Leaving Air Temperature", :float, @abc.leaving_air_temperature,
105
121
  unit: "ºF")
106
122
  node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
@@ -110,22 +126,74 @@ class MQTTBridge
110
126
  end
111
127
  node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
112
128
  format: 0..100)
113
- node.property("waterflow", "Waterflow", :float, unit: "gpm")
114
129
  node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
115
130
  node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
116
- %i[compressor blower aux_heat loop_pump total].each do |component|
131
+ %i[compressor aux_heat total].each do |component|
117
132
  component = "#{component}_watts"
118
133
  node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
119
134
  @abc.public_send(component), unit: "W")
120
135
  end
136
+ end
137
+
138
+ @blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
139
+ if @abc.blower.respond_to?(:running)
140
+ node.property("running", "Blower is running", :boolean, @abc.blower.running?)
141
+ else
142
+ node.property("speed", "Current blower speed", :integer, @abc.blower.speed, format: @abc.blower.speed_range)
143
+ end
144
+ node.property("watts", "Energy Usage", :integer, @abc.blower.watts, unit: "W") if @abc.energy_monitoring?
145
+
146
+ next unless @abc.blower.is_a?(Aurora::Blower::ECM)
121
147
 
122
- node.property("blower-only-ecm-speed", "Blower Only ECM Speed", :integer, @abc.blower_only_ecm_speed,
123
- format: 1..12) do |value, property|
124
- @mutex.synchronize { property.value = @abc.blower_only_ecm_speed = value }
148
+ presets = %w[blower-only aux-heat]
149
+ presets.concat %w[low-compressor high-compressor] unless @abc.iz2?
150
+ presets.each do |setting|
151
+ field = "#{setting.tr('-', '_')}_speed"
152
+ node.property("#{setting}-speed", "#{setting.tr('-', ' ').titleize} Preset Speed", :integer,
153
+ @abc.blower.public_send(field), format: 1..12) do |value, property|
154
+ @mutex.synchronize { property.value = @abc.blower.public_send("#{field}=", value) }
155
+ end
156
+ end
157
+ if @abc.iz2?
158
+ node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.blower.iz2_desired_speed,
159
+ format: 0..100, unit: "%")
125
160
  end
126
- node.property("aux-heat-ecm-speed", "Aux Heat ECM Speed", :integer, @abc.aux_heat_ecm_speed,
127
- format: 1..12) do |value, property|
128
- @mutex.synchronize { property.value = @abc.aux_heat_ecm_speed = value }
161
+ end
162
+
163
+ @pump = @homie.node("pump", "Loop Pump", @abc.pump.type) do |node|
164
+ node.property("waterflow", "Waterflow", :float, @abc.pump.waterflow, unit: "gpm")
165
+ node.property("watts", "Energy Usage", :integer, @abc.pump.watts, unit: "W") if @abc.energy_monitoring?
166
+
167
+ next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
168
+
169
+ node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
170
+ @mutex.synchronize { property.value = @abc.pump.speed = value }
171
+ end
172
+ node.property("manual-control", "If manual control is enabled", :boolean,
173
+ @abc.pump.manual_control?) do |value, property|
174
+ @mutex.synchronize { property.value = @abc.pump.manual_control = value }
175
+ end
176
+ node.property("minimum-speed", "Speed pump runs at compressor speed 0", :integer, @abc.pump.minimum_speed,
177
+ format: 0..100, unit: "%") do |value, property|
178
+ @mutex.synchronize { property.value = @abc.pump.minimum_speed = value }
179
+ end
180
+ node.property("maximum-speed", "Speed pump runs at compressor speed 12", :integer, @abc.pump.minimum_speed,
181
+ format: 0..100, unit: "%") do |value, property|
182
+ @mutex.synchronize { property.value = @abc.pump.maximum_speed = value }
183
+ end
184
+ end
185
+
186
+ if @abc.dhw?
187
+ @dhw = @homie.node("dhw", "Domestic Hot Water Generator", "DHW") do |node|
188
+ node.property("enabled", "Enabled", :boolean, @abc.dhw_enabled) do |value, property|
189
+ @mutex.synchronize { property.value = @abc.dhw_enabled = value }
190
+ end
191
+ node.property("water-temperature", "DHW Water Temperature", :float,
192
+ @abc.dhw_water_temperature, unit: "ºF")
193
+ node.property("set-point", "DHW Set Point", :float, @abc.dhw_setpoint, format: 100..140,
194
+ unit: "ºF") do |value, property|
195
+ @mutex.synchronize { property.value = @abc.dhw_setpoint = value }
196
+ end
129
197
  end
130
198
  end
131
199
 
@@ -191,7 +259,7 @@ end
191
259
  log_level = ARGV.include?("--debug") ? :debug : :warn
192
260
  logger = Logger.new($stdout)
193
261
  logger.level = log_level
194
- slave.logger = logger
262
+ abc.modbus_slave.logger = logger
195
263
 
196
264
  device = "aurora-#{abc.serial_number}"
197
265
  homie = MQTT::Homie::Device.new(device, "Aurora MQTT Bridge", mqtt: mqtt_uri)
data/exe/web_aid_tool CHANGED
@@ -7,17 +7,13 @@ require "logger"
7
7
  require "optparse"
8
8
  require "yaml"
9
9
 
10
- debug_modbus = monitor = mock = false
10
+ debug_modbus = monitor = false
11
11
 
12
12
  options = OptionParser.new do |opts|
13
13
  opts.banner = "Usage: web_aid_tool /path/to/serial/port [options]"
14
14
 
15
15
  opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
16
- opts.on("--mock",
17
- "Instead of talking to an actual heat pump, mock it with registers from the given YAML file (instead of a serial port)") do # rubocop:disable Layout/LineLength
18
- mock = true
19
- end
20
- opts.on("--monitor", "Print interperted registers as they are requested, like aurora_monitor") { monitor = true }
16
+ opts.on("--monitor", "Print interpreted registers as they are requested, like aurora_monitor") { monitor = true }
21
17
  opts.on("-h", "--help", "Prints this help") do
22
18
  puts opts
23
19
  exit
@@ -31,51 +27,9 @@ unless ARGV.length == 1
31
27
  exit 1
32
28
  end
33
29
 
34
- class MockSlave
35
- def initialize(registers)
36
- @registers = registers
37
- end
38
-
39
- def read_multiple_holding_registers(*queries)
40
- result = {}
41
- queries.each do |query|
42
- Array(query).each do |i|
43
- result[i] = @registers[i]
44
- end
45
- end
46
- result
47
- end
48
-
49
- def write_holding_register(addr, value)
50
- @registers[addr] = value
51
- end
52
- end
53
-
54
- if mock
55
- slave = MockSlave.new(YAML.load_file(ARGV[0]))
56
- else
57
- uri = URI.parse(ARGV[0])
58
-
59
- args = case uri.scheme
60
- when "tcp"
61
- require "socket"
62
- [TCPSocket.new(uri.host, uri.port)]
63
- when "telnet", "rfc2217"
64
- require "net/telnet/rfc2217"
65
- [Net::Telnet::RFC2217.new(uri.host,
66
- port: uri.port || 23,
67
- baud: 19_200,
68
- parity: :even)]
69
- else
70
- [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
71
- end
72
-
73
- client = ModBus::RTUClient.new(*args)
74
- client.logger = Logger.new($stdout)
75
- client.logger.level = debug_modbus ? :debug : :warn
76
-
77
- slave = client.with_slave(1)
78
- end
30
+ slave = Aurora::ABCClient.open_modbus_slave(ARGV[0])
31
+ slave.logger = Logger.new($stdout)
32
+ slave.logger.level = debug_modbus ? :debug : :warn
79
33
 
80
34
  def parse_query_string(query_string)
81
35
  query_string.split("&").map { |p| p.split("=") }.to_h
@@ -89,6 +43,7 @@ end
89
43
  require "sinatra"
90
44
 
91
45
  set :public_folder, "html"
46
+ set :logging, false
92
47
 
93
48
  get "/" do
94
49
  send_file "html/index.htm"
@@ -138,7 +93,10 @@ get "/request.cgi" do
138
93
  start...(start + length)
139
94
  end
140
95
  registers = slave.read_multiple_holding_registers(*queries)
141
- puts Aurora.print_registers(registers) if monitor
96
+ if monitor
97
+ puts "READING"
98
+ puts Aurora.print_registers(registers)
99
+ end
142
100
  result["values"] = registers.values.join(",")
143
101
  when "putregs"
144
102
  writes = params["regs"].split(";").map do |write|
@@ -147,7 +105,6 @@ get "/request.cgi" do
147
105
  if monitor
148
106
  puts "WRITING"
149
107
  puts Aurora.print_registers(writes)
150
- puts "==="
151
108
  end
152
109
 
153
110
  writes.each do |(addr, value)|