Broad, catchall device.on() and agent.on()


#1

Has the Electric Imp team considered an alternate use of device.on() and agent.on() where the messageName is not specified? Instead, a single handler is called that is called with two parameters, the messageName and the payload.

e.g. instead of agent.on(“messageName”,function(payload){ … }), we can use agent.on(function(message,payload){ … })

In the handler, a switch statement could be used to split the message types.

There’d be some benefits to this:

  1. unhandled message types could be picked up.
  2. any common pre-processing of the payload could be done in the same code block
  3. messageNames could be dynamic, rather than fixed
  4. The payload in agent.send()/device.send() would be optional, lowering data use
  5. The existing functionality would not be disturbed. Message names specified with agent.on(msg,callback) would have precedence over the catchall version.

#2

That’s a great idea for the MessageManager library! I believe, the feature doesn’t have to be implemented on the platform Squirrel API level.


#3

@ppetrosh, that’s good to know it could be of use within MessageManager. Unfortunately, I can’t consider it as my connection and messaging layers are quite different to ConnectionManager and MessageManager. I developed them before even Rocky and Bullwinkle existed. I guess I am looking for direct API support, as library support would just add bulk to my project, with fewer benefits.

IMO, the initial Squirrel API was developed with the goal of enabling agent<->device interaction with a minimal amount of code. Now, we have more powerful imps and more demanding applications. If someone were starting from scratch, they’d be wise to consider more dynamic and flexible approaches.


#4

Well, your request totally makes sense to me. We’ll discuss adding support for it on the impOS level.

However, it’s pretty easy to work it around at this point. You send all the messages with the same “name” and do dispatching to handlers on the application side. The application defined name/topic is going to be a part of the message payload in this case. I.e.

agent.send("message", {"topic": "appTopic", "data": "application data"}

function dispatcher(msg) {
    ... 
}

device.on("message", dispatcher.bindenv(this));

This approach would have a minimal footprint overhead on the app and can easily be wrapped into a simple reusable library.

I hope it makes sense.


#5

Thanks, that’s exactly what I do at the moment.
It’s a small thing, but it does add to the number of bytes exchanged between agent and device. Furthermore, because agent.send() doesn’t have an asynchronous ack layer that’s exposed to Squirrel, I need to send an explicit message in the other direction to confirm that the request got through.


#6

Right, this is exactly what MessageManager does, but I optimized it a little bit. To ack a message MM doesn’t send the full original message payload back to the sender. Instead, it sends just the message id. And on the sender side, MM keeps the sent messages in a queue until they are acked, replied or time out. So that if needed, applications can resend them.


#7

Thanks for this suggestion! This feature has been added to our backlog.