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.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aurora
4
+ class Thermostat
5
+ attr_reader :target_mode,
6
+ :target_fan_mode,
7
+ :ambient_temperature,
8
+ :cooling_target_temperature,
9
+ :heating_target_temperature
10
+
11
+ def initialize(abc)
12
+ @abc = abc
13
+ end
14
+
15
+ def refresh(registers)
16
+ @ambient_temperature = registers[747]
17
+ @heating_target_temperature = registers[746]
18
+ @cooling_target_temperature = registers[745]
19
+ end
20
+
21
+ def target_mode=(value)
22
+ return unless (raw_value = HEATING_MODE.invert[value])
23
+
24
+ @abc.modbus_slave.holding_registers[12_602] = raw_value
25
+ @target_mode = value
26
+ end
27
+
28
+ def target_fan_mode=(value)
29
+ return unless (raw_value = FAN_MODE.invert[value])
30
+
31
+ @abc.modbus_slave.holding_registers[12_621] = raw_value
32
+ @target_fan_mode = value
33
+ end
34
+
35
+ def heating_target_temperature=(value)
36
+ return unless value >= 40 && value <= 90
37
+
38
+ raw_value = (value * 10).to_i
39
+ @abc.modbus_slave.holding_registers[12_619] = raw_value
40
+ @heating_target_temperature = value
41
+ end
42
+
43
+ def cooling_target_temperature=(value)
44
+ return unless value >= 54 && value <= 99
45
+
46
+ raw_value = (value * 10).to_i
47
+ @abc.modbus_slave.holding_registers[12_620] = raw_value
48
+ @cooling_target_temperature = value
49
+ end
50
+
51
+ def inspect
52
+ "#<Aurora::#{self.class.name} #{(instance_variables - [:@abc]).map do |iv|
53
+ "#{iv}=#{instance_variable_get(iv).inspect}"
54
+ end.join(', ')}>"
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aurora
2
- VERSION = '0.1.1'
4
+ VERSION = "0.3.0"
3
5
  end
data/lib/aurora.rb CHANGED
@@ -1,10 +1,13 @@
1
- require 'rmodbus'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'aurora/abc_client'
4
- require 'aurora/iz2_zone'
5
- require 'aurora/modbus/server'
6
- require 'aurora/modbus/slave'
7
- require 'aurora/registers'
3
+ require "rmodbus"
4
+
5
+ require "aurora/abc_client"
6
+ require "aurora/iz2_zone"
7
+ require "aurora/thermostat"
8
+ require "aurora/modbus/server"
9
+ require "aurora/modbus/slave"
10
+ require "aurora/registers"
8
11
 
9
12
  # extend ModBus for WaterFurnace's custom functions
10
13
  ModBus::RTUServer.include(Aurora::ModBus::Server)
@@ -1 +1,3 @@
1
- require 'aurora'
1
+ # frozen_string_literal: true
2
+
3
+ require "aurora"
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterfurnace_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-23 00:00:00.000000000 Z
11
+ date: 2021-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: mqtt
14
+ name: ccutrer-serialport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.0
19
+ version: 1.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.0
26
+ version: 1.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: net-telnet-rfc2217
28
+ name: homie-mqtt
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.4
33
+ version: 1.4.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.4
40
+ version: 1.4.2
41
41
  - !ruby/object:Gem::Dependency
42
- name: ccutrer-serialport
42
+ name: net-telnet-rfc2217
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
47
+ version: 0.0.4
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.0
54
+ version: 0.0.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rmodbus-ccutrer
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -81,51 +81,56 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '9.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: gserver
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '13.0'
89
+ version: 0.0.1
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '13.0'
96
+ version: 0.0.1
97
97
  - !ruby/object:Gem::Dependency
98
- name: gserver
98
+ name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.0.1
103
+ version: '1.19'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.0.1
110
+ version: '1.19'
111
111
  description:
112
112
  email: cody@cutrer.com'
113
113
  executables:
114
+ - aurora_monitor
114
115
  - aurora_mqtt_bridge
116
+ - aurora_mock
117
+ - aurora_fetch
115
118
  extensions: []
116
119
  extra_rdoc_files: []
117
120
  files:
