IHClassControlManager.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. //
  2. // IHClassControlManager.swift
  3. // Inhealth
  4. //
  5. // Created by weclouds on 2020/8/19.
  6. // Copyright © 2020 weclouds. All rights reserved.
  7. //
  8. import UIKit
  9. import SwiftyJSON
  10. import PKHUD
  11. let KNotifiGetAllDeviceInforFromGateway = "KNotifiGetAllDeviceInforFromGateway"
  12. class IHClassControlManager: NSObject {
  13. lazy var mainView : IHClassControlView = {
  14. let mainView = IHClassControlView.init(frame: CGRect.init(x: 0, y: 0, width: KSCREENWIDTH, height: self.vc!.viewH!))
  15. mainView.backgroundColor = .white
  16. mainView.delegate = self
  17. return mainView
  18. }()
  19. private weak var vc : IHClassControlCtr?
  20. lazy var clientSocket: GCDAsyncUdpSocket? = {
  21. var mainQueue = DispatchQueue.main
  22. var clientSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.global())
  23. return clientSocket
  24. }()
  25. var modelList = [gatewayInfor]()
  26. private var isReload = false
  27. func bindController(_ vc : UIViewController) {
  28. self.vc = vc as? IHClassControlCtr
  29. self.vc?.view.addSubview(mainView)
  30. //checksum(command: "12a15303011700")
  31. getAllDevice()
  32. }
  33. deinit {
  34. log.debug("IHClassControlManager销毁")
  35. clientSocket = nil
  36. }
  37. //viewWillAppear时执行
  38. func getClassDevice(isReload : Bool) {
  39. self.isReload = isReload
  40. //发送命令
  41. getAllDevice()
  42. }
  43. }
  44. extension IHClassControlManager{
  45. func scanUnAddDevice() {
  46. // a.Byte 0-1: sequence number, when replying back, module will have to repeat the same SEQ number.
  47. // b.Byte 2: 0x01
  48. // c.Byte 3: 0x00
  49. // Byte 4: CheckSum.
  50. //扫描没有添加的设置 -- 固定的指令
  51. //[0x12, 0xa1, 0x01, 0x00,0xb4] //返回 12 A1 01 05 01 (00 01 01 69) 25 - 面板灯
  52. //"12a1 01 05 01 0001010c c8" -- 黑板灯
  53. //添加设备 - 变化
  54. //[0x12, 0xa1, 0x02, 0x05,0x01,0x00,0x01,0x01,0x69,0x26]
  55. //"12a1 02 0301170100000000d1"
  56. //删除设备
  57. //[0x12, 0xa1, 0x03, 0x02,0x01,0x17,0xb7]
  58. //亮度(里面的值是变化的) --485灯
  59. //[0x12, 0xa1, 0x52, 0x03,0x01,0x17,0x00,0x20]
  60. //色温(里面的值是变化的) -- 485灯
  61. //[0x12, 0xa1, 0x53, 0x03,0x01,0x17,0x00,0x21]
  62. //情景开关 Switch Scenes Mode
  63. //[0x12, 0xa1, 0x57, 0x03,0x01,0x17,0x02,0x27]
  64. //亮度与色温 -- CW灯 -- 根据从网关里获取灯的类型
  65. //[0x12, 0xa1, 0x5A,0x04, 0x01,0x17,0x1e,0x1e,0x65]
  66. //设置情景模式
  67. //获取网关里的所有设备 - 固定
  68. //[0x12, 0xa1, 0x04, 0x00,0xb7]
  69. }
  70. // //计算checksum
  71. // private func checksum(command : String) -> String{
  72. // let str = command as NSString
  73. // let count = str.length / 2
  74. // var sum = 0x0
  75. // for i in 0..<count {
  76. // let subStr = str.substring(with: NSRange.init(location: i * 2, length: 2))
  77. // sum = sum + hexStringToInt(from: subStr)
  78. // }
  79. // //10进制转换成16进制 - 截取最后二位
  80. // let hexStr = String(sum,radix:16) as NSString
  81. // if hexStr.length > 1{
  82. // return hexStr.substring(with: NSRange.init(location: hexStr.length - 2, length: 2))
  83. // }else{
  84. // return "0\(hexStr)"
  85. // }
  86. //
  87. // }
  88. //
  89. // //16进制的字符串转换数字
  90. // func hexStringToInt(from:String) -> Int {
  91. // let str = from.uppercased()
  92. // var sum = 0
  93. // for i in str.utf8 {
  94. // sum = sum * 16 + Int(i) - 48 // 0-9 从48开始
  95. // if i >= 65 { // A-Z 从65开始,但有初始值10,所以应该是减去55
  96. // sum -= 7
  97. // }
  98. // }
  99. // return sum
  100. // }
  101. //发送命令
  102. private func getAllDevice(){
  103. do{
  104. // //不连接,直接发命令
  105. try clientSocket?.enableBroadcast(true)
  106. // //let wifiIp = getLocalIPAddressForCurrentWiFi()
  107. // //第二次就不用了,直接使用这个
  108. // try clientSocket?.bind(toPort: 37030)
  109. // //第一次要绑定interface,后面就不用了
  110. // //try clientSocket?.bind(toPort: 37030, interface: wifiIp)
  111. try clientSocket?.beginReceiving() // 0117-设备地址
  112. //[0x12, 0xa1, 0x52, 0x06,0x01,0x17,0x10,0x33]
  113. //"12a1 01 05 01 0001010c c8"
  114. //12a10203 011d 0400000000da
  115. // 用这个
  116. let bytes: [UInt8] = [0x12, 0xa1, 0x5B, 0x00,0x0E]
  117. let command: Data = Data.init(bytes: bytes, count: bytes.count)
  118. //warn如果返回多个网关,这里只显示第一个
  119. if self.vc?.gatewayList?.count ?? 0 > 0{
  120. clientSocket?.send(command, toHost: self.vc!.gatewayList!.first!.ip!, port:UInt16(self.vc!.gatewayList!.first!.port!)! , withTimeout: -1, tag: 0)
  121. }
  122. }catch{
  123. log.debug("绑定失败\(error)")
  124. }
  125. }
  126. // 获取当前wifi的IP地址
  127. func getLocalIPAddressForCurrentWiFi() -> String? {
  128. var address: String?
  129. // get list of all interfaces on the local machine
  130. var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
  131. guard getifaddrs(&ifaddr) == 0 else {
  132. return nil
  133. }
  134. guard let firstAddr = ifaddr else {
  135. return nil
  136. }
  137. for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
  138. let interface = ifptr.pointee
  139. // Check for IPV4 or IPV6 interface
  140. let addrFamily = interface.ifa_addr.pointee.sa_family
  141. if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
  142. // Check interface name
  143. let name = String(cString: interface.ifa_name)
  144. if name == "en0" {
  145. // Convert interface address to a human readable string
  146. var addr = interface.ifa_addr.pointee
  147. var hostName = [CChar](repeating: 0, count: Int(NI_MAXHOST))
  148. getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostName, socklen_t(hostName.count), nil, socklen_t(0), NI_NUMERICHOST)
  149. address = String(cString: hostName)
  150. }
  151. }
  152. }
  153. freeifaddrs(ifaddr)
  154. return address
  155. }
  156. }
  157. extension IHClassControlManager:GCDAsyncUdpSocketDelegate{
  158. func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
  159. log.debug("didNotConnect")
  160. }
  161. func udpSocket(_ sock: GCDAsyncUdpSocket, didConnectToAddress address: Data) {
  162. log.debug("didConnectToAddress:\(String(data: address, encoding: String.Encoding.utf8))")
  163. }
  164. func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
  165. // //十进制数组
  166. // let bytes: [UInt8]? = [UInt8](data)
  167. // var str : String = ""
  168. // for byte in bytes! {
  169. // //十进制转换成16进制字符串
  170. // var s = String(byte,radix:16)
  171. // if s.count == 1{
  172. // s = "0" + s
  173. // }
  174. // str = str + s
  175. // }
  176. //扫描未添加的设备
  177. //foundDevice(respondStr: str)
  178. let str = dataConvertToHexString(data: data)
  179. //扫描网关返回的设备(带地址)
  180. getDeviceFromGateway(respondStr: str)
  181. //从网关中删除设备
  182. //deleteDevieFromGateway(respondStr: str)
  183. //添加设备到网关
  184. //addDeviceToGateway(respondStr: str)
  185. //调节CW灯的亮度与色温
  186. // adjustLampBrightnessAndColor(respondStr: str)
  187. log.debug("didReceive获取所有的设备:\(str)")
  188. }
  189. //调节CW灯的亮度与色温
  190. func adjustLampBrightnessAndColor(respondStr: String){
  191. //"12a1 5a 03 0117 0028"
  192. let str = respondStr as NSString
  193. let componeStr = str.substring(with: NSRange.init(location: 12, length: 2))
  194. if componeStr == "00" {
  195. //成功
  196. log.debug("调节成功")
  197. }else{
  198. //失败
  199. log.debug("调节失败")
  200. }
  201. }
  202. //添加设备到网关
  203. func addDeviceToGateway(respondStr: String){
  204. //没有判断的条件
  205. }
  206. //从网关中删除设备
  207. func deleteDevieFromGateway(respondStr: String) {
  208. //"12a1 03 02 0117 d0"
  209. //如果 Address == 0117 相等的就成功
  210. }
  211. //扫描网关返回的设备
  212. func getDeviceFromGateway(respondStr : String) {
  213. let str = respondStr as NSString
  214. //"12a1 04 04 01 0117 01 d5"
  215. let componeStr = str.substring(with: NSRange.init(location: 8, length: 2))
  216. let check = str.substring(with: NSRange.init(location: 4, length: 2))
  217. //Found Device Count.
  218. var deviceArr = [(address : String ,type : String,location : String)]()
  219. if componeStr == "00" && check == "5b"{
  220. log.debug("没有发现添加的设备")
  221. }else{
  222. //如果 componeStr 是大于或等于01,里面可能是多个了
  223. for i in 0..<Int(componeStr)! {
  224. let deviceAdress = str.substring(with: NSRange.init(location: 10 + i * 8, length: 4))
  225. let deviceType = str.substring(with: NSRange.init(location: 14 + i * 8, length: 2))
  226. let deviceLocation = str.substring(with: NSRange.init(location: 16 + i * 8, length: 2))
  227. deviceArr.append((address : deviceAdress,type : deviceType,location:deviceLocation))
  228. }
  229. }
  230. if self.isReload == true{
  231. //切换页面时
  232. NotificationCenter.default.post(name: NSNotification.Name(KNotifiSwitchScenseMode), object: nil, userInfo: ["isfail":true,"devicesInfor" : deviceArr])
  233. }else{
  234. NotificationCenter.default.post(name: NSNotification.Name(KNotifiGetAllDeviceInforFromGateway), object: nil, userInfo: ["devicesInfor" : deviceArr])
  235. }
  236. }
  237. //扫描未添加的设备
  238. func foundDevice(respondStr : String) {
  239. let str = respondStr as NSString
  240. //"12 a1 01 01 00 b5"
  241. //12 A1 01 05 01 00 01 01 69 25
  242. let componeStr = str.substring(with: NSRange.init(location: 8, length: 2))
  243. //Found Device Count.
  244. if componeStr == "00" {
  245. log.debug("没有发现新设备")
  246. }else{
  247. //如果 componeStr 是大于或等于01,里面可能是多个了
  248. var deviceUUidArr = [String]()
  249. for i in 0..<Int(componeStr)! {
  250. let compone = str.substring(with: NSRange.init(location: 10 + i * 8, length: 8))
  251. deviceUUidArr.append(compone)
  252. }
  253. }
  254. }
  255. func udpSocket(_ sock: GCDAsyncUdpSocket, didSendDataWithTag tag: Int) {
  256. log.debug("didSendDataWithTag")
  257. }
  258. func udpSocketDidClose(_ sock: GCDAsyncUdpSocket, withError error: Error?) {
  259. log.debug("withError")
  260. }
  261. func udpSocket(_ sock: GCDAsyncUdpSocket, didNotSendDataWithTag tag: Int, dueToError error: Error?) {
  262. log.debug("didNotSendDataWithTag")
  263. }
  264. }
  265. extension IHClassControlManager : IHClassControlViewDelegate{
  266. //其它的模式 -//面板情景id绑定按键id
  267. func panelBindScenesAndKeyId(panel: (address: String, type: String, location: String), curtain: (address: String, type: String, location: String)?, lampLights: [(address: String, type: String, location: String)]?, classLights: [(address: String, type: String, location: String)]?, scenes: String, keyId: String) {
  268. IHClassControlService.share.setPanelBindSencesAndKeyId(panel: panel, curtain: curtain, scenes: scenes, keyId: keyId, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  269. // IHClassControlService.share.setPanenlAndAllLight(panelAddress: panel.address, lampLights: lampLights!, classLights: classLights!, scenes: scenes,keyId : keyId, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  270. }
  271. //全开/全关
  272. func switchScenesMode(panelAddress: String, lampLights: [(address: String, type: String, location: String)], classLights: [(address: String, type: String, location: String)], scenes: String,keyId : String) {
  273. if self.vc!.gatewayList?.count ?? 0 > 0 {
  274. IHClassControlService.share.setPanenlAndAllLight(panelAddress: panelAddress, lampLights: lampLights, classLights: classLights, scenes: scenes,keyId : keyId, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  275. //IHClassControlService.share.setSwitchScenesMode(address: address, scenes: scenes, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  276. }
  277. }
  278. //重新获取数据
  279. func getDeviceData() {
  280. getAllDevice()
  281. }
  282. //设置设置的位置
  283. func setDeviceLocation(device: (address: String, type: String, location: String)) {
  284. IHClassControlService.share.setAllDeviceLocation(device: device, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  285. }
  286. //面板情景id绑定按键id
  287. // func panelBindScenesAndKeyId(panel: (address: String, type: String, location: String), curtain: (address: String, type: String, location: String)?, scenes: String, keyId: String) {
  288. // IHClassControlService.share.setPanelBindSencesAndKeyId(panel: panel, curtain: curtain, scenes: scenes, keyId: keyId, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  289. // }
  290. //窗帘的开关
  291. func controlCurtainTurnOn(panel : (address : String ,type : String,location : String),curtainDevice: (address: String, type: String, location: String), scenes: String) {
  292. //先绑定后再提示开关
  293. IHClassControlService.share.setPanelBindSencesAndKeyId(panel: panel, curtain: curtainDevice, scenes: scenes, keyId: "5", ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  294. }
  295. //操作模式
  296. // func switchScenesMode(address: String, scenes: String) {
  297. // if self.vc!.gatewayList?.count ?? 0 > 0 {
  298. // IHClassControlService.share.setSwitchScenesMode(address: address, scenes: scenes, ip: self.vc!.gatewayList![0].ip!, port: self.vc!.gatewayList![0].port!)
  299. // }
  300. //
  301. // }
  302. func pushToLightCommandVC(ShoolDevice: (address: String, type: String, location: String)) {
  303. self.vc?.bottomView!.isHidden = true
  304. let lightVC = IHLightCommandCtr()
  305. //warn
  306. lightVC.gateway = self.vc?.gatewayList?[0]
  307. lightVC.schollDeviceInfor = ShoolDevice
  308. self.vc?.navigationController?.pushViewController(lightVC)
  309. }
  310. }