Untitled
user_3839718
php
2 years ago
74 kB
7
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);
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 and entry in robot stream table, verify if this uri is functional ie do I get a time out
# 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 {
$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 ($counter == $limit || $counter == $count) {
$this?->key = $object?->_source?->objectKey;
break;
}
$counter++;
}
$pool?->wait();
return [
'images' => $this?->images,
'key' => $offset + $count,
];
}
}Editor is loading...