waterfurnace_aurora 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/aurora_monitor +54 -12
- data/exe/aurora_mqtt_bridge +5 -5
- data/lib/aurora/registers.rb +22 -21
- data/lib/aurora/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fde3dc688654c589d5638b794484035f3ab7ca8c102fe1ef27bb6365ddd51d22
|
4
|
+
data.tar.gz: 6d679712a9375c94f8a1f7b2fe3fa6102c606a433c0449049ae289773cdaf735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd90afd3a8f15ddec22ec29f23679d4def25b768b47eaf7adc37c37ab0a5b98bfb98a11811133d67dbbb1afd23b03ea5689fe4be55c2966eb19b68b9b8827667
|
7
|
+
data.tar.gz: 9c855a9730f2a86678876f3866ea7a6583925781e2397e13738b9f413e4b318a89c7860706e22e88c94d090f37afccd775b2b54242b9555530993e7021b995c6
|
data/exe/aurora_monitor
CHANGED
@@ -3,11 +3,38 @@
|
|
3
3
|
|
4
4
|
require "aurora"
|
5
5
|
require "ccutrer-serialport"
|
6
|
+
require "optparse"
|
6
7
|
require "socket"
|
7
8
|
require "uri"
|
8
9
|
|
10
|
+
diff_only = debug_modbus = ignore_awl_heartbeat = ignore_sensors = false
|
11
|
+
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: aurora_monitor /path/to/serial/port [options]"
|
14
|
+
|
15
|
+
opts.on("-q", "--quiet",
|
16
|
+
"Enables quiet mode (--diff-only, --ignore-awl-heartbeat, --ignore-sensors) to ease in deciphering new registers") do # rubocop:disable Layout/LineLength
|
17
|
+
diff_only = true
|
18
|
+
ignore_awl_heartbeat = true
|
19
|
+
ignore_sensors = true
|
20
|
+
end
|
21
|
+
opts.on("--diff-only", "Only show registers if they've changed from their previous value") { diff_only = true }
|
22
|
+
opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
|
23
|
+
opts.on("--ignore-awl-heartbeat", "Don't print AWL heartbeat requests") { ignore_awl_heartbeat = true }
|
24
|
+
opts.on("--ignore-sensors", "Don't print sensor registers (i.e. because they change a lot)") { ignore_sensors = true }
|
25
|
+
opts.on("-h", "--help", "Prints this help") do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end.parse!
|
30
|
+
|
9
31
|
uri = URI.parse(ARGV[0])
|
10
32
|
|
33
|
+
last_registers = {}
|
34
|
+
|
35
|
+
SENSOR_REGISTERS = [16, 19, 20, 740, 900, 1109, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117, 1134, 1147, 1149, 1151,
|
36
|
+
1153, 1165].freeze
|
37
|
+
|
11
38
|
args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
12
39
|
require "net/telnet/rfc2217"
|
13
40
|
[Net::Telnet::RFC2217.new("Host" => uri.host,
|
@@ -20,23 +47,38 @@ args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
|
20
47
|
|
21
48
|
server = ModBus::RTUServer.new(*args)
|
22
49
|
server.promiscuous = true
|
23
|
-
server.debug =
|
50
|
+
server.debug = debug_modbus
|
51
|
+
|
52
|
+
diff_and_print = lambda do |registers|
|
53
|
+
registers = registers.slice(*(registers.keys - SENSOR_REGISTERS)) if ignore_sensors
|
54
|
+
next puts Aurora.print_registers(registers) unless diff_only
|
55
|
+
|
56
|
+
new_registers = last_registers.merge(registers)
|
57
|
+
diff = Aurora.diff_registers(last_registers, new_registers)
|
58
|
+
unless diff.empty?
|
59
|
+
puts "#{Time.now} ===== read"
|
60
|
+
puts Aurora.print_registers(diff)
|
61
|
+
end
|
62
|
+
last_registers = new_registers
|
63
|
+
end
|
24
64
|
|
25
65
|
server.request_callback = lambda { |uid, func, req|
|
26
66
|
if func == 68
|
27
|
-
puts "===== no idea to #{uid}: #{req.inspect}"
|
67
|
+
puts "#{Time.now} ===== no idea to #{uid}: #{req.inspect}" unless diff_only
|
28
68
|
elsif func == 67
|
29
|
-
puts "===== write discontiguous registers to #{uid}:"
|
69
|
+
puts "#{Time.now} ===== write discontiguous registers to #{uid}:"
|
30
70
|
registers = req.map { |p| [p[:addr], p[:val]] }.to_h
|
31
71
|
puts Aurora.print_registers(registers)
|
32
72
|
elsif func == 16
|
33
|
-
puts "===== write multiple registers to #{uid}:"
|
34
73
|
registers = Range.new(req[:addr], req[:addr] + req[:quant] - 1).zip(req[:val]).to_h
|
74
|
+
next if ignore_awl_heartbeat && registers == { 460 => 102, 461 => 0, 462 => 5 }
|
75
|
+
|
76
|
+
puts "#{Time.now} ===== write multiple registers to #{uid}:"
|
35
77
|
puts Aurora.print_registers(registers)
|
36
78
|
elsif [3, 65, 66].include?(func)
|
37
79
|
# no output
|
38
80
|
else
|
39
|
-
puts "**** new func #{func}"
|
81
|
+
puts "#{Time.now} **** new func #{func}"
|
40
82
|
end
|
41
83
|
}
|
42
84
|
|
@@ -46,9 +88,9 @@ server.response_callback = lambda { |uid, func, res, req|
|
|
46
88
|
puts "wrong number of results"
|
47
89
|
next
|
48
90
|
end
|
49
|
-
puts "===== read registers from #{uid}"
|
91
|
+
puts "#{Time.now} ===== read registers from #{uid}" unless diff_only
|
50
92
|
registers = Range.new(req[:addr], req[:addr] + req[:quant], true).to_a.zip(res).to_h
|
51
|
-
|
93
|
+
diff_and_print.call(registers)
|
52
94
|
elsif func == 65 && res.is_a?(Array) && req
|
53
95
|
register_list = []
|
54
96
|
req.each { |params| register_list.concat(Range.new(params[:addr], params[:addr] + params[:quant], true).to_a) }
|
@@ -56,21 +98,21 @@ server.response_callback = lambda { |uid, func, res, req|
|
|
56
98
|
puts "wrong number of results"
|
57
99
|
next
|
58
100
|
end
|
59
|
-
puts "===== read multiple register ranges from #{uid}"
|
101
|
+
puts "#{Time.now} ===== read multiple register ranges from #{uid}" unless diff_only
|
60
102
|
result = register_list.zip(res).to_h
|
61
|
-
|
103
|
+
diff_and_print.call(result)
|
62
104
|
elsif func == 66 && res.is_a?(Array) && req
|
63
105
|
unless req.length == res.length
|
64
106
|
puts "wrong number of results"
|
65
107
|
next
|
66
108
|
end
|
67
|
-
puts "===== read discontiguous registers from #{uid}"
|
109
|
+
puts "#{Time.now} ===== read discontiguous registers from #{uid}" unless diff_only
|
68
110
|
registers = req.zip(res).to_h
|
69
|
-
|
111
|
+
diff_and_print.call(registers)
|
70
112
|
elsif [16, 67, 68].include?(func)
|
71
113
|
# no output
|
72
114
|
else
|
73
|
-
puts "**** new func #{func}"
|
115
|
+
puts "#{Time.now} **** new func #{func}"
|
74
116
|
end
|
75
117
|
}
|
76
118
|
|
data/exe/aurora_mqtt_bridge
CHANGED
@@ -91,8 +91,8 @@ class MQTTBridge
|
|
91
91
|
@homie_abc[property.to_s.tr("_", "-")].value = @abc.public_send(property)
|
92
92
|
end
|
93
93
|
|
94
|
-
@abc.zones.
|
95
|
-
homie_zone = @homie["zone#{
|
94
|
+
@abc.zones.each_with_index do |z, idx|
|
95
|
+
homie_zone = @homie["zone#{idx + 1}"]
|
96
96
|
homie_zone.each do |property|
|
97
97
|
property.value = z.public_send(property.id.tr("-", "_"))
|
98
98
|
end
|
@@ -134,11 +134,11 @@ class MQTTBridge
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
@abc.zones.
|
137
|
+
@abc.zones.each_with_index do |zone, i|
|
138
138
|
type = zone.is_a?(Aurora::IZ2Zone) ? "IntelliZone 2 Zone" : "Thermostat"
|
139
|
-
@homie.node("zone#{
|
139
|
+
@homie.node("zone#{i + 1}", "Zone #{i + 1}", type) do |node|
|
140
140
|
allowed_modes = %w[off auto cool heat]
|
141
|
-
allowed_modes << "eheat" if
|
141
|
+
allowed_modes << "eheat" if i.zero?
|
142
142
|
node.property("target-mode", "Target Heating/Cooling Mode", :enum, zone.target_mode,
|
143
143
|
format: allowed_modes) do |value, property|
|
144
144
|
@mutex.synchronize { property.value = zone.target_mode = value.to_sym }
|
data/lib/aurora/registers.rb
CHANGED
@@ -52,7 +52,6 @@ module Aurora
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def to_string(registers, idx, length)
|
55
|
-
puts "converting #{idx} of length #{length}"
|
56
55
|
(idx...(idx + length)).map do |i|
|
57
56
|
(registers[i] >> 8).chr + (registers[i] & 0xff).chr
|
58
57
|
end.join.sub(/[ \0]+$/, "")
|
@@ -495,25 +494,6 @@ module Aurora
|
|
495
494
|
61_000..61_009
|
496
495
|
].freeze
|
497
496
|
|
498
|
-
def read_all_registers(modbus_slave)
|
499
|
-
result = []
|
500
|
-
REGISTER_RANGES.each do |range|
|
501
|
-
# read at most 100 at a time
|
502
|
-
range.each_slice(100) do |keys|
|
503
|
-
result.concat(modbus_slave.holding_registers[keys.first..keys.last])
|
504
|
-
end
|
505
|
-
end
|
506
|
-
REGISTER_RANGES.map(&:to_a).flatten.zip(result).to_h
|
507
|
-
end
|
508
|
-
|
509
|
-
def diff_registers(lhs, rhs)
|
510
|
-
diff = {}
|
511
|
-
lhs.each_key do |k|
|
512
|
-
diff[k] = [lhs[k], rhs[k]] if lhs[k] != rhs[k]
|
513
|
-
end
|
514
|
-
diff
|
515
|
-
end
|
516
|
-
|
517
497
|
REGISTER_NAMES = {
|
518
498
|
1 => "Random Start Delay",
|
519
499
|
2 => "ABC Program Version",
|
@@ -648,6 +628,25 @@ module Aurora
|
|
648
628
|
registers
|
649
629
|
end
|
650
630
|
|
631
|
+
def read_all_registers(modbus_slave)
|
632
|
+
result = []
|
633
|
+
REGISTER_RANGES.each do |range|
|
634
|
+
# read at most 100 at a time
|
635
|
+
range.each_slice(100) do |keys|
|
636
|
+
result.concat(modbus_slave.holding_registers[keys.first..keys.last])
|
637
|
+
end
|
638
|
+
end
|
639
|
+
REGISTER_RANGES.map(&:to_a).flatten.zip(result).to_h
|
640
|
+
end
|
641
|
+
|
642
|
+
def diff_registers(lhs, rhs)
|
643
|
+
diff = {}
|
644
|
+
(lhs.keys | rhs.keys).each do |k|
|
645
|
+
diff[k] = rhs[k] if lhs[k] != rhs[k]
|
646
|
+
end
|
647
|
+
diff
|
648
|
+
end
|
649
|
+
|
651
650
|
def print_registers(registers)
|
652
651
|
result = []
|
653
652
|
registers.each do |(k, value)|
|
@@ -655,15 +654,17 @@ module Aurora
|
|
655
654
|
next if REGISTER_NAMES.key?(k) && REGISTER_NAMES[k].nil?
|
656
655
|
|
657
656
|
name = REGISTER_NAMES[k]
|
657
|
+
|
658
658
|
value_proc = REGISTER_CONVERTERS.find { |(_, z)| z.include?(k) }&.first || ->(v) { v }
|
659
659
|
format = REGISTER_FORMATS.find { |(_, z)| z.include?(k) }&.first || "%s"
|
660
660
|
format = "%1$d (0x%1$04x)" unless name
|
661
|
-
name ||= "???"
|
662
661
|
|
663
662
|
value = value_proc.arity == 2 ? value_proc.call(registers, k) : value_proc.call(value)
|
664
663
|
value = value.join(", ") if value.is_a?(Array)
|
665
664
|
value = format(format, value) if value
|
666
665
|
|
666
|
+
name ||= "???"
|
667
|
+
|
667
668
|
result << "#{name} (#{k}): #{value}"
|
668
669
|
end
|
669
670
|
result.join("\n")
|
data/lib/aurora/version.rb
CHANGED