118
- - bin/aurora_fetch
119
- - bin/aurora_mock
120
- - bin/aurora_monitor
121
- - bin/aurora_mqtt_bridge
122
- - bin/registers.yml
121
+ - exe/aurora_fetch
122
+ - exe/aurora_mock
123
+ - exe/aurora_monitor
124
+ - exe/aurora_mqtt_bridge
125
+ - exe/registers.yml
123
126
  - lib/aurora.rb
124
127
  - lib/aurora/abc_client.rb
128
+ - lib/aurora/core_ext/string.rb
125
129
  - lib/aurora/iz2_zone.rb
126
130
  - lib/aurora/modbus/server.rb
127
131
  - lib/aurora/modbus/slave.rb
128
132
  - lib/aurora/registers.rb
133
+ - lib/aurora/thermostat.rb
129
134
  - lib/aurora/version.rb
130
135
  - lib/waterfurnace_aurora.rb
131
136
  homepage: https://github.com/ccutrer/waterfurnace
@@ -140,7 +145,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
145
  requirements:
141
146
  - - ">="
142
147
  - !ruby/object:Gem::Version
143
- version: '0'
148
+ version: '2.6'
144
149
  required_rubygems_version: !ruby/object:Gem::Requirement
145
150
  requirements:
146
151
  - - ">="
data/bin/aurora_fetch DELETED
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'aurora'
4
- require 'ccutrer-serialport'
5
- require 'uri'
6
-
7
- uri = URI.parse(ARGV[0])
8
-
9
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
10
- require 'net/telnet/rfc2217'
11
- [Net::Telnet::RFC2217.new('Host' => uri.host,
12
- 'Port' => uri.port || 23,
13
- 'baud' => 19200,
14
- 'parity' => Net::Telnet::RFC2217::EVEN)]
15
- else
16
- [CCutrer::SerialPort.new(uri.path, baud: 19200, parity: :even)]
17
- end
18
-
19
- client = ModBus::RTUClient.new(*args)
20
- client.debug = true
21
- slave = client.with_slave(1)
22
-
23
- registers = slave.holding_registers[ARGV[1].to_i]
24
-
25
- puts registers.inspect
@@ -1,289 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'aurora'
4
- require 'mqtt'
5
- require 'ccutrer-serialport'
6
- require 'uri'
7
-
8
- uri = URI.parse(ARGV[0])
9
- mqtt_uri = URI.parse(ARGV[1])
10
-
11
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
12
- require 'net/telnet/rfc2217'
13
- [Net::Telnet::RFC2217.new('Host' => uri.host,
14
- 'Port' => uri.port || 23,
15
- 'baud' => 19200,
16
- 'parity' => Net::Telnet::RFC2217::EVEN)]
17
- else
18
- [CCutrer::SerialPort.new(uri.path, baud: 19200, parity: :even)]
19
- end
20
-
21
- slave = ModBus::RTUClient.new(*args).with_slave(1)
22
- abc = Aurora::ABCClient.new(slave)
23
-
24
- class MQTTBridge
25
- def initialize(abc, mqtt_uri)
26
- @base_topic = "homie/aurora"
27
- @abc = abc
28
- @mqtt = MQTT::Client.new(mqtt_uri)
29
- @mqtt.set_will("#{@base_topic}/$state", "lost", true, 1)
30
- @mqtt.connect
31
- @attributes = {}
32
- @mutex = Mutex.new
33
-
34
- publish_basic_attributes
35
-
36
- abc_thread = Thread.new do
37
- loop do
38
- begin
39
- @mutex.synchronize do
40
- @abc.refresh
41
- publish_attribute("abc/compressor-speed", @abc.compressor_speed)
42
- publish_attribute("abc/current-mode", @abc.current_mode)
43
- publish_attribute("abc/dhw-water-temperature", @abc.dhw_water_temperature)
44
- publish_attribute("abc/entering-air-temperature", @abc.entering_air_temperature)
45
- publish_attribute("abc/entering-water-temperature", @abc.entering_water_temperature)
46
- publish_attribute("abc/fan-speed", @abc.fan_speed)
47
- publish_attribute("abc/leaving-air-temperature", @abc.leaving_air_temperature)
48
- publish_attribute("abc/leaving-water-temperature", @abc.leaving_water_temperature)
49
- publish_attribute("abc/outdoor-temperature", @abc.outdoor_temperature)
50
- publish_attribute("abc/relative-humidity", @abc.relative_humidity)
51
- publish_attribute("abc/waterflow", @abc.waterflow)
52
- publish_attribute("abc/fp1", @abc.fp1)
53
- publish_attribute("abc/fp2", @abc.fp2)
54
-
55
- @abc.iz2_zones.each do |z|
56
- i = z.zone_number
57
- publish_attribute("zone#{i}/target-mode", z.target_mode)
58
- publish_attribute("zone#{i}/current-mode", z.current_mode)
59
- publish_attribute("zone#{i}/target-fan-mode", z.target_fan_mode)
60
- publish_attribute("zone#{i}/current-fan-mode", z.current_fan_mode)
61
- publish_attribute("zone#{i}/fan-intermittent-on", z.fan_intermittent_on)
62
- publish_attribute("zone#{i}/fan-intermittent-off", z.fan_intermittent_off)
63
- publish_attribute("zone#{i}/priority", z.priority)
64
- publish_attribute("zone#{i}/size", z.size)
65
- publish_attribute("zone#{i}/normalized-size", z.normalized_size)
66
- publish_attribute("zone#{i}/ambient-temperature", z.ambient_temperature)
67
- publish_attribute("zone#{i}/heating-target-temperature", z.heating_target_temperature)
68
- publish_attribute("zone#{i}/cooling-target-temperature", z.cooling_target_temperature)
69
- end
70
- end
71
- rescue => e
72
- puts "got garbage: #{e}; #{e.backtrace}"
73
- exit 1
74
- end
75
- sleep(5)
76
- end
77
- end
78
-
79
- @mqtt.get do |topic, value|
80
- puts "got #{value.inspect} at #{topic}"
81
- zone = topic =~ %r{zone([1-6])/} && @abc.iz2_zones[$1.to_i - 1]
82
-
83
- begin
84
- @mutex.synchronize do
85
- case topic
86
- when %r{zone([1-6])/target-mode/set$}
87
- publish_attribute("zone#{$1}/target-mode", zone.target_mode = value.to_sym)
88
- when %r{zone([1-6])/target-fan-mode/set$}
89
- publish_attribute("zone#{$1}/target-fan-mode", zone.target_fan_mode = value.to_sym)
90
- when %r{zone([1-6])/fan-intermittent-(on|off)/set$}
91
- publish_attribute("zone#{$1}/fan-intermittent-#{$2}", zone.send("fan_intermittent_#{$2}=", value.to_i))
92
- when %r{zone([1-6])/(heating|cooling)-target-temperature}
93
- publish_attribute("zone#{$1}/#{$2}-target-temperature", zone.send("#{$2}_target_temperature=", value.to_f))
94
- when /\$modbus$/
95
- query = value.split(',').map do |addr|
96
- if addr == "known"
97
- Aurora::REGISTER_NAMES.keys
98
- elsif addr =~ /^(\d+)\.\.(\d+)$/
99
- $1.to_i..$2.to_i
100
- else
101
- addr.to_i
102
- end
103
- end
104
- queries = Aurora.normalize_ranges(query)
105
- registers = {}
106
- queries.each do |query|
107
- registers.merge!(@abc.modbus_slave.read_multiple_holding_registers(*query))
108
- end
109
- result = Aurora.print_registers(registers)
110
- @mqtt.publish("#{@base_topic}/$modbus/response", result, false, 1)
111
- when %r{\$modbus/(\d+)$}
112
- register = $1.to_i
113
- value = case value
114
- when /\d+/
115
- value.to_i
116
- when /0x(\d+)/
117
- $1.to_i(16)
118
- end
119
- @abc.modbus_slave.holding_registers[register] = value if value
120
- end
121
- end
122
- rescue => e
123
- puts "failed processing message: #{e}\n#{e.backtrace}"
124
- end
125
- end
126
- end
127
-
128
- def publish(topic, value)
129
- @mqtt.publish("#{@base_topic}/#{topic}", value, true, 1)
130
- end
131
-
132
- def publish_attribute(attr, value)
133
- if !@attributes.key?(attr) || @attributes[attr] != value
134
- publish(attr, value.to_s)
135
- @attributes[attr] = value
136
- end
137
- end
138
-
139
- def subscribe(topic)
140
- @mqtt.subscribe("#{@base_topic}/#{topic}")
141
- end
142
-
143
- def publish_basic_attributes
144
- publish("$homie", "4.0.0")
145
- publish("$name", "Aurora MQTT Bridge")
146
- publish("$state", "init")
147
- nodes = ["abc"]
148
-
149
- publish("abc/$name", "Aurora Basic Control")
150
- publish("abc/$datatype", "ABC")
151
- publish("abc/$properties", "compressor-speed,current-mode,dhw-water-temperature,entering-air-temperature,entering-water-temperature,fan-speed,leaving-air-temperature,leaving-water-temperature,outdoor-temperature,relative-humidity,waterflow,fp1,fp2")
152
-
153
- publish("abc/compressor-speed/$name", "Compressor Speed")
154
- publish("abc/compressor-speed/$datatype", "integer")
155
- publish("abc/compressor-speed/$format", "0:12")
156
-
157
- publish("abc/current-mode/$name", "Current Heating/Cooling Mode")
158
- publish("abc/current-mode/$datatype", "enum")
159
- publish("abc/current-mode/$format", "lockout,standby,blower,h1,h2,c1,c2,eh1,eh2")
160
-
161
- publish("abc/dhw-water-temperature/$name", "DHW Water Temperature")
162
- publish("abc/dhw-water-temperature/$datatype", "float")
163
- publish("abc/dhw-water-temperature/$unit", "ºF")
164
-
165
- publish("abc/entering-air-temperature/$name", "Entering Air Temperature")
166
- publish("abc/entering-air-temperature/$datatype", "float")
167
- publish("abc/entering-air-temperature/$unit", "ºF")
168
-
169
- publish("abc/entering-water-temperature/$name", "Entering Water Temperature")
170
- publish("abc/entering-water-temperature/$datatype", "float")
171
- publish("abc/entering-water-temperature/$unit", "ºF")
172
-
173
- publish("abc/fan-speed/$name", "Fan Speed")
174
- publish("abc/fan-speed/$datatype", "integer")
175
- publish("abc/fan-speed/$format", "0:11")
176
-
177
- publish("abc/leaving-air-temperature/$name", "Leaving Air Temperature")
178
- publish("abc/leaving-air-temperature/$datatype", "float")
179
- publish("abc/leaving-air-temperature/$unit", "ºF")
180
-
181
- publish("abc/leaving-water-temperature/$name", "Leaving Water Temperature")
182
- publish("abc/leaving-water-temperature/$datatype", "float")
183
- publish("abc/leaving-water-temperature/$unit", "ºF")
184
-
185
- publish("abc/outdoor-temperature/$name", "Outdoor Temperature")
186
- publish("abc/outdoor-temperature/$datatype", "float")
187
- publish("abc/outdoor-temperature/$unit", "ºF")
188
-
189
- publish("abc/relative-humidity/$name", "Relative Humidity")
190
- publish("abc/relative-humidity/$datatype", "integer")
191
- publish("abc/relative-humidity/$unit", "%")
192
- publish("abc/relative-humidity/$format", "0:100")
193
-
194
- publish("abc/waterflow/$name", "Waterflow")
195
- publish("abc/waterflow/$datatype", "float")
196
- publish("abc/waterflow/$unit", "gpm")
197
-
198
- publish("abc/fp1/$name", "FP1 Sensor")
199
- publish("abc/fp1/$datatype", "float")
200
- publish("abc/fp1/$unit", "ºF")
201
-
202
- publish("abc/fp2/$name", "FP1 Sensor")
203
- publish("abc/fp2/$datatype", "float")
204
- publish("abc/fp2/$unit", "ºF")
205
-
206
- (1..@abc.iz2_zones.length).each do |i|
207
- nodes << "zone#{i}"
208
- publish("zone#{i}/$name", "Zone #{i}")
209
- publish("zone#{i}/$datatype", "IntelliZone 2 Zone")
210
- publish("zone#{i}/$properties", "target-mode,current-mode,target-fan-mode,current-fan-mode,fan-intermittent-on,fan-intermittent-off,priority,size,normalized-size,ambient-temperature,heating-target-temperature,cooling-target-temperature")
211
-
212
- publish("zone#{i}/target-mode/$name", "Target Heating/Cooling Mode")
213
- publish("zone#{i}/target-mode/$datatype", "enum")
214
- if i == 1
215
- publish("zone#{i}/target-mode/$format", "off,auto,cool,heat,eheat")
216
- else
217
- publish("zone#{i}/target-mode/$format", "off,auto,cool,heat")
218
- end
219
- publish("zone#{i}/target-mode/$settable", "true")
220
- subscribe("zone#{i}/target-mode/set")
221
-
222
- publish("zone#{i}/current-mode/$name", "Current Heating/Cooling Mode Requested")
223
- publish("zone#{i}/current-mode/$datatype", "enum")
224
- publish("zone#{i}/current-mode/$format", "standby,h1,h2,h3,c1,c2")
225
-
226
- publish("zone#{i}/target-fan-mode/$name", "Target Fan Mode")
227
- publish("zone#{i}/target-fan-mode/$datatype", "enum")
228
- publish("zone#{i}/target-fan-mode/$format", "auto,continuous,intermittent")
229
- publish("zone#{i}/target-fan-mode/$settable", "true")
230
- subscribe("zone#{i}/target-fan-mode/set")
231
-
232
- publish("zone#{i}/current-fan-mode/$name", "Current Fan Status")
233
- publish("zone#{i}/current-fan-mode/$datatype", "boolean")
234
-
235
- publish("zone#{i}/fan-intermittent-on/$name", "Fan Intermittent Mode On Duration")
236
- publish("zone#{i}/fan-intermittent-on/$datatype", "enum")
237
- publish("zone#{i}/fan-intermittent-on/$format", "0,5,10,15,20")
238
- publish("zone#{i}/fan-intermittent-on/$unit", "M")
239
- publish("zone#{i}/fan-intermittent-on/$settable", "true")
240
- subscribe("zone#{i}/fan-intermittent-on/set")
241
-
242
- publish("zone#{i}/fan-intermittent-off/$name", "Fan Intermittent Mode Off Duration")
243
- publish("zone#{i}/fan-intermittent-off/$datatype", "enum")
244
- publish("zone#{i}/fan-intermittent-off/$format", "0,5,10,15,20,25,30,35,40")
245
- publish("zone#{i}/fan-intermittent-off/$unit", "M")
246
- publish("zone#{i}/fan-intermittent-off/$settable", "true")
247
- subscribe("zone#{i}/fan-intermittent-off/set")
248
-
249
- publish("zone#{i}/priority/$name", "Zone Priority")
250
- publish("zone#{i}/priority/$datatype", "enum")
251
- publish("zone#{i}/priority/$format", "economy,comfort")
252
-
253
- publish("zone#{i}/size/$name", "Size")
254
- publish("zone#{i}/size/$datatype", "enum")
255
- publish("zone#{i}/size/$format", "0,25,45,70")
256
-
257
- publish("zone#{i}/normalized-size/$name", "Normalized Size")
258
- publish("zone#{i}/normalized-size/$datatype", "integer")
259
- publish("zone#{i}/normalized-size/$format", "0:100")
260
- publish("zone#{i}/normalized-size/$unit", "%")
261
-
262
- publish("zone#{i}/ambient-temperature/$name", "Ambient Temperature")
263
- publish("zone#{i}/ambient-temperature/$datatype", "float")
264
- publish("zone#{i}/ambient-temperature/$unit", "ºF")
265
-
266
- publish("zone#{i}/heating-target-temperature/$name", "Heating Target Temperature")
267
- publish("zone#{i}/heating-target-temperature/$datatype", "integer")
268
- publish("zone#{i}/heating-target-temperature/$unit", "ºF")
269
- publish("zone#{i}/heating-target-temperature/$format", "40:90")
270
- publish("zone#{i}/heating-target-temperature/$settable", "true")
271
- subscribe("zone#{i}/heating-target-temperature/set")
272
-
273
- publish("zone#{i}/cooling-target-temperature/$name", "Cooling Target Temperature")
274
- publish("zone#{i}/cooling-target-temperature/$datatype", "integer")
275
- publish("zone#{i}/cooling-target-temperature/$unit", "ºF")
276
- publish("zone#{i}/cooling-target-temperature/$format", "54:99")
277
- publish("zone#{i}/cooling-target-temperature/$settable", "true")
278
- subscribe("zone#{i}/cooling-target-temperature/set")
279
- end
280
- publish("$nodes", nodes.join(','))
281
-
282
- # direct access to modbus registers for debugging purposes
283
- subscribe("$modbus")
284
- subscribe("$modbus/+")
285
- publish("$state", 'ready')
286
- end
287
- end
288
-
289
- MQTTBridge.new(abc, mqtt_uri)