Передача Журнала и форматирование для 1С
«Посещаемость» поддерживает передачу журнала по HTTP-запросу в формате CSV.
Подробное описание строки содержится в руководстве по эксплуатации «Посещаемость».
Принятый журнал счетчиков возможно импортировать в 1С и т.д.
Рассмотрим пример PHP-скрипта для запроса журналов от нескольких счетчиков, фильтрации событий и записи в файлы для импорта в 1С.
В параметрах запуска скрипта передаются IP-адреса, сетевые имена, порт подключения счетчиков. К примеру, php.exe guestget.php 192.168.0.70 guest.advrouter.asuscomm.com:8009
В начале скрипта константами задаются основные настройки: расположения записываемых файлов, учетная запись для доступа к счетчикам, фильтр событий, шаблон изменения формата строки для записи в CSV-файл.
В скрипте применяется ООП для описания объекта взаимодействия с счетчиком. Далее создается количество объектов в соответствии с количеством переданных IP и сетевых имен.
Из счетчика запрашивается серийный номер, затем журнал работы. Для ускорения работы с несколькими счетчиками HTTP-запросы выполняются одновременно. Обработка журнала выполняется поочереди в момент завершения приема данных.
Принятый журнал в формате CSV в кодировке CP1251 разбивается на строки. Затем применяется фильтр событий, изменение формата полей строки и записывается в файл. Имя файла содержит идентификатор счетчика.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | <?php /***************************************************** Guestget Module: Guest Get MultiCURL TIGRA electronic Inc. Copyright, 02.2019 *****************************************************/ # Скрипт для запроса от счетчиков журнала, преобразования к формату 1С и записи в файл. # В параметрах запуска указываются IP адреса или имена счетчиков в сети # Скрипт использует многопоточный доступ к счетчикам, требуется PHP версия не ниже 5.3, модуль CURL # Строка запуска: php.exe guestget.php guestance guestance1 guestance2 192.168.0.70 define( 'GUESTGET_DIRECTORY', 'reports\\' ); # директория для обработанных файлов define( 'GUESTGET_LOG', GUESTGET_DIRECTORY.'\\guestget.log' ); # расположение журнала работы программы define( 'GUESTGET_URL_JOURNAL', '/journal.cgi?t=a&f=c&d=a'); # запрос журнала #define( 'GUEST_URL_CARDS', '/cards.cgi?f=c'); # запрос карт define( 'GUESTGET_URL_ID', '/id.xml'); # запрос id define( 'GUESTGET_ACCESS', 'guest:guest' ); # учетная запись счетчика #******************* Основные события счетчика ************** define( 'EVENT_ON', 1 ); define( 'EVENT_OFF', 2 ); define( 'EVENT_TIME', 3 ); define( 'EVENT_PASSWORD', 4 ); define( 'EVENT_LOGIN', 5 ); define( 'EVENT_CARD_CHANGE', 6 ); define( 'EVENT_UPDATE_LOAD', 7 ); define( 'EVENT_UPDATE_COMPLETE', 8 ); define( 'EVENT_UPDATE_FAIL', 9 ); define( 'EVENT_INNOW', 10 ); define( 'EVENT_INOUT', 11 ); define( 'EVENT_EMITTER_SHOW', 12 ); define( 'EVENT_EMITTER_HIDE', 13 ); define( 'EVENT_EMAIL', 23 ); define( 'EVENT_CARD', 25 ); #********************* Фильтр событий ******************* define( 'GUESTGET_FILTER', [EVENT_INNOW, EVENT_INOUT] ); #********************* Первая строка в файле ******************* define( 'GUESTGET_FILE_START', "52-3-3\r\n" ); #********************** Изменение строки в журнале для импорта в 1С ********** define( 'GUESTGET_PATTERN', '/(\d+)\/(\d+)\/(\d+) ([\d: ]+),(\d+),(\d*),(\d*).*/' ); define( 'GUESTGET_REPLACE', "$1.$2.$3 $4:00 $6 $7\r\n" ); ob_implicit_flush(); date_default_timezone_set('Europe/Moscow'); class Guestget { public $id, $idx, $ip, $mh, $chs, $callback; function __construct( $idx, $ip, $mh, &$chs ) { $this->idx = $idx; $this->ip = $ip; $this->mh = $mh; $this->chs = &$chs; $this->request( GUESTGET_URL_ID ); # запрос id счетчика $this->callback = "process_id"; # функция обработчика id } function process_id() { if( !preg_match( "/<serial>([0-9]+)<\/serial>/", $this->get(), $m ) ) { // взять id счетчика $this->slog( "id error\n" ); return; } $this->id = $m[1]; $this->request( GUESTGET_URL_JOURNAL ); # запрос журнала $this->callback = "process_journal"; # функция обработчика журнала } function process_journal() { $result = explode( "\n", $this->get() );# разделение строк в журнале if( $result == NULL ) return; $csv = GUESTGET_FILE_START; # первая строка в файле $filter = GUESTGET_FILTER; foreach( $result as $line ) { # разделение строк и цикл обработки для каждой строки if( strlen($line) < 10 ) # для удаления некорректных строк continue; if( !in_array( explode(',', $line)[1], $filter ) ) # фильтр событий continue; $csv .= preg_replace(GUESTGET_PATTERN, GUESTGET_REPLACE, $line); # замена формата строки } file_put_contents( GUESTGET_DIRECTORY.$this->id."_journal.csv", $csv ); # запись результата в файл $this->slog("work complete"); } function request( $url ) { # создание запроса файла $this->slog( "request $url" ); $ch = curl_init( "http://".$this->ip.$url ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); # таймаут соединения curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_USERPWD, GUESTGET_ACCESS); # логин и пароль curl_multi_add_handle( $this->mh, $ch ); $this->chs[$this->idx] = $this->ch = $ch; # записали дескриптор нового запроса } function get() { # чтение данных и закрытие запроса $result = curl_multi_getcontent( $this->ch ); $info = curl_getinfo($this->ch); curl_multi_remove_handle( $this->mh, $this->ch ); curl_close($this->ch); if( !$result || $info['http_code'] != 200 ) { $this->slog( "HTTP error ".$info['http_code'] ); return NULL; } $this->slog("request complete"); return $result; } function process() { # вызов функции-обработчика call_user_func( array( $this, $this->callback) ); } function slog( $msg ) { # вывод сообщение на экран и в файл $str = date("r")." <".$this->ip."> $msg\r\n"; echo $str; file_put_contents(GUESTGET_LOG, $str, FILE_APPEND); } } $mh = curl_multi_init(); # инициализация мультизапросов $threads = []; # массив счетчиков $chs = []; # дескрипторы запросов foreach( array_slice($argv, 1) as $ip ) # просмотреть все IP или имена array_push( $threads, new Guestget(count($threads), $ip, $mh, $chs) ); # создать поток работы со счетчиком $active = $prev_active = count($chs); while( 1 ) { curl_multi_exec( $mh, $active ); # количество текущих запросов if( $active != $prev_active ) { # если изменилось количество активных запросов $prev_active = $active; do { $infos = curl_multi_info_read( $mh, $queue ); # выбрать завершившийся запрос if( is_array($infos) && ($ch = $infos['handle']) ) $threads[array_search( $ch, $chs )]->process( $ch );# обработать полученные данные } while( $queue ); } else if( !$active ) # если запросы отсутствуют break; usleep( 1000 ); } curl_multi_close( $mh ); ?> |