gateway.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. package gateway
  2. import (
  3. "confrontation-training/common"
  4. "confrontation-training/constant"
  5. errors "confrontation-training/err"
  6. "confrontation-training/global"
  7. "confrontation-training/http"
  8. "confrontation-training/models"
  9. "confrontation-training/models/gateway"
  10. "confrontation-training/response"
  11. "encoding/hex"
  12. "encoding/json"
  13. "fmt"
  14. "github.com/gin-gonic/gin"
  15. "io/ioutil"
  16. "strings"
  17. "time"
  18. )
  19. // ScanDevice
  20. // PingExample confrontation-training
  21. // @Summary 扫描设备
  22. // @Schemes
  23. // @Description 扫描设备
  24. // @Tags 设备管理
  25. // @Param device body string true "chip:芯片编号,1或1;filterName:0 脑电 1 心电;filterRssi:信号强度,小于0的整数,字符串格式传输;filterMac:过滤Mac地址,以","分割,如 61-Dg-89-22-39-3b,80-kD-0E-40-57-8A;filterType:1 表示已录入的设备"
  26. // @Accept json
  27. // @Produce json
  28. // @Success 200 {string} string "ok"
  29. // @Router /v1/device/scan [post]
  30. func ScanDevice(c *gin.Context) {
  31. var param gateway.DeviceScanParam
  32. err := c.ShouldBindJSON(&param)
  33. if err != nil {
  34. fmt.Printf("参数格式化异常:%s", err.Error())
  35. response.Failed(errors.ParamInvalid, c)
  36. return
  37. }
  38. paramMap := make(map[string]string)
  39. if param.Chip != "" {
  40. paramMap["chip"] = param.Chip
  41. }
  42. if param.FilterName != "" {
  43. //查询设备mac过滤信息
  44. filterMac := ""
  45. deviceInfos, count := GetDeviceService().DeviceService.FindDeviceByType(param.FilterName)
  46. if count > 0 {
  47. for i := range deviceInfos {
  48. filterMac += deviceInfos[i].Mac + ","
  49. }
  50. }
  51. if len(filterMac) > 0 {
  52. if strings.HasSuffix(filterMac, ",") {
  53. filterMac = filterMac[0 : len(filterMac)-1]
  54. }
  55. paramMap["filter_mac"] = filterMac
  56. }
  57. if param.FilterName == "0" {
  58. paramMap["filter_name"] = constant.FilterNameEEG
  59. } else if param.FilterName == "1" {
  60. paramMap["filter_name"] = constant.FilterNameECG
  61. } else {
  62. response.Failed(errors.ParamInvalid+":过滤类型-"+param.FilterName+"无效", c)
  63. return
  64. }
  65. } else {
  66. paramMap["filter_name"] = constant.FilterNameALL
  67. }
  68. if param.FilterRssi != "" {
  69. paramMap["filter_rssi"] = param.FilterRssi
  70. }
  71. if param.FilterMac != "" {
  72. paramMap["filter_mac"] = param.FilterMac
  73. }
  74. paramMap["active"] = "1"
  75. paramMap["event"] = "1"
  76. param.FilterType = "1"
  77. go SseScanDevice(paramMap, param.FilterType)
  78. response.Success("扫描完成", "", c)
  79. return
  80. }
  81. // ConnectDevice
  82. // PingExample confrontation-training
  83. // @Summary 连接设备
  84. // @Schemes
  85. // @Description 连接设备
  86. // @Tags 设备管理
  87. // @Param device body string true "chip:芯片编号,0或1;mac:Mac地址;addrType:地址类型 public/random "
  88. // @Accept json
  89. // @Produce json
  90. // @Success 200 {string} string "ok"
  91. // @Router /v1/device/connection [post]
  92. func ConnectDevice(c *gin.Context) {
  93. var param gateway.DeviceConnParam
  94. err := c.ShouldBindJSON(&param)
  95. if err != nil {
  96. fmt.Printf("参数格式化异常:%s", err.Error())
  97. response.Failed(errors.ParamInvalid, c)
  98. return
  99. }
  100. jsonParam, err := json.Marshal(param)
  101. if err != nil {
  102. fmt.Printf("参数转换异常:%s", err.Error())
  103. response.Failed("参数转换异常:%s"+err.Error(), c)
  104. return
  105. }
  106. url := global.Config.Gateway.BaseUrl + global.Config.Gateway.ConnUrl
  107. url = strings.Replace(url, "MAC", param.Mac, -1)
  108. if param.FilterName == "0" {
  109. url = strings.Replace(url, "chip", "chip=0", -1)
  110. } else if param.FilterName == "1" {
  111. url = strings.Replace(url, "chip", "chip=1", -1)
  112. }
  113. httpResponse := http.PostReqJson(url, jsonParam)
  114. status := httpResponse.StatusCode
  115. body, _ := ioutil.ReadAll(httpResponse.Body)
  116. if status != 200 {
  117. response.Failed(errors.DeviceConnectError+string(body), c)
  118. return
  119. }
  120. if param.FilterName == "1" {
  121. openChannelUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.OpenChannel
  122. openChannelUrl = strings.Replace(openChannelUrl, "MAC", param.Mac, -1)
  123. httpResponse = http.GetReq(openChannelUrl)
  124. if httpResponse.StatusCode != 200 {
  125. fmt.Printf("%s:%s", errors.OpenChannelError, httpResponse.Body)
  126. response.Failed(errors.OpenChannelError, c)
  127. return
  128. }
  129. }
  130. go StopScan(c.Writer, c.Request)
  131. response.Success(errors.DeviceConnectSuccess, param.Mac, c)
  132. return
  133. }
  134. // WriteData
  135. // PingExample confrontation-training
  136. // @Summary 写入数据——发送指令
  137. // @Schemes
  138. // @Description 写入数据——发送指令 ,ECG设备开启测试功能
  139. // @Tags 设备管理
  140. // @Param mac body string true "mac:设备MAC地址 userName:用户姓名 gender:性别 age:年龄 height:身高 weight:体重"
  141. // @Accept json
  142. // @Produce json
  143. // @Success 200 {string} string "ok"
  144. // @Router /v1/device/write/data/ [post]
  145. func WriteData(c *gin.Context) {
  146. var param models.WriteData
  147. err := c.ShouldBindJSON(&param)
  148. if err != nil {
  149. fmt.Printf("参数格式化异常:%s", err.Error())
  150. response.Failed(errors.ParamInvalid, c)
  151. return
  152. }
  153. userNameHex := hex.EncodeToString([]byte(param.UserName))
  154. //1 绑定用户指令
  155. //指令头(E841) + user信息前缀(AA)+姓名(姓名字节长度+姓名+姓名不足12字节占位符)+性别+年龄+身高+体重
  156. var stringBuild strings.Builder
  157. stringBuild.WriteString(constant.BindUserInfoCmdPrefix)
  158. length := len(userNameHex) / 2
  159. bytes := common.Int2Bytes(length)
  160. result := common.Bytes2HexStr(bytes)
  161. result = common.Int2Byte(int64(length))
  162. if result == "" {
  163. response.Failed("用户名处理异常", c)
  164. return
  165. }
  166. result = result[len(result)-2:]
  167. stringBuild.WriteString(result)
  168. stringBuild.WriteString(userNameHex)
  169. placeHolder := common.GenerateHexStringCmdPlaceHolder(constant.MaxNameByteLength - length)
  170. stringBuild.WriteString(placeHolder)
  171. hexGender := common.Int2Byte(param.Gender)
  172. stringBuild.WriteString(hexGender[len(hexGender)-2:])
  173. if param.Age == 0 {
  174. param.Age = constant.EcgDefaultAge
  175. }
  176. hexAge := common.Int2Byte(param.Age)
  177. stringBuild.WriteString(hexAge[len(hexAge)-2:])
  178. if param.Height == 0 {
  179. param.Height = constant.EcgDefaultHeight
  180. }
  181. hexHeight := common.Int2Byte(param.Height)
  182. stringBuild.WriteString(hexHeight[len(hexHeight)-2:])
  183. if param.Weight == 0 {
  184. param.Weight = constant.EcgDefaultWeight
  185. }
  186. hexWeight := common.Int2Byte(param.Weight)
  187. stringBuild.WriteString(hexWeight[len(hexWeight)-2:])
  188. bindUserCmdByte := []byte(stringBuild.String())
  189. bindUserCmd := string(bindUserCmdByte)
  190. fmt.Println(bindUserCmd)
  191. //2.授时指令
  192. //timeCmd := common.GetTimeCmd()
  193. timeCmd := common.GetHexTimeStr()
  194. //timeCmd = fmt.Sprintf("%s%s", "0x", timeCmd)
  195. setTimeCmd := fmt.Sprintf("%s%s", constant.SetTimeCmdPrefix, timeCmd)
  196. fmt.Println(setTimeCmd)
  197. //3.开始收集指令
  198. startCollectCmd := fmt.Sprintf("%s%s", constant.StartCollectCmdPrefix, timeCmd)
  199. fmt.Println(startCollectCmd)
  200. //发送指令
  201. //绑定用户
  202. bindUserUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl)
  203. bindUserUrl = strings.Replace(bindUserUrl, "MAC", param.Mac, -1)
  204. bindUserUrl = strings.Replace(bindUserUrl, "DATA", bindUserCmd, -1)
  205. fmt.Println("bindUserUrl====" + bindUserUrl)
  206. httpResponse := http.GetReq(bindUserUrl)
  207. if httpResponse.StatusCode != 200 {
  208. fmt.Printf("%s:%s", errors.BindUserFailed, httpResponse.Body)
  209. response.Failed(errors.BindUserFailed, c)
  210. return
  211. }
  212. //授时
  213. setTimeUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl)
  214. setTimeUrl = strings.Replace(setTimeUrl, "MAC", param.Mac, -1)
  215. setTimeUrl = strings.Replace(setTimeUrl, "DATA", setTimeCmd, -1)
  216. httpResponse = http.GetReq(setTimeUrl)
  217. if httpResponse.StatusCode != 200 {
  218. fmt.Printf("%s:%s", errors.BindUserFailed, httpResponse.Body)
  219. response.Failed(errors.BindUserFailed, c)
  220. return
  221. }
  222. fmt.Println("setTimeUrl=====" + setTimeUrl)
  223. //开始收集
  224. startCollectUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl)
  225. startCollectUrl = strings.Replace(startCollectUrl, "MAC", param.Mac, -1)
  226. startCollectUrl = strings.Replace(startCollectUrl, "DATA", startCollectCmd, -1)
  227. fmt.Println("startCollectUrl=====" + startCollectUrl)
  228. httpResponse = http.GetReq(startCollectUrl)
  229. if httpResponse.StatusCode != 200 {
  230. fmt.Printf("%s:%s", errors.StartCollocateFailed, httpResponse.Body)
  231. response.Failed(errors.StartCollocateFailed, c)
  232. return
  233. }
  234. //开始传输指令
  235. startTransUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl)
  236. startTransUrl = strings.Replace(startTransUrl, "MAC", param.Mac, -1)
  237. startTransUrl = strings.Replace(startTransUrl, "DATA", constant.StartTransCmd, -1)
  238. fmt.Println("startTransUrl====" + startTransUrl)
  239. httpResponse = http.GetReq(startTransUrl)
  240. if httpResponse.StatusCode != 200 {
  241. fmt.Printf("%s:%s", errors.StartTransFailed, httpResponse.Body)
  242. response.Failed(errors.StartTransFailed, c)
  243. return
  244. }
  245. response.Success(errors.WriteDataSuccess, nil, c)
  246. return
  247. }
  248. // OpenNotify
  249. // PingExample confrontation-training
  250. // @Summary 开启数据通知
  251. // @Schemes
  252. // @Description 开启数据通知
  253. // @Tags 设备管理
  254. // @Accept json
  255. // @Produce json
  256. // @Success 200 {string} string "ok"
  257. // @Router /v1/device/open/notify/ [get]
  258. func OpenNotify(c *gin.Context) {
  259. SseOpenNotify()
  260. response.Success("开启通知", "", c)
  261. return
  262. }
  263. // StopTrans
  264. // PingExample confrontation-training
  265. // @Summary 停止传输
  266. // @Schemes
  267. // @Description 停止传输
  268. // @Tags 设备管理
  269. // @Accept json
  270. // @Produce json
  271. // @Success 200 {string} string "ok"
  272. // @Router /v1/device/:mac/stop/trans [get]
  273. func StopTrans(c *gin.Context) {
  274. mac := c.Param("mac")
  275. stopTransUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.WriteDataUrl
  276. stopTransUrl = strings.Replace(stopTransUrl, "MAC", mac, -1)
  277. stopTransUrl = strings.Replace(stopTransUrl, "DATA", constant.StopTransCmd, -1)
  278. response.Success("停止传输", "", c)
  279. return
  280. }
  281. // StopCollect
  282. // PingExample confrontation-training
  283. // @Summary 停止采集
  284. // @Schemes
  285. // @Description 停止采集
  286. // @Tags 设备管理
  287. // @Accept json
  288. // @Produce json
  289. // @Success 200 {string} string "ok"
  290. // @Router /v1/device/:mac/stop/collect [get]
  291. func StopCollect(c *gin.Context) {
  292. mac := c.Param("mac")
  293. stopTransUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.WriteDataUrl
  294. stopTransUrl = strings.Replace(stopTransUrl, "MAC", mac, -1)
  295. stopTransUrl = strings.Replace(stopTransUrl, "DATA", constant.StopCollectCmd, -1)
  296. response.Success("停止采集", "", c)
  297. return
  298. }
  299. // ScanDeviceEmq
  300. // PingExample confrontation-training
  301. // @Summary 扫描设备
  302. // @Schemes
  303. // @Description 扫描设备
  304. // @Tags 设备管理
  305. // @Accept json
  306. // @Produce json
  307. // @Success 200 {string} string "ok"
  308. // @Router /v2/device/scan [get]
  309. func ScanDeviceEmq(c *gin.Context) {
  310. topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  311. client := global.EmqClient
  312. //停止扫描
  313. fmt.Println("停止扫描")
  314. fmt.Println(constant.CmdStopScan)
  315. Publish(client, topic, constant.CmdStopScan)
  316. //开启扫描
  317. //Publish(client, "/EE3870DA24C4/connect_packet/connect1_subscribe", "[{\"cmd\":\"AT+SCAN=\",\"s\":\"1\"}]")
  318. //停止扫描
  319. //Publish(client, "/EE3870DA24C4/connect_packet/connect1_subscribe", "[{\"cmd\":\"AT+SCAN=\",\"s\":\"0\"}]")
  320. //设置设备服务UUID
  321. //fmt.Println("设置设备服务UUID")
  322. if global.EmqConfig.FirstOpen == "0" {
  323. SendUUID(client, topic)
  324. }
  325. time.Sleep(time.Millisecond * 100)
  326. Publish(global.EmqClient, topic, constant.CmdStartScan)
  327. response.Success("开启扫描完成", "", c)
  328. return
  329. }
  330. // StopScanDeviceEmq
  331. // PingExample confrontation-training
  332. // @Summary 停止扫描设备
  333. // @Schemes
  334. // @Description 停止扫描设备
  335. // @Tags 设备管理
  336. // @Accept json
  337. // @Produce json
  338. // @Success 200 {string} string "ok"
  339. // @Router /v2/device/stop/scan [get]
  340. func StopScanDeviceEmq(c *gin.Context) {
  341. topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  342. Publish(global.EmqClient, topic, constant.CmdStopScan)
  343. response.Success("关闭扫描完成", "", c)
  344. return
  345. }
  346. // ConnectDevice2
  347. // PingExample confrontation-training
  348. // @Summary 连接设备
  349. // @Schemes
  350. // @Description 连接设备
  351. // @Tags 设备管理
  352. // @Param device body string true "mac:设备MAC地址 ai:终端BLE设备的地址ID at:终端BLE设备的地址类型 "
  353. // @Accept json
  354. // @Produce json
  355. // @Success 200 {string} string "ok"
  356. // @Router /v2/device/conn [post]
  357. func ConnectDevice2(c *gin.Context) {
  358. var param gateway.ConnectDevice
  359. err := c.ShouldBindJSON(&param)
  360. if err != nil {
  361. fmt.Printf("参数格式化异常:%s", err.Error())
  362. response.Failed(errors.ParamInvalid, c)
  363. return
  364. }
  365. topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  366. ConnectDeviceEmq(global.EmqClient, topic, param.Mac, "0", param.Ai, param.At)
  367. response.Success("连接设备完成", "", c)
  368. return
  369. }
  370. // DisConnect
  371. // PingExample confrontation-training
  372. // @Summary 断开连接设备
  373. // @Schemes
  374. // @Description 断开连接设备
  375. // @Tags 设备管理
  376. // @Param device body string true "mac:设备MAC地址 "
  377. // @Accept json
  378. // @Produce json
  379. // @Success 200 {string} string "ok"
  380. // @Router /v2/device/dis/conn [post]
  381. func DisConnect(c *gin.Context) {
  382. var param gateway.ConnectDevice
  383. err := c.ShouldBindJSON(&param)
  384. if err != nil {
  385. fmt.Printf("参数格式化异常:%s", err.Error())
  386. response.Failed(errors.ParamInvalid, c)
  387. return
  388. }
  389. topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  390. DisConnectDeviceEmq(global.EmqClient, topic, param.Mac)
  391. response.Success("断开设备连接成功", "", c)
  392. return
  393. }
  394. // ConnectList
  395. // PingExample confrontation-training
  396. // @Summary 已连接列表 已连接列表中不再做任何处理,在连接或断开连接 成功或失败时系统自动调用
  397. // @Schemes
  398. // @Description 已连接列表
  399. // @Tags 设备管理
  400. // @Accept json
  401. // @Produce json
  402. // @Success 200 {string} string "ok"
  403. // @Router /v2/device/connected/list [get]
  404. func ConnectList(c *gin.Context) {
  405. //topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  406. ////ConnectedListEmq(global.EmqClient, topic)
  407. ////ConnectedNumber(global.EmqClient, topic)
  408. //for i := 0; i < 6; i++ {
  409. // ConnectedListEmq(global.EmqClient, topic, strconv.Itoa(i))
  410. //}
  411. response.Success("查询连接列表完成", "", c)
  412. return
  413. }
  414. // WriteDataEmq
  415. // PingExample confrontation-training
  416. // @Summary 写入数据-脑电写入指令
  417. // @Schemes
  418. // @Description 写入数据-脑电写入指令
  419. // @Tags 设备管理
  420. // @Param mac body string true "mac:设备MAC地址 userName:用户姓名 gender:性别 age:年龄 height:身高 weight:体重"
  421. // @Accept json
  422. // @Produce json
  423. // @Success 200 {string} string "ok"
  424. // @Router /v2/device/write/data [post]
  425. func WriteDataEmq(c *gin.Context) {
  426. var param models.WriteData
  427. err := c.ShouldBindJSON(&param)
  428. if err != nil {
  429. fmt.Printf("参数格式化异常:%s", err.Error())
  430. response.Failed(errors.ParamInvalid, c)
  431. return
  432. }
  433. userNameHex := hex.EncodeToString([]byte(param.UserName))
  434. topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub
  435. //写入
  436. //1 绑定用户指令
  437. //指令头(E841) + user信息前缀(AA)+姓名(姓名字节长度+姓名+姓名不足12字节占位符)+性别+年龄+身高+体重
  438. var stringBuild strings.Builder
  439. stringBuild.WriteString(constant.BindUserInfoCmdPrefix)
  440. length := len(userNameHex) / 2
  441. bytes := common.Int2Bytes(length)
  442. result := common.Bytes2HexStr(bytes)
  443. result = common.Int2Byte(int64(length))
  444. if result == "" {
  445. response.Failed("用户名处理异常", c)
  446. return
  447. }
  448. result = result[len(result)-2:]
  449. stringBuild.WriteString(result)
  450. stringBuild.WriteString(userNameHex)
  451. placeHolder := common.GenerateHexStringCmdPlaceHolder(constant.MaxNameByteLength - length)
  452. stringBuild.WriteString(placeHolder)
  453. hexGender := common.Int2Byte(param.Gender)
  454. stringBuild.WriteString(hexGender[len(hexGender)-2:])
  455. if param.Age == 0 {
  456. param.Age = constant.EcgDefaultAge
  457. }
  458. hexAge := common.Int2Byte(param.Age)
  459. stringBuild.WriteString(hexAge[len(hexAge)-2:])
  460. if param.Height == 0 {
  461. param.Height = constant.EcgDefaultHeight
  462. }
  463. hexHeight := common.Int2Byte(param.Height)
  464. stringBuild.WriteString(hexHeight[len(hexHeight)-2:])
  465. if param.Weight == 0 {
  466. param.Weight = constant.EcgDefaultWeight
  467. }
  468. hexWeight := common.Int2Byte(param.Weight)
  469. stringBuild.WriteString(hexWeight[len(hexWeight)-2:])
  470. bindUserCmdByte := []byte(stringBuild.String())
  471. bindUserCmd := string(bindUserCmdByte)
  472. fmt.Println(bindUserCmd)
  473. //2.授时指令
  474. //timeCmd := common.GetTimeCmd()
  475. timeCmd := common.GetHexTimeStr()
  476. //timeCmd = fmt.Sprintf("%s%s", "0x", timeCmd)
  477. setTimeCmd := fmt.Sprintf("%s%s", constant.SetTimeCmdPrefix, timeCmd)
  478. fmt.Println(setTimeCmd)
  479. //3.开始收集指令
  480. startCollectCmd := fmt.Sprintf("%s%s", constant.StartCollectCmdPrefix, timeCmd)
  481. fmt.Println(startCollectCmd)
  482. //发送指令
  483. //绑定用户
  484. WNP(global.EmqClient, topic, param.Mac, "FFF1", bindUserCmd)
  485. //授时
  486. WNP(global.EmqClient, topic, param.Mac, "FFF1", setTimeCmd)
  487. //开始收集
  488. WNP(global.EmqClient, topic, param.Mac, "FFF1", startCollectCmd)
  489. //开始传输指令
  490. WNP(global.EmqClient, topic, param.Mac, "FFF1", constant.StartTransCmd)
  491. response.Success(errors.WriteDataSuccess, nil, c)
  492. return
  493. }