I am working on a web site where users can control their thermostat, but I'm having difficulty with the schedule part. I can display it, but when I create a new schedule the temperature desired is not applied, but works in postman. Here's my code:
Script.php
class ConnectTuya
{
private $_baseUrl;
private $_deviceId;
private $_clientId;
private $_secret_key;
private $_getToken;
private $_fDevices;
private $_aDevices;
private $_bDevices;
private $_t;
public function __construct()
{
$this->_baseUrl = 'https://openapi.tuyaeu.com/';
$this->_clientId = 'xxxxxxxxxxxxxxxxxxxxxx';
$this->_secret_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
$this->_getToken = "v1.0/token?grant_type=1";
$this->_t = round(microtime(true) * 1000);
$this->_fDevices = 'v1.0/iot-03/devices/';
$this->_aDevices = 'v1.0/devices/';
$this->_bDevices = 'v2.0/cloud/timer/device/';
}
public function get_token()
{
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: '.$this->_clientId,
't: '.$this->_t,
'Content-Type: application/json',
'access_token:'
);
$url = $this->_baseUrl . $this->_getToken;
$sign = $this->build_sign('GET', $url, [], []);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function get_specification($device_id, $access_token)
{
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: '.$this->_clientId,
't: '.$this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'GET';
$payload = array(
'device_id' => $device_id
);
$url = $this->_baseUrl . $this->_fDevices . $device_id . '/specification';
$sign = $this->build_sign($method, $url, [], [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function send_commands($device_id, $commands ,$access_token)
{
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: '.$this->_clientId,
't: '.$this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'POST';
if (empty($commands)) {
return false;
}
$payload = array(
"commands" => $commands
);
$url = $this->_baseUrl . $this->_fDevices . $device_id . '/commands';
$sign = $this->build_sign($method, $url, $payload, [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function get_scheduled($device_id, $access_token)
{
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: '.$this->_clientId,
't: '.$this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'GET';
$payload = array(
'device_id' => $device_id
);
$url = $this->_baseUrl . $this->_bDevices . $device_id ;
$sign = $this->build_sign($method, $url, [], [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function add_scheduled($device_id,$temp_add, $time, $loops, $access_token) {
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: ' . $this->_clientId,
't: ' . $this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'POST';
$payload = array(
"alias_name" => "Scheduled",
"category" => "Scheduled",
"time" => $time,
"timezone_id" => "Europe/Paris",
"loops" => $loops,
"functions" => array(
array(
"code" => "switch_1",
"value" => true
),
array(
"code" => "temp_set",
"value" => array("Value" =>strval($temp_add))
),
array(
"code" => "customize_mode_switch",
"value" => true
)
)
);
$url = $this->_baseUrl . $this->_bDevices . $device_id;
$sign = $this->build_sign($method, $url, $payload, [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function get_device_information($device_id, $access_token)
{
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: '.$this->_clientId,
't: '.$this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'GET';
$payload = array(
'device_id' => $device_id
);
$url = $this->_baseUrl . $this->_aDevices . $device_id . '/';
$sign = $this->build_sign($method, $url, [], [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function delete_scheduled($device_id, $timer_id, $access_token) {
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: ' . $this->_clientId,
't: ' . $this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'DELETE';
$url = $this->_baseUrl . $this->_bDevices . $device_id . '/batch?timer_ids=' . $timer_id;
$sign = $this->build_sign($method, $url, [], [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function modeVacance($device_id,$access_token, $idVacance, $mode){
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: ' . $this->_clientId,
't: ' . $this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'PUT';
$payload = array(
"timer_id" => $idVacance,
"enable" => $mode
);
$url = $this->_baseUrl . $this->_bDevices . $device_id . '/state';
$sign = $this->build_sign($method, $url, $payload, [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function modeVacanceOther($device_id,$access_token, $idVacance, $mode){
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: ' . $this->_clientId,
't: ' . $this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'PUT';
$payload = array(
"timer_id" => $idVacance,
"enable" => $mode
);
$url = $this->_baseUrl . $this->_bDevices . $device_id . '/state';
$sign = $this->build_sign($method, $url, $payload, [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
public function add_scheduled_Vacence($device_id,$access_token){
$headers = array(
'sign_method: HMAC-SHA256',
'client_id: ' . $this->_clientId,
't: ' . $this->_t,
'Content-Type: application/json',
'access_token: ' . $access_token
);
$method = 'POST';
$payload = array(
"alias_name" => "Scheduled-Vacance",
"category" => "Scheduled-Vacance",
"time" => "00:00",
"timezone_id" => "Europe/Paris",
"loops" => "1111111",
"functions" => array(
array(
"code" => "switch_1",
"value" => true
),
array(
"code" => "temp_set",
"value" => 120
),
array(
"code" => "customize_mode_switch",
"value" => true
)
)
);
$url = $this->_baseUrl . $this->_bDevices . $device_id;
$sign = $this->build_sign($method, $url, $payload, [], $access_token);
$headers[] = "sign: " . $sign;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => $headers
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
private function build_sign($method, $url ,$payload, $headers, $token = "")
{
$str_header = "";
if ($headers) {
$str_header = implode("\n", $headers);
}
$str_payload = "";
if ($payload) {
$str_payload = json_encode($payload);
}
$content_SHA256 = hash('sha256', $str_payload);
$parse_url = parse_url($url);
$part_url = empty($parse_url['path']) ? "" : $parse_url['path'];
$query_url = empty($parse_url['query']) ? "" : "?" . $parse_url['query'];
$str_to_sign = $method . "\n" . $content_SHA256 . "\n" . $str_header . "\n" . $part_url . $query_url;
$sign = strtoupper(hash_hmac('SHA256', $this->_clientId . $token . $this->_t . $str_to_sign, $this->_secret_key));
return $sign;
}
}
$ConnexionTuya = new ConnectTuya();
The add_scheduled function is my only big problem
index.php
if(isset ($_POST['time_add']) && isset ($_POST['day_add']) && isset ($_POST['temp_add'])){
$time_add = $_POST['time_add'];
$loops_add = $_POST['day_add'];
$temp_add = $_POST['temp_add'];
$time_add = strval($time_add);
$loops_add = strval($loops_add);
$add_schedule = $ConnexionTuya->add_scheduled($device_id,$temp_add, $time_add, $loops_add, $access_token['result']['access_token']);
print_r($add_schedule);
}
For the error I got it's when I do it in postman :
{
"alias_name": "Scheduled",
"category": "Scheduled",
"date": "00000000",
"enable": true,
"functions": [
{
"code": "switch_1",
"value": true
},
{
"code": "temp_set",
"value": {
"Value": "160.0"
}
},
{
"code": "customize_mode_switch",
"value": true
}
],
"loops": "0100000",
"time": "08:00",
"timer_id": "320383673",
"timezone_id": "Europe/Paris"
}
and if i do it in my web site :
{
"alias_name": "Scheduled",
"category": "Scheduled",
"date": "00000000",
"enable": true,
"functions": [
{
"code": "switch_1",
"value": true
},
{
"code": "temp_set",
"value": {
"value": "160.0"
}
},
{
"code": "customize_mode_switch",
"value": true
}
],
"loops": "0100000",
"time": "12:48",
"timer_id": "320385032",
"timezone_id": "Europe/Paris"
}
The issue is that when I execute my add_schedule function, it succeeds, but the result in the temp_set code sets the value as value:temp. For it to function properly, I require the value to be Value:temp.
I try using all I know and the GitHub of the script: https://github.com/hao159/tuya-connect-php
In postman:
The web site:




If you check the
send_commands()method, you can see that it passes the$payloadtobuild_sign()as an array, notjson_encode()d.If you trace through
build_sign(), you can see itjson_encode()s the payload it receives.But if you compare that to
add_scheduled()- which I understand is the method that is not working - you are passingbuild_sign()an alreadyjson_encode()d payload.build_sign()willjson_encode()that a second time, and I guess that is a problem.Try passing the payload as the original array: