addtag,removetag in meshctrl.js #7723
Signed-off-by: si458 <simonsmith5521@gmail.com>
si458 committed
Apr 4, 2026 at 20:48 UTC
6c376c30c948b985ea198a351fcf2860e13bfce9
2 files changed
+69
-14
meshctrl.js
+63
-14
@@ -865,6 +865,8 @@ if (args['_'].length == 0) {
865
case 'editdevice': {
866
console.log("Change information about a device, Example usages:\r\n");
867
console.log(winRemoveSingleQuotes(" MeshCtrl EditDevice --id 'deviceid' --name 'device1'"));
868
+ console.log(winRemoveSingleQuotes(" MeshCtrl EditDevice --id 'deviceid' --addtag 'newtag'"));
869
+ console.log(winRemoveSingleQuotes(" MeshCtrl EditDevice --id 'deviceid' --removetag 'oldtag'"));
870
console.log("\r\nRequired arguments:\r\n");
871
if (process.platform == 'win32') {
872
console.log(" --id [deviceid] - The device identifier.");
@@ -873,13 +875,17 @@ if (args['_'].length == 0) {
875
}
876
console.log("\r\nOptional arguments:\r\n");
877
if (process.platform == 'win32') {
876
- console.log(" --name [name] - Change device name.");
877
- console.log(" --desc [description] - Change device description.");
878
- console.log(" --tags [tag1,tags2] - Change device tags.");
878
+ console.log(" --name [name] - Change device name.");
879
+ console.log(" --desc [description] - Change device description.");
880
+ console.log(" --tags [tag1,tag2] - Set device tags (replaces all existing tags).");
881
+ console.log(" --addtag [tag1,tag2] - Add tags to existing tags.");
882
+ console.log(" --removetag [tag1,tag2] - Remove tags from existing tags.");
883
} else {
880
- console.log(" --name '[name]' - Change device name.");
881
- console.log(" --desc '[description]' - Change device description.");
882
- console.log(" --tags '[tag1,tags2]' - Change device tags.");
884
+ console.log(" --name '[name]' - Change device name.");
885
+ console.log(" --desc '[description]' - Change device description.");
886
+ console.log(" --tags '[tag1,tag2]' - Set device tags (replaces all existing tags).");
887
+ console.log(" --addtag '[tag1,tag2]' - Add tags to existing tags.");
888
+ console.log(" --removetag '[tag1,tag2]' - Remove tags from existing tags.");
889
}
890
console.log(" --icon [number] - Change the device icon (1 to 8).");
891
console.log(" --consent [flags] - Sum of the following numbers:");
@@ -1728,14 +1734,20 @@ function serverConnect() {
1734
break;
1735
}
1736
case 'editdevice': {
1731
- var op = { action: 'changedevice', nodeid: args.id, responseid: 'meshctrl' };
1732
- if (typeof args.name == 'string') { op.name = args.name; }
1733
- if (typeof args.name == 'number') { op.name = '' + args.name; }
1734
- if (args.desc) { if (args.desc === true) { op.desc = ''; } else if (typeof args.desc == 'string') { op.desc = args.desc; } else if (typeof args.desc == 'number') { op.desc = '' + args.desc; } }
1735
- if (args.tags) { if (args.tags === true) { op.tags = ''; } else if (typeof args.tags == 'string') { op.tags = args.tags.split(','); } else if (typeof args.tags == 'number') { op.tags = '' + args.tags; } }
1736
- if (args.icon) { op.icon = parseInt(args.icon); if ((typeof op.icon != 'number') || isNaN(op.icon) || (op.icon < 1) || (op.icon > 8)) { console.log("Icon must be between 1 and 8."); process.exit(1); return; } }
1737
- if (args.consent) { op.consent = parseInt(args.consent); if ((typeof op.consent != 'number') || isNaN(op.consent) || (op.consent < 1)) { console.log("Invalid consent flags."); process.exit(1); return; } }
1738
- ws.send(JSON.stringify(op));
1737
+ if (args.addtag || args.removetag) {
1738
+ // we need to fetch the node data first to then modify the tags
1739
+ var nodeid = args.id;
1740
+ ws.send(JSON.stringify({ action: 'nodes', id: args.id, responseid: 'meshctrl' }));
1741
+ } else {
1742
+ var op = { action: 'changedevice', nodeid: args.id, responseid: 'meshctrl' };
1743
+ if (typeof args.name == 'string') { op.name = args.name; }
1744
+ if (typeof args.name == 'number') { op.name = '' + args.name; }
1745
+ if (args.desc) { if (args.desc === true) { op.desc = ''; } else if (typeof args.desc == 'string') { op.desc = args.desc; } else if (typeof args.desc == 'number') { op.desc = '' + args.desc; } }
1746
+ if (args.tags) { if (args.tags === true) { op.tags = ''; } else if (typeof args.tags == 'string') { op.tags = args.tags.split(','); } else if (typeof args.tags == 'number') { op.tags = '' + args.tags; } }
1747
+ if (args.icon) { op.icon = parseInt(args.icon); if ((typeof op.icon != 'number') || isNaN(op.icon) || (op.icon < 1) || (op.icon > 8)) { console.log("Icon must be between 1 and 8."); process.exit(1); return; } }
1748
+ if (args.consent) { op.consent = parseInt(args.consent); if ((typeof op.consent != 'number') || isNaN(op.consent) || (op.consent < 1)) { console.log("Invalid consent flags."); process.exit(1); return; } }
1749
+ ws.send(JSON.stringify(op));
1750
+ }
1751
break;
1752
}
1753
case 'runcommand': {
@@ -2473,6 +2485,43 @@ function serverConnect() {
2485
}
2486
}
2487
}
2488
+ if ((settings.cmd == 'editdevice') && (data.responseid == 'meshctrl')) {
2489
+ // Find the node to get its current tags
2490
+ var targetNode = null;
2491
+ for (var i in data.nodes) {
2492
+ for (var j in data.nodes[i]) {
2493
+ if (data.nodes[i][j]._id == args.id) { targetNode = data.nodes[i][j]; break; }
2494
+ }
2495
+ if (targetNode != null) { break; }
2496
+ }
2497
+ if (targetNode == null) {
2498
+ console.log('Node not found.');
2499
+ process.exit();
2500
+ return;
2501
+ }
2502
+ // Start with current tags or empty array
2503
+ var tags = (Array.isArray(targetNode.tags)) ? targetNode.tags.slice() : [];
2504
+ // Add tags: --addtag tag1,tag2
2505
+ if (args.addtag) {
2506
+ var addtags = (typeof args.addtag == 'string') ? args.addtag.split(',') : ['' + args.addtag];
2507
+ for (var i in addtags) { var t = addtags[i].trim(); if (t && (tags.indexOf(t) < 0)) { tags.push(t); } }
2508
+ }
2509
+ // Remove tags: --removetag tag1,tag2
2510
+ if (args.removetag) {
2511
+ var removetags = (typeof args.removetag == 'string') ? args.removetag.split(',') : ['' + args.removetag];
2512
+ var removetrimmed = removetags.map(function(r) { return r.trim(); });
2513
+ tags = tags.filter(function(t) { return removetrimmed.indexOf(t) < 0; });
2514
+ }
2515
+ // Build and send the changedevice op
2516
+ var op = { action: 'changedevice', nodeid: args.id, responseid: 'meshctrl' };
2517
+ if (typeof args.name == 'string') { op.name = args.name; }
2518
+ if (typeof args.name == 'number') { op.name = '' + args.name; }
2519
+ if (args.desc) { if (args.desc === true) { op.desc = ''; } else if (typeof args.desc == 'string') { op.desc = args.desc; } else if (typeof args.desc == 'number') { op.desc = '' + args.desc; } }
2520
+ if (args.icon) { op.icon = parseInt(args.icon); if ((typeof op.icon != 'number') || isNaN(op.icon) || (op.icon < 1) || (op.icon > 8)) { console.log("Icon must be between 1 and 8."); process.exit(1); return; } }
2521
+ if (args.consent) { op.consent = parseInt(args.consent); if ((typeof op.consent != 'number') || isNaN(op.consent) || (op.consent < 1)) { console.log("Invalid consent flags."); process.exit(1); return; } }
2522
+ op.tags = tags;
2523
+ ws.send(JSON.stringify(op));
2524
+ }
2525
break;
2526
}
2527
case 'meshes': { // LISTDEVICEGROUPS
meshuser.js
+6
@@ -729,6 +729,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
729
if (command.meshid == null) { err = 'Invalid group id'; }
730
}
731
732
+ // Check if command.id is set with a domain id, if not, add the domain id to it.
733
+ if (typeof command.id == 'string' && command.id !== '') {
734
+ if (common.validateString(command.id, 1, 1024) == false) { err = 'Invalid device identifier'; }
735
+ else if (command.id.indexOf('/') == -1) { command.id = 'node/' + domain.id + '/' + command.id; }
736
+ }
737
+
738
if (err == null) {
739
try {
740
if (command.meshid == null) {