Как стать автором
Обновить

Простой способ управления удалёнными устройствами

Время на прочтение 4 мин
Количество просмотров 23K
Что хотелось:

  • при завершении задачи в jenkins выводить уведомление на компьютере и как дополнение — вывести его на физический дисплей, подключенный к arduino;
  • интерфейс, который можно открыть на телефоне или планшете, для управления проигрывателем музыки на компьютере и видеоплеером на raspberry pi;
  • интерфейс, доступный снаружи локальной сети, для вывода значения с датчиков, установленных на arduino.

Что получилось:

  • клиент, запускаемый на устройстве, с декларацией методов на python;
  • RESTful api для запуска «методов»(картинка справа выведена через него);
  • «панели управления» с web-интерфейсом;
  • сервис для управления устройствами, методами и панелями.


Ссылки


Сервис — rdevic.es
Исходный код сервера — rdevices-server
Исходный код клиента — rdevices-client

Что внутри




rdclient — запускается на устройстве пользователя, декларирует методы, выполнят их по запросу с сервера и отправляет результат обратно. Написан на python. Изначально для связи с сервером хотелось использовать ØMQ, но для его установки пользователю потребуется собирать модуль. Поэтому используются обычные сокеты.

connector — демон получает запросы от API, отправляет их на клиентское устройство, получает результат, записывает его в базу и отправляет демон уведомлений. Написан на python и tornado. Для связи с API и сервисом уведомлений используется redis.

RESTfull API — получает запросы напрямую от пользователей или через «панели управления» и передаёт их connector'у. Написан на python, django и tastypie.

push notifications — демон получает уведомления о завершении выполнения методов от connector'а и передаёт их в «панели управления». Сделан для уменьшения количества запросов к API. Написан на python, tornado и sockjs.

dashboard — web-интерфейс для управления устройствами создаётся пользователем и хранится на сервере. Для разметки используется html, для скриптов — JavaScript, CoffeeScript или IcedCoffeeScript.

Как создать устройство


Для создания его вам потребуется установить pip и git, если они у вас не установлены.

И установить rdclient:
pip install -e git://github.com/nvbn/rdevices-client.git#egg=rdclient


Теперь нужно создать устройство через сайт и скопировать его uuid.

Для декларации устройства вам нужно создать python файл, например, device.py, унаследоваться от класса Device, декорировать методы с method(result, [arg1], [arg2], ..) и указать uuid в Meta.
Аннотация параметров и результата метода обязательна, но используется только в информативных целях.

Пример простого устройства:
from rdclient import Device, method

class MyDevice(Device):
    class Meta:
        uuid = 'DEVICE_UUID'
    
    @method('None')
    def print_123(self):
        print 123
    
    @method('int', a='int', b='int')
    def sum_a_and_b(self, a, b):
        return a + b


Теперь можно запустить клиент:
rdclient device.py

После этого на странице устройства появится краткая документация для его устройства.

Для некоторых приложений есть уже готовые миксины:


Использование API



Первым делом нужно создать ключ для доступа к API.

Все запросы должны быть в json или xml и это нужно явно указывать в заголовке, например:

Accept: application/json
Content-type: application/json


Для вызова метода нужно отправить POST-запрос на rdevic.es/api/v1/device_method_call?username=USERNAME&api_key=API_KEY с телом, содержащим объект(в json или xml):
{
    method: METHOD_NAME,
    device: DEVICE_UUID,
    request: {
        arg1: 'arg1Value',
        arg2: 'arg2Value'
    }
}

В ответ придёт:
{
    method_id: METHOD_ID,
    request: {
        arg1: 'arg1Value',
        arg2: 'arg2Value'
    },
    response: {},
    state: 0,
    text_state: 'started',
    id: CALL_ID,
    resource_uri: '/api/v1/device_method_call/CALL_ID/',
}

Обновлённую версию можно получить, сделав GET-запрос по адресу resource_uri?username=USERNAME&api_key=API_KEY. Результат вызова метода находится в поле response. Статус выполнения метода в state. Возможные значения:
STATE_CREATED = 0
STATE_FINISHED = 1
STATE_ERROR = 2

Запрос можно делать с curl:
curl "http://rdevic.es/api/v1/device_method_call/?username=nvbn&api_key=45932208bfb91d5ba8c9ab82137026c76ece69a8" -H "Accept: application/json" -H "Content-type: application/json" -X POST -d "{\"method\":\"arduino_write\",\"device\":\"bcc97caa-a09b-11e2-a15d-009c02975edf\",\"request\":{\"data\": \"clear\nwrite:Hello habr\!\n\"}}"

Результат его выполнения показан не первой картинке.

Создание приборной панели


Для начала вам нужно создать её на сайте и открыть редактирование кода.
Скрипты можно писать на JavaScript(type="javascript"), CoffeeScript(type="coffeescript") и IcedCoffeeScript(type="iced-coffeescript").
В них можно использовать dashboard api, оно предоставляет:
  • dashboard.ready(callback) — инициализация приборной панели;
  • dashboard.getDevice(deviceId, callback) — получить устройство в callback;
  • device.method(args, [callback]) — вызвать метод и получить результат в callback. args — объект, содержащий аргумент: значение аргумента.


Как пример панели — пульт для rhythmbox(миксин rdclient.mixins.RhythmboxMixin):
<script type='text/javascript'>
    dashboard.ready(function(){
        dashboard.getDevice(DEVICE_ID, function(device){
            $('#prev').click(function(){
                device.rhythmbox_previous({});
            });
            
            $('#next').click(function(){
                device.rhythmbox_next({});
            });
            
            $('#play-pause').click(function(){
                device.rhythmbox_play_pause({});
            });
        });
    });
</script>

<button class='btn' id='prev'>Prev</button>
<button class='btn' id='play-pause'>Play/pause</button>
<button class='btn' id='next'>Next</button>

Для избежания лесенки можно использовать IcedCoffeeScript. С ним часть со скриптом будет выглядеть так:
<script type='text/iced-coffeescript'>
    await dashboard.ready
    await dashboard.getDevice DEVICE_ID, defer device
    
    $('#prev').click =>
        device.rhythmbox_previous {}
    
    $('#next').click =>
        device.rhythmbox_next {}
    
    $('#play-pause').click =>
        device.rhythmbox_play_pause {}
</script>


Планы на будущее


Сейчас в проекте реализованы только базовые возможности. Ещё планируются:
  • event'ы на стороне устройства;
  • git репозитории с пользовательскими «панелями»;
  • ключи api с ограниченным доступом к устройствам и методом.


P.S. все ключи и uuid в статье несуществующие.
Теги:
Хабы:
+20
Комментарии 30
Комментарии Комментарии 30

Публикации

Истории

Работа

Data Scientist
66 вакансий
Python разработчик
136 вакансий
React разработчик
65 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн