О переделке передачи сообщений
Итак - не нравится нам работа терминалов? Будем исправлять ? Ну да....
Принцип работы будет прост до безобразия - система генерирует событие, на основе этого события генератор речи (в частности Виндовс ТТС) генерирует полное сообщение на основе которого мы уже имеем и длительность сообщения и всё необходимое для сообщения, потом это сообщение запихивается в очередь сообщений, которая в свою очередь отправляет все сообщения на терминалы которые существуют в системе.... Ну где то так...
Итак возьмем самый простой вариант берем МАИН терминал - поскольку его описание отсутствует то создадим его main.addon.php
Вариант 1 Терминал МАИН (который отсутствует в системе)
<?php
/*
Addon Main terminal for app_player
*/
class main extends app_player_addon {
// Private properties
private $address;
// Constructor
function __construct($terminal) {
$this->title = 'Main terminal for Majordomo';
$this->description = 'Умная колонка от Google.';
$this->terminal = $terminal;
$this->reset_properties();
}
// Play
function play($input) {
$this->reset_properties();
if(strlen($input)) {
if(file_exists($input)) {
if (IsWindowsOS()){
safe_exec(DOC_ROOT . '/rc/madplay.exe ' . $input);
} else {
safe_exec('mplayer ' . $input . " >/dev/null 2>&1");
}
$this->success = TRUE;
$this->message = 'OK';
} else {
$this->success = FALSE;
$this->message = 'Command execution error!';
}
} else {
$this->success = FALSE;
$this->message = 'Input is missing!';
}
return $this->success;
}
// Say
/**
* Summary of play message
* @param mixed $param['filename'] File name
* @param mixed $param['level'] level of message
* @param mixed $param['message'] text of message
* @param mixed $param['event'] type of event
* @return void
*/
function say($param) {
$this->reset_properties();
$out = explode(',', $param);
$filename = $out[0];
$level = $out[1];
$message = $out[2];
$event = $out[3];
if(strlen($message)) {
if(file_exists($filename)) {
if (IsWindowsOS()){
safe_exec(DOC_ROOT . '/rc/madplay.exe ' . $filename);
} else {
safe_exec('mplayer ' . $filename . " >/dev/null 2>&1");
}
$this->success = TRUE;
$this->message = 'OK';
} else {
$this->success = FALSE;
$this->message = 'Command execution error!';
}
} else {
$this->success = FALSE;
$this->message = 'Input is missing!';
}
return $this->success;
}
}
?>
ну и т.д. смысл я думаю понятен....
// Say
public function say($param) {
/**
* Summary of play message
* @param mixed $param['filename'] File name
* @param mixed $param['level'] level of message
* @param mixed $param['message'] text of message
* @param mixed $param['event'] type of event
* @return void
*/
return $this->not_supported();
}
создадим функцию
/**
* Summary of send message to terminal
* @param mixed $param['filename'] File name
* @param mixed $param['level'] level of message
* @param mixed $param['message'] text of message
* @param mixed $param['event'] type of event
* @return void
*/
function send_message_to_terminal ($host = 'localhost', $filename, $level, $message, $event)
{
if (!$terminal = getTerminalsByName($host, 1)[0]) {
$terminal = getTerminalsByHost($host, 1)[0];
}
// надо фнукцию новую создать
//if (!$terminal['ID']) {
// $terminal = getTerminalsCanPlay(1)[0];
//}
if (!$terminal['ID']) {
$terminal = getMainTerminal();
}
if (!$terminal['ID']) {
$terminal = getAllTerminals(1)[0];
}
if (!$terminal['ID']) {
return 0;
}
$url = BASE_URL . ROOTHTML . 'ajax/app_player.html?';
$url .= "&command=say";
$url .= "&terminal_id=" . $terminal['ID'];
$url .= "¶m=" . urlencode($filename.','.$level.','.$message.','.$event);
//DebMes($url,'playmedia');
getURLBackground($url);
return 1;
}
Выкидываем функцию
function terminalSay($terminal_rec, $message, $level)
function terminalSayByCache($terminal_rec, $cached_filename, $level)
и исправляем 2 функции на вот так
/**
* terminals subscription events
*
* @access public
*/
function processSubscription($event, $details = '')
{
$this->getConfig();
DebMes("Processing $event: ".json_encode($details),'terminals');
// если происходит событие SAY_CACHED_READY то запускаемся
if ($event == 'SAY_CACHED_READY') {
// $details['level'] $details['message'] $details['destination'] $details['filename'] $details['event'] $event
// нужна проверка на уровень сообщения если мало то возвращаемся
// здесь еще надо пропинговать и проверить на онлайность
// нужна проверка наличие файла
$filename = $details['filename'];
if (!file_exists($filename)) return false;
if ($details['event']) {
$details['event'] = $details['event'];
} else {
$details['event'] = 'SAY';
}
if ($details['event'] == 'SAY') {
$terminals = SQLSelect("SELECT * FROM terminals WHERE CANTTS=1");
foreach ($terminals as $terminal_rec) {
$this->terminalSayByCacheQueue($terminal_rec,$details);
}
} elseif ($details['event'] == 'SAYTO' || $details['event'] == 'ASK'|| $details['event'] == 'SAYREPLY') {
$terminal_rec = array();
if ($details['destination']) {
if (!$terminal_rec = getTerminalsByName($details['destination'], 1)[0]) {
$terminal_rec = getTerminalsByHost($details['destination'], 1)[0];
}
}
if (!$terminal_rec['ID'] OR !$terminal_rec['CANTTS'] OR !$terminal_rec['PLAYER_TYPE']) {
return false;
}
if ($source_event == 'ASK') {
$details['level']=9999;
}
$this->terminalSayByCacheQueue($terminal_rec,$details);
}
} elseif ($event == 'HOURLY') {
// check terminals
$terminals=SQLSelect("SELECT * FROM terminals WHERE IS_ONLINE=0 AND HOST!=''");
foreach($terminals as $terminal) {
if (ping($terminal['HOST'])) {
$terminal['LATEST_ACTIVITY']=date('Y-m-d H:i:s');
$terminal['IS_ONLINE']=1;
SQLUpdate('terminals',$terminal);
}
}
SQLExec('UPDATE terminals SET IS_ONLINE=0 WHERE LATEST_ACTIVITY < (NOW() - INTERVAL 90 MINUTE)'); //
}
}
/**
* очередь сообщений
*
* @access public
*/
function terminalSayByCacheQueue($target, $details) {
// poluchaem adress cashed files dlya zapuska ego na vosproizvedeniye
if (preg_match('/\/cms\/cached.+/',$details['filename'],$m)) {
$server_ip = getLocalIp();
if (!$server_ip) {
//DebMes("Server IP not found", 'terminals');
return false;
} else {
$cached_filename='http://'.$server_ip.$m[0];
}
} else {
//DebMes("Unknown file path format: " . $cached_filename, 'terminals');
return false;
}
// berem vse soobsheniya iz shoots dlya poiska soobsheniya s takoy frazoy
$messages = SQLSelect("SELECT * FROM shouts ORDER BY ID DESC LIMIT 0 , 100");
foreach ( $messages as $message ) {
if ($details['message']==$message['MESSAGE']) {
$number_message = $message['ID'];
break;
}
}
// получаем данные оплеере для восстановления проигрываемого контента
$chek_restore = SQLSelectOne("SELECT * FROM jobs WHERE TITLE LIKE'".'allsay-target-'.$target['TITLE'].'-number-'."99999999998'");
if (!$chek_restore ) {
$played = getPlayerStatus($target['NAME']);
if (($played['state']=='playing') and (stristr($played['file'], 'cms\cached\voice') === FALSE)) {
addScheduledJob('allsay-target-'.$target['TITLE'].'-number-99999999998', "playMedia('".$played['file']."', '".$target['TITLE']."',1);", time()+100, 4);
addScheduledJob('allsay-target-'.$target['TITLE'].'-number-99999999999', "seekPlayerPosition('".$target['TITLE']."',".$played['time'].");", time()+110, 4);
}
}
// dobavlyaem soobshenie v konec potom otsortituem
$time_shift = 2 + getMediaDurationSeconds($cached_filename); // необходимая задержка для перезапуска проигрівателя на факте 2 секундЫ
//DebMes("Add new message".$last_mesage,'terminals');
addScheduledJob('allsay-target-'.$target['TITLE'].'-number-'.$number_message, "send_message_to_terminal('".$target['TITLE']."','".$details['filename']."','".$details['level']."','".$details['message']."','".$details['event']."');", time()+1, $time_shift);
// vibiraem vse soobsheniya dla terminala s sortirovkoy po nazvaniyu
$all_messages = SQLSelect("SELECT * FROM jobs WHERE TITLE LIKE'".'allsay-target-'.$target['TITLE'].'-number-'."%' ORDER BY `TITLE` ASC");
$first_fields = reset($all_messages);
$runtime = (strtotime($first_fields['RUNTIME']));
foreach ($all_messages as $message) {
$expire = (strtotime($message['EXPIRE']))-(strtotime($message['RUNTIME']));
$rec['ID'] = $message['ID'];
$rec['TITLE'] = $message['TITLE'];
$rec['COMMANDS'] = $message['COMMANDS'];
$rec['RUNTIME'] = date('Y-m-d H:i:s', $runtime);
$rec['EXPIRE'] = date('Y-m-d H:i:s', $runtime+$expire);
// proverka i udaleniye odinakovih soobsheniy
if ($prev_message['TITLE'] == $message['TITLE']) {
SQLExec("DELETE FROM jobs WHERE ID='".$rec['ID']."'");
} else {
SQLUpdate('jobs', $rec);
}
$runtime = $runtime + $expire;
$prev_message = $message;
}
}
выкинуть галочку - МажордроидАПИ
И соответственно надо укоротить генераторы речи до простой функции на примере виндовс ТТС
/**
* Summary of processSubscription
* @param mixed $event Event
* @param mixed $details Event detail
*/
function processSubscription($event, &$details) {
$this->getConfig();
//DebMes('processing '.$event.': '.json_encode($details),'windows_tts');
$level = (int)$details['level'];
$message = $details['message'];
$destination = $details['destination'];
$mmd5 = md5($message);
$cached_filename = ROOT.'cms/cached/voice/sapi_'.$mmd5.'.mp3';
$on_complete="if (file_exists('$cached_filename')) {
processSubscriptionsSafe('SAY_CACHED_READY', array(
'level' => $level,
'tts_engine' => 'windows_tts',
'filename' => '$cached_filename',
'destination' => '$destination',
'event' => '$event',
'message' => '$message',
));
}";
if ($event == 'SAY' || $event == 'SAYTO' || $event == 'ASK' || $event == 'SAYREPLY') {
if ($level >= (int)getGlobal('minMsgLevel') && IsWindowsOS()) {
//safe_exec('cscript ' . DOC_ROOT . '/rc/sapi.js ' . $message, 1, $level);
if (file_exists($cached_filename)) {
//DebMes('playing '.$cached_filename,'windows_tts');
eval ($on_complete);
//playSound($cached_filename, 1, $level);
} else {
$cmd = 'cscript ' . DOC_ROOT . '/rc/sapi.js /md5:' .$mmd5.' ' . $message;
//DebMes("Running: ".$cmd,'windows_tts');
safe_exec($cmd, 1, $level,$on_complete);
}
$details['ignoreVoice'] = 1;
}
}
}