Skip to main content

Writing, Testing And Using Factory Firmware

Everything You Need To Know About Factory Control Code

Factory firmware is Squirrel code you develop to run on all of your devices in the Connected Factory. This includes not only Devices Under Test (DUTs) on the assembly line but also the imp-based BlinkUp™ fixture you will use to configure DUTs for enrollment with the Electric Imp impCloud™ and for factory network access, as required.

The same factory firmware runs on both of these types of device: DUTs and fixtures. You must develop your factory firmware with separate code paths for each of these two types of device and carefully ensure that the correct code path is chosen so that:

  • When running on a BlinkUp fixture, factory firmware performs factory BlinkUp operations.
  • When running on a DUT, factory firmware tests and blesses the host device.

The following flowchart shows the two code paths your factory firmware must include:

Electric Imp provides a free-to-use code library, FactoryTools, to help you in this task.

Factory firmware is closely bound to the device you are manufacturing, so you will need to create separate factory firmware for each product you make. In impCentral, factory firmware is developed and tested in a Test Factory Device Group in impCentral’s Test Zone. When factory firmware is ready to be used in production, it must be promoted and then deployed to a Factory Device Group in impCentral’s Production Zone. Factory Device Groups gather together one or more of the Product’s BlinkUp fixtures.

Because the factory firmware is run on every DUT before the hardware is provisioned with its application firmware, the factory firmware is the ideal place to include code to test each DUT before final assembly and shipment.

If those tests have been passed, the factory firmware blesses the DUT on which it is running. If this too is successful, the DUT is now a Production Device — it is ready for packaging, shipment and sale. In addition, it is registered with the impCloud as an end-user device, and impCloud billing will commence when an end-user activates it. Depending on how you have set up the Connected Factory Process, each Production Device will received its assigned application firmware either immediately after blessing, or when it is purchased by an end-user and activated.

Factory Firmware On The BlinkUp Fixture

Because the factory firmware will run on the BlinkUp fixture and on each DUT, it must be able to distinguish between these two types of hardware. This can be done by utilizing Electric Imp’s Factory Tools library, which provides a method, isFactoryImp(), which indicates if the device it is running on is a BlinkUp fixture. This is demonstrated in the sample code below.

Factory BlinkUp

To perform factory BlinkUp, the factory firmware needs to be programmed with the factory WiFi network’s credentials. You can set and send dummy and empty strings if your DUTs do not use WiFi to connect to the Internet. The BlinkUp signal is triggered by calling the factory-only imp API method server.factoryblinkup() in your factory firmware’s fixture flow. This method has four parameters, all of which are required:

  • The factory network SSID (or an dummy string, eg. "dummy", if WiFi is not required).
  • The factory network password (or an empty string, "", if there is no password or WiFi is not required).
  • The imp pin to which the BlinkUp fixture’s LED is attached. In the case of Electric Imp’s impFactory™ fixture, this is pin M.
  • An optional series of constants to tailor the process to your hardware. Please see the method’s documentation for details.

Calling this method causes the BlinkUp fixture’s LED to transmit a factory enrollment token and the supplied network details. The method returns immediately; an implicit request for the factory token is handled asynchronously by impOS™. When the token is received, BlinkUp begins; Squirrel is suspended until it is complete. After completion, the factory firmware’s BlinkUp fixture code branch is ready to configure the next DUT on the assembly line. Typically, BlinkUp is triggered by a button pressed manually by an assembly line operator, or automatically by wire in response to a signal from a sensor or other system tracking the progress of the assembly. In the case of the impFactory, the button is on pin C.

Example Factory BlinkUp Fixture Code

This example is not complete factory firmware — it simply illustrates that portion of the factory firmware dedicated to BlinkUp Fixture operation. The full factory firmware example can be found here.

Factory Firmware On A DUT

Electric Imp’s Factory Tools library provides a method, isDeviceUnderTest(), to indicate if the device on which it is running is a DUT. This is demonstrated in the sample code presented below.

