Controlling a device you have right in front of you is all very well, but the Electric Imp Platform is really about connected devices. How then do you control a device remotely? To do so, you need to make use of Electric Imp’s agent technology .
In this stage of the guide, you will use impCentral™ to add Internet interactivity to your program and make the LED seen in the last stage remotely controllable.
Here is the code you’ll need to run the example. This time there are two parts: as before there’s some code for the device, but we now have some code for the agent too.
Copy the two code listings below, making sure you paste each one into the correct part of the code editor, overwriting any code that’s already there. The agent code goes in the impCentral code editor’s left-hand pane; the device code goes in the right-hand pane:
Now click Build and Force Restart to install the code and run it.
If you typed in the code rather than pasted it and you made a mistake, impCentral will flag up the error if it’s a matter of incorrect syntax. If the error can only be detected when the code is running, you’ll see it reported in the log.
When the impExplorer starts up with the new code, you’ll see an entry like this appear in the log:
[Status] Downloading new code; 4.63% program storage used
As the agent starts up, you’ll the following lines logged:
[Status] Agent restarted: reload.
[Agent] Turn LED On: https://agent.electricimp.com/1234abcd?led=1
[Agent] Turn LED Off: https://agent.electricimp.com/1234abcd?led=0
These lines are posted by the first two lines of the agent code. These lines make use of the imp API method http.agenturl(), which returns the agent’s Internet address. Each agent URL is unique so you’ll see a different string of characters in your log.
Copy the first URL from your log (ie. your equivalent of https://agent.electricimp.com/1234abcd?led=1
) and paste it into a new browser tab’s address field. Hit the Return key on your keyboard and... the LED should turn on (red this time). Make sure you copy the line from the impCentral log, not this guide.
You have connected your impExplorer to the Internet and controlled it remotely. Change the final digit to 0, press Return, and the LED will now turn off. With the two URLs, you can control the LED from any Internet-connected device that can run a browser: your office computer, your tablet, your phone, a computer in an Internet cafe, or even other people’s devices.
This is a simple example. It is capable of much improvement , but nonetheless demonstrates the fundamental two-part (agent and device) structure of an Electric Imp application.
You’re now ready to move on to the next stage: Ready-to-Run Code Libraries.
Agents are per-device micro-servers that mediate communication between the device and Internet-connected resources. You might use an agent to provide an API through which a mobile app can send commands to the device. In response, the device might ask the agent to fetch it information, such as a weather forecast, from an online service.
The agent handles the outgoing request and, when the data comes back, sends the appropriate part to the device.
Agents run continually, allowing devices to be accessible even if they have been temporarily disconnected — it is being moved by its owner from one room to another or is in deep sleep mode to conserve battery power.
Being server-based, the agent has access to more processing horsepower than the device does, so you can offload number-crunching tasks to the agent and leave the device to focus on what it does best: handling input and output. This can be particularly important when the device is battery powered.
Finally, there’s security. Thanks to its agent, the device itself doesn’t need a visible presence on the Internet so it’s not exposed to attacks. In fact, it’s impossible to communicate with a device directly, even on the local network. All communication must be routed via its agent. If anything happens to an agent, its device will continue to operate. Agents are insulated from each other.
Let’s look at the device code first. The key line is the last one; the others simply set the LED to light up or not, just as we did in the previous stage. This time, however, we don’t run a loop to switch the LED on and off, we only change its state in response to a message from the agent. The last line of the code tells the device to run the LED switch code, embodied in the function setLedState(), whenever it receives the message string “set.led”
from the agent:
agent.on("set.led", setLedState);
This is another example of the Electric Imp Platform’s event-driven nature. When the device reaches this line of code, it records the fact it needs to trigger the function setLedState() ‘on’ receipt of a “set.led”
message from the agent. It doesn’t call setLedState() at this point; instead the program ends. The device will run no further user code until such a message arrives, in which case the function setLedState() is called. Remember, the method takes a reference to the function to be called, so we don’t include brackets after the function name (this would call the function immediately and pass into the method the value returned by the function).
This is a powerful approach. It saves you, the programmer from constantly checking for incoming messages and, if there are any, whether they’re the ones you’re interested in. impOS™ does all that for you, and runs the correct response code, all with the single line above.
But how does the agent send a message to the device? Look at line 15 in the agent code:
device.send("set.led", ledState);
This sends the message “set.led”
(the send() method’s first parameter) to the agent’s device (represented by the device object) and packages it with the data value stored in the variable ledState. We’ll see how ledState gets set in a moment: for now, let’s see what the impExplorer does with it. Look at lines 9 through 12 of the device code:
function setLedState(state) {
local color = state ? [255,0,0] : [0,0,0];
led.set(0, color).draw();
}
The code sets the color the LED will show according to the value of the variable state, which will be either true
or false
: if it is true
, the RGB color is set to the array [255,0,0] (red), otherwise [0,0,0] (off). Line 11 sets the led’s color to that specified by the variable color, and then draws the color on the LED itself.
The pairing of device.send() and agent.on() always includes a single data variable which impOS automatically forwards to the function it has been told to call in response to the arrival of a specifically named message. Here, this data is placed in setLedState()’s local variable state.
The agent demonstrates a second example of event-driven programming, in line 27:
http.onrequest(requestHandler);
Just like agent.on(), http.onrequest() registers a function that the agent will call if a certain event takes place, in this case the receipt of an HTTP request issued by a web browser. When such a request is made, the agent runs the function requestHandler(). Data is packaged up and passed to this function as parameters: an httprequest object which records the details of the incoming request, and an automatically generated httpresponse object which the agent can use to acknowledge receipt of the request or, if an error has occurred, return a suitable warning (line 22).
Both httprequest and httpresponse are objects defined by the imp API. If you look at the function requestHandler() you’ll see we examine the query property of the httprequest request to see if it is one we need to respond to here. If query contains the property led, the code reads its value, sets the local variable ledState with that value and then, as we saw above, sends the value to the device. More generally, the query property contains any and all URL-encoded keys and values sent as part of the initial HTTP request. These values are accessed through their keys, which are presented as properties of query using dot syntax.
Whether query contains led or not — it could contain any of a number of parameters we may or may not be interested in — we use the httpresponse object response to send the standard HTTP response code 200 back to the browser that issued the request:
response.send(200, "OK");
You might care to modify the code so that the browser command has three data points, red, green and blue, which are submitted to the agent and then relayed to the device to set the LED to whatever color you set in your browser.
A task for more advanced developers: since the agent is a micro web server, use web technologies like JQuery and Ajax to build an interactive web UI served by the agent that allows the user to click on LED on/off buttons, and to enter color values into text fields. This example code will help you.
With suitable code, your agent can interpret much more complex HTTP requests combining multiple commands relevant to the device, which may include displays, sensors, control motors and more. You can write complex APIs served by the agent through which mobile apps can interact with your device.