@fdm-monster/server 1.9.0 → 1.9.2

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 (257) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/.yarn/releases/{yarn-4.9.1.cjs → yarn-4.12.0.cjs} +329 -335
  3. package/.yarnrc.yml +1 -1
  4. package/README.md +3 -2
  5. package/RELEASE_NOTES.MD +17 -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/consoles/utils/api-messages.js +5 -5
  9. package/dist/consoles/utils/api-messages.js.map +1 -1
  10. package/dist/constants/authorization.constants.js +9 -9
  11. package/dist/constants/authorization.constants.js.map +1 -1
  12. package/dist/constants/event.constants.js +8 -8
  13. package/dist/constants/event.constants.js.map +1 -1
  14. package/dist/constants/server-settings.constants.js +15 -14
  15. package/dist/constants/server-settings.constants.js.map +1 -1
  16. package/dist/constants/service.constants.js +4 -4
  17. package/dist/constants/service.constants.js.map +1 -1
  18. package/dist/container.js +11 -3
  19. package/dist/container.js.map +1 -1
  20. package/dist/container.tokens.js +4 -0
  21. package/dist/container.tokens.js.map +1 -1
  22. package/dist/controllers/auth.controller.js.map +1 -1
  23. package/dist/controllers/batch-call.controller.js.map +1 -1
  24. package/dist/controllers/camera-stream.controller.js.map +1 -1
  25. package/dist/controllers/custom-gcode.controller.js.map +1 -1
  26. package/dist/controllers/first-time-setup.controller.js +33 -2
  27. package/dist/controllers/first-time-setup.controller.js.map +1 -1
  28. package/dist/controllers/floor.controller.js.map +1 -1
  29. package/dist/controllers/metrics.controller.js.map +1 -1
  30. package/dist/controllers/print-completion.controller.js.map +1 -1
  31. package/dist/controllers/printer-files.controller.js.map +1 -1
  32. package/dist/controllers/printer-group.controller.js.map +1 -1
  33. package/dist/controllers/printer-settings.controller.js.map +1 -1
  34. package/dist/controllers/printer.controller.js.map +1 -1
  35. package/dist/controllers/server-private.controller.js +10 -10
  36. package/dist/controllers/server-private.controller.js.map +1 -1
  37. package/dist/controllers/server-public.controller.js +4 -0
  38. package/dist/controllers/server-public.controller.js.map +1 -1
  39. package/dist/controllers/settings.controller.js +22 -0
  40. package/dist/controllers/settings.controller.js.map +1 -1
  41. package/dist/controllers/user.controller.js.map +1 -1
  42. package/dist/controllers/validation/batch-controller.validation.js +4 -4
  43. package/dist/controllers/validation/batch-controller.validation.js.map +1 -1
  44. package/dist/controllers/validation/generic.validation.js +3 -3
  45. package/dist/controllers/validation/generic.validation.js.map +1 -1
  46. package/dist/controllers/validation/printer-controller.validation.js +6 -6
  47. package/dist/controllers/validation/printer-controller.validation.js.map +1 -1
  48. package/dist/controllers/validation/printer-files-controller.validation.js +5 -5
  49. package/dist/controllers/validation/printer-files-controller.validation.js.map +1 -1
  50. package/dist/controllers/validation/setting.validation.js +4 -4
  51. package/dist/controllers/validation/setting.validation.js.map +1 -1
  52. package/dist/controllers/validation/user-controller.validation.js +8 -8
  53. package/dist/controllers/validation/user-controller.validation.js.map +1 -1
  54. package/dist/entities/index.js +12 -12
  55. package/dist/entities/index.js.map +1 -1
  56. package/dist/entities/settings.entity.js.map +1 -1
  57. package/dist/exceptions/failed-dependency.exception.js.map +1 -1
  58. package/dist/exceptions/job.exceptions.js.map +1 -1
  59. package/dist/exceptions/runtime.exceptions.js +10 -10
  60. package/dist/exceptions/runtime.exceptions.js.map +1 -1
  61. package/dist/handlers/logger.js.map +1 -1
  62. package/dist/handlers/logging/static.logger.js +4 -4
  63. package/dist/handlers/logging/static.logger.js.map +1 -1
  64. package/dist/handlers/validators.js +3 -3
  65. package/dist/handlers/validators.js.map +1 -1
  66. package/dist/middleware/authenticate.js +4 -4
  67. package/dist/middleware/authenticate.js.map +1 -1
  68. package/dist/middleware/global.middleware.js +4 -3
  69. package/dist/middleware/global.middleware.js.map +1 -1
  70. package/dist/middleware/param-converter.middleware.js +5 -5
  71. package/dist/middleware/param-converter.middleware.js.map +1 -1
  72. package/dist/middleware/passport.js +4 -4
  73. package/dist/middleware/passport.js.map +1 -1
  74. package/dist/middleware/printer.js +17 -6
  75. package/dist/middleware/printer.js.map +1 -1
  76. package/dist/models/Printer.js +3 -3
  77. package/dist/models/Printer.js.map +1 -1
  78. package/dist/models/Settings.js +5 -0
  79. package/dist/models/Settings.js.map +1 -1
  80. package/dist/models/index.js +11 -11
  81. package/dist/models/index.js.map +1 -1
  82. package/dist/server.constants.js +1 -1
  83. package/dist/server.env.js +9 -9
  84. package/dist/server.env.js.map +1 -1
  85. package/dist/server.host.js.map +1 -1
  86. package/dist/services/authentication/auth.service.js +1 -2
  87. package/dist/services/authentication/auth.service.js.map +1 -1
  88. package/dist/services/authentication/jwt.service.js.map +1 -1
  89. package/dist/services/bambu/bambu-ftp.adapter.js +204 -0
  90. package/dist/services/bambu/bambu-ftp.adapter.js.map +1 -0
  91. package/dist/services/bambu/bambu-mqtt.adapter.js +387 -0
  92. package/dist/services/bambu/bambu-mqtt.adapter.js.map +1 -0
  93. package/dist/services/bambu/bambu.client.js +67 -0
  94. package/dist/services/bambu/bambu.client.js.map +1 -0
  95. package/dist/services/bambu/mqtt-message.types.js +6 -0
  96. package/dist/services/bambu/mqtt-message.types.js.map +1 -0
  97. package/dist/services/bambu.api.js +221 -0
  98. package/dist/services/bambu.api.js.map +1 -0
  99. package/dist/services/core/batch-call.service.js.map +1 -1
  100. package/dist/services/core/client-bundle.service.js +4 -8
  101. package/dist/services/core/client-bundle.service.js.map +1 -1
  102. package/dist/services/core/cradle.service.js.map +1 -1
  103. package/dist/services/core/github.service.js.map +1 -1
  104. package/dist/services/core/http-client.factory.js.map +1 -1
  105. package/dist/services/core/logs-manager.service.js.map +1 -1
  106. package/dist/services/core/monsterpi.service.js.map +1 -1
  107. package/dist/services/core/multer.service.js +6 -7
  108. package/dist/services/core/multer.service.js.map +1 -1
  109. package/dist/services/core/server-release.service.js +6 -12
  110. package/dist/services/core/server-release.service.js.map +1 -1
  111. package/dist/services/core/yaml.service.js +123 -37
  112. package/dist/services/core/yaml.service.js.map +1 -1
  113. package/dist/services/interfaces/camera-stream.dto.js +4 -4
  114. package/dist/services/interfaces/camera-stream.dto.js.map +1 -1
  115. package/dist/services/interfaces/floor.dto.js +6 -6
  116. package/dist/services/interfaces/floor.dto.js.map +1 -1
  117. package/dist/services/interfaces/print-completion.dto.js +3 -3
  118. package/dist/services/interfaces/print-completion.dto.js.map +1 -1
  119. package/dist/services/interfaces/printer-group.dto.js +3 -3
  120. package/dist/services/interfaces/printer-group.dto.js.map +1 -1
  121. package/dist/services/interfaces/printer.dto.js +3 -3
  122. package/dist/services/interfaces/printer.dto.js.map +1 -1
  123. package/dist/services/interfaces/settings.dto.js.map +1 -1
  124. package/dist/services/interfaces/user.dto.js +3 -3
  125. package/dist/services/interfaces/user.dto.js.map +1 -1
  126. package/dist/services/mongoose/camera-stream.service.js +1 -2
  127. package/dist/services/mongoose/camera-stream.service.js.map +1 -1
  128. package/dist/services/mongoose/floor.service.js +1 -1
  129. package/dist/services/mongoose/floor.service.js.map +1 -1
  130. package/dist/services/mongoose/permission.service.js.map +1 -1
  131. package/dist/services/mongoose/print-completion.service.js.map +1 -1
  132. package/dist/services/mongoose/printer.service.js.map +1 -1
  133. package/dist/services/mongoose/refresh-token.service.js.map +1 -1
  134. package/dist/services/mongoose/role.service.js +1 -2
  135. package/dist/services/mongoose/role.service.js.map +1 -1
  136. package/dist/services/mongoose/settings.service.js.map +1 -1
  137. package/dist/services/mongoose/user.service.js +7 -0
  138. package/dist/services/mongoose/user.service.js.map +1 -1
  139. package/dist/services/moonraker/constants/moonraker-event.dto.js +3 -3
  140. package/dist/services/moonraker/constants/moonraker-event.dto.js.map +1 -1
  141. package/dist/services/moonraker/dto/objects/idle-timeout.dto.js +3 -3
  142. package/dist/services/moonraker/dto/objects/idle-timeout.dto.js.map +1 -1
  143. package/dist/services/moonraker/dto/objects/print-stats.dto.js +3 -3
  144. package/dist/services/moonraker/dto/objects/print-stats.dto.js.map +1 -1
  145. package/dist/services/moonraker/dto/objects/printer-objects-list.dto.js +3 -3
  146. package/dist/services/moonraker/dto/objects/printer-objects-list.dto.js.map +1 -1
  147. package/dist/services/moonraker/dto/printer-info.dto.js +3 -3
  148. package/dist/services/moonraker/dto/printer-info.dto.js.map +1 -1
  149. package/dist/services/moonraker/dto/server-history/job.dto.js +3 -3
  150. package/dist/services/moonraker/dto/server-history/job.dto.js.map +1 -1
  151. package/dist/services/moonraker/dto/websocket/methods.js +3 -3
  152. package/dist/services/moonraker/dto/websocket/methods.js.map +1 -1
  153. package/dist/services/moonraker/dto/websocket/notify-update-response.params.js +3 -3
  154. package/dist/services/moonraker/dto/websocket/notify-update-response.params.js.map +1 -1
  155. package/dist/services/moonraker/moonraker-websocket.adapter.js +13 -13
  156. package/dist/services/moonraker/moonraker-websocket.adapter.js.map +1 -1
  157. package/dist/services/moonraker/moonraker.client.js.map +1 -1
  158. package/dist/services/moonraker.api.js.map +1 -1
  159. package/dist/services/octoprint/constants/octoprint-service.constants.js +7 -7
  160. package/dist/services/octoprint/constants/octoprint-service.constants.js.map +1 -1
  161. package/dist/services/octoprint/constants/octoprint-websocket.constants.js +3 -3
  162. package/dist/services/octoprint/constants/octoprint-websocket.constants.js.map +1 -1
  163. package/dist/services/octoprint/dto/octoprint-event.dto.js +4 -4
  164. package/dist/services/octoprint/dto/octoprint-event.dto.js.map +1 -1
  165. package/dist/services/octoprint/octoprint-websocket.adapter.js +17 -17
  166. package/dist/services/octoprint/octoprint-websocket.adapter.js.map +1 -1
  167. package/dist/services/octoprint/octoprint.client.js.map +1 -1
  168. package/dist/services/octoprint/utils/api.utils.js +3 -3
  169. package/dist/services/octoprint/utils/api.utils.js.map +1 -1
  170. package/dist/services/octoprint.api.js.map +1 -1
  171. package/dist/services/orm/base.service.js.map +1 -1
  172. package/dist/services/orm/floor.service.js +1 -1
  173. package/dist/services/orm/floor.service.js.map +1 -1
  174. package/dist/services/orm/permission.service.js.map +1 -1
  175. package/dist/services/orm/print-completion.service.js.map +1 -1
  176. package/dist/services/orm/printer-group.service.js.map +1 -1
  177. package/dist/services/orm/printer.service.js.map +1 -1
  178. package/dist/services/orm/refresh-token.service.js.map +1 -1
  179. package/dist/services/orm/role.service.js +2 -2
  180. package/dist/services/orm/role.service.js.map +1 -1
  181. package/dist/services/orm/settings.service.js +0 -4
  182. package/dist/services/orm/settings.service.js.map +1 -1
  183. package/dist/services/orm/user.service.js +8 -0
  184. package/dist/services/orm/user.service.js.map +1 -1
  185. package/dist/services/printer-api.factory.js +7 -1
  186. package/dist/services/printer-api.factory.js.map +1 -1
  187. package/dist/services/printer-api.interface.js +11 -6
  188. package/dist/services/printer-api.interface.js.map +1 -1
  189. package/dist/services/prusa-link/prusa-link-http-polling.adapter.js +2 -4
  190. package/dist/services/prusa-link/prusa-link-http-polling.adapter.js.map +1 -1
  191. package/dist/services/prusa-link/prusa-link.api.js +1 -2
  192. package/dist/services/prusa-link/prusa-link.api.js.map +1 -1
  193. package/dist/services/socket.factory.js +3 -0
  194. package/dist/services/socket.factory.js.map +1 -1
  195. package/dist/services/task-manager.service.js +1 -2
  196. package/dist/services/task-manager.service.js.map +1 -1
  197. package/dist/services/validators/floor-service.validation.js +10 -10
  198. package/dist/services/validators/floor-service.validation.js.map +1 -1
  199. package/dist/services/validators/printer-service.validation.js +15 -15
  200. package/dist/services/validators/printer-service.validation.js.map +1 -1
  201. package/dist/services/validators/settings-service.validation.js +21 -14
  202. package/dist/services/validators/settings-service.validation.js.map +1 -1
  203. package/dist/services/validators/user-service.validation.js +3 -3
  204. package/dist/services/validators/user-service.validation.js.map +1 -1
  205. package/dist/services/validators/yaml-service.validation.js +33 -7
  206. package/dist/services/validators/yaml-service.validation.js.map +1 -1
  207. package/dist/shared/default-http-client.builder.js.map +1 -1
  208. package/dist/shared/runtime-settings.migration.js +1 -0
  209. package/dist/shared/runtime-settings.migration.js.map +1 -1
  210. package/dist/shared/websocket.adapter.js.map +1 -1
  211. package/dist/state/file-upload-tracker.cache.js +1 -2
  212. package/dist/state/file-upload-tracker.cache.js.map +1 -1
  213. package/dist/state/file.cache.js.map +1 -1
  214. package/dist/state/floor.store.js.map +1 -1
  215. package/dist/state/printer-events.cache.js +13 -0
  216. package/dist/state/printer-events.cache.js.map +1 -1
  217. package/dist/state/printer-files.store.js.map +1 -1
  218. package/dist/state/printer-socket.store.js +1 -2
  219. package/dist/state/printer-socket.store.js.map +1 -1
  220. package/dist/state/printer-thumbnail.cache.js +3 -3
  221. package/dist/state/printer-thumbnail.cache.js.map +1 -1
  222. package/dist/state/printer.cache.js.map +1 -1
  223. package/dist/state/settings.store.js +14 -6
  224. package/dist/state/settings.store.js.map +1 -1
  225. package/dist/state/socket-io.gateway.js +3 -3
  226. package/dist/state/socket-io.gateway.js.map +1 -1
  227. package/dist/state/test-printer-socket.store.js.map +1 -1
  228. package/dist/tasks/boot.task.js.map +1 -1
  229. package/dist/tasks/client-bundle.task.js.map +1 -1
  230. package/dist/tasks/print-completion.socketio.task.js +1 -2
  231. package/dist/tasks/print-completion.socketio.task.js.map +1 -1
  232. package/dist/tasks/printer-file-clean.task.js.map +1 -1
  233. package/dist/tasks/printer-websocket-restore.task.js.map +1 -1
  234. package/dist/tasks/printer-websocket.task.js.map +1 -1
  235. package/dist/tasks/socketio.task.js.map +1 -1
  236. package/dist/tasks/software-update.task.js.map +1 -1
  237. package/dist/tasks.js +3 -3
  238. package/dist/tasks.js.map +1 -1
  239. package/dist/utils/array.util.js +3 -3
  240. package/dist/utils/array.util.js.map +1 -1
  241. package/dist/utils/crypto.utils.js +3 -3
  242. package/dist/utils/crypto.utils.js.map +1 -1
  243. package/dist/utils/env.utils.js +6 -6
  244. package/dist/utils/env.utils.js.map +1 -1
  245. package/dist/utils/fs.utils.js +4 -4
  246. package/dist/utils/fs.utils.js.map +1 -1
  247. package/dist/utils/gcode.utils.js +3 -3
  248. package/dist/utils/gcode.utils.js.map +1 -1
  249. package/dist/utils/pretty-print.utils.js +3 -3
  250. package/dist/utils/pretty-print.utils.js.map +1 -1
  251. package/dist/utils/semver.utils.js +3 -3
  252. package/dist/utils/semver.utils.js.map +1 -1
  253. package/dist/utils/url.utils.js +3 -3
  254. package/dist/utils/url.utils.js.map +1 -1
  255. package/package.json +48 -41
  256. package/dist/utils/printer-type.utils.js +0 -32
  257. package/dist/utils/printer-type.utils.js.map +0 -1
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "BambuFtpAdapter", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return BambuFtpAdapter;
9
+ }
10
+ });
11
+ const _basicftp = require("basic-ftp");
12
+ const _eventconstants = require("../../constants/event.constants");
13
+ const _nodefs = require("node:fs");
14
+ const _nodeos = require("node:os");
15
+ const _nodepath = require("node:path");
16
+ class BambuFtpAdapter {
17
+ settingsStore;
18
+ eventEmitter2;
19
+ logger;
20
+ ftpClient = null;
21
+ host = null;
22
+ accessCode = null;
23
+ isConnecting = false;
24
+ constructor(settingsStore, loggerFactory, eventEmitter2){
25
+ this.settingsStore = settingsStore;
26
+ this.eventEmitter2 = eventEmitter2;
27
+ this.settingsStore = settingsStore;
28
+ this.eventEmitter2 = eventEmitter2;
29
+ this.logger = loggerFactory(BambuFtpAdapter.name);
30
+ }
31
+ async connect(host, accessCode) {
32
+ if (this.ftpClient && !this.ftpClient.closed) {
33
+ this.logger.debug("FTP already connected");
34
+ return;
35
+ }
36
+ if (this.isConnecting) {
37
+ throw new Error("Connection already in progress");
38
+ }
39
+ const sanitizedHost = this.sanitizeHost(host);
40
+ const sanitizedAccessCode = this.sanitizeAccessCode(accessCode);
41
+ this.host = sanitizedHost;
42
+ this.accessCode = sanitizedAccessCode;
43
+ this.isConnecting = true;
44
+ const timeout = this.settingsStore.getTimeoutSettings().apiTimeout;
45
+ this.logger.log(`Connecting to Bambu FTP at ${sanitizedHost}:990`);
46
+ try {
47
+ this.ftpClient = new _basicftp.Client(timeout);
48
+ this.ftpClient.ftp.verbose = false;
49
+ await this.ftpClient.access({
50
+ host: sanitizedHost,
51
+ port: 990,
52
+ user: "bblp",
53
+ password: sanitizedAccessCode,
54
+ secure: true,
55
+ secureOptions: {
56
+ rejectUnauthorized: false,
57
+ minVersion: 'TLSv1.2',
58
+ maxVersion: 'TLSv1.3'
59
+ }
60
+ });
61
+ this.isConnecting = false;
62
+ this.logger.log("FTP connected successfully");
63
+ } catch (error) {
64
+ this.isConnecting = false;
65
+ this.cleanup();
66
+ this.logger.error("FTP connection failed:", error);
67
+ throw error;
68
+ }
69
+ }
70
+ async disconnect() {
71
+ if (!this.ftpClient) {
72
+ return;
73
+ }
74
+ this.logger.log("Disconnecting FTP");
75
+ try {
76
+ this.ftpClient.close();
77
+ } catch (error) {
78
+ this.logger.error("Error closing FTP:", error);
79
+ } finally{
80
+ this.cleanup();
81
+ }
82
+ }
83
+ async listFiles(dirPath = "/") {
84
+ this.ensureConnected();
85
+ try {
86
+ const files = await this.ftpClient.list(dirPath);
87
+ this.logger.debug(`Listed ${files.length} files in ${dirPath}`);
88
+ return files;
89
+ } catch (error) {
90
+ this.logger.error(`Failed to list files in ${dirPath}:`, error);
91
+ throw error;
92
+ }
93
+ }
94
+ async uploadFile(fileBuffer, filename, progressToken) {
95
+ this.ensureConnected();
96
+ const remotePath = `/sdcard/${filename}`;
97
+ const tempPath = (0, _nodepath.join)((0, _nodeos.tmpdir)(), `bambu-upload-${Date.now()}-${filename}`);
98
+ try {
99
+ (0, _nodefs.writeFileSync)(tempPath, fileBuffer);
100
+ this.logger.debug(`Wrote temp file: ${tempPath}`);
101
+ if (progressToken) {
102
+ this.ftpClient.trackProgress((info)=>{
103
+ this.eventEmitter2.emit(`${(0, _eventconstants.uploadProgressEvent)(progressToken)}`, progressToken, {
104
+ loaded: info.bytes,
105
+ total: info.bytesOverall
106
+ });
107
+ });
108
+ }
109
+ this.logger.log(`Uploading ${filename} to ${remotePath}`);
110
+ await this.ftpClient.uploadFrom(tempPath, remotePath);
111
+ this.ftpClient.trackProgress();
112
+ if (progressToken) {
113
+ this.eventEmitter2.emit(`${(0, _eventconstants.uploadDoneEvent)(progressToken)}`, progressToken);
114
+ }
115
+ this.logger.log(`File uploaded successfully: ${filename}`);
116
+ } catch (error) {
117
+ if (progressToken) {
118
+ this.eventEmitter2.emit(`${(0, _eventconstants.uploadFailedEvent)(progressToken)}`, progressToken, error?.message);
119
+ }
120
+ this.logger.error(`Upload failed for ${filename}:`, error);
121
+ throw error;
122
+ } finally{
123
+ try {
124
+ (0, _nodefs.unlinkSync)(tempPath);
125
+ this.logger.debug(`Cleaned up temp file: ${tempPath}`);
126
+ } catch (cleanupError) {
127
+ this.logger.warn(`Failed to cleanup temp file ${tempPath}:`, cleanupError);
128
+ }
129
+ }
130
+ }
131
+ async downloadFile(remotePath, localPath) {
132
+ this.ensureConnected();
133
+ try {
134
+ this.logger.log(`Downloading ${remotePath} to ${localPath}`);
135
+ await this.ftpClient.downloadTo(localPath, remotePath);
136
+ this.logger.log(`File downloaded successfully: ${remotePath}`);
137
+ } catch (error) {
138
+ this.logger.error(`Download failed for ${remotePath}:`, error);
139
+ throw error;
140
+ }
141
+ }
142
+ async deleteFile(remotePath) {
143
+ this.ensureConnected();
144
+ try {
145
+ this.logger.log(`Deleting file: ${remotePath}`);
146
+ await this.ftpClient.remove(remotePath);
147
+ this.logger.log(`File deleted successfully: ${remotePath}`);
148
+ } catch (error) {
149
+ this.logger.error(`Delete failed for ${remotePath}:`, error);
150
+ throw error;
151
+ }
152
+ }
153
+ get isConnected() {
154
+ return this.ftpClient != null && !this.ftpClient.closed;
155
+ }
156
+ ensureConnected() {
157
+ if (!this.isConnected) {
158
+ throw new Error("FTP not connected. Call connect() first.");
159
+ }
160
+ }
161
+ cleanup() {
162
+ this.ftpClient = null;
163
+ }
164
+ sanitizeHost(host) {
165
+ if (!host?.length) {
166
+ throw new Error("Host must be a non-empty string");
167
+ }
168
+ const trimmed = host.trim();
169
+ if (trimmed.length === 0) {
170
+ throw new Error("Host cannot be empty");
171
+ }
172
+ const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
173
+ const hostnamePattern = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
174
+ if (!ipv4Pattern.test(trimmed) && !hostnamePattern.test(trimmed)) {
175
+ throw new Error("Invalid host format. Must be a valid IP address or hostname");
176
+ }
177
+ if (ipv4Pattern.test(trimmed)) {
178
+ const parts = trimmed.split(".").map(Number);
179
+ if (parts.some((part)=>part < 0 || part > 255)) {
180
+ throw new Error("Invalid IPv4 address. Octets must be between 0 and 255");
181
+ }
182
+ }
183
+ return trimmed;
184
+ }
185
+ sanitizeAccessCode(accessCode) {
186
+ if (!accessCode?.length) {
187
+ throw new Error("Access code must be a non-empty string");
188
+ }
189
+ const trimmed = accessCode.trim();
190
+ if (trimmed.length === 0) {
191
+ throw new Error("Access code cannot be empty");
192
+ }
193
+ if (trimmed.length < 4 || trimmed.length > 32) {
194
+ throw new Error("Access code must be between 4 and 32 characters");
195
+ }
196
+ const alphanumericPattern = /^[a-zA-Z0-9]+$/;
197
+ if (!alphanumericPattern.test(trimmed)) {
198
+ throw new Error("Access code must contain only alphanumeric characters");
199
+ }
200
+ return trimmed;
201
+ }
202
+ }
203
+
204
+ //# sourceMappingURL=bambu-ftp.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/bambu/bambu-ftp.adapter.ts"],"names":["BambuFtpAdapter","logger","ftpClient","host","accessCode","isConnecting","settingsStore","loggerFactory","eventEmitter2","name","connect","closed","debug","Error","sanitizedHost","sanitizeHost","sanitizedAccessCode","sanitizeAccessCode","timeout","getTimeoutSettings","apiTimeout","log","Client","ftp","verbose","access","port","user","password","secure","secureOptions","rejectUnauthorized","minVersion","maxVersion","error","cleanup","disconnect","close","listFiles","dirPath","ensureConnected","files","list","length","uploadFile","fileBuffer","filename","progressToken","remotePath","tempPath","join","tmpdir","Date","now","writeFileSync","trackProgress","info","emit","uploadProgressEvent","loaded","bytes","total","bytesOverall","uploadFrom","uploadDoneEvent","uploadFailedEvent","message","unlinkSync","cleanupError","warn","downloadFile","localPath","downloadTo","deleteFile","remove","isConnected","trimmed","trim","ipv4Pattern","hostnamePattern","test","parts","split","map","Number","some","part","alphanumericPattern"],"mappings":"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"}
@@ -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}:1883`;
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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"}