package main import ( "encoding/json" "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "io/ioutil" "log" "math/rand" "net/http" "strconv" "time" ) var client mqtt.Client var db *gorm.DB var conf Config type DeviceInfo struct { ID int64 `json:"id"` DevEui string `json:"devEUI"` DevAddr string `json:"devAddr"` Username string `json:"username"` CreateAt time.Time `json:"createAt"` } type Config struct { Server struct { Port string } DB struct { Host string Port int User string Password string Name string LogMode bool } MQTT struct { Server string Topic string } } func loadConfig(filename string, c *Config) error { data, err := ioutil.ReadFile(filename) if err != nil { return nil } err = json.Unmarshal(data, c) if err != nil { return err } return nil } func Krand(size int, kind int) []byte { ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size) is_all := kind > 2 || kind < 0 for i :=0; i < size; i++ { if is_all { // random ikind ikind = rand.Intn(3) } scope, base := kinds[ikind][0], kinds[ikind][1] result[i] = uint8(base+rand.Intn(scope)) } return result } func Setup(c *Config) { var err error dsn := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", c.DB.User, c.DB.Password, c.DB.Host, c.DB.Port,c.DB.Name) db, err = gorm.Open("mysql", dsn) if err != nil { panic(err) } db.LogMode(c.DB.LogMode) db.AutoMigrate(&DeviceInfo{}) db.Model(&DeviceInfo{}).AddUniqueIndex("idx_dev_eui","dev_eui") db.Model(&DeviceInfo{}).AddUniqueIndex("idx_dev_addr", "dev_addr") db.Model(&DeviceInfo{}).AddIndex("idx_create_at", "create_at") opts := mqtt.NewClientOptions().AddBroker(c.MQTT.Server).SetClientID("deviceIDServer_"+string(Krand(16,3))) client = mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } } func PostDevice(c *gin.Context) { var device DeviceInfo device.CreateAt = time.Now() if err := c.BindJSON(&device); err != nil { log.Println("bind json error: ",err) c.JSON(http.StatusOK,gin.H{"code":-1,"msg": err.Error()}) return } if err := db.Create(&device).Error; err != nil { log.Println("db insert error: ",err) c.JSON(http.StatusOK,gin.H{"code":-1,"msg": err.Error()}) return } data,_ := json.Marshal(device) token := client.Publish(conf.MQTT.Topic,0,false,data) if token.Wait() && token.Error() != nil { log.Println("mqtt publish error: ",token.Error()) c.JSON(http.StatusOK,gin.H{"code":-1,"msg": token.Error().Error()}) return } log.Println("devEUI: "+ device.DevEui + " post success") c.JSON(http.StatusOK,gin.H{"code":0,"msg": "OK"}) return } func GetDevice(c *gin.Context) { devEui := c.Query("dev_eui") limit,_ := strconv.Atoi(c.DefaultQuery("limit","10")) offset,_ := strconv.Atoi(c.DefaultQuery("offset","0")) total := 0 var deviceInfos []DeviceInfo devEui = "%" + devEui + "%" db.Model(&DeviceInfo{}).Where("dev_eui like ?", devEui).Count(&total) err := db.Where("dev_eui like ?",devEui).Limit(limit).Offset(offset).Order("create_at desc").Find(&deviceInfos).Error if err != nil { log.Println("query db error",err) c.JSON(http.StatusOK,gin.H{"code":-1,"msg": err.Error()}) } else { c.JSON(http.StatusOK,gin.H{"code":0,"msg": "OK","data":gin.H{"total": total, "result": deviceInfos}}) } } func main() { err := loadConfig("./config.json",&conf) if err != nil { panic(err) } Setup(&conf) gin.SetMode(gin.ReleaseMode) engine := gin.Default() engine.GET("/device/info", GetDevice) engine.POST("/device/info", PostDevice) log.Println("start deviceIDServer port " + conf.Server.Port) err = engine.Run(":" + conf.Server.Port) if err != nil { panic(err) } _ = db.Close() }