Post to multiple devices queue


#1

Is there a way to post to multiple devices queue at the same time instead of just one at a time?
As i want the same message to be sent to each device queue without having to do the multiple http post requests.


#2

No, this is not possible. But it seems like you might want to look into multicast? That is a more efficient way to send the same message to a group of devices.


#3

ahh OK thanks for that just a few questions what values do you enter multicast address, multicast network session key, multicast application session key. It allows me the option to generate random keys but should i have these keys already or should generating random keys work ?


#4

The devices should be aware they are part of a multicast-group. You either generate these values in LoRa App Server and provision your devices, or make sure that the values in LoRa App Server reflect your already multicast provisioned devices.


#5

Ok thanks for the help i will try that


#6

In your documentation on https://www.loraserver.io/loraserver/features/multicast/ it only supports class B and C device classes. My devices are class A. So i cannot select class A in the multicast group. Does class A not support multicast ?


#7

You can’t have a Class A exclusive device in a Multicast group. The LoRa Alliance’s Multicast Documentation say that you should be able to switch the device’s class to B or C prior to sending a multicast message, then switch the device back to A when it’s done. Haven’t done it myself, but it should be possible. (You must enable “Device supports Class-B/C” in the “Class B/C” tab).


#8

thanks for the help i was just reading about that in the lora alliance doc will try and see if it will work.


#9

As others mentioned, multicast is for class B and C only, as it doesn’t make sense for class A because rx windows depend on an uplink. I think you were really looking for some endpoint that just allowed you to enqueue the same data to multiple devices in one call instead of several ones: that’s not implemented. You may easily extend the API to allow this if it’s worth your trouble.


#10

I haven’t tried doing multicast yet but it should be possible.
This is in the lora alliance doc
This document defines an application layer messaging package running over LoRaWAN to
perform the following operations on a fleet of end-devices:
• Program a multicast distribution window into a group of end-devices
• Having all end-devices of the group switch to ClassB or ClassC temporarily at the beginning of the slot
• Close the distribution window and revert to normal operation (e.g. return to Class A,or change to a different periodicity in Class B)

Otherwise i will try what you said about extending the api


#11

If it’s of any help, just some minutes ago I had the exact same use case for a particular test we are running. Here’s a quick implementation that worked for me. First, at api/deviceQueue.proto add this method to the service and the necessary messages:

...
    // MultiEnqueue adds the given items to the device-queues of the given devices.
    rpc MultiEnqueue(MultiEnqueueDeviceQueueItemRequest) returns (MultiEnqueueDeviceQueueItemResponse) {
        option(google.api.http) = {
            post: "/api/devices/queue"
            body: "*"
        };
    }
...
message MultiEnqueueDeviceQueueItemRequest {
    // Queue-item objects to enqueue.
    repeated DeviceQueueItem device_queue_items = 1;
}

message MultiEnqueueDeviceQueueItemResponse {
    // Frame-counters for the enqueued payload.
    repeated uint32 f_cnts = 1;
}
...

Now, the quickest way to implement it at internal/api/device_queue.go was calling Enqueue on each item and just logging individual errors (reimplement it however you like):

// MultiEnqueue adds the given items to the device-queues of the given devices.
func (d *DeviceQueueAPI) MultiEnqueue(ctx context.Context, req *pb.MultiEnqueueDeviceQueueItemRequest) (*pb.MultiEnqueueDeviceQueueItemResponse, error) {

	var fCnts = make([]uint32, len(req.DeviceQueueItems))

	for i := 0; i < len(req.DeviceQueueItems); i++ {
		enqueueReq := &pb.EnqueueDeviceQueueItemRequest{
			DeviceQueueItem: req.DeviceQueueItems[i],
		}
		pbDeviceQueueItemResponse, err := d.Enqueue(ctx, enqueueReq)
		if err != nil {
			log.Errorf("couldn't enqueue item for device %s: %s", enqueueReq.DeviceQueueItem.DevEui, err)
			fCnts[i] = 0
		} else {
			fCnts[i] = pbDeviceQueueItemResponse.FCnt
		}
	}

	return &pb.MultiEnqueueDeviceQueueItemResponse{
		FCnts: fCnts,
	}, nil
}

Finally, extend ui/src/stores/DeviceQueueStore.js to make the method available:

  multiEnqueue(deviceQueueItems, callbackFunc) {
		this.swagger.then(client => {
      client.apis.DeviceQueueService.MultiEnqueue({
        body: {
          deviceQueueItems: deviceQueueItems,
        },
			})
      .then(checkStatus)
      .then(resp => {
        this.notify("created");
        callbackFunc(resp.obj);
      })
      .catch(errorHandler);
		});
	}

Hope it helps!


#12

Ok i will try that if i cant get the multicast working thanks for help