package comm import ( "encoding/hex" "fmt" "log" "net/http" "reflect" "time" "tmr-watch/conf/setting" "tmr-watch/http/handle/restful" "tmr-watch/pkg/app" "tmr-watch/pkg/e" "unsafe" "github.com/gin-gonic/gin" "github.com/jacobsa/go-serial/serial" ) //一个已经被关闭的channel不会阻塞,已经被关闭的channel会实时返回 //goroutine退出,关闭done来进行广播 var done = make(chan struct{}) var Id = make(chan int) var timeout = make(chan int) var ReturnString = make(chan string) //判断done是否关闭,即是否执行goroutine退出 func cancelled() bool { select { case <-done: return true default: return false } } func Int2Byte(data int) (ret []byte) { var len uintptr = unsafe.Sizeof(data) ret = make([]byte, len) var tmp int = 0xff var index uint = 0 for index = 0; index < uint(len); index++ { ret[index] = byte((tmp << (index * 8) & data) >> (index * 8)) } return ret } func OpenComm() { var sum byte var recLength, dataLength, state int comtimeout := 0 buf := make([]byte, 32) recbuf := make([]byte, 1) //s_params := make([]interface{}, 1) openSerial: f, err := serial.Open(*setting.CommSetting) if err != nil { fmt.Println("Error opening serial port: ", err) time.Sleep(1 * time.Second) goto openSerial } else { log.Printf("[info] Serial %s is Started", setting.CommSetting.PortName) if comtimeout == 0 { defer f.Close() } for { sum = (0x55 + 0xAA + 0x06 + 0x01 + 0x03 + 0x01) & 0xFF v := 0 if comtimeout == 0 { v, _ = <-Id } comtimeout = 0 cowidByte := Int2Byte(v)[:3] sum = (sum + cowidByte[0] + cowidByte[1] + cowidByte[2]) & 0xFF cowidByte = append(cowidByte, sum) requestCowid := "55AA06010301" + hex.EncodeToString(cowidByte) txData_, err := hex.DecodeString(requestCowid) recLength = 0 state = 0 _, err = f.Write(txData_) fmt.Println(hex.EncodeToString(txData_)) if err != nil { fmt.Println("Error writing to serial port: ", err) time.Sleep(1 * time.Second) comtimeout = 1 goto openSerial } loop: for { select { case <-timeout: break loop default: n, err := f.Read(buf) if err != nil { //if err != io.EOF { fmt.Println("Error reading from serial port: ", err) time.Sleep(1 * time.Second) comtimeout = 1 goto openSerial //} //break loop } else if n > 0 { buf = buf[:n] for _, value := range buf { switch state { case 0: //头判断 if value == 0x55 { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, (byte)(value&0xFF)) } case 1: //头判断中 if value == 0xAA { state = 2 recLength = 2 recbuf = append(recbuf, (byte)(value&0xFF)) } else { state = 0 recLength = 0 } case 2: //接收数据长度 state = 3 recLength = 3 dataLength = (int)(value + 4) recbuf = append(recbuf, (byte)(value&0xFF)) case 3: //接收数据中 recbuf = append(recbuf, (byte)(value&0xFF)) recLength++ if recLength == dataLength { fmt.Println(hex.EncodeToString(recbuf)) ReturnString <- hex.EncodeToString(recbuf) state = 0 recLength = 0 break loop } } } } else { time.Sleep(10 * time.Millisecond) } } } } } } func saveData(ReceStr string, x int, y int) (string, error) { s_params := make([]interface{}, 0) //bytelist, err := hex.DecodeString(ReturnS) s_params = append(s_params, 1) s_params = append(s_params, x) s_params = append(s_params, y) s_params = append(s_params, 1) _, err := restful.ExecQuery("INSERT INTO `cps_m` (`barid`, `x`, `y`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE barid = ?", s_params) if err != nil { return "", err } else { bytelist, err := hex.DecodeString(ReceStr) rodecount := (int)((bytelist[2] - 5) >> 1) s_params = s_params[1:3] if rodecount > 0 { for i := 0; i < rodecount; i++ { beaconname := (int)(bytelist[8+2*i]) rssi := (int)(bytelist[9+2*i]) s_params = s_params[:2] s_params = append(s_params, beaconname) s_params = append(s_params, rssi) s_params = append(s_params, rssi) _, err = restful.ExecQuery("INSERT INTO `cps_d`(`pid`,`beaconid`,`rssi`) "+ "SELECT (SELECT `id` FROM `cps_m` WHERE `x`=? AND `y`=?),?,? ON DUPLICATE KEY UPDATE rssi = ?", s_params) if err != nil { return "", err } } if err == nil { return "成功保存", nil } } else { return "没有收到数据", nil } } return "没有收到数据", nil } func savePointData(ReceStr string, limit int) (interface{}, error) { s_params := make([]interface{}, 1) //bytelist, err := hex.DecodeString(ReturnS) bytelist, err := hex.DecodeString(ReceStr) rodecount := (int)((bytelist[2] - 5) >> 1) low := (int)(bytelist[5]) mid := (int)(bytelist[6]) mid = mid << 8 high := (int)(bytelist[7]) high = high << 16 tagid := (int)(low | mid | high) s_params[0] = tagid if rodecount > 0 { for i := 0; i < rodecount; i++ { beaconname := (int)(bytelist[8+2*i]) rssi := (int)(bytelist[9+2*i]) s_params = s_params[:1] s_params = append(s_params, beaconname) s_params = append(s_params, rssi) s_params = append(s_params, rssi) _, err = restful.ExecQuery(" INSERT INTO `cps_point`(`tagid`,`beaconid`,`rssi`) "+ " Values( ?, ?, ?) ON DUPLICATE KEY UPDATE rssi = ?", s_params) if err != nil { return "", err } } if err == nil { s_params = s_params[:2] s_params[0] = tagid s_params[1] = limit resultdata, err := restful.QueryByMap(" SELECT AVG(X) X,AVG(Y) Y FROM ( "+ "SELECT `cps_m`.x,`cps_m`.y, SUM(ABS(`cps_d`.`rssi`-`cps_point`.`rssi`)) absrssi "+ "FROM `cps_d` JOIN `cps_point` ON `cps_d`.`beaconid`=`cps_point`.`beaconid` "+ "JOIN `cps_m` ON `cps_m`.`id`=`cps_d`.`pid` WHERE `cps_point`.`tagid`= ? "+ "GROUP BY `cps_m`.x,`cps_m`.y "+ "ORDER BY SUM(ABS(`cps_d`.`rssi`-`cps_point`.`rssi`)) "+ "LIMIT ?) AS d ", 0, 0, s_params) if err != nil { return "", err } else { return resultdata, nil } } } else { return "没有收到数据", nil } return "没有收到数据", nil } func ProcessHttp(c *gin.Context) { var ( appG = app.Gin{C: c} ) id := 0 //com.StrTo(c.Param("id")).MustInt() x := 0 //com.StrTo(c.Param("x")).MustInt() y := 0 //com.StrTo(c.Param("y")).MustInt() Id <- id select { case ReturnS := <-ReturnString: //拿到锁 if x >= 0 && y >= 0 { returnData, err := saveData(ReturnS, x, y) if err != nil { appG.Response(http.StatusOK, e.ERROR, err.Error()) } else { appG.Response(http.StatusOK, e.SUCCESS, returnData) } } else { returnData, err := savePointData(ReturnS, 1) if err != nil { appG.Response(http.StatusOK, e.ERROR, err.Error()) } else { appG.Response(http.StatusOK, e.SUCCESS, returnData) } } case <-time.After(10 * time.Second): //超时5s timeout <- 1 appG.Response(http.StatusOK, e.ERROR, "超时") } } func ProcessHttpCPS(c *gin.Context) { var ( appG = app.Gin{C: c} ) id := 0 //com.StrTo(c.Param("id")).MustInt() limit := 0 //com.StrTo(c.Param("limit")).MustInt() Id <- id select { case ReturnS := <-ReturnString: //拿到锁 { returnData, err := savePointData(ReturnS, limit) if err != nil { appG.Response(http.StatusOK, e.ERROR, err.Error()) } else { appG.Response(http.StatusOK, e.SUCCESS, returnData) } } case <-time.After(10 * time.Second): //超时5s timeout <- 1 appG.Response(http.StatusOK, e.ERROR, "超时") } } // interface转map[string]interface{} func ToMap(in interface{}, tagName string) (map[string]interface{}, error) { out := make(map[string]interface{}) v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Struct { // 非结构体返回错误提示 return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v) } t := v.Type() // 遍历结构体字段 // 指定tagName值为map中key;字段值为map中value for i := 0; i < v.NumField(); i++ { fi := t.Field(i) if tagValue := fi.Tag.Get(tagName); tagValue != "" { out[tagValue] = v.Field(i).Interface() } } return out, nil } // 错误返回提示语 func ErrorWoring(err string) (end string) { var endReturn string switch err { case "": endReturn = "" default: endReturn = err } return endReturn }