Прослушивание TCP/IP

Подключение исполнительных устройств, датчиков, контроллеров.

Модератор: immortal

Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Пн ноя 26, 2018 9:54 pm

xor писал(а):
Пн ноя 26, 2018 9:40 pm
А этот прибор в каком виде отсылает по сетке? Можно указать адрес-то? Я к тому, что если передается что-то типа адрес_сервера/php_script.php&param=a&value=1111&param=b&value=222 это легко обрабатывать скриптом
Вот именно передаёт номер контакта и его состояние: cn1_true (т.е. контакт первый замкнут) или cn1_false (разомкнут)
Соединение он поддерживает по IP на порту 10000. Как-то так.
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Пн ноя 26, 2018 9:57 pm

skysilver писал(а):
Пн ноя 26, 2018 9:41 pm
Lerych писал(а):
Пн ноя 26, 2018 9:38 pm
Вот результат замены
Parse error: syntax error, unexpected '$data' (T_VARIABLE), expecting ';' or '{' in C:\_majordomo\htdocs\modules\TCP_socket\TCP_socket.class.php on line 249
Скобочку потерял )
dbInstall($data = '') {
Вот так сработало:

Код: Выделить всё

 function dbInstall($data='') {
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Пн ноя 26, 2018 9:59 pm

Господа, завтра проверю на боевой, что с этим модулей получилось и отпишусь. Всем спасибо. Пока
skysilver
Сообщения: 3006
Зарегистрирован: Чт авг 21, 2014 8:28 am
Откуда: Киров, Россия
Благодарил (а): 400 раз
Поблагодарили: 1753 раза
Контактная информация:

Re: Прослушивание TCP/IP

Сообщение skysilver » Пн ноя 26, 2018 10:07 pm

Lerych писал(а):
Пн ноя 26, 2018 9:45 pm
Железка в сети под номером 192.168.1.111:10000, комп под номером 192.168.1.1
Почему работать не будет?
Вот и нужно вписывать этот сокет 192.168.1.111:10000, а не localhost:80. :)
За это сообщение автора skysilver поблагодарил:
Lerych (Пн ноя 26, 2018 10:07 pm)
Рейтинг: 1.16%
MajorDoMo (GitHub) на Cubietruck. ОС Debian 7 (wheezy) (kernel 3.4.105) с переносом на HDD.
Мой CONNECT | Блоги | Telegram
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Пн ноя 26, 2018 10:08 pm

serghei писал(а):
Пн ноя 26, 2018 9:23 pm
А случайно UDP пакеты этот контроллер не передает ? А то ESP32 умеет их ловить из сети. Так я перехватываю пакеты от сети MySensors.
Кстати, у него есть ещё порты RS232, RS232/RS485, но тогда нужен преобразователь. Хотя написано, что они только для конфигурации и обновления MiniOs
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Вт ноя 27, 2018 12:46 pm

Мужики!
Всё получилось.
Модуль работает как надо, данные идут. Единственное см.выше в постах правки в файле класса TCP_socket.class.php строку 244 заменить на

Код: Выделить всё

 function dbInstall($data='') {
Кстати, для отладки удобно использовать эмулятор под Windows (https://www.hw-group.com/software/hercu ... up-utility)
Ещё раз всем спасибо!
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Ср ноя 28, 2018 7:32 pm

Приветствую!
Опять нужна помощь по данному модулю. Сейчас данные с ПЛК я могу получить с помощью этого модуля в виде 0 или 1.
Т.е. мне надо сделать 128*2=256 записей в настройках модуля, чтобы получать состояние одного из 128 контактов.
Что-то типа:
cn0true, для состояния контакта №1 "замкнут" и привязки в свойства объекта "status" - единицы, отображения на сцене ВКЛ
и ещё запись cn0false, для для состояния контакта №1 "разомкнут" и привязки в свойства объекта "status" - ноль, отображения на сцене ВЫКЛ
008.png
008.png (44.97 КБ) 3621 просмотр
Но по моему, это не по фэншую. ПЛК (железка) может выдавать мне строку в виде состояния всех контактов, т.е. 0101010.....000
Вопрос: чего переделать в классе "cycle_TCP_socket.php"
СпойлерПоказать
<?php
chdir(dirname(__FILE__) . '/../');
include_once("./config.php");
include_once("./lib/loader.php");
include_once("./lib/threads.php");
set_time_limit(0);
// connecting to database
$db = new mysql(DB_HOST, '', DB_USER, DB_PASSWORD, DB_NAME);
include_once("./load_settings.php");
include_once(DIR_MODULES . "control_modules/control_modules.class.php");
$ctl = new control_modules();
include_once(DIR_MODULES . 'TCP_socket/TCP_socket.class.php');
$TCP_socket_module = new TCP_socket();
$TCP_socket_module->getConfig();
$tmp = SQLSelectOne("SELECT ID FROM Sockets LIMIT 1");
if (!$tmp['ID'])
exit; // no devices added -- no need to run this cycle
echo date("H:i:s") . " running " . basename(__FILE__) . PHP_EOL;
$latest_check = 0;
$ping_cnt = 0;
$execute = true;
$checkEvery = 1; // poll every 1 seconds
$ping_esc = 4; // escape polling (for ping only)


while (1)
{
setGlobal((str_replace('.php', '', basename(__FILE__))) . 'Run', time(), 1);
if ((time()-$latest_check)>=$checkEvery)
{
$latest_check=time();
echo "\r\n".date('Y-m-d H:i:s').' Polling devices...\r\n';
$TCP_socket_module->processCycle();

// Получаем все сокеты из БД
$sockets = SQLSelect("SELECT * FROM Sockets");
$total = count($sockets);
for($i = 0; $i < $total; $i++)
{
$sock = $sockets[$i];
$IP = $sock['IP'];
$port = $sock['PORT'];
// Пинг IP
$online = ping(processTitle($sock['IP']));
if($online)
{
if($execute)
{
// Пинг сокета
$out = "ping";
$res = socket_sendto($socket[$i], $out, strlen($out), 0, $IP, $port);
if(!($res != 0))
{
$sock['STATUS'] = '0';
// Создаём TCP/IP сокет
$socket[$i] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!($socket[$i] === false))
{
socket_set_option($socket[$i], SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0,"usec"=>10000)); // Ждать новые данные 10ms
// Подключаем TCP/IP сокет
$result = socket_connect($socket[$i], $IP, $port);
if (!($result === false))
{
$sock['STATUS'] = '1';
}
// else
// {
// echo "\r\nFail socket_connect(): reason: ($result) " . socket_strerror(socket_last_error($socket[$i])) . "\r\n";
// }
}
// else
// {
// echo "\r\nFail socket_create(): reason: " . socket_strerror(socket_last_error()) . "\r\n";
// }
}
else
{
$sock['STATUS'] = '1';
}
}
// Чтение сокета
$read_buf = '';
$res = socket_recv($socket[$i], $read_buf, 255, 0);
// if(!($res != 0))
// {
// echo "\r\nFail to read socket at addres ".$IP."and port ".$port."\r\n";
// }
//echo "Bytes receive:".$res."\r\n";
// Получаем все каналы из БД
$channels = SQLSelect("SELECT * FROM Channels WHERE DEVICE_ID=($i + 1)");
$cnt = count($channels);
for($j = 0; $j < $cnt; $j++)
{
$chan = $channels[$j];
if($chan['LINKED_OBJECT']!='' && $chan['LINKED_PROPERTY']!='')
{
if(preg_match('\'^GET\\([0-9]{1,}\\)$\'', $chan['VALUE']))
{
preg_match('\'[0-9]{1,}\'', $chan['VALUE'], $val);
$pos = strpos($read_buf, $chan['TITLE']);
if(!($pos === false))
{
setGlobal($chan['LINKED_OBJECT'].'.'.$chan['LINKED_PROPERTY'], $val[0]);
}
}
if(preg_match('\'^SET\\([0-9]{1,}\\)$\'', $chan['VALUE']))
{
preg_match('\'[0-9]{1,}\'', $chan['VALUE'], $val);
$status_new = getGlobal($chan['LINKED_OBJECT'].'.'.$chan['LINKED_PROPERTY']);
$status_old = $chan['STATUS'];
if($status_new === $val[0])
{
if($status_new != $status_old)
{
$write_buf = $chan['TITLE'];
// Запись сокета
$res = socket_sendto($socket[$i], $write_buf, strlen($write_buf), 0, $IP, $port);
// if(!($res != 0))
// {
// echo "\r\nFail to write socket at addres ".$IP."and port ".$port."\r\n";
// }
// echo "Bytes send:".$res."\r\n";
usleep(10000); // Небольшая (10ms) задержка после записи сокета
}
}
$chan['STATUS'] = $status_new;
}
}
SQLUpdate('Channels', $chan);
}
}
else
{
$sock['STATUS'] = '0';
}
SQLUpdate('Sockets', $sock);
}
$ping_cnt++;
if($ping_cnt > $ping_esc)
{
$ping_cnt = 0;
$execute = true;
}
else
{
$execute = false;
}
}
if (file_exists('./reboot') || IsSet($_GET['onetime']))
{
$db->Disconnect();
exit;
}
//sleep(1);
}
DebMes("Unexpected close of cycle: " . basename(__FILE__));
чтобы получить всю строку из сокета.
Я потом её буду разбирать на "составляющие" и записывать в соответствующие свойства объектов статусы.
Я понимаю, что где-то с 97 по 105 строку, это надо править, но что-то не выходит каменный цветок. Я конечно посижу во всемирной паутине пару часов и найду, но может для Вас - гуру PHP, это займёт совсем немного времени.
Спасибо!
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Ср ноя 28, 2018 8:15 pm

Сдаётся мне в этом классе, функцию preg_match не уместно использовать для моих целей, т.к. она возвращает только число вхождений (0 или 1). Так?
Аватара пользователя
Lerych
Сообщения: 191
Зарегистрирован: Чт дек 14, 2017 8:46 pm
Откуда: Московская область, Серпухов
Благодарил (а): 79 раз
Поблагодарили: 24 раза

Re: Прослушивание TCP/IP

Сообщение Lerych » Вс дек 02, 2018 11:01 pm

Мужики помогите с кодом!
Имеем такой код:

Код: Выделить всё

// Получаем все каналы из БД
                $channels = SQLSelect("SELECT * FROM Channels WHERE DEVICE_ID=($i + 1)");
                $cnt = count($channels);
                for($j = 0; $j < $cnt; $j++) 
                {
                    $chan = $channels[$j];
                    if($chan['LINKED_OBJECT']!='' && $chan['LINKED_PROPERTY']!='') 
                    {
                        if(preg_match('\'^GET\\([0-9]{1,}\\)$\'', $chan['VALUE']))
                        {
                            preg_match('\'[0-9]{1,}\'', $chan['VALUE'], $val);
                            $pos = strpos($read_buf, $chan['TITLE']);
                            if(!($pos === false))
                            {                               
				$code = substr($read_buf,5,20);
				setGlobal($chan['LINKED_OBJECT'].'.'.$chan['LINKED_PROPERTY'], $code);
                            }
                        }
т.е. записываем в свойства объекта вырезанную часть строки из буфера. В коде выше вырезаем из буфера с 5-ой позиции, 20-ть символов. Но эти переменные могут быть различными.
Надо вместо 5 подставлять $chan['TITLE'], а вместо 20: $read_buf-$chan['TITLE'].
Помогите с синтаксисом этого действия.
fandaymon
Сообщения: 1553
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Прослушивание TCP/IP

Сообщение fandaymon » Вс дек 02, 2018 11:27 pm

Lerych писал(а):
Вс дек 02, 2018 11:01 pm
Мужики помогите с кодом!
Имеем такой код:

Код: Выделить всё

// Получаем все каналы из БД
                $channels = SQLSelect("SELECT * FROM Channels WHERE DEVICE_ID=($i + 1)");
                $cnt = count($channels);
                for($j = 0; $j < $cnt; $j++) 
                {
                    $chan = $channels[$j];
                    if($chan['LINKED_OBJECT']!='' && $chan['LINKED_PROPERTY']!='') 
                    {
                        if(preg_match('\'^GET\\([0-9]{1,}\\)$\'', $chan['VALUE']))
                        {
                            preg_match('\'[0-9]{1,}\'', $chan['VALUE'], $val);
                            $pos = strpos($read_buf, $chan['TITLE']);
                            if(!($pos === false))
                            {                               
				$code = substr($read_buf,5,20);
				setGlobal($chan['LINKED_OBJECT'].'.'.$chan['LINKED_PROPERTY'], $code);
                            }
                        }
т.е. записываем в свойства объекта вырезанную часть строки из буфера. В коде выше вырезаем из буфера с 5-ой позиции, 20-ть символов. Но эти переменные могут быть различными.
Надо вместо 5 подставлять $chan['TITLE'], а вместо 20: $read_buf-$chan['TITLE'].
Помогите с синтаксисом этого действия.
Я правильно понимаю, что железка присылает cn0_true или cn199_false в зависимости от того, какой контакт замкнут/разомкнут?
Если да, то зачем всё это городить, когда можно просто разбить пришедшее командой $plc=explode('_',$read_buff)

И без всяких таблиц просто занести свойство нужному объекту

Код: Выделить всё

$obj_name=$plc[0]; // При условии что объекты будут называться cn0, если нужно как-то по другому, то просто добавить нужное
if ($plc[1]=='true')  {
 sg( $obj_name. '.status',1);
} else {
 sg($obj_name . '.status',0);
}
Ну конечно перед этим проверить есть ли такой объект, а если нет, то создать

Код: Выделить всё

$obj=getObject($obj_name);
if ($obj==0) {
 addClassObject('PLC', $obj_name); //Вместо PLC тут указать свой класс объектов
}
 
За это сообщение автора fandaymon поблагодарил:
Lerych (Вс дек 02, 2018 11:49 pm)
Рейтинг: 1.16%
Ответить