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

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

Время на прочтение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 в статье несуществующие.
Теги:
Хабы:
Всего голосов 24: ↑22 и ↓2+20
Комментарии30

Публикации

Истории

Работа

Data Scientist
84 вакансии
Python разработчик
130 вакансий
React разработчик
56 вакансий

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

19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн