Explore Our Command Line Tool Using The imp006 Breakout Kit
If you have completed the imp006 Breakout Kit Getting Started Guide, you will be familiar with impCentral™, Electric Imp’s online IDE. This is a great tool for simple projects and incorporates the functionality you’ll need if you go into production with your IoT project.
However, it’s not the only development and production tool that Electric Imp makes available to customers. Some developers prefer functionality they can use offline and access from the command line — either for preference or because they need to make use of an existing workflow. For developers in this situation, Electric Imp offers a suite of CLI tools of which the primary program is impt.
This tutorial will introduce you to impt, with an emphasis on its project management functionality. You’ll learn how to create impt projects, upload application code to the impCloud™ and view log messages from development devices as they’re issued. You’ll see how logs can be used to debug your Squirrel code.
Electric Imp also provides Builder, a code preprocessor which works alongside impt and allows you to integrate multiple files, in particular those under version control, into your project. We’ll be looking at the capabilities Builder brings to impt in a subsequent tutorial.
impt is run from the command line, so this tutorial assumes that you are familiar with accessing the command line on your development machine, and with running commands, creating directories and so forth.
First, though, this tutorial can’t be completed unless you have created an Electric Imp account and added your imp006 Breakout Kit to it. If you haven’t performed these basic tasks, please do so now. When you’ve done, come right back here, open up a command line and we’ll begin...
impt is written in JavaScript and runs under Node, which you’ll need to have installed on your system. Please check out the Node installation process for your computer at Nodejs.org. You will need to install Node 8 or above. When you’ve installed Node, run the following at the command line:
npm install -g imp-central-impt
We first need to log into impCentral, which we do using impt. Enter the following line, replacing the capitalized words with your own Electric Imp account credentials:
impt auth login --user <USERNAME> --pwd <PASSWORD>
This command establishes the authentication tokens that impt needs to communicate with impCentral. You’ll need to sign in whenever you interact with impCentral; impt manages this for you while you’re in a session. If you need to sign in again at the start of a future session, impt will prompt you.
The credentials you created are stored globally — they’ll be applied to all of your impt projects. However, it is also possible to have per-project credentials. We won’t use any such ‘local’ login credentials in this tutorial, but you can find out more about them here.
Now let’s set up a project.
impt organizes all of the key files relating to a project into a single project directory. Create one called imp-project
now and navigate into it.
We’re going to create an impCentral Product called iot-product
and we’re going to add to it a Device Group called iot-sensors
. To do so using impt, enter the following command:
impt project create --name iot-sensors --product iot-product --create-product
Assuming you don’t already have a Product called iot-product
and a Device Group called iot-sensors
, impt will create these entities within the impCloud for you now. If you know that iot-product
already exists, omit the --create-product
option.
impt will create two files in the project directory, device.nut
and agent.nut
, in which you can write the code that devices and their agents will run. A third local file, .impt.project
, holds the project configuration information used by impt itself.
When you run the command you’ll see something like this:
Product "iot-product" is created successfully.
Device Group "iot-sensors" is created successfully.
Device source file "device.nut" is created successfully.
Agent source file "agent.nut" is created successfully.
Project is created successfully.
Project:
Device file: device.nut
Agent file: agent.nut
Device Group:
id: 90a26ef0-babc-098b-1cc8-b0629b3b5a0d
type: development
name: iot-sensors
description:
region:
target_os: release-40.13
created_at: 2020-07-10T15:20:49.470Z
updated_at: 2020-07-10T15:20:49.470Z
env_vars:
Product:
id: a8542927-9b9e-b32b-fb8e-6a32910c58d6
name: iot-product
IMPT COMMAND SUCCEEDS
Today we’re creating a new project based on a new Device Group, but if you want to work on an existing Device Group — perhaps one you created and worked on in impCentral — then you can call:
impt project link --dg <DEVICE_GROUP_ID>
from within a newly created project directory. You can get the Device Group’s unique ID by calling impt dg list
and locating it in the output. To download your application source code to the project, call impt build get
.
Before we write some code, let’s add an imp006 Breakout Board to the Device Group we just created. To do so, we’ll need the ID of the device itself. Its unique ID and MAC address are written on the box the device came in, but of course you’ve already put that in the recycling. No problem: let’s get a list of devices in your account:
impt device list
impt will contact impCentral and download a list of devices, which may stretch from one to many, depending on the number of devices you have already assigned to your account. Remember, these are ‘development devices’ — impCentral separates out devices by their intended usage: development, product testing, and end-use.
Look at the listed devices’ id
values; imp006 Breakout Board IDs begin with 600a
. Copy the full id
value of your board then paste it into the command line:
impt device assign --device <YOUR_DEVICE_ID>
Make sure there’s a space between what you typed and the pasted device ID, then hit Enter. How does impt know which Device Group to assign the device to? It uses the group that was associated with the project when the project was created.
Incidentally, you can simplify device identification by giving it an easy-to-remember name. You’ll need the ID you found from the list:
impt device update --device <YOUR_DEVICE_ID> --name <YOUR_CHOSEN_DEVICE_NAME>
Let’s have a quick recap. So far we’ve logged into impCentral and created both a Product and a subsidiary Device Group; we’ve also assigned a device to that group, after we learned the device‘s ID by getting a list of our development devices. We’ve done all this in the context of an impt project.
Projects are how impt organizes all these entities. Each project references a single Device Group; every Device Group must belong to a Product. A Product can contain as many Device Groups as you need, but an impt project will only address one of them. However, you can link it to a different Device Group whenever you wish.
impt commands all take the form impt <command_group> <command>
. We’ve seen three command groups so far: auth
, project
, build
and device
, and the commands login
, create
, list
, link
, get
, update
and assign
. That’s quite a lot, but we’ll see some more command groups and commands shortly. All command groups support the command help
, which lists the group’s commands. For more information about a specific command, call it with the --help
option.
Device Groups are the means by which impCentral connects devices and their agents to code: you build and deploy code to a Device Group; any devices within that group then get the new code. Let’s write some code now.
Unlike the impCentral IDE, impt allows you to use whatever code editor you prefer. Code for imp applications is stored in .nut
files. That’s not a common file extension, so you may need to configure your system to open such files in your editor of choice, or you open the app and load the file manually. You might use a simple text editor, or a full-blown desktop IDE — the choice is yours, and too wide for us to cover all the possibilities here. So we’ll leave it to you to open the file device.nut
from the directory impt-project
in your favorite editor.
When you’ve done so, you’ll see that the file is empty. Just copy and paste the following line into it, then save the file.
server.log("Welcome to Electric Imp app development");
Go back to the command line, and upload the code to the Device Group using the following command:
impt build run
This tells impt to create a build and run it. It uploads your code to impCentral, which compiles and then deploys the new build to the Device Group referenced by the project. It then tells all of the group’s devices to restart — this causes them to get the fresh application code and to run it. When an imp-enabled device restarts, it always checks for new code.
If the code you upload contains a syntax error, impt will report that to you immediately. Runtime errors are another matter of course, and to spot those you’ll need to use impt’s logging facility to view messages as they are posted by the device. Let’s get that going now.
To start displaying logs from your device enter:
impt log stream
This sets up a logging stream and adds all of the devices in the project’s Device Group to it — only one so far!
Now press and release the Reset button on the imp006 Breakout Board. The board will reboot, reconnect and run the device code from the top. You’ll see all the log messages it and its agent generate at the command line:
[600a0c2a69e604fe] 2020-07-10T16:38:47.089Z [status] Agent restarted: reload.
[600a0c2a69e604fe] 2020-07-10T16:38:47.723Z [status] Device connected
[600a0c2a69e604fe] 2020-07-10T16:38:47.920Z [server.log] Welcome to Electric Imp app development
Logging ties up the command line in your current window, so to continue to issue commands, you need to open a second window, position it so you can see both windows, and then navigate to your project directory. To restart your device remotely, just enter:
impt dg restart
dg
is short for Device Group, of course. This command works just like hitting Reset simultaneously on all of the devices in the group, which would be hard enough even if they’re all right there on your bench, but impossible if they are running in remote locations.
To restart a specific device, call:
impt device restart --device <DEVICE_IDENTIFIER>
where DEVICE_IDENTIFIER
can be the device’s ID, its MAC address or, if you’ve set one, its name. Remember, you can find these with impt device list
.
Streaming shows current log entries as they are posted. If you need to look back at previously posted log messages, just enter impt log get
to receive up to 1000 past messages. The output is paged; by default you’ll see 20 messages per page. You can change this by including the --page-size
option:
impt log get --page-size 100
To wrap up this tutorial, let’s run a more interesting application, one that makes use of the imp006 Breakout Board’s onboard sensors. That way we can get it generating some real data to display in the log. You’ll also need to set up a second command line window as mentioned above because you’ll need to work on one window while observing the log in the other.
Open up your project’s device.nut
file and paste in the following code. You can safely overwrite the line you added before.
Save the file and then build and run the new program. Have a quick look back at the final command of step 5, if you’re unsure how that’s done.
What did you see in the log?
You shouldn’t have seen any output from the device itself, because impt will have reported a syntax error in your code. Look for the text Error: Compilation Error: There was an error with compilation
. impt will also tell you on which line the error can be found.
Can you see what’s wrong with the code? That’s right, we forgot to include parameter parentheses in the first function definition, on line 32. So you can fix the error in your device.nut
file by changing line 32 to:
function loop() {
Save the file and re-upload the code, as before, by typing:
impt build run
Now impt will tell you that everything is good. But wait, what’s this? Now we have a runtime error in the log!
[600a0c2a69e604fe] 2020-07-13T10:35:02.022Z [server.error] ERROR: the index 'i2cLN' does not exist
[600a0c2a69e604fe] 2020-07-13T10:35:02.022Z [server.error] ERROR: in main device_code:11
The first problem was a syntax error — a mistake in the text of the code. This time we’ve encountered a runtime error. The code is written correctly and compiles, but when it’s run, it’s asked to do something it’s not able to or doesn’t understand.
The error here is more subtle than the previous one. In line 11, we reference a property of the imp API hardware object to a global variable i2c (globals are declared and given an initial value with the <-
operator; see The Squirrel Programming Guide). That’s valid syntax. But hardware doesn’t have a property called i2cLN — it should be i2cLM — which is why we see the ‘index does not exist’ runtime error.
Again, the fix is easy: replace line 11 in your device.nut
file with:
i2c <- hardware.i2cLM;
Save the file and re-upload the code. Your log should now begin to show what we want to see: regular sensor readings, each one signalled by a flash of the Breakout Board’s user LED.
You can view the correct version of the code in full here.
Well done, you have completed this tutorial. You have successfully used impt to
You’ve also found out how to
The working code you now have is a great basis for the start of your exploration of the Electric Imp Platform. Here are some suggestions for what you can try next.
#require "LIS3DH.class.nut:3.0.0"
right below the existing #require
line.0x32
.accelerometer <- LIS3DH(i2c, 0x32);
.accelerometer.setDataRate(100);
.local reading = accelerometer.getAccel();
.