Xively/Cosm and communication between Imps

Hey All,

So i’ve been thumbing through alot of documentation/references to find this answer, but am a bit daunted where to begin due to my lack of experience.

I essentially want to send messages between imps on my account. I figured xively would be the best approach, but am a bit confused. I had originally hosted a php script on a site to receive commands, but after looking through the forums, I assumed the new IDE/Xively might be the best approach.

I saw this thread: http://forums.electricimp.com/discussion/comment/7529#Comment_7529

and followed the directions, (not sure if this is even how I should begin) to simply send data from a photocell to one of my channels graphs. I receive this message:

no handler for agent.send()

I know this is a bit of a loaded post, so I guess my questions would be just a general question on getting the imps to receive messages amongst each other, and secondly why I am receiving this message/nothing is being logged to my xively account.

here is my code also:

AGENT:

`const FEED_ID = “I ADDED MY CUSTOM ID”;
const API_KEY = “ADDED MY API KEY”;

function get_xively() {
//wakeup
imp.wakeup(30.0, get_xively); //schedule when to wakeup again

local xively_url = "https://api.xively.com/v2/feeds/" + FEED_ID + ".json";      //format xively url
server.log(xively_url);
 
local getreq = http.get(xively_url, {"X-ApiKey":API_KEY, "User-Agent":"xively-Imp-Lib/1.0"});       //add headers
local res = getreq.sendsync();      //actuallty send request
if(res.statuscode != 200) {
    server.log("error sending message: " + res.body);
}
server.log("#####RESPONSE#####");
server.log(res.statuscode + " OK");     //status
server.log(res.body);                   //body
//format data into table - uncomment to use

// local resTable = http.jsondecode(res.body);
// server.log(“table:”);
// server.log(resTable.title);
// server.log(resTable.id);
// //print ds0
// server.log(resTable.datastreams[0].id);
// server.log(resTable.datastreams[0].current_value + " at " + resTable.datastreams[0].at);

//send to device
//device.send("value", resTable.datastreams[0].current_value);      //send custom data from table

device.send("json", res.body);     //send json

}
get_xively(); //initialize first get request. will continue to call itself.
function send_xively(body) { //take in csv value
local xively_url = “https://api.xively.com/v2/feeds/” + FEED_ID + “.csv”; //setup url for csv
server.log(xively_url);
server.log(body); //pring body for testing
local req = http.put(xively_url, {“X-ApiKey”:API_KEY, “Content-Type”:“text/csv”, “User-Agent”:“xively-Imp-Lib/1.0”}, body); //add headers
local res = req.sendsync(); //send request
if(res.statuscode != 200) {
server.log("error sending message: “+res.body);
}else device.send(“status”, (res.statuscode + " OK”)); //sends status to uart. this can be removed if not desired
}

device.on(“data”, function(feedCSV) { //take csv body in from device
server.log(“device on”);

//send preformatted multi-ds csv
send_xively(feedCSV);         //send to function to call xively

});

agent.on(“sendToXively”, sendToXively);

function sendToXively(data) {
//data is an array of key value pairs
local channels = [];

// loop through array and create 1 channel per item
for (local i = 0; i < data.len(); i++) {
    local channel = Xively.Channel(data.key);
    channel.Set(data.value);
    channels.push(channel);
}

// create our feed and push to Xively
local feed = Xively.Feed(Xively.FEED_ID, channels);
local resp = Xively.Put(feed);

}`

DEVICE

`// Control a LED intensity throught PWM Control
//http://forums.electricimp.com/discussion/comment/7529#Comment_7529

server.log(“Start PWM LED Intensity”);

hardware.pin7.configure(PWM_OUT, 0.02, 1.0);
hardware.pin8.configure(PWM_OUT, 0.02, 1.0);
hardware.pin9.configure(PWM_OUT, 0.02, 1.0);
local nextLoop = 0.0;
local lastLoop = 0.0;
sensor1 <- hardware.pin2;
sensor1.configure(ANALOG_IN);

// Create inputPort and correspondent function light the LED
class LEDintensity extends InputPort
{
// Set name and type of input port
name = “InputAnalog”;
type = “number”;

// Create function to light the LED
function set(value)
{
    
 
  
   if (nextLoop==0.0){
   // local new_val = scale(value, 0, 1.0, 0, 256.0);
   for(local value=0.0; value<=1.0; value+=0.02){
    // Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
    hardware.pin7.write(value/1.0);
    ///server.log(format("%.2f", value));
   imp.sleep(0.04);
  // return 0;

}
for(local value=1.0; value>=0.0; value-=0.02){
    // Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
    hardware.pin7.write(value/1.0);
    //server.log(format("%.2f", value));
  imp.sleep(0.04);
  //return 0;

}

nextLoop=1.0;
}

if (nextLoop==1.0){
// local new_val = scale(value, 0, 1.0, 0, 256.0);
for(local value=0.0; value<=1.0; value+=0.02){
// Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
hardware.pin8.write(value/1.0);
///server.log(format("%.2f", value));
imp.sleep(0.04);
// return 0;

}
for(local value=1.0; value>=0.0; value-=0.02){
    // Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
    hardware.pin8.write(value/1.0);
    //server.log(format("%.2f", value));
  imp.sleep(0.04);
  //return 0;

}

lastLoop = 1.0;
}
if(lastLoop==1.0){

       for(local value=0.0; value<=1.0; value+=0.02){
    // Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
    hardware.pin9.write(value/1.0);
    ///server.log(format("%.2f", value));
   imp.sleep(0.04);
  // return 0;

}
for(local value=1.0; value>=0.0; value-=0.02){
    // Write PWM value accordingly to the input value. Divide by 65535 to get a value between 0 and 1
    hardware.pin9.write(value/1.0);
    //server.log(format("%.2f", value));
  imp.sleep(0.04);

}
nextLoop=0.0;
}

////these bottom brackets close function/Class
}

}

/////////////////////

function getValuesAndSendToXively() {
// read values from pins
local s1 = sensor1.read();

// make array of {key/value} objects to send to agent
local data = [];
data.push( { key = "sensor1", value = s1 } );


// send to agent
agent.send("sendToXively", 40);

// wakeup in 15 minutes, and do it again
imp.wakeup(10, getValuesAndSendToXively);

}
getValuesAndSendToXively();
// Configure imp in the server
imp.configure(“PWM LED Intensity”, [LEDintensity()], [getValuesAndSendToXively()]);`

