[Разработка для интернета вещей, Интернет вещей] Системы контроля управления доступом в IoT — умеем, знаем, практикуем
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
И снова привет, мир!В прошлой статье про IoT-елочку в голосовании многие отметили, что интересна тема управления устройствами в зависимости от количества человек в помещении. Это довольно масштабная задача, и мы предлагаем разделить ее решение на несколько этапов. Сегодня поговорим о системе контроля управления доступом (СКУД), которая, будучи подключенной к платформе интернета вещей Rightech IoT Cloud (далее по тексту - платформа), является базовым элементом в системе подсчета количества человек в офисе. Мы уже поверхностно освещали этот кейс в одной из статей, но сегодня рассмотрим этот проект более подробно и погрузимся в особенности исполнения.СКУД?Система контроля и управления доступом, СКУД (англ. Physical Access Control System, PACS) — совокупность программно-аппаратных средств контроля и управления, главная цель которой - ограничение и регистрация входа-выхода объектов (людей, транспорта) на заданной территории через «точки прохода»: двери, ворота, КПП.
С чего все началосьЗадача обеспечить контроль за входом-выходом в офисе возникла еще в те времена, когда у нас был выход на крышу с отличным видом на Москву, и поэтому часто приходили люди, не являющиеся нашими сотрудниками. Тогда мы решили принять какие-то меры по безопасности и установить СКУД.
АрхитектураСистема открытия дверей по картеВ качестве модуля, отвечающего за обработку информации по считыванию бесконтактных карт, выбрали GATE-8000. Основные достоинства контроллера:
- формирование и хранение необходимой информации о факте открытия двери по карте и времени прохода человека в офис;
- возможность автономной работы и защиты от зависания;
- хранение 16 тысяч ключей и 8 тысяч событий;
- простое подключение и управление;
- российский производитель, хорошая документация с описанием работы контроллера.
Внешний вид платы с контроллером
Основной принцип работы: контроллер обрабатывает информацию, поступающую со считывателя, и с помощью встроенного реле коммутирует исполнительное устройство - электромагнитный замок двери. Система взаимодействия с платформойПосле того, как контроллер установили в систему по общей схеме подключения, а карты записали в память, мы уже обезопасили себя от прохода в офис посторонних. А дальше возник вопрос, как подключить этот контроллер к платформе Rightech ioT Cloud. Ведь очень здорово иметь а) графический интерфейс, в котором можно полистать историю всех проходов, б) возможность отправки команд на открытие двери удаленно, не отходя от рабочего места, например, для гостей или доставщика еды.У контроллера нет выхода в Интернет и видимой возможности подключения к платформе, к тому же все события нужно принудительно считывать из его циклического буфера. Однако у него есть свой протокол обмена данными с компьютером управления, благодаря которому можно отправлять на контроллер команды, такие как считать из контроллера, записать в контроллер, открыть/закрыть замок и другие. Значит, нужно сделать некоторую программно-аппаратную прослойку между контроллером и платформой - агента, который будет отправлять команды на чтение событий и управление контроллером.
Обращаем внимание, что в данной архитектуре функция открытия двери при прикладывании карты не перестанет выполняться при отсутствии Интернета. За открытие двери и сбор информации отвечает контроллер СКУД, поэтому в случае потери Интернета, единственное, что нам грозит, - это то, что агент, который доставляет данные на платформу, не будет функционировать, так как не сможет получать команды на чтение буфера. Однако при восстановлении соединения все события считаются в полном объеме и не потеряются, так как они будут сохранены в буфере контроллера СКУД.▍Аппаратная частьДля начала нужно было выбрать устройство, которое будет всегда в активном состоянии с включенной программой-агентом в непосредственной близости от платы СКУД. Из многообразия микрокомпьютеров первое что попало под руку выбор пал на Raspberry Pi.
Дальше возник вопрос, как подсоединить GATE-8000 к Raspberry - то есть как подключить последовательный интерфейс RS485 от GATE к USB от микрокомпьютера. Начались поиски переходника USB-RS485. Первый вариант, который мы испробовали, - Espada за 200 рублей. Надежда на то, что маленький хлипкий китайский переходник заработает, была небольшой. Он и не заработал. Вместо нужных данных приходило что-то похожее по виду и размеру, но… всё же не то. В чем было дело: в отсутствии гальванической развязки, невозможности поддерживать скорость 19200 bps или же просто в некачественной элементной базе, - загадка. Но после обращения к производителю GATE-8000, мы получили рекомендацию на более дорогой (в 10 раз) и громоздкий (но аккуратный и корпусированный) переходник Z-397, который заработал тут же как надо.
▍Программная частьНачинаем разработку программы с определения, какие функции она должна выполнять.
- Что нужно - взаимодействие с GATE-8000 для отправки команд и получения данных. Как решим - изучим протокол GATE, напишем сериализатор и десериализатор данных, подключим библиотеку для работы с последовательным портом.
- Что нужно - взаимодействие с платформой для получения команд и отправки данных.Как решим - выберем для общения протокол MQTT, в коде воспользуемся готовой библиотекой Paho MQTT.
Итак, мы приступили к изучению протокола GATE-8000, который является закрытым, поэтому ниже рассказано только о некоторых его особенностях. Он достаточно низкоуровневый, и необходимо обращаться напрямую к регистрам памяти устройства. В документе по этому протоколу описаны кадры запросов от компьютера контроллеру и кадры ответов контроллера компьютеру. Меняя поля в кадре запроса, можно отправлять на устройство различные команды и получать информацию из регистров. Одна из особенностей протокола в том, что инициатором обмена всегда является компьютер. Поэтому есть два подхода работы с устройством: 1) задавать всю логику работы в агенте;2) использовать внешние запросы (от платформы). Мы выбрали второй вариант и вынесли логику с конечного устройства на платформу (подробнее про сервис сценариев автоматизации >>>). Так ее легко адаптировать и подстроить, при этом код программы остается компактным и позволяет просто формировать команды для устройства, а платформа в свою очередь координирует отправку команд и их периодичность. Всегда ли нужно выносить логику работы с устройства? Такое решение, конечно, не подойдет, если от устройства требуется предпринять действия мгновенно (например, если идет речь о жизни человека), но даже в таком случае часть логики можно вынести на платформу. Как вариант, для выбора заранее запрограммированных шаблонов поведения.После того как мы внимательно изучили этот протокол, формат кадров и список команд, возникла первая сложность. Команды для чтения буфера, в котором содержатся события о том, кто и во сколько пришел, не оказалось. А ведь получить эту информацию - первоочередная задача. Понадобилось изучить карту памяти контроллера, чтобы определить адреса, по которым нужно считывать данные.
Карта памяти контроллера? WTF?Под картой памяти контроллера (термин из протокола) имеется в виду таблица с описанием заполнения регистров памяти, а не микрофлешка =). Следующая особенность работы с контроллером в том, что за один цикл чтения можно получить только 12 событий, по 8 байт на каждое. А на каждый проход человека в офис генерируется уже два события:1) найден ключ в банке ключей (банк ключей - еще один блок в распределенной памяти контроллера);2) состоялся проход (если он, конечно, состоялся). Ниже представлен фрагмент кода на С++, реализующий метод одного цикла чтения буфера.
bool SerialPortInlet::readBufferCycle(unsigned short& bottom, unsigned short const& top, unsigned char& u_lowerBound,
unsigned char& l_lowerBound, std::vector<unsigned char>& readBuffer, std::string& result)
{
// Подсчет байтов, которые необходимо считать
unsigned short byteCountTmp = top - bottom;
BOOST_LOG_SEV(log_, logging::info) << "Need read " << byteCountTmp << " byte";
unsigned char byteCount;
// За один цикл нельзя прочитать более 12 событий (96 байт)
byteCount = byteCountTmp > 0x60 ? 0x60 : (unsigned char)byteCountTmp;
BOOST_LOG_SEV(log_, logging::info) << "Read " << +byteCount << " byte";
// Описываем тело команды
std::vector<unsigned char> body = {0x02, 0xA0, byteCount, u_lowerBound, l_lowerBound};
std::vector<unsigned char> command;
// Получаем полный текст команды
generateComplexCommand(command, Command::BYTE_CODE_READ, body);
// Если не удалось по каким-то причинам отправить команду (например, конечное устройство не подключено), возвращается false
if (!sendCommand(command, result))
{
return false;
}
// Иначе отправляем ответ с устройства на парсинг по событиям
SerialPortType::Answer answerEvents;
if(!Parsers::parserAnswer(log_, result, answerEvents, Command::BYTE_CODE_READ))
{
BOOST_LOG_SEV(log_, logging::error) << "Failed parse buffer reading";
return false;
}
readBuffer.insert(readBuffer.end(), answerEvents.body.begin(), answerEvents.body.end());
// Сдвигаем нижнюю границу буфера для чтения следующих событий
bottom = bottom + byteCount;
u_lowerBound = (unsigned char)(bottom >> 8) ;
l_lowerBound = (unsigned char)bottom;
return true;
}
Немного добавило хлопот то, что, наконец вытащив нужные байты, на месте информации о карте, мы увидели не номер карты, а адрес, по которому он находится. Поэтому потом каждый номер ключа приходится отдельно считывать по адресу. Также не сразу заметили наличие байтстаффинга, его обработку мы ввели уже после первого тестирования с платой.Байтстаффинг?Процедура байтстаффинга заключается в замене зарезервированных символов в теле пакета на специальную последовательность, не содержащую данных символов.
Пример байтстаффинга из документацииПолная структурная схема разработанной системы выглядит так.
Работоспособность всех устройств было очень удобно проверять с помощью графического последовательного терминала СuteCom. После успешного тестирования программа была поставлена на автозапуск, а Raspberry отправилась жить на потолке рядом с платой СКУДа.
Один делает, другой смотрит, третий фотографирует, огнетушитель придерживает дверь - настоящая командная работа =)Работа на платформе Rightech IoT CloudМодельОсновные данные с контроллера - это события, на платформу они приходит в формате JSON и включают в себя поля
- eventTime - время наступления события;
- eventCode - код события;
- keyNumber - номер карты сотрудника (поле может быть пустым, если событие вызвано не картой).
Модель устройства выглядит следующим образом.
Посмотреть оригинал >>>Возможные события:
- нажата кнопка звонка;
- неопознанный ключ на входе;
- неопознанный ключ на выходе;
- ключ найден в банке ключей при входе;
- ключ найден в банке ключей при выходе;
- открывание оператором по сети;
- дверь заблокирована оператором;
- дверь оставлена открытой после входа;
- дверь оставлена открытой после выхода;
- проход состоялся на вход;
- проход состоялся на выход;
- перезагрузка контроллера.
ОбъектИнтерфейс объекта полностью формируется согласно разработанной модели.
Интерфейс истории журнала объектаПосмотреть оригинал >>>
Интерфейс командУра, теперь, собравшись на кухне офиса в ожидании пиццы на праздник, можно никуда не идти, а просто открыть мобильное приложение и нажать кнопку открытия двери для курьера!
АвтоматМожно заметить, что есть команда не только на чтение буфера событий, но и на запись новых границ. В памяти контроллера хранятся границы буфера - начало и конец. Когда на устройство приходит команда чтения, из памяти берутся эти границы и в их пределах происходит чтение из буфера событий. Граница конца буфера сдвигается автоматически на контроллере при получении новых событий. А вот начальную границу буфера нужно перезаписать (указав конечную границу после прошедшего чтения), чтобы не прочитать одни и те же данные повторно. Но это необходимо сделать только после того, как данные о событиях успешно отправлены на платформу.
Зафиксировать успешное получение данных и затем отправить команду на перезапись начальной границы удобно в автомате.
Посмотреть оригинал >>>Здесь виден цикл <чтение>-<запись новой границы буфера>-<ожидание таймера> (сейчас события считываются каждые 30 секунд).
- В состоянии “Read events” читаем новые события.
- В состоянии “Clear buffer” записываем новую границу.
- В состоянии “Await timer …” ожидаем начала нового цикла.
Также есть дополнительные обратные связи для состояний, в которых отправляются команды. Если в течение работы таймера не произошло успешное выполнение команды, таймер срабатывает и отправляется соответствующее сообщение оператору, после чего происходит повторная отправка команды.Дальнейшее использование собранных данныхДанный проект нашел свое продолжение в интеграции с нашей внутренней CRM системой, в которой на вкладке информации о сотрудниках всегда видны актуальные сведения о том, кто находится или отсутствует в офисе.
Также отображается время входа/выхода из офиса, считается суммарное количество часов в месяц.
Посмотреть оригинал >>>
В мессенджер Slack каждый день пишется о том, что офис открыт, когда приходит первый человек, взявший ключи на ресепшене.
Забор данных из платформы производится по REST API. API платформы предоставляет возможность работы, взаимодействия и использования сущностей платформы и их данных в таких внешних системах, как веб-порталы, мобильные и веб-приложения или, как в нашем случае, - CRM системах.Посмотреть проект, в котором есть пример настройки взаимодействия и получения данных с платформы>>>Теперь мы знаем немного больше о том, как может работать СКУД в IoT-проектах. В следующих материалах рассмотрим, как рассчитать на базе полученной информации количество человек в офисе и какие практические применения есть у этой идеи.
===========
Источник:
habr.com
===========
Похожие новости:
- [Big Data, Разработка для интернета вещей] Вебинар «Создавайте больше деталей за меньшее время, отслеживая полезное время работы станков»
- [Обработка изображений, Microsoft Azure, Машинное обучение, Разработка для интернета вещей] Azure Custom Vision без Azure, или «где у них маска». Как мы распознавали маску на лице (и других частях тела)
- [Научная фантастика] Фантастические книги, которые вы могли пропустить в 2020 году
- [Законодательство в IT, Интернет вещей] Более 1 млн счётчиков в ЖКХ используют стандарт связи, который не входит в список одобренных Минсвязью
- [Программирование, Отладка, Go, DevOps] Monitoring your application with distributed tracing so you actually know what it's doing
- [Веб-дизайн, Разработка веб-сайтов, Тестирование веб-сервисов, Веб-аналитика, Монетизация веб-сервисов] Revealed: 7 Top Web Development Companies & Trends for 2021
- [Умный дом, Интернет вещей, DIY или Сделай сам] Умный дом, опыт построения, бег по граблям (MajorDomo, Tasmota и Алиса)
- [Разработка под Android, Производство и разработка электроники, Процессоры, Интернет вещей] Компания T-Head собрала порт Android 10 для процессоров архитектуры RISC-V
- [Информационная безопасность, C++, C, Разработка для интернета вещей] Espressif IoT Development Framework: 71 выстрел в ногу
- [Информационная безопасность, C++, C, Разработка для интернета вещей] Espressif IoT Development Framework: 71 Shots in the Foot
Теги для поиска: #_razrabotka_dlja_interneta_veschej (Разработка для интернета вещей), #_internet_veschej (Интернет вещей), #_iot, #_development, #_iot_razrabotka (iot разработка), #_iot_platforma (iot платформа), #_chitalnyj_zal (читальный зал), #_skud (скуд), #_pacs, #_umnyj_ofis (умный офис), #_blog_kompanii_rightech_iot_cloud (
Блог компании Rightech IoT Cloud
), #_razrabotka_dlja_interneta_veschej (
Разработка для интернета вещей
), #_internet_veschej (
Интернет вещей
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:11
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
И снова привет, мир!В прошлой статье про IoT-елочку в голосовании многие отметили, что интересна тема управления устройствами в зависимости от количества человек в помещении. Это довольно масштабная задача, и мы предлагаем разделить ее решение на несколько этапов. Сегодня поговорим о системе контроля управления доступом (СКУД), которая, будучи подключенной к платформе интернета вещей Rightech IoT Cloud (далее по тексту - платформа), является базовым элементом в системе подсчета количества человек в офисе. Мы уже поверхностно освещали этот кейс в одной из статей, но сегодня рассмотрим этот проект более подробно и погрузимся в особенности исполнения.СКУД?Система контроля и управления доступом, СКУД (англ. Physical Access Control System, PACS) — совокупность программно-аппаратных средств контроля и управления, главная цель которой - ограничение и регистрация входа-выхода объектов (людей, транспорта) на заданной территории через «точки прохода»: двери, ворота, КПП. С чего все началосьЗадача обеспечить контроль за входом-выходом в офисе возникла еще в те времена, когда у нас был выход на крышу с отличным видом на Москву, и поэтому часто приходили люди, не являющиеся нашими сотрудниками. Тогда мы решили принять какие-то меры по безопасности и установить СКУД. АрхитектураСистема открытия дверей по картеВ качестве модуля, отвечающего за обработку информации по считыванию бесконтактных карт, выбрали GATE-8000. Основные достоинства контроллера:
Внешний вид платы с контроллером Основной принцип работы: контроллер обрабатывает информацию, поступающую со считывателя, и с помощью встроенного реле коммутирует исполнительное устройство - электромагнитный замок двери. Система взаимодействия с платформойПосле того, как контроллер установили в систему по общей схеме подключения, а карты записали в память, мы уже обезопасили себя от прохода в офис посторонних. А дальше возник вопрос, как подключить этот контроллер к платформе Rightech ioT Cloud. Ведь очень здорово иметь а) графический интерфейс, в котором можно полистать историю всех проходов, б) возможность отправки команд на открытие двери удаленно, не отходя от рабочего места, например, для гостей или доставщика еды.У контроллера нет выхода в Интернет и видимой возможности подключения к платформе, к тому же все события нужно принудительно считывать из его циклического буфера. Однако у него есть свой протокол обмена данными с компьютером управления, благодаря которому можно отправлять на контроллер команды, такие как считать из контроллера, записать в контроллер, открыть/закрыть замок и другие. Значит, нужно сделать некоторую программно-аппаратную прослойку между контроллером и платформой - агента, который будет отправлять команды на чтение событий и управление контроллером. Обращаем внимание, что в данной архитектуре функция открытия двери при прикладывании карты не перестанет выполняться при отсутствии Интернета. За открытие двери и сбор информации отвечает контроллер СКУД, поэтому в случае потери Интернета, единственное, что нам грозит, - это то, что агент, который доставляет данные на платформу, не будет функционировать, так как не сможет получать команды на чтение буфера. Однако при восстановлении соединения все события считаются в полном объеме и не потеряются, так как они будут сохранены в буфере контроллера СКУД.▍Аппаратная частьДля начала нужно было выбрать устройство, которое будет всегда в активном состоянии с включенной программой-агентом в непосредственной близости от платы СКУД. Из многообразия микрокомпьютеров первое что попало под руку выбор пал на Raspberry Pi. Дальше возник вопрос, как подсоединить GATE-8000 к Raspberry - то есть как подключить последовательный интерфейс RS485 от GATE к USB от микрокомпьютера. Начались поиски переходника USB-RS485. Первый вариант, который мы испробовали, - Espada за 200 рублей. Надежда на то, что маленький хлипкий китайский переходник заработает, была небольшой. Он и не заработал. Вместо нужных данных приходило что-то похожее по виду и размеру, но… всё же не то. В чем было дело: в отсутствии гальванической развязки, невозможности поддерживать скорость 19200 bps или же просто в некачественной элементной базе, - загадка. Но после обращения к производителю GATE-8000, мы получили рекомендацию на более дорогой (в 10 раз) и громоздкий (но аккуратный и корпусированный) переходник Z-397, который заработал тут же как надо. ▍Программная частьНачинаем разработку программы с определения, какие функции она должна выполнять.
Карта памяти контроллера? WTF?Под картой памяти контроллера (термин из протокола) имеется в виду таблица с описанием заполнения регистров памяти, а не микрофлешка =). Следующая особенность работы с контроллером в том, что за один цикл чтения можно получить только 12 событий, по 8 байт на каждое. А на каждый проход человека в офис генерируется уже два события:1) найден ключ в банке ключей (банк ключей - еще один блок в распределенной памяти контроллера);2) состоялся проход (если он, конечно, состоялся). Ниже представлен фрагмент кода на С++, реализующий метод одного цикла чтения буфера. bool SerialPortInlet::readBufferCycle(unsigned short& bottom, unsigned short const& top, unsigned char& u_lowerBound,
unsigned char& l_lowerBound, std::vector<unsigned char>& readBuffer, std::string& result) { // Подсчет байтов, которые необходимо считать unsigned short byteCountTmp = top - bottom; BOOST_LOG_SEV(log_, logging::info) << "Need read " << byteCountTmp << " byte"; unsigned char byteCount; // За один цикл нельзя прочитать более 12 событий (96 байт) byteCount = byteCountTmp > 0x60 ? 0x60 : (unsigned char)byteCountTmp; BOOST_LOG_SEV(log_, logging::info) << "Read " << +byteCount << " byte"; // Описываем тело команды std::vector<unsigned char> body = {0x02, 0xA0, byteCount, u_lowerBound, l_lowerBound}; std::vector<unsigned char> command; // Получаем полный текст команды generateComplexCommand(command, Command::BYTE_CODE_READ, body); // Если не удалось по каким-то причинам отправить команду (например, конечное устройство не подключено), возвращается false if (!sendCommand(command, result)) { return false; } // Иначе отправляем ответ с устройства на парсинг по событиям SerialPortType::Answer answerEvents; if(!Parsers::parserAnswer(log_, result, answerEvents, Command::BYTE_CODE_READ)) { BOOST_LOG_SEV(log_, logging::error) << "Failed parse buffer reading"; return false; } readBuffer.insert(readBuffer.end(), answerEvents.body.begin(), answerEvents.body.end()); // Сдвигаем нижнюю границу буфера для чтения следующих событий bottom = bottom + byteCount; u_lowerBound = (unsigned char)(bottom >> 8) ; l_lowerBound = (unsigned char)bottom; return true; } Пример байтстаффинга из документацииПолная структурная схема разработанной системы выглядит так. Работоспособность всех устройств было очень удобно проверять с помощью графического последовательного терминала СuteCom. После успешного тестирования программа была поставлена на автозапуск, а Raspberry отправилась жить на потолке рядом с платой СКУДа. Один делает, другой смотрит, третий фотографирует, огнетушитель придерживает дверь - настоящая командная работа =)Работа на платформе Rightech IoT CloudМодельОсновные данные с контроллера - это события, на платформу они приходит в формате JSON и включают в себя поля
Посмотреть оригинал >>>Возможные события:
Интерфейс истории журнала объектаПосмотреть оригинал >>> Интерфейс командУра, теперь, собравшись на кухне офиса в ожидании пиццы на праздник, можно никуда не идти, а просто открыть мобильное приложение и нажать кнопку открытия двери для курьера! АвтоматМожно заметить, что есть команда не только на чтение буфера событий, но и на запись новых границ. В памяти контроллера хранятся границы буфера - начало и конец. Когда на устройство приходит команда чтения, из памяти берутся эти границы и в их пределах происходит чтение из буфера событий. Граница конца буфера сдвигается автоматически на контроллере при получении новых событий. А вот начальную границу буфера нужно перезаписать (указав конечную границу после прошедшего чтения), чтобы не прочитать одни и те же данные повторно. Но это необходимо сделать только после того, как данные о событиях успешно отправлены на платформу. Зафиксировать успешное получение данных и затем отправить команду на перезапись начальной границы удобно в автомате. Посмотреть оригинал >>>Здесь виден цикл <чтение>-<запись новой границы буфера>-<ожидание таймера> (сейчас события считываются каждые 30 секунд).
Также отображается время входа/выхода из офиса, считается суммарное количество часов в месяц. Посмотреть оригинал >>> В мессенджер Slack каждый день пишется о том, что офис открыт, когда приходит первый человек, взявший ключи на ресепшене. Забор данных из платформы производится по REST API. API платформы предоставляет возможность работы, взаимодействия и использования сущностей платформы и их данных в таких внешних системах, как веб-порталы, мобильные и веб-приложения или, как в нашем случае, - CRM системах.Посмотреть проект, в котором есть пример настройки взаимодействия и получения данных с платформы>>>Теперь мы знаем немного больше о том, как может работать СКУД в IoT-проектах. В следующих материалах рассмотрим, как рассчитать на базе полученной информации количество человек в офисе и какие практические применения есть у этой идеи. =========== Источник: habr.com =========== Похожие новости:
Блог компании Rightech IoT Cloud ), #_razrabotka_dlja_interneta_veschej ( Разработка для интернета вещей ), #_internet_veschej ( Интернет вещей ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:11
Часовой пояс: UTC + 5