Программа Python, управляющая контроллером Open DMXPython

Программы на Python
Ответить
Anonymous
 Программа Python, управляющая контроллером Open DMX

Сообщение Anonymous »

I wrote a program that controls an OpenDMX controller (Enttec OpenDMX controller), but I'm getting an error.

an error appears when selecting a target
Ошибка в цикле: 'OpenDMXController' object has no attribute 'set_channel'
Please help
Code:
import socket
import json
import struct
import math
import time
from PyDMXControl.controllers import OpenDMXController
# ==========================================
# 1. НАСТРОЙКИ ПОДКЛЮЧЕНИЯ
# ==========================================
# Мы подключаемся к stracker.py, который работает на этом же компьютере
SERVER_IP = '127.0.0.1'
SERVER_PORT = 65432
# ==========================================
# 2. НАСТРОЙКИ СЦЕНЫ И КАМЕРЫ
# ==========================================
# Важно! Расстояние от проектора до сцены (в сантиметрах)
DISTANCE_TO_STAGE = 300.0
# Разрешение камеры (нужно для поиска центра кадра)
# Обычно Jetson использует 1280x720. Если у вас другое - поменяйте.
CAMERA_WIDTH = 1280
CAMERA_HEIGHT = 720
# ==========================================
# 3. НАСТРОЙКИ КАНАЛОВ (ПО ВАШЕМУ ФОТО)
# ==========================================
# Таблица из инструкции:
# 1: Pan (Горизонт)
# 2: Pan Fine (Тонкая) - пропускаем
# 3: Tilt (Вертикаль)
# 4: Tilt Fine (Тонкая) - пропускаем
# 5: Color (Цвет)
# 7: Strobe (Строб)
# 8: Dimmer (Яркость)
CH_PAN = 1
CH_TILT = 3
CH_COLOR = 5
CH_STROBE = 7
CH_DIMMER = 8
# Максимальные углы поворота головы (обычно 540 и 270)
MAX_PAN_ANGLE = 540.0
MAX_TILT_ANGLE = 270.0
# ==========================================
# 4. ИНИЦИАЛИЗАЦИЯ DMX
# ==========================================
print("--- ЗАПУСК DMX КЛИЕНТА ---")
print("Поиск контроллера OpenDMX...")
try:
\# Инициализация контроллера Enttec Open DMX

dmx = OpenDMXController()

print("\>\> Контроллер успешно подключен!")

кроме исключения как e:
print(f"\>\> ОШИБКА подключения контроллера: {e}")

print("Проверьте, подключен ли USB кабель и есть ли права (sudo).")

exit()

def set_dmx_val(канал, значение):
"""Безопасная отправка значения (0-255)"""

safe_val = max(0, min(255, int(value)))

dmx.set_channel(channel, safe_val)

# ==========================================
# 5. ФУНКЦИИ СЕТИ (Чтение протокола stracker.py)
# ==========================================
def recvall(sock, n):
"""Помощник: читать ровно n байт"""

data = bytearray()

while len(data) \< n:

packet = sock.recv(n - len(data))

if not packet:

return None

data.extend(packet)

return data

def Recv_msg(sock):
"""Чтение сообщения с 4-байтовым заголовком длины (как в stracker.py)"""

\# 1. Читаем 4 байта (длина сообщения)

raw_msglen = recvall(sock, 4)

if not raw_msglen:

return None

\# 2. Распаковываем длину (big-endian integer)

msglen = struct.unpack('\>I', raw_msglen)\[0\]

\# 3. Читаем само сообщение

return recvall(sock, msglen)

# =======================================
# 6. МАТЕМАТИКА (Координаты -> Углы)
# ========================================================(c>def Calculate_dmx_gls(cam_x, cam_y):\# 1. Находим отклонение от центра кадра в пикселях

\# Если cam_x = 640 (центр), то offset_x = 0

offset_x = cam_x - (CAMERA_WIDTH / 2)

\# Инверсия Y (часто камеры видят верх как 0, а проекторы низ как 0)

\# Если нужно инвертировать движение по вертикали, поменяйте знак

offset_y = cam_y - (CAMERA_HEIGHT / 2)

\# 2. Считаем угол через арктангенс

\# math.atan возвращает радианы, переводим в градусы

angle_x = math.degrees(math.atan(offset_x / DISTANCE_TO_STAGE))

angle_y = math.degrees(math.atan(offset_y / DISTANCE_TO_STAGE))

\# 3. Переводим угол в DMX (0-255)

\# 128 - это центр (0 градусов)

pan_dmx = 128 + (angle_x \* (255 / MAX_PAN_ANGLE))

tilt_dmx = 128 + (angle_y \* (255 / MAX_TILT_ANGLE))

return int(pan_dmx), int(tilt_dmx)

# ==========================================
# 7. ОСНОВНОЙ ЦИКЛ
# ==========================================
def main():
while True:

try:

print(f"Подключение к stracker.py ({SERVER_IP}:{SERVER_PORT})...")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((SERVER_IP, SERVER_PORT))

print("\>\> Соединение установлено! Ожидание данных...")

while True:

\# Получаем JSON от stracker.py

data_bytes = recv_msg(s)

if not data_bytes:

print("Сервер закрыл соединение.")

break

\# Декодируем

json_str = data_bytes.decode('utf-8')

targets = json.loads(json_str) # Это список \[...\]

\# Проверяем, есть ли кого отслеживать

\# stracker.py отправляет список, нам нужен тот, у кого 'State' или просто первый

if len(targets) \> 0:

\# Берем первую цель из списка (обычно это TargetID)

target = targets\[0\]

x = target.get('CenterX', 0)

y = target.get('CenterY', 0)

state = target.get('State', 0) # 1 - красный (вкл), 0 - зеленый (выкл)

\# --- 1. Движение ---

pan, tilt = calculate_dmx_angles(x, y)

set_dmx_val(CH_PAN, pan)

set_dmx_val(CH_TILT, tilt)

\# --- 2. Управление светом ---

\# На фото: Ch7 Strobe, Ch8 Dimmer.

\# Чтобы светило: Strobe=0 (без мигания), Dimmer=255.

\# Чтобы выключить: Dimmer=0.

if state == 1:

\# ВКЛЮЧИТЬ (Красный режим в трекере)

set_dmx_val(CH_COLOR, 0) # Белый цвет (0-139)

set_dmx_val(CH_STROBE, 0) # Строб открыт/выключен

set_dmx_val(CH_DIMMER, 255)# Яркость на полную

else:

\# ВЫКЛЮЧИТЬ (Зеленый режим в трекере)

set_dmx_val(CH_DIMMER, 0)

set_dmx_val(CH_STROBE, 0)

dmx.render()

\# print(f"Target X:{int(x)} Y:{int(y)} | Pan:{pan} Tilt:{tilt} | Light: {'ON' if state else 'OFF'}")

else:

\# Если никого нет в кадре - ничего не делаем или выключаем свет

\# set_dmx_val(CH_DIMMER, 0)

\# dmx.render()

pass

except ConnectionRefusedError:

print("Не могу подключиться. stracker.py запущен? Повтор через 3 сек...")

time.sleep(3)

except Exception as e:

print(f"Ошибка в цикле: {e}")

time.sleep(1)

finally:

s.close()

if _name_ == "_main_":
main()


Подробнее здесь: https://stackoverflow.com/questions/798 ... controller
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»