A couple of notes. With the new IDE + Beta you should never be using Input and OutputPorts. You should be replacing these with agent code. Input and Output ports are considered legacy (in the Beta and moving forwards).

The particular error you are receiving (no handler for agent.send()) is being triggered because you have some agent.send calls, without corresponding device.on calls.

Here is how agent/device communication works. To send a message from the device to the agent, you need to:

  1. Send the message from the device
    agent.send("messageName", data);

  2. Setup a handler for that particular message (“messageName”) in the agent:
    device.on("messageName", handlerFunctionWithOneParameter);

In your example code, you are calling device.send(“json”, res.body); but don’t have an agent.on(“json”, data) in your device code.

In your agent code, this: agent.on(“sendToXively”, sendToXively);
needs to be device.on.

In your agent you use device.on and device.send, and in your device, you use agent.on and agent.send.

That’s why it cant find a handler for agent.send.

Took me a bit to get a handle on it as well.

Edit… looks like @beardedinventor beat me too this. :slight_smile:

Thanks for the clarification. the email you had sent earlier had very helpful documentation, but a bit unclear for me to grasp. Thanks for the clarification.

Ive tried your suggestion but am getting this error:

Thu Aug 08 2013 14:02:18 GMT-0500 (CDT): ERROR: bad parameter types for method Thu Aug 08 2013 14:02:18 GMT-0500 (CDT): ERROR: at getValuesAndSendToXively:112 Thu Aug 08 2013 14:02:18 GMT-0500 (CDT): ERROR: from main:120

and now I had switched both agent/device settings to both “device” and receiving error:

Thu Aug 08 2013 14:07:12 GMT-0500 (CDT): ERROR: the index 'device' does not exist Thu Aug 08 2013 14:07:12 GMT-0500 (CDT): ERROR: at getValuesAndSendToXively:112 Thu Aug 08 2013 14:07:12 GMT-0500 (CDT): ERROR: from main:120

i guess while I trouble shoot, my main question was how should i tackle sending info between imps?

In terms of your other question, of what’s the best way to send data from one device to another - you can use an intermediate service like Xively (or Firebase, or any number of other services), but the easiest way is probably just to send HTTP requests from one of the device’s agents to another.

Here is a Gist I just made up with device+agent code for two devices. One of them has an LED, and one of them has a button. When the button on the one imp is pressed, it sends an HTTP request directly to the agent of the device with the LED to set it’s state.

Along with showing how two imps can communicate over HTTP, it’s a fairly bare bones examples for sending messages between imps and devices, and sending + processing incoming HTTP requests :slight_smile:

The only thing you need to do to make that example work is wire up the super simple circuits (as described in the files), and set the otherAgentUrl constant in the one agent file.

Wow, I can’t thank you guys enough for taking the time to answer/give examples. Im going to take a go at this when I receive my other imps, and will post in this thread if any issues.

Thanks again.

and just to clarify, everything can be sent on Imps server now?

I am a bit confused on the last part you said:

"and set the otherAgentUrl constant in the one agent file."

following the example exactly I am currently here:

I have two imps, ones imp has the agent.button in agent / and device.button in device.

this has the button.

the other imp respectively has the agent.led in agent and device.led in device.
this has the led.

I think my problem lies in understanding this part in the agent.led code:

server.log("Copy this URL to your other agent (otherAgentURL):" + http.agenturl());

receiving the error:
Thu Aug 08 2013 21:31:38 GMT-0500 (CDT): ERROR: class instances do not support the new slot operator Thu Aug 08 2013 21:31:38 GMT-0500 (CDT): ERROR: at set:103

SOLVED.

thanks again for all of your help.

hmm, how did you solve it?

Im having an issue parsing the values coming in. I have a sketch thats reliant on the “tick tock” node, and also receiving incoming values from another agent. is their a way around this since I think all the values are meshing together ?

im trying to understand this example, but its leaving me very confused:

http://devwiki.electricimp.com/doku.php?id=example:inputport&s[]=constructor

Im guessing this is the method to parse numbers that are coming from the agent and the tick tock node? do i even need a tick tock node to simply just fade an LED?

do i even need a tick tock node to simply just fade an LED?

No, you don’t: http://forums.electricimp.com/discussion/1438/out-of-memory-issue#Item_5

Peter