123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- package main
- import (
- "context"
- "encoding/json"
- "errors"
- "sparrow/pkg/productconfig"
- "sparrow/pkg/rpcs"
- "github.com/opentracing/opentracing-go/ext"
- "github.com/opentracing/opentracing-go"
- "net/http"
- "sparrow/pkg/models"
- "sparrow/pkg/server"
- "github.com/go-martini/martini"
- "github.com/martini-contrib/render"
- )
- const (
- ErrOK = 0
- ErrSystemFault = 10001
- ErrProductNotFound = 10002
- ErrDeviceNotFound = 10003
- ErrDeviceNotOnline = 10004
- ErrWrongRequestFormat = 10005
- ErrWrongProductConfig = 10006
- ErrWrongQueryFormat = 10007
- ErrAccessDenied = 10008
- ErrIllegalityAction = 10009 //非法操作
- ErrWrongSecret = 10010 //
- )
- var (
- // ErrBadRequestString 参数不全错误
- errBadRequestString = errors.New("请求参数不全")
- errIllegalityString = errors.New("非法操作")
- )
- const (
- defaultTimeOut = 3 // seconds
- )
- func renderError(code int, err error) Common {
- result := Common{}
- result.Code = code
- result.Message = err.Error()
- server.Log.Error(err.Error())
- return result
- }
- func done(result interface{}) Common {
- return Common{
- Code: ErrOK,
- Message: "success",
- Result: result,
- }
- }
- // GetDeviceInfoByKey get device info with device key
- func GetDeviceInfoByKey(params martini.Params, req *http.Request, r render.Render) {
- key := req.URL.Query().Get("device_key")
- server.Log.Printf("ACTION GetDeviceInfoByKey, key:: %v", key)
- device := &models.Device{}
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByKey")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- span.SetTag("device_key", key)
- err := server.RPCCallByName(ctx, "registry", "Registry.ValidateDevice", key, device)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
- return
- }
- result := DeviceInfoResponse{
- Data: DeviceInfoData{
- Identifier: device.DeviceIdentifier,
- Name: device.DeviceName,
- Description: device.DeviceDescription,
- Version: device.DeviceVersion,
- },
- }
- r.JSON(http.StatusOK, result)
- return
- }
- // GetDeviceInfoByIdentifier get device info with device identifier
- func GetDeviceInfoByIdentifier(urlparams martini.Params, r render.Render) {
- identifier := urlparams["identifier"]
- server.Log.Printf("ACTION GetDeviceInfoByIdentifier, identifier:: %v", identifier)
- device := &models.Device{}
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByIdentifier")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- span.SetTag("identifier", identifier)
- err := server.RPCCallByName(ctx, "registry", "Registry.FindDeviceByIdentifier", identifier, device)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
- return
- }
- result := DeviceInfoResponse{
- Data: DeviceInfoData{
- Identifier: device.DeviceIdentifier,
- Name: device.DeviceName,
- Description: device.DeviceDescription,
- Version: device.DeviceVersion,
- },
- }
- r.JSON(http.StatusOK, result)
- return
- }
- func GetDeviceCurrentStatus(device *models.Device, config *productconfig.ProductConfig,
- urlparams martini.Params, r render.Render) {
- server.Log.Printf("ACTION GetDeviceCurrentStatus, identifier:: %v", device.DeviceIdentifier)
- statusargs := rpcs.ArgsGetStatus{
- Id: uint64(device.ID),
- }
- statusreply := rpcs.ReplyGetStatus{}
- //opentracing
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceCurrentStatus")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- err := server.RPCCallByName(ctx, "controller", "Controller.GetStatus", statusargs, &statusreply)
- if err != nil {
- server.Log.Errorf("get devie status error: %v", err)
- r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
- return
- }
- status, err := config.StatusToMap(statusreply.Status)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- result := DeviceStatusResponse{
- Data: status,
- }
- r.JSON(http.StatusOK, result)
- return
- }
- // GetDeviceLatestStatus get device latest status
- func GetDeviceLatestStatus() {
- }
- // SetDeviceStatus set device status
- func SetDeviceStatus(device *models.Device, config *productconfig.ProductConfig,
- urlparams martini.Params, req *http.Request, r render.Render) {
- server.Log.Printf("ACTION GetDeviceCurrentStatus, identifier:: %v,request: %v", device.DeviceIdentifier, req.Body)
- var args interface{}
- decoder := json.NewDecoder(req.Body)
- err := decoder.Decode(&args)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- m, ok := args.(map[string]interface{})
- if !ok {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- status, err := config.MapToStatus(m)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- statusargs := rpcs.ArgsSetStatus{
- DeviceId: uint64(device.ID),
- Status: status,
- }
- statusreply := rpcs.ReplySetStatus{}
- //opentracing
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "SetDeviceStatus")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- err = server.RPCCallByName(ctx, "controller", "Controller.SetStatus", statusargs, &statusreply)
- if err != nil {
- server.Log.Errorf("set devie status error: %v", err)
- r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
- return
- }
- r.JSON(http.StatusOK, Common{})
- return
- }
- // SendCommandToDevice send command to device
- func SendCommandToDevice(device *models.Device, config *productconfig.ProductConfig,
- urlparams martini.Params, req *http.Request, r render.Render) {
- timeout := req.URL.Query().Get("timeout")
- server.Log.Printf("ACTION SendCommandToDevice, identifier:: %v, request: %v, timeout: %v",
- device.DeviceIdentifier, req.Body, timeout)
- var args interface{}
- decoder := json.NewDecoder(req.Body)
- err := decoder.Decode(&args)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- m, ok := args.(map[string]interface{})
- if !ok {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- command, err := config.MapToCommand(m)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- cmdargs := rpcs.ArgsSendCommand{
- DeviceId: uint64(device.ID),
- SubDevice: uint16(command.Head.SubDeviceid),
- No: uint16(command.Head.No),
- WaitTime: uint32(defaultTimeOut),
- Params: command.Params,
- }
- cmdreply := rpcs.ReplySendCommand{}
- //opentracing
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "SendCommandToDevice")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- err = server.RPCCallByName(ctx, "controller", "Controller.SendCommand", cmdargs, &cmdreply)
- if err != nil {
- server.Log.Errorf("send devie command error: %v", err)
- r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
- return
- }
- r.JSON(http.StatusOK, Common{})
- return
- }
- // AddRule 增加设备规则
- func AddRule(device *models.Device, req *http.Request, r render.Render) {
- var ruleReq CreateRuleRequest
- decoder := json.NewDecoder(req.Body)
- err := decoder.Decode(&ruleReq)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- rule := &models.Rule{
- DeviceID: int64(device.ID),
- RuleType: ruleReq.Type,
- Trigger: ruleReq.Trigger,
- Target: ruleReq.Target,
- Action: ruleReq.Action,
- }
- reply := &rpcs.ReplyEmptyResult{}
- //opentracing
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "AddRule")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- err = server.RPCCallByName(ctx, "registry", "Registry.CreateRule", rule, reply)
- if err != nil {
- server.Log.Errorf("create device rule error: %v", err)
- r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
- return
- }
- r.JSON(http.StatusOK, Common{})
- return
- }
- func AppAuth(req *http.Request, r render.Render) {
- var ruleReq rpcs.ArgsAppAuth
- decoder := json.NewDecoder(req.Body)
- err := decoder.Decode(&ruleReq)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
- return
- }
- span, ctx := opentracing.StartSpanFromContext(context.Background(), "DeveloperRegist")
- defer span.Finish()
- ext.SpanKindRPCClient.Set(span)
- app := &models.Application{}
- err = server.RPCCallByName(ctx, "registry", "Registry.FindApplicationByAppKey", ruleReq, app)
- if err != nil {
- r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("Invalid secret key")))
- return
- }
- if app.SecretKey != ruleReq.Secretkey {
- // device secret is wrong.
- r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("wrong application secret.")))
- return
- }
- result := AppAuthDataResponse{
- AccessToken: TokenMaker(app),
- }
- r.JSON(http.StatusOK, result)
- return
- }
|