导航链接
(1)香橙派+apache2与php+天猫精灵=自建平台语音支持--前言
(2)香橙派+apache2与php+天猫精灵=自建平台语音支持--香橙派操作系统安装
(3)香橙派+apache2与php+天猫精灵=自建平台语音支持--香橙派环境配置
(4)香橙派+apache2与php+天猫精灵=自建平台语音支持--apache2与php
(5)香橙派+apache2与php+天猫精灵=自建平台语音支持--MariaDB的安装
(6)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接1
(7)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接2
(8)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接3
(9)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接4
(10)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接5
(11)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接6
(12)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接7
设备查询
还是先上个时序图,看图基本功能也就都知道了。
下图为设备响应指令的详细协议以及协议的解析和响应
case 'AliGenie.Iot.Device.Query': {error_log('----case in Query----');$result = device_status($obj, $messageId);break;}
协议的解析和设备控制协议的解析采用的思想差不多,只不过查询和控制这两个过程是正好相反的。过程控制是主动存储数据,然后又硬件设备读取,查询是硬件设备返回数据存储到服务器上在查询的时候读取。就这样,具体的代码看aligenies_handle.php中的内容吧,这里会调用存储读取的具体PHP。
function device_status($obj, $messageId)
{error_log('----device_status in----');global $sqlFileName;$deviceId = $obj->payload->deviceId;$action = '';$deviceType = check_type_from_id($deviceId);switch ($obj->header->name) {case 'QueryPowerState':$action = 'powerstate';break;case 'QueryColor':$action = 'color';break;case "QueryTemperature":$action = "temperature";break;case "QueryWindspeed":$action = "windspeed";break;case "QueryBrightness":$action = "brightness";break;case "QueryFog":$action = "fog";break;case "QueryHumidity":$action = "humidity";break;case "QueryPm25":$action = "pm25";break;case "QueryChannel":$action = "channel";break;case "QueryNumber":$action = "number";break;case "QueryDirection":$action = "direction";break;case "QueryAngle":$action = "angle";break;case "QueryAnion":$action = "anion";break;case "QueryEffluent":$action = "effluent";break;case "QueryMode":$action = "mode";break;case "QueryLeftTime":$action = "lefttime";break;case "QueryRemoteStatus":$action = "remotestatus";break;case "QueryOnlineState":$action = "onlinestate";break;case "QueryColorTemperature":$action = "colorTemperature";break;case "Query":$action = "all";break;default:$action = "";} if ($action == "" || $deviceType == "") {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("DEVICE_NOT_SUPPORT_FUNCTION");$retJson = json_encode($ret);return $retJson;}$properties = array();$findDevice = false;$queryValue = '';if (($txtRes = fopen($sqlFileName, "r")) === false) {error_log('----get_control fopen failed----');$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_OPEN");$retJson = json_encode($ret);return $retJson;}$str = fread($txtRes, filesize($sqlFileName));$sqlObj = json_decode($str);$devArray = $sqlObj->dev_array;$ret = new AliGenie\QueryResponse();$ret->header->putResponseName($obj->header->name);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);foreach ($devArray as $data) {error_log('entity_id-->'.$data->entity_id);error_log('device_type-->'.$data->device_type);if ($data->entity_id == $deviceId) {$findDevice = true;switch ($data->device_type) {case 'ceiling_lamp': {$brightnessWhite = '';$brightnessYellow = '';foreach ($data->properties as $element) {error_log('name-->'.$element->name);error_log('value-->'.$element->value);if ($element->name =='brightness_w') {$brightnessWhite = $element->value;} elseif ($element->name =='brightness_y') {$brightnessYellow = $element->value;} else {$properties[$element->name] = $element->value;}}$properties['brightness'] = ($brightnessWhite>$brightnessYellow)?$brightnessWhite:$brightnessYellow;if ($brightnessWhite != 0 && $brightnessYellow == 0) {$properties['color'] = 'White';} elseif ($brightnessWhite == 0 && $brightnessYellow != 0) {$properties['color'] = 'Yellow';} elseif ($brightnessWhite == $brightnessYellow && $brightnessYellow != 0) {$properties['mode'] = '自然模式';}break;}}}}fclose($txtRes);if ($action != 'all') {$queryValue = $properties[$obj->header->name];array_splice($properties, 0);$properties[$obj->header->name] = $queryValue;}foreach ($properties as $name => $value) {$pro = new AliGenie\QueryPropertie($name, $value);$ret->properties[] = $pro;}if ($findDevice == false) {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("DEVICE_IS_NOT_EXIST");$retJson = json_encode($ret);return $retJson;} else if ($queryValue == '' && $action != 'all') {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("INVALIDATE_PARAMS");$retJson = json_encode($ret);return $retJson;}$retJson = json_encode($ret);error_log('----device_status out----');return $retJson;
}
到这里所有的文件部署完毕,我们现在天猫精灵上新建一个智能家居,用于真机测试。
下面是
aligenies_gate.php和aligenies_handle.php完整文件的代码。
aligenies_gate.php
<?php
error_log('----aligenies_gate.php in----');
require_once __DIR__.'/aligenies_handle.php';$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars,0,8) . '-';
$uuid .= substr($chars,8,4) . '-';
$uuid .= substr($chars,12,4) . '-';
$uuid .= substr($chars,16,4) . '-';
$uuid .= substr($chars,20,12);$postStr = file_get_contents("php://input");
$obj = json_decode($postStr);
$messageId = $uuid;
error_log('get-request->'.$postStr);
switch ($obj->header->namespace) {case 'AliGenie.Iot.Device.Discovery': {error_log('----case in Discovery----');$result = device_discovery($messageId);break;}case 'AliGenie.Iot.Device.Control': {error_log('----case in Control----');$result = device_control($obj, $messageId);break;}case 'AliGenie.Iot.Device.Query': {error_log('----case in Query----');$result = device_status($obj, $messageId);break;}default: {$result='Nothing return,there is an error~!!';}
}
echo($result);
error_log('----reseponse----');
error_log($result);
error_log('----aligenies_gate.php out----');
?>
aligenies_handle.php
<?php
require_once __DIR__.'/DiscoveryResponse.php';
require_once __DIR__.'/ControlResponse.php';
require_once __DIR__.'/QueryResponse.php';$sqlFileName = "../sqldata.txt";function device_discovery($messageId)
{error_log('----device_discovery in----');global $sqlFileName;if (($txtRes = fopen($sqlFileName, "r")) === false) {error_log('----gate_implement fopen failed----');$ret = new AliGenie\DiscoveryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_OPEN");$retJson = json_encode($ret);return $retJson;}$str = fread($txtRes, filesize($sqlFileName));error_log("str-->".$str);$obj = json_decode($str);$ret = new AliGenie\DiscoveryResponse();$ret->header->putResponseMessageId($messageId);foreach ($obj->dev_array as $devElement) {error_log('entity_id-->'.$devElement->entity_id);switch ($devElement->device_type) {case 'ceiling_lamp': {$dev = new AliGenie\DiscoveryDevice();$dev->putResponseDeviceInfo($devElement->entity_id, "吸顶灯", device_id_to_devicetype($devElement->entity_id), "https://www.rtplay.cn/icon/td.png");$dev->actions = array("TurnOn","TurnOff","SetBrightness","SetColor","AdjustUpBrightness","AdjustDownBrightness","QueryBrightness","QueryPowerState","QueryColor","Query");$brightnessWhite = '';$brightnessYellow = '';foreach ($devElement->properties as $propertie) {if ($propertie->name =='brightness_w') {$brightnessWhite = $propertie->value;} elseif ($propertie->name =='brightness_y') {$brightnessYellow = $propertie->value;} else {$pro = new AliGenie\DiscoveryPropertie($propertie->name, $propertie->value);$dev->putResponseProperties($pro);}}$brightness = ($brightnessWhite>$brightnessYellow)?$brightnessWhite:$brightnessYellow;$pro = new AliGenie\DiscoveryPropertie("brightness", $brightness);$dev->putResponseProperties($pro);if ($brightnessWhite == 100 && $brightnessYellow == 0) {$pro = new AliGenie\DiscoveryPropertie("color", "White");$dev->putResponseProperties($pro);} elseif ($brightnessWhite == 0 && $brightnessYellow == 100) {$pro = new AliGenie\DiscoveryPropertie("color", "Yellow");$dev->putResponseProperties($pro);} elseif ($brightnessWhite == $brightnessYellow && $brightnessYellow != 0) {$pro = new AliGenie\DiscoveryPropertie("mode", "自然模式");$dev->putResponseProperties($pro);}$ext = new AliGenie\DiscoveryExtension();$dev->putResponseExtensions($ext);$ret->payload->putResponseDevices($dev);break;}case 'gateway_switch': {$dev = new AliGenie\DiscoveryDevice();$dev->putResponseDeviceInfo($devElement->entity_id, "插排", device_id_to_devicetype($devElement->entity_id), "https://www.rtplay.cn/icon/cz.png");$dev->actions = array("TurnOn","TurnOff","QueryPowerState","Query");foreach ($devElement->properties as $propertie) {$pro = new AliGenie\DiscoveryPropertie($propertie->name, $propertie->value);$dev->putResponseProperties($pro);}$ext = new AliGenie\DiscoveryExtension();$dev->putResponseExtensions($ext);$ret->payload->putResponseDevices($dev);break;}}}$retJson = json_encode($ret);error_log('retJson-->'.$retJson);error_log('----device_discovery out----');return $retJson;
}function device_status($obj, $messageId)
{error_log('----device_status in----');global $sqlFileName;$deviceId = $obj->payload->deviceId;$action = '';$deviceType = check_type_from_id($deviceId);switch ($obj->header->name) {case 'QueryPowerState':$action = 'powerstate';break;case 'QueryColor':$action = 'color';break;case "QueryTemperature":$action = "temperature";break;case "QueryWindspeed":$action = "windspeed";break;case "QueryBrightness":$action = "brightness";break;case "QueryFog":$action = "fog";break;case "QueryHumidity":$action = "humidity";break;case "QueryPm25":$action = "pm25";break;case "QueryChannel":$action = "channel";break;case "QueryNumber":$action = "number";break;case "QueryDirection":$action = "direction";break;case "QueryAngle":$action = "angle";break;case "QueryAnion":$action = "anion";break;case "QueryEffluent":$action = "effluent";break;case "QueryMode":$action = "mode";break;case "QueryLeftTime":$action = "lefttime";break;case "QueryRemoteStatus":$action = "remotestatus";break;case "QueryOnlineState":$action = "onlinestate";break;case "QueryColorTemperature":$action = "colorTemperature";break;case "Query":$action = "all";break;default:$action = "";} if ($action == "" || $deviceType == "") {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("DEVICE_NOT_SUPPORT_FUNCTION");$retJson = json_encode($ret);return $retJson;}$properties = array();$findDevice = false;$queryValue = '';if (($txtRes = fopen($sqlFileName, "r")) === false) {error_log('----get_control fopen failed----');$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_OPEN");$retJson = json_encode($ret);return $retJson;}$str = fread($txtRes, filesize($sqlFileName));$sqlObj = json_decode($str);$devArray = $sqlObj->dev_array;$ret = new AliGenie\QueryResponse();$ret->header->putResponseName($obj->header->name);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);foreach ($devArray as $data) {error_log('entity_id-->'.$data->entity_id);error_log('device_type-->'.$data->device_type);if ($data->entity_id == $deviceId) {$findDevice = true;switch ($data->device_type) {case 'ceiling_lamp': {$brightnessWhite = '';$brightnessYellow = '';foreach ($data->properties as $element) {error_log('name-->'.$element->name);error_log('value-->'.$element->value);if ($element->name =='brightness_w') {$brightnessWhite = $element->value;} elseif ($element->name =='brightness_y') {$brightnessYellow = $element->value;} else {$properties[$element->name] = $element->value;}}$properties['brightness'] = ($brightnessWhite>$brightnessYellow)?$brightnessWhite:$brightnessYellow;if ($brightnessWhite != 0 && $brightnessYellow == 0) {$properties['color'] = 'White';} elseif ($brightnessWhite == 0 && $brightnessYellow != 0) {$properties['color'] = 'Yellow';} elseif ($brightnessWhite == $brightnessYellow && $brightnessYellow != 0) {$properties['mode'] = '自然模式';}break;}}}}fclose($txtRes);if ($action != 'all') {$queryValue = $properties[$obj->header->name];array_splice($properties, 0);$properties[$obj->header->name] = $queryValue;}foreach ($properties as $name => $value) {$pro = new AliGenie\QueryPropertie($name, $value);$ret->properties[] = $pro;}if ($findDevice == false) {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("DEVICE_IS_NOT_EXIST");$retJson = json_encode($ret);return $retJson;} else if ($queryValue == '' && $action != 'all') {$ret = new AliGenie\QueryResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseDeviceId($deviceId);$ret->payload->putResponseError("INVALIDATE_PARAMS");$retJson = json_encode($ret);return $retJson;}$retJson = json_encode($ret);error_log('----device_status out----');return $retJson;
}function device_control($obj, $messageId)
{error_log('----device_control in----');global $sqlFileName;$deviceId = $obj->payload->deviceId;$action = '';$deviceType = '';//Customize device type$deviceType = device_id_to_type($deviceId);error_log("deviceType-->".$deviceType);$action = get_control_action($obj->header->name);error_log("action-->".$action);if ($action == "" || $deviceType == "") {error_log('----get_control_action failed----');$ret = new AliGenie\ControlResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("SERVICE_ERROR", "action or device not support,name:".$obj->header->name." device:".substr($deviceId,0,stripos($deviceId,".")));$retJson = json_encode($ret);return $retJson;}$validArray = array ("deviceId" => $deviceId,"deviceType" => $deviceType,"actionName" => $obj->header->name,"action" => $action,"attribute" => $obj->payload->attribute,"value" => $obj->payload->value);$checkResult = control_checker($validArray);if ($checkResult != 'succeed') {error_log('----control_checker failed----');$ret = new AliGenie\ControlResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("DEVICE_NOT_SUPPORT_FUNCTION");$retJson = json_encode($ret);return $retJson;}//-----------------------------------if (($txtRes = fopen($sqlFileName, "r+")) === false) {error_log('----get_control fopen failed----');$ret = new AliGenie\ControlResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_OPEN");$retJson = json_encode($ret);return $retJson;}$str = fread($txtRes, filesize($sqlFileName));error_log("str-->".$str);$sqlObj = json_decode($str);//error_log("sqlObj-->".print_r($sqlObj, true));$ret = new AliGenie\ControlResponse();$ret->header->putResponseMessageId($messageId);$ret->header->putResponseName($obj->header->name);$ret->payload->putResponseDeviceId($obj->payload->deviceId);foreach ($sqlObj->dev_array as $devElement) {error_log('entity_id-->'.$devElement->entity_id);if ($devElement->entity_id == $validArray['deviceId']) {$ret->payload->putResponseDeviceId($devElement->entity_id);switch ($devElement->device_type) {case 'ceiling_lamp': {switch ($validArray['action']) {case 'turn_on': {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "powerstate") {$propertie->value = "on";break;}}break;}case 'turn_off': {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "powerstate") {$propertie->value = "off";break;}}break;}case 'bright_set': {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w" && $propertie->value != 0) {$propertie->value = $validArray['value'];} else if ($propertie->name == "brightness_y" && $propertie->value != 0) {$propertie->value = $validArray['value'];}}break;}case 'bright_up': {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w" && $propertie->value != 0) {$propertie->value += $validArray['value'];if ($propertie->value > 100) {$propertie->value = 100;}} else if ($propertie->name == "brightness_y" && $propertie->value != 0) {$propertie->value += $validArray['value'];if ($propertie->value > 100) {$propertie->value = 100;}}if ($propertie->name == "powerstate") {$propertie->value = "on";break;}}break;}case 'bright_down': {$brightnessWhite = '10';$brightnessYellow = '10';foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w" && $propertie->value != 0) {$propertie->value -= $validArray['value'];if ($propertie->value < 0) {$propertie->value = 0;}$brightnessWhite = $propertie->value;} else if ($propertie->name == "brightness_y" && $propertie->value != 0) {$propertie->value -= $validArray['value'];if ($propertie->value < 0) {$propertie->value = 0;}$brightnessYellow = $propertie->value;}if ($brightnessWhite == 0 && $brightnessYellow == 0) {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "powerstate") {$propertie->value = "off";break;}}}}break;}case 'mode_set': {$brightnessWhite = '0';$brightnessYellow = '0';foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w") {$brightnessWhite = $propertie->value;} else if ($propertie->name == "brightness_y") {$brightnessYellow = $propertie->value;}}$brightness = ($brightnessWhite>$brightnessYellow)?$brightnessWhite:$brightnessYellow;foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w" || $propertie->name == "brightness_y") {$propertie->value = $brightness;}}break;}case 'color_set': {if ($validArray['value'] == 'White') {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w") {$propertie->value = 100;} else if ($propertie->name == "brightness_y") {$propertie->value = 0;}}} else if ($validArray['value'] == 'Yellow') {foreach ($devElement->properties as $propertie) {error_log('name-->'.$propertie->name);if ($propertie->name == "brightness_w") {$propertie->value = 0;} else if ($propertie->name == "brightness_y") {$propertie->value = 100;}}}break;}}break;}}}}$jsonData = json_encode($sqlObj);error_log('jsonData-->'.$jsonData);fclose($txtRes);if (($txtRes = fopen($sqlFileName, "w+")) === false) {error_log('----get_control fopen failed----');$ret = new AliGenie\ControlResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_OPEN");$retJson = json_encode($ret);return $retJson;}if (!fwrite($txtRes, $jsonData)) {fclose($txtRes);error_log('----get_control fwrite failed----');$ret = new AliGenie\ControlResponse(true);$ret->header->putResponseMessageId($messageId);$ret->payload->putResponseError("SERVICE_ERROR", "CANNOT_WRITE");$retJson = json_encode($ret);return $retJson;}fclose($txtRes);$retJson = json_encode($ret);error_log('----device_control out----');return $retJson;
}function check_type_from_id($deviceId)
{$deviceType = device_id_to_type($deviceId);if ($deviceType != 'ceiling_lamp' && $deviceType != 'gateway_switch') {$deviceType = "";}return $deviceType;
}function get_control_action($controlName)
{$action = "";switch ($controlName) {case 'TurnOn':$action = 'turn_on';break;case 'TurnOff':$action = 'turn_off';break;case 'SelectChannel':$action = 'channel_set';break;case 'AdjustUpChannel':$action = 'channel_up';break;case 'AdjustDownChannel':$action = 'channel_down';break;case 'AdjustUpVolume':$action = 'volume_up';break;case 'AdjustDownVolume':$action = 'volume_down';break;case 'SetVolume':$action = 'volume_set';break;case 'SetMute':$action = 'mute_set';break;case 'CancelMute':$action = 'mute_cancel';break;case 'Play':$action = 'play';break;case 'Pause':$action = 'pause';break;case 'Continue':$action = 'continue';break;case 'Next':$action = 'next';break;case 'Previous':$action = 'previous';break;case 'SetBrightness':$action = 'bright_set';break;case 'AdjustUpBrightness':$action = 'bright_up';break;case 'AdjustDownBrightness':$action = 'bright_down';break;case 'SetTemperature':$action = 'temperature_set';break;case 'AdjustUpTemperature':$action = 'temperature_up';break;case 'AdjustDownTemperature':$action = 'temperature_down';break;case 'SetWindSpeed':$action = 'windspeed_set';break;case 'AdjustUpWindSpeed':$action = 'WindSpeed_up';break;case 'AdjustDownWindSpeed':$action = 'WindSpeed_down';break;case 'SetMode':$action = 'mode_set';break;case 'SetColor':$action = 'color_set';break;case 'OpenFunction':$action = 'function_open';break;case 'CloseFunction':$action = 'function_close';break;case 'Cancel':$action = 'cancel';break;case 'CancelMode':$action = 'mode_cancel';break;default:break;}return $action;
}function device_id_to_type($deviceId)
{$deviceType = "";$deviceArray = [];$deviceArray = explode('.', $deviceId);$deviceType = $deviceArray[1];return $deviceType;
}function device_id_to_devicetype($deviceId)
{$deviceType = "";$deviceArray = [];$deviceArray = explode('.', $deviceId);$deviceType = $deviceArray[0];return $deviceType;
}function control_checker($arrayData)
{error_log('----control_checker in----');if (empty($arrayData)) {return "jsonData null";}switch ($arrayData['deviceType']) {case 'ceiling_lamp': {if ($arrayData['attribute'] == 'powerstate' || $arrayData['attribute'] == 'brightnessStep' || $arrayData['attribute'] == 'brightness' ) {//Full Support Request Actionreturn 'succeed';}if ($arrayData['attribute'] == 'mode' && $arrayData['value'] == '自然模式') {return 'succeed';}if ($arrayData['attribute'] == 'color' && ($arrayData['value'] == 'White' || $arrayData['value'] == 'Yellow')) {return 'succeed';}return 'failed';}break;case 'gateway_switch': {}break;default:break;}error_log('----control_checker out----');
}?>