diff --git a/app/Routes.php b/app/Routes.php index f973faa..6e7f198 100644 --- a/app/Routes.php +++ b/app/Routes.php @@ -13,6 +13,7 @@ $router->any('/logout', 'Logout'); $router->any('/automation', 'Automation'); $router->any('/setting', 'Setting'); $router->any('/ajax', 'Ajax'); +$router->any('/oauth', 'Oauth'); $router->post('/api/login', 'AuthApi@login'); $router->post('/api/logout', 'AuthApi@logout'); @@ -20,7 +21,7 @@ $router->post('/api/logout', 'AuthApi@logout'); $router->get('/api/devices', 'DevicesApi@default'); $router->get('/api/rooms', 'RoomsApi@default'); -$router->get('/api/HA/auth', 'GoogleHomeApi@autorize'); +$router->any('/api/HA/auth', 'Oauth'); $router->any('/api/HA', 'GoogleHomeApi@response'); // examples diff --git a/app/api/GoogleHomeApi.php b/app/api/GoogleHomeApi.php index 40f67cd..a495669 100644 --- a/app/api/GoogleHomeApi.php +++ b/app/api/GoogleHomeApi.php @@ -1,7 +1,7 @@ requireAuth(); $json = file_get_contents('php://input'); $obj = json_decode($json, true); diff --git a/app/api/RecordApi.php b/app/api/RecordApi.php new file mode 100644 index 0000000..6c313ae --- /dev/null +++ b/app/api/RecordApi.php @@ -0,0 +1,26 @@ +requireAuth(); + $response = []; + $roomIds = []; + $roomsData = RoomManager::getRoomsDefault(); + + foreach ($roomsData as $roomKey => $room) { + $roomIds[] = $room['room_id']; + } + + $subDevicesData = SubDeviceManager::getSubdevicesByRoomIds($roomIds); + + foreach ($roomsData as $roomKey => $roomData) { + $response[] = [ + 'room_id' => $roomData['room_id'], + 'name' => $roomData['name'], + 'widgets' => isset($subDevicesData[$roomData['room_id']]) ? $subDevicesData[$roomData['room_id']] : [], + ]; + } + $this->response($response); + } +} diff --git a/app/controllers/oauthController.php b/app/controllers/oauthController.php new file mode 100644 index 0000000..9a208f7 --- /dev/null +++ b/app/controllers/oauthController.php @@ -0,0 +1,75 @@ +haveOtaEnabled($userName); + if ($ota == "") { + $token = (new AuthManager)->getToken($userName,$userPassword, $clientId); + if (!$token) { + throw new Exception("Auth failed", 401); + } + + $get = [ + "access_token"=>$token, + "token_type"=>"Bearer", + "state"=>$state, + ]; + + header('Location: ' . $_POST["redirectUrl"] . '#' . http_build_query($get)); + die(); + } + + $_SESSION['USERNAME'] = $userName; + $_SESSION['PASSWORD'] = $userPassword; + $_SESSION['OTA'] = $ota; + $_SESSION['STATE'] = $state; + $_SESSION['REDIRECT'] = $_POST["redirectUrl"]; + $_SESSION['CLIENT'] = $clientId; + + +} else if ( + isset($_POST['otaCode']) && + $_POST['otaCode'] != '' +) { + $otaCode = $_POST['otaCode']; + $otaSecret = $_POST['otaSecret']; + + $userName = $_SESSION['USERNAME']; + $userPassword = $_SESSION['PASSWORD']; + $ota = $_SESSION['OTA']; + $oauthState = $_SESSION['STATE']; + $oauthRedirect = $_SESSION['REDIRECT']; + $oauthClientId = $_SESSION['CLIENT']; + + $ga = new PHPGangsta_GoogleAuthenticator(); + $checkResult = $ga->verifyCode($otaSecret, $otaCode, 2); // 2 = 2*30sec clock tolerance + if ($checkResult) { + $token = (new AuthManager)->getToken($userName,$userPassword, $oauthClientId); + if (!$token) { + throw new Exception("Auth failed", 401); + } + + $get = [ + "access_token"=>$token, + "token_type"=>"Bearer", + "state"=>$oauthState, + ]; + + header('Location: ' . $oauthRedirect . '#' . http_build_query($get)); + echo 'OK'; + } else { + echo 'FAILED'; + } + die(); +} diff --git a/app/controllers/settingController.php b/app/controllers/settingController.php index f31a8de..068aecb 100644 --- a/app/controllers/settingController.php +++ b/app/controllers/settingController.php @@ -14,9 +14,8 @@ if (isset($_POST) && !empty($_POST)){ header('Location: ' . BASEURL . 'setting'); die(); } else if (isset($_POST['submitEnableOta']) && $_POST['submitEnableOta'] != "") { - echo $otaCode = $_POST['otaCode']; - echo $otaSecret = $_POST['otaSecret']; - + $otaCode = $_POST['otaCode']; + $otaSecret = $_POST['otaSecret']; $ga = new PHPGangsta_GoogleAuthenticator(); $checkResult = $ga->verifyCode($otaSecret, $otaCode, 2); // 2 = 2*30sec clock tolerance diff --git a/app/models/GoogleHome.php b/app/models/GoogleHome.php index 9d66421..919799d 100644 --- a/app/models/GoogleHome.php +++ b/app/models/GoogleHome.php @@ -12,6 +12,11 @@ class GoogleHome { //Google Compatibile Action Type $actionType = GoogleHomeDeviceTypes::getAction($subDeviceData['type']); + + if (strpos($deviceData['name'], 'Světlo') !== false || strpos($deviceData['name'], 'světlo') !== false) { + $actionType = 'action.devices.types.LIGHT'; + } + $tempDevice = [ 'id' => (string) $subDeviceData['subdevice_id'], 'type' => $actionType, @@ -78,181 +83,181 @@ class GoogleHome { $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'; - } + 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]; + } else { + $tempDevice[$deviceId['id']]['on'] = $state; } - - $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; + $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); } - $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); + static function execute($requestId, $payload){ + $commands = []; - echo json_encode($response); - } + 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]; + } - static function executeSwitch($subDeviceId, $executionCommand){ - $value = 0; - $status = 'SUCCESS'; - if ($executionCommand['params']['on']) $value = 1; + $subDeviceId = $device['id']; - RecordManager::createWithSubId($subDeviceId, $value); + switch ($executionCommand['command']) { + case 'action.devices.commands.OnOff': + $commands[] = self::executeSwitch($subDeviceId, $executionCommand); + break; - $executed = 0; - $waiting = 0; - foreach (RecordManager::getLastRecord($subDeviceId, 4) as $key => $value) { - if ($value['execuded'] == 1){ - $executed++; - } else { - $waiting++; + case 'action.devices.commands.ThermostatTemperatureSetpoint': + $commands[] = self::executeTermostatValue($subDeviceId, $executionCommand); + break; + + case 'action.devices.commands.ThermostatSetMode': + $commands[] = self::executeTermostatMode($subDeviceId, $executionCommand); + break; + } + } } - } - if ($waiting < $executed){ - $status = "PENDING"; - } else { - $status = "OFFLINE"; + + $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); } - $commandTemp = [ - 'ids' => [$subDeviceId], - 'status' => $status, - 'states' => [ - 'on' => $executionCommand['params']['on'], - ], - ]; - return $commandTemp; - } + static function executeSwitch($subDeviceId, $executionCommand){ + $value = 0; + $status = 'SUCCESS'; + if ($executionCommand['params']['on']) $value = 1; - static function executeTermostatValue($subDeviceId, $executionCommand){ - $value = 0; - $status = 'SUCCESS'; + RecordManager::createWithSubId($subDeviceId, $value); - 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++; + $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; } - if ($waiting < $executed){ - $status = "PENDING"; + + 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"; + $status = "SUCCESS"; + } else { + $status = "OFFLINE"; + } + + $commandTemp = [ + 'ids' => [$subDeviceId], + 'status' => $status, + 'states' => [ + 'thermostatMode' => 'heat', + 'thermostatTemperatureSetpoint' => $value, + 'thermostatTemperatureAmbient' => $value, + //ambient z dalšího zenzoru v roomu + ], + ]; + return $commandTemp; + } + + static function executeTermostatMode($subDeviceId, $executionCommand){ + $mode = "off"; + $value = 0; $status = "SUCCESS"; - } else { - $status = "OFFLINE"; - } - $commandTemp = [ - 'ids' => [$subDeviceId], - 'status' => $status, - 'states' => [ - 'thermostatMode' => 'heat', - 'thermostatTemperatureSetpoint' => $value, - 'thermostatTemperatureAmbient' => $value, - //ambient z dalšího zenzoru v roomu - ], - ]; - 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($subDeviceId, 4) as $key => $value) { - if ($value['execuded'] == 1){ - $executed++; - } else { - $waiting++; + if (isset($executionCommand['params']['thermostatMode']) && $executionCommand['params']['thermostatMode'] != 'off') { + $mode = $executionCommand['params']['thermostatMode']; + $value = RecordManager::getLastRecordNotNull($subDeviceId)['value']; } - } - if ($waiting < $executed){ - $status = "PENDING"; - } - $commandTemp = [ - 'ids' => [$subDeviceId], - 'status' => $status, - 'states' => [ - 'thermostatMode' => $mode - ], - ]; + RecordManager::createWithSubId($subDeviceId, $value); - return $commandTemp; + $executed = 0; + $waiting = 0; + foreach (RecordManager::getLastRecord($subDeviceId, 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/managers/AuthManager.php b/app/models/managers/AuthManager.php index 88c96a6..65a71f1 100644 --- a/app/models/managers/AuthManager.php +++ b/app/models/managers/AuthManager.php @@ -1,7 +1,11 @@ headers['HTTP_USER_AGENT']; + } + $userManager = new UserManager(); if ($username != '' || $password != ''){ $userLogedIn = $userManager->loginNew($username, $password); @@ -10,7 +14,11 @@ class AuthManager { // Create token header as a JSON string $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']); // Create token payload as a JSON string - $payload = json_encode(['user_id' => $userLogedIn]); + $payload = json_encode([ + 'user_id' => $userLogedIn, + 'exp' => date('Y-m-d H:i:s',strtotime("+90 Days")), + 'iat' => date('Y-m-d H:i:s',time()), + ]); // Encode Header to Base64Url String $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); // Encode Payload to Base64Url String @@ -22,7 +30,17 @@ class AuthManager { // Create JWT $jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature; - return $jwt; + + $token = [ + 'user_id' => $userLogedIn, + 'user_agent' => $userAgent, + 'token' => $jwt, + 'expire' => date('Y-m-d H:i:s',strtotime("+90 Days")), + 'issued' => date('Y-m-d H:i:s',time()), + ]; + if (Db::add ('tokens', $token)){ + return $jwt; + } } } return false; diff --git a/app/models/managers/UserManager.php b/app/models/managers/UserManager.php index 05fd3ef..1bdc2a6 100644 --- a/app/models/managers/UserManager.php +++ b/app/models/managers/UserManager.php @@ -206,5 +206,15 @@ class UserManager return false; } } + + public static function setOta($otaCode, $otaSecret){ + $ga = new PHPGangsta_GoogleAuthenticator(); + $checkResult = $ga->verifyCode($otaSecret, $otaCode, 2); // 2 = 2*30sec clock tolerance + if ($checkResult) { + self::setUserData('ota', $otaSecret); + return true; + } + return false; + } } ?> diff --git a/app/views/Oauth.php b/app/views/Oauth.php new file mode 100644 index 0000000..0a7fb9a --- /dev/null +++ b/app/views/Oauth.php @@ -0,0 +1,30 @@ +prepare('baseDir', BASEDIR); + $template->prepare('title', 'Home'); + + $template->prepare('lang', $lang); + + if (isset($_GET['redirect_uri'])) { + $template->prepare('responseType', $_GET['response_type']); + $template->prepare('redirectUrl', $_GET['redirect_uri']); + $template->prepare('clientId', $_GET['client_id']); + $template->prepare('state', $_GET['state']); + } else { + $template->prepare('responseType', $_POST['responseType']); + $template->prepare('redirectUrl', $_POST['redirectUrl']); + $template->prepare('clientId', $_POST['clientId']); + $template->prepare('state', $_POST['state']); + } + + + $template->render(); + } +} diff --git a/app/views/templates/oauth.phtml b/app/views/templates/oauth.phtml new file mode 100644 index 0000000..c754f96 --- /dev/null +++ b/app/views/templates/oauth.phtml @@ -0,0 +1,33 @@ + + +
+ prepare('baseDir',$BASEDIR); + $partial->render(); + ?> +