Skip to content

Bullwinkle extends the agent and device communication mechanisms

License

Notifications You must be signed in to change notification settings

electricimp/Bullwinkle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bullwinkle Framework 2.3.2

Bullwinkle has been deprecated and will no longer be updated -- please use MessageManager instead

Bullwinkle is an easy to use framework for asynchronous agent and device communication. The Bullwinkle library consists of two classes:

  • Bullwinkle - The core application - used to add/remove handlers, and send messages.
    • Bullwinkle.send - Sends a message to the partner application.
    • Bullwinkle.on - Adds a message listener for the specified messageName.
      • message - The message table passed into .on handlers.
      • reply - A method passed into .on handlers that is used to reply to the message.
    • Bullwinkle.remove - Removes a message listener for the specified messageName.
  • Bullwinkle.Package - A packaged message with event handlers.
    • Package.onSuccess - Adds a handler that will be invoked if the message is successfully delivered and acknowledged.
    • Package.onReply - Adds a handler that will be invoked if the message is replied to.
    • Package.onFail - Adds an onFail handler that will be invoked if the send failed.
      • retry - A method passed into .onFail handlers that is used to retry sending the message.

To add this library to your project, add #require "bullwinkle.class.nut:2.3.2" to the top of your agent and device code.

Note You must #require and instantiate Bullwinkle in both the agent and device code.

Bullwinkle Usage

Constructor: Bullwinkle([options])

Calling the Bullwinkle constructor creates a new Bullwinkle application. An optional options table can be passed into the constructor to override default behaviors.

options

A table containing any of the following keys may be passed into the Bullwinkle constructor to modify the default behavior:

Key Data Type Default Value Description
messageTimeout Integer 10 Changes the default timeout required before a message is considered failed.
retryTimeout Integer 60 Changes the default timeout parameter passed to the retry method.
maxRetries Integer 0 Changes the default number of times the retry method will function. After this number the retry method will do nothing. If set to 0 there is no limit to the number of retries.
autoRetry Boolean false If set to true, Bullwinkle will automatically continue to retry sending a message until maxRetries has been reached when no onFail is supplied. Please note if maxRetries is set to 0, autoRetry will have no limit to the number of times it will retry.
onError function null Callback to be executed if a low level error is encountered. Currently it is called when too many timers have been created.

Examples

// Initialize using default settings
bull <- Bullwinkle();
options <- { "messageTimeout": 5,   // If there is no response from a message in 5 seconds,
                                    // consider it failed
             "retryTimeout": 30,    // Calling package.retry() with no parameter will retry
                                    // in 30 seconds
             "maxRetries": 10,      // Limit to the number of retries to 10
             "autoRetry": true      // Automatically retry 10 times
           }
// Initialize using custom settings
bull <- Bullwinkle(options);

Bullwinkle Methods

send(messageName[, data])

Sends a named message to the partner’s Bullwinkle application, and returns a Bullwinkle.Package. The data parameter can be a basic Squirrel type (1, true, "A String") or more complex data structures such as an array or table, but it must be a serializable Squirrel value.

bull.send("setLights", true);   // Turn the lights on

The send() method returns a Bullwinkle.Package object that can be used to attach onFail, onSuccess and onReply handlers.

on(messageName, callback)

Adds a message listener (the callback) for the specified messageName. The callback method takes two parameters: message (the message) and reply (a method that can be called to reply to the message).

// Get a message, and do something with it
bull.on("setLights", function(message, reply) {
    led.write(message.data);
});

message

The message parameter is a table that contains some or all of the following keys:

Key Data Type Description
type Integer Bullwinkle message type
tries Integer Number of attempts made to deliver the message
name String Name of the message
id Integer ID of the message
ts Integer Timestamp when message was created
data Serializable Squirrel value data passed into the #send method
retry Table A table containing ts the timestamp of the latest retry and sent a boolean
latency Float Seconds taken to deliver the message

reply(data)

The second parameter, reply, is a method that can be invoked to reply to the message caught by the .on handler. The reply method takes a parameter, data, representing the information we want to pass back to the partner. The data parameter can be any serializable Squirrel value.

// Get a message, and respond to it
bull.on("temp", function(message, reply) {
    // Read the temperature and humidity sensor
    local data = tempHumid.read();

    // Reply to the message
    reply(data);
});

remove(messageName)

The remove() method removes a message listener that was added with the .on method.

bull.remove("test");     // Don't listen for 'test' messages any more.

Bullwinkle.Package

A Bullwinkle.Package object represents a message that has been sent to the partner, and has event handlers attached to it. Bullwinkle.Package objects should never be manually constructed: the Bullwinkle.send() method returns a Bullwinkle.Package object.

onSuccess(callback)

The onSuccess() method adds an event listener (the callback) that will execute if the partner .on handler receives the message. The callback’s message parameter contains the successfully delivered message, including a tries count and a round-trip latency float in seconds.

bull.send("importantMessage")
    .onSuccess(function(message) {
        server.log("Done!");
    })
    .onFail(function(err, message, retry) {
        retry();
    });

onReply(callback)

The onReply() method adds an event listener (the callback) that will execute if the partner .on handler replies to the message with the reply() method. The callback takes a single parameter, message, which contains the message information, including a tries count and a round-trip latency float in seconds.

The following example demonstrates how to get real time sensor information with Rocky and Bullwinkle:

// Agent Code
#require "Rocky.class.nut:1.2.3"
#require "Bullwinkle.class.nut:2.3.2"

app <- Rocky();
bull <- Bullwinkle();

app.get("/data", function(context) {
    bull.send("temp").onReply(function(message) {
        context.send(200, message.data);
    });
});
// Device Code
#require "Si702x.class.nut:1.0.0"
#require "Bullwinkle.class.nut:2.3.2"

bull <- Bullwinkle();

i2c <- hardware.i2c89;
i2c.configure(CLOCK_SPEED_400_KHZ);
tempHumid <- Si702x(i2c);

bull.on("temp", function(message, reply){
    local result = tempHumid.read();
    reply(result);
});

onFail(callback)

The onFail() method adds an event listener (the callback) that will execute if the partner application does not have a handler for the specified message name, or if the partner fails to respond within a specified period of time (the messageTimeout). The callback method requires three parameters: err, message and retry. If onFail() is used the autoRetry setting will not be envoked. To resend the message you must use the retry callback parameter.

The err parameter describes the error, and will either be BULLWINKLE_ERR_NO_HANDLER (in the event the partner application does not have a handler for the specified message name), or BULLWINKLE_ERR_NO_RESPONSE (in the event the partner application fails to respond in the specified timeout period).

The message parameter contains the failed message, including a tries count and a latency float in seconds.

The retry parameter is a method that can be invoked to retry sending the message in a specified period of time. This method must be called synchronously if it is to be called at all. If the retry() method is not called the message will be expired.

bull.send("importantMessage")
    .onFail(function(err, message, retry) {
        // Try sending the message again in 60 seconds
        if (!retry(60)) {
            server.error("No more retry attempts are allowed");
        }
    }).onReply(function(message) {
        server.log("Done!");
    });

retry([timeout])

The retry() method is passed into onFail handler, and can be used to try sending the failed message again after the specified timeout has elapsed. If no timeout is specified, the retry message will use the default retryTimeout setting. If the maximum number of retries have been attempted then this function will return false and no more retries will be attempted, otherwise it will return true. See onFail for example usage.

License

Bullwinkle is licensed under the MIT License.