【问题标题】:Problems with sending UDP packets (milight, limitlessled)发送 UDP 数据包的问题(轻微,无限)
【发布时间】:2017-03-01 15:18:38
【问题描述】:

我尝试编写一个菜单栏应用程序来通过 Mac 控制我的灯。 我正在使用milight (limitless, easybulbs...)的系统。 他们有一个开放的系统,你可以通过 UDP 发送命令。

我可以通过python中的python-limitless库来控制我的灯,所以我知道IP和端口等网络是正确的。

所以我认为我对这个从未使用过的 UDP 东西做错了什么。 我正在尝试使用 SwiftSocket 库来发送我的命令,但没有任何反应,我已经尝试了 2 天。

这是我正在尝试的:

let host = "192.168.2.102"
let port = 5987

var client: UDPClient!

@IBAction func lightOn(_ sender: NSButton) {

    let bridgeon: [UInt8] = [0x31, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01]
    let rgbwon: [UInt8] = [0x31, 0x00, 0x00, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0]

    print("Licht an")
    print(client.send(data: bridgeon))
    sleep(1)
    print(client.send(data: rgbwon))
    sleep(1)

}

@IBAction func lightOff(_ sender: NSButton) {
    print("Licht aus")
}

override func viewDidLoad() {
    super.viewDidLoad()

    client = UDPClient(address: host, port: Int32(port))
}

当我将此与 python 库的复杂性进行比较时,我确信我忘记了一些重要的事情。我还没有与网络合作过,所以请对我宽容。

谢谢和问候。

【问题讨论】:

    标签: swift macos sockets udp udpclient


    【解决方案1】:

    我有点晚了,但我希望它可以帮助你:

    在发送您的 lighton 请求之前,您必须发送第一个请求以获取 wifi 桥接会话。您还需要根据您的请求计算 Milight 所谓的“校验和”。

    您还要确定您拥有什么样的灯泡,是 WW 灯泡还是 CW?我被困了好几天,因为我发送了错误的请求..

    我做了一个实现,它在 php 中,但你可以在 Objective-C 中以同样的方式使用它。

    检查一下:https://github.com/winosaure/MilightAPI

    更新:

    根据无限的“文档”(http://www.limitlessled.com/dev/),这是请求的组成方式:

    UDP 十六进制发送格式:80 00 00 00 11 {WifiBridgeSessionID1} {WifiBridgeSessionID2} 00 {SequenceNumber} 00 {COMMAND} {ZONE NUMBER} 00 {校验和}

    这就是为什么你必须先获取 wifibridge 会话然后你需要计算校验和。

    让我举一个关于如何打开灯的例子。

    文档说:

    31 00 00 08 04 01 00 00 00 = 灯亮

    31 00 00 08 04 01 00 00 00 参考上面的{COMMAND}。

    到目前为止,完整的请求必须是:

    80 00 00 00 11 {WifiBridgeSessionID1} {WifiBridgeSessionID2} 00 {SequenceNumber} 00 31 00 00 08 04 01 00 00 00 {ZONE NUMBER} 00 {Checksum}
    

    现在让我们获取 Wifibridge 会话。文件说:

    要获得 WifiBridgeSessionID1 和 WifiBridgeSessionID2 发送这个 命令 UDP。

    发送十六进制字节:20 00 00 00 16 02 62 3A D5 ED A3 01 AE 08 2D 46 61 41 A7 F6 DC AF (D3 E6) 00 00 1E

    这就是我这样做的原因:

    private function getWifiBridgeSession()
        {
            $command = array (
                0x20,0x00, 0x00,
                0x00, 0x16, 0x02,
                0x62, 0x3A, 0xD5,
                0xED, 0xA3, 0x01,
                0xAE, 0x08, 0x2D,
                0x46, 0x61, 0x41,
                0xA7, 0xF6, 0xDC,
                0xAF, 0xD3, 0xE6,
                0x00, 0x00, 0x1E);
    
            return $this->sendCommand($command);
        }
    

    一旦你用这个命令发送一个 UDP 请求,你就会得到一个结果。 Wifi Bridge session1 指的是响应的第 20 个字节,WifiBridge Session2 指的是响应的第 21 个字节(不要忘记我们是从 0 开始计数的,所以你必须采取类似“response[19]”和“response [20]")。

    比方说,在发送这个请求后,我得到了这个响应:

    28 00 00 00 11 00 02 AC CF 23 F5 7A D4 69 F0 3C 23 00 01 05 00
    

    所以我的“WifiBridgesession1”是 0x05 而“Wifibridgesession2”是 0x00

    所以现在我们“打开”灯的请求是:

    80 00 00 00 11 0x05 0x00 00 {SequenceNumber} 00 31 00 00 08 04 01 00 00 00 {ZONE NUMBER} 00 {Checksum}
    

    所以现在我们需要找出 {SequenceNumber} {Zone Number} 和 {Checksum}

    什么是“序列号”?

    医生说:

    顺序字节只是有助于保持命令的正确顺序, 它有助于忽略已经收到的重复数据包。增量 每个新命令的这个字节加 1。

    所以放上你想要的,并为每个请求将这个值增加到 1。 (我个人总是发送 0x01)。

    “区域编号”是指您同步灯光的区域。

    {ZONE NUMBER} 的有效列表 0x00 全部 0x01 Zone1 0x02 Zone2 0x03 Zone3 0x04 Zone4

    假设我们的“区域”是 0x01。

    快完成了。我们现在只需要计算“校验和”。

    医生说:

    取命令的 9 个字节,区域的 1 个字节,加上 0 = 校验和 = (校验和 & 0xFF) 例如SUM((31 00 00 08 04 01 00 00 00)(command) 01(zone) 00) = 3F(chksum)

    所以我们命令的校验和是: 31+00+00+08+04+01+00+00+00+01+00 = 0x54

    我为区域添加命令的所有字节(打开)+ 0x01 + 0x00

    所以现在我们拥有了一切,打开灯的完整请求是:

    80 00 00 00 11 05 00 00 01 00 31 00 00 08 04 01 00 00 00 01 00 54

    就是这样。

    注意:不要只是复制粘贴请求,我是根据例子计算的值,每次开灯的请求都会改变,根据你的计算。

    也许你注意到我写了“00 31 00 00 08 04 01 00 00 00”来执行“打开”命令,这仅适用于CW灯泡。该文档没有指定... WW 灯泡的相同命令是 00 31 00 00 07 03 01 00 00 00 所以 WW 灯泡的完整命令是:

    80 00 00 00 11 05 00 00 01 00 31 00 00 07 03 01 00 00 00 01 00 54
    

    CW 和 WW 灯泡有什么区别? 我可以说 CW 指的是“冷白”,WW 指的是“暖白”。但由于我不是“led 灯泡”方面的专家,我无法解释更多,我也不知道为什么我们需要为两者编写不同的请求。

    无论如何,我希望我足够清楚。 让我知道情况如何。

    【讨论】:

    • 永远不会迟到!还在做这个项目!我所有的灯泡都是 WW 哪里有区别?在您的代码中,您还使用 WW 所以我可以使用它们对吗?你能解释更多吗?如何获得 Bridgesession,为什么需要校验和,即所有接收字节的总和!?
    • 我更新了我的评论以更详细地解释我做了什么。
    • 你真是个好人!这是完美的!我还没有解决它,因为我必须弄清楚如何使用我正在使用的 UDP 库接收数据,我认为这是不可能的,所以我必须搜索另一个。我会尽快更新你!到目前为止感谢!再好不过了!
    • 不客气!我对 swift 不太了解,不幸的是,我对此无能为力。我相信如果您能够从 UDP 读取数据,那么您已经完成了最困难的部分。我也被卡住了一段时间,因为limitlessled的文档不是很清楚
    • 是的,doku 太可怕了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 2011-11-22
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 2012-12-07
    相关资源
    最近更新 更多