Я пытаюсь сделать HTTP POST-запрос к регистратору данных SMA, который использует JSON-RPC для ответа на HTTP-запросы.
С помощью hurl.it Я могу сделать успешный запрос, например:
Направление: ПОЧТА, http://aaa.no-ip.org:101/rpc, следовать перенаправлениям: вкл.
Заголовки: Host: aaa.no-ip.org:101, Content-Type: text / plain.
Body: RPC = {«proc»: «GetPlantOverview», «format»: «JSON», «version»: «1.0», «id»: «1»}
затем hurl.it обработать следующий запрос:
Success
POST http://aaa.no-ip.org:101/rpc
200 OK 401 bytes 3.76 secs
HEADERS
Accept: */*
Accept-Encoding: application/json
Content-Length: 122
Content-Type: text/plain
Host: aaa.no-ip.org
User-Agent: runscope/0.1
BODY
RPC=%7B%22proc%22%3A%22GetPlantOverview%22%2C%22format%22%3A%22JSON%22%2C%22version%22%3A%221.0%22%2C%22id%22%3A%221%22%7D
И ответ:
HEADERS
Cache-Control: no-store, no-cache, max-age=0
Connection: keep-alive
Content-Length: 401
Content-Type: text/html
Date: Wed, 22 Oct 2014 14:15:50 GMT
Keep-Alive: 300
Pragma: no-cache
Server: Sunny WebBox
BODY
{"format":"JSON","result":{"overview":[{"unit":"W","meta":"GriPwr","name":"GriPwr","value":"99527"},{"unit":"kWh","meta":"GriEgyTdy","name":"GriEgyTdy","value":"842.849"},{"unit":"kWh","meta":"GriEgyTot","name":"GriEgyTot","value":"2851960.438"},{"unit":"","meta":"OpStt","name":"OpStt","value":""},{"unit":"","meta":"Msg","name":"Msg","value":""}]},"proc":"GetPlantOverview","version":"1.0","id":"1"}
Моя проблема в том, что каждый раз, когда я пытаюсь повторить эти запросы, я всегда получаю:
string(0) ""
Это может быть потому, что я использую общий хост. Я пробовал cURL, обычный PHP (socket и file_get_contents, и даже jQuery.
Может кто-нибудь привести пример того, как сделать этот запрос?
Либо jquery, либо php, мне уже все равно, я пробовал 2 недели и столько попыток, и либо я получаю ошибки кода, либо просто string(0)""
,
PS: примеры предыдущих попыток смотрите: https://stackoverflow.com/questions/26408153/solar-energy-monitoring-sma-webbox-json-post-request
Вот клиент JSONRPC, который я использовал для успешного выполнения HTTP-запросов JSON RPC. Надеюсь это поможет:
Возможно, вам придется изменить некоторые вещи, чтобы работать в вашем коде.
<?php
use Exception;
use ReflectionClass;
/*
* A client for accessing JSON-RPC over HTTP servers.
*
*/
class JsonRpcClient
{
private $_url = false;
private $_reuseConnections = true;
private static $_curl = null;
private $_nextId = 99;
/*
* Creates the client for the given URL.
* @param string $_url
*/
public function __construct($url)
{
$this->_url = $url;
}
/*
* Returns a curl resource.
* @return resource
*/
private function getCurl()
{
if (!isset(self::$_curl)) {
// initialize
self::$_curl = curl_init();
// set options
curl_setopt(self::$_curl, CURLOPT_FAILONERROR, true);
curl_setopt(self::$_curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt(self::$_curl, CURLOPT_FORBID_REUSE, $this->_reuseConnections===false);
curl_setopt(self::$_curl, CURLOPT_FRESH_CONNECT, $this->_reuseConnections===false);
curl_setopt(self::$_curl, CURLOPT_CONNECTTIMEOUT, 5);
return self::$_curl;
}
}
/*
* Invokes the given method with the given arguments
* on the server and returns it's value. If {@code $returnType}
* is specified than an instance of the class that it names
* will be created passing the json object (stdClass) to it's
* constructor.
*
* @param string $method the method to invoke
* @param Array $params the parameters (if any) to the method
* @param string $id the request id
* @param Array $headers any additional headers to add to the request
*/
public function invoke($method, Array $params=Array(), $id=false, Array $headers=Array())
{
// get curl
$curl = $this->getCurl();
// set url
curl_setopt($curl, CURLOPT_URL, $this->_url);
// set post body
$request = json_encode(
Array(
'jsonrpc' => '2.0',
'method' => $method,
'params' => $params,
'id' => ($id===false) ? ++$this->nextId : $id
)
);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// set headers
$curlHeaders = Array();
$curlHeaders []= "Content-type: application/json-rpc";
for (reset($headers); list($key, $value)=each($headers); ) {
$curlHeaders []= $key.": ".$value."\n";
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeaders);
// post the data
$response = curl_exec($curl);
if (!$response) {
throw new Exception('cURL error '.curl_error($curl).' while making request to '.$this->_url);
}
// decode json response
$response = json_decode($response);
if ($response==NULL || curl_error($curl)!=0) {
throw new Exception("JSON parsing error occured: ".json_last_error());
// throw errors
} else if (isset($response->error)) {
$msg = 'JSON-RPC error';
if (isset($response->error->message) && !empty($response->error->message)) {
$msg .= ': "' . $response->error->message . '"';
}
$msg .= "\n";
$msg .= 'URL: ' . $this->_url;
$msg .= "\n";
$msg .= 'Method: ' . $method;
$msg .= "\n";
$msg .= 'Arguments: ' . self::printArguments($params, 2);
if (isset($response->error->code)) {
throw new Exception($msg, intval($response->error->code));
} else {
throw new Exception($msg);
}
}
// get the headers returns (APPSVR, JSESSIONID)
$responsePlusHeaders = Array();
$responsePlusHeaders['result'] = $response->result;
$responsePlusHeaders['headers'] = curl_getinfo($curl);
// return the data
return $responsePlusHeaders;
}
/*
* Printing arguments.
* @param $arg
* @param $depth
*/
private static function printArguments($args, $depth=1)
{
$argStrings = Array();
foreach ($args as $arg) {
$argStrings[] = self::printArgument($arg, $depth);
}
return implode($argStrings, ', ');
}
/*
* Print an argument.
* @param $arg
* @param $depth
*/
private static function printArgument($arg, $depth=1)
{
if ($arg === NULL) {
return 'NULL';
} else if (is_array($arg)) {
if ($depth > 1) {
return '[' . self::printArguments($arg, ($depth - 1)) . ']';
} else {
return 'Array';
}
} else if (is_object($arg)) {
return 'Object';
} else if (is_bool($arg)) {
return ($arg === TRUE) ? 'true' : 'false';
} else if (is_string($arg)) {
return "'$arg'";
}
return strval($arg);
}
}
Использование тогда будет:
include JsonRpcClient.php$client = new JsonRpcClient('http://aaa.no-ip.org:101/rpc');
$response = $client->invoke('GetPlantOverview', 1, array('Host: aaa.no-ip.org:101'));
Других решений пока нет …