diff --git a/app/api/GoogleHomeApi.php b/app/api/GoogleHomeApi.php index 10a82c4..895176a 100644 --- a/app/api/GoogleHomeApi.php +++ b/app/api/GoogleHomeApi.php @@ -1,7 +1,7 @@ write("[Google Home] action.devices.SYNC", LogRecordType::INFO); break; case 'action.devices.QUERY': - self::query($obj['requestId'], $obj['inputs'][0]['payload']); - $apiLogManager->write("[Google Home] action.devices.QUERY", LogRecordType::INFO); + GoogleHome::query($obj['requestId'], $obj['inputs'][0]['payload']); + //$apiLogManager->write("[Google Home] action.devices.QUERY", LogRecordType::INFO); break; case 'action.devices.EXECUTE': - self::execute($obj['requestId'], $obj['inputs'][0]['payload']); + GoogleHome::execute($obj['requestId'], $obj['inputs'][0]['payload']); $apiLogManager->write("[Google Home] action.devices.EXECUTE", LogRecordType::INFO); break; } } - static function sync($requestId){ - $devices = []; - - $roomsData = RoomManager::getAllRooms(); - foreach ($roomsData as $roomKey => $roomData) { - $devicesData = DeviceManager::getAllDevicesInRoom($roomData['room_id']); - foreach ($devicesData as $deviceKey => $deviceData) { - $subDevicesData = SubDeviceManager::getAllSubDevices($deviceData['device_id']); - foreach ($subDevicesData as $subDeviceKey => $subDeviceData) { - if ($subDeviceData['type'] != "on/off" && $subDeviceData['type'] != "temp_cont") continue; - - //Google Compatibile Action Type - $actionType = GoogleHomeDeviceTypes::getAction($subDeviceData['type']); - $tempDevice = [ - 'id' => (string) $subDeviceData['subdevice_id'], - 'type' => $actionType, - 'name' => [ - 'name' => $deviceData['name'], - ], - 'willReportState' => false, - 'roomHint' => $roomData['name'] - ]; - - //traids & Attributes - $devices[] = GoogleHomeDeviceTypes::getSyncObj($tempDevice, $actionType); - } - } - } - - $response = [ - 'requestId' => $requestId, - 'payload' => [ - 'agentUserId'=>'651351531531', - 'devices' => $devices, - ], - ]; - $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); - $apiLogManager->write("[API] request response\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); - echo json_encode($response); - } - - static function query($requestId, $payload){ - $devices = []; - foreach ($payload['devices'] as $deviceId) { - $subDeviceData = SubDeviceManager::getSubDevice($deviceId['id']); - if ($subDeviceData['type'] != "on/off" && $subDeviceData['type'] != "temp_cont") continue; - - $state = false; - if (RecordManager::getLastRecord($deviceId['id'])['value'] == 1){ - $state = true; - } - - $online = false; - $status = 'OFFLINE'; - if (RecordManager::getLastRecord($deviceId['id'])['execuded'] == 1){ - $online = true; - $status = 'SUCCESS'; - } - - $tempDevice = [ - $deviceId['id'] => [ - 'online' => $online, - 'status'=> $status, - ] - ]; - - if ($subDeviceData['type'] == "temp_cont"){ - $tempDevice[$deviceId['id']]['thermostatMode'] = 'heat'; - $tempDevice[$deviceId['id']]['thermostatTemperatureAmbient'] = RecordManager::getLastRecord($deviceId['id'])['value']; - $tempDevice[$deviceId['id']]['thermostatTemperatureSetpoint'] = RecordManager::getLastRecord($deviceId['id'])['value']; - } else { - $tempDevice[$deviceId['id']]['on'] = $state; - } - $devices = $tempDevice; - if (count($devices)> 1){ - $devices[] = $tempDevice; - } - } - - - $response = [ - 'requestId' => $requestId, - 'payload' => [ - 'devices' => $devices, - ], - ]; - - $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); - $apiLogManager->write("[API] request response\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); - echo json_encode($response); - } - - static function execute($requestId, $payload){ - $commands = []; - - foreach ($payload['commands'] as $key => $command) { - foreach ($command['devices'] as $key => $device) { - $executionCommand = $command['execution'][0]; - if (isset($command['execution'][$key])) { - $executionCommand = $command['execution'][$key]; - } - - $subDeviceId = $device['id']; - - switch ($executionCommand['command']) { - case 'action.devices.commands.OnOff': - $value = 0; - if ($executionCommand['params']['on']) $value = 1; - - RecordManager::createWithSubId($subDeviceId, $value); - - $timeout = 0; - while(RecordManager::getLastRecord($subDeviceId)['execuded'] == 0 && $timeout < 5 ){ - sleep(1); - $timeout++; - } - - $commandTemp = [ - 'ids' => [$subDeviceId], - 'status' => 'SUCCESS', - 'states' => [ - 'on' => $executionCommand['params']['on'], - ], - ]; - - if ($timeout >= 5){ - $commandTemp['status'] = "OFFLINE"; - } - $commands[] = $commandTemp; - - break; - - case 'action.devices.commands.ThermostatTemperatureSetpoint': - $value = 0; - if (isset($executionCommand['params']['thermostatTemperatureSetpoint'])) $value = $executionCommand['params']['thermostatTemperatureSetpoint']; - - RecordManager::createWithSubId($subDeviceId, $value); - - $timeout = 0; - while(RecordManager::getLastRecord($subDeviceId)['execuded'] == 0 && $timeout < 5 ){ - sleep(1); - $timeout++; - } - - $commandTemp = [ - 'ids' => [$subDeviceId], - 'status' => 'SUCCESS', - 'states' => [ - 'thermostatMode' => 'heat', - 'thermostatTemperatureSetpoint' => $value, - 'thermostatTemperatureAmbient' => $value, - ], - ]; - - if ($timeout >= 5){ - $commandTemp['status'] = "OFFLINE"; - } - $commands[] = $commandTemp; - - break; - } - } - } - - $response = [ - 'requestId' => $requestId, - 'payload' => [ - 'commands' => $commands, - ], - ]; - $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); - $apiLogManager->write("[API] request response\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); - - echo json_encode($response); - } - static function autorize(){ $json = file_get_contents('php://input'); $obj = json_decode($json, true); diff --git a/app/models/GoogleHome.php b/app/models/GoogleHome.php new file mode 100644 index 0000000..8882be9 --- /dev/null +++ b/app/models/GoogleHome.php @@ -0,0 +1,260 @@ + $roomData) { + $devicesData = DeviceManager::getAllDevicesInRoom($roomData['room_id']); + foreach ($devicesData as $deviceKey => $deviceData) { + $subDevicesData = SubDeviceManager::getAllSubDevices($deviceData['device_id']); + foreach ($subDevicesData as $subDeviceKey => $subDeviceData) { + if ($subDeviceData['type'] != "on/off" && $subDeviceData['type'] != "temp_cont") continue; + + //Google Compatibile Action Type + $actionType = GoogleHomeDeviceTypes::getAction($subDeviceData['type']); + $tempDevice = [ + 'id' => (string) $subDeviceData['subdevice_id'], + 'type' => $actionType, + 'name' => [ + 'name' => $deviceData['name'], + ], + 'willReportState' => false, + 'roomHint' => $roomData['name'] + ]; + + //traids & Attributes + $devices[] = GoogleHomeDeviceTypes::getSyncObj($tempDevice, $actionType); + } + } + } + + $response = [ + 'requestId' => $requestId, + 'payload' => [ + 'agentUserId'=>'651351531531', + 'devices' => $devices, + ], + ]; + $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); + $apiLogManager->write("[API][$requestId] request response\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); + echo json_encode($response); + } + + static function query($requestId, $payload){ + $devices = []; + foreach ($payload['devices'] as $deviceId) { + $subDeviceData = SubDeviceManager::getSubDevice($deviceId['id']); + if ($subDeviceData['type'] != "on/off" && $subDeviceData['type'] != "temp_cont") continue; + + $state = false; + if (RecordManager::getLastRecord($deviceId['id'])['value'] == 1){ + $state = true; + } + + $online = false; + $status = 'OFFLINE'; + + if (RecordManager::getLastRecord($deviceId['id'])['execuded'] == 1){ + $online = true; + $status = 'SUCCESS'; + } else { + $executed = 0; + $waiting = 0; + foreach (RecordManager::getLastRecord($deviceId['id'], 6) as $key => $value) { + if ($value['execuded'] == 1){ + $executed++; + } else { + $waiting++; + } + } + if ($waiting < $executed){ + $status = "PENDING"; + $online = true; + } + } + + $tempDevice = [ + $deviceId['id'] => [ + 'online' => $online, + 'status'=> $status, + ] + ]; + + if ($subDeviceData['type'] == "temp_cont"){ + $tempDevice[$deviceId['id']]['thermostatMode'] = 'off'; + if (RecordManager::getLastRecord($deviceId['id'])['value'] != 0) { + $tempDevice[$deviceId['id']]['thermostatMode'] = 'heat'; + $tempDevice[$deviceId['id']]['thermostatTemperatureAmbient'] = RecordManager::getLastRecord($deviceId['id'])['value']; + $tempDevice[$deviceId['id']]['thermostatTemperatureSetpoint'] = RecordManager::getLastRecord($deviceId['id'])['value']; + } + } else { + $tempDevice[$deviceId['id']]['on'] = $state; + } + $devices = $tempDevice; + if (count($devices)> 1){ + $devices[] = $tempDevice; + } + } + + $response = [ + 'requestId' => $requestId, + 'payload' => [ + 'devices' => $devices, + ], + ]; + + $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); + $apiLogManager->write("[API][$requestId] request response\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); + echo json_encode($response); + } + + static function execute($requestId, $payload){ + $commands = []; + + foreach ($payload['commands'] as $key => $command) { + foreach ($command['devices'] as $key => $device) { + $executionCommand = $command['execution'][0]; + if (isset($command['execution'][$key])) { + $executionCommand = $command['execution'][$key]; + } + + $subDeviceId = $device['id']; + + switch ($executionCommand['command']) { + case 'action.devices.commands.OnOff': + $commands[] = self::executeSwitch($subDeviceId, $executionCommand); + break; + + case 'action.devices.commands.ThermostatTemperatureSetpoint': + $commands[] = self::executeTermostatValue($subDeviceId, $executionCommand); + break; + + case 'action.devices.commands.ThermostatSetMode': + $commands[] = self::executeTermostatMode($subDeviceId, $executionCommand); + break; + } + } + } + + $response = [ + 'requestId' => $requestId, + 'payload' => [ + 'commands' => $commands, + ], + ]; + $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log'); + $apiLogManager->write("[API][EXECUTE][$requestId]\n" . json_encode($response, JSON_PRETTY_PRINT), LogRecordType::INFO); + + echo json_encode($response); + } + + static function executeSwitch($subDeviceId, $executionCommand){ + $value = 0; + $status = 'SUCCESS'; + if ($executionCommand['params']['on']) $value = 1; + + RecordManager::createWithSubId($subDeviceId, $value); + + $executed = 0; + $waiting = 0; + foreach (RecordManager::getLastRecord($subDeviceId, 4) as $key => $value) { + if ($value['execuded'] == 1){ + $executed++; + } else { + $waiting++; + } + } + if ($waiting < $executed){ + $status = "PENDING"; + } else { + $status = "OFFLINE"; + } + + $commandTemp = [ + 'ids' => [$subDeviceId], + 'status' => $status, + 'states' => [ + 'on' => $executionCommand['params']['on'], + ], + ]; + return $commandTemp; + } + + static function executeTermostatValue($subDeviceId, $executionCommand){ + $value = 0; + $status = 'SUCCESS'; + + if (isset($executionCommand['params']['thermostatTemperatureSetpoint'])) { + $value = $executionCommand['params']['thermostatTemperatureSetpoint']; + } + + RecordManager::createWithSubId($subDeviceId, $value); + + $executed = 0; + $waiting = 0; + foreach (RecordManager::getLastRecord($subDeviceId, 4) as $key => $lastValue) { + if ($lastValue['execuded'] == 1){ + $executed++; + } else { + $waiting++; + } + } + if ($waiting < $executed){ + $status = "PENDING"; + } else { + $status = "OFFLINE"; + } + + $commandTemp = [ + 'ids' => [$subDeviceId], + 'status' => $status, + 'states' => [ + 'thermostatMode' => 'heat', + 'thermostatTemperatureSetpoint' => $value, + 'thermostatTemperatureAmbient' => $value, + //ambient z dalšího zenzoru v roomu + ], + ]; + + if ($timeout >= 5){ + $commandTemp['status'] = "OFFLINE"; + } + return $commandTemp; + } + + static function executeTermostatMode($subDeviceId, $executionCommand){ + $mode = "off"; + $value = 0; + $status = "SUCCESS"; + + if (isset($executionCommand['params']['thermostatMode']) && $executionCommand['params']['thermostatMode'] != 'off') { + $mode = $executionCommand['params']['thermostatMode']; + $value = RecordManager::getLastRecordNotNull($subDeviceId)['value']; + } + + RecordManager::createWithSubId($subDeviceId, $value); + + $executed = 0; + $waiting = 0; + foreach (RecordManager::getLastRecord($deviceId['id'], 4) as $key => $value) { + if ($value['execuded'] == 1){ + $executed++; + } else { + $waiting++; + } + } + if ($waiting < $executed){ + $status = "PENDING"; + } + + $commandTemp = [ + 'ids' => [$subDeviceId], + 'status' => $status, + 'states' => [ + 'thermostatMode' => $mode + ], + ]; + + return $commandTemp; + } +} diff --git a/app/models/RecordManager.php b/app/models/RecordManager.php index b2046a7..143b6a2 100644 --- a/app/models/RecordManager.php +++ b/app/models/RecordManager.php @@ -3,11 +3,15 @@ class RecordManager{ public static $records; public static function createWithSubId ($subDeviceId, $value) { - $record = array ( - 'subdevice_id' => $subDeviceId, - 'value' => $value, - ); try { + $record = [ + 'execuded' => 1, + ]; + Db::edit ('records', $record, 'WHERE subdevice_id = ?', array ($subDeviceId)); + $record = array ( + 'subdevice_id' => $subDeviceId, + 'value' => $value, + ); return Db::add ('records', $record); } catch(PDOException $error) { echo $error->getMessage(); @@ -20,11 +24,15 @@ class RecordManager{ if ($subDeviceId == '') { return false; }; - $record = array ( - 'subdevice_id' => $subDeviceId, - 'value' => $value, - ); try { + $record = [ + 'execuded' => 1, + ]; + Db::edit ('records', $record, 'WHERE subdevice_id = ?', array ($subDeviceId)); + $record = array ( + 'subdevice_id' => $subDeviceId, + 'value' => $value, + ); return Db::add ('records', $record); } catch(PDOException $error) { echo $error->getMessage(); @@ -56,6 +64,10 @@ class RecordManager{ return Db::loadAll('SELECT * FROM records WHERE subdevice_id = ? AND value != ? ORDER BY time DESC LIMIT ?;', array($subDeviceId, 999, $num)); } + public static function getLastRecordNotNull($subDeviceId) { + return Db::loadOne('SELECT * FROM records WHERE subdevice_id = ? AND value != ? ORDER BY time DESC;', array($subDeviceId, 0)); + } + public static function getAllRecord($subDeviceId, $timeFrom, $timeTo) { return Db::loadAll('SELECT * FROM records WHERE subdevice_id = ? AND time >= ? AND time <= ? AND value != ? ORDER BY time;', array($subDeviceId, $timeFrom, $timeTo, 999)); } diff --git a/app/models/types/GoogleHomeDeviceTypes.php b/app/models/types/GoogleHomeDeviceTypes.php index e38a19d..e3e9ca6 100644 --- a/app/models/types/GoogleHomeDeviceTypes.php +++ b/app/models/types/GoogleHomeDeviceTypes.php @@ -98,8 +98,8 @@ class GoogleHomeDeviceTypes { 'maxThresholdCelsius' => 30, ], "thermostatTemperatureUnit" => "C", - "commandOnlyTemperatureSetting" => false, - "queryOnlyTemperatureSetting" => false, + "commandOnlyTemperatureSetting" => true, + "queryOnlyTemperatureSetting" => true, "bufferRangeCelsius" => 0, ]; break;