Перейти к основному содержимому

Протокол ArtNet

Art-Net является простой реализацией DMX512 протокола по UDP, в котором информация управления каналами передается в IP пакетах, как правило, по локальной сети(LAN), по технологии Ethernet. ArtNet является протоколом с обратной связью. Как правило в приборах работающих по ArtNet имеется функция ответа на принятые данные. Например прибор получил данные, и может отправить ответ, что он их получил.

ArtNet может передавать абсолютно всё, вплоть до файлов. Артнет может осуществлять передачу координат приборов, а также может передавать таймкод (адресно-временной код — цифровые данные о времени, записываемые и передаваемые совместно с изображением или звуком. Применяется для синхронизации различных медиа систем — звук, видео, свет и т.д.).

ArtNet устройства используют для коммутации между собой так называемые узлы. В качестве узлов могут выступать преобразователи Artnet в физический DMX512, либо световые приборы или оборудование, уже имеющее встроенный интерфейс Art-Net. В тоже время сервер может раздавать пакеты как всем узлам ArtNet, так и отдельно выбранным. В качестве Artnet сервера может служить компьютер со световым программным обеспечением или световая консоль.

Каждое пространство из 512 DMX каналов в протоколе Art-Net называется Universe. Каждый узел (устройство) может поддерживать максимум 1024 каналов DMX (2 Universe) на одном ip-адресе. Каждые 16 Universe объединяются в подсеть. Группа из 16 подсетей (256 Universe) образует сеть. Максимальное количество сетей — 128. Итого в протоколе Artnet количество узлов может достигать 32768 шт, каждый с 512 DMX каналами.

Адреса Артнет обычно используются в пределах 2.0.0.0/8, но и в обычных локальных сетях 192.168.1.0/255 работают без проблем.

Наглядная схема подключения устройств с использованием узлов представлена на рисунке 2:

Рисунок 1 – Множественное подключение устройств по ArtNet.

Примеры реализации

Задача 1

В стенде расположена светодиодная лента, управляемая с помощью протокола DMX. В свою очередь она соединена с USB-DMX контроллером, который подключен к одноплатному компьютеру (Jetson Nano).

Работать с USB-DMX контроллером можно двумя путями:

  1. через библиотеку на Python, запуская скрипты на одноплатном компьютере
  2. через API и веб-интерфейс

В этой лабораторной работе Вам предстоит пойти по второму (простому) пути.

Задача состоит в следующем:

  • получить цвет, который установлен на светодиодной ленте
  • рассчитать цвет, который дополнит исходный до белого (в RGB)
  • установить этот цвет на светодиодную ленту

Документация API: http://172.18.212.21:8085/docs

При выполнении задания в GitLab нужно использовать токен из переменной окружения `ACCESS_TOKEN`.

Итак, вначале нужно импортировать библиотеки необходимые для выполнения HTTP-запросов, обработки данных JSON и доступа к переменным окружения.

import requests
import json
import os

Далее создаем переменные, содержащие ссылку на страницу с методом по получению информации о цвете и отправке информации.

get_request_url = 'http://172.18.212.21:8085/api/v1/color' 
put_request_url = 'http://172.18.212.21:8085/api/v1/color'

Далее присваиваем переменной  token значение токена из среды Gitlab. Это значение появляется в момент выполнения кода в Gitlab. Этот токен нужен для заголовка запроса, чтобы идентифицировать клиента. Затем нужно получить ответ по данному запросу и конвертировать в формат json.

token = os.getenv('ACCESS_TOKEN')
headers = {"Authorization": "Bearer " + token, 'Content-Type': 'application/json'}
response = requests.get(get_request_url, headers=headers)
response_data = json.loads(response.text)
initial_color = response_data['color']

Далее значение цвета, полученного в шестнадцатеричного формате преобразуется в RGB с помощью функции hex_to_rgb(). Внутри функции создается пустой список для хранения значений RGB. Для каждой итерации код извлекает две шестнадцатеричные цифры из шестнадцатеричной строки и преобразует их в целое число с помощью int(hex[i:i + 2], 16). Полученное целое число добавляется к списку rgb. Наконец, функция возвращает кортеж, содержащий значения RGB. Таким образом, мы решили первую задачу.

def hex_to_rgb(hex):
    rgb = []
    for i in (0, 2, 4):
        x = int(hex[i:i + 2], 16)
        rgb.append(x)

    return tuple(rgb)

Далее для того, чтобы понять, какой цвет дополнит текущее значение до белого, нужно вспомнить, что белый цвет в RGB – это 255,255,255. Поэтому нужно просто вычесть из 255 значения каждого цвета. И чтобы впоследствие установить этот цвет на ленту создадим словарь с одной парой ключ-значение.

rgb = hex_to_rgb(initial_color[1:])
new_color = [255 - color for color in rgb]

put_request_data = {'color': new_color}

Чтобы отправить значение цвета на светодиодную ленту, воспользуемся функцией, отправляющей данные по ранее обозначенному адресу.

response = requests.put(put_request_url, data=json.dumps(put_request_data), headers=headers)

Весь код представлен ниже:

import requests
import json
import os

get_request_url = 'http://172.18.212.21:8085/api/v1/color' 
put_request_url = 'http://172.18.212.21:8085/api/v1/color'
token = os.getenv('ACCESS_TOKEN')
headers = {"Authorization": "Bearer " + token, 'Content-Type': 'application/json'}
response = requests.get(get_request_url, headers=headers)
response_data = json.loads(response.text)
initial_color = response_data['color']

def hex_to_rgb(hex):
    rgb = []
    for i in (0, 2, 4):
        x = int(hex[i:i + 2], 16)
        rgb.append(x)
    return tuple(rgb)

rgb = hex_to_rgb(initial_color[1:])
new_color = [255 - color for color in rgb]

put_request_data = {'color': new_color}

response = requests.put(put_request_url, data=json.dumps(put_request_data), headers=headers)

Задача 2

Данное задание нацелено на управление светодиодной лентой, поддерживающей протокол DMX, через DMX-контроллер. Взаимодействовать с ним можно посредством библиотеки на Python.

::: info Доступ к одноплатнику Jetson Nano осуществляется по ssh, который подключен к USB-DMX-контроллеру. IP-адрес для подключения по ssh: 172.18.212.22

:::

На вход программы подаётся цвет в формате RGB. Необходимо подсветить ленту этим цветом, запустив скрипт (написанный при помощи модуля udmx-pyusb) на jetson. Цвет подается программе как аргумент командной строки. Например: python solution.py 255 0 0

Для начала импортируем необходимые библиотеки. Модуль argparse позволяет разбирать аргументы, передаваемые скрипту при его запуске из командной строки, и даёт возможность пользоваться этими аргументами в скрипте. То есть речь идёт о том, что этот модуль позволяет предоставлять скрипту некие данные в момент его запуска, а этими данными скрипт сможет воспользоваться во время выполнения его кода.

from pyudmx
import pyudmx
import sys
import argparse

С использованием конструкции argparse.ArgumentParser(), создаётся объект parser. Далее, с помощью метода parser.add_argument(), описываются переменные red, green, blue. На следующем шаге в переменную args попадает результат разбора аргументов командной строки. То, что передано скрипту при запуске, теперь будет доступно в виде свойств red, green, blue объекта params. Также создается список color, содержащий RGB-значения, полученные из аргументов командной строки.

parser.add_argument('red')
parser.add_argument('green')
parser.add_argument('blue')
params = parser.parse_args(sys.argv[1:])
color = [int(params.red), int(params.green), int(params.blue)]

Подключаемся к контроллеру с помощью метода uDMXDevice. Создаем массив и заполняем его нулями. Далее присваиваем первым трем переменным значения каналов цвета. Затем с помощью метода send_single_value отправляем блок из 512 значений на контроллер. И закрываем соединение.

dev = pyudmx.uDMXDevice()`
dev.open()
cv = [0 for _ in range(0, 512)]
cv[0] = color[0]
cv[1] = color[1]
cv[2] = color[2]
sent = dev.send_multi_value(1, cv)
dev.close()

Весь код представлен ниже:

from pyudmx 
import pyudmx
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('red')
parser.add_argument('green')
parser.add_argument('blue')
params = parser.parse_args(sys.argv[1:])
color = [int(params.red), int(params.green), int(params.blue)]
dev = pyudmx.uDMXDevice()
dev.open()
cv = [0 for _ in range(0, 512)]
cv[0] = color[0]
cv[1] = color[1]
cv[2] = color[2]
sent = dev.send_multi_value(1, cv)
dev.close()

Вложения