package gateway import ( "confrontation-training/common" "confrontation-training/constant" errors "confrontation-training/err" "confrontation-training/global" "confrontation-training/http" "confrontation-training/models" "confrontation-training/models/gateway" "confrontation-training/response" "encoding/hex" "encoding/json" "fmt" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "io/ioutil" "os" "strconv" "strings" "time" ) // ScanDevice // PingExample confrontation-training // @Summary 扫描设备 // @Schemes // @Description 扫描设备 // @Tags 设备管理 // @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 表示已录入的设备" // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/scan [post] func ScanDevice(c *gin.Context) { var param gateway.DeviceScanParam err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) global.Log4J.Info("参数格式化异常:", err.Error()) response.Failed(errors.ParamInvalid, c) return } paramMap := make(map[string]string) if param.Chip != "" { paramMap["chip"] = param.Chip } if param.FilterName != "" { //查询设备mac过滤信息 filterMac := "" deviceInfos, count := GetDeviceService().DeviceService.FindDeviceByType(param.FilterName) if count > 0 { for i := range deviceInfos { filterMac += deviceInfos[i].Mac + "," } } if len(filterMac) > 0 { if strings.HasSuffix(filterMac, ",") { filterMac = filterMac[0 : len(filterMac)-1] } paramMap["filter_mac"] = filterMac } if param.FilterName == "0" { paramMap["filter_name"] = constant.FilterNameEEG } else if param.FilterName == "1" { paramMap["filter_name"] = constant.FilterNameECG } else { response.Failed(errors.ParamInvalid+":过滤类型-"+param.FilterName+"无效", c) return } } else { paramMap["filter_name"] = constant.FilterNameALL } if param.FilterRssi != "" { paramMap["filter_rssi"] = param.FilterRssi } if param.FilterMac != "" { paramMap["filter_mac"] = param.FilterMac } paramMap["active"] = "1" paramMap["event"] = "1" param.FilterType = "1" go SseScanDevice(paramMap, param.FilterType) response.Success("扫描完成", "", c) return } // ConnectDevice // PingExample confrontation-training // @Summary 连接设备 // @Schemes // @Description 连接设备 // @Tags 设备管理 // @Param device body string true "chip:芯片编号,0或1;mac:Mac地址;addrType:地址类型 public/random " // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/connection [post] func ConnectDevice(c *gin.Context) { var param gateway.DeviceConnParam err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) log.Infof("参数格式化异常:%s", err.Error()) response.Failed(errors.ParamInvalid, c) return } jsonParam, err := json.Marshal(param) if err != nil { fmt.Printf("参数转换异常:%s", err.Error()) log.Infof("参数转换异常:%s", err.Error()) response.Failed("参数转换异常:%s"+err.Error(), c) return } url := global.Config.Gateway.BaseUrl + global.Config.Gateway.ConnUrl url = strings.Replace(url, "MAC", param.Mac, -1) if param.FilterName == "0" { url = strings.Replace(url, "chip", "chip=0", -1) } else if param.FilterName == "1" { url = strings.Replace(url, "chip", "chip=1", -1) } httpResponse := http.PostReqJson(url, jsonParam) status := httpResponse.StatusCode body, _ := ioutil.ReadAll(httpResponse.Body) if status != 200 { response.Failed(errors.DeviceConnectError+string(body), c) return } if param.FilterName == "1" { openChannelUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.OpenChannel openChannelUrl = strings.Replace(openChannelUrl, "MAC", param.Mac, -1) httpResponse = http.GetReq(openChannelUrl) if httpResponse.StatusCode != 200 { fmt.Printf("%s:%s", errors.OpenChannelError, httpResponse.Body) log.Infof("%s:%s", errors.OpenChannelError, httpResponse.Body) response.Failed(errors.OpenChannelError, c) return } } go StopScan(c.Writer, c.Request) response.Success(errors.DeviceConnectSuccess, param.Mac, c) return } // WriteData // PingExample confrontation-training // @Summary 写入数据——发送指令 // @Schemes // @Description 写入数据——发送指令 ,ECG设备开启测试功能 // @Tags 设备管理 // @Param mac body string true "mac:设备MAC地址 userName:用户姓名 gender:性别 age:年龄 height:身高 weight:体重" // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/write/data/ [post] func WriteData(c *gin.Context) { var param models.WriteData err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) log.Infof("参数格式化异常:%s", err.Error()) response.Failed(errors.ParamInvalid, c) return } userNameHex := hex.EncodeToString([]byte(param.UserName)) //1 绑定用户指令 //指令头(E841) + user信息前缀(AA)+姓名(姓名字节长度+姓名+姓名不足12字节占位符)+性别+年龄+身高+体重 var stringBuild strings.Builder stringBuild.WriteString(constant.BindUserInfoCmdPrefix) length := len(userNameHex) / 2 bytes := common.Int2Bytes(length) result := common.Bytes2HexStr(bytes) result = common.Int2Byte(int64(length)) if result == "" { response.Failed("用户名处理异常", c) return } result = result[len(result)-2:] stringBuild.WriteString(result) stringBuild.WriteString(userNameHex) placeHolder := common.GenerateHexStringCmdPlaceHolder(constant.MaxNameByteLength - length) stringBuild.WriteString(placeHolder) hexGender := common.Int2Byte(param.Gender) stringBuild.WriteString(hexGender[len(hexGender)-2:]) if param.Age == 0 { param.Age = constant.EcgDefaultAge } hexAge := common.Int2Byte(param.Age) stringBuild.WriteString(hexAge[len(hexAge)-2:]) if param.Height == 0 { param.Height = constant.EcgDefaultHeight } hexHeight := common.Int2Byte(param.Height) stringBuild.WriteString(hexHeight[len(hexHeight)-2:]) if param.Weight == 0 { param.Weight = constant.EcgDefaultWeight } hexWeight := common.Int2Byte(param.Weight) stringBuild.WriteString(hexWeight[len(hexWeight)-2:]) bindUserCmdByte := []byte(stringBuild.String()) bindUserCmd := string(bindUserCmdByte) fmt.Println(bindUserCmd) log.Infoln(bindUserCmd) //2.授时指令 //timeCmd := common.GetTimeCmd() timeCmd := common.GetHexTimeStr() //timeCmd = fmt.Sprintf("%s%s", "0x", timeCmd) setTimeCmd := fmt.Sprintf("%s%s", constant.SetTimeCmdPrefix, timeCmd) fmt.Println(setTimeCmd) log.Infoln(setTimeCmd) //3.开始收集指令 startCollectCmd := fmt.Sprintf("%s%s", constant.StartCollectCmdPrefix, timeCmd) fmt.Println(startCollectCmd) log.Infoln(startCollectCmd) //发送指令 //绑定用户 bindUserUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl) bindUserUrl = strings.Replace(bindUserUrl, "MAC", param.Mac, -1) bindUserUrl = strings.Replace(bindUserUrl, "DATA", bindUserCmd, -1) fmt.Println("bindUserUrl====" + bindUserUrl) log.Infoln("bindUserUrl====" + bindUserUrl) httpResponse := http.GetReq(bindUserUrl) if httpResponse.StatusCode != 200 { fmt.Printf("%s:%s", errors.BindUserFailed, httpResponse.Body) log.Infof("%s:%s", errors.BindUserFailed, httpResponse.Body) response.Failed(errors.BindUserFailed, c) return } //授时 setTimeUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl) setTimeUrl = strings.Replace(setTimeUrl, "MAC", param.Mac, -1) setTimeUrl = strings.Replace(setTimeUrl, "DATA", setTimeCmd, -1) httpResponse = http.GetReq(setTimeUrl) if httpResponse.StatusCode != 200 { fmt.Printf("%s:%s", errors.BindUserFailed, httpResponse.Body) log.Infof("%s:%s", errors.BindUserFailed, httpResponse.Body) response.Failed(errors.BindUserFailed, c) return } fmt.Println("setTimeUrl=====" + setTimeUrl) log.Infoln("setTimeUrl=====" + setTimeUrl) //开始收集 startCollectUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl) startCollectUrl = strings.Replace(startCollectUrl, "MAC", param.Mac, -1) startCollectUrl = strings.Replace(startCollectUrl, "DATA", startCollectCmd, -1) fmt.Println("startCollectUrl=====" + startCollectUrl) log.Infoln("startCollectUrl=====" + startCollectUrl) httpResponse = http.GetReq(startCollectUrl) if httpResponse.StatusCode != 200 { fmt.Printf("%s:%s", errors.StartCollocateFailed, httpResponse.Body) log.Infof("%s:%s", errors.StartCollocateFailed, httpResponse.Body) response.Failed(errors.StartCollocateFailed, c) return } //开始传输指令 startTransUrl := fmt.Sprintf("%s%s", global.Config.Gateway.BaseUrl, global.Config.Gateway.WriteDataUrl) startTransUrl = strings.Replace(startTransUrl, "MAC", param.Mac, -1) startTransUrl = strings.Replace(startTransUrl, "DATA", constant.StartTransCmd, -1) fmt.Println("startTransUrl====" + startTransUrl) log.Infoln("startTransUrl====" + startTransUrl) httpResponse = http.GetReq(startTransUrl) if httpResponse.StatusCode != 200 { fmt.Printf("%s:%s", errors.StartTransFailed, httpResponse.Body) log.Infof("%s:%s", errors.StartTransFailed, httpResponse.Body) response.Failed(errors.StartTransFailed, c) return } response.Success(errors.WriteDataSuccess, nil, c) return } // OpenNotify // PingExample confrontation-training // @Summary 开启数据通知 // @Schemes // @Description 开启数据通知 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/open/notify/ [get] func OpenNotify(c *gin.Context) { SseOpenNotify() response.Success("开启通知", "", c) return } // StopTrans // PingExample confrontation-training // @Summary 停止传输 // @Schemes // @Description 停止传输 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/:mac/stop/trans [get] func StopTrans(c *gin.Context) { mac := c.Param("mac") stopTransUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.WriteDataUrl stopTransUrl = strings.Replace(stopTransUrl, "MAC", mac, -1) stopTransUrl = strings.Replace(stopTransUrl, "DATA", constant.StopTransCmd, -1) response.Success("停止传输", "", c) return } // StopCollect // PingExample confrontation-training // @Summary 停止采集 // @Schemes // @Description 停止采集 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v1/device/:mac/stop/collect [get] func StopCollect(c *gin.Context) { mac := c.Param("mac") stopTransUrl := global.Config.Gateway.BaseUrl + global.Config.Gateway.WriteDataUrl stopTransUrl = strings.Replace(stopTransUrl, "MAC", mac, -1) stopTransUrl = strings.Replace(stopTransUrl, "DATA", constant.StopCollectCmd, -1) response.Success("停止采集", "", c) return } // ScanDeviceEmq // PingExample confrontation-training // @Summary 扫描设备 // @Schemes // @Description 扫描设备 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/scan [get] func ScanDeviceEmq(c *gin.Context) { topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub client := global.EmqClient //停止扫描 fmt.Println("停止扫描") log.Infoln("停止扫描") global.Log4J.Info("停止扫描") fmt.Println(constant.CmdStopScan) Publish(client, topic, constant.CmdStopScan) //开启扫描 //Publish(client, "/EE3870DA24C4/connect_packet/connect1_subscribe", "[{\"cmd\":\"AT+SCAN=\",\"s\":\"1\"}]") //停止扫描 //Publish(client, "/EE3870DA24C4/connect_packet/connect1_subscribe", "[{\"cmd\":\"AT+SCAN=\",\"s\":\"0\"}]") //设置设备服务UUID //fmt.Println("设置设备服务UUID") if global.EmqConfig.FirstOpen == "0" { SendUUID(client, topic) } time.Sleep(time.Millisecond * 100) Publish(global.EmqClient, topic, constant.CmdStartScan) response.Success("开启扫描完成", "", c) return } // StopScanDeviceEmq // PingExample confrontation-training // @Summary 停止扫描设备 // @Schemes // @Description 停止扫描设备 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/stop/scan [get] func StopScanDeviceEmq(c *gin.Context) { topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub Publish(global.EmqClient, topic, constant.CmdStopScan) response.Success("关闭扫描完成", "", c) return } // ConnectDevice2 // PingExample confrontation-training // @Summary 连接设备 // @Schemes // @Description 连接设备 // @Tags 设备管理 // @Param device body string true "mac:设备MAC地址 ai:终端BLE设备的地址ID at:终端BLE设备的地址类型 " // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/conn [post] func ConnectDevice2(c *gin.Context) { var param gateway.ConnectDevice err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) global.Log4J.Info("参数格式化异常:", err.Error()) response.Failed(errors.ParamInvalid, c) return } global.Log4J.Info("连接Mac:" + param.Mac) info := global.DeviceMap[param.Mac] for s, deviceInfo := range global.DeviceMap { global.Log4J.Info("mac"+s, "deviceInfo:", deviceInfo) } global.Log4J.Info("设备信息:", info) if info.Type == "" { response.Failed("设备未入库,请先添加设备", c) return } topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub mac := strings.ReplaceAll(param.Mac, ":", "") ConnectDeviceEmq(global.EmqClient, topic, mac, "0", param.Ai, param.At) response.Success("连接设备完成", "", c) return } // DisConnect // PingExample confrontation-training // @Summary 断开连接设备 // @Schemes // @Description 断开连接设备 // @Tags 设备管理 // @Param device body string true "mac:设备MAC地址 " // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/dis/conn [post] func DisConnect(c *gin.Context) { var param gateway.ConnectDevice err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) global.Log4J.Info("参数格式化异常:", err.Error()) response.Failed(errors.ParamInvalid, c) return } topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub mac := strings.ReplaceAll(param.Mac, ":", "") DisConnectDeviceEmq(global.EmqClient, topic, mac) response.Success("断开设备连接成功", "", c) return } // DisConnectAll // PingExample confrontation-training // @Summary 断开所有已连接设备 // @Schemes // @Description 断开所有已连接设备 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/dis/connAll [get] func DisConnectAll(c *gin.Context) { topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub //断开所有的连接 for s := range global.DeviceMap { if len(s) == 17 { s = strings.ReplaceAll(s, ":", "") DisConnectDeviceEmq(global.EmqClient, topic, s) } } response.Success("断开所有已连接设备成功", "", c) return } // ConnectList // PingExample confrontation-training // @Summary 已连接列表 已连接列表中不再做任何处理,在连接或断开连接 成功或失败时系统自动调用 // @Schemes // @Description 已连接列表 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/connected/list [get] func ConnectList(c *gin.Context) { topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub //ConnectedListEmq(global.EmqClient, topic) //ConnectedNumber(global.EmqClient, topic) for i := 0; i < 6; i++ { ConnectedListEmq(global.EmqClient, topic, strconv.Itoa(i)) time.Sleep(time.Millisecond * 500) } response.Success("查询连接列表完成", "", c) return } // WriteDataEmq // PingExample confrontation-training // @Summary 写入数据-脑电写入指令 // @Schemes // @Description 写入数据-脑电写入指令 // @Tags 设备管理 // @Param mac body string true "mac:设备MAC地址 userName:用户姓名 gender:性别 age:年龄 height:身高 weight:体重" // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/device/write/data [post] func WriteDataEmq(c *gin.Context) { var param models.WriteData err := c.ShouldBindJSON(¶m) if err != nil { fmt.Printf("参数格式化异常:%s", err.Error()) global.Log4J.Info("参数格式化异常:", err.Error()) response.Failed(errors.ParamInvalid, c) return } userNameHex := hex.EncodeToString([]byte(param.UserName)) topic := "/" + global.Config.EmqConfig.GatewayMac + constant.TopicConnectSub //写入 //1 绑定用户指令 //指令头(E841) + user信息前缀(AA)+姓名(姓名字节长度+姓名+姓名不足12字节占位符)+性别+年龄+身高+体重 var stringBuild strings.Builder stringBuild.WriteString(constant.BindUserInfoCmdPrefix) length := len(userNameHex) / 2 bytes := common.Int2Bytes(length) result := common.Bytes2HexStr(bytes) result = common.Int2Byte(int64(length)) if result == "" { response.Failed("用户名处理异常", c) return } result = result[len(result)-2:] stringBuild.WriteString(result) stringBuild.WriteString(userNameHex) placeHolder := common.GenerateHexStringCmdPlaceHolder(constant.MaxNameByteLength - length) stringBuild.WriteString(placeHolder) hexGender := common.Int2Byte(param.Gender) stringBuild.WriteString(hexGender[len(hexGender)-2:]) if param.Age == 0 { param.Age = constant.EcgDefaultAge } hexAge := common.Int2Byte(param.Age) stringBuild.WriteString(hexAge[len(hexAge)-2:]) if param.Height == 0 { param.Height = constant.EcgDefaultHeight } hexHeight := common.Int2Byte(param.Height) stringBuild.WriteString(hexHeight[len(hexHeight)-2:]) if param.Weight == 0 { param.Weight = constant.EcgDefaultWeight } hexWeight := common.Int2Byte(param.Weight) stringBuild.WriteString(hexWeight[len(hexWeight)-2:]) bindUserCmdByte := []byte(stringBuild.String()) bindUserCmd := string(bindUserCmdByte) fmt.Println(bindUserCmd) global.Log4J.Info(bindUserCmd) //2.授时指令 //timeCmd := common.GetTimeCmd() timeCmd := common.GetHexTimeStr() //timeCmd = fmt.Sprintf("%s%s", "0x", timeCmd) setTimeCmd := fmt.Sprintf("%s%s", constant.SetTimeCmdPrefix, timeCmd) fmt.Println(setTimeCmd) global.Log4J.Info(setTimeCmd) //3.开始收集指令 startCollectCmd := fmt.Sprintf("%s%s", constant.StartCollectCmdPrefix, timeCmd) fmt.Println(startCollectCmd) global.Log4J.Info(startCollectCmd) //发送指令 //绑定用户 WNP(global.EmqClient, topic, param.Mac, "FFF1", bindUserCmd) //授时 WNP(global.EmqClient, topic, param.Mac, "FFF1", setTimeCmd) //开始收集 WNP(global.EmqClient, topic, param.Mac, "FFF1", startCollectCmd) //开始传输指令 WNP(global.EmqClient, topic, param.Mac, "FFF1", constant.StartTransCmd) response.Success(errors.WriteDataSuccess, nil, c) return } // FindGateway // PingExample confrontation-training // @Summary 查询可能是蓝牙网关的设备 // @Schemes // @Description 查询可能是蓝牙网关的设备 // @Tags 设备管理 // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/gateway/find [get] func FindGateway(c *gin.Context) { marshal, err := json.Marshal(global.GatewayList) if err != nil { return } response.Success("查询网关设备完成", marshal, c) return } // SetGatewayMac // PingExample confrontation-training // @Summary 保存网关MAC // @Schemes // @Description 保存网关MAC-脑电写入指令 // @Tags 设备管理 // @Param mac body string true "mac:网关MAC地址 " // @Accept json // @Produce json // @Success 200 {string} string "ok" // @Router /v2/gateway/set [post] func SetGatewayMac(c *gin.Context) { var param gateway.GatewayInfo c.ShouldBindJSON(¶m) file, err := os.OpenFile("./config/application.yaml", os.O_APPEND, 0666) if err != nil { response.Failed("读取配置文件失败", c) return } _, err = file.Write([]byte(param.Mac)) if err != nil { response.Failed("写入配置文件失败", c) return } response.Success("网关信息保存成功,请重启软件!", "", c) return }