Skip to main content

Using Agents In Factory Firmware: Examples

Some Typical Applications For Agents In The Factory

Factory Label Printer

You decide your product should ship with its MAC address and other unit-specific information printed on a sticky label which can be attached to the product packaging or to the base of the unit itself. How do you get the unique data from each Device Under Test (DUT) back to your BlinkUp™ fixture for printing? Factory agents allow you to do this.

The diagram below shows the flow of information from DUT to DUT’s agent, DUT agent to fixture’s agent, and fixture’s agent to fixture:


 

Once the DUT has been tested and blessed, the device-side firmware can call the imp API method agent.send() to transmit its data to its own agent:

local deviceData = {};
local netData = imp.net.info();
local network = netData.interface[("active" in netData ? netData.active : 0)];
deviceData.mac <- network.mac;
deviceData.id <- hardware.getdeviceid();
agent.send("dut.set.label.data", deviceData);

The agent that makes use of the information it has been sent might contain the following code:

device.on("dut.set.label.data", function(deviceData) {
    // Get the URL of the BlinkUp fixture that configured the DUT
    local fixtureAgentURL = imp.configparams.factory_fixture_url;

    if (fixtureAgentURL != null) {
        // Relay the DUT's data (MAC, deviceID) to the factory BlinkUp fixture via HTTP
        local header = { "content-type" : "application/json" };
        local body = http.jsonencode(deviceData);
        local request = http.post(fixtureAgentURL, header, body);

        // Wait for a response before proceeding, ie. pause operation until
        // fixture confirms receipt. We need label printing and DUT's position
        // on the assembly line to stay in sync
        local response = request.sendsync();

        if (response.statuscode != 200) {
            // Issue a simple error here; real firmware would need a more advanced solution
            server.error("Problem contacting fixture");
        } else {
            // Device can now be blessed while the label is printing...
            device.send("ready.to.bless", true);
        }
    } else {
        server.error("Posting code called in BlinkUp fixture flow not DUT flow");
    }
});

The BlinkUp fixture’s agent URL can be obtained from the imp.configparams property, factory_fixture_url, as the code above demonstrates.

The BlinkUp fixture agent needs code of its own: an HTTP request handler function to receive and process the data sent by each DUT’s agent:

http.onrequest(function(request, response) {
    try {
        // Look for a POST request from a device
        if (request.method == "POST") {
            // Make sure the request has a non-null body
            if (request.body) {
                try {
                    // Check that we have received JSON
                    local data = http.jsondecode(request.body);

                    // Send the device’s data to the BlinkUp fixture
                    device.send("fixture.data.to.print", data);

                    // Confirm successful receipt
                    response.send(200, "OK");
                } catch (error) {
                    response.send(400, "Could not process JSON");
                }
            }
        }
    } catch (error) {
        response.send(500, "Transmission failed - please try again");
    }
});

Having received the data from the DUT’s agent (via an HTTPS POST operation), the fixture’s agent sends the printable data to the fixture itself. This is the device.send() line in the above code. The code to pick the transmitted data up at the device side is:

agent.on("fixture.data.to.print", function(deviceData) {
    // Send the data to the label printer
    printLabel(deviceData);
});

The factory manager needs to organize this set-up so that each label is attached to the correct unit, and that blessing and printing move in step with the assembly flow. The function printLabel(), which we have not included here for clarity’s sake, will need to extract the mac and id values from deviceData table, and insert them into a template which will then be sent as data to the printer via serial or USB.

We have shown here the use of simple textual data, but the BlinkUp fixture’s agent might also transmit the DUT information to a remote server running a QR-code generation program. The agent requests the QR code, which is returned to it as a small bitmap graphic. This is then sent to the BlinkUp fixture to be added to the printed label. There is an example of this in the Dev Center’s sample code section.

Downloading Device Resources

If you expect to ship your product with data stored on board — perhaps samples of audio tones or voice recordings transmitted to the user for guidance and feedback, or graphics that will be displayed on the product’s LCD — you can use factory agents to download these resources before blessing and place them in the DUT’s flash storage. This saves the need to directly program this content into flash at an earlier stage in the assembly process, and gives you greater control over the content itself. For example, if you need to change an audio sample slightly, you can do so on the server your factory agent reaches out to; you don’t need to bundle up a new flash image and send it to the factory, which might be on a different continent and run by a contractor. This way you can guarantee that the update is applied to the production line as soon as it is ready.

Similarly, if your product contains a microphone, you might choose to take an audio sample as part of the DUT testing phase and use the factory agent to send the sample back to base. Here it can be analyzed and, if necessary, suitable calibration settings returned to the device and stored in the on-board flash.

In each case, the request for the data can come from the DUT’s agent; there’s no need here to route the request via the BlinkUp fixture. Once the data has been received by the DUT’s agent, it can be sent (using device.send()) to the DUT; the DUT’s firmware will have been written to store the downloaded data appropriately.

Production BlinkUp

Many products will be configured for end-use in the field. After all, the manufacturer doesn’t know what a given end-user’s network access information will be. However, in a small number of cases this information is known in advance — for example, devices being prepared for a specific customer. In such instances, the manufacturer would like to pre-configure production devices ahead of shipment so that they are ready to use upon installation.

Electric Imp has a REST API which can be used to acquire device enrollment credentials from the Electric Imp impCloud™. These credentials can then be applied to a device using the factory API method imp.setenroltokens(). WiFi credentials can be set using imp.setwificonfiguration().

This done, when the device first connects to the specified WiFi network, it will immediately attempt to enroll itself into the Electric Imp impCloud without the need for end-user BlinkUp: the end-user simply has to turn the device on and it will be ready to use.