Problem Posting Data to URL

Hello,
I’m trying to simply post some data - status of some switches - onto a webpage. This snippet writes to the php file on our sever when we manually hit this url - so we know the server is listening/responding to get and post requests - though we can’t seem to format the Imp Agent post request in such a way that the server will listen/respond. Any help would be awesome.
Thanks!

php
`

<?php if ( isset( $_REQUEST ) && ! empty( $_REQUEST ) ) { $time = strtotime("now"); file_put_contents('jobs.txt', $time . " WRITING \\r\ "); echo "Received!"; } else { echo "Missed it"; }` Agent `device.on("job1", function(data) { server.log(data); // Set URL to your web service local url = "http://example/imp.php"; // Set Content-Type header to json local headers = { "Content-Type": "application/json" }; // encode data and log local body = http.jsonencode({ message = data }); server.log(body); // send data to your web service http.post(url, headers, body).sendsync(); });` Device `button <- hardware.pin1; function buttonPress() { local state = button.read(); imp.sleep(0.05); if (state == 1) { // when the button is released job1 <- "working" } else { job1 <- "off the clock" } agent.send("job1", job1); } button.configure(DIGITAL_IN_PULLUP, buttonPress);`

looks fine to me except for the “<-” inside the if statement. I would change it to…

`button <- hardware.pin1;

job1 <- “”;

function buttonPress() {
local state = button.read();

imp.sleep(0.05);

if (state == 1) {
// when the button is released
job1 =“working”;
} else {
job1 = “off the clock”;
}
agent.send(“job1”, job1);

}

button.configure(DIGITAL_IN_PULLUP, buttonPress);`

Your agent code looks correct to my eye - assuming you would put your proper and correct path in ‘url’

I don’t know very much about PHP. From some other example I put this together and it has been working.

`<?php
/* sript to recieve the JSON data from the agent

agent sends…
{ “meterdata”: { “I”: 2.72236, “unixtime”: 1385870780, “GMT”: “2013-12-01T04:06:21”, “V”: 122.664, “PF”: 0.917173, “W”: 306.4, “Ipeak”: 2.37886 } }
php input receives
{ “meterdata”: { “I”: 2.72236, “unixtime”: 1385870780, “GMT”: “2013-12-01T04:06:21”, “V”: 122.664, “PF”: 0.917173, “W”: 306.4, “Ipeak”: 2.37886 } }

in the electric imp Agent the table is created like this; the values of this table are modified before sending each point

//{ “meterdata”: { “I”: 2.72236, “unixtime”: 1385870780, “GMT”: “2013-12-01T04:06:21”, “V”: 122.664, “PF”: 0.917173, “W”: 306.4, “Ipeak”: 2.37886 } }

*/
$logfilename = “Sensorlogs/” . “logfilename.csv”; //. $dArray[‘meterdata’][‘flname’]; //The filename to log to

$dArray = json_decode(file_get_contents(‘php://input’),true);//php function json to php array

$HZ = $dArray[‘meterdata’][‘HZ’];//RMS Voltage
$V = $dArray[‘meterdata’][‘V’];//RMS Voltage
$I = $dArray[‘meterdata’][‘I’];//RMS Current
$Ipeak = $dArray[‘meterdata’][‘Ipeak’];//peak DC level at really high (?.? khz) sample speed
$time = $dArray[‘meterdata’][‘GMT’]; //Time and date Agent
$timestamp = $dArray[‘meterdata’][‘unixtime’]; //Linux timestamp from Device
$W = $dArray[‘meterdata’][‘W’]; //The active power in Watts
$VA = $dArray[‘meterdata’][‘VA’]; //The apparant power
$PF = $dArray[‘meterdata’][‘PF’]; //Power Factor

// see http://php.net/manual/en/timezones.php for supported timezones
date_default_timezone_set(“America/Chicago”); //php handles timezones and daylight savings time
$dateTime = date(‘Y-m-d H:i:s’); //‘Y-m-d H:i:s’

$fa = fopen($logfilename, ‘a’); //other is ‘w’ for write

if(flock($fa, LOCK_EX)) {
//fwrite($fa, file_get_contents(‘php://input’) . “
”); //to see the raw message
fwrite($fa, $dateTime . “,” . $timestamp. “,” . ($time) ."," . ($V) ."," . ($I) . “,” . $W . “,” . $Ipeak."," . $PF ."
");

fflush($fa);
flock($fa, LOCK_UN);
}
?>`

In your question you state that you are trying to post some data onto a web page. From what i know, this is not possible. The web page (browser) must initiate a request for information. The web page would do a request to the agent. The agent can respond right away with information on hand or it could send something to the device and wait for a response but of course this causes added lag. You should only need php for logging - and I see that is what you are doing.

EDIT:
MJ beat me to the post … he uses:
$dArray = json_decode(file_get_contents(‘php://input’),true);//php function json to php array

which is basically the same thing I show below.

You are POSTing JSON to your imp.php script.

When the PHP script is executed (by your agent), it needs to see the POSTed variable.

Try this (untested):

<?php $jsonData = file_get_contents('php://input'); $phpArray = json_decode($jsonData); foreach ($phpArray as $key => $value) { $myData = "$key | $value"; } $time = time(); $myString="Timestamp: ".$time." Data: ".$myData." WRITING \\r\ "; file_put_contents('jobs.txt', $myString); ?>

If you wish to post to a web page in “real time”, the web page needs to be using javascripting (JQuery) to either access your .txt file every 10 seconds (or whatever), or request the data from your agent every 10 seconds. A web page will just sit there doing nothing until the browser or the person using it initiates something to happen, such as clicking the refresh button on your browser.

Thanks all for the replies. Here is the updated PHP script that still isn’t catching anything from the Agent:

`<?php

$input = json_decode( file_get_contents(‘php://input’) );

if ( empty( $input ) ) {
$input = print_r($_REQUEST, true);
}
if ( empty( $input ) ) {
$input = $HTTP_RAW_POST_DATA;
}
if ( empty( $input ) ) {
$input = “All methods failed ;(”;
}

$time = date( “m-d-Y h:i:s”, strtotime(“now”) );

file_put_contents(‘jobs.txt’, $time . " " . $input . “\r
”, FILE_APPEND);

die();`

Essentially, we checking the php://input, if that is empty, we check the $_REQUEST global, if that is empty, we grab the $HTTP_RAW_POST_DATA global. If all of those are empty, we print out that all methods have failed.

What’s crazy is that we get zero output from the Agent. It’s as if the agent never hits the url with any kind of request. We’ve verified the url about 100 times. I can do a jQuery AJAX call using jsonp from any domain. I can post a form from another server to that url and get results. We’re also getting a http statuscode of 200 in the Agent, but not message.

Ideas?

json_decode ends-up in an array.

So you have to go through the array and grab all of the keys and values.

Try this:

`<?php
$input = json_decode( file_get_contents(‘php://input’) );

foreach ($input as $key => $value) {
$myData .= "$key , $value | ";
}

$time = date( “m-d-Y h:i:s”, strtotime(“now”) );

file_put_contents(‘jobs.txt’, $time . " " . $myData . “\r
”, FILE_APPEND);

?>`

You can POST multiple values too. It will append them to $myData because of the .=

Example:
{“Username”:“John Smith”, “Day”: “Monday”, “Action”: “IN”}

Your jobs.txt will look like this:

05-12-2014 07:08:20 Username , John Smith | Day , Monday | Action , IN

Thanks mlseim,

Either way, though, something should be output based on the logic of the script, no? Even if $input is empty, the timestamp should still be printed to the file, right?

I’ve updated our script and will test as soon as possible.

Thanks again,
Jacob

Maybe not because your script is failing?
I’m not sure of how you have your PHP error reporting configured.

I’m reporting all errors. And am not seeing any errors reported in my logs. I don’t get errors when I hit the script directly or via any other method (jQuery AJAX, etc).

There is another argument “true” in the code I use

$dArray = json_decode(file_get_contents('php://input'),true);

don’t know exactly what it does as I copied/pasted and hacked this code from someone else. been working really good though…

That argument is to search for the file in the include path, which is irrelevant when dealing with php://input.

-Jacob

Hmmmm…
I tested my script by using another php script to post json, and it works.
Let’s focus on the agent. Also, does your .txt file have proper permissions?

Make sure you can write to it with another php test script.

Focussing on the agent is a great idea. The text file has proper permissions, as I can write to it when I hit the url in any other manner.

Here’s the agent code on more time:

`device.on(“job1”, function(data) {
server.log(data);
// Set URL to your web service
local url = “http://example/imp.php”;

// Set Content-Type header to json
local headers = { “Content-Type”: “application/json” };

// encode data and log
local body = http.jsonencode({ message = data });
server.log(body);

// send data to your web service
http.post(url, headers, body).sendsync();
});`

We know we’re hitting the job1 function because we get output from the server.log(data) line.

Any insight is greatly appreciated.

-Jacob

I added server.log to put out my url to make sure I had it correct. What I did just now is copy/paste the url from the agent log into the address bar and watched the dev tools in chrome.

From what I can see (and test) there is nothing wrong in your agent code. maybe you’d be willing to do the same sanity check on the url that I did?

is there htaccess on this?

`device.on(“job1”, function(data) {

server.log(data);

// Set URL to your web service
local url = _PHPLogScript;

// Set Content-Type header to json
local headers = { “Content-Type”: “application/json” };

// encode data and log
local body = http.jsonencode({ message = “running” });
server.log(body);

// send data to your web service
server.log(url);
http.post(url, headers, body).sendsync();
server.log(“php done”);
});`

Below is a function I use to POST JSON to sendhub for text message.

Notice how the json value is actually JSON format, with the double quotes ‘escaped’, so they go with the string.

You encode your string like this, which should be OK to do…
local body = http.jsonencode({ message = data });

When you view your server log, do the quotes appear?

So this function is basically the same as yours, I see a difference with .sendsync()
I’m not sure what that does.

`function sendSMSStatus()
{
local json = “{“groups”: [“342639” ], “text”: “door : “+a_currentDoorState+””}”;

local req = http.post("https://api.sendhub.com/v1/messages/?username=919YOURNUM&api_key=Your Key GOes here", 
    { "Content-Type" : "application/json" }, json );
      
local res = req.sendsync();
if(res.statuscode != 201) {
    server.log("Error sending SMS");
}
else
{
    server.log("Sent SMS Door State : " + a_currentDoorState );
}

}`

Should this:
local headers = { “Content-Type”: “application/json” };

Be like this?
local headers = “{ “Content-Type”: “application/json” }”;

Thanks guys. I, unfortunately, don’t have direct access to the Imp/Agent code, so will have to wait for my good buddy Zach to get home and run a few tests. Will report back as soon as we can.

Really appreciate your continued support here!

-Jacob

Another thing to try …

Hard-code the entire http.post like in my example function.

I’m not good enough with squirrel to know the syntax of the { } and " "

It just seems like something is different there.

small fyi… these are fine just as shown here. I’ve tested it and my log file gets the text “running” just fine through a php script patterned after what I posted earlier. puzzled…

`local headers = { “Content-Type”: “application/json” };

// encode data and log
local body = http.jsonencode({ message = “running” });`