.
*/
/* * ***************************Includes**********************************/
require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';
require_once dirname(__FILE__) . '/../../3rdparty/NeatoBotvacClient.php';
require_once dirname(__FILE__) . '/../../3rdparty/NeatoBotvacRobot.php';
class neato extends eqLogic {
/***************************Attributs*******************************/
public static $_widgetPossibility = array('custom' => true, 'custom::layout' => false);
public static $_encryptConfigKey = array('password');
/* * ***********************Methode static*************************** */
public static function templateWidget(){
$return = array('info' => array('string' => array()));
$return['info']['string']['state'] = array(
'template' => 'tmplmultistate',
'test' => array(
array('operation' => '#value# == 2','state_light' => ''),
array('operation' => '#value# == 3','state_light' => ''),
array('operation' => '#value# > 3 || #value# < 2','state_light' => '')
)
);
return $return;
}
public static function cron15($_eqlogic_id = null,$_data = null) {
if ($_eqlogic_id !== null) {
$eqLogics = array(eqLogic::byId($_eqlogic_id));
} else {
$eqLogics = eqLogic::byType('neato');
}
foreach ($eqLogics as $neato) {
log::add('neato', 'debug', 'cron15: Neato object : '.$neato->getName());
$changed = false;
if ($neato->getIsEnable() != 1) {
continue;
}
$serial = $neato->getLogicalId();
$secret = $neato->getConfiguration('secret');
if($_data != null && is_array($_data)){
$result = $_data;
}else{
$robot = new NeatoBotvacRobot($serial, $secret, $neato->getConfiguration('model'), $neato->getConfiguration('robotid'));
$result = $robot->getState();
}
log::add('neato', 'debug', json_encode($result));
if (!isset($result['details'])) {
continue;
}
$batterylevel = $result['details']['charge'];
if ($batterylevel < 0) {
$batterylevel = 0;
} else if ($batterylevel > 97) {
$batterylevel = 100;
}
if ($batterylevel != $neato->getStatus('battery')) {
$neato->batteryStatus($batterylevel);
$changed = true;
}
$oldapi = false;
if (oldapi===true) {
$firmware = $result['meta']['firmware'];
if ($neato->getConfiguration('firmware', '') != $firmware) {
$neato->setConfiguration('firmware', $firmware);
$neato->save();
}
$modelCleaning = $result['availableServices']['houseCleaning'];
if ($neato->getConfiguration('modelCleaning', '') != $modelCleaning) {
$neato->setConfiguration('modelCleaning', $modelCleaning);
$neato->save();
}
$maps = $result['availableServices']['maps'];
if ($neato->getConfiguration('maps', '') != $maps) {
$neato->setConfiguration('maps', $maps);
$neato->save();
}
$changed = $neato->checkAndUpdateCmd('docked', $result['details']['isDocked']) || $changed;
$changed = $neato->checkAndUpdateCmd('charging', $result['details']['isCharging']) || $changed;
$changed = $neato->checkAndUpdateCmd('scheduled', $result['details']['isScheduleEnabled']) || $changed;
$changed = $neato->checkAndUpdateCmd('etattech', $result['state']) || $changed;
} else {
$changed = $neato->checkAndUpdateCmd('docked', $result['details']['is_docked']) || $changed;
$changed = $neato->checkAndUpdateCmd('charging', $result['details']['is_charging']) || $changed;
$changed = $neato->checkAndUpdateCmd('etattech', $result['state']) || $changed;
}
$state = $result['state'];
switch ($state) {
case "idle":
case 1:
$state = __('Prêt à nettoyer', __FILE__);
break;
case "busy":
case 2:
$state = __('En cours de nettoyage', __FILE__);
break;
case "paused":
case 3:
$state = __('En pause', __FILE__);
break;
}
$changed = $neato->checkAndUpdateCmd('etat', $state) || $changed;
$alert = $result['error'];
switch ($alert) {
case 'ui_alert_recovering_location':
$alert = __('Recherche position', __FILE__);
break;
case 'ui_error_dust_bin_emptied':
$alert = __('Bac à poussières vidé', __FILE__);
break;
case 'ui_alert_dust_bin_full':
$alert = __('Bac à poussières plein', __FILE__);
break;
case 'ui_error_dust_bin_full':
$alert = __('Bac à poussières plein', __FILE__);
break;
case 'ui_error_navigation_origin_unclean':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_error_navigation_noprogress':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_alert_charging_power':
$alert = __('Besoin de me charger', __FILE__);
break;
case 'ui_alert_invalid':
$alert = __('Aucune alerte', __FILE__);
break;
case '':
$alert = __('Aucune alerte', __FILE__);
break;
case 'ui_alert_return_to_base':
$alert = __('Retour à la base', __FILE__);
break;
case 'ui_alert_return_to_start':
$alert = __('Retour au départ', __FILE__);
break;
case 'ui_error_bumper_stuck':
$alert = __('Pare-chocs bloqué', __FILE__);
break;
case 'ui_error_brush_stuck':
$alert = __('Brosse bloquée', __FILE__);
break;
case 'ui_error_brush_overload':
$alert = __('Brosse bloquée', __FILE__);
break;
case 'ui_error_picked_up':
$alert = __('Reposez moi au sol', __FILE__);
break;
case 'ui_alert_return_to_charge':
$alert = __('Besoin de me charger', __FILE__);
break;
case 'ui_alert_busy_charging':
$alert = __('Besoin de me charger', __FILE__);
break;
case 'ui_error_deck_debris':
$alert = __('Laser Obstrué', __FILE__);
break;
case 'ui_error_navigation_undockingfailed':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_error_navigation_falling':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_error_navigation_nomotioncommands':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_error_navigation_pathproblems_returninghome':
$alert = __('Bloqué', __FILE__);
break;
case 'ui_error_navigation_rightdrop_leftbump':
$alert = __('Bloqué', __FILE__);
case 'ui_error_navigation_backdrop_leftbump':
$alert = __('Bloqué', __FILE__);
break;
}
$changed = $neato->checkAndUpdateCmd('alert', $alert) || $changed;
if ($changed == true) {
$neato->refreshWidget();
}
}
}
public static function getRobot() {
try {
$email = config::byKey('email', 'neato', 0);
$password = config::byKey('password', 'neato', 0);
$client = new NeatoBotvacClient(false);
$auth = $client->authorize($email, $password, true);
if ($auth === false) {
log::add('neato', 'debug', 'Unable to authorize for neato client');
$client = new NeatoBotvacClient(false, "vorwerk");
$auth = $client->authorize($email, $password, true);
}
if ($auth === false) {
log::add('neato', 'debug', 'Unable to authorize for vorwerk client');
$client = new NeatoBotvacClient(false, "orbital");
$auth = $client->authorize($email, $password, true);
}
if ($auth !== false) {
log::add('neato', 'debug', 'Token: ' . $auth);
$result = $client->getRobots();
if ($result !== false) {
if (isset($result["robots"])) {
$robots = $result["robots"];
} else {
$robots = $result;
}
foreach ($robots as $robot) {
log::add('neato', 'debug', json_encode($robot));
$eqLogic = eqLogic::byLogicalId($robot['serial'], 'neato');
if (!is_object($eqLogic)) {
$eqLogic = new self();
$eqLogic->setLogicalId($robot['serial']);
$eqLogic->setCategory('automatism', 1);
$eqLogic->setName('Neato ' . $robot['name']);
$eqLogic->setConfiguration('battery_type', 'Batterie');
$eqLogic->setConfiguration('mac', $robot['mac_address']);
$eqLogic->setEqType_name('neato');
$eqLogic->setIsVisible(1);
$eqLogic->setIsEnable(1);
}
if (isset($robot['secret_key'])) {
$eqLogic->setConfiguration('secret', $robot['secret_key']);
$eqLogic->setConfiguration('model', $robot['model']);
//$eqLogic->setConfiguration('firmware', "unknown");
//$eqLogic->setConfiguration('robotid', $robot['serial']);
} else {
$eqLogic->setConfiguration('secret', $client->token);
$eqLogic->setConfiguration('model', $robot['model_name']);
$eqLogic->setConfiguration('firmware', $robot['firmware']);
$eqLogic->setConfiguration('robotid', $robot['id']);
}
$eqLogic->save();
$robot_client = new NeatoBotvacRobot($eqLogic->getConfiguration('serial'), $eqLogic->getConfiguration('secret'), $eqLogic->getConfiguration('model'), $eqLogic->getConfiguration('robotid'));
if ($robot_client->apimodel == "ability") {
$maps = [];
foreach ($robot_client->getRanks() as $map) {
$rank_id = $map['rank_uuid'];
$floor_id = $map['floorplan_uuid'];
$floor_name = $map['name'];
array_push($maps,array("id"=>$floor_id,"name"=>$floor_name));
}
$robot['persistent_maps'] = $maps;
}
if($robot['persistent_maps'] && count($robot['persistent_maps']) > 0){
foreach($robot['persistent_maps'] as $maps){
$cmd = $eqLogic->getCmd(null, 'start::'.$maps['id']);
if (!is_object($cmd)) {
$cmd = new neatocmd();
$cmd->setLogicalId('start::'.$maps['id']);
$cmd->setName(__('Démarrer ', __FILE__).$maps['name']);
$cmd->setOrder(4);
}
$cmd->setType('action');
$cmd->setSubType('other');
$cmd->setEqLogic_id($eqLogic->getId());
$cmd->save();
$cmd = $eqLogic->getCmd(null, 'starteco::'.$maps['id']);
if (!is_object($cmd)) {
$cmd = new neatocmd();
$cmd->setLogicalId('starteco::'.$maps['id']);
$cmd->setIsVisible(0);
$cmd->setName(__('Démarrer Turbo ', __FILE__).$maps['name']);
}
$cmd->setConfiguration('boundary',$boundary['id']);
$cmd->setType('action');
$cmd->setSubType('other');
$cmd->setEqLogic_id($eqLogic->getId());
$cmd->save();
$boundaries = $robot_client->getMapBoundaries($maps['id']);
log::add('neato','debug','boundaries : '.json_encode($boundaries));
if(isset($boundaries['data']) && isset($boundaries['data']['boundaries'])){
foreach($boundaries['data']['boundaries'] as $boundary){
if($boundary['name'] == ''){
continue;
}
$cmd = $eqLogic->getCmd(null, 'start::'.$boundary['id']);
if (!is_object($cmd)) {
$cmd = new neatocmd();
$cmd->setLogicalId('start::'.$boundary['id']);
$cmd->setName(__('Démarrer ', __FILE__).$maps['name'].' '.$boundary['name']);
$cmd->setOrder(4);
}
$cmd->setConfiguration('boundary',$boundary['id']);
$cmd->setType('action');
$cmd->setSubType('other');
$cmd->setEqLogic_id($eqLogic->getId());
$cmd->save();
$cmd = $eqLogic->getCmd(null, 'starteco::'.$boundary['id']);
if (!is_object($cmd)) {
$cmd = new neatocmd();
$cmd->setLogicalId('starteco::'.$boundary['id']);
$cmd->setIsVisible(0);
$cmd->setName(__('Démarrer Turbo ', __FILE__).$maps['name'].' '.$boundary['name']);
}
$cmd->setConfiguration('boundary',$boundary['id']);
$cmd->setType('action');
$cmd->setSubType('other');
$cmd->setSubType('other');
$cmd->setEqLogic_id($eqLogic->getId());
$cmd->save();
}
}
}
}
}
$eqLogic->cron15($eqLogic->getId());
}
} else {
log::add('neato', 'debug', 'Unable to authorize for orbital client');
}
} catch (Exception $e) {
log::add('neato', 'debug', log::exception($e));
}
}
public function getImage() {
$file = dirname(__FILE__) . '/../config/' . $this->getConfiguration('model') . '.png';
if (file_exists($file)) {
return 'plugins/neato/core/config/' . $this->getConfiguration('model') . '.png';
} else {
return 'plugins/neato/plugin_info/neato_icon.png';
}
}
public function postSave() {
$etat = $this->getCmd(null, 'etat');
if (!is_object($etat)) {
$etat = new neatocmd();
$etat->setName(__('Etat', __FILE__));
$etat->setIsVisible(0);
}
$etat->setEqLogic_id($this->getId());
$etat->setLogicalId('etat');
$etat->setType('info');
$etat->setSubType('string');
$etat->save();
$etattech = $this->getCmd(null, 'etattech');
if (!is_object($etattech)) {
$etattech = new neatocmd();
$etattech->setName(__('Code état', __FILE__));
$etattech->setOrder(3);
$etattech->setTemplate('dashboard','neato::state');
$etattech->setTemplate('mobile','neato::state');
}
$etattech->setEqLogic_id($this->getId());
$etattech->setLogicalId('etattech');
$etattech->setType('info');
$etattech->setSubType('string');
$etattech->save();
$alert = $this->getCmd(null, 'alert');
if (!is_object($alert)) {
$alert = new neatocmd();
$alert->setName(__('Alerte', __FILE__));
$alert->setOrder(2);
}
$alert->setEqLogic_id($this->getId());
$alert->setLogicalId('alert');
$alert->setType('info');
$alert->setSubType('string');
$alert->save();
$charging = $this->getCmd(null, 'charging');
if (!is_object($charging)) {
$charging = new neatocmd();
$charging->setName(__('En charge', __FILE__));
$charging->setIsVisible(0);
$charging->setConfiguration('repeatEventManagement','never');
}
$charging->setEqLogic_id($this->getId());
$charging->setLogicalId('charging');
$charging->setType('info');
$charging->setSubType('binary');
$charging->save();
$docked = $this->getCmd(null, 'docked');
if (!is_object($docked)) {
$docked = new neatocmd();
$docked->setName(__('Sur dock', __FILE__));
$docked->setIsVisible(0);
$docked->setConfiguration('repeatEventManagement','never');
}
$docked->setEqLogic_id($this->getId());
$docked->setLogicalId('docked');
$docked->setType('info');
$docked->setSubType('binary');
$docked->save();
$scheduled = $this->getCmd(null, 'scheduled');
if (!is_object($scheduled)) {
$scheduled = new neatocmd();
$scheduled->setName(__('Programmation', __FILE__));
$scheduled->setIsVisible(0);
$scheduled->setConfiguration('repeatEventManagement','never');
}
$scheduled->setEqLogic_id($this->getId());
$scheduled->setLogicalId('scheduled');
$scheduled->setType('info');
$scheduled->setSubType('binary');
$scheduled->save();
$start = $this->getCmd(null, 'start');
if (!is_object($start)) {
$start = new neatocmd();
$start->setLogicalId('start');
$start->setName(__('Démarrer', __FILE__));
$start->setOrder(4);
}
$start->setType('action');
$start->setSubType('other');
$start->setEqLogic_id($this->getId());
$start->save();
$starteco = $this->getCmd(null, 'starteco');
if (!is_object($starteco)) {
$starteco = new neatocmd();
$starteco->setLogicalId('starteco');
$starteco->setIsVisible(0);
$starteco->setName(__('Démarrer Turbo, __FILE__));
}
$starteco->setType('action');
$starteco->setSubType('other');
$starteco->setEqLogic_id($this->getId());
$starteco->save();
$pause = $this->getCmd(null, 'pause');
if (!is_object($pause)) {
$pause = new neatocmd();
$pause->setLogicalId('pause');
$pause->setName(__('Pause', __FILE__));
$pause->setIsVisible(0);
}
$pause->setType('action');
$pause->setSubType('other');
$pause->setEqLogic_id($this->getId());
$pause->save();
$resume = $this->getCmd(null, 'resume');
if (!is_object($resume)) {
$resume = new neatocmd();
$resume->setLogicalId('resume');
$resume->setName(__('Reprendre', __FILE__));
$resume->setIsVisible(0);
}
$resume->setType('action');
$resume->setSubType('other');
$resume->setEqLogic_id($this->getId());
$resume->save();
$base = $this->getCmd(null, 'base');
if (!is_object($base)) {
$base = new neatocmd();
$base->setLogicalId('base');
$base->setName(__('Retour base', __FILE__));
$base->setOrder(5);
}
$base->setType('action');
$base->setSubType('other');
$base->setEqLogic_id($this->getId());
$base->save();
$stop = $this->getCmd(null, 'stop');
if (!is_object($stop)) {
$stop = new neatocmd();
$stop->setLogicalId('stop');
$stop->setIsVisible(1);
$stop->setName(__('Arrêter', __FILE__));
$stop->setOrder(4);
}
$stop->setType('action');
$stop->setSubType('other');
$stop->setEqLogic_id($this->getId());
$stop->save();
$refresh = $this->getCmd(null, 'refresh');
if (!is_object($refresh)) {
$refresh = new neatocmd();
}
$refresh->setName(__('Rafraichir', __FILE__));
$refresh->setLogicalId('refresh');
$refresh->setEqLogic_id($this->getId());
$refresh->setType('action');
$refresh->setSubType('other');
$refresh->save();
}
}
class neatoCmd extends cmd {
/***************************Attributs*******************************/
/*************************Methode static****************************/
/***********************Methode d'instance**************************/
public function imperihomeGenerate($ISSStructure) {
$eqLogic = $this->getEqLogic();
$object = $eqLogic->getObject();
if ($this->getLogicalId() == 'alert') {
$info_device = array(
"id" => $this->getId(),
"name" => $eqLogic->getName(),
"room" => (is_object($object)) ? $object->getId() : 99999,
"type" => imperihome::convertType($this, $ISSStructure, true),
'params' => array(),
);
$cmd_params = imperihome::generateParam($this, $info_device['type'], $ISSStructure);
$info_device['params'] = $cmd_params['params'];
$info_device['params'][0]['value'] = '#' . $eqLogic->getCmd('info', 'etat')->getId() . '# - #' . $eqLogic->getCmd('info', 'alert')->getId() . '#';
return $info_device;
}
$type = 'DevMultiSwitch';
$info_device = array(
'id' => $this->getId(),
'name' => $eqLogic->getName(),
'room' => (is_object($object)) ? $object->getId() : 99999,
'type' => $type,
'params' => array(),
);
$info_device['params'] = $ISSStructure[$info_device['type']]['params'];
$info_device['params'][0]['value'] = '#' . $eqLogic->getCmd('info', 'etat')->getId() . '#';
$info_device['params'][1]['value'] = 'Retour base,Arrêter,Reprendre,Pause,Démarrer Turbo Maison,Démarrer Eco Maison,Rafraichir';
return $info_device;
}
public function imperihomeAction($_action, $_value) {
if ($_action == 'setChoice') {
$eqLogic = $this->getEqLogic();
switch ($_value) {
case 'Retour base':
$eqLogic->getCmd('action', 'base')->execCmd();
break;
case 'Arrêter':
$eqLogic->getCmd('action', 'stop')->execCmd();
break;
case 'Reprendre':
$eqLogic->getCmd('action', 'resume')->execCmd();
break;
case 'Pause':
$eqLogic->getCmd('action', 'pause')->execCmd();
break;
case 'Démarrer Turbo Maison':
$eqLogic->getCmd('action', 'start')->execCmd();
break;
case 'Démarrer Eco Maison':
$eqLogic->getCmd('action', 'starteco')->execCmd();
break;
case 'Rafraichir':
$eqLogic->getCmd('action', 'refresh')->execCmd();
break;
}
}
}
public function imperihomeCmd() {
return ($this->getLogicalId() == 'etat' || $this->getLogicalId() == 'alert');
}
public function execute($_options = null) {
if ($this->getType() == '') {
return '';
}
$eqLogic = $this->getEqlogic();
$robot = new NeatoBotvacRobot($eqLogic->getLogicalId(), $eqLogic->getConfiguration('secret'), $eqLogic->getConfiguration('model'), $eqLogic->getConfiguration('robotid'));
switch ($this->getLogicalId()) {
case 'refresh':
$eqLogic->cron15($eqLogic->getId());
return;
break;
case 'stop':
$result = $robot->stopCleaning();
break;
case 'pause':
$result = $robot->pauseCleaning();
break;
case 'resume':
$result = $robot->resumeCleaning();
break;
case 'base':
$result = $robot->sendToBase();
break;
case 'start':
$result = $robot->startCleaning(false,$eqLogic->getConfiguration('modelCleaning', ''));
break;
case 'starteco':
$result = $robot->startCleaning(true,$eqLogic->getConfiguration('modelCleaning', ''));
break;
}
if(strpos($this->getLogicalId(),'start::') !== false){
if($this->getConfiguration('boundary') != ''){
$result = $robot->startCleaning(false,$eqLogic->getConfiguration('modelCleaning', ''),$eqLogic->getConfiguration('maps', ''),$this->getConfiguration('boundary', ''));
}else{
$result = $robot->startCleaning(false,$eqLogic->getConfiguration('modelCleaning', ''),$eqLogic->getConfiguration('maps', ''));
}
}else if(strpos($this->getLogicalId(),'starteco::') !== false){
if($this->getConfiguration('boundary') != ''){
$result = $robot->startCleaning(true,$eqLogic->getConfiguration('modelCleaning', ''),$eqLogic->getConfiguration('maps', ''),$this->getConfiguration('boundary', ''));
}else{
$result = $robot->startCleaning(true,$eqLogic->getConfiguration('modelCleaning', ''),$eqLogic->getConfiguration('maps', ''));
}
}
log::add('neato','debug','Command execution result : '.json_encode($result));
if(!isset($result['result']) && !isset($result['ability'])){
throw new \Exception(__('Echec de l\'éxecution de la commande',__FILE__));
}
if(isset($result['result']) && $result['result'] != 'ok'){
throw new \Exception(__('Echec de l\'éxecution de la commande : ',__FILE__).$result['result']);
}
if(isset($result['message'])){
throw new \Exception(__('Echec de l\'éxecution de la commande : ',__FILE__).$result['message']);
}
log::add('neato','debug','Command execution result : '.json_encode($result));
$eqLogic->cron15($eqLogic->getId(),$result);
}
/************************Getteur Setteur****************************/
}
?>