waterfurnace_aurora 0.3.7 → 0.3.11

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: beb1fa2f6415ac6723e0725460e8fbc6f5c8f04c76848034821176ce834f2cf3
4
- data.tar.gz: 7a697e8d8bcf8b2abf83bf13c7294498947653f4b4237ede075d1bf01b338bc1
3
+ metadata.gz: fc29704fadc06f5e325457150e088018586a4f824fc776f0c8736d45f012e30d
4
+ data.tar.gz: 38820a0d7713c7957d186bdbc6d3ab52cf3064fa94e15370a118058fe777d636
5
5
  SHA512:
6
- metadata.gz: 4a15073444778a08e9e46c8bedfaf957c7e055d11202e767d592439dfc8ae71f436d89550649a1e6040264e4a81c7189464fa6f9b3e2dc50fe4581a6368d950d
7
- data.tar.gz: 722b3a899a1626458dc31c9b0345e85ea64d9e80cd8b40fd5cb6f64241f74752938123eee8b841259496803e6b12643eb014e25b737798aa2e198867e0b37d88
6
+ metadata.gz: f53b075711ce3df9fdd69b6daa8a1520d6830ae9c8717ede4a8de7c0379420a64e835abefeb56ec481a586f5d328c6f967ad1fca48b08933f6145d927877c8b4
7
+ data.tar.gz: 5b858edd848f538c59f89a83d8372f6e3682066fac5586d7f3c350dc53a79e0bc23741fd472f3c43456467b8c51fcc6066ba092f1ba3c4a157c453f6937a1c41
data/exe/aurora_fetch CHANGED
@@ -3,7 +3,30 @@
3
3
 
4
4
  require "aurora"
5
5
  require "ccutrer-serialport"
6
+ require "logger"
7
+ require "optparse"
6
8
  require "uri"
