Управляем чем угодно откуда угодно

[remote][лисапед] Еще одна управлялка.

Обсуждение линуксовой части и софта на борту виртурилки

[remote][лисапед] Еще одна управлялка.

Сообщение nwnclv » 27 сен 2014, 20:42

Приветствую всех.

Накидал очередную управлялку железкой.

Написано все на С++, пользуется библиотека vtrc, которую я тут не так давно выкладывал. Рабочее название проекта - ferro-remote.
GitHub: https://github.com/newenclave/ferro-remote ; для сборки нужна собранная либа vtrc: https://github.com/newenclave/vtrc
Собранный сервер и клиент для v2r, а так же консольный клиент для win можно взять тут

Проект разделен на 3 части:

  • Protocol - описание протокола; состоит только из файлов *.proto
  • Server - собссно сам процесс-сервер, который умеет работать на стороне v2r и предоставлять сервисы для управления
  • Client-core - библиотека, которая умеет соединяться и пользоваться сервисами сервера, предоставляя простые интерфейсы.
  • + в состав проекта входит console-client (построен на client-core), который сделан для проверки работоспособности. Клиент консольный, потому как с GUI я не очень умею.

Сервер может работать на 1 потоке или нескольких (задается из командной строки) + запускает еще один поток для нотификаций, который обрабатывает открытые файлы (к которым относятся и GPIO).

Пока сервер (а соответственно и клиент) предоставляет возможности:
  • Получить доступ к файловой системе. То есть возможность работы с каталогами (создавать, удалять, итерировать содержимое, получать информацию или статистику (man 2 stat) о файловом элементе), возможность работы с файлами (открывать, создавать, читать, писать, ждать асинхронные события).
  • Предоставляет интерфейс работы с GPIO (на стороне сервера это делается через sysfs). Можно поменять параметры, получить параметры, поменять и получить значение, подписаться на событие изменения значения (не все пины такое поддерживают)
  • Сделать вызов system("...") на стороне v2r. Штука хоть и удобная, но довольно опасная, потому как долгая
  • ...пока все. Никаких девайсов у меня нет, так что интерфейсов для их управления пока тоже нет.

Тут небольшие примеры:
На стороне v2r сервер запустить можно так:
Код: Выделить всё
./ferro_remote_server -s 0.0.0.0:12345 -o

Это запустит сервер на 1 потоке, который будет и принимать соединения и обрабатывать запросы. Ну и + поток-реактор.
Если запускать без -o, то будет уже 3 потока. Один из них будет заниматься исключительно вызовами клиента, второй только системными событиями. Третий, опять же, реактор.

Далее приведу пример вызовов консольного клиента и код этих вызовов.
¡Работа консольного клиента разделена на, так называемые, командные блоки! Доступ к каждому блоку осуществляется ключем -c (или --command) параметр принимает имя блока, после этого исполняется этот блок со всеми остальными параметрами. Список блоков можно получить
Код: Выделить всё
 % ./ferro_remote_client -h

Пока их всего 3: fs, gpio, os

ключ -s указывает адрес и порт сервера

OS
Начнем с самого простого.
Пока тут только одна команда --exec (она же -e)
Код: Выделить всё
 ./ferro_remote_client -s 192.168.3.1:12345 -c os -e "echo -e 'Hello, world' > test.txt"

Выполнит system("echo -e 'Hello, world' > test.txt") на стороне v2r
Исходник этого модуля тут. Весь модуль это всего 2 строки:
Код: Выделить всё
std::unique_ptr<os::iface> inst(os::create(client)); // создали интерфейс
inst->execute( cmd ); // выполнили команду.


FS
Если мы хотим, например, получить листинг каталога /dev, то команда:
Код: Выделить всё
./ferro_remote_client -s 192.168.3.1:12345 -c fs -l /dev

Покажет все пути в данной директории.
Код С++ итерации директории выглядит вот так
Код: Выделить всё
std::unique_ptr<fs::iface> i( fs::create( cl, path ) ); /// получили интерфейс
for( auto &d: *i ) {             // проитерировали 
    std::cout << d.path << "\n"; // показали путь элемента
}


Клиентом можно слить файл с, либо залить файл на. для этого есть ключи --pull и --push
Код: Выделить всё
./ferro_remote_client -s 192.168.3.1:12345 -c fs --pull=/home/default/data.file -O /home/user/data.file

Сольет файл с v2r в /home/user/data.file локальной машины

Код: Выделить всё
./ferro_remote_client -s 192.168.3.1:12345 -c fs --push=/home/user/data.file -O  /home/default/data.file

Зальет файл /home/user/data.file на v2r в /home/default/data.file
В C++ это выглядит почти как работа с локальными файлами; Пример скачивания файла:
Код: Выделить всё
std::unique_ptr<fsf::iface> iimpl(fsf::create( cl, remote_path, fsf::flags::RDONLY ) );
std::ofstream out(local_path, std::ofstream::out);
std::vector<char> buf(4096);
while( size_t r = iimpl->read( &buf[0], buf.size( ) ) ) { // iimpl->read удаленный вызов
    out.write( &buf[0], r );
}


Код: Выделить всё
% ./ferro_remote_client -s 192.168.3.1:12345 -c fs -W "set gpio 50 output 1" -O /dev/v2r_gpio

Запишет строку в файл.
Исходник этого модуля тут тут

GPIO
Модуль GPIO консольного клиента умеет немного пока. Делал его для теста модуля GPIO на стороне сервера. Умеет одну интересную вещь: подписываться на изменения состояния пина, который настроен на input. Пин должен поддерживать прерывания. Это пины gpio 1-7, на виртурилке, если не ошибаюсь.

допустим у нас есть пин 3, который настроен на такое и к нему подключен другой пин, который настроен на out и установлен в 1. Они соединены кнопкой.
выполняем
Код: Выделить всё
 % ./ferro_remote_client -s 192.168.3.1:12345 -c gpio -I3 -t-1

параметр -t-1 говорит клиенту ждать бесконечно

Эта команда позволяет подписаться на изменение состояния пина GPIO3, как только состояние меняется, мы получаем асинхронное событие (за это отвечает тот самый реактор, который крутится в своем потоке-песочнице). Теперь, когда изменяется состояние пина, клиент нам об этом скажет:
Код: Выделить всё
New value for 3 = 0
New value for 3 = 1
New value for 3 = 0
New value for 3 = 1
New value for 3 = 0


Дальше можно распространить это состояние на другие пины. Например на 22 пине у меня есть диод (как на картинке), тогда команда
Код: Выделить всё
 % ./ferro_remote_client -s 192.168.3.1:12345 -c gpio -I3 -O22 -t-1

при изменении состояние пина 3 поменяет состояние пина 22, и засветит диод. параметров -O в этом случае может быть несколько. тогда при нажатии кнопки клиент поменяет состояние всех пинов.

Можно заставить клиента выводить состояние пина на консоль в бинарном виде, за это отвечает ключ -B, в этом случае, при изменении состояния пина клиент будет выкидывать на консоль 2 байта: 1 - номер GPIO, 2 - текущее состояние.

работа с GPIO в С++ выглядит вот так:
Код: Выделить всё
std::unique_ptr<igpio::iface> ptr( igpio::create( cli, inp ) ); // создали интерфейс для gpio input
ptr->export_device( ); //export
ptr->set_direction( igpio::DIRECT_IN ); // установили направление
ptr->set_edge( igpio::EDGE_BOTH );  // установили edge

igpio::value_change_callback cb( std::bind( // создали функцию-колбек
                    &event_cb,
                    std::placeholders::_1,
                    std::placeholders::_2 ));

ptr->register_for_change( cb ); // подписались на события изменения. Теперь при каждом изменении состояния будет вызвана функция event_cb


Исходники модуля тут

Вот так выглядит моя схемка GPIO50(out) -> GPIO3(in) через кнопку, GPIO22(out) ->GRND через диод.
Изображение

Пока все. Интерфейс для доступа к возможностям, которые дают драйвера v2r, пока не делал. Но их можно использовать через файловый клиент.

PS: доки для либы client-core тоже допишу, пока со временем не очень хорошо.
PPS: ./ferro_remote_client -s 192.168.3.1:12345 -q Остановит процесс удаленного сервера.
nwnclv
 
Сообщения: 67
Зарегистрирован: 22 авг 2014, 19:04

Вернуться в Софт на виртурилке - SDK, Linux, Github, программирование (C/C++ и др.)

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron