MegaD
-
Если остановимся на этом варианте, можно отсекать полный путь при сохранении.
Я прочитал ваши убедительные доводы в пользу такого решения на форуме ab-log. Полностью с ними согласен, хотя есть некоторое неудобство…думаю привыкнем. Однако у меня возникло 2 проблемы:
1. При разрешении экрана 1280х720 название плагина в первом столбце меню Redirect не отображается. На работе при 1920х1280 - все нормально.
2. Не изменяется состояние устройства в вебе, привязанного к каналу 9 MG3:26.01 22:46:36.539 192.168.12.30 => localhost:10030 HTTP GET /mod_megad.php?pt=0&m=1&cnt=16&mdid= 26.01 22:46:36.542 MG4?0=0& 26.01 22:46:36.543 Redirect to MG3 26.01 22:46:36.543 localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=9:1 26.01 22:46:36.544 MG3?9=1& 26.01 22:46:36.544 192.168.12.30 <= localhost:10030 26.01 22:46:36.553 localhost <= 192.168.12.30:80 response: statusCode=200 contentType = text/html 26.01 22:46:36.555 localhost <= 192.168.12.30:80 HTTP Done 26.01 22:46:40.698 192.168.12.30 => localhost:10030 HTTP GET /mod_megad.php?pt=0&cnt=16&mdid= 26.01 22:46:40.702 MG4?0=1& 26.01 22:46:40.702 Redirect to MG3 26.01 22:46:40.702 localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=9:0 26.01 22:46:40.703 MG3?9=0& 26.01 22:46:40.704 192.168.12.30 <= localhost:10030 26.01 22:46:40.711 localhost <= 192.168.12.30:80 response: statusCode=200 contentType = text/html 26.01 22:46:40.714 localhost <= 192.168.12.30:80 HTTP Done
-
Поправим, вечером выложим обновление.
-
Еще такой момент по request от MegaD вида st=1 (контроллер стартовал). Вы по этому request какой-нибудь функционал закладывали?
Вроде как при получении этой команды происходит новый опрос контроллера - это видно по логу:
28.01 10:09:06.133 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=31&cmd=list 28.01 10:09:06.134 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=31&cmd=list HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:06.214 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:06.216 localhost <= 192.168.12.21:80 HTTP ff862a831501:26.31;ff6e2a831501:26.31;ff676b821503:25.93 28.01 10:09:06.216 MG3?31_ff862a831501=26.31&31_ff6e2a831501=26.31&31_ff676b821503=25.93& 28.01 10:09:06.217 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:06.332 28.01 10:09:06.333 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=34&scl=35&i2c_dev=htu21d&i2c_par=1 28.01 10:09:06.334 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=34&scl=35&i2c_dev=htu21d&i2c_par=1 HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:11.339 Socket timeout - abort! 28.01 10:09:11.341 28.01 10:09:11.341 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=34&scl=35&i2c_dev=htu21d 28.01 10:09:11.343 localhost <=>192.168.12.21:80 socket handle=17\. Header: GET /sec/?pt=34&scl=35&i2c_dev=htu21d HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:16.337 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?st=1 28.01 10:09:16.340 192.168.12.21 <= localhost:10021 28.01 10:09:16.355 Socket timeout - abort! 28.01 10:09:16.364 28.01 10:09:16.364 localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=all 28.01 10:09:16.367 localhost <=>192.168.12.21:80 socket handle=19\. Header: GET /sec/?cmd=all HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:16.489 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:16.492 localhost <= 192.168.12.21:80 HTTP OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;temp:0.00/hum:0.00;;OFF;OFF;;OFF;247;ON 28.01 10:09:16.493 Address 36 28.01 10:09:16.493 run script: val=247 depo={ res: [] } 28.01 10:09:16.494 script return:{ reqsek: 5 } depo={ res: [ 247 ] } 28.01 10:09:16.494 Address 36\. Shift request interval: 5 sek. 28.01 10:09:16.494 MG3?0=0&1=0&2=0&3=0&4=0&5=0&6=0&7=0&8=0&9=0&10=0&11=0&12=0&13=0&14=1&15=0&16=0&17=0&18=0&19=0&20=0&21=0&22=0&23=0&24=0&25=0&26=0&27=0&28=0&29=1&30_1=0&30_2=0&31=0&32=0&33=0&34=0&35=0&37=1& 28.01 10:09:16.495 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:18.374 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:18.379 localhost <= 192.168.12.21:80 HTTP 22.67 28.01 10:09:18.380 MG3?342=22.67& 28.01 10:09:18.381 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:19.2 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:19.5 localhost <= 192.168.12.21:80 HTTP 26.86 28.01 10:09:19.5 MG3?341=26.86& 28.01 10:09:19.6 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:21.563 28.01 10:09:21.564 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=36&cmd=get 28.01 10:09:21.566 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=36&cmd=get HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:21.571 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:21.573 localhost <= 192.168.12.21:80 HTTP 248 28.01 10:09:21.573 Address 36 28.01 10:09:21.574 run script: val=248 depo={ res: [ 247 ] } 28.01 10:09:21.575 script return:{ reqsek: 5 } depo={ res: [ 247, 248 ] } 28.01 10:09:21.575 MG3? 28.01 10:09:21.576 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:26.572 28.01 10:09:26.572 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=36&cmd=get 28.01 10:09:26.574 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=36&cmd=get HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:26.580 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:26.582 localhost <= 192.168.12.21:80 HTTP 240 28.01 10:09:26.582 Address 36 28.01 10:09:26.583 run script: val=240 depo={ res: [ 247, 248 ] } 28.01 10:09:26.584 script return:{ reqsek: 5 } depo={ res: [ 247, 248, 240 ] } 28.01 10:09:26.584 MG3? 28.01 10:09:26.585 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:31.581 28.01 10:09:31.581 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=36&cmd=get 28.01 10:09:31.584 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=36&cmd=get HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:31.590 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:31.592 localhost <= 192.168.12.21:80 HTTP 238 28.01 10:09:31.593 Address 36 28.01 10:09:31.594 run script: val=238 depo={ res: [ 247, 248, 240 ] } 28.01 10:09:31.596 script return:{ reqsek: 5 } depo={ res: [ 247, 248, 240, 238 ] } 28.01 10:09:31.596 MG3? 28.01 10:09:31.598 localhost <=>192.168.12.21:80 socket closed 28.01 10:09:36.590 28.01 10:09:36.591 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=36&cmd=get 28.01 10:09:36.593 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=36&cmd=get HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:09:36.598 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:09:36.601 localhost <= 192.168.12.21:80 HTTP 244 28.01 10:09:36.601 Address 36 28.01 10:09:36.602 run script: val=244 depo={ res: [ 247, 248, 240, 238 ] } 28.01 10:09:36.607 script return:{ val: 1790, reqsek: 300 } depo={ res: [] } 28.01 10:09:36.607 Address 36\. Shift request interval: 300 sek. 28.01 10:09:36.608 MG3?36=1790& 28.01 10:09:36.610 localhost <=>192.168.12.21:80 socket closed 28.01 10:10:16.459 28.01 10:10:16.460 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=31&cmd=list 28.01 10:10:16.462 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=31&cmd=list HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:10:16.541 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:10:16.543 localhost <= 192.168.12.21:80 HTTP ff862a831501:26.31;ff6e2a831501:26.37;ff676b821503:25.93 28.01 10:10:16.544 MG3?31_ff862a831501=26.31&31_ff6e2a831501=26.37&31_ff676b821503=25.93& 28.01 10:10:16.545 localhost <=>192.168.12.21:80 socket closed 28.01 10:10:16.659 28.01 10:10:16.660 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=34&scl=35&i2c_dev=htu21d&i2c_par=1 28.01 10:10:16.662 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=34&scl=35&i2c_dev=htu21d&i2c_par=1 HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:10:16.715 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:10:16.717 localhost <= 192.168.12.21:80 HTTP 26.88 28.01 10:10:16.717 MG3?341=26.88& 28.01 10:10:16.718 localhost <=>192.168.12.21:80 socket closed 28.01 10:10:16.860 28.01 10:10:16.860 localhost => 192.168.12.21:80 HTTP GET /sec/?pt=34&scl=35&i2c_dev=htu21d 28.01 10:10:16.862 localhost <=>192.168.12.21:80 socket handle=11\. Header: GET /sec/?pt=34&scl=35&i2c_dev=htu21d HTTP/1.1 Host: 192.168.12.21 Connection: close 28.01 10:10:16.885 localhost <= 192.168.12.21:80 response: statusCode=200 contentType = text/html 28.01 10:10:16.887 localhost <= 192.168.12.21:80 HTTP 22.58 28.01 10:10:16.887 MG3?342=22.58& 28.01 10:10:16.888 localhost <=>192.168.12.21:80 socket closed
Однако я пытался по этому request (st=1) выполнить команду, но она не срабатывает (по логу также ничего связанного с этой командой нет):
-
Еще такой момент по request от MegaD вида st=1 (контроллер стартовал). Вы по этому request какой-нибудь функционал закладывали?
Сейчас как раз проверяем этот функционал. Вы правы, так как там была заложена дополнительная логика (сброс всех таймеров и первый опрос), действия при получении не выполнялись. Также проверяем перенаправление команды на другой контроллер. После тестирования выложим, надеюсь, сегодня
-
Еще такой момент по request от MegaD вида st=1 (контроллер стартовал)…. я пытался по этому request (st=1) выполнить команду, но она не срабатывает (по логу также ничего связанного с этой командой нет):
Ошибку исправили, st=1 обрабатывается, но, похоже, MegaD в ответ на st=1 команду не принимает.
Вариант с отправкой команды через Redirect - работает.
Req:/megad?st=1 Resp:7:1 - так выход не переключается А такой вариант рабочий: Req:/megad?st=1 Req:/sec/?cmd=7:1 Resp:Done
В принципе, это логично. Контроллер принимает команду только в ответ на сообщение о переключении состояния порта.
Обновление выложили, но новость пока публиковать не будем.
Реально проверить передачу команд на другие контроллеры мы не можем, т.к. имеем только один контроллер и тестируем на эмуляторе, что не совсем аутентично :).
Что исправлено:
1. Переключение состояния канала при передаче команды на другой контроллер
2. Ширина столбца для показа названия контроллера в таблице Redirect
Думаю, эти две ошибки и привели к тому, что разобраться получилось не сразу.
3. На запрос st=1 можно вешать команды в Redirect
-
Ошибку исправили, st=1 обрабатывается, но, похоже, MegaD в ответ на st=1 команду не принимает.
Как-то странно, должно все работать - потестирую. Вообще в MegaD-2561 Андрей предлагал после получения st=1 сервером, например, устанавливать время в контроллере (для работы с локальным cron).
@intrapro:Реально проверить передачу команд на другие контроллеры мы не можем, т.к. имеем только один контроллер и тестируем на эмуляторе, что не совсем аутентично :).
Проверил на том же варианте, который был настроен в прошлый раз - после обновления переключаются порты удаленного контроллера и, соответственно, меняется состояние привязанного к каналу устройства в вебе.
@intrapro:Что исправлено:
1. Переключение состояния канала при передаче команды на другой контроллер
2. Ширина столбца для показа названия контроллера в таблице Redirect
Думаю, эти две ошибки и привели к тому, что разобраться получилось не сразу.
1. Работает с изменением состояния устройства, привязанного к каналу.
2. Да, теперь в столбце на моем нетбуке отображается название контроллера.
@intrapro:3. На запрос st=1 можно вешать команды в Redirect
Это конечно очень хорошо!!! и я очень благодарен Вам за развитие плагина, но сейчас возможно вешать только простые команды, типа переключение каналов. Надо вводить возможность привязки скриптов, как это сделано у каналов. Например, при st=1 надо:
1. Установить время в MegaD. Команда такая http://192.168.0.14/sec/?cf=7&stime=10:57:06:4, но прежде надо запросить системное время с днем недели. То есть нужен скрипт.
2. Инициализировать OLED дисплей.
Хотя скорее все же скрипт нужен только к request st=1. Поскольку всю остальную логику можно реализовать средствами ih (сценарии и прочее).
-
Вообще, хочу Вам дать "пищу" для реализации в плагине поддержки I2C. В варианте реализации MegaD-2561 - это все довольно просто, поскольку основные команды I2C реализованы аппаратно!
i2c_cmd - команды (1 - инициализация; 2 - старт; 3 - стоп) i2c_send - отправка данных в HEX-виде i2c_read - считывание данных в HEX-виде (0 - на конце ACK; 1 - на конце NACK [конец связи]) i2c_sendp - отправка пакетных данных в HEX-виде
Пример последовательности команд передаваемых на контроллер MegaD-2561 для опроса датчика HTU21D:
http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=1 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=80E3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=81 //Тут нужна задержка не менее 15000 мкс http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0 http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0 http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=1 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 Температура: 25.49° http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=1 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=80E5 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=81 //Тут нужна задержка не менее 15000 мкс http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0 http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0 http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=1 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 Относительная влажность: 25.59%
Последовательность команд для инициализации OLED с контроллером SSD1306:
http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=1 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=7800AFD58081EE8D14AFA1C8A6 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3
Последовательность команд для очистки дисплея OLED с контроллером SSD1306:
http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=7800200021007F220007 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=7840 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=0000000000000000000000000000000000000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=00000000 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3
Ну и на "закуску" - тестовый php-скрипт с которого я начинал, осваивая I2C с MegaD: Считывание данных с htu21d, инициализация OLED SSD1306, вывод информации в веб и на OLED. И HTU21D, и OLED подключены к одной и той же шине I2C на MegaD - 34-порт SDA и 35-порт SCL.
define("SCL", "35"); define("SDA", "34"); define("ADR", "78"); //Display adress define("MD", "http://192.168.12.21/sec/?"); function i2c_init() { file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_cmd=1"); } function i2c_start() { file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_cmd=2"); } function i2c_stop() { file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_cmd=3"); } function i2c_send($data) { file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_send=" .$data); } function i2c_send_p($data) { file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_sendp=" .$data); } function i2c_read($nack = 0) { return file_get_contents(MD."pt=".SDA."&scl=".SCL."&i2c_read=" .$nack); } function check_htu21d_crc($raw_data, $crc) { $remainder = $raw_data << 8; $divsor = 0x988000; for ( $i = 0 ; $i < 16 ; $i++) { if ( $remainder & 1<<(23 - $i) ) $remainder ^= $divsor; $divsor >>= 1; } return dechex($remainder); } function get_htu21d_temperature() { i2c_init(); i2c_start(); i2c_send_p("80E3"); i2c_stop(); i2c_start(); i2c_send("81"); usleep(15000); $msb = i2c_read(); $lsb = i2c_read(); $crc = i2c_read(1); i2c_stop(); if ( strlen($msb) == 1 ) $msb = "0$msb"; if ( strlen($lsb) == 1 ) $lsb = "0$lsb"; $msb = hexdec($msb); $lsb = hexdec($lsb); $raw_temp = ($msb << 8) | $lsb; if ( check_htu21d_crc($raw_temp, $crc) != $crc ) return "CRC error - $crc"; else { $raw_temp &= 0xFFFC; $temperature = number_format(round(-46.85 + 175.72 * ($raw_temp / 65536), 2), 2); return $temperature; } } function get_htu21d_humidity() { i2c_init(); i2c_start(); i2c_send_p("80E5"); i2c_stop(); i2c_start(); i2c_send("81"); usleep(15000); $msb = i2c_read(); $lsb = i2c_read(); $crc = i2c_read(1); i2c_stop(); if ( strlen($msb) == 1 ) $msb = "0$msb"; if ( strlen($lsb) == 1 ) $lsb = "0$lsb"; $msb = hexdec($msb); $lsb = hexdec($lsb); $raw_hum = ($msb << 8) | $lsb; if ( check_htu21d_crc($raw_hum, $crc) != $crc ) return "CRC error - $crc"; else { $raw_hum &= 0xFFFC; $humidity = number_format(round(-6 + (125 * ($raw_hum / 65536)), 2), 2); if ( $humidity > 100 ) $humidity = 100; return $humidity; } } function ssd1306_init() { i2c_stop(); i2c_init(); i2c_start(); i2c_send_p(ADR."00AFD58081EE8D14AFA1C8A6"); i2c_stop(); } function ssd1306_clear_display() { i2c_start(); i2c_send_p(ADR."00200021007F220007"); i2c_stop(); i2c_start(); i2c_send_p(ADR."40"); $my_cnt = 0; $data_p = ""; for ( $i = 0; $i < 1024; $i++ ) { $data_p .= "00"; $my_cnt++; if ( $my_cnt == 20 || $i == 1023 ) { $my_cnt = 0; i2c_send_p($data_p); $data_p = ""; } } i2c_stop(); } function ssd1306_write_text($string, $font = "default", $col = 0, $page = 0) { $my_string = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY); include("libs/ssd1306/mod_ssd1306_fonts.php"); $my_font = $$font; i2c_start(); i2c_send_p(ADR. "00204121"); i2c_send(dechex($col)); i2c_send_p("7F22"); i2c_send(dechex($page)); i2c_send(dechex($page + 1)); i2c_stop(); i2c_start(); i2c_send_p(ADR."40"); $my_cnt = 0; $data_p = ""; for ( $j = 0; $j < count($my_string); $j++ ) { $flag = 1; $data = ""; for ( $i = 0; $i < count($my_font[$my_string[$j]]); $i++ ) { $data = dechex($my_font[$my_string[$j]][$i + $flag]); if ( strlen($data) == 1 ) $data = "0$data"; $data_p .= $data; $my_cnt++; if ( $my_cnt == 20 || $i == count($my_font[$my_string[$j]]) - 1 ) { $my_cnt = 0; i2c_send_p($data_p); $data_p = ""; } $flag = $flag * -1; } i2c_send_p("0000"); } i2c_stop(); } $temperature = get_htu21d_temperature(); echo "Температура: ".$temperature."° \n"; $humidity = get_htu21d_humidity(); echo "Относительная влажность: ".$humidity."% \n"; $hum_compensated = $humidity + (25 - $temperature) * -0.15; echo "Относительная влажность (комп.): ".$hum_compensated."% \n"; echo " * * * \n"; ssd1306_init(); echo "Дисплей инициализирован! \n"; ssd1306_clear_display(); echo "Дисплей очищен! \n"; ssd1306_write_text("OLED with SSD1306", "verdana_10", 6, 0); ssd1306_write_text("Температура: $temperature C", "verdana_10", 2, 2); ssd1306_write_text("Влажность: $humidity %", "verdana_10", 7, 4); ssd1306_write_text("Информационная строка", "default", 0, 6); echo "Данные выведены на дисплей! \n";
Собственно за такую реализацию I2C в MegaD-2561, библиотеки и примеры работы с устройствами I2C большое спасибо все тому же Андрею - автору проекта ab-log.
-
Alex_Jet, большое спасибо за быстрое тестирование
-
По поводу отправки времени по команде st=1 - можно просто заложить в плагин ( опционально, если это важно). Мы st=1 уже обрабатываем.
По I2C - действительно, API красивое, температуру и влажность сделать можно, если из скрипта возвращать запросы. А они подряд могут идти или нужны задержки? И наверно нужны команды чтения, если как в php-скрипте?
http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=1 // ?Подряд? или дождаться ответа? или некоторую задержку сделать? http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendp=80E3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3 http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2 http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=81 //Тут нужна задержка не менее 15000 мкс - понятно // ?Здесь видимо нужно чтение выполнить: ??http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendi2c_read=0 - и получить 1 байт ??http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendi2c_read=0 - и 2 байт ??http://192.168.12.21/sec/?pt=34&scl=35&i2c_sendi2c_read=1 - закончить чтение и выполнить преобразование значения http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3
А по поводу дисплея…Их может быть несколько? как они адресуются?
include("libs/ssd1306/mod_ssd1306_fonts.php"); - это видимо таблица символов разными шрифтами?
Ее и саму процедуру вывода значения на дисплей можно, наверно, включить в плагин, если это штатное оборудование для MegaD. Организовать некую библиотеку плагина.
Как выводить на дисплей, когда? Можно отдельные сегменты (только температуру) или нужно все переписывать? Там ведь могут быть данные не только с каналов MegaD? В общем, нужно подумать
-
По поводу отправки времени по команде st=1 - можно просто заложить в плагин ( опционально, если это важно). Мы st=1 уже обрабатываем.
Можно заложить, но только опционально, поскольку MegaD-328 этот функционал не поддерживает.
@intrapro:По I2C - действительно, API красивое, температуру и влажность сделать можно, если из скрипта возвращать запросы. А они подряд могут идти или нужны задержки? И наверно нужны команды чтения, если как в php-скрипте?
Идут подряд, но как вы говорите PHP сам по себе медленный…надо учесть что I2C обычно работает с частотой 10кГц (медленный режим - как раз для нас, поскольку датчики от контроллера надо располагать на расстоянии 5-10 м). Команды чтения - конечно нужны.
Вообще строго говоря нужен функционал:
-
например, создать скрипт на том же 34-м канале или на "виртуальных" каналах 341,342....349 уже можем
-
в скрипте написать нужные функции для обработки результатов чтения и их возврат/присвоение каналу. Тут как минимум нужен пример как обращаться к функциям I2C, как связать эти функции с IP контроллера и т.д. Пользователи напишут сами нужные функции в скрипте.
По коду (немного ошибся в предыдущем посте, но уже все поправил). Про скорость уже написал. Ниже "рукопашный" код считывания температуры с HTU21D и вывод в веб. На почту скинул damp обмена данными. В принципе видно, что при команде read=0 контроллер отвечает 200 ОК со значением 68, потом b8, а при read=1 - 64 (см.вывод веба).
function Read_Temp() { file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=1"); //init file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2"); //start file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=80"); //adress + write file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=E3"); //trigger temperature measurement file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3"); //stop file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=2"); //start file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_send=81"); //adress + read usleep(15000); $msb = file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0"); //ACK $lsb = file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=0"); //ACK $crc = file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_read=1"); //NACK file_get_contents("http://192.168.12.21/sec/?pt=34&scl=35&i2c_cmd=3"); //stop echo "Data (MSB): " .$msb. " \n"; echo "Data (LSB): " .$lsb. " \n"; echo "Checksum: " .$crc. " \n"; $msb = hexdec($msb); $lsb = hexdec($lsb); $raw = ($msb << 8) | $lsb; echo "Raw: " .$raw. " \n"; $temp = round((-46.85 + 175.72*(($raw)/65536)), 2); echo "Температура: " .$temp. "°"; }
Data (MSB): 68 Data (LSB): b8 Checksum: 64 Raw: 26808 Температура: 25.03°
А по поводу дисплея…Их может быть несколько? как они адресуются?
На самом деле многие I2C устройства могут иметь несколько адресов. В частности OLED дисплеи могут иметь 2 адреса. Датчик освещенности TSL2561 - 3 шт.
@intrapro:include("libs/ssd1306/mod_ssd1306_fonts.php"); - это видимо таблица символов разными шрифтами?
Ее и саму процедуру вывода значения на дисплей можно, наверно, включить в плагин, если это штатное оборудование для MegaD. Организовать некую библиотеку плагина.
Да, эту таблицу я так понимаю сгенерировал Андрей. Там сейчас есть 3 шрифта. Главное правильно продумать процедуру вывода, поскольку дисплеи могут быть разного формата. Пока сообщество использует самый дешевый 0,96" дисплей.
@intrapro:Как выводить на дисплей, когда? Можно отдельные сегменты (только температуру) или нужно все переписывать? Там ведь могут быть данные не только с каналов MegaD? В общем, нужно подумать
Периодичность обновления данных, думаю, надо задавать. Вообще для чего эти дисплеи можно использовать? - например, встроить в заглушку подрозетника - туда же где будет размещаться датчик температуры. Это своеобразный "железный" термогигрометр, который кроме температуры, влажности, может отобразить уровень СО2 и другие показатели - по пути подошел и посмотрел какой же климат в данном помещении. Поэтому период обновления от 5 до 10 минут. Для больших дисплеев же применение не ограничено…
Можно переписывать отдельные сегменты, но это вероятно должно определяться в пользовательском скрипте. Конечно же на дисплей можно выводить любые данные. Поэтому как вариант для MegaD-2561 нужен свой раздел, например, "I2C display".
-
-
Как-то странно, должно все работать - потестирую. Вообще в MegaD-2561 Андрей предлагал после получения st=1 сервером, например, устанавливать время в контроллере (для работы с локальным cron).
Если давать команду на включение порта через request, то контроллер не отрабатывает! А если через redirect, то все хорошо. Вот лог не успешного включения канала через request:
29.01 11:31:39.0545 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?st=1 29.01 11:31:39.0553 MG3?22=1& 29.01 11:31:39.0554 192.168.12.21 <= localhost:10021 22:1 29.01 11:31:39.0661 localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=all 29.01 11:31:39.0785 localhost <= 192.168.12.21:80 HTTP OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;temp:0.00/hum:0.00;;OFF;OFF;;OFF;256;ON
По логу видно, что сервер дает команду контроллеру не по 80-му порту… сравните действие 29.01 11:31:39.0554 и 29.01 11:31:39.0661 localhost
Лог при redirect:
29.01 11:39:24.0895 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?st=1 29.01 11:39:24.0900 192.168.12.21 <= localhost:10021 29.01 11:39:24.0911 Redirect to MG3 29.01 11:39:24.0913 localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=22:1 29.01 11:39:24.0915 MG3?22=1& 29.01 11:39:24.0935 localhost <= 192.168.12.21:80 HTTP Done
-
Если давать команду на включение порта через request, то контроллер не отрабатывает! А если через redirect, то все хорошо.
По логу видно, что сервер дает команду контроллеру не по 80-му порту… сравните действие 29.01 11:31:39.0554 и 29.01 11:31:39.0661 localhost
Но включение порта ведь работает через request, если входящий запрос имеет вид /megad?pt=1 ?
Не работает только для запроса st=1. Порт здесь не при чем.
Разница в том, что в первом случае сервер отвечает на входящий запрос (слушает порт 10021 и просто посылает команду В ОТВЕТ на запрос).
Если порт вывести - это будет просто динамически назначенный порт входящего запроса.
192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?st=1 - Request от MegaD 192.168.12.21 <= localhost:10021 22:1 - Response на request, кто послал, тому и отвечаем.
Во втором случае - инициатива исходит от сервера, поэтому от адресуется к IP и порту.
Если послать такую команду, то она работает, неважно, какой перед этим был запрос.
localhost => 192.168.12.21:80 HTTP GET /sec/?cmd=22:1 - Request от сервера localhost <= 192.168.12.21:80 HTTP Done - Response на request от MegaD
Сейчас реакция на сообщения так и реализована: если прописываете Response в ответ на Request - работает по первому варианту.
Если через Redirect - по второму.
-
Да, вы во всем правы!
Для удобства использования redirect необходим столбец с признаком наличия хотя бы одного правила для redirect у соответствующего request. Иначе при большом количестве request сложно соориентироваться у каких есть redirect.
-
Для удобства использования redirect необходим столбец с признаком наличия хотя бы одного правила для redirect у соответствующего request.
Сделаем в следующем релизе в конце недели.
Иначе при большом количестве request сложно соориентироваться у каких есть redirect.
Действительно, сейчас настройка не прозрачна. В версии Cherry планируется при выборе записи сразу отображать связанные таблицы. Это относится также к каналам - можно будет показать сразу запросы канала.
По поводу передачи времени от сервера при получении st=1.
Думаю, это работает,если это отдельный запрос от сервера (в нашей терминологии Redirect), а не ответ (response) на st=1.
Сеанс в HTTP 1.0 - это только 1 запрос и 1 ответ.
Именно поэтому контроллер уже не может ответить Done, если мы передаем команду как ответ на сообщение от MegaD.
И по термину Redirect. Надо бы придумать другое название, т.к. это просто передача запроса по инициативе сервера при получении сообщения от контроллера (не в том же сеансе).
-
По поводу передачи времени от сервера при получении st=1.
Думаю, это работает,если это отдельный запрос от сервера (в нашей терминологии Redirect), а не ответ (response) на st=1.
Сеанс в HTTP 1.0 - это только 1 запрос и 1 ответ.
Именно поэтому контроллер уже не может ответить Done, если мы передаем команду как ответ на сообщение от MegaD.
Да, так и есть. Главная суть, в том что TCP-соединение - это "запрос-ответ": http://www.ab-log.ru/forum/viewtopic.php?f=1&t=1195&p=26365#p26363
По redirect… мыслей нет, поскольку у нашего "Redirect" есть 2 варианта:
1. Ответ текущему контроллеру на основе его запроса, но в новой сессии TCP-соединения - это что-то типа "response to a request"
2. Выдача команды другому контроллеру, на основе запроса текущего - это что-то типа "command on a request of master"
Как вариант оставить как есть.
-
Обдумываю как с помощью intrahouse обрабатывать короткое и длинное нажатие одной и той же кнопки. Пока мыслей как это сделать нет.
Сейчас имеем такой лог при нажатии и удержании кнопки, подключенной к MegaD:
19.02 23:23:20.0065 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=15&cnt=62 19.02 23:23:20.0072 MG3?22=TG& 19.02 23:23:20.0073 192.168.12.21 <= localhost:10021 22:2 19.02 23:23:21.0055 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=15&m=2&cnt=62 19.02 23:23:21.0057 MG3?22=TG& 19.02 23:23:21.0058 192.168.12.21 <= localhost:10021 22:2
Как видите MegaD через 1 секунду после нажатия выдает серверу сообщение (m=2) о длительном нажатии кнопки. Однако в request у меня сейчас прописано mod_megad.php?pt=15, соответственно сервер и первое сообщение и второе сообщение от MegaD интерпретирует одинаково.
Если в request прописать явно mod_megad.php?pt=15&m=2, то первое сообщение сервером вообще не будет обрабатываться. Как быть?
UPD: единственное, что это режим входа называется P, а можно установить еще P&R, тогда при отжатии кнопки будет дополнительное сообщение типа mod_megad.php?pt=15&m=1&cnt=62.
-
Обдумываю как с помощью intrahouse обрабатывать короткое и длинное нажатие одной и той же кнопки. … можно установить еще P&R, тогда при отжатии кнопки будет дополнительное сообщение типа mod_megad.php?pt=15&m=1&cnt=62.
Все верно, длинное от короткого можно отличить только если отслеживать отжатие.
mod_megad.php?pt=15&m=1 - короткое, сработает при отпускании
mod_megad.php?pt=15&m=2 - длинное через секунду
Если в request прописать явно mod_megad.php?pt=15&m=2, то первое сообщение сервером вообще не будет обрабатываться. Как быть?.
На самом деле для сервера mod_megad.php?pt=15 и mod_megad.php?pt=15&m=2 - это разные сообщения, попробуйте
Просто mod_megad.php?pt=15 - сработает при нажатии, а уж сколько будут держать, определяется моментом отжатия
-
Все верно, длинное от короткого можно отличить только если отслеживать отжатие.
mod_megad.php?pt=15&m=1 - короткое, сработает при отпускании
mod_megad.php?pt=15&m=2 - длинное через секунду
ОК, но после того как придет mod_megad.php?pt=15&m=2, кнопку отпустим и снова придет mod_megad.php?pt=15&m=1!!! Поэкспериментировал.
1. Зажимаем кратковременно кнопку (вход в режиме P&R) и отпускаем ее:
20.02 21:14:44.0242 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&cnt=1 20.02 21:14:44.0244 MG3?7=TG& 20.02 21:14:44.0244 192.168.12.21 <= localhost:10021 7:2 20.02 21:14:44.0772 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&m=1&cnt=2 20.02 21:14:44.0774 MG3?7=TG& 20.02 21:14:44.0774 192.168.12.21 <= localhost:10021 7:2
2. Зажимаем надолго кнопку (вход в режиме P&R) и отпускаем ее:
20.02 21:14:46.0756 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&cnt=3 20.02 21:14:46.0758 MG3?7=TG& 20.02 21:14:46.0758 192.168.12.21 <= localhost:10021 7:2 20.02 21:14:47.0751 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&m=2&cnt=3 20.02 21:14:47.0759 MG3?7=TG& 20.02 21:14:47.0759 192.168.12.21 <= localhost:10021 7:2 20.02 21:14:48.0775 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&m=1&cnt=4 20.02 21:14:48.0776 MG3?7=TG& 20.02 21:14:48.0777 192.168.12.21 <= localhost:10021 7:2
Значит:
-
если пришло pt=0, а следом pt=0&m=1 - то это короткое нажатие.
-
если пришло pt=0, а следом pt=0&m=2 - то это длинное нажатие.
Как эти условия проверять в ih? Нужна какая-то доработка.
-
-
Значит:
-
если пришло pt=0, а следом pt=0&m=1 - то это короткое нажатие.
-
если пришло pt=0, а следом pt=0&m=2 - то это длинное нажатие.
Как эти условия проверять в ih? Нужна какая-то доработка.
Да, вы правы. После m=2 приходит m=1 - это меняет дело
Нужны цепочки запросов:
megad?pt=0 then megad?pt=0&m=2
или просто
megad?pt=0; megad?pt=0&m=2
Постараемся в праздники сделать.
-
-
Постараемся в праздники сделать.
Ну совсем наизнос работаете…
UPD: Поменял режим работы входа на P. В итоге сообщение об отпускании теперь не приходит.
- Короткое нажатие кнопки:
22.02 00:13:46.0491 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&cnt=8 22.02 00:13:46.0493 MG3?7=TG& 22.02 00:13:46.0496 192.168.12.21 <= localhost:10021 7:2
- Длинное нажатие кнопки:
22.02 00:13:53.0077 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&cnt=9 22.02 00:13:53.0078 MG3?7=TG& 22.02 00:13:53.0079 192.168.12.21 <= localhost:10021 7:2 22.02 00:13:54.0073 192.168.12.21 => localhost:10021 HTTP GET /mod_megad.php?pt=0&m=2&cnt=9 22.02 00:13:54.0075 MG3?7=TG& 22.02 00:13:54.0075 192.168.12.21 <= localhost:10021 7:2
В request у меня прописано действие 7:2 для события /mod_megad.php?pt=0. Как видим во втором случае (длинное нажатие кнопки) это действие срабатывает и при событии /mod_megad.php?pt=0&m=2, а по идее не должно! Вот этот случай надо разрешить.