9
+ require "yaml"
10
+
11
+ debug_modbus = yaml = false
12
+
13
+ options = OptionParser.new do |opts|
14
+ opts.banner = "Usage: aurora_fetch /path/to/serial/port REGISTERS [options]"
15
+
16
+ opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
17
+ opts.on("-y", "--yaml", "Output raw values as YAML") { yaml = 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
7
30
 
8
31
  uri = URI.parse(ARGV[0])
9
32
 
@@ -22,8 +45,15 @@ args = case uri.scheme
22
45
  end
23
46
 
24
47
  client = ModBus::RTUClient.new(*args)
48
+ client.logger = Logger.new($stdout)
49
+ client.logger.level = debug_modbus ? :debug : :warn
50
+
25
51
  slave = client.with_slave(1)
26
52
  abc = Aurora::ABCClient.new(slave)
27
53
  registers = abc.query_registers(ARGV[1])
28
54
 
29
- puts Aurora.print_registers(registers)
55
+ if yaml
56
+ puts YAML.dump(registers)
57
+ else
58
+ puts Aurora.print_registers(registers)
59
+ end
@@ -71,6 +71,10 @@ class MQTTBridge
71
71
  property.value = @abc.public_send(property.id.tr("-", "_"))
72
72
  end
73
73
 
74
+ @abc.faults.each_with_index do |fault_count, i|
75
+ @faults["e#{i + 1}"].value = fault_count
76
+ end
77
+
74
78
  @abc.zones.each_with_index do |z, idx|
75
79
  homie_zone = @homie["zone#{idx + 1}"]
76
80
  homie_zone.each do |property|
@@ -125,6 +129,13 @@ class MQTTBridge
125
129
  end
126
130
  end
127
131
 
132
+ @faults = @homie.node("faults", "Fault History", "ABC") do |node|
133
+ @abc.faults.each_with_index do |count, i|
134
+ name = Aurora::FAULTS[i + 1]
135
+ node.property("e#{i + 1}", name || "E#{i + 1}", :integer, count)
136
+ end
137
+ end
138
+
128
139
  @abc.zones.each_with_index do |zone, i|
129
140
  type = zone.is_a?(Aurora::IZ2Zone) ? "IntelliZone 2 Zone" : "Thermostat"
130
141
  @homie.node("zone#{i + 1}", "Zone #{i + 1}", type) do |node|
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+
3
+ mkdir -p html
4
+ mkdir -p html/css
5
+ mkdir -p html/js
6
+ mkdir -p html/images
7
+
8
+ IP=${1:-172.20.10.1}
9
+
10
+ curl http://$IP/ > html/index.htm
11
+ curl http://$IP/config.htm > html/config.htm
12
+ curl http://$IP/favicon.ico > html/favicon.ico
13
+ curl http://$IP/css/index.css > html/css/index.css
14
+ curl http://$IP/css/phone.css > html/css/phone.css
15
+ curl http://$IP/js/indexc.js > html/js/indexc.js
16
+ curl http://$IP/js/configc.js > html/js/configc.js
17
+ curl http://$IP/images/aurora.png > html/images/aurora.png
18
+ curl http://$IP/images/back.png > html/images/back.png
19
+ curl http://$IP/images/cfailed.png > html/images/cfailed.png
20
+ curl http://$IP/images/cgood.png > html/images/cgood.png
21
+ curl http://$IP/images/cidle.png > html/images/cidle.png
data/exe/web_aid_tool ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "aurora"
5
+ require "ccutrer-serialport"
6
+ require "logger"
7
+ require "optparse"
8
+ require "yaml"
9
+
10
+ debug_modbus = monitor = mock = false
11
+
12
+ options = OptionParser.new do |opts|
13
+ opts.banner = "Usage: web_aid_tool /path/to/serial/port [options]"
14
+
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 }
21
+ opts.on("-h", "--help", "Prints this help") do
22
+ puts opts
23
+ exit
24
+ end
25
+ end
26
+
27
+ options.parse!
28
+
29
+ unless ARGV.length == 1
30
+ puts options
31
+ exit 1
32
+ end
33
+
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
79
+
80
+ def parse_query_string(query_string)
81
+ query_string.split("&").map { |p| p.split("=") }.to_h
82
+ end
83
+
84
+ # _don't_ do URI escaping
85
+ def encode_result(params)
86
+ params.map { |p| p.join("=") }.join("&")
87
+ end
88
+
89
+ require "sinatra"
90
+
91
+ set :public_folder, "html"
92
+
93
+ get "/" do
94
+ send_file "html/index.htm"
95
+ end
96
+
97
+ units = 0
98
+
99
+ get "/getunits.cgi" do
100
+ encode_result(units: units)
101
+ end
102
+
103
+ get "/setunits.cgi" do
104
+ units = params["units"].to_i
105
+ encode_result(error: 0)
106
+ end
107
+
108
+ get "/config.cgi" do
109
+ encode_result(
110
+ "AWL Version" => Aurora::VERSION,
111
+ "Local Web Version" => 1.08,
112
+ "SSID" => nil,
113
+ "Units" => units,
114
+ "AWL ID" => ARGV[0],
115
+ "AWL ID CRC" => nil
116
+ )
117
+ end
118
+
119
+ get "/request.cgi" do
120
+ params = parse_query_string(request.query_string)
121
+ result = params.slice("cmd", "id", "set", "addr")
122
+ result["err"] = nil
123
+
124
+ # these are just aliases to get a certain set of registers
125
+ case params["cmd"]
126
+ when "abcinfo"
127
+ params["regs"] = "2;8;88,4"
128
+ when "devices"
129
+ params["regs"] = "800;803;806,3;812;815;818;824"
130
+ end
131
+
132
+ case params["cmd"]
133
+ when "getregs", "abcinfo", "devices"
134
+ queries = params["regs"].split(";").map do |range|
135
+ start, length = range.split(",").map(&:to_i)
136
+ next start if length.nil?
137
+
138
+ start...(start + length)
139
+ end
140
+ registers = slave.read_multiple_holding_registers(*queries)
141
+ puts Aurora.print_registers(registers) if monitor
142
+ result["values"] = registers.values.join(",")
143
+ when "putregs"
144
+ writes = params["regs"].split(";").map do |write|
145
+ write.split(",").map(&:to_i)
146
+ end.compact.to_h
147
+ if monitor
148
+ puts "WRITING"
149
+ puts Aurora.print_registers(writes)
150
+ puts "==="
151
+ end
152
+
153
+ writes.each do |(addr, value)|
154
+ slave.write_holding_register(addr, value)
155
+ end
156
+ else
157
+ return ""
158
+ end
159
+
160
+ encode_result(result)
161
+ end
@@ -5,6 +5,7 @@ module Aurora
5
5
  attr_reader :modbus_slave,
6
6
  :serial_number,
7
7
  :zones,
8
+ :faults,
8
9
  :current_mode,
9
10
  :fan_speed,
10
11
  :entering_air_temperature,
@@ -40,6 +41,7 @@ module Aurora
40
41
  iz2_zone_count = @modbus_slave.holding_registers[483]
