2017-03-01 82 views
1

我试图编写一个菜单栏应用程序来通过Mac控制我的灯光。 我使用的是milight (limitless, easybulbs...)的系统。 他们有一个开放的系统,你可以通过UDP发送命令。发送UDP数据包的问题(milight,limitlessled)

我可以通过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)) 
} 

当我比较这与该pythonlibrary的复杂程度我敢肯定,我忘记一些重要的事情。我还没有和网络合作过,所以对我很宽容。

感谢和问候。

回答

3

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

之前发送您的lighton要求你必须发送到获得第一个请求时,无线桥接器会话。您还需要根据您的请求来计算Milight称为“校验和”的内容。

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

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

检查出来:https://github.com/winosaure/MilightAPI

UPDATE:

据limitlessled “文档”(http://www.limitlessled.com/dev/),这是一个请求是如何组成:

UDP十六进制发送格式:80 00 00 00 11 {WifiBridgeSessionID1} {WifiBridgeSessionID2} 00 {序列号} 00 {命令} {区号} 00 {校验和}

这就是为什么您必须首先获得wifibridge会话,然后您需要计算校验和。

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

文档说:

31 00 00 08 04 01 00 00 00 =光ON

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。

SEND十六进制字节: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 < - 发送给的所述IP地址 无线网桥V6

这就是为什么我这样做:

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开始计数,因此您必须采取类似于“响应[19]”和“响应[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} {区号码}和{}校验

什么是“序列号”?

的医生说:

连续字节只是保持命令以正确的顺序, 帮助,它可以帮助忽略已经收到重复的数据包。每个新命令的这个字节增加 。

因此,把你想要的和增加这个值为1为每个请求。 (Personnally我总是发送0x01)。

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

有效列表为{ZONE NUMBER} 0×00全0×01 1区2区0×02×03 3区0×04 zone4中

比方说,我们的 “区” 为0x01。

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

的医生说:

取9个字节的命令,并且所述区的1个字节,并添加0 =校验=(校验&为0xFF)例如SUM((31 00 00 08 04 01 00 00 00)(命令)01(区)00)= 3F(CHKSUM)

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

我添加的命令的所有字节(打开)+ 0×01为+ 0×00

所以现在我们所拥有的一切和完整的请求区打开灯:

就是这样。

注意:不要只是复制和粘贴请求,我根据示例计算值,开启灯光的请求将根据您将要计算的内容每次更改。

也许你已经注意到我写了“00 31 00 00 08 04 01 00 00 00”做“打开”命令,这只适用于CW灯泡。本文件并不指定... 武威灯泡相同的命令是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灯泡”方面的专家,我无法解释更多,我不知道为什么我们需要为两者写出不同的要求。

无论如何,我希望我足够清楚。 让我知道事情是如何工作的。

+0

永远不要迟到!仍在研究这个项目!我所有的灯泡都是WW Wheres的区别?在你的代码中你也使用WW,所以我可以正确使用它们吗?你能解释更多吗?我如何获得Bridgesession以及为什么需要校验和,即所有接收字节的总和!? – kuemme01

+0

我更新了我的评论,以更详细地解释我做了什么。 – wilfleaji

+0

男人你这样一个好人!这很完美!我还没有解决它,因为我必须弄清楚如何使用我正在使用的UDP库接收数据,我认为它不可能,所以我必须搜索另一个。我会尽快更新你的!非常感谢!它不能被更好地解释! – kuemme01