a:1:{i:0;a:6:{s:5:"TITLE";s:5:"MegaD";s:5:"NOLOG";s:1:"0";s:11:"DESCRIPTION";s:104:"Класс для связи устройств MegaD с объектами системы МД
ver 3.2";s:7:"METHODS";a:3:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:278:"Получение обработанного сообщения от файла mega.php или метода getData. Для каждого объекта Меги нужно указать каким именно объектам, как и что будет передано.";s:4:"CODE";s:1338:"/* Общий код метода:
   Обработка сообщения о температуре внетреннего датчика
   ToDo Тревога при превышении температуты
   Установка статуса alive
*/   

$reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все )

$ot=$this->object_title;      

// Открывает лог если нужно
if ($reclog) { $log = getLogger($this); }

$this->setProperty('alive',1);
$alive_timeout=(int)$this->getProperty('aliveTimeOut');
if (!$alive_timeout) { $alive_timeout=15*60; }
setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);


/* Получение сообщения с данными температуры внутреннего датчика */
$dt=$params['tget'];
if (isset($dt)) {
  // Проверить $dt на число и Записать в свойство объекта 
  if (is_numeric($dt)) {  
    $this->setProperty('temperature', $dt);
  } else {
    if ($reclog) { $log->error('Failed to get data internal temperature sensor for object '.$ot); }
  }
  // Сразу установить флаг "не живой" если в $dt ничего нет
  if (!strlen($dt)) {  
    $this->setProperty('alive',0);
  }  
}";s:11:"CALL_PARENT";s:1:"0";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:43:00";s:15:"EXECUTED_PARAMS";s:83:"a:3:{s:2:"pt";i:15;s:6:"iasked";s:1:"0";s:21:"ORIGINAL_OBJECT_TITLE";s:6:"MegaD1";}";}i:1;a:7:{s:5:"TITLE";s:9:"setOutput";s:11:"DESCRIPTION";s:344:"Отправка команды Меге на коммутацию ее выхода. Метод сформирует строку вида http://192.168.0.14/sec/?cmd=0:1, что, к примеру, означает включить канал 0. В качестве параметров требуются $params['port'] и $params['value']";s:4:"CODE";s:556:"// Expects 'output' and 'value' in $params

$reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все )

// Открывает лог если нужно
if ($reclog) { $log = getLogger($this); }

$cmdUrl = sprintf('http://%s/%s/?cmd=%d:%d', $this->getProperty('IpAddress'), $this->getProperty('Password'),
                  intval($params['port']), intval($params['value']));
// Запись данных в лог
if ($reclog == 2) {
  $log->trace('setOutput method: '.$cmdUrl);
}
getURL($cmdUrl, 0);";s:11:"CALL_PARENT";s:1:"0";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:15:46";s:15:"EXECUTED_PARAMS";s:79:"a:3:{s:4:"port";i:7;s:5:"value";i:0;s:21:"ORIGINAL_OBJECT_TITLE";s:6:"MegaD4";}";}i:2;a:7:{s:5:"TITLE";s:7:"getData";s:11:"DESCRIPTION";s:129:"Спросить о состоянии нужного порта с передачей ответа в метод incomingMessage";s:4:"CODE";s:2993:"/* Варианты что можно спросить
 callMethod('MegaD99.getData', array('port'=>'all'));   // спросить сразу все.
 callMethod('MegaD99.getData', array('port'=>1));       // состояние первого порта
 callMethod('MegaD99.getData', array('port'=>'tget'));  // показания встроенного температурного датчика (Только для версии прошивки 3.25 и выше)
*/

$reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все )

$ot = $this->object_title;

// Открывает лог если нужно
if ($reclog) { $log = getLogger($this); }

// Проверка что есть ip адрес
if (!filter_var($this->getProperty('IpAddress'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  if ($reclog) { $log->error('ip address is not set for object '.$ot); }
  return; 
}
// Проверка что есть пароль
if (!$this->getProperty('Password')) {
  if ($reclog) { $log->error('Password address is not set for object '.$ot); }
  return; 
}

// Сборка строки начала запроса для Меги
$cmdUrl = sprintf("http://%s/%s/", $this->getProperty('IpAddress'), $this->getProperty('Password'));

// Добавление дополнительных параметрами запроса в зависимости от его типа
switch ($params['port']) {
case 'all':  // Спросить сразу все
  $cmdUrl .= '?cmd=all';
  $ta = 5;   //Таймаут ожидания меги
  break;
case 'tget': // Температура встроенного датчика
  $cmdUrl .= '?tget=1';
  $ta = 1;
  break;
default:     // Состояние указанного порта
  $cmdUrl .= sprintf("?pt=%d&cmd=get", intval($params['port']));
  $ta = 5;
}

$ctx = stream_context_create(array(
    'http' => array('timeout'=>$ta)
    )
);

// Запрос данных у Меги
$dt = trim(file_get_contents($cmdUrl, 0, $ctx));

// Запись данных в лог
if ($reclog == 2) {
  $log->trace(sprintf('getData method: %s returned %s', $cmdUrl, $dt));
}

// Обработка ответа в зависимости от его типа
switch ($params['port']) {
// Температура внутреннего датчика
case 'tget':
  $this->callMethod('incomingMessage', array('tget'=>$dt));
  break;
// Запустить метод incomingMessage с передачей всего ответа в параметре all
case 'all':
  $this->callMethod('incomingMessage', array('all'=>$dt));
  break;
// Запустить метод incomingMessage с передачей параметров как есть в параметре 'iasked' с номером указанного порта в параметре 'pt'
default:
  $this->callMethod('incomingMessage', array('pt'=>$params['port'], 'iasked'=>$dt));  
}";s:11:"CALL_PARENT";s:1:"0";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:43:00";s:15:"EXECUTED_PARAMS";s:64:"a:2:{s:4:"port";i:15;s:21:"ORIGINAL_OBJECT_TITLE";s:6:"MegaD1";}";}}s:10:"PROPERTIES";a:6:{i:0;a:4:{s:5:"TITLE";s:5:"alive";s:11:"DESCRIPTION";s:206:"Результат периодической проверки температуры. Заменяет обычный пинг. Если есть отклик Меги, то значение будет = 1";s:12:"KEEP_HISTORY";s:1:"0";s:8:"ONCHANGE";s:0:"";}i:1;a:4:{s:5:"TITLE";s:12:"aliveTimeOut";s:11:"DESCRIPTION";s:123:"Время признания девайса живым после последнего опроса температуры";s:12:"KEEP_HISTORY";s:1:"0";s:8:"ONCHANGE";s:0:"";}i:2;a:4:{s:5:"TITLE";s:9:"ipAddress";s:11:"DESCRIPTION";s:122:"Нужен для отправки команд и идентификации объекта если не задан mdid";s:12:"KEEP_HISTORY";s:1:"0";s:8:"ONCHANGE";s:0:"";}i:3;a:4:{s:5:"TITLE";s:4:"mdid";s:11:"DESCRIPTION";s:187:"Идентификатор Меги. Может быть задан в ее настройках. Вначале поиск объекта в megad.php проводится по нему.";s:12:"KEEP_HISTORY";s:1:"0";s:8:"ONCHANGE";s:0:"";}i:4;a:4:{s:5:"TITLE";s:8:"password";s:11:"DESCRIPTION";s:56:"Пароль от Меги (по умолчанию sec)";s:12:"KEEP_HISTORY";s:1:"0";s:8:"ONCHANGE";s:0:"";}i:5;a:4:{s:5:"TITLE";s:11:"temperature";s:11:"DESCRIPTION";s:484:"Температура Меги с историей. Летом в жару шкафы могут сильно нагреваться. Зимой тоже интересно на сколько там холодно. Кроме того, периодический опрос температуры заменяет ping и постоянно проверяет всю цепочку передачи данных.
(Только для версии прошивки 3.25 и выше)";s:12:"KEEP_HISTORY";s:1:"7";s:8:"ONCHANGE";s:0:"";}}s:7:"OBJECTS";a:5:{i:0;a:4:{s:5:"TITLE";s:6:"MegaD1";s:11:"DESCRIPTION";s:27:"Мансарда Мега 1";s:12:"KEEP_HISTORY";s:1:"0";s:7:"METHODS";a:1:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:0:"";s:4:"CODE";s:4152:"$ot=$this->object_title;      
$pt=$params['pt'];

/* если мега передала все параметры одной строкой all=OFF/0;OFF/0;OFF/0;OFF/0;ON/1;OFF/0;OFF/0;OFF;ON;OFF;OFF;OFF;OFF;OFF;288;203
   Смотрим на строку! Сначала идут входы (со счетчиками), потом выходы, и в конце 2 АЦП порта. Универсального кода тут написать невозможно.
   Все будет зависеть от комплектации меги, но с большей долей вероятности у Вас будет модуль 7I7O (7 входов 7 выходов) + 2 АЦП порта.
   Разбиваем строку на массив, перебираем значения и устанавливаем нужные свойства. Это условие сработает !!!_ТОЛЬКО_!!! при передаче мегой 
   параметра all= и может пригодится для синхронизации статусов портов меги и статусов объектов МД. 
   ВНИМАНИЕ! в группах case нужно изменить код на свой!
*/   
if (isset($params['all'])) {
  $ps = explode(";", $params['all']);
  $i=0;
  foreach($ps as $dt) {
    $i = $i + 1;
    // Разделить статус и счетчик
    $dt = explode("/", $dt);
    // Заменить слова на цифры
    if ($dt[0] == 'ON') { $dt[0] = 1; }
    if ($dt[0] == 'OFF') { $dt[0] = 0; }
    // Обрабатываем значения только нужных нам портов
    switch ($i) {
    case 999:
      // Пока мне тут ничего не нужно
      break;
    }
  }
  return;
}


/* Если мы сами спросили Мегу о чем то, запустив метод getData
   и указав номер интересующего нас порта.
*/
if (isset($params['iasked'])) {
  // Разделить статус и счетчик
  $dt = explode("/", $params['iasked']);
  // Заменить слова на цифры    
  if ($dt[0] == 'ON') { $dt[0] = 1; }
  if ($dt[0] == 'OFF') { $dt[0] = 0; }

  // Обрабатываем значения портов, которые мы моглы бы сами спросить
  switch ($pt) {
  case 14: //Port A6 // Датчик газа в воздуховоде притока
    //setGlobal('sensorOutdoorAirGas.status', $dt[0]); 
    callMethod('sensorOutdoorAirGas.statusChanged', array('status'=>$dt[0])); 
    break;
  case 15: //Port A7 // Датчик света на улице
    callMethod('ls_driveway.statusChanged', array('status'=>$dt[0])); 
    break;
  default:
    // Если порта нет в группах case
    say('Я спросил статус порта '.$pt.', а что с ним делать пока не придумал.');
  }
  return;
}


/* Мегадевайс сам шлет нам на сервер get сообщение о изменении статуса порта.
   Мега передаст номер порта в $pt и статус замкнули/разомкнули в $params['m'].
*/
if (isset($pt)) {
  //Параметр 'm' с меги не передается при нажатии. А при отпускании кнопки его значение = 1
  //Переводим его в статус. 1 - замкнули (нажали); 0 - разомкнули (отпустили)
  if (!isset($params['m'])) {$ms=1;} else {$ms=0;}

  switch ($pt) { //pt это порт Меги. Для каждого порта своя группа команд case
  case 4: // P&R
    //say('Передаю датчику воздушной заслонки статус '.$ms);
     callMethod('sensorOutdoorAirDamperClose.statusChanged', array('status'=>$ms));
   break;

  default:
    // Если порта нет в группах case
    say('Получено сообщение от Меги с порта '.$pt);
  }
}";s:11:"CALL_PARENT";s:1:"1";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:43:00";s:15:"EXECUTED_PARAMS";s:41:"a:2:{s:2:"pt";i:15;s:6:"iasked";s:1:"0";}";}}}i:1;a:4:{s:5:"TITLE";s:6:"MegaD2";s:11:"DESCRIPTION";s:27:"Мансарда Мега 2";s:12:"KEEP_HISTORY";s:1:"0";s:7:"METHODS";a:1:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:0:"";s:4:"CODE";s:3693:"$ot=$this->object_title;      
$pt=$params['pt'];

/* если мега передала все параметры одной строкой all=OFF/0;OFF/0;OFF/0;OFF/0;ON/1;OFF/0;OFF/0;OFF;ON;OFF;OFF;OFF;OFF;OFF;288;203
   Смотрим на строку! Сначала идут входы (со счетчиками), потом выходы, и в конце 2 АЦП порта. Универсального кода тут написать невозможно.
   Все будет зависеть от комплектации меги, но с большей долей вероятности у Вас будет модуль 7I7O (7 входов 7 выходов) + 2 АЦП порта.
   Разбиваем строку на массив, перебираем значения и устанавливаем нужные свойства. Это условие сработает !!!_ТОЛЬКО_!!! при передаче мегой 
   параметра all= и может пригодится для синхронизации статусов портов меги и статусов объектов МД. 
*/   
if (isset($params['all'])) {
  $ps = explode(";", $params['all']);
  $i=0;
  foreach($ps as $dt) {
    $i = $i + 1;
    // Разделить статус и счетчик
    $dt = explode("/", $dt);
    // Заменить слова на цифры    
    if ($dt[0] == 'ON') { $dt[0] = 1; }
    if ($dt[0] == 'OFF') { $dt[0] = 0; }
    // Обрабатываем значения только нужных нам портов
    switch ($i) {
    case 999:
      // Пока мне тут ничего не нужно
      break;
    }
  }
  return; 
}


/* Если мы сами спросили Мегу о чем то, запустив метод getData
   и указав номер интересующего нас порта.
*/   
if (isset($params['iasked'])) {
  // Разделить статус и счетчик
  $dt = explode("/", $params['iasked']);
  // Заменить слова на цифры    
  if ($dt[0] == 'ON') { $dt[0] = 1; }
  if ($dt[0] == 'OFF') { $dt[0] = 0; }
  
  // Обрабатываем значения портов, которые мы могли бы сами спросить 
  switch ($pt) {
  case 999:
    // Пока мне тут ничего не нужно
    break;
  default:
    // Если порта нет в группах case, но мы все же спрашиваем его
    say('Я спросил статус порта '.$pt.', а что с ним делать пока не придумал.');
  }
  return; 
}


/* Мегадевайс сам шлет нам на сервер get сообщение о изменении статуса порта.
   Мега передаст номер порта в $pt и статус замкнули/разомкнули в $params['m'].
*/
if (isset($pt)) {

  //Параметр 'm' с меги не передается при нажатии. А при отпускании кнопки его значение = 1
  //Переводим его в статус. 1 - замкнули (нажали); 0 - разомкнули (отпустили)
  if (!isset($params['m'])) {$ms=1;} else {$ms=0;}
  
  switch ($pt) { //pt это порт Меги. Для каждого порта своя группа команд case
  case 999:
    // Пока мне тут ничего не нужно
    break;
  default:
    // Если порта нет в группах case
    say('Получено сообщение от Меги с порта '.$pt);
  }
}";s:11:"CALL_PARENT";s:1:"1";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2014-12-07 16:30:18";s:15:"EXECUTED_PARAMS";s:48:"a:2:{s:2:"pt";s:4:"tget";s:6:"iasked";s:2:"30";}";}}}i:2;a:4:{s:5:"TITLE";s:7:"MegaD99";s:11:"DESCRIPTION";s:58:"Тестовая Мега для примеров кода";s:12:"KEEP_HISTORY";s:1:"0";s:7:"METHODS";a:1:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:0:"";s:4:"CODE";s:16253:"/* запускается из файла megad.php с передачей всех параметров от Меги
   или из метода getData, когда сами спрашиваем состояние нужного порта.

   Обрабатывает нажатия, отпускания, а так же двойные и долгие нажатия в любой комбинации.
   Для этого не забудьте на самой Меге настроить нужные порты как P&R !!!

   Не нагружайте этот метод своим кодом если планируйте в дальнейшем обновлять этот класс. 
   Мой совет - просто передавайте данные отсюда в свои объекты. Проще будет при обновлении.

   План по отлову двойного и долгого нажатия: 
   ---
   При нажатии 
   запускаем два разных таймера
   _doublePressTimer на 1 секунду для контроля двойного нажатия и
   _longPressTimer на 3 секунды для запуска события долгого нажатия
   Если уже существует _doublePressTimer, значит произошло событие двойное нажатие.
   ---
   При отпускании
   Произошло событие отпускание1. Оно произойдет в любом случае при отпускании.
   Событие Отпустил2 произойдет только если не было долгого нажатия.
   удаляем _longPressTimer чтобы не запустилось долгое нажатие.
   ---
   Обработку ненужных событий при желании можно закоментировать. 
   События "Отпустил" нужны в том случае, если ненужно выполнять событие нажал при событии долгое нажатие.
   Или требуется начать некую обработку при нажатии, а закончить при отпускании.
   ---
   Замените все нужные say() на код установки свойств или запуска ВАШИХ методов.
   
   Играемся, тестируем, смотрим лог, пишем свои комментарии!
*/

$ot=$this->object_title;      
$pt=$params['pt'];

/* если мега передала все параметры одной строкой all=OFF/0;OFF/0;OFF/0;OFF/0;ON/1;OFF/0;OFF/0;OFF;ON;OFF;OFF;OFF;OFF;OFF;288;203
   Смотрим на строку! Сначала идут входы (со счетчиками), потом выходы, и в конце 2 АЦП порта. Универсального кода тут написать невозможно.
   Все будет зависеть от комплектации меги, но с большей долей вероятности у Вас будет модуль 7I7O (7 входов 7 выходов) + 2 АЦП порта.
   Разбиваем строку на массив, перебираем значения и устанавливаем нужные свойства. Это условие сработает !!!_ТОЛЬКО_!!! при передаче мегой 
   параметра all= и может пригодится например для первичной синхронизации статусов портов меги и статусов объектов МД. 
   ВНИМАНИЕ! в группах case нужно изменить код на свой!
*/   
if (isset($params['all'])) {
  $ps = explode(";", $params['all']);
  $i=0;
  foreach($ps as $dt) {
    $i = $i + 1;
    // Разделить статус и счетчик
    $dt = explode("/", $dt);
    // Заменить слова на цифры    
    if ($dt[0] == 'ON') { $dt[0] = 1; }
    if ($dt[0] == 'OFF') { $dt[0] = 0; }
    // Обрабатываем значения только нужных нам портов
    switch ($i) {
    case 1:
      // Сказать счетчик входа 1 и его статус
      // Не спрашивайте счетчики у выходов. Они есть только у входов (1-7 при использовании модуля 7I7O).
      say('значение входа 1 равно '.$dt[0].', счётчик '.$dt[1]);
      break;
    case 8:
      // Если есть задача периодически синхронизировать статус порта меги со статусом объекта МД.
      // Изменение статуса объекта реле таким образом не приведет к отправке команды меге на включение или выключение порта, что нам и надо.
      setGlobal('Relay1MegaD99.status',$dt[0]); 
      break;
    case 9:
      // Просто сказать статус порта 2 для примера.
      say('значение выхода 2 равно '.$dt[0]);
      break;
    }
  }
  return; 
}


/* Если мы сами спросили Мегу о чем то, запустив метод getData
   и указав номер интересующего нас порта.
   ВНИМАНИЕ! в группах case нужно изменить код на свой!
*/   
if (isset($params['iasked'])) {
  // Разделить статус и счетчик
  $dt = explode("/", $params['iasked']);
  // Заменить слова на цифры    
  if ($dt[0] == 'ON') { $dt[0] = 1; }
  if ($dt[0] == 'OFF') { $dt[0] = 0; }
  
  // Обрабатываем значения портов, которые мы могли бы сами спросить 
  switch ($pt) {
  case 14:
    // Сказать счетчик входа 1 и его статус
    // Не спрашивайте счетчики у выходов. Они есть только у входов 1-7.
    say('Я спросил значение входа 1 равно '.$dt[0].', счётчик '.$dt[1]);
    break;
  default:
    // Если порта нет в группах case, но мы все же спрашиваем его
    say('Я спросил статус порта '.$pt.', а что с ним делать пока не придумал.');
  }
  return; 
}


/* Мегадевайс сам шлет нам на сервер get сообщение о изменении статуса порта.
   Мега передаст номер порта в $pt и статус замкнули/разомкнули в $params['m'].
   ВНИМАНИЕ! в группах case нужно изменить код на свой!
*/
if (isset($pt)) {

  //Параметр 'm' с меги не передается при нажатии. А при отпускании кнопки его значение = 1
  //Переводим его в статус. 1 - замкнули (нажали); 0 - разомкнули (отпустили)
  if (!isset($params['m'])) {$ms=1;} else {$ms=0;}
  
  // ВНИМАНИЕ! в группах case нужно изменить код на свой!
  switch ($pt) { //pt это порт Меги. Для каждого порта своя группа команд case
  case 0: //Этот порт на Меге настроен как P  //Задача - просто что то запустить
    say('Ку Ку');
    break;

  case 1: // P&R //Задача - Передать объекту sensorTest статус 1 при замыкании порта Мегии, и статус 0 при размыкании
    say('Передаю тестовому датчику статус '.$ms);
    //callMethod('sensorTest.statusChanged', array('status'=>$ms));
    break;

  case 2: // P //Задача - Определить простое, двойное или тройное нажатие
    // Получаем детали события
    $dt = registeredEventDetails($ot.'_'.$pt.'_clicks');
    
    // Параметр doit будет добавлен только при последующем рекурсивном вызове для окончания обработки комбинации нажатия
    if (!isset($params['doit'])) { 
      // Добавить состояние (нажата/отпущена) и записать в детали события
      registerEvent($ot.'_'.$pt.'_clicks', $details=$dt.$ms, $expire_in=1);
      // Если таймер не существует 
      if (!timeOutExists($ot.'_'.$pt.'_press')) {
        // Нажата или отпущена
        if ($ms) {
          // Сбросить временную переменную
          registerEvent($ot.'_'.$pt.'_clicks', $details='1', $expire_in=1);
          // создать таймер с рекурсивным вызовом
          setTimeOut($ot.'_'.$pt.'_press', "cm($ot.'.incomingMessage', array('pt'=>".$pt.", 'doit'=>1));", 1);
        } else {
          // сразу рекурсивный вызов
          callMethod($ot.'.incomingMessage', array('pt'=>$pt, 'doit'=>1));
        }  
      }

    } else { // параметр doit есть. Значит это рекурсивный вызов для окончания обработки комбинации нажатия
      // Очистить временную переменную
      // registerEvent($ot.'_'.$pt.'_clicks', $details='', $expire_in=1); // тут можно просто удалять Event
      clearEvent($ot.'_'.$pt.'_clicks');
      // Посчитать количество циферок
      $dt = strlen($dt);
      say($dt.' нажатий');

      // ВЫПОЛНИТЬ нужный метод с передачей ему $dt как число нажатий
    }
    break;

  case 3: // P // Звонок + ПинКод ******************************
   /* 
  Пин код задуман длянной в 3 цифры. Это можно легко изменить при жлании. 
  При наборе цифры 3 и более звонок не включается.
  Последняя цифра пин кода может быть два, и если пин правильный, то звонок не включится
  */
    // Получаем детали события
    $dt = registeredEventDetails($ot.'_'.$pt.'_pin');

    // Параметр doit будет добавлен только при последующем рекурсивном вызове когда отработает таймер
    if (!isset($params['doit'])) { 
      // Если таймер существует 
      if (timeOutExists($ot.'_'.$pt.'_press')) {     
        // Удалить таймер
        ClearTimeOut($ot.'_'.$pt.'_press');  
        // Добавляем +1  
        $dt = $dt+1;

      } else {
        // Взять две последние цифры
        // Если есть способ проще, ПОПРАВЬТЕ!
        if (strlen($dt)>2) { $dt = substr($dt, -2); }
        // к двум последним цифрам приклеиваем 1
        $dt = $dt.'1';
      }
      // записать детали в событие
      registerEvent($ot.'_'.$pt.'_pin', $details=$dt, $expire_in=1);
      // создаем таймер  
      setTimeOut($ot.'_'.$pt.'_press', "cm(".$ot.".'.incomingMessage', array('pt'=>".$pt.", 'doit'=>1));", 1);

    } else { // параметр doit есть. Значит это рекурсивный вызов для окончания обработки комбинации нажатия
      // Удалить запомненные цифры через 10 секунд
      setTimeOut($ot.'_'.$pt.'_clear', "clearEvent('".$ot."_".$pt."_pin');", 10);
      
      // Проверяем пинкод * * * * * * * * 
      if ($dt == 342) {
        // Очистить временную переменную (чтобы пин лишний раз не был виден в X-Ray)
        //clearEvent($ot.'_'.$pt.'_pin');
        // Событие правильный пин код
        callMethod('RelayFrontDoorOpen.click');
        say('Пин код. Открываю входную дверь.');
      } else {
        // Если набранная цифра меньше 3, включаем звонок      
        if (substr($dt, -1)<3) {
          // Событие Звонок
          $filename=gg('ThisComputer.ringtoneFile');
          playSound($filename);
        }      
      }
    }
    break;

  case 4: // P&R //Задача - Получить любые комбинации
    // Получаем детали события
    $dt = registeredEventDetails($ot.'_'.$pt.'_clicks');
    
    // Параметр doit будет добавлен только при последующем рекурсивном вызове для окончания обработки комбинации нажатия
    if (!isset($params['doit'])) { 
      // Добавить состояние (нажата/отпущена) и записать в детали события
      registerEvent($ot.'_'.$pt.'_clicks', $details=$dt.$ms, $expire_in=1);
      // Если таймер не существует 
      if (!timeOutExists($ot.'_'.$pt.'_press')) {
        // Нажата или отпущена
        if ($ms) {
          // Сбросить временную переменную
          registerEvent($ot.'_'.$pt.'_clicks', $details='1', $expire_in=1);
          // создать таймер с рекурсивным вызовом
          setTimeOut($ot.'_'.$pt.'_press', "cm($ot.'.incomingMessage', array('pt'=>".$pt.", 'doit'=>1));", 1);
        } else {
          // сразу рекурсивный вызов
          callMethod($ot.'.incomingMessage', array('pt'=>$pt, 'doit'=>1));
        }  
      }

    } else { // параметр doit есть. Значит это рекурсивный вызов для окончания обработки комбинации нажатия
      // если справа 1 (то есть последнее действие нажал)
      if (substr($dt, -1)) {
        registerEvent($ot.'_'.$pt.'_clicks', $details=$dt.'-', $expire_in=1);
      } else {
        // registerEvent($ot.'_'.$pt.'_clicks', $details='', $expire_in=1); // тут можно просто удалять Event
        clearEvent($ot.'_'.$pt.'_clicks');
      }  
      /* Закомментировать или удалить этот блок switch после отладки */
      switch ($dt) {  //1-нажал 0-отпустил
      case '10':      say('нажатие');                  break;
      case '1010':    say('двойное нажатие');          break;
      case '101010':  say('тройное нажатие');          break;
      case '1':       say('удержание');                break;
      case '101':     say('удержание после двойного'); break;
      case '10101':   say('удержание после тройного'); break;
      case '1-0':     say('отпустил');                 break;
      case '101-0':   say('отпустил после двойного');  break;
      case '10101-0': say('отпустил после тройного');  break;
      default:        say('непонятно');  	       break;
      }

      // ВЫПОЛНИТЬ нужный метод с передачей ему кода комбинации $dt
    }
    break;
    
  default:
    // Если порта нет в группах case
    say('Получено сообщение от Меги с порта '.$pt);
  }
}";s:11:"CALL_PARENT";s:1:"1";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2014-12-21 17:04:43";s:15:"EXECUTED_PARAMS";s:34:"a:2:{s:2:"pt";i:3;s:4:"doit";i:1;}";}}}i:3;a:4:{s:5:"TITLE";s:6:"MegaD3";s:11:"DESCRIPTION";s:21:"Гараж Мега 1";s:12:"KEEP_HISTORY";s:1:"0";s:7:"METHODS";a:1:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:0:"";s:4:"CODE";s:3693:"$ot=$this->object_title;      
$pt=$params['pt'];

/* если мега передала все параметры одной строкой all=OFF/0;OFF/0;OFF/0;OFF/0;ON/1;OFF/0;OFF/0;OFF;ON;OFF;OFF;OFF;OFF;OFF;288;203
   Смотрим на строку! Сначала идут входы (со счетчиками), потом выходы, и в конце 2 АЦП порта. Универсального кода тут написать невозможно.
   Все будет зависеть от комплектации меги, но с большей долей вероятности у Вас будет модуль 7I7O (7 входов 7 выходов) + 2 АЦП порта.
   Разбиваем строку на массив, перебираем значения и устанавливаем нужные свойства. Это условие сработает !!!_ТОЛЬКО_!!! при передаче мегой 
   параметра all= и может пригодится для синхронизации статусов портов меги и статусов объектов МД. 
*/   
if (isset($params['all'])) {
  $ps = explode(";", $params['all']);
  $i=0;
  foreach($ps as $dt) {
    $i = $i + 1;
    // Разделить статус и счетчик
    $dt = explode("/", $dt);
    // Заменить слова на цифры    
    if ($dt[0] == 'ON') { $dt[0] = 1; }
    if ($dt[0] == 'OFF') { $dt[0] = 0; }
    // Обрабатываем значения только нужных нам портов
    switch ($i) {
    case 999:
      // Пока мне тут ничего не нужно
      break;
    }
  }
  return; 
}


/* Если мы сами спросили Мегу о чем то, запустив метод getData
   и указав номер интересующего нас порта.
*/   
if (isset($params['iasked'])) {
  // Разделить статус и счетчик
  $dt = explode("/", $params['iasked']);
  // Заменить слова на цифры    
  if ($dt[0] == 'ON') { $dt[0] = 1; }
  if ($dt[0] == 'OFF') { $dt[0] = 0; }
  
  // Обрабатываем значения портов, которые мы могли бы сами спросить 
  switch ($pt) {
  case 999:
    // Пока мне тут ничего не нужно
    break;
  default:
    // Если порта нет в группах case, но мы все же спрашиваем его
    say('Я спросил статус порта '.$pt.', а что с ним делать пока не придумал.');
  }
  return; 
}


/* Мегадевайс сам шлет нам на сервер get сообщение о изменении статуса порта.
   Мега передаст номер порта в $pt и статус замкнули/разомкнули в $params['m'].
*/
if (isset($pt)) {

  //Параметр 'm' с меги не передается при нажатии. А при отпускании кнопки его значение = 1
  //Переводим его в статус. 1 - замкнули (нажали); 0 - разомкнули (отпустили)
  if (!isset($params['m'])) {$ms=1;} else {$ms=0;}
  
  switch ($pt) { //pt это порт Меги. Для каждого порта своя группа команд case
  case 999:
    // Пока мне тут ничего не нужно
    break;
  default:
    // Если порта нет в группах case
    say('Получено сообщение от Меги с порта '.$pt);
  }
}";s:11:"CALL_PARENT";s:1:"1";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:40:00";s:15:"EXECUTED_PARAMS";s:26:"a:1:{s:4:"tget";s:2:"25";}";}}}i:4;a:4:{s:5:"TITLE";s:6:"MegaD4";s:11:"DESCRIPTION";s:21:"Гараж Мега 2";s:12:"KEEP_HISTORY";s:1:"0";s:7:"METHODS";a:1:{i:0;a:7:{s:5:"TITLE";s:15:"incomingMessage";s:11:"DESCRIPTION";s:0:"";s:4:"CODE";s:6516:"$ot=$this->object_title;      
$pt=$params['pt'];

/* если мега передала все параметры одной строкой all=OFF/0;OFF/0;OFF/0;OFF/0;ON/1;OFF/0;OFF/0;OFF;ON;OFF;OFF;OFF;OFF;OFF;288;203
   Смотрим на строку! Сначала идут входы (со счетчиками), потом выходы, и в конце 2 АЦП порта. Универсального кода тут написать невозможно.
   Все будет зависеть от комплектации меги, но с большей долей вероятности у Вас будет модуль 7I7O (7 входов 7 выходов) + 2 АЦП порта.
   Разбиваем строку на массив, перебираем значения и устанавливаем нужные свойства. Это условие сработает !!!_ТОЛЬКО_!!! при передаче мегой 
   параметра all= и может пригодится для синхронизации статусов портов меги и статусов объектов МД. 
*/   
if (isset($params['all'])) {
  $ps = explode(";", $params['all']);
  $i=0;
  foreach($ps as $dt) {
    $i = $i + 1;
    // Разделить статус и счетчик
    $dt = explode("/", $dt);
    // Заменить слова на цифры    
    if ($dt[0] == 'ON') { $dt[0] = 1; }
    if ($dt[0] == 'OFF') { $dt[0] = 0; }
    // Обрабатываем значения только нужных нам портов
    switch ($i) {
    case 999:
      // Пока мне тут ничего не нужно
      break;
    }
  }
  return; 
}


/* Если мы сами спросили Мегу о чем то, запустив метод getData
   и указав номер интересующего нас порта.
*/   
if (isset($params['iasked'])) {
  // Разделить статус и счетчик
  $dt = explode("/", $params['iasked']);
  // Заменить слова на цифры    
  if ($dt[0] == 'ON') { $dt[0] = 1; }
  if ($dt[0] == 'OFF') { $dt[0] = 0; }
  
  // Обрабатываем значения портов, которые мы могли бы сами спросить 
  switch ($pt) {
  case 999:
    // Пока мне тут ничего не нужно
    break;
  default:
    // Если порта нет в группах case, но мы все же спрашиваем его
    say('Я спросил статус порта '.$pt.', а что с ним делать пока не придумал.');
  }
  return; 
}


/* Мегадевайс сам шлет нам на сервер get сообщение о изменении статуса порта.
   Мега передаст номер порта в $pt и статус замкнули/разомкнули в $params['m'].
*/
if (isset($pt)) {

  //Параметр 'm' с меги не передается при нажатии. А при отпускании кнопки его значение = 1
  //Переводим его в статус. 1 - замкнули (нажали); 0 - разомкнули (отпустили)
  if (!isset($params['m'])) {$ms=1;} else {$ms=0;}
  
  switch ($pt) { //pt это порт Меги. Для каждого порта своя группа команд case

  case 0: // P&R 
   callMethod('MegaD4.setOutput',array('port'=>7,'value'=>$ms));
   break;
   
  case 6: // P // Звонок + ПинКод ******************************
  /* 
  Пин код задуман длянной в 3 цифры. Это можно легко изменить при жлании. 
  При наборе цифры 3 и более звонок не включается.
  Последняя цифра пин кода может быть два, и если пин правильный, то звонок не включится
  */
    // Получаем детали события
    $dt = registeredEventDetails($ot.'_'.$pt.'_pin');

    // Параметр doit будет добавлен только при последующем рекурсивном вызове когда отработает таймер
    if (!isset($params['doit'])) { 
      // Если таймер существует 
      if (timeOutExists($ot.'_'.$pt.'_press')) {     
        // Удалить таймер
        ClearTimeOut($ot.'_'.$pt.'_press');  
        // Добавляем +1  
        $dt = $dt+1;

      } else {
        // Взять две последние цифры
        // Если есть способ проще, ПОПРАВЬТЕ!
        if (strlen($dt)>2) { $dt = substr($dt, -2); }
        // к двум последним цифрам приклеиваем 1
        $dt = $dt.'1';
      }
      // записать детали в событие
      registerEvent($ot.'_'.$pt.'_pin', $details=$dt, $expire_in=1);
      // создаем таймер  
      setTimeOut($ot.'_'.$pt.'_press', "cm(".$ot.".'.incomingMessage', array('pt'=>".$pt.", 'doit'=>1));", 1);

    } else { // параметр doit есть. Значит это рекурсивный вызов для окончания обработки комбинации нажатия
      // Удалить запомненные цифры через 10 секунд
      setTimeOut($ot.'_'.$pt.'_clear', "clearEvent('".$ot."_".$pt."_pin');", 10);
      
      // Проверяем пинкод * * * * * * * * 
      if ($dt == 342) {
        // Очистить временную переменную (чтобы пин лишний раз не был виден в X-Ray)
        //clearEvent($ot.'_'.$pt.'_pin');
        // Событие правильный пин код
        callMethod('RelayFrontDoorOpen.click');
        say('Пин код. Открываю входную дверь.');
      } else {
        // Если набранная цифра меньше 3, включаем звонок      
        if (substr($dt, -1)<3) {
          // Событие Звонок
          $filename=gg('ThisComputer.ringtoneFile');
          playSound($filename);
        }      
      }
    }
    break;

  default:
    // Если порта нет в группах case
    say('Получено сообщение от Меги с порта '.$pt);
  }
}";s:11:"CALL_PARENT";s:1:"1";s:9:"SCRIPT_ID";s:1:"0";s:8:"EXECUTED";s:19:"2015-02-04 19:40:00";s:15:"EXECUTED_PARAMS";s:26:"a:1:{s:4:"tget";s:2:"16";}";}}}}}}