When a DUT is configured by a BlinkUp fixture, it is able to connect to the impCloud. Factory BlinkUp provides the DUT with a factory token which is relayed to the impCloud to authenticate the DUT. Once the DUT has been authenticated, it receives the factory firmware.


To ready a DUT for end-use, ie. to register it as an end-user device with the impCloud, the factory firmware must call the factory-only imp API method server.bless(). This takes two parameters: a boolean value and a callback function. The callback itself requires only one parameter: a boolean value containing the outcome of the blessing attempt: true for success, false for failure.

The boolean value passed to server.bless() should be generated by code that you have incorporated into your factory firmware to test the DUT’s hardware. This is shown in the example below. You might want to take readings from all of the device’s sensors, for instance, in a rig that provides each one with a calibrated reading. In some cases, test results can be assessed in code. Others may require an assembly line operator to verify a successful result and confirm that by pressing a button built into the device or by bridging two terminals on the product’s circuitboard.

The outcome of these tests should be true for a pass, and false for a fail. Only if true is passed as the first parameter of server.bless() will the impCloud be contacted to bless the DUT. If the first server.bless() parameter is passed false, the DUT’s BlinkUp LED will be lit red to alert the assembly line operator to remove the rejected device. If blessing fails for some reason, the LED will also be lit red. Only if the first parameter is true and blessing is successful will the LED be lit green.

Do not call server.bless() on the factory BlinkUp fixture as it will turn this hardware into a Production Device. This is why you must always code your factory firmware to check what kind of device it is running on and to take the appropriate code path for that device. This is shown in the sample code above and below.

If you bless your factory BlinkUp fixture, it will no longer function in its assigned role. If it is the only fixture on the assembly line, this will halt production.

Finally, your factory firmware’s DUT path should call imp.clearconfiguration() to erase your factory’s WiFi credentials and the factory enrollment token from the DUT. This ensures that the end-user sees the device as a clean slate: the device correctly signals its unconfigured state on its BlinkUp status LED.

When Is Application Firmware Installed?

By default, the new Production Device will receive its application firmware immediately after blessing. This is set to take place approximately one second (1s) after the callback function registered with sever.bless() is executed. However, the transfer of firmware is initiated by the impCloud and because of the nature of Internet communications, you should not assume this will be a fixed duration. The recommended procedure therefore is to prevent your factory firmware from going idle in the post-bless callback until all of its essential tasks have been completed. As soon as Squirrel yields, impOS will be free to restart the Squirrel virtual machine, which will trigger receipt of the application code.

It is for this reason that it is important to include the call to imp.clearconfiguration() within the sever.bless() callback. The Squirrel VM restart triggered by impCloud to signal that the device should install its application firmware does not cause a re-connection, so the device is still connected to the factory network at this time (which is how it is able to receive the application firmware even though its WiFi settings have been cleared). Only when the application has been installed does the imp break the connection; it cannot now re-connect to WiFi because its configuration has been cleared and will need to be activated by an end-user to connect again.

If you are installing your application upon device activation (either the first end-user BlinkUp or you are activating production devices in the factory), you can simply power down the device at this point.

Example DUT Code

This example is not complete factory firmware — it simply illustrates that portion of the factory firmware dedicated to DUT operation. The full factory firmware example can be found here.

Developing Factory Firmware

You develop factory firmware within one of impCentral’s Test Factory Device Groups.

The factory API comprises the following mandatory methods. Your factory firmware must include these calls:

  • server.factoryblinkup() — Called to initiate a BlinkUp configuration.
    • Transmits a factory token from the factory BlinkUp fixture to a DUT on the assembly line. The token instructs the impCloud to provide the DUT with your factory firmware.
    • Should be called only in the factory BlinkUp fixture code branch.
  • server.bless() — Called to bless DUTs that have passed hardware checks.
    • Permanently binds a new device to the specified application firmware.
    • Should be called only in the DUT code branch.
    • If blessing succeeds, the DUT’s BlinkUp status LED turns green.
    • If blessing fails, the DUT’s BlinkUp status LED turns red.

The following factory API method is optional but highly recommended:

  • imp.clearconfiguration() — clear the device’s WiFi settings and factory token.
    • This method should only be used in factory firmware after a successful bless.
    • This method puts the device into a ‘clean slate’ state.

The following factory API methods are optional:

  • imp.setenroltokens() — Sets the device’s end-user enrollment token and plan ID without BlinkUp.
  • imp.setwificonfiguration() — Sets the device’s WiFi access credentials without BlinkUp.
    • This method is usually combined with imp.setenroltokens().
    • The supplied credentials will be used for all subsequent connections, including those initiated after a cold boot. However, the credentials can be overwritten by a subsequent BlinkUp.
  • imp.setcountry() — Sets the device’s wireless regulatory region.
    • Sets the number of channels within the 2.4GHz band that the device is permitted to use.
  • imp.setnvramimage() — Writes the WiFi controller settings page.
    • imp003, imp004m, imp005-enabled devices only.

Note Factory firmware is currently not able to make use of the imp API’s nv table to persist data across warm reboots.

Factory Agents

Factory firmware can incorporate agent code as well as device code. Just as your device code needs to detect which kind of device it is running on, as described above, so too must the agent provide separate code for working with factory BlinkUp fixtures and with DUTs. Again, Electric Imp’s, FactoryTools library can help you determine which agent code flow to take.

If your factory agent code is driven solely by messages from the device (using agent.send() and device.on()) it’s sufficient to implement device differentiation by ensuring that each message the agent responds to is sent only by a DUT or by a BlinkUp fixture. This is demonstrated in the sample code.

When a DUT restarts after being enrolled, its agent is also started. Factory agents will continue to run for as long as they are in active communication with their device, or for a set period of time should communication be lost. In the case of BlinkUp fixtures, that extension period is 30 days. For DUTs, however, the agent will continue to run only for 24 hours.

  • Please see this page for some examples of factory agent usage.

Testing Factory Firmware

impCentral makes testing factory firmware not only easy but also exactly as it were being run in the factory. You assign BlinkUp fixtures to your Test Factory Device Group, and these then receive your in-development factory firmware. They can be then used to configure DUTs, which will receive and run the factory firmware too. In the test environment (impCentral’s Test Zone), all calls to server.factoryblinkup() and server.bless() work exactly as they do in production. Upon blessing, DUTs become Test Production Devices, which are listed under the Test Factory Device Group’s target Test Production Device Group (select the Device Icon icon from the left-hand side panel).

Running Factory Firmware

To use your factory firmware in production, you will need to promote it to impCentral’s Production Zone. Do this by clicking on the Promote button in the impCentral code editor, or by viewing an existing deployment’s settings (navigate to your Product’s Test Factory Device Groups list and click Deployments under MANAGE, then click Settings under MANAGE) and checking the Promoted box. You should have already promoted a similar deployment of your application firmware and used this to create a new Production Device Group. You can now create a Factory Device Group with the aforementioned Production Device Group as its target. Assign your BlinkUp fixture(s) to the Factory Device Group, to which you should then deploy the promoted factory firmware. When the BlinkUp fixtures are powered up, they will be ready to begin enrolling DUTs.

Updating Factory Firmware

Should you update your factory firmware, perhaps to add further DUT hardware tests, you’ll need to promote it again from the Test Factory Device Group’s code editor or its Deployments list, as described in the previous section. Once promoted, the new code can be deployed to a Factory Device Group in the Production Zone as detailed above. When the updated factory firmware is deployed, the group’s fixtures will restart and receive the new firmware automatically, and all DUTs subsequently configured by those fixtures will also receive the new factory firmware.

Logging From Factory Firmware

You may include server.log() and server.error() calls in your factory firmware. When run in Test Factory Device Groups, these calls will log messages in the usual way: from fixtures, within the code editor’s log pane; from DUTs, accessed via the Test Production Device Groups list.

Sample Code

You will find a complete factory firmware example, based on the code segments listed earlier, in our Sample Code section.