41
42
  (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
42
43
  end
44
+ @faults = []
43
45
  end
44
46
 
45
47
  def query_registers(query)
@@ -47,6 +49,8 @@ module Aurora
47
49
  case addr
48
50
  when "known"
49
51
  Aurora::REGISTER_NAMES.keys
52
+ when "valid"
53
+ break Aurora::REGISTER_RANGES
50
54
  when /^(\d+)(?:\.\.|-)(\d+)$/
51
55
  $1.to_i..$2.to_i
52
56
  else
@@ -62,8 +66,8 @@ module Aurora
62
66
  end
63
67
 
64
68
  def refresh
65
- registers_to_read = [19..20, 30, 340, 344, 347, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027,
66
- 31_003]
69
+ registers_to_read = [19..20, 30, 340, 344, 347, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165,
70
+ 3027, 31_003]
67
71
  if zones.first.is_a?(IZ2Zone)
68
72
  zones.each_with_index do |_z, i|
69
73
  base1 = 21_203 + i * 9
@@ -77,6 +81,8 @@ module Aurora
77
81
  registers_to_read << (745..747)
78
82
  end
79
83
 
84
+ @faults = @modbus_slave.holding_registers[601..699]
85
+
80
86
  registers = @modbus_slave.holding_registers[*registers_to_read]
81
87
  Aurora.transform_registers(registers)
82
88
 
@@ -49,7 +49,8 @@ module Aurora
49
49
  when 0x80..0xff
50
50
  msg += read(io, 3)
51
51
  else
52
- raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
52
+ log "Rx (#{msg.size} bytes): " + logging_bytes(msg)
53
+ raise ::ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
53
54
  end
54
55
  msg
55
56
  end
@@ -3,6 +3,11 @@
3
3
  module Aurora
4
4
  module_function
5
5
 
6
+ # take an array of ranges, and breaks it up into queryable chunks
7
+ # the ABC limits to 100 registers per read operation
8
+ # there also seem to be issues that some ranges can't be read at
9
+ # the same time as other ranges. possibly correspond to different
10
+ # components?
6
11
  def normalize_ranges(ranges)
7
12
  registers = ranges.map { |r| Array(r) }.flatten.sort.uniq
8
13
  result = []
@@ -11,7 +16,10 @@ module Aurora
11
16
  count = 0
12
17
  registers.each_with_index do |r, i|
13
18
  run_start ||= r
14
- next unless i + 1 == registers.length || r + 1 != registers[i + 1]
19
+ next unless i + 1 == registers.length ||
20
+ r + 1 != registers[i + 1] ||
21
+ (r - run_start) == 100 ||
22
+ REGISTER_BREAKPOINTS.include?(r + 1)
15
23
 
16
24
  if r == run_start
17
25
  result << r
@@ -23,7 +31,7 @@ module Aurora
23
31
  else
24
32
  range = run_start..r
25
33
  if count + range.count > 100
26
- totals << result
34
+ totals << result unless result.empty?
27
35
  result = []
28
36
  count = 0
29
37
  end
@@ -390,7 +398,11 @@ module Aurora
390
398
  end
391
399
 
392
400
  def faults(range)
393
- range.map { |i| [i, "E#{i % 100}"] }.to_h
401
+ range.map do |i|
402
+ name = FAULTS[i % 100]
403
+ name = " (#{name})" if name
404
+ [i, "E#{i % 100}#{name}"]
405
+ end.to_h
394
406
  end
395
407
 
396
408
  def zone_registers
@@ -494,6 +506,12 @@ module Aurora
494
506
  61_000..61_009
495
507
  ].freeze
496
508
 
509
+ # see normalize_ranges
510
+ REGISTER_BREAKPOINTS = [
511
+ 12_100,
512
+ 12_500
513
+ ].freeze
514
+
497
515
  REGISTER_NAMES = {
498
516
  1 => "Random Start Delay",
499
517
  2 => "ABC Program Version",
@@ -594,7 +612,10 @@ module Aurora
594
612
  12_619 => "Heating Setpoint (write)",
595
613
  12_620 => "Cooling Setpoint (write)",
596
614
  12_621 => "Fan Mode (write)",
615
+ 3000 => "Compressor Speed?",
616
+ 3001 => "Compressor Speed?",
597
617
  3027 => "Compressor Speed",
618
+ 3904 => "Leaving Air Temperature?",
598
619
  31_003 => "Outdoor Temp",
599
620
  31_005 => "IZ2 Demand",
600
621
  31_109 => "Humidifier Mode", # write to 21114
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.3.7"
4
+ VERSION = "0.3.11"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterfurnace_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-29 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ccutrer-serialport
@@ -73,33 +73,33 @@ dependencies:
73
73
  - !ruby/object:Gem::Version
74
74
  version: '2.1'
75
75
  - !ruby/object:Gem::Dependency
76
- name: byebug
76
+ name: sinatra
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '9.0'
82
- type: :development
81
+ version: '2.1'
82
+ type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '9.0'
88
+ version: '2.1'
89
89
  - !ruby/object:Gem::Dependency
90
- name: gserver
90
+ name: byebug
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 0.0.1
95
+ version: '9.0'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 0.0.1
102
+ version: '9.0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rubocop
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -117,8 +117,10 @@ dependencies:
117
117
  description:
118
118
  email: cody@cutrer.com'
119
119
  executables:
120
+ - grab_awl_assets.sh
120
121
  - aurora_monitor
121
122
  - aurora_mqtt_bridge
123
+ - web_aid_tool
122
124
  - aurora_mock
123
125
  - aurora_fetch
124
126
  extensions: []
@@ -128,7 +130,8 @@ files:
128
130
  - exe/aurora_mock
129
131
  - exe/aurora_monitor
130
132
  - exe/aurora_mqtt_bridge
131
- - exe/registers.yml
133
+ - exe/grab_awl_assets.sh
134
+ - exe/web_aid_tool
132
135
  - lib/aurora.rb
133
136
  - lib/aurora/abc_client.rb
134
137
  - lib/aurora/core_ext/string.rb