Python - 使用 Philips Hue Entertainment API通过 DTLS/PSK无法正确发送 XY 颜色值

如何解决Python - 使用 Philips Hue Entertainment API通过 DTLS/PSK无法正确发送 XY 颜色值

编辑以添加指向 github 存储库的完整类链接

https://github.com/EvillerBobUK/pyHue-BridgeLink-Example

需要您拥有 Philips Hue 硬件和各种 DTSL/PSK 软件包才能使示例工作


我正在用 Python 3 编写一个小程序,该程序在 RaspBerry Pi 上的 Ubuntu 中运行,以通过飞利浦 Hue 桥接器(版本 2)向智能灯发送指令。

该程序可在大多数模式下运行,除了一种(详情如下),所以我相信连接本身运行正常。我认为问题在于特定模式的数据报的构建 - 可能与根据文档在该模式下仅对 X 和 Y 浮点数使用 12 位分辨率的桥有关? - 但这是一个我真的不熟悉的领域,我就是看不出哪里出错了!

PH API 具有通过 https 发送指令的“标准”模式和使用 dtls/psk 通过 UDP 广播指令的“娱乐”模式。娱乐模式支持以 RGB 或 XY + 亮度发送数据,任一版本都相当于 3 x 16 位数据类型。 API 指南中的字节序是“Big-Endian(网络)”; BigEndian 和网络均已尝试并给出相同的结果。

RGB 以 0-254 之间的三个整数形式发送。

XY 作为 0.0-1.0 之间的两个浮点数发送。 API 文档似乎建议亮度应该作为 0-254 之间的整数发送,这不起作用。实验上,将它作为 0.0-1.0 之间的浮点数发送,按预期工作。

我正在使用从互联网某处抓取的一段代码来创建 DTS/PSK 连接和打包的结构(我真的在整个 DTLS/PSK/数据报方面苦苦挣扎),尽管它只是被使用如果我记得,代码中的RGB。根据我对 Philips Hue API 指南的理解,该结构以相同的方式构建和发送,只是更改了我所做的颜色空间标志和数据类型,所以理论上它应该可以工作?

如果我使用标准模式通过 https 发送指令 {"xy":[0.6915,0.3083],"bri":254},指示灯会按预期变成红色。

如果我使用娱乐模式通过 UDP 发送指令 [(3,255,0)],'RGB',指示灯会按预期变为红色,并且飞利浦 Hue API 调试 CLIP 工具会报告 "xy": [0.6915,0.3083]

如果我使用娱乐模式通过 UDP 发送指令 [(3,0.6915,0.3083,0.1)],'XYB',指示灯会变成非常白的蓝色,而飞利浦 Hue API 调试工具会报告 "xy": [0.2245,0.2065]

使用 0.0-1.0 之间的不同值似乎总是以某种淡蓝色结束。有一次,我运行了一个循环,它只是将数字推向各个方向并超出预期范围,这确实导致偶尔出现黄色、绿色和很少出现红色,但通常是当发送的值大大超出范围/负值时.这些深夜绝望的测试都没有被正确记录或指向我可以在结果中看到的任何类型的模式/逻辑!

对理解问题和解决问题的任何帮助将不胜感激!

从类中提取代码

class pyHue_BridgeLink:
    def __init__(self,bridgename=False,config=False):
        # self.broadcast is a class-level variable for holding the datagram packed struct.      
        self.broadcast = None

    # put is the function that takes the instructions and turns them into a https put request,# which is then sent to the bridge for forwarding to the appropriate light.
    def put(self,url,request,payload,sslverify=False):
        return requests.put(f"{url}{request}",json=payload,verify=sslverify).json() 

    # prepare_broadcast is the function that takes the instructions and turns them into a datagram,# which is then sent to the bridge (by a call elsewhere to send_broadcast) for broadcasting to the
    # entertainment light group.
    # Datatype 'e' is,I believe,a 16bit float.
    # Endian type > (BigEndian) and ! (network) have both been tried
    def prepare_broadcast(self,states,colourspace='RGB'): #colourspace = 'RGB' or 'XYB'
        if colourspace == 'XYB':
            cs = 0x01
            datatypes = ">BHeee"
        else:
            cs = 0x00
            datatypes = ">BHHHH"
        count = len(states)
        self.broadcast = bytearray([0]*(16+count*9))
        struct.pack_into(">9s2BB2BBB",self.broadcast,"HueStream".encode('ascii'),# Protocol Name (fixed)
                         0x01,0x00,# Version (=01.00)
                         0x00,# Sequence ID (ignored)
                         0x00,# Reserved (zeros)
                         cs,# Color Space (RGB=0x00,XYB=0x01)
                         0x00                          # Reserved (zero)
                         )
        for i in range(count):  # Step through each set of instructions in "states"
            struct.pack_into(datatypes,16 + i*9,# Type: Light
                             states[i][0],# Light ID
                             states[i][1],# Red/X
                             states[i][2],# Blue/Y
                             states[i][3]               # Green/Brightness
                             )

    # send_broadcast passes the prepared datagram held in self.broadcast to the socket
    # for sending via DTLS/PSK which is,as far as I can establish,some kind of witchcraft.
    def send_broadcast(self):
        if self.sock:
            self.sock.send(self.broadcast) 

    # prepare_and_send_broadcast is an intermediary function that,unsurprisingly,calls the
    # prepare_broadcast command above then calls the send_broadcast command. There are cases where the
    # self.broadcast packed struct will be sent at a different time to when it was prepared. This
    # function is used when both need to happen at the same time.
    def prepare_and_send_broadcast(self,colourspace='RGB'):
        self.prepare_broadcast(states,colourspace)
        self.send_broadcast()

示例用法

bl = pyHue_BridgeLink("BridgeOne")

# Using the standard API to send via https. This works correctly!
# Physical light turns red as expected.
# Philips Hue API Debug CLIP tool reports "xy": [0.6915,0.3083] as it should.
bl.put(bl.url,'lights/3/state',{"xy":[0.6915,"bri":254})

# Switching to Entertainment mode...
bl.enable_streaming()

# Using the entertainment API to stream RGB instructions via UDP. This works correctly!
# Physical light turns red as expected.
# Philips Hue API Debug CLIP tool reports "xy": [0.6915,0.3083] as it should.
bl.prepare_and_send_broadcast([(3,'RGB')

# Using the entertainment API to stream XY+Brightness instructions via UDP. This fails!
# Physical light turns a very whitish-blue.
# Philips Hue API Debug CLIP tool reports "xy": [0.2245,0.2065] which is very wrong.
bl.prepare_and_send_broadcast([(3,'XYB')

# Switching back out of Entertainment mode...
bl.disable_streaming()

编辑以添加指向 github 存储库的完整类链接

https://github.com/EvillerBobUK/pyHue-BridgeLink-Example

需要您拥有 Philips Hue 硬件和各种 DTSL/PSK 软件包才能使示例工作

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?