nest.class.php
protected function doRequest($method, $url, $data_fields = NULL, $with_retry = TRUE) {
        $ch = curl_init();
        if ($url[0] == '/') {
            $url = $this->transport_url . $url;
        }
        $headers = array('X-nl-protocol-version: ' . self::PROTOCOL_VERSION);
        if (isset($this->userid)) {
            $headers[] = 'X-nl-user-id: ' . $this->userid;
            $headers[] = 'Authorization: Basic ' . $this->access_token;
        }
        if (is_array($data_fields)) {
            $data = array();
            foreach ($data_fields as $k => $v) {
                $data[] = "$k=" . urlencode($v);
            }
            $data = implode('&', $data);
        } elseif (is_string($data_fields)) {
            $data = $data_fields;
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
        curl_setopt($ch, CURLOPT_USERAGENT, self::USER_AGENT);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie_file);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file);
        if ($method == 'POST') {
            if (!isset($data)) {
                throw new RuntimeException("Error: You need to specify \$data when sending a POST.");
            }
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            $headers[] = 'Content-length: ' . strlen($data);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); // for security this should always be set to true.
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    // for security this should always be set to 2.
        curl_setopt($ch, CURLOPT_SSLVERSION, 1);        // Nest servers now require TLSv1; won't work with SSLv2 or even SSLv3!

        // Update cacert.pem (valid CA certificates list) from the cURL website once a month
        $curl_cainfo = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'cacert.pem';
        $last_month = time()-30*24*60*60;
        if (!file_exists($curl_cainfo) || filemtime($curl_cainfo) < $last_month || filesize($curl_cainfo) < 100000) {
            $certs = static::getCURLCerts();
            if ($certs) {
                file_put_contents($curl_cainfo, $certs);
            }
        }
        if (file_exists($curl_cainfo) && filesize($curl_cainfo) > 100000) {
            curl_setopt($ch, CURLOPT_CAINFO, $curl_cainfo);
        }
        $response = curl_exec($ch);
        $info = curl_getinfo($ch);

        if ($info['http_code'] == 401 || (!$response && curl_errno($ch) != 0)) {
            if ($with_retry && $this->use_cache()) {
                // Received 401, and was using cached data; let's try to re-login and retry.
                @unlink($this->cookie_file);
                @unlink($this->cache_file);
                if ($info['http_code'] == 401) {
                    $this->login();
                }
                return $this->doRequest($method, $url, $data_fields, !$with_retry);
            } else {
                throw new RuntimeException("Error: HTTP request to $url returned an error: " . curl_error($ch), curl_errno($ch));
            }
        }

        $json = json_decode($response);
        if (!is_object($json) && ($method == 'GET' || $url == self::LOGIN_URL)) {
            if (strpos($response, "currently performing maintenance on your Nest account") !== FALSE) {
                throw new RuntimeException("Error: Account is under maintenance; API temporarily unavailable.", NESTAPI_ERROR_UNDER_MAINTENANCE);
            }
            if (empty($response)) {
                throw new RuntimeException("Error: Received empty response from request to $url.", NESTAPI_ERROR_EMPTY_RESPONSE);
            }
            throw new RuntimeException("Error: Response from request to $url is not valid JSON data. Response: " . str_replace(array("\n","\r"), '', $response), NESTAPI_ERROR_NOT_JSON_RESPONSE);
        }

        if ($info['http_code'] == 400) {
            if (!is_object($json)) {
                throw new RuntimeException("Error: HTTP 400 from request to $url. Response: " . str_replace(array("\n","\r"), '', $response), NESTAPI_ERROR_API_OTHER_ERROR);
            }
            throw new RuntimeException("Error: HTTP 400 from request to $url. JSON error: $json->error - $json->error_description", NESTAPI_ERROR_API_JSON_ERROR);
        }

        // No body returned; return a boolean value that confirms a 200 OK was returned.
        if ($info['download_content_length'] == 0) {
            return $info['http_code'] == 200;
        }

        return $json;
    }
protected function doRequest($method, $url, $data_fields = NULL, $with_retry = TRUE) {
        $ch = curl_init();
        if ($url[0] == '/') {
            $url = $this->transport_url . $url;
        }
        $headers = array('X-nl-protocol-version: ' . self::PROTOCOL_VERSION);
        if (isset($this->userid)) {
            $headers[] = 'X-nl-user-id: ' . $this->userid;
            $headers[] = 'Authorization: Basic ' . $this->access_token;
        }
        if (is_array($data_fields)) {
            $data = array();
            foreach ($data_fields as $k => $v) {
                $data[] = "$k=" . urlencode($v);
            }
            $data = implode('&', $data);
        } elseif (is_string($data_fields)) {
            $data = $data_fields;
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
        curl_setopt($ch, CURLOPT_USERAGENT, self::USER_AGENT);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie_file);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file);
        if ($method == 'POST') {
            if (!isset($data)) {
                throw new RuntimeException("Error: You need to specify \$data when sending a POST.");
            }
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            $headers[] = 'Content-length: ' . strlen($data);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); // for security this should always be set to true.
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    // for security this should always be set to 2.
        curl_setopt($ch, CURLOPT_SSLVERSION, 1);        // Nest servers now require TLSv1; won't work with SSLv2 or even SSLv3!

        // Update cacert.pem (valid CA certificates list) from the cURL website once a month
        $curl_cainfo = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'cacert.pem';
        $last_month = time()-30*24*60*60;
        if (!file_exists($curl_cainfo) || filemtime($curl_cainfo) < $last_month || filesize($curl_cainfo) < 100000) {
            $certs = static::getCURLCerts();
            if ($certs) {
                file_put_contents($curl_cainfo, $certs);
            }
        }
        if (file_exists($curl_cainfo) && filesize($curl_cainfo) > 100000) {
            curl_setopt($ch, CURLOPT_CAINFO, $curl_cainfo);
        }
        $response = curl_exec($ch);
        $info = curl_getinfo($ch);

        if ($info['http_code'] == 401 || (!$response && curl_errno($ch) != 0)) {
            if ($with_retry && $this->use_cache()) {
                // Received 401, and was using cached data; let's try to re-login and retry.
                @unlink($this->cookie_file);
                @unlink($this->cache_file);
                if ($info['http_code'] == 401) {
                    $this->login();
                }
                return $this->doRequest($method, $url, $data_fields, !$with_retry);
            } else {
                throw new RuntimeException("Error: HTTP request to $url returned an error: " . curl_error($ch), curl_errno($ch));
            }
        }

        $json = json_decode($response);
        if (!is_object($json) && ($method == 'GET' || $url == self::LOGIN_URL)) {
            if (strpos($response, "currently performing maintenance on your Nest account") !== FALSE) {
                throw new RuntimeException("Error: Account is under maintenance; API temporarily unavailable.", NESTAPI_ERROR_UNDER_MAINTENANCE);
            }
            if (empty($response)) {
                throw new RuntimeException("Error: Received empty response from request to $url.", NESTAPI_ERROR_EMPTY_RESPONSE);
            }
            throw new RuntimeException("Error: Response from request to $url is not valid JSON data. Response: " . str_replace(array("\n","\r"), '', $response), NESTAPI_ERROR_NOT_JSON_RESPONSE);
        }

        if ($info['http_code'] == 400) {
            if (!is_object($json)) {
                throw new RuntimeException("Error: HTTP 400 from request to $url. Response: " . str_replace(array("\n","\r"), '', $response), NESTAPI_ERROR_API_OTHER_ERROR);
            }
            throw new RuntimeException("Error: HTTP 400 from request to $url. JSON error: $json->error - $json->error_description", NESTAPI_ERROR_API_JSON_ERROR);
        }

        // No body returned; return a boolean value that confirms a 200 OK was returned.
        if ($info['download_content_length'] == 0) {
            return $info['http_code'] == 200;
        }

        return $json;
    }
Send a HTTP request.

@param string       $method      HTTP method: GET or POST
@param string       $url         URL
@param array|string $data_fields Data to send via POST.
@param bool         $with_retry  Retry if request fails?

@return stdClass|bool JSON-decoded object, or boolean if no response was returned.

@throws RuntimeException