node-red-contrib-my-tools 1.0.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.
Files changed (67) hide show
  1. package/README.txt +69 -0
  2. package/node-red-contrib-mysql-extended-test/mysql-extended.html +443 -0
  3. package/node-red-contrib-mysql-extended-test/mysql-extended.js +355 -0
  4. package/node-red-contrib-rfid-helper/rfid-lazy.html +153 -0
  5. package/node-red-contrib-rfid-helper/rfid-lazy.js +361 -0
  6. package/node-red-contrib-s7-plus/LICENSE +235 -0
  7. package/node-red-contrib-s7-plus/README.md +141 -0
  8. package/node-red-contrib-s7-plus/examples/read-multiple-values-flow.json +346 -0
  9. package/node-red-contrib-s7-plus/examples/read-write-test-flow.json +172 -0
  10. package/node-red-contrib-s7-plus/examples/write-single-values-flow.json +5583 -0
  11. package/node-red-contrib-s7-plus/lib/s7plus/browse/README.md +72 -0
  12. package/node-red-contrib-s7-plus/lib/s7plus/browse/areas.js +36 -0
  13. package/node-red-contrib-s7-plus/lib/s7plus/browse/datatypes.js +91 -0
  14. package/node-red-contrib-s7-plus/lib/s7plus/browse/flat-browser.js +433 -0
  15. package/node-red-contrib-s7-plus/lib/s7plus/browse/index.js +22 -0
  16. package/node-red-contrib-s7-plus/lib/s7plus/browse/lazy.js +397 -0
  17. package/node-red-contrib-s7-plus/lib/s7plus/browse/node-id.js +22 -0
  18. package/node-red-contrib-s7-plus/lib/s7plus/browse/resolve-symbolic.js +181 -0
  19. package/node-red-contrib-s7-plus/lib/s7plus/browse/vte-helpers.js +49 -0
  20. package/node-red-contrib-s7-plus/lib/s7plus/buffer-stream.js +96 -0
  21. package/node-red-contrib-s7-plus/lib/s7plus/client.js +1238 -0
  22. package/node-red-contrib-s7-plus/lib/s7plus/constants.js +155 -0
  23. package/node-red-contrib-s7-plus/lib/s7plus/crc/index.js +3 -0
  24. package/node-red-contrib-s7-plus/lib/s7plus/crc/s7-crc32.js +70 -0
  25. package/node-red-contrib-s7-plus/lib/s7plus/crc/symbol-crc.js +271 -0
  26. package/node-red-contrib-s7-plus/lib/s7plus/debug.js +88 -0
  27. package/node-red-contrib-s7-plus/lib/s7plus/explore-result.js +41 -0
  28. package/node-red-contrib-s7-plus/lib/s7plus/item-address.js +55 -0
  29. package/node-red-contrib-s7-plus/lib/s7plus/pdu-explore.js +77 -0
  30. package/node-red-contrib-s7-plus/lib/s7plus/pdu-messages.js +359 -0
  31. package/node-red-contrib-s7-plus/lib/s7plus/pobject.js +197 -0
  32. package/node-red-contrib-s7-plus/lib/s7plus/pvalue-codec.js +435 -0
  33. package/node-red-contrib-s7-plus/lib/s7plus/pvalue.js +653 -0
  34. package/node-red-contrib-s7-plus/lib/s7plus/pvar-lists.js +336 -0
  35. package/node-red-contrib-s7-plus/lib/s7plus/read-result.js +91 -0
  36. package/node-red-contrib-s7-plus/lib/s7plus/s7p.js +266 -0
  37. package/node-red-contrib-s7-plus/lib/s7plus/tag-routing.js +30 -0
  38. package/node-red-contrib-s7-plus/lib/s7plus/transport/cotp-stream.js +335 -0
  39. package/node-red-contrib-s7-plus/lib/s7plus/transport/s7-transport.js +335 -0
  40. package/node-red-contrib-s7-plus/nodes/icons/s7complus.png +0 -0
  41. package/node-red-contrib-s7-plus/nodes/icons/s7complus.svg +17 -0
  42. package/node-red-contrib-s7-plus/nodes/s7complus-endpoint.js +825 -0
  43. package/node-red-contrib-s7-plus/nodes/s7complus-explore.js +91 -0
  44. package/node-red-contrib-s7-plus/nodes/s7complus-in.js +255 -0
  45. package/node-red-contrib-s7-plus/nodes/s7complus-out.js +182 -0
  46. package/node-red-contrib-s7-plus/nodes/s7complus.html +1541 -0
  47. package/node-red-contrib-s7-plus/nodes/s7complus.js +10 -0
  48. package/node-red-contrib-s7-plus/package.json +50 -0
  49. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Arrays.db +17 -0
  50. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Binary.db +16 -0
  51. package/node-red-contrib-s7-plus/plc/s7-1500/DB_BitStrings.db +36 -0
  52. package/node-red-contrib-s7-plus/plc/s7-1500/DB_CharacterStrings.db +42 -0
  53. package/node-red-contrib-s7-plus/plc/s7-1500/DB_DateAndTime.db +70 -0
  54. package/node-red-contrib-s7-plus/plc/s7-1500/DB_FloatingPoint.db +42 -0
  55. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Integers.db +72 -0
  56. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Timers.db +40 -0
  57. package/node-red-contrib-s7-plus/scripts/example-flow-shared.js +39 -0
  58. package/node-red-contrib-s7-plus/scripts/generate-read-multiple-flow.js +331 -0
  59. package/node-red-contrib-s7-plus/scripts/generate-rw-test-flow.js +690 -0
  60. package/node-red-contrib-s7-plus/scripts/generate-write-flow.js +476 -0
  61. package/node-red-contrib-s7-plus/scripts/layout-write-flow.js +156 -0
  62. package/node-red-contrib-s7-plus/scripts/run-tests.js +16 -0
  63. package/node-red-flowgobal-change/variable-change.html +425 -0
  64. package/node-red-flowgobal-change/variable-change.js +92 -0
  65. package/node-red-ui_media_viewer/ui_media_viewer.html +87 -0
  66. package/node-red-ui_media_viewer/ui_media_viewer.js +136 -0
  67. package/package.json +12 -0
@@ -0,0 +1,136 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ module.exports = function(RED) {
5
+ let ui = undefined;
6
+ try {
7
+ ui = RED.require("node-red-dashboard")(RED);
8
+ } catch (e) {
9
+ RED.log.warn("ui_media_viewer 需要安裝 node-red-dashboard 才能運作。");
10
+ }
11
+
12
+ // 全域共用的 API 路由
13
+ RED.httpNode.get('/ui_media_viewer_api', function(req, res) {
14
+ let filePath = req.query.f;
15
+
16
+ if (filePath) {
17
+ filePath = filePath.replace(/^["']|["']$/g, '').trim();
18
+ }
19
+
20
+ if (filePath && fs.existsSync(filePath)) {
21
+ res.sendFile(filePath);
22
+ } else {
23
+ res.status(404).send("File not found");
24
+ }
25
+ });
26
+
27
+ function UIMediaViewerNode(config) {
28
+ RED.nodes.createNode(this, config);
29
+ const node = this;
30
+
31
+ if (!ui) return;
32
+
33
+ const htmlTemplate = `
34
+ <div id="media-container-{{$id}}" style="width:100%; height:100%; display:flex; justify-content:center; align-items:center; overflow:hidden;">
35
+ </div>
36
+ `;
37
+
38
+ const done = ui.addWidget({
39
+ node: node,
40
+ group: config.group,
41
+ width: config.width,
42
+ height: config.height,
43
+ format: htmlTemplate,
44
+ templateScope: "local",
45
+ order: config.order,
46
+ emitOnlyNewValues: false,
47
+ forwardInputMessages: false,
48
+ storeFrontEndInputAsState: false,
49
+
50
+ beforeEmit: function(msg, value) {
51
+ // 處理消失(Reset)
52
+ if (msg.payload === "reset" || msg.payload === "clear" || msg.reset === true) {
53
+ msg.payload = "CLEAR_MEDIA";
54
+ return { msg: msg };
55
+ }
56
+
57
+ // 【極致容錯的輸入判斷】
58
+ let filePath = config.filepath;
59
+
60
+ if (msg.filepath && typeof msg.filepath === 'string' && msg.filepath.trim() !== '') {
61
+ filePath = msg.filepath;
62
+ }
63
+ else if (typeof msg.payload === 'string' && msg.payload.trim() !== '' && msg.payload !== 'CLEAR_MEDIA') {
64
+ filePath = msg.payload;
65
+ }
66
+ // 新增:如果使用者傳遞了 JSON 物件 msg.payload.filepath 也能抓到
67
+ else if (msg.payload && typeof msg.payload.filepath === 'string' && msg.payload.filepath.trim() !== '') {
68
+ filePath = msg.payload.filepath;
69
+ }
70
+
71
+ // 清除路徑頭尾引號與多餘的空白換行
72
+ if (filePath) {
73
+ filePath = filePath.replace(/^["']|["']$/g, '').trim();
74
+ }
75
+
76
+ let mType = msg.mediaType || config.mediaType || "image";
77
+ let dWidth = config.displayWidth || "100%";
78
+
79
+ if (!filePath) {
80
+ node.error("未設定檔案路徑或路徑無效", msg);
81
+ msg.payload = "CLEAR_MEDIA";
82
+ return { msg: msg };
83
+ }
84
+
85
+ // 自動偵測副檔名
86
+ let ext = filePath.split('.').pop().toLowerCase();
87
+ if (['mp4', 'webm', 'mov'].includes(ext)) {
88
+ mType = "video";
89
+ } else if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)) {
90
+ mType = "image";
91
+ }
92
+
93
+ let ts = new Date().getTime();
94
+ let fileUrl = `/ui_media_viewer_api?ts=${ts}&f=${encodeURIComponent(filePath)}`;
95
+
96
+ let mediaStyle = `max-width:100%; max-height:100%; object-fit:contain;`;
97
+ if (dWidth && dWidth !== "100%") {
98
+ mediaStyle += ` width:${dWidth};`;
99
+ } else {
100
+ mediaStyle += ` width:100%;`;
101
+ }
102
+
103
+ let renderHtml = "";
104
+ if (mType === "video") {
105
+ renderHtml = `<video src="${fileUrl}" style="${mediaStyle}" controls autoplay muted loop type="video/mp4"></video>`;
106
+ } else {
107
+ renderHtml = `<img src="${fileUrl}" style="${mediaStyle}">`;
108
+ }
109
+
110
+ msg.payload = renderHtml;
111
+ return { msg: msg };
112
+ },
113
+
114
+ initController: function($scope, events) {
115
+ $scope.$watch('msg', function(msg) {
116
+ if (!msg) return;
117
+
118
+ var container = $('#media-container-' + $scope.$id);
119
+ if (msg.payload === "CLEAR_MEDIA") {
120
+ container.html('');
121
+ } else if (msg.payload) {
122
+ container.html(msg.payload);
123
+ }
124
+ });
125
+ }
126
+ });
127
+
128
+ node.on("close", function() {
129
+ if (done) {
130
+ done();
131
+ }
132
+ });
133
+ }
134
+
135
+ RED.nodes.registerType("ui_media_viewer", UIMediaViewerNode);
136
+ };
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "node-red-contrib-my-tools",
3
+ "version": "1.0.0",
4
+ "node-red": {
5
+ "nodes": {
6
+ "my-mysql-extended": "node-red-contrib-mysql-extended-test/mysql-extended.js",
7
+ "rfid-helper": "node-red-contrib-rfid-helper/rfid-lazy.js",
8
+ "node-red-flowgobal-change": "node-red-flowgobal-change/variable-change.js",
9
+ "node-red-ui_media_viewer" : "node-red-ui_media_viewer/ui_media_viewer.js"
10
+ }
11
+ }
12
+ }