node-red-contrib-symi-modbus 2.7.5 → 2.7.7

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.
@@ -5,15 +5,20 @@
5
5
  defaults: {
6
6
  name: {value: "从站开关"},
7
7
  // RS-485连接配置(共享配置节点)
8
- serialPortConfig: {value: "", type: "serial-port-config", required: true},
8
+ serialPortConfig: {value: "", type: "serial-port-config", required: false},
9
9
  // MQTT配置(可选)
10
10
  enableMqtt: {value: false}, // 默认不启用MQTT
11
11
  mqttServer: {value: "", type: "mqtt-server-config", required: false},
12
12
  // 开关面板配置
13
13
  switchBrand: {value: "symi"}, // 品牌选择
14
- buttonType: {value: "switch"}, // 按钮类型:switch=开关模式,scene=场景模式
14
+ buttonType: {value: "switch"}, // 按钮类型:switch=开关模式,scene=场景模式,mesh=Mesh模式
15
15
  switchId: {value: 0, validate: RED.validators.number()},
16
16
  buttonNumber: {value: 1, validate: RED.validators.number()},
17
+ // Mesh模式配置
18
+ meshMacAddress: {value: ""}, // Mesh设备MAC地址
19
+ meshShortAddress: {value: 0}, // Mesh设备短地址
20
+ meshButtonNumber: {value: 1, validate: RED.validators.number()}, // Mesh按键编号(1-6)
21
+ meshTotalButtons: {value: 1, validate: RED.validators.number()}, // Mesh开关总路数(1-6)
17
22
  // 映射到继电器
18
23
  targetSlaveAddress: {value: 10, validate: RED.validators.number()},
19
24
  targetCoilNumber: {value: 1, validate: RED.validators.number()} // 默认值改为1(显示为1路)
@@ -22,11 +27,21 @@
22
27
  outputs: 1,
23
28
  icon: "light.png",
24
29
  label: function() {
25
- // 显示时直接使用用户输入的路数(1-32)
26
- const coilDisplay = this.targetCoilNumber || 1;
27
- return this.name || `开关${this.switchId}-按钮${this.buttonNumber} 继电器${this.targetSlaveAddress}-${coilDisplay}路`;
30
+ if (this.buttonType === 'mesh') {
31
+ // Mesh模式显示
32
+ const mac = this.meshMacAddress || '未选择';
33
+ const btn = this.meshButtonNumber || 1;
34
+ const coilDisplay = this.targetCoilNumber || 1;
35
+ return this.name || `Mesh[${mac}]-按钮${btn} → 继电器${this.targetSlaveAddress}-${coilDisplay}路`;
36
+ } else {
37
+ // 开关模式和场景模式显示
38
+ const coilDisplay = this.targetCoilNumber || 1;
39
+ return this.name || `开关${this.switchId}-按钮${this.buttonNumber} → 继电器${this.targetSlaveAddress}-${coilDisplay}路`;
40
+ }
28
41
  },
29
42
  oneditprepare: function() {
43
+ const node = this;
44
+
30
45
  // MQTT开关控制显示/隐藏
31
46
  $("#node-input-enableMqtt").on("change", function() {
32
47
  if ($(this).is(":checked")) {
@@ -35,9 +50,139 @@
35
50
  $(".form-row-mqtt-slave").hide();
36
51
  }
37
52
  });
38
-
53
+
54
+ // 按钮类型切换控制显示/隐藏
55
+ $("#node-input-buttonType").on("change", function() {
56
+ const buttonType = $(this).val();
57
+ if (buttonType === 'mesh') {
58
+ // Mesh模式:显示Mesh配置,隐藏RS-485配置
59
+ $(".form-row-mesh").show();
60
+ $(".form-row-rs485").hide();
61
+ $("#btn-discover-mesh").show();
62
+ } else {
63
+ // 开关/场景模式:显示RS-485配置,隐藏Mesh配置
64
+ $(".form-row-mesh").hide();
65
+ $(".form-row-rs485").show();
66
+ $("#btn-discover-mesh").hide();
67
+ }
68
+ });
69
+
70
+ // Mesh设备发现按钮
71
+ $("#btn-discover-mesh").on("click", function() {
72
+ const serialPortConfig = $("#node-input-serialPortConfig").val();
73
+ if (!serialPortConfig) {
74
+ RED.notify("请先选择RS-485连接配置", "warning");
75
+ return;
76
+ }
77
+
78
+ // 禁用按钮,显示加载状态
79
+ $(this).prop("disabled", true).html('<i class="fa fa-spinner fa-spin"></i> 正在扫描...');
80
+
81
+ // 发送设备发现请求
82
+ $.ajax({
83
+ url: "symi-mesh/discover",
84
+ type: "POST",
85
+ data: JSON.stringify({
86
+ serialPortConfig: serialPortConfig
87
+ }),
88
+ contentType: "application/json",
89
+ success: function(devices) {
90
+ // 更新设备列表
91
+ const select = $("#node-input-meshMacAddress");
92
+ select.empty();
93
+ select.append('<option value="">请选择Mesh开关</option>');
94
+
95
+ devices.forEach(function(device) {
96
+ if (device.type === 0x01 && device.buttons > 0) {
97
+ // 只显示开关类型设备
98
+ const mac = device.mac;
99
+ const label = `${mac} (${device.buttons}路开关)`;
100
+ select.append(`<option value="${mac}" data-short-addr="${device.shortAddr}" data-buttons="${device.buttons}">${label}</option>`);
101
+ }
102
+ });
103
+
104
+ RED.notify(`发现 ${devices.length} 个Mesh设备`, "success");
105
+ $("#btn-discover-mesh").prop("disabled", false).html('<i class="fa fa-search"></i> 扫描设备');
106
+ },
107
+ error: function(xhr, status, error) {
108
+ RED.notify("设备发现失败: " + error, "error");
109
+ $("#btn-discover-mesh").prop("disabled", false).html('<i class="fa fa-search"></i> 扫描设备');
110
+ }
111
+ });
112
+ });
113
+
114
+ // Mesh设备选择变化时更新短地址和按钮数
115
+ $("#node-input-meshMacAddress").on("change", function() {
116
+ const selected = $(this).find("option:selected");
117
+ const shortAddr = selected.data("short-addr");
118
+ const buttons = selected.data("buttons");
119
+
120
+ if (shortAddr !== undefined) {
121
+ $("#node-input-meshShortAddress").val(shortAddr);
122
+ $("#node-input-meshTotalButtons").val(buttons);
123
+
124
+ // 更新按钮编号选项
125
+ const btnSelect = $("#node-input-meshButtonNumber");
126
+ btnSelect.empty();
127
+ for (let i = 1; i <= buttons; i++) {
128
+ btnSelect.append(`<option value="${i}">按钮 ${i}</option>`);
129
+ }
130
+ }
131
+ });
132
+
133
+ // 加载已保存的Mesh设备列表
134
+ function loadSavedMeshDevices() {
135
+ $.ajax({
136
+ url: "symi-mesh/devices",
137
+ type: "GET",
138
+ success: function(devices) {
139
+ if (devices && devices.length > 0) {
140
+ const select = $("#node-input-meshMacAddress");
141
+ select.empty();
142
+ select.append('<option value="">请选择Mesh开关</option>');
143
+
144
+ devices.forEach(function(device) {
145
+ if (device.type === 0x01 && device.buttons > 0) {
146
+ const mac = device.mac;
147
+ const label = `${mac} (${device.buttons}路开关)`;
148
+ const option = $(`<option value="${mac}" data-short-addr="${device.shortAddr}" data-buttons="${device.buttons}">${label}</option>`);
149
+ select.append(option);
150
+
151
+ // 如果是当前配置的设备,选中它
152
+ if (mac === node.meshMacAddress) {
153
+ option.prop("selected", true);
154
+ $("#node-input-meshShortAddress").val(device.shortAddr);
155
+ $("#node-input-meshTotalButtons").val(device.buttons);
156
+
157
+ // 更新按钮编号选项
158
+ const btnSelect = $("#node-input-meshButtonNumber");
159
+ btnSelect.empty();
160
+ for (let i = 1; i <= device.buttons; i++) {
161
+ const btnOption = $(`<option value="${i}">按钮 ${i}</option>`);
162
+ if (i === node.meshButtonNumber) {
163
+ btnOption.prop("selected", true);
164
+ }
165
+ btnSelect.append(btnOption);
166
+ }
167
+ }
168
+ }
169
+ });
170
+ }
171
+ },
172
+ error: function(xhr, status, error) {
173
+ console.log("加载Mesh设备列表失败: " + error);
174
+ }
175
+ });
176
+ }
177
+
39
178
  // 初始化显示状态
40
179
  $("#node-input-enableMqtt").trigger("change");
180
+ $("#node-input-buttonType").trigger("change");
181
+
182
+ // 如果是Mesh模式,加载已保存的设备列表
183
+ if (node.buttonType === 'mesh') {
184
+ loadSavedMeshDevices();
185
+ }
41
186
  }
42
187
  });
43
188
  </script>
@@ -119,16 +264,19 @@
119
264
  <div class="form-row">
120
265
  <label for="node-input-buttonType" style="width: 110px;"><i class="fa fa-cog"></i> 按钮类型</label>
121
266
  <select id="node-input-buttonType" style="width: 200px;">
122
- <option value="switch">开关按钮</option>
123
- <option value="scene">场景按钮</option>
267
+ <option value="switch">开关按钮(RS-485)</option>
268
+ <option value="scene">场景按钮(RS-485)</option>
269
+ <option value="mesh">Mesh开关(蓝牙Mesh)</option>
124
270
  </select>
125
271
  <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 3px;">
126
- <strong>开关按钮</strong>:灯光、插座等开关控制,有开/关状态<br>
127
- <strong>场景按钮</strong>:场景触发、一键全开/全关等,只触发动作
272
+ <strong>开关按钮</strong>:RS-485开关,有开/关状态<br>
273
+ <strong>场景按钮</strong>:RS-485场景触发<br>
274
+ <strong>Mesh开关</strong>:蓝牙Mesh开关(1-6路)
128
275
  </div>
129
276
  </div>
130
277
 
131
- <div class="form-row">
278
+ <!-- RS-485模式配置 -->
279
+ <div class="form-row form-row-rs485">
132
280
  <label for="node-input-switchId" style="width: 110px;"><i class="fa fa-id-card"></i> 开关ID</label>
133
281
  <input type="number" id="node-input-switchId" placeholder="0" min="0" max="255" style="width: 90px; padding: 5px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;">
134
282
  <span style="margin-left: 10px; color: #666; font-size: 12px;">物理面板地址:<strong>0-255</strong></span>
@@ -137,7 +285,7 @@
137
285
  </div>
138
286
  </div>
139
287
 
140
- <div class="form-row">
288
+ <div class="form-row form-row-rs485">
141
289
  <label for="node-input-buttonNumber" style="width: 110px;"><i class="fa fa-hand-pointer-o"></i> 按钮编号</label>
142
290
  <select id="node-input-buttonNumber" style="width: 150px;">
143
291
  <option value="1">按钮 1</option>
@@ -151,6 +299,42 @@
151
299
  </select>
152
300
  <span style="margin-left: 10px; font-size: 11px; color: #666; font-style: italic;">面板物理按键</span>
153
301
  </div>
302
+
303
+ <!-- Mesh模式配置 -->
304
+ <div class="form-row form-row-mesh" style="display: none;">
305
+ <button type="button" id="btn-discover-mesh" class="red-ui-button" style="margin-left: 110px;">
306
+ <i class="fa fa-search"></i> 扫描设备
307
+ </button>
308
+ <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 5px;">
309
+ 点击扫描按钮自动发现Mesh网关中的所有开关设备
310
+ </div>
311
+ </div>
312
+
313
+ <div class="form-row form-row-mesh" style="display: none;">
314
+ <label for="node-input-meshMacAddress" style="width: 110px;"><i class="fa fa-bluetooth"></i> Mesh设备</label>
315
+ <select id="node-input-meshMacAddress" style="width: 300px;">
316
+ <option value="">请选择Mesh开关</option>
317
+ </select>
318
+ <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 3px;">
319
+ 选择要控制的Mesh开关设备(MAC地址)
320
+ </div>
321
+ </div>
322
+
323
+ <div class="form-row form-row-mesh" style="display: none;">
324
+ <label for="node-input-meshButtonNumber" style="width: 110px;"><i class="fa fa-hand-pointer-o"></i> 按钮编号</label>
325
+ <select id="node-input-meshButtonNumber" style="width: 150px;">
326
+ <option value="1">按钮 1</option>
327
+ <option value="2">按钮 2</option>
328
+ <option value="3">按钮 3</option>
329
+ <option value="4">按钮 4</option>
330
+ <option value="5">按钮 5</option>
331
+ <option value="6">按钮 6</option>
332
+ </select>
333
+ <span style="margin-left: 10px; font-size: 11px; color: #666; font-style: italic;">Mesh开关按键(1-6路)</span>
334
+ </div>
335
+
336
+ <input type="hidden" id="node-input-meshShortAddress">
337
+ <input type="hidden" id="node-input-meshTotalButtons">
154
338
 
155
339
  <!-- 映射到继电器配置 -->
156
340
  <hr style="margin: 15px 0; border: 0; border-top: 2px solid #e0e0e0;">