waterfurnace_aurora 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)