diff --git a/package-lock.json b/package-lock.json
index 08d5fba..5ab97b9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@chirpstack/node-red-contrib-chirpstack",
- "version": "4.0.0-rc.2",
+ "version": "4.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@chirpstack/node-red-contrib-chirpstack",
- "version": "4.0.0-rc.2",
+ "version": "4.0.0",
"license": "MIT",
"dependencies": {
"@chirpstack/chirpstack-api": "^4.0.0",
@@ -573,9 +573,9 @@
}
},
"node_modules/protobufjs": {
- "version": "6.11.2",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
- "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==",
+ "version": "6.11.3",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
+ "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==",
"hasInstallScript": true,
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
@@ -1257,9 +1257,9 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"protobufjs": {
- "version": "6.11.2",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
- "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==",
+ "version": "6.11.3",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
+ "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==",
"requires": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
diff --git a/package.json b/package.json
index 49a54f2..d0dc1fc 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
"node-red": {
"nodes": {
"device-event": "src/device-event.js",
- "device-downlink": "src/device-downlink.js"
+ "device-downlink": "src/device-downlink.js",
+ "multicast-downlink": "src/multicastGroup-downlink.js"
}
}
}
diff --git a/src/multicastGroup-downlink.html b/src/multicastGroup-downlink.html
new file mode 100644
index 0000000..b8156de
--- /dev/null
+++ b/src/multicastGroup-downlink.html
@@ -0,0 +1,74 @@
+
+
+
+
+
diff --git a/src/multicastGroup-downlink.js b/src/multicastGroup-downlink.js
new file mode 100644
index 0000000..95a3e84
--- /dev/null
+++ b/src/multicastGroup-downlink.js
@@ -0,0 +1,64 @@
+module.exports = function(RED) {
+ "use strict";
+ var multicastGroup = require("@chirpstack/chirpstack-api/api/multicast_group_grpc_pb");
+ var multicastGroup_pb = require("@chirpstack/chirpstack-api/api/multicast_group_pb");
+ var grpc = require("@grpc/grpc-js");
+
+ function MulticastGroupDownlink(config) {
+ RED.nodes.createNode(this, config);
+ var node = this;
+ var client = null;
+
+ if (config.useTls) {
+ client = new multicastGroup.MulticastGroupServiceClient(config.server, grpc.credentials.createSsl());
+ } else {
+ client = new multicastGroup.MulticastGroupServiceClient(config.server, grpc.credentials.createInsecure());
+ }
+
+
+ var meta = new grpc.Metadata();
+ meta.add('authorization', 'Bearer ' + config.apiToken);
+
+
+ node.on("input", function(msg) {
+
+ var item = new multicastGroup_pb.MulticastGroupQueueItem();
+ var req = new multicastGroup_pb.EnqueueMulticastGroupQueueItemRequest();
+
+ if (msg.multicastGroupId === undefined) {
+ node.error("multicastGroupId is undefined");
+ return;
+ } else {
+ item.setMulticastGroupId(msg.multicastGroupId);
+ }
+
+ if (msg.fPort === undefined) {
+ node.error("fPort is undefined");
+ return;
+ } else {
+ item.setFPort(msg.fPort);
+ }
+
+ if (msg.payload !== undefined) {
+ item.setData(Buffer.from(msg.payload, config.encoding).toString("base64"));
+ } else {
+ node.log("payload is undefined, assuming empty downlink frame");
+ }
+
+ req.setQueueItem(item);
+ client.enqueue(req, meta, function(err, resp) {
+ if (err !== null) {
+ node.error("Enqueue error: ", err);
+ } else {
+ node.log("Downlink enqueued");
+
+ node.send({
+ fCnt: resp.getFCnt()
+ });
+ }
+ });
+ });
+ }
+
+ RED.nodes.registerType("multicast group downlink", MulticastGroupDownlink);
+}