package main import ( "context" "encoding/hex" "errors" "math/rand" "net/http" "sparrow/pkg/models" "sparrow/pkg/rpcs" "sparrow/pkg/server" "sparrow/pkg/token" "strings" "github.com/opentracing/opentracing-go/ext" "github.com/opentracing/opentracing-go" "github.com/martini-contrib/render" ) const ( ErrOK = 0 ErrSystemFault = 10001 ErrDeviceNotFound = 10002 ErrWrongSecret = 10003 ErrProtocolNotSuported = 10004 ) func renderError(code int, err error) Common { result := Common{} result.Code = code result.Message = err.Error() server.Log.Error(err.Error()) return result } // DeviceRegisterArgs device register args type DeviceRegisterArgs struct { ProductKey string `json:"product_key" binding:"required"` DeviceCode string `json:"device_code" binding:"required"` Version string `json:"version" binding:"required"` ModuleName string `json:"module" binding:"required"` } // DeviceAuthArgs device authentication args type DeviceAuthArgs struct { DeviceId int64 `json:"device_id" binding:"required"` DeviceSecret string `json:"device_secret" binding:"required"` Protocol string `json:"protocol" binding:"required"` } // RegisterDevice 设备激活 func RegisterDevice(args DeviceRegisterArgs, r render.Render) { server.Log.Printf("ACTION RegisterDevice, args:: %v ", args) span, ctx := opentracing.StartSpanFromContext(context.Background(), "RegisterDevice") defer span.Finish() rpcargs := &rpcs.ArgsDeviceRegister{ ProductKey: args.ProductKey, DeviceCode: args.DeviceCode, DeviceVersion: args.Version, ModuleName: args.ModuleName, } device := &models.Device{} ext.SpanKindRPCClient.Set(span) err := server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.RegisterDevice", rpcargs, device) if err != nil { r.JSON(http.StatusOK, renderError(ErrSystemFault, err)) return } server.Log.Infof("register device success: %v", device) result := DeviceRegisterResponse{} result.Data = DeviceRegisterData{ DeviceId: int64(device.ID), DeviceSecret: device.DeviceSecret, DeviceKey: device.DeviceKey, DeviceIdentifier: device.DeviceIdentifier, } r.JSON(http.StatusOK, result) return } // AuthDevice device auth func AuthDevice(args DeviceAuthArgs, r render.Render) { server.Log.Printf("ACTION AuthDevice, args:: %v", args) device := &models.Device{} span, ctx := opentracing.StartSpanFromContext(context.Background(), "AuthDevice") defer span.Finish() ext.SpanKindRPCClient.Set(span) arg := uint64(args.DeviceId) err := server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.FindDeviceById", &arg, device) if err != nil { r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err)) return } if device.DeviceSecret != args.DeviceSecret { // device secret is wrong. r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("wrong device secret."))) return } hepler := token.NewHelper(*confRedisHost) token, err := hepler.GenerateToken(device.RecordId) if err != nil { r.JSON(http.StatusOK, renderError(ErrSystemFault, err)) return } var hosts []string switch args.Protocol { case "http": hosts, err = server.GetServerHosts(strings.ToUpper(args.Protocol)+"Access", "httphost") case "mqtt": hosts, err = server.GetServerHosts(strings.ToUpper(args.Protocol)+"Access", "tcphost") case "coap": hosts, err = server.GetServerHosts(strings.ToUpper(args.Protocol)+"Access", "udphost") default: err = errors.New("unsuported protocol: " + args.Protocol) } if err != nil { r.JSON(http.StatusOK, renderError(ErrProtocolNotSuported, err)) return } // just get a random host host := hosts[rand.Intn(len(hosts))] result := DeviceAuthResponse{} result.Data = DeviceAuthData{ AccessToken: hex.EncodeToString(token), AccessAddr: host, } server.Log.Infof("auth device success: %v, token: %x, access: %v", device, token, host) r.JSON(http.StatusOK, result) return }