Untitled
user_3839718
php
2 years ago
74 kB
3
Indexable
<?php namespace App\Controller; use App\Model\RobotManager; use App\Model\RoundManager; use App\Model\AlertManager; use App\Model\CurvesManager; use App\Model\ElasticSearchManager; use App\Helper\SignatureHelper; use Laminas\View\Model\JsonModel; use App\Model\UserManager; use Laminas\ServiceManager\ServiceManager; use App\File\AwsS3; use Spatie\Async\Pool; use Throwable; /** * This controller is responsible for robot management */ class RobotController extends \App\Controller\AbstractBaseController { const LATEST = 'latest'; const INTERVAL = 'interval'; const HOURLY_OVERVIEW = 'hourly_overview'; const HOURLY = 'hour'; const DAILY = 'day'; const WEEKLY = 'week'; const ROUND = 'round'; const NEW_DAY = 'new_day'; const TIME_OF_DAY = 'time_of_day'; const HEAT_MAP = 'heatmap'; const GRAPH = 'graph'; private $s3FileSystem; private $robotManager; private $userManager; private $curvesManager; private $alertManager; private $roundManager; private $elasticSearchManager; private $images; /** * Constructor. */ public function __construct(ServiceManager $container) { parent::__construct($container); $this?->robotManager = $container?->get(RobotManager::class); $this?->roundManager = $container?->get(RoundManager::class); $this?->userManager = $container?->get(UserManager::class); $this?->curvesManager = $container?->get(CurvesManager::class); $this?->alertManager = $container?->get(AlertManager::class); $this?->elasticSearchManager = $container?->get(ElasticSearchManager::class); $this?->s3FileSystem = $container?->get(AwsS3::class); } // this one return the entity of one robot public function returnRobotAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $isAdmin = $this?->isAdmin($identity); $robot = $this?->robotManager?->returnRobotView($robotId, $identity, $isAdmin); return new JsonModel([ 'data' => $robot ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this one gives you all the robots you have related to you account public function getRobotsViewAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } $offset = $this?->params()?->fromQuery('offset', 0); $limit = $this?->params()?->fromQuery('limit', 5); $search = $this?->params()?->fromQuery('search', null); $status = $this?->params()?->fromQuery('status', '1'); $param = [ 'offset' => $offset, 'limit' => $limit, 'search' => $search, 'status' => $status ]; $isAdmin = $this?->isAdmin($identity); $robots = $this?->robotManager?->fetch($identity['id'], $param, $isAdmin); return new JsonModel([ 'robots' => $robots, ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this endpoint return all the users that are related to a robot public function getRobotUsersAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } return new JsonModel([ 'users' => $this?->robotManager?->usersAssociatedToMyRobots($robotId), ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // This endpoint gives us the cameras, the values for frontend tables of the status page // and also the alerts we have on those tables and observables public function getRobotStatusPageDataAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); $houseId = $this?->params()?->fromQuery('houseId', -1); if ($robotId == -1 && $houseId == -1) { return $this?->handleError(400, 'You need to send robotId or houseId'); } $byTime = false; if ($houseId !== -1) { $robotId = $this?->robotManager?->getRobotsInHouse($houseId)?->current()?->robot_id; } else if ($this?->robotManager?->returnRobot('id', $robotId)?->robot_type == 'cd') { $byTime = true; } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $roundId = $this?->robotManager?->getRobotRound($robotId)?->id; $cameraDetails = $this?->getRobotCameraFromConfig($robotId); $cameras = []; if ($cameraDetails != null) { foreach ($cameraDetails?->{'camera-details'}?->children() as $cameraDetail) { $camera = []; $camera['name'] = $cameraDetail?->getName(); $camera['id'] = (string) $cameraDetail["id"]; array_push($cameras, $camera); } } $alerts = $this?->alertManager?->alertsAfterLastLoginbyRobot($identity, $robotId); $observableAlerts = []; foreach ($alerts as $alert) { isset($this?->config['alert_ids']['ambient_conditions'][$alert['alert_id']]) ? array_push($observableAlerts, $this?->config['alert_ids']['ambient_conditions'][$alert['alert_id']]) : null; isset($this?->config['alert_ids']['health_welfare'][$alert['alert_id']]) ? array_push($observableAlerts, $this?->config['alert_ids']['health_welfare'][$alert['alert_id']]) : null; isset($this?->config['alert_ids']['equipment'][$alert['alert_id']]) ? array_push($observableAlerts, $this?->config['alert_ids']['equipment'][$alert['alert_id']]) : null; } return new JsonModel([ 'cameras' => $cameras, 'currentValues' => $this?->robotManager?->latestValue($roundId, $robotId, $byTime), 'yesterdayValues' => $this?->robotManager?->yesterdayValues($roundId, $robotId, $byTime), 'lastRoundValues' => $this?->robotManager?->lastRoundValues($roundId, $robotId), 'observableAlerts' => array_count_values($observableAlerts), ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // This endpoint gives us all the data from the robot and his status public function getRobotStatusLayoutDataAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } // here is when we get all the data $params = $this?->getRobotStatusLayoutData($identity, $robotId); return new JsonModel($params); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // This endpoint gives us all the data from the robot and his status // including laser, light or lift configuration public function getRobotStatusAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $getRobotStatus = $this?->robotManager?->returnRobotStatus($identity, $robotId); return new JsonModel([ 'robotType' => $getRobotStatus?->robot_type ?? 'cb', 'lastUpdate' => $this?->robotManager?->getLastRobotPing($robotId) ?? null, 'battery' => $getRobotStatus?->battery ?? 0, 'location' => $getRobotStatus?->location ?? '[0,0,0]', 'estimatedRecharge' => $getRobotStatus?->remaining_recharge_time ?? '0', 'batteryTime' => $getRobotStatus?->battery_time ?? '0', 'operationalState' => $getRobotStatus?->operational_state ?? null, 'onCharger' => $getRobotStatus?->on_charger ?? null, 'restartDate' => $getRobotStatus?->restart_date ?? null, 'errorMsg' => $getRobotStatus?->error_msg ?? null, 'status' => $getRobotStatus?->status ?? null, 'action' => $getRobotStatus?->robot_action ?? null, 'laser' => $getRobotStatus?->laser ?? 'off', 'light' => $getRobotStatus?->light ?? 'off', 'lift' => $getRobotStatus?->lift ?? 'manual', ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this endpoint gives to us all observables settings from a robot, // also information about the controls public function getRobotSettingsAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $robotSettings = json_decode($this?->robotManager?->getRobotSettings($robotId, $identity['id'])); $robotObs = $this?->robotManager?->returnRobotAvailableObservables($robotId); $controlsConfig = $this?->robotManager?->getRobotControlsFromConfig($robotId); $controls = []; if (!empty($controlsConfig)) { foreach ($controlsConfig?->{'control-details'}?->children() as $controlsDetail) { $controls[$controlsDetail?->getName()] = (string) $controlsDetail["enabled"]; } } $roundId = $this?->robotManager?->getRobotRound($robotId)?->id; return new JsonModel([ 'settings' => $robotSettings, 'availableObservables' => $robotObs, 'availableControls' => $controls, 'siUnit' => $this?->roundManager?->getSiUnit($roundId) ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // Return to the user the dimensions of the house stored on the config file of the robot public function getHouseDimensionsAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } return new JsonModel( $this?->getHouseDimensions($robotId) ); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // This endpoint returns the configuration file of the robot public function getConfigurationFileAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $configXml = $this?->robotManager?->getConfigurationFile($robotId); return new JsonModel([ 'configuration' => $configXml ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this function gives tu us the rails of a robot configuration public function getRobotRailsAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $configFile = $this?->robotManager?->getConfigurationFile($robotId); $xml = simplexml_load_string($configFile); $result = [ 'offset' => $xml?->path?->{'offset'}, 'sections' => $xml?->path?->{'sections'}, 'path-configuration' => $xml?->path?->{'path-configuration'}, ]; return new JsonModel([ 'data' => $result ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this endpoint is the one that connects to ES and aws S3 and return to you the images // related to a robot and an observable type public function getGalleryImagesObservableAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); $observableName = $this?->params()?->fromQuery('observableName', -1); $offset = $this?->params()?->fromQuery('offset', -1); $limit = $this?->params()?->fromQuery('limit', -1); if ($robotId == -1 || $observableName == -1 || $limit == -1 || $offset == -1) { return $this?->handleError(400, 'You need to send robotId, observable name, offset and limit'); } $camera = $this?->params()?->fromQuery('camera', null); $from = $this?->params()?->fromQuery('from', null); $to = $this?->params()?->fromQuery('to', null); // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $end = false; $anomalies = [ 'deadBirds' => 'dead_birds', 'badDroppings' => 'bad_droppings', 'brokenDrinkers' => 'wet_spots', # bad naming from the way the file is saved before correcting think of backward compatibility ]; $roundId = $this?->robotManager?->getRobotRound($robotId)?->id; $param = $this?->getObjectsForObservablesElasticSearch($roundId, $anomalies[$observableName], $camera, $offset, $limit, $from, $to); if ($param['images'] !== null) { if (count($param['images']) == 0 || count($param['images']) < $limit) { $end = true; } } else { $end = true; } return new JsonModel([ 'images' => $param['images'] ?? [], 'key' => $param['key'], 'end' => $end, 'observableName' => $observableName ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // Endpoint that returns a heatmap with an hourly overview for each day of // prod for an observable and a robot public function getHourMapAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $observableName = $this?->params()?->fromQuery('observableName', -1); $roundId = $this?->params()?->fromQuery('roundId', -1); if ($roundId == -1 || $observableName == -1) { return $this?->handleError(400, 'You need to send roundId and observable name'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'round.id' => $roundId]; $role = $this?->roundManager?->getUserRoleInEntity($select, 'round.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $data = $this?->robotManager?->getFrontEndData($roundId, self::HEAT_MAP, self::HOURLY_OVERVIEW, $observableName); $data = $data?->data ?? null; return new JsonModel([ 'data' => $data, 'siUnitType' => $this?->roundManager?->getSiUnit($roundId) ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // Endpoint that returns a lineplot of a // prod for an observable, a robot, an event type and a time public function getGraphDataAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $observableName = $this?->params()?->fromQuery('observableName', -1); $roundId = $this?->params()?->fromQuery('roundId', -1); $eventType = $this?->params()?->fromQuery('type', -1); $time = $this?->params()?->fromQuery('time', -1); if ($roundId == -1 || $observableName == -1 || $time == -1 || $eventType == -1) { return $this?->handleError(400, 'You need to send roundId, observable name, event type and time'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'round.id' => $roundId]; $role = $this?->roundManager?->getUserRoleInEntity($select, 'round.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } switch ($eventType) { case self::LATEST: $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::LATEST, $observableName); break; case self::ROUND: $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::ROUND, $observableName); break; case self::INTERVAL: if ($time == self::HOURLY) { $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::HOURLY, $observableName); } elseif ($time == self::TIME_OF_DAY) { $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::TIME_OF_DAY, $observableName); } elseif ($time == self::DAILY) { $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::NEW_DAY, $observableName); } else { $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::WEEKLY, $observableName); } break; case self::TIME_OF_DAY: $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::TIME_OF_DAY, $observableName); break; case self::NEW_DAY: $data = $this?->robotManager?->getFrontEndData($roundId, self::GRAPH, self::NEW_DAY, $observableName); break; } $data = $data?->data ?? null; $targets_raw = json_decode($this?->curvesManager?->getRoundTarget($roundId)); return new JsonModel([ 'data' => $data, 'target_raw' => $targets_raw, 'siUnitType' => $this?->roundManager?->getSiUnit($roundId), ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // Endpoint that returns a heatmap of a // prod for an observable, a robot, an event type public function getHeatMapDataAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $roundId = $this?->params()?->fromQuery('roundId', -1); $observableName = $this?->params()?->fromQuery('observableName', -1); $eventType = $this?->params()?->fromQuery('type', -1); if ($roundId == -1 || $observableName == -1 || $eventType == -1) { return $this?->handleError(400, 'You need to send roundId, observable name, event type and time'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'round.id' => $roundId]; $role = $this?->roundManager?->getUserRoleInEntity($select, 'round.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } switch ($eventType) { case self::LATEST: $data = $this?->robotManager?->getFrontEndData($roundId, self::HEAT_MAP, self::LATEST, $observableName); break; case self::ROUND: $data = $this?->robotManager?->getFrontEndData($roundId, self::HEAT_MAP, self::ROUND, $observableName); break; case self::TIME_OF_DAY: $data = $this?->robotManager?->getFrontEndData($roundId, self::HEAT_MAP, self::TIME_OF_DAY, $observableName); break; case self::NEW_DAY: $data = $this?->robotManager?->getFrontEndData($roundId, self::HEAT_MAP, self::NEW_DAY, $observableName); break; } $data = $data?->data ?? null; return new JsonModel([ 'z' => $data, 'dayOfProduction' => $data?->date ?? null, 'siUnitType' => $this?->roundManager?->getSiUnit($roundId) ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this function validates a Mater token from a robot // you dont need to have a session to validate it public function validateMasterTokenAction() { try { $data = $this?->getRequest()?->getPost(); // filter content from user $filter = new \Laminas\I18n\Filter\Alnum(); $masterToken = $filter?->filter($data['masterToken']); $isMasterTokenValid = $this?->robotManager?->isMasterTokenValid($masterToken); return new JsonModel([ 'isMasterTokenValid' => $isMasterTokenValid, ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this endpoint check if a user is able to associate a robot // if they exist or if they have the robot public function validateUserBeforeAssociationAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $data = $this?->getRequest()?->getPost(); // this input should be filtered $userId = $data['userId']; $id = $this?->userManager?->returnUser('id', $userId); $email = $this?->userManager?->returnUser('email', $userId); $user = $id || $email; if (!$user) { return new JsonModel([ 'type' => 'error', 'text' => 'User does not exist' ]); } $checkUserExistsInRobot = $this?->robotManager?->getUserInRobot($data['userId'], $robotId); if (isset($checkUserExistsInRobot)) { return new JsonModel([ 'type' => 'error', 'text' => 'User is already linked with this robot.' ]); } return new JsonModel([ 'type' => 'success', 'user' => $user ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // this is the endpoint that confirm that you are associated // to new robot public function confirmRobotAssociationApiAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } $key = $this?->config['signatureHelper']['key']; $signedUrl = $this?->getRequest()?->getUriString(); $request = $this?->params()?->fromQuery('request', null); $userId = substr($request, 0, 7); $roboId = substr($request, 7, 7); $fmId = substr($request, 14, 7); $role = substr($request, 21, 1); // if the user is not the same as the one we want to confirm if ($identity['id'] != $userId || $signedUrl == null) { return $this?->handleError(400, 'The link is not for this user'); } elseif (!SignatureHelper::isValid($signedUrl, $key)) { return $this?->handleError(400, 'The link has expired'); } else { if (!is_null($this?->robotManager?->getUserInRobot($userId, $roboId))) { return $this?->handleError(400, 'You already have that robot'); } else { $this?->robotManager?->confirmUserAdded($userId, $roboId, $fmId, $role); return new JsonModel([ 'text' => 'You have successfully added the robot.', 'redirectUrl' => '/robot/view-robots', 'type' => 'success' ]); } } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // here we the robot to a farm manager and send an email to the user public function addFarmManagerToRobotAction() { try { if ($this?->getRequest()?->isPost()) { // we check the method $data = $this?->getRequest()?->getPost(); // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // filter content from user $filter = new \Laminas\I18n\Filter\Alnum(); $masterToken = $filter?->filter($data['masterToken']); // add farm manager to robot $this?->robotManager?->addFarmManagerToRobot($identity['id'], $masterToken); return new JsonModel([ 'success' => True, ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } // return all the robots status of the system public function getRobotsStatusAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if the user has permision to do this if (!$this?->isAdmin($identity)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $robotsStatus = $this?->robotManager?->returnRobotsStatus($identity); return new JsonModel([ 'data' => $robotsStatus, ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function exportParamsAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $isAdmin = $this?->isAdmin($identity); $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); $param = [ 'offset' => 0, 'limit' => 99999, 'robotId' => $robotId, 'range' => 'false', 'status' => 'notDeleted', 'exportable' => (!$this?->isWritable($role)) ? '1' : null ]; $rounds = $this?->roundManager?->fetch($identity['id'], $param, $isAdmin); // Pending to implement - Return observables that have permissions to be exported if farm manager // want to restrict it like for the prod cycles or we have some "internal" observables that don't want to allow user to downlaod it but us, yes // For now we return ALL observable added to the robot, and filtering by exportable ones $allObs = $this?->robotManager?->returnRobotAvailableObservables($robotId); $filterObservableName = new \Laminas\Filter\Whitelist(['list' => $this?->config['exportable_observables']]); $observables = []; foreach ($allObs as $obs) { if ($filterObservableName($obs) !== null) { array_push($observables, $obs); } } return new JsonModel([ 'rounds' => $rounds, 'observables' => $observables ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function addRobotAction() { try { if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if the user has permision to do this if (!$this?->isAdmin($identity)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $robotId = ''; $data = $this?->getRequest()?->getPost(); $robotId = $this?->robotManager?->addRobot($data, $identity); return new JsonModel([ 'text' => 'User successfully created a new robot.', 'type' => 'success', 'redirectUrl' => '/admin/assembly-order/' . $robotId ]); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function associateUserToRobotAction() { try { if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $data = $this?->getRequest()?->getPost(); if ($data['type'] == 'email') { $data['userId'] = $this?->userManager?->returnUser('email', $data['userId'])?->id; } $this?->robotManager?->addUserToRobot($identity, $robotId, $data); return new JsonModel([ 'success' => True, ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateConfigurationFileAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } // update robot $data = $this?->getRequest()?->getPost(); $this?->robotManager?->configuration($robotId, $data, $identity['id']); return new JsonModel([ 'success' => True, ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function editRobotSettingsAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $data = $this?->getRequest()?->getPost(); $this?->robotManager?->updateRobotSettings($robotId, $data, $identity); return new JsonModel([ 'success' => true ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function associateHouseToRobotAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } // update robot $data = $this?->getRequest()?->getPost(); $this?->robotManager?->moveRobotToNewHouse($data, $robotId, $identity); return new JsonModel([ 'success' => True, ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateRobotAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } // update robot $data = $this?->getRequest()?->getPost(); $this?->robotManager?->updateRobot($data, $robotId, $identity); return new JsonModel([ 'success' => True, ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateLaserStatusAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $laser = $this?->params()?->fromQuery('laser', -1); $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1 || $laser == -1) { return $this?->handleError(400, 'You need to send robotId and laser'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $filterAction = new \Laminas\Filter\Whitelist(['list' => ['off', 'auto']]); $laser = $filterAction($laser) ?? 'off'; $response = $this?->robotManager?->updateLaserStatus($robotId, $laser); return new JsonModel([ 'success' => $response ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateActionStatusAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); $action = $this?->params()?->fromQuery('action', -1); if ($robotId == -1 || $action == -1) { return $this?->handleError(400, 'You need to send robotId and action'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $filterAction = new \Laminas\Filter\Whitelist(['list' => ['start', 'stop', 'gohome']]); $action = $filterAction($action); $response = $this?->robotManager?->updateActionStatus($robotId, $action); return new JsonModel([ 'success' => $response ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateLightStatusAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $light = $this?->params()?->fromQuery('light', -1); $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1 || $light == -1) { return $this?->handleError(400, 'You need to send robotId and light'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $filterAction = new \Laminas\Filter\Whitelist(['list' => ['off', 'auto']]); $light = $filterAction($light) ?? 'off'; $response = $this?->robotManager?->updateLightStatus($robotId, $light); return new JsonModel([ 'success' => $response ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function updateLiftStatusAction() { try { // we check the method if ($this?->getRequest()?->isPost()) { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $lift = $this?->params()?->fromQuery('lift', -1); $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1 || $lift == -1) { return $this?->handleError(400, 'You need to send robotId and lift'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $filterAction = new \Laminas\Filter\Whitelist(['list' => ['manual', 'auto']]); $lift = $filterAction($lift) ?? 'manual'; $response = $this?->robotManager?->updateLiftStatus($robotId, $lift); return new JsonModel([ 'success' => $response ]); } else { return $this?->handleError(405, 'You need to send a POST request'); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function deleteApiKeyAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $key = $this?->params()?->fromQuery('key', -1); if ($key == -1) { return $this?->handleError(400, 'You need to send key'); } $owner = $this?->robotManager?->checkAPIKeyOwner($identity['id'], $key); if (!$owner) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $this?->robotManager?->deleteAPIKey($key); return new JsonModel([ 'text' => 'You have successfully deleted your API Key.', 'type' => 'success', 'redirectUrl' => '/export-data' //Keep user same page, name to be defined ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function generateRobotApiKeyAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $APIKey = $this?->robotManager?->generateAPIKey($identity['id'], $robotId); return new JsonModel([ 'key' => $APIKey ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function getRobotAvailableObservablesAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } // we check if the user has permision to do this $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isAdmin($identity) && !$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $robotObs = $this?->robotManager?->returnRobotAvailableObservables($robotId); return new JsonModel([ 'robotObs' => $robotObs ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function getAllAvailableObservablesAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } $allObs = $this?->robotManager?->returnAllAvailableObservables(); return new JsonModel([ 'data' => $allObs ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function getRobotApiKeyAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $APIKey = $this?->robotManager?->getRobotApiKey($identity['id'], $robotId); return new JsonModel([ 'key' => $APIKey ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function removeUserFromRobotAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('id', -1); if ($robotId == -1) { return $this?->handleError(400, 'You need to send robotId'); } $userId = $this?->params()?->fromQuery('userId', $identity['id']); $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isWritable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $this?->robotManager?->removeUserFromRobot($robotId, $userId); return new JsonModel([ 'text' => 'You have successfully removed a user from the robot.', 'type' => 'success', ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function showVideoAction() { try { // we check the user session $identity = $this?->identity(); if (!isset($identity)) { return $this?->handleError(401, 'User not registered or not logged in'); } // we check if all params are here $robotId = $this?->params()?->fromQuery('robotId', -1); $typeId = $this?->params()?->fromQuery('typeId', -1); $cameraId = $this?->params()?->fromQuery('cameraId', -1); if ($robotId == -1 || $typeId == -1 || $cameraId == -1) { return $this?->handleError(400, 'You need to send robotId, typeId and cameraId'); } $select = ['u.id' => $identity['id'], 'r.id' => $robotId]; $role = $this?->robotManager?->getUserRoleInEntity($select, 'r.id'); if (!$this?->isReadable($role)) { return $this?->handleError(403, 'You do not have sufficient permissions to access this functionality'); } $stream = $this?->robotManager?->getStreamStatus($robotId); $stream_stat = $stream != '0' || $stream == null; $streamDetails = "robotId: " . $robotId . ", typeId: " . $typeId . ", cameraId: " . $cameraId . ", is streaming: " . $stream . ", stream status: " . strval($stream_stat); error_log("Streaming about to start: $streamDetails", E_USER_NOTICE); if ($stream != '0' || $stream == null) { $streamDetails = $this?->robotManager?->getStreamingDetails($robotId); if ($streamDetails !== null) { try { $adapter = new \Laminas\Http\Client\Adapter\Curl(); $adapter?->setCurlOption(CURLOPT_FOLLOWLOCATION, true); $adapter?->setCurlOption(CURLOPT_SSL_VERIFYPEER, false); # I was getting errors about secured certificates, this is why I have tried to remove https and disabled verification this is a security risk. $url_in = str_replace(("https", "http", $streamDetails?->url_in); $url_details = "This is the url: " . $url_in; error_log("Streaming about to start: $url_details", E_USER_NOTICE); $uri = $streamDetails?->url_in . "/" . $streamDetails?->stream_id; $client = new \Laminas\Http\Client($uri); $client?->setAdapter($adapter); $client?->setOptions([ "timeout" => 2 ]); $response = $client?->send()?->getBody(); } catch (\Laminas\Http\Client\Adapter\Exception\TimeoutException $e) { // when a client wants to initiate connection and there already exists an entry in robot stream table, verify if this uri is functional ie do I get a timeout // or do I get connection refused. React based on this response. return new JsonModel([ 'robotId' => $robotId, 'streamId' => $streamDetails?->stream_id, 'url' => $streamDetails?->url_out, ]); } catch (\Exception $e) { $this?->robotManager?->updateRobotStreamStatus($robotId, 0); $this?->robotManager?->deleteStream(['id' => $robotId]); sleep(3); $res = $this?->createStreamParameters($robotId, $typeId, $cameraId); if ($res == False) { return new JsonModel([ 'error' => 'connection refused', ]); } return new JsonModel([ 'url' => $res['url_out'], 'streamId' => $res['streamId'], 'typeId' => $typeId, ]); } return new JsonModel([ 'robotId' => $robotId, 'streamId' => $streamDetails?->stream_id, 'url' => $streamDetails?->url_out, ]); } else { return new JsonModel([ 'error' => 'streaming details not found', ]); } } else { $res = $this?->createStreamParameters($robotId, $typeId, $cameraId); if ($res == False) { return new JsonModel([ 'error' => 'connection refused', ]); } return new JsonModel([ 'url' => $res['url_out'], 'streamId' => $res['streamId'], 'typeId' => $typeId, ]); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function closeVideoStreamAction() { try { $streamId = $this?->params()?->fromQuery('streamId', -1); $robotId = $this?->params()?->fromQuery('robotId', -1); if ($this?->robotManager?->checkIfStreamIdValid($robotId, $streamId)) { $this?->robotManager?->updateRobotStreamStatus($robotId, 0); $this?->robotManager?->deleteStream(['id' => $robotId]); return new JsonModel([ 'result' => 'closed' ]); } else { return new JsonModel([ 'result' => 'error not permitted' ]); } } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } public function verifyVideoStreamAction() { try { $streamId = $this?->params()?->fromQuery('streamId', -1); $robotId = $this?->params()?->fromQuery('robotId', -1); if ($streamId == null) { return new JsonModel([ 'error' => 'error' ]); } return new JsonModel([ $this?->robotManager?->checkIfStreamIdValid($robotId, $streamId) ]); } catch (Exception $e) { return $this?->handleError(500, 'Internal Server Error: ' . $e?->getMessage()); } } /** * HELPERS */ private function createStreamParameters($robotId, $typeId, $cameraId) { $streamId = bin2hex(random_bytes(20)); $this?->robotManager?->insertStream(['id' => $robotId, 'stream_id' => $streamId]); $host = $_SERVER['SERVER_NAME'] == 'localhost' ? $this?->config['video_streaming']['localhost'] : $this?->config['video_streaming']['host']; $uri = 'http://' . $host . ':3000/api/start-stream?streamId=' . $streamId . '&robotId=' . $robotId; try { $adapter = new \Laminas\Http\Client\Adapter\Curl(); $adapter?->setCurlOption(CURLOPT_NOBODY, true); $client = new \Laminas\Http\Client($uri); $response = $client?->send()?->getBody(); } catch (\AdapterException\RuntimeException $e) { $this?->robotManager?->deleteStream(['id' => $robotId]); return False; } catch (\Exception $e) { $this?->robotManager?->deleteStream(['id' => $robotId]); $this?->robotManager?->updateRobotStreamStatus($robotId, 0); return False; } $response = \Laminas\Json\Json::decode($response); $url_in = 'https://' . $host . ':' . $response?->port; //https or http $url_out = 'wss://' . $host . ':' . $response?->port; if ($typeId == 'normal_video') { $this?->robotManager?->updateRobotStreamStatus($robotId, 1); $this?->robotManager?->updateStreamTable($robotId, ['url_in' => $url_in, 'url_out' => $url_out, 'normal_video' => 1, 'audio' => 1, 'camera_id' => $cameraId]); } elseif ($typeId == 'thermal_video') { $this?->robotManager?->updateRobotStreamStatus($robotId, 1); $this?->robotManager?->updateStreamTable($robotId, ['url_in' => $url_in, 'url_out' => $url_out, 'thermal_video' => 1, 'camera_id' => $cameraId]); } else { $this?->robotManager?->updateRobotStreamStatus($robotId, 1); $this?->robotManager?->updateStreamTable($robotId, ['url_in' => $url_in, 'url_out' => $url_out, 'audio' => 1, 'camera_id' => $cameraId]); } return [ 'url_out' => $url_out, 'streamId' => $streamId ]; } private function getHouseDimensions($robotId) { $configFile = $this?->robotManager?->getConfigurationFile($robotId); $xml = simplexml_load_string($configFile); return [ 'dimX' => (int) $xml?->house?->{'dimension-x'} ?? null, 'dimY' => (int) $xml?->house?->{'dimension-y'} ?? null ]; } // for some reason I couldn't move this is the robot manager. I was getting memory leakages when I tried to inject alertManager into the robotManager public function getRobotStatusLayoutData($identity, $robotId) { $identity = $this?->identity(); $status = $this?->robotManager?->returnRobotStatus($identity, $robotId); $alerts = [ 'total' => count($this?->alertManager?->alertsAfterLastLogin($identity)) ?? 0, 'ambientConditions' => $this?->alertManager?->ambientConditionAlertCount($identity['id'], $robotId), 'healthAndWelfare' => $this?->alertManager?->healthandWelfareAlertCount($identity['id'], $robotId), 'equipment' => $this?->alertManager?->equipmentAlertCount($identity['id'], $robotId), ]; $lastping = $this?->robotManager?->getLastRobotPing($robotId); return [ 'robotType' => $status?->robot_type ?? 'cb', 'location' => $status?->location ?? null, 'battery' => $status?->battery ?? null, 'estimatedRecharge' => $status?->remaining_recharge_time ?? '0', 'batteryTime' => $status?->battery_time ?? '0', 'restartDate' => $status?->restart_date ?? null, 'operationalState' => $status?->operational_state ?? null, 'onCharger' => $status?->on_charger ?? null, 'errorMsg' => $status?->error_msg ?? null, 'status' => $status?->status ?? null, 'alert' => $alerts, 'lastUpdate' => $lastping ? $lastping : null ]; } public function getRobotCameraFromConfig($robotId) { $configFile = $this?->robotManager?->getConfigurationFile($robotId); if (isset($configFile)) { $xml = simplexml_load_string($configFile); return $xml?->camera; } else { return null; } } public function getObjectsForObservablesElasticSearch($roundId, $observable, $camera, $offset, $limit, $from, $to) { $this?->counter = 1; $objects = $this?->elasticSearchManager?->image_search($roundId, $observable, $camera, $offset, $limit, $from, $to)['hits']['hits']; $count = count($objects); // If object count is zero it means we reached the end of the objects in the location. The key is set to the last object once more. if ($count == 0) { return [ 'images' => [], //null 'key' => $offset + $count, ]; } $pool = Pool::create(); foreach ($objects as $object) { $pool?->add(function () use ($object) { $this?->counter += 1; $request = $this?->s3FileSystem?->createUri($object['_source']['objectKey'], '+20 minutes'); $metaData = $this?->s3FileSystem?->getHeader($object['_source']['objectKey']); return [ 'request' => $request, 'metaData' => $metaData ]; })?->then(function ($output) use ($object) { $request = $output['request']; $metaData = $output['metaData']; $time = strtotime($object['_source']['createdDate']); //Extract time from file name if have correct format, because time extracted from last modified is in GMT $nameTime = strtotime(str_replace(("_", ":", substr(explode("/", $object['_source']['objectKey'])[4], 14, 20))); $this?->images[] = [ 'uri' => (string) $request?->getUri(), 'time' => $nameTime ? date("Y-m-d H:i:s", $nameTime) : date("Y-m-d H:i:s", $time), 'coordinates' => $metaData['@metadata']['headers']['x-amz-meta-coordinates'] ?? NULL, 'camera' => $metaData['@metadata']['headers']['x-amz-meta-camera'] ?? NULL ]; })?->catch(function (Throwable $exception) { // Handle exception }); // By default return 6 images max if ($this?->counter == $limit || $this?->counter == $count) { $this?->key = $object['_source']['objectKey']; break; } $this?->counter++; } $pool?->wait(); return [ 'images' => $this?->images, 'key' => $offset + $count, ]; } }
Editor is loading...