Skip to main content

Hyperion 环境照明 Python 包

项目描述

海波龙标志

派皮 派皮 构建状态 测试覆盖率 执照 买我咖啡

海波图书馆

Hyperion-NG 的Python 库 。有关此库的输入和输出的更多详细信息,请参阅JSON API

安装

$ pip3 install hyperion-py

用法

数据模型哲学

虽然并非普遍适用,但该库试图精确表示Hyperion JSON 文档中定义的数据模型、API 和参数。因此,没有尝试(故意)以比模型已经支持的更精细的粒度级别呈现方便的访问器/调用。这是为了确保客户端有足够的机会保持功能,而不管服务器的底层数据模型如何更改,并且将更改与服务器的数据模型(例如新的 Hyperion 服务器功能)相匹配的责任属于调用者。

构造函数参数

以下参数可以传递给HyperionClient构造函数:

争论 类型 默认 描述
主持人 str 要连接的主机或 IP
港口 int 19444 要连接的端口
默认回调 callable 没有任何 Hyperion 回调的可调用对象。查看回调
回调 dict 没有任何 由更新名称键入的可调用字典。查看回调
令牌 str 没有任何 身份验证令牌
实例 int 0 连接时切换到的实例 ID
起源 str “hyperion-py” 描述调用应用程序的任意字符串
timeout_secs float 5.0 在放弃之前等待服务器响应或连接尝试的秒数。查看超时
重试秒数 float 30.0 连接尝试之间的秒数
原始连接 bool 错误的 如果为 True,则连接调用将建立网络连接但不尝试进行身份验证,切换到所需的实例或加载状态。客户端必须调用async_client_login登录、async_client_switch_instance切换到配置的实例并async_get_serverinfo手动加载状态。如果调用者希望在身份验证之前与服务器通信,这可能很有用。

连接、断开和客户端控制调用

  • async_client_connect(): 连接客户端。
  • async_client_disconnect(): 断开客户端。
  • async_client_login():登录已连接的客户端。async_client_connect()除非raw_connection构造函数参数为 True ,否则自动调用 。
  • async_client_switch_instance():切换到 Hyperion 服务器上配置的实例。async_client_connect()除非raw_connection 构造函数参数为 True ,否则自动调用。

原生 API 调用

所有 API 调用都可以在 client.py中找到。所有异步调用都以async_.

发送请求并等待响应 仅发送请求 文档
异步清除 async_send_clear 文档
async_image_stream_start async_send_image_stream_start 文档
async_image_stream_stop async_send_image_stream_stop 文档
async_is_auth_required async_send_is_auth_required 文档
async_led_stream_start async_send_led_stream_start 文档
async_led_stream_stop async_send_led_stream_stop 文档
异步登录 async_send_login 文档
异步注销 async_send_logout 文档
async_request_token async_send_request_token 文档
async_request_token_abort async_send_request_token_abort 文档
async_get_serverinfo async_send_get_serverinfo 文档
async_set_adjustment async_send_set_adjustment 文档
async_set_color async_send_set_color 文档
async_set_component async_send_set_component 文档
async_set_effect async_send_set_effect 文档
async_set_image async_send_set_image 文档
async_set_led_mapping_type async_send_set_led_mapping_type 文档
async_set_sourceselect async_send_set_sourceselect 文档
async_set_videomode async_send_set_videomode 文档
async_start_instance async_send_start_instance 文档
async_stop_instance async_send_stop_instance 文档
async_switch_instance async_send_switch_instance 文档
async_sysinfo async_send_sysinfo 文档

请注意,上述链接文档中显示的commandsubcommand键将自动包含在客户端发送的调用中,无需指定。

客户输入/输出

API 参数和输出都在JSON API 文档中定义。

示例用法:

#!/usr/bin/env python
"""Simple Hyperion client read demonstration."""

import asyncio

from hyperion import client, const

HOST = "hyperion"


async def print_brightness() -> None:
    """Print Hyperion brightness."""

    async with client.HyperionClient(HOST) as hyperion_client:
        assert hyperion_client

        adjustment = hyperion_client.adjustment
        assert adjustment

        print("Brightness: %i%%" % adjustment[0][const.KEY_BRIGHTNESS])


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(print_brightness())

在后台运行

后台asyncio task运行以处理所有连接后的入站数据(例如,请求响应,或来自服务器端状态更改的订阅更新)。此后台任务必须在连接后启动,或者启动(它自己会建立连接)。

可选地,此后台任务可以将回调回调给用户。

等待回复

如果用户进行了名称中没有的调用_send_(见上表),函数调用将等待响应并将其返回给调用者。这种请求和响应的匹配是通过tan参数完成的。如果未指定,客户端将自动附加一个tan整数,这将在返回的输出数据中可见。这种匹配对于区分由于请求的响应和来自订阅更新的“自发数据”是必要的。

示例:等待响应

#!/usr/bin/env python
"""Simple Hyperion client request demonstration."""

import asyncio

from hyperion import client

HOST = "hyperion"


async def print_if_auth_required() -> None:
    """Print whether auth is required."""

    hc = client.HyperionClient(HOST)
    await hc.async_client_connect()

    result = await hc.async_is_auth_required()
    print("Result: %s" % result)

    await hc.async_client_disconnect()


asyncio.get_event_loop().run_until_complete(print_if_auth_required())

输出:

Result: {'command': 'authorize-tokenRequired', 'info': {'required': False}, 'success': True, 'tan': 1}

示例:发送命令

发送命令的稍微复杂一点的示例(以给定的优先级清除 Hyperion 源选择,然后以相同的优先级设置颜色)。

#!/usr/bin/env python
"""Simple Hyperion client request demonstration."""

import asyncio
import logging
import sys

from hyperion import client

HOST = "hyperion"
PRIORITY = 20


async def set_color() -> None:
    """Set red color on Hyperion."""

    async with client.HyperionClient(HOST) as hc:
        assert hc

        if not await hc.async_client_connect():
            logging.error("Could not connect to: %s", HOST)
            return

        if not client.ResponseOK(
            await hc.async_clear(priority=PRIORITY)
        ) or not client.ResponseOK(
            await hc.async_set_color(
                color=[255, 0, 0], priority=PRIORITY, origin=sys.argv[0]
            )
        ):
            logging.error("Could not clear/set_color on: %s", HOST)
            return


logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
asyncio.get_event_loop().run_until_complete(set_color())

示例:启动和切换实例

下面的示例将启动一个停止的实例,等待它准备好,然后切换到它。使用回调,下面讨论。

#!/usr/bin/env python
"""Simple Hyperion client request demonstration."""

from __future__ import annotations

import asyncio
import logging
import sys
from typing import Any

from hyperion import client

HOST = "hyperion"
PRIORITY = 20


async def instance_start_and_switch() -> None:
    """Wait for an instance to start."""

    instance_ready = asyncio.Event()

    def instance_update(json: dict[str, Any]) -> None:
        for data in json["data"]:
            if data["instance"] == 1 and data["running"]:
                instance_ready.set()

    async with client.HyperionClient(
        HOST, callbacks={"instance-update": instance_update}
    ) as hc:
        assert hc

        if not client.ResponseOK(await hc.async_start_instance(instance=1)):
            logging.error("Could not start instance on: %s", HOST)
            return

        # Blocks waiting for the instance to start.
        await instance_ready.wait()

        if not client.ResponseOK(await hc.async_switch_instance(instance=1)):
            logging.error("Could not switch instance on: %s", HOST)
            return


logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
asyncio.get_event_loop().run_until_complete(instance_start_and_switch())

回调

客户端可以配置为在 Hyperion 服务器报告新值时进行回调。支持两类回调:

  • default_callback:当未指定更具体的回调时,将调用此回调。
  • 回调:以 Hyperion 订阅“命令”为键的回调字典(请参阅JSON API 文档

回调可以在HyperionClient构造函数(default_callback=callbacks=参数)中指定,也可以在构造之后通过 set_callbacks()andset_default_callback()方法指定。

如上所述,callbacksdict 以相关的 Hyperion 订阅为键 command(例如components-updatepriorities-update)。client-update客户端还使用以下形式的命令提供自定义回调:

{"command": "client-update",
 "connected": True,
 "logged-in": True,
 "instance": 0,
 "loaded-state": True}

这可用于在客户端与服务器连接或断开连接时采取特殊操作。

示例:回调

#!/usr/bin/env python
"""Simple Hyperion client callback demonstration."""

from __future__ import annotations

import asyncio
from typing import Any

from hyperion import client

HOST = "hyperion"


def callback(json: dict[str, Any]) -> None:
    """Sample callback function."""

    print("Received Hyperion callback: %s" % json)


async def show_callback() -> None:
    """Show a default callback is called."""

    async with client.HyperionClient(HOST, default_callback=callback):
        pass


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(show_callback())

输出,显示连接阶段的进展:

Received Hyperion callback: {'connected': True, 'logged-in': False, 'instance': None, 'loaded-state': False, 'command': 'client-update'}
Received Hyperion callback: {'connected': True, 'logged-in': True, 'instance': None, 'loaded-state': False, 'command': 'client-update'}
Received Hyperion callback: {'connected': True, 'logged-in': True, 'instance': 0, 'loaded-state': False, 'command': 'client-update'}
Received Hyperion callback: {'command': 'serverinfo', ... }
Received Hyperion callback: {'connected': True, 'logged-in': True, 'instance': 0, 'loaded-state': True, 'command': 'client-update'}

ThreadedHyperionClient

AThreadedHyperionClient也作为非异步代码的便利包装器提供。用ThreadedHyperionClient非异步版本包装异步调用(方法命名如上所示,除了不以 开头 async_)。

等待线程初始化客户端

线程必须有机会在与其交互之前初始化客户端。此方法调用将阻塞调用者,直到客户端被初始化。

  • wait_for_client_init()

线程客户端的示例使用

#!/usr/bin/env python
"""Simple Threaded Hyperion client demonstration."""

from hyperion import client, const

HOST = "hyperion"

if __name__ == "__main__":
    hyperion_client = client.ThreadedHyperionClient(HOST)

    # Start the asyncio loop in a new thread.
    hyperion_client.start()

    # Wait for the client to initialize in the new thread.
    hyperion_client.wait_for_client_init()

    # Connect the client.
    hyperion_client.client_connect()

    print("Brightness: %i%%" % hyperion_client.adjustment[0][const.KEY_BRIGHTNESS])

    # Disconnect the client.
    hyperion_client.client_disconnect()

    # Stop the loop (will stop the thread).
    hyperion_client.stop()

    # Join the created thread.
    hyperion_client.join()

输出:

Brightness: 59%

异常/错误

哲学

无论网络环境如何,HyperionClient 都力求不抛出异常,重新连接将在后台自动发生。仅在可能出现程序员错误的情况下(有意)引发异常。

超离子错误

不直接引发,但其他异常继承自此。

HyperionClientTanNotAvailable

tan如果向 API 调用提供了参数,但该 tan参数已被另一个正在进行的调用使用,则会引发异常。用户要么根本不指定tan(客户端库将以增量方式自动管理它),要么如果手动指定,则调用者有责任确保没有两个同时调用共享 a tan(否则客户端将无法将调用与响应相匹配,并且此异常将在调用之前自动引发)。

“任务已销毁,但未决!”

如果HyperionClient对象已连接但在断开连接之前已销毁,则可能会打印一条警告消息(“任务已销毁,但未决!”)。为避免这种情况,请确保始终async_client_disconnect在销毁连接的客户端之前调用。或者使用异步上下文管理器:

async with client.HyperionClient(TEST_HOST, TEST_PORT) as hc:
    if not hc:
        return
    ...

超时

客户端自由使用超时,可以在多个级别指定:

  • 在客户端构造函数参数timeout_secs中,用于连接和请求。
  • 在每个请求中使用timeout_secs单个调用的参数

超时值:

  • None:如果None用作超时,客户端将永远等待。
  • 0:如果0用作超时,将使用客户端默认值(在构造函数中指定)。
  • >0.0:将使用此秒数(或部分秒数)。

默认情况下,所有请求都将遵守timeout_secs客户端构造函数中指定的请求,除非显式覆盖并默认为 5 秒(请参阅const.py)。一个例外是async_send_request_token它具有更大的默认值(180 秒,请参阅const.py),因为此请求涉及用户需要在调用能够返回之前与 Hyperion UI 进行交互。

帮手

响应OK

提供了一些方便的可调用类来确定服务器响应是否成功。

  • ResponseOK:是否有任何 Hyperion 命令响应成功(一般)。
  • ServerInfoResponseOK: aasync_get_serverinfo是否成功。
  • LoginResponseOK: 是否async_login成功。
  • SwitchInstanceResponseOK:async_switch_instance命令是否成功。

示例用法

if not client.ResponseOK(await hc.async_clear(priority=PRIORITY))

身份验证 ID

请求身份验证令牌时,可以指定 5 个字符的 ID 以确保管理员用户正在授权来自正确来源的正确请求。默认情况下async_request_token会随机生成一个 ID,但如果需要允许用户确认匹配,则可以显式提供。在这种情况下,此辅助方法可用。

  • generate_random_auth_id:生成一个随机的 5 个字符的身份验证 ID,用于外部显示并包含在对async_request_token.

示例用法

auth_id  = hc.generate_random_auth_id()
hc.async_send_login(comment="Trustworthy actor", id=auth_id)
# Show auth_id to the user to allow them to verify the origin of the request,
# then have them visit the Hyperion UI.

项目详情