Предупреждение! Я опытный пользователь персонального компьютера и программы МС Ворд и Звукозапись. Однако ряд терминов и определений в этой статье могу употребить не верно. Сообщите о моих ошибках, если они найдутся.
Есть две системы. Одна разрабатывается мной и на ней отображены лица сотрудников ИПК. Страница первой системы открыта на большой сенсорной панеле на входе. По тычку в лицо соответствующий человек записывается в базу, выделяется цветом вовремя пришедшего или опаздавшего и т.д. Вторая — это СКУД от RusGuard.
Предусмотрена система синхронизации моей системы со скудом. Но работает она так: каждые N секунд уходит аякс на сервер, сервер получает данные от MS SQL на скуде за текущее число, парсит тех, кто есть в скуде, но не отмечен на странице моей системы (открытой на сенсорной панельке) и делает по ним джаваскриптовый клик.
Мне не нравится это решение.
Метод проб и ошибок привел меня к следующему решению. На сервере скуда в Конфигурации_системы-Реакции добавляем расписание от 00:00 до 23:59, например. Создаем событие, указываем типы и источники событий, во вкладке Сотрудников не забываем указать сотрудников (по умолчанию никто не стоит). Привязываем расписание к событию. Создаем действие Запуска программы. В пути прописываем путь до файла bat (русгуард только их в данном случае принимает). В корневой каталог дублирую каталог файла.
В батнике курл или вгет делает гет запрос к моей системе с указанием ключа в мд5.
У себя в шаблоне обозначаю EventSource
const eventSource = new EventSource("/sse");
eventSource.onmessage = function (event) {
console.log(event['data']);
if (event['data'] === 'update') {
check_cart();
}
};
eventSource.onopen = function (e) {
console.log("Открыто соединение");
};
eventSource.onerror = function (e) {
console.log(e);
};
Пишем роуты для нашего события и потока.
Route::get('/sse', 'PeopleController@sse');
Route::get('/upd/{key}', 'PeopleController@scud_upd_event');
И самое кайфоное. Создаем метод для события, который запоминает в кеш необходимость обновить данные на открытой странице моей системы:
public function scud_upd_event($key) {
if(md5(self::$key) === $key){
Cache::forget('update_event_cache');
Cache::put('update_event_cache', 'true', 3500);
}
}
И говорим, что сервак транслирует поток, реализуем в нем цикл с какой-то например задержкой, который работает до появления данных в "update_event_cache" кеша. После чего отправляем клиенту информацию о необходимости совершения аякса, который запустит клики по лицам, пикнувшимся в скуде, но не тыкнувшимся на панеле:
public function sse() {
return response()->stream(function () {
while (true) {
usleep(1000);
if (Cache::has('update_event_cache')) {
Cache::forget('update_event_cache');
echo "data: " . 'update' . "\n\n";
ob_flush();
flush();
}
}
}, 200, [
'Cache-Control' => 'no-cache',
'Content-Type' => 'text/event-stream',
]);
}
Технология server sent events помогла нам установить постоянное соединение с сервера с клиентом, в котором клиену в реальном времени можно дослать информацию по событию, произошедшему на сервере.
Ключевые фрагменты на гитхаб