@fdm-monster/server 1.9.1 → 1.9.3

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.
Files changed (75) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/.yarn/releases/{yarn-4.10.3.cjs → yarn-4.12.0.cjs} +300 -300
  3. package/.yarnrc.yml +1 -1
  4. package/README.md +3 -2
  5. package/RELEASE_NOTES.MD +20 -0
  6. package/dist/consoles/mock-bambu.server.js +305 -0
  7. package/dist/consoles/mock-bambu.server.js.map +1 -0
  8. package/dist/constants/server-settings.constants.js +1 -0
  9. package/dist/constants/server-settings.constants.js.map +1 -1
  10. package/dist/container.js +8 -0
  11. package/dist/container.js.map +1 -1
  12. package/dist/container.tokens.js +4 -0
  13. package/dist/container.tokens.js.map +1 -1
  14. package/dist/controllers/first-time-setup.controller.js +33 -2
  15. package/dist/controllers/first-time-setup.controller.js.map +1 -1
  16. package/dist/controllers/server-private.controller.js +10 -10
  17. package/dist/controllers/server-private.controller.js.map +1 -1
  18. package/dist/controllers/server-public.controller.js +4 -0
  19. package/dist/controllers/server-public.controller.js.map +1 -1
  20. package/dist/controllers/settings.controller.js +22 -0
  21. package/dist/controllers/settings.controller.js.map +1 -1
  22. package/dist/entities/settings.entity.js.map +1 -1
  23. package/dist/middleware/global.middleware.js +1 -0
  24. package/dist/middleware/global.middleware.js.map +1 -1
  25. package/dist/middleware/printer.js +11 -0
  26. package/dist/middleware/printer.js.map +1 -1
  27. package/dist/models/Settings.js +5 -0
  28. package/dist/models/Settings.js.map +1 -1
  29. package/dist/server.constants.js +1 -8
  30. package/dist/server.constants.js.map +1 -1
  31. package/dist/services/bambu/bambu-ftp.adapter.js +204 -0
  32. package/dist/services/bambu/bambu-ftp.adapter.js.map +1 -0
  33. package/dist/services/bambu/bambu-mqtt.adapter.js +387 -0
  34. package/dist/services/bambu/bambu-mqtt.adapter.js.map +1 -0
  35. package/dist/services/bambu/bambu.client.js +67 -0
  36. package/dist/services/bambu/bambu.client.js.map +1 -0
  37. package/dist/services/bambu/mqtt-message.types.js +6 -0
  38. package/dist/services/bambu/mqtt-message.types.js.map +1 -0
  39. package/dist/services/bambu.api.js +221 -0
  40. package/dist/services/bambu.api.js.map +1 -0
  41. package/dist/services/core/yaml.service.js +123 -37
  42. package/dist/services/core/yaml.service.js.map +1 -1
  43. package/dist/services/interfaces/printer.dto.js.map +1 -1
  44. package/dist/services/interfaces/settings.dto.js.map +1 -1
  45. package/dist/services/mongoose/floor.service.js +1 -1
  46. package/dist/services/mongoose/floor.service.js.map +1 -1
  47. package/dist/services/mongoose/settings.service.js.map +1 -1
  48. package/dist/services/mongoose/user.service.js +7 -0
  49. package/dist/services/mongoose/user.service.js.map +1 -1
  50. package/dist/services/orm/floor.service.js +1 -1
  51. package/dist/services/orm/settings.service.js +0 -4
  52. package/dist/services/orm/settings.service.js.map +1 -1
  53. package/dist/services/orm/user.service.js +8 -0
  54. package/dist/services/orm/user.service.js.map +1 -1
  55. package/dist/services/printer-api.factory.js +7 -1
  56. package/dist/services/printer-api.factory.js.map +1 -1
  57. package/dist/services/printer-api.interface.js +5 -0
  58. package/dist/services/printer-api.interface.js.map +1 -1
  59. package/dist/services/socket.factory.js +3 -0
  60. package/dist/services/socket.factory.js.map +1 -1
  61. package/dist/services/validators/printer-service.validation.js +1 -1
  62. package/dist/services/validators/printer-service.validation.js.map +1 -1
  63. package/dist/services/validators/settings-service.validation.js +8 -1
  64. package/dist/services/validators/settings-service.validation.js.map +1 -1
  65. package/dist/services/validators/yaml-service.validation.js +27 -1
  66. package/dist/services/validators/yaml-service.validation.js.map +1 -1
  67. package/dist/shared/runtime-settings.migration.js +1 -0
  68. package/dist/shared/runtime-settings.migration.js.map +1 -1
  69. package/dist/state/printer-events.cache.js +13 -0
  70. package/dist/state/printer-events.cache.js.map +1 -1
  71. package/dist/state/settings.store.js +13 -4
  72. package/dist/state/settings.store.js.map +1 -1
  73. package/package.json +34 -27
  74. package/dist/utils/printer-type.utils.js +0 -32
  75. package/dist/utils/printer-type.utils.js.map +0 -1
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get BambuMqttAdapter () {
13
+ return BambuMqttAdapter;
14
+ },
15
+ get bambuEvent () {
16
+ return bambuEvent;
17
+ }
18
+ });
19
+ const _mqtt = /*#__PURE__*/ _interop_require_default(require("mqtt"));
20
+ const _socketstatetype = require("../../shared/dtos/socket-state.type");
21
+ const _apistatetype = require("../../shared/dtos/api-state.type");
22
+ const _printerapiinterface = require("../printer-api.interface");
23
+ function _interop_require_default(obj) {
24
+ return obj && obj.__esModule ? obj : {
25
+ default: obj
26
+ };
27
+ }
28
+ const bambuEvent = (event)=>`bambu.${event}`;
29
+ class BambuMqttAdapter {
30
+ logger;
31
+ settingsStore;
32
+ eventEmitter2;
33
+ printerType = _printerapiinterface.BambuType;
34
+ printerId;
35
+ socketState = _socketstatetype.SOCKET_STATE.unopened;
36
+ apiState = _apistatetype.API_STATE.unset;
37
+ login;
38
+ lastMessageReceivedTimestamp = null;
39
+ mqttClient = null;
40
+ host = null;
41
+ accessCode = null;
42
+ serial = null;
43
+ lastState = null;
44
+ isConnecting = false;
45
+ eventsAllowed = true;
46
+ constructor(settingsStore, loggerFactory, eventEmitter2){
47
+ this.settingsStore = settingsStore;
48
+ this.eventEmitter2 = eventEmitter2;
49
+ this.logger = loggerFactory(BambuMqttAdapter.name);
50
+ }
51
+ registerCredentials(socketLogin) {
52
+ const { printerId, loginDto } = socketLogin;
53
+ this.printerId = printerId;
54
+ this.login = loginDto;
55
+ this.host = loginDto.printerURL?.replace(/^https?:\/\//, '');
56
+ this.accessCode = loginDto.password || null;
57
+ this.serial = loginDto.username || null;
58
+ }
59
+ needsReopen() {
60
+ const isApiOnline = this.apiState === _apistatetype.API_STATE.responding;
61
+ return isApiOnline && (this.socketState === _socketstatetype.SOCKET_STATE.closed || this.socketState === _socketstatetype.SOCKET_STATE.error);
62
+ }
63
+ needsSetup() {
64
+ return this.socketState === _socketstatetype.SOCKET_STATE.unopened;
65
+ }
66
+ needsReauth() {
67
+ return false;
68
+ }
69
+ isClosedOrAborted() {
70
+ return this.socketState === _socketstatetype.SOCKET_STATE.closed || this.socketState === _socketstatetype.SOCKET_STATE.aborted;
71
+ }
72
+ async reauthSession() {
73
+ this.logger.debug("reauthSession called but not needed for Bambu");
74
+ }
75
+ open() {
76
+ if (!this.host || !this.accessCode || !this.serial) {
77
+ throw new Error("Cannot open connection: credentials not registered");
78
+ }
79
+ this.connect(this.host, this.accessCode, this.serial).catch((err)=>{
80
+ this.logger.error("Failed to open MQTT connection: " + err.toString());
81
+ this.socketState = _socketstatetype.SOCKET_STATE.error;
82
+ });
83
+ }
84
+ close() {
85
+ this.disconnect().catch((err)=>{
86
+ this.logger.error("Error during MQTT disconnect:", err);
87
+ });
88
+ }
89
+ async setupSocketSession() {
90
+ if (!this.host || !this.accessCode || !this.serial) {
91
+ this.socketState = _socketstatetype.SOCKET_STATE.aborted;
92
+ this.apiState = _apistatetype.API_STATE.noResponse;
93
+ throw new Error("Credentials not properly registered");
94
+ }
95
+ this.socketState = _socketstatetype.SOCKET_STATE.opening;
96
+ this.apiState = _apistatetype.API_STATE.responding;
97
+ }
98
+ allowEmittingEvents() {
99
+ this.eventsAllowed = true;
100
+ }
101
+ disallowEmittingEvents() {
102
+ this.eventsAllowed = false;
103
+ }
104
+ async connect(host, accessCode, serial) {
105
+ if (this.mqttClient?.connected) {
106
+ this.logger.debug("MQTT already connected");
107
+ this.socketState = _socketstatetype.SOCKET_STATE.opened;
108
+ return;
109
+ }
110
+ if (this.isConnecting) {
111
+ throw new Error("Connection already in progress");
112
+ }
113
+ this.host = host;
114
+ this.accessCode = accessCode;
115
+ this.serial = serial;
116
+ this.isConnecting = true;
117
+ this.socketState = _socketstatetype.SOCKET_STATE.opening;
118
+ const mqttUrl = `mqtt://${host}:8883`;
119
+ const timeout = this.settingsStore.getTimeoutSettings().apiTimeout;
120
+ this.logger.log(`Connecting to Bambu MQTT at ${mqttUrl}`);
121
+ return new Promise((resolve, reject)=>{
122
+ const connectionTimeout = setTimeout(()=>{
123
+ this.isConnecting = false;
124
+ this.socketState = _socketstatetype.SOCKET_STATE.error;
125
+ this.cleanup();
126
+ reject(new Error("MQTT connection timeout"));
127
+ }, timeout);
128
+ try {
129
+ this.mqttClient = _mqtt.default.connect(mqttUrl, {
130
+ username: "bblp",
131
+ password: accessCode,
132
+ clientId: `fdm_monster_${serial}_${Date.now()}`,
133
+ protocol: "mqtt",
134
+ connectTimeout: timeout,
135
+ reconnectPeriod: 5000,
136
+ keepalive: 60
137
+ });
138
+ this.mqttClient.on("connect", ()=>{
139
+ clearTimeout(connectionTimeout);
140
+ this.isConnecting = false;
141
+ this.socketState = _socketstatetype.SOCKET_STATE.authenticated;
142
+ this.apiState = _apistatetype.API_STATE.responding;
143
+ this.logger.log("MQTT connected successfully");
144
+ const reportTopic = `device/${serial}/report`;
145
+ this.mqttClient.subscribe(reportTopic, {
146
+ qos: 0
147
+ }, (err)=>{
148
+ if (err) {
149
+ this.logger.error(`Failed to subscribe to ${reportTopic}:`, err);
150
+ this.socketState = _socketstatetype.SOCKET_STATE.error;
151
+ reject(new Error(`Subscribe failed: ${err.message}`));
152
+ } else {
153
+ this.logger.debug(`Subscribed to ${reportTopic}`);
154
+ resolve();
155
+ }
156
+ });
157
+ });
158
+ this.mqttClient.on("error", (error)=>{
159
+ clearTimeout(connectionTimeout);
160
+ this.isConnecting = false;
161
+ this.socketState = _socketstatetype.SOCKET_STATE.error;
162
+ this.logger.error("MQTT error:", error);
163
+ if (!this.mqttClient?.connected) {
164
+ reject(error);
165
+ }
166
+ });
167
+ this.mqttClient.on("message", (topic, message)=>{
168
+ this.lastMessageReceivedTimestamp = Date.now();
169
+ this.handleMessage(topic, message);
170
+ });
171
+ this.mqttClient.on("disconnect", ()=>{
172
+ this.socketState = _socketstatetype.SOCKET_STATE.closed;
173
+ this.logger.warn("MQTT disconnected");
174
+ });
175
+ this.mqttClient.on("reconnect", ()=>{
176
+ this.socketState = _socketstatetype.SOCKET_STATE.opening;
177
+ this.logger.debug("MQTT reconnecting...");
178
+ });
179
+ this.mqttClient.on("close", ()=>{
180
+ this.socketState = _socketstatetype.SOCKET_STATE.closed;
181
+ this.logger.debug("MQTT connection closed");
182
+ });
183
+ } catch (error) {
184
+ clearTimeout(connectionTimeout);
185
+ this.isConnecting = false;
186
+ this.socketState = _socketstatetype.SOCKET_STATE.error;
187
+ this.cleanup();
188
+ reject(error);
189
+ }
190
+ });
191
+ }
192
+ async disconnect() {
193
+ if (!this.mqttClient) {
194
+ this.socketState = _socketstatetype.SOCKET_STATE.closed;
195
+ return;
196
+ }
197
+ this.logger.log("Disconnecting MQTT");
198
+ this.socketState = _socketstatetype.SOCKET_STATE.closed;
199
+ return new Promise((resolve)=>{
200
+ if (this.mqttClient?.connected) {
201
+ this.mqttClient.end(false, {}, ()=>{
202
+ this.cleanup();
203
+ resolve();
204
+ });
205
+ } else {
206
+ this.cleanup();
207
+ resolve();
208
+ }
209
+ });
210
+ }
211
+ getLastState() {
212
+ return this.lastState;
213
+ }
214
+ async sendCommand(payload) {
215
+ if (!this.mqttClient?.connected) {
216
+ throw new Error("MQTT not connected");
217
+ }
218
+ if (!this.serial) {
219
+ throw new Error("Serial number not set");
220
+ }
221
+ const requestTopic = `device/${this.serial}/request`;
222
+ const message = JSON.stringify(payload);
223
+ return new Promise((resolve, reject)=>{
224
+ this.mqttClient.publish(requestTopic, message, {
225
+ qos: 0
226
+ }, (err)=>{
227
+ if (err) {
228
+ this.logger.error("Failed to send command:", err);
229
+ reject(err);
230
+ } else {
231
+ this.logger.debug("Command sent:", payload);
232
+ resolve();
233
+ }
234
+ });
235
+ });
236
+ }
237
+ async startPrint(filename) {
238
+ await this.sendCommand({
239
+ print: {
240
+ command: "project_file",
241
+ param: filename,
242
+ url: `file:///sdcard/${filename}`,
243
+ subtask_name: filename,
244
+ sequence_id: String(Date.now())
245
+ }
246
+ });
247
+ }
248
+ async pausePrint() {
249
+ await this.sendCommand({
250
+ print: {
251
+ command: "pause",
252
+ sequence_id: String(Date.now())
253
+ }
254
+ });
255
+ }
256
+ async resumePrint() {
257
+ await this.sendCommand({
258
+ print: {
259
+ command: "resume",
260
+ sequence_id: String(Date.now())
261
+ }
262
+ });
263
+ }
264
+ async stopPrint() {
265
+ await this.sendCommand({
266
+ print: {
267
+ command: "stop",
268
+ sequence_id: String(Date.now())
269
+ }
270
+ });
271
+ }
272
+ async sendGcode(gcode) {
273
+ await this.sendCommand({
274
+ print: {
275
+ command: "gcode_line",
276
+ param: gcode,
277
+ sequence_id: String(Date.now())
278
+ }
279
+ });
280
+ }
281
+ resetSocketState() {
282
+ this.lastState = null;
283
+ }
284
+ async emitEvent(event, payload) {
285
+ if (!this.eventsAllowed) {
286
+ return;
287
+ }
288
+ await this.eventEmitter2.emitAsync(bambuEvent(event), {
289
+ event,
290
+ payload,
291
+ printerId: this.printerId,
292
+ printerType: _printerapiinterface.BambuType
293
+ });
294
+ }
295
+ emitEventSync(event, payload) {
296
+ if (!this.eventsAllowed) {
297
+ return;
298
+ }
299
+ this.eventEmitter2.emit(bambuEvent(event), {
300
+ event,
301
+ payload,
302
+ printerId: this.printerId,
303
+ printerType: _printerapiinterface.BambuType
304
+ });
305
+ }
306
+ transformStateToCurrentMessage(state) {
307
+ const isPrinting = state.gcode_state === "PRINTING" || state.mc_print_stage === "printing";
308
+ const isPaused = state.mc_print_stage === "paused";
309
+ const isPausedText = isPaused ? "Paused" : "Printing";
310
+ return {
311
+ state: {
312
+ text: isPrinting ? isPausedText : "Operational",
313
+ flags: {
314
+ operational: true,
315
+ printing: isPrinting && !isPaused,
316
+ paused: isPaused,
317
+ ready: !isPrinting,
318
+ error: state.print_error !== 0,
319
+ cancelling: false,
320
+ pausing: false,
321
+ sdReady: true,
322
+ closedOrError: false
323
+ }
324
+ },
325
+ temps: [
326
+ {
327
+ time: Date.now(),
328
+ tool0: {
329
+ actual: state.nozzle_temper || 0,
330
+ target: state.nozzle_target_temper || 0
331
+ },
332
+ bed: {
333
+ actual: state.bed_temper || 0,
334
+ target: state.bed_target_temper || 0
335
+ },
336
+ chamber: {
337
+ actual: state.chamber_temper || 0,
338
+ target: 0
339
+ }
340
+ }
341
+ ],
342
+ progress: {
343
+ completion: state.mc_percent || 0,
344
+ printTime: null,
345
+ printTimeLeft: state.mc_remaining_time ? state.mc_remaining_time * 60 : null
346
+ },
347
+ job: {
348
+ file: {
349
+ name: state.gcode_file || state.subtask_name || null
350
+ }
351
+ },
352
+ currentZ: state.layer_num || null,
353
+ offsets: {},
354
+ resends: {
355
+ count: 0,
356
+ transmitted: 0,
357
+ ratio: 0
358
+ },
359
+ logs: [],
360
+ messages: []
361
+ };
362
+ }
363
+ handleMessage(topic, message) {
364
+ try {
365
+ const payload = JSON.parse(message.toString());
366
+ if (topic.endsWith("/report") && payload.print) {
367
+ this.lastState = payload.print;
368
+ this.logger.debug("Received printer state update");
369
+ const currentMessage = this.transformStateToCurrentMessage(this.lastState);
370
+ this.emitEvent("current", currentMessage).catch((err)=>{
371
+ this.logger.error("Failed to emit current event:", err);
372
+ });
373
+ }
374
+ } catch (error) {
375
+ this.logger.error("Failed to parse MQTT message:", error);
376
+ }
377
+ }
378
+ cleanup() {
379
+ if (this.mqttClient) {
380
+ this.mqttClient.removeAllListeners();
381
+ this.mqttClient = null;
382
+ }
383
+ this.lastState = null;
384
+ }
385
+ }
386
+
387
+ //# sourceMappingURL=bambu-mqtt.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/bambu/bambu-mqtt.adapter.ts"],"names":["BambuMqttAdapter","bambuEvent","event","logger","settingsStore","eventEmitter2","printerType","BambuType","printerId","socketState","SOCKET_STATE","unopened","apiState","API_STATE","unset","login","lastMessageReceivedTimestamp","mqttClient","host","accessCode","serial","lastState","isConnecting","eventsAllowed","loggerFactory","name","registerCredentials","socketLogin","loginDto","printerURL","replace","password","username","needsReopen","isApiOnline","responding","closed","error","needsSetup","needsReauth","isClosedOrAborted","aborted","reauthSession","debug","open","Error","connect","catch","err","toString","close","disconnect","setupSocketSession","noResponse","opening","allowEmittingEvents","disallowEmittingEvents","connected","opened","mqttUrl","timeout","getTimeoutSettings","apiTimeout","log","Promise","resolve","reject","connectionTimeout","setTimeout","cleanup","mqtt","clientId","Date","now","protocol","connectTimeout","reconnectPeriod","keepalive","on","clearTimeout","authenticated","reportTopic","subscribe","qos","message","topic","handleMessage","warn","end","getLastState","sendCommand","payload","requestTopic","JSON","stringify","publish","startPrint","filename","print","command","param","url","subtask_name","sequence_id","String","pausePrint","resumePrint","stopPrint","sendGcode","gcode","resetSocketState","emitEvent","emitAsync","emitEventSync","emit","transformStateToCurrentMessage","state","isPrinting","gcode_state","mc_print_stage","isPaused","isPausedText","text","flags","operational","printing","paused","ready","print_error","cancelling","pausing","sdReady","closedOrError","temps","time","tool0","actual","nozzle_temper","target","nozzle_target_temper","bed","bed_temper","bed_target_temper","chamber","chamber_temper","progress","completion","mc_percent","printTime","printTimeLeft","mc_remaining_time","job","file","gcode_file","currentZ","layer_num","offsets","resends","count","transmitted","ratio","logs","messages","parse","endsWith","currentMessage","removeAllListeners"],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "BambuClient", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return BambuClient;
9
+ }
10
+ });
11
+ class BambuClient {
12
+ eventEmitter2;
13
+ settingsStore;
14
+ logger;
15
+ ftpAdapter;
16
+ connected = false;
17
+ constructor(settingsStore, loggerFactory, eventEmitter2, bambuFtpAdapter){
18
+ this.settingsStore = settingsStore;
19
+ this.eventEmitter2 = eventEmitter2;
20
+ this.logger = loggerFactory(BambuClient.name);
21
+ this.ftpAdapter = bambuFtpAdapter;
22
+ }
23
+ async connect(login) {
24
+ const host = this.extractHost(login.printerURL);
25
+ const accessCode = login.password || "";
26
+ if (!accessCode) {
27
+ throw new Error("Access code (password) is required for Bambu Lab printers");
28
+ }
29
+ this.logger.log(`Connecting to Bambu Lab printer FTP at ${host}`);
30
+ try {
31
+ await this.ftpAdapter.connect(host, accessCode);
32
+ this.connected = true;
33
+ this.logger.log("Successfully connected to Bambu Lab printer FTP");
34
+ } catch (error) {
35
+ this.logger.error("Failed to connect to Bambu Lab printer FTP:", error);
36
+ await this.disconnect();
37
+ throw error;
38
+ }
39
+ }
40
+ async disconnect() {
41
+ this.logger.log("Disconnecting from Bambu Lab printer FTP");
42
+ await this.ftpAdapter.disconnect();
43
+ this.connected = false;
44
+ this.logger.log("Disconnected from Bambu Lab printer FTP");
45
+ }
46
+ get ftp() {
47
+ return this.ftpAdapter;
48
+ }
49
+ get isConnected() {
50
+ return this.connected && this.ftpAdapter.isConnected;
51
+ }
52
+ extractHost(printerURL) {
53
+ try {
54
+ const url = new URL(printerURL);
55
+ return url.hostname;
56
+ } catch {
57
+ return printerURL.replace(/^https?:\/\//, "").split(":")[0].split("/")[0];
58
+ }
59
+ }
60
+ async getApiVersion(_login, _timeout) {
61
+ return {
62
+ version: "bambu-1.0"
63
+ };
64
+ }
65
+ }
66
+
67
+ //# sourceMappingURL=bambu.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/bambu/bambu.client.ts"],"names":["BambuClient","eventEmitter2","settingsStore","logger","ftpAdapter","connected","loggerFactory","bambuFtpAdapter","name","connect","login","host","extractHost","printerURL","accessCode","password","Error","log","error","disconnect","ftp","isConnected","url","URL","hostname","replace","split","getApiVersion","_login","_timeout","version"],"mappings":";;;;+BAkBaA;;;eAAAA;;;AAAN,MAAMA;IACFC,cAA6B;IAC7BC,cAA6B;IACnBC,OAAsB;IACxBC,WAA4B;IACrCC,YAAY,MAAM;IAE1B,YACEH,aAA4B,EAC5BI,aAA6B,EAC7BL,aAA4B,EAC5BM,eAAgC,CAChC;QACA,IAAI,CAACL,aAAa,GAAGA;QACrB,IAAI,CAACD,aAAa,GAAGA;QACrB,IAAI,CAACE,MAAM,GAAGG,cAAcN,YAAYQ,IAAI;QAC5C,IAAI,CAACJ,UAAU,GAAGG;IACpB;IAKA,MAAME,QAAQC,KAAe,EAAiB;QAC5C,MAAMC,OAAO,IAAI,CAACC,WAAW,CAACF,MAAMG,UAAU;QAC9C,MAAMC,aAAaJ,MAAMK,QAAQ,IAAI;QAErC,IAAI,CAACD,YAAY;YACf,MAAM,IAAIE,MAAM;QAClB;QAEA,IAAI,CAACb,MAAM,CAACc,GAAG,CAAC,CAAC,uCAAuC,EAAEN,MAAM;QAEhE,IAAI;YACF,MAAM,IAAI,CAACP,UAAU,CAACK,OAAO,CAACE,MAAMG;YACpC,IAAI,CAACT,SAAS,GAAG;YACjB,IAAI,CAACF,MAAM,CAACc,GAAG,CAAC;QAClB,EAAE,OAAOC,OAAO;YACd,IAAI,CAACf,MAAM,CAACe,KAAK,CAAC,+CAA+CA;YACjE,MAAM,IAAI,CAACC,UAAU;YACrB,MAAMD;QACR;IACF;IAKA,MAAMC,aAA4B;QAChC,IAAI,CAAChB,MAAM,CAACc,GAAG,CAAC;QAChB,MAAM,IAAI,CAACb,UAAU,CAACe,UAAU;QAChC,IAAI,CAACd,SAAS,GAAG;QACjB,IAAI,CAACF,MAAM,CAACc,GAAG,CAAC;IAClB;IAKA,IAAIG,MAAuB;QACzB,OAAO,IAAI,CAAChB,UAAU;IACxB;IAKA,IAAIiB,cAAuB;QACzB,OAAO,IAAI,CAAChB,SAAS,IAAI,IAAI,CAACD,UAAU,CAACiB,WAAW;IACtD;IAKQT,YAAYC,UAAkB,EAAU;QAC9C,IAAI;YACF,MAAMS,MAAM,IAAIC,IAAIV;YACpB,OAAOS,IAAIE,QAAQ;QACrB,EAAE,OAAM;YAEN,OAAOX,WAAWY,OAAO,CAAC,gBAAgB,IAAIC,KAAK,CAAC,IAAI,CAAC,EAAE,CAACA,KAAK,CAAC,IAAI,CAAC,EAAE;QAC3E;IACF;IAMA,MAAMC,cAAcC,MAAgB,EAAEC,QAAiB,EAAgC;QAErF,OAAO;YAACC,SAAS;QAAW;IAC9B;AACF"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+
6
+ //# sourceMappingURL=mqtt-message.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/bambu/mqtt-message.types.ts"],"names":[],"mappings":""}