actions.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "sparrow/pkg/productconfig"
  7. "sparrow/pkg/rpcs"
  8. "github.com/opentracing/opentracing-go/ext"
  9. "github.com/opentracing/opentracing-go"
  10. "net/http"
  11. "sparrow/pkg/models"
  12. "sparrow/pkg/server"
  13. "github.com/go-martini/martini"
  14. "github.com/martini-contrib/render"
  15. )
  16. const (
  17. ErrOK = 0
  18. ErrSystemFault = 10001
  19. ErrProductNotFound = 10002
  20. ErrDeviceNotFound = 10003
  21. ErrDeviceNotOnline = 10004
  22. ErrWrongRequestFormat = 10005
  23. ErrWrongProductConfig = 10006
  24. ErrWrongQueryFormat = 10007
  25. ErrAccessDenied = 10008
  26. ErrIllegalityAction = 10009 //非法操作
  27. ErrWrongSecret = 10010 //
  28. )
  29. var (
  30. // ErrBadRequestString 参数不全错误
  31. errBadRequestString = errors.New("请求参数不全")
  32. errIllegalityString = errors.New("非法操作")
  33. )
  34. const (
  35. defaultTimeOut = 3 // seconds
  36. )
  37. func renderError(code int, err error) Common {
  38. result := Common{}
  39. result.Code = code
  40. result.Message = err.Error()
  41. server.Log.Error(err.Error())
  42. return result
  43. }
  44. func done(result interface{}) Common {
  45. return Common{
  46. Code: ErrOK,
  47. Message: "success",
  48. Result: result,
  49. }
  50. }
  51. // GetDeviceInfoByKey get device info with device key
  52. func GetDeviceInfoByKey(params martini.Params, req *http.Request, r render.Render) {
  53. key := req.URL.Query().Get("device_key")
  54. server.Log.Printf("ACTION GetDeviceInfoByKey, key:: %v", key)
  55. device := &models.Device{}
  56. span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByKey")
  57. defer span.Finish()
  58. ext.SpanKindRPCClient.Set(span)
  59. span.SetTag("device_key", key)
  60. err := server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.ValidateDevice", key, device)
  61. if err != nil {
  62. r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
  63. return
  64. }
  65. result := DeviceInfoResponse{
  66. Data: DeviceInfoData{
  67. Identifier: device.DeviceIdentifier,
  68. Name: device.DeviceName,
  69. Description: device.DeviceDescription,
  70. Version: device.DeviceVersion,
  71. },
  72. }
  73. r.JSON(http.StatusOK, result)
  74. return
  75. }
  76. // GetDeviceInfoByIdentifier get device info with device identifier
  77. func GetDeviceInfoByIdentifier(urlparams martini.Params, r render.Render) {
  78. identifier := urlparams["identifier"]
  79. server.Log.Printf("ACTION GetDeviceInfoByIdentifier, identifier:: %v", identifier)
  80. device := &models.Device{}
  81. span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByIdentifier")
  82. defer span.Finish()
  83. ext.SpanKindRPCClient.Set(span)
  84. span.SetTag("identifier", identifier)
  85. err := server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", identifier, device)
  86. if err != nil {
  87. r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
  88. return
  89. }
  90. result := DeviceInfoResponse{
  91. Data: DeviceInfoData{
  92. Identifier: device.DeviceIdentifier,
  93. Name: device.DeviceName,
  94. Description: device.DeviceDescription,
  95. Version: device.DeviceVersion,
  96. },
  97. }
  98. r.JSON(http.StatusOK, result)
  99. return
  100. }
  101. func GetDeviceCurrentStatus(device *models.Device, config *productconfig.ProductConfig,
  102. urlparams martini.Params, r render.Render) {
  103. server.Log.Printf("ACTION GetDeviceCurrentStatus, identifier:: %v", device.DeviceIdentifier)
  104. statusargs := rpcs.ArgsGetStatus{
  105. Id: device.RecordId,
  106. }
  107. statusreply := rpcs.ReplyGetStatus{}
  108. //opentracing
  109. span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceCurrentStatus")
  110. defer span.Finish()
  111. ext.SpanKindRPCClient.Set(span)
  112. err := server.RPCCallByName(ctx, rpcs.ControllerName, "Controller.GetStatus", statusargs, &statusreply)
  113. if err != nil {
  114. server.Log.Errorf("get devie status error: %v", err)
  115. r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
  116. return
  117. }
  118. status, err := config.StatusToMap(statusreply.Status)
  119. if err != nil {
  120. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  121. return
  122. }
  123. result := DeviceStatusResponse{
  124. Data: status,
  125. }
  126. r.JSON(http.StatusOK, result)
  127. return
  128. }
  129. // GetDeviceLatestStatus get device latest status
  130. func GetDeviceLatestStatus() {
  131. }
  132. // SetDeviceStatus set device status
  133. func SetDeviceStatus(device *models.Device, config *productconfig.ProductConfig,
  134. urlparams martini.Params, req *http.Request, r render.Render) {
  135. server.Log.Printf("ACTION GetDeviceCurrentStatus, identifier:: %v,request: %v", device.DeviceIdentifier, req.Body)
  136. var args interface{}
  137. decoder := json.NewDecoder(req.Body)
  138. err := decoder.Decode(&args)
  139. if err != nil {
  140. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  141. return
  142. }
  143. m, ok := args.(map[string]interface{})
  144. if !ok {
  145. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  146. return
  147. }
  148. status, err := config.MapToStatus(m)
  149. if err != nil {
  150. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  151. return
  152. }
  153. statusargs := rpcs.ArgsSetStatus{
  154. DeviceId: device.RecordId,
  155. Status: status,
  156. }
  157. statusreply := rpcs.ReplySetStatus{}
  158. //opentracing
  159. span, ctx := opentracing.StartSpanFromContext(context.Background(), "SetDeviceStatus")
  160. defer span.Finish()
  161. ext.SpanKindRPCClient.Set(span)
  162. err = server.RPCCallByName(ctx, rpcs.ControllerName, "Controller.SetStatus", statusargs, &statusreply)
  163. if err != nil {
  164. server.Log.Errorf("set devie status error: %v", err)
  165. r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
  166. return
  167. }
  168. r.JSON(http.StatusOK, Common{})
  169. return
  170. }
  171. // SendCommandToDevice send command to device
  172. func SendCommandToDevice(device *models.Device, config *productconfig.ProductConfig,
  173. urlparams martini.Params, req *http.Request, r render.Render) {
  174. timeout := req.URL.Query().Get("timeout")
  175. server.Log.Printf("ACTION SendCommandToDevice, identifier:: %v, request: %v, timeout: %v",
  176. device.DeviceIdentifier, req.Body, timeout)
  177. var args interface{}
  178. decoder := json.NewDecoder(req.Body)
  179. err := decoder.Decode(&args)
  180. if err != nil {
  181. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  182. return
  183. }
  184. m, ok := args.(map[string]interface{})
  185. if !ok {
  186. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  187. return
  188. }
  189. command, err := config.MapToCommand(m)
  190. if err != nil {
  191. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  192. return
  193. }
  194. cmdargs := rpcs.ArgsSendCommand{
  195. DeviceId: device.RecordId,
  196. SubDevice: uint16(command.Head.SubDeviceid),
  197. No: uint16(command.Head.No),
  198. WaitTime: uint32(defaultTimeOut),
  199. Params: command.Params,
  200. }
  201. cmdreply := rpcs.ReplySendCommand{}
  202. //opentracing
  203. span, ctx := opentracing.StartSpanFromContext(context.Background(), "SendCommandToDevice")
  204. defer span.Finish()
  205. ext.SpanKindRPCClient.Set(span)
  206. err = server.RPCCallByName(ctx, rpcs.ControllerName, "Controller.SendCommand", cmdargs, &cmdreply)
  207. if err != nil {
  208. server.Log.Errorf("send devie command error: %v", err)
  209. r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
  210. return
  211. }
  212. r.JSON(http.StatusOK, Common{})
  213. return
  214. }
  215. // AddRule 增加设备规则
  216. func AddRule(device *models.Device, req *http.Request, r render.Render) {
  217. var ruleReq CreateRuleRequest
  218. decoder := json.NewDecoder(req.Body)
  219. err := decoder.Decode(&ruleReq)
  220. if err != nil {
  221. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  222. return
  223. }
  224. rule := &models.Rule{
  225. DeviceID: device.RecordId,
  226. RuleType: ruleReq.Type,
  227. Trigger: ruleReq.Trigger,
  228. Target: ruleReq.Target,
  229. Action: ruleReq.Action,
  230. }
  231. reply := &rpcs.ReplyEmptyResult{}
  232. //opentracing
  233. span, ctx := opentracing.StartSpanFromContext(context.Background(), "AddRule")
  234. defer span.Finish()
  235. ext.SpanKindRPCClient.Set(span)
  236. err = server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.CreateRule", rule, reply)
  237. if err != nil {
  238. server.Log.Errorf("create device rule error: %v", err)
  239. r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
  240. return
  241. }
  242. r.JSON(http.StatusOK, Common{})
  243. return
  244. }
  245. func AppAuth(req *http.Request, r render.Render) {
  246. var ruleReq rpcs.ArgsAppAuth
  247. decoder := json.NewDecoder(req.Body)
  248. err := decoder.Decode(&ruleReq)
  249. if err != nil {
  250. r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
  251. return
  252. }
  253. span, ctx := opentracing.StartSpanFromContext(context.Background(), "AppAuth")
  254. defer span.Finish()
  255. ext.SpanKindRPCClient.Set(span)
  256. app := &models.Application{}
  257. err = server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.FindApplicationByAppKey", ruleReq, app)
  258. if err != nil {
  259. r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("Invalid secret key")))
  260. return
  261. }
  262. if app.SecretKey != ruleReq.Secretkey {
  263. // device secret is wrong.
  264. r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("wrong application secret.")))
  265. return
  266. }
  267. result := AppAuthDataResponse{
  268. AccessToken: TokenMaker(app),
  269. }
  270. r.JSON(http.StatusOK, Common{
  271. Result: result,
  272. })
  273. return
  274. }