yufan_gate.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. package v1
  2. import (
  3. "context"
  4. "fmt"
  5. "git.getensh.com/common/gopkgs/logger"
  6. "git.getensh.com/common/gopkgs/tasker/httptasker"
  7. "github.com/gin-gonic/gin"
  8. "github.com/tidwall/gjson"
  9. "go.uber.org/zap"
  10. "io/ioutil"
  11. "net/http"
  12. param_v1 "property-device-gateway/param/v1"
  13. "property-device-gateway/parser"
  14. "property-device-gateway/pb"
  15. pb_v1 "property-device-gateway/pb/v1"
  16. "strconv"
  17. "strings"
  18. "time"
  19. )
  20. const (
  21. PersonRegersterTaskName = "person/create"
  22. PersonUpdateTaskName = "person/update"
  23. PersonDelTaskName = "person/delete"
  24. PhotoRegisterByUrlTaskName = "face/createByUrl"
  25. TakePhotoRegisterTaskName = "face/takeImg"
  26. PhotoDelTaskName = "face/delete"
  27. DeviceRebootTaskName = "restartDevice"
  28. DeviceOpenTaskName = "device/openDoorControl"
  29. PhotoUpdateByUrlTaskName = "face"
  30. )
  31. type PersonRegesterTask struct {
  32. TaskNo string `json:"taskNo"`
  33. InterfaceName string `json:"interfaceName"`
  34. Result bool `json:"result"`
  35. Person PersonRegesterData `json:"person"`
  36. }
  37. type PersonRegesterData struct {
  38. Id string `json:"id"`
  39. Name string `json:"name"`
  40. IdCardNum string `json:"idcardNum"`
  41. IdNumber string `json:"iDNumber"`
  42. FacePermission int `json:"facePermission"`
  43. IdCardPermission int `json:"idCardPermission"`
  44. FaceAndCardPermission int `json:"faceAndCardPermission"`
  45. IDPermission int `json:"iDPermission"`
  46. Tag string `json:"tag"`
  47. Phone string `json:"phone"`
  48. }
  49. type PersonUpdateTask struct {
  50. TaskNo string `json:"taskNo"`
  51. InterfaceName string `json:"interfaceName"`
  52. Result bool `json:"result"`
  53. Person PersonUpdateData `json:"person"`
  54. }
  55. type PersonUpdateData struct {
  56. Id string `json:"id"`
  57. Name string `json:"name"`
  58. IdCardNum string `json:"idcardNum"`
  59. IdNumber string `json:"iDNumber"`
  60. FacePermission string `json:"facePermission"`
  61. IdCardPermission string `json:"idCardPermission"`
  62. FaceAndCardPermission string `json:"faceAndCardPermission"`
  63. IDPermission string `json:"iDPermission"`
  64. Tag string `json:"tag"`
  65. Phone string `json:"phone"`
  66. }
  67. type PersonDelTask struct {
  68. TaskNo string `json:"taskNo"`
  69. InterfaceName string `json:"interfaceName"`
  70. Result bool `json:"result"`
  71. Id string `json:"id"`
  72. }
  73. type PhoneRegisterTask struct {
  74. TaskNo string `json:"taskNo"`
  75. InterfaceName string `json:"interfaceName"`
  76. Result bool `json:"result"`
  77. PhotoRegisterData
  78. }
  79. type PhotoRegisterData struct {
  80. PersonId string `json:"personId"`
  81. FaceId string `json:"faceId"`
  82. ImgUrl string `json:"imgUrl"`
  83. }
  84. type PhotoUpdateTask struct {
  85. TaskNo string `json:"taskNo"`
  86. InterfaceName string `json:"interfaceName"`
  87. Result bool `json:"result"`
  88. PhotoUpdateData
  89. }
  90. type PhotoUpdateData struct {
  91. PersonId string `json:"personId"`
  92. FaceId string `json:"faceId"`
  93. Url string `json:"url"`
  94. }
  95. type PhoneDelTask struct {
  96. TaskNo string `json:"taskNo"`
  97. InterfaceName string `json:"interfaceName"`
  98. Result bool `json:"result"`
  99. FaceId string `json:"faceId"`
  100. }
  101. type TaskPhotoRegister struct {
  102. TaskNo string `json:"taskNo"`
  103. InterfaceName string `json:"interfaceName"`
  104. Result bool `json:"result"`
  105. PersonId string `json:"personId"`
  106. ImgUrl string `json:"imgUrl"`
  107. FaceId string `json:"faceId"`
  108. }
  109. type DeviceRebootTask struct {
  110. TaskNo string `json:"taskNo"`
  111. InterfaceName string `json:"interfaceName"`
  112. Result bool `json:"result"`
  113. }
  114. type DeviceOpenTask struct {
  115. TaskNo string `json:"taskNo"`
  116. InterfaceName string `json:"interfaceName"`
  117. Result bool `json:"result"`
  118. // 1:开门 2:串口 3:韦根 4:表示自定义文字弹
  119. OType int32 `json:"type"`
  120. }
  121. func getYufanTask(param string, cmdId int64) interface{} {
  122. taskNoStr := fmt.Sprintf("\"taskNo\":\"%d\"", cmdId)
  123. param = strings.ReplaceAll(param, `"taskNo":""`, taskNoStr)
  124. taskName := gjson.GetBytes([]byte(param), "interfaceName").String()
  125. switch taskName {
  126. case PersonRegersterTaskName:
  127. ret := PersonRegesterTask{}
  128. json.Unmarshal([]byte(param), &ret)
  129. return ret
  130. case PersonDelTaskName:
  131. ret := PersonDelTask{}
  132. json.Unmarshal([]byte(param), &ret)
  133. return ret
  134. case PhotoRegisterByUrlTaskName:
  135. ret := TaskPhotoRegister{}
  136. json.Unmarshal([]byte(param), &ret)
  137. return ret
  138. case PhotoUpdateByUrlTaskName:
  139. ret := PhotoUpdateTask{}
  140. json.Unmarshal([]byte(param), &ret)
  141. return ret
  142. }
  143. return nil
  144. }
  145. //
  146. // @Summary 宇泛心跳
  147. // @Description 宇泛心跳
  148. // @Tags 宇泛
  149. // @Accept json
  150. // @Produce json
  151. // @Failure 500 {object} base.HTTPError
  152. // @Router /api/yufan/heartbeat [post]
  153. func (c *Controller) YuFanHeartBeat(ctx *gin.Context) {
  154. // 解析参数
  155. body, err := ioutil.ReadAll(ctx.Request.Body)
  156. resp := param_v1.YuFanHeartBeatResponse{Result: false}
  157. if err != nil {
  158. ctx.JSON(http.StatusOK, resp)
  159. return
  160. }
  161. fmt.Printf("心跳body:%s\n", body)
  162. defer ctx.Request.Body.Close()
  163. sn := gjson.GetBytes(body, "deviceKey").String()
  164. if sn == "" {
  165. ctx.JSON(http.StatusOK, resp)
  166. return
  167. }
  168. handleServiceTask := func() error {
  169. mreq := pb_v1.GateOnlineRequest{Sn: sn, Protocol: GateProtocolYufanHttpV1}
  170. mreply, err := pb.Device.GateOnline(context.Background(), &mreq)
  171. if err != nil {
  172. s, _ := json.MarshalToString(mreq)
  173. logger.Error("func",
  174. zap.String("call", "pb.Device.GateOnline"),
  175. zap.String("params", s),
  176. zap.String("error", err.Error()))
  177. }
  178. // 查看是否有命令需要
  179. if mreply.HasTask {
  180. resp.Result = true
  181. }
  182. ctx.JSON(http.StatusOK, resp)
  183. return nil
  184. }
  185. // 执行任务
  186. httptasker.Exec(ctx, handleServiceTask)
  187. }
  188. //
  189. // @Summary 宇泛获取任务
  190. // @Description 宇泛获取任务
  191. // @Tags 宇泛
  192. // @Accept json
  193. // @Produce json
  194. // @Failure 500 {object} base.HTTPError
  195. // @Router /api/yufan/task [post]
  196. func (c *Controller) YuFanTaskGet(ctx *gin.Context) {
  197. body, err := ioutil.ReadAll(ctx.Request.Body)
  198. resp := param_v1.YuFanHeartBeatResponse{Result: false}
  199. if err != nil {
  200. ctx.JSON(http.StatusOK, resp)
  201. return
  202. }
  203. fmt.Printf("任务body:%s\n", body)
  204. defer ctx.Request.Body.Close()
  205. sn := gjson.GetBytes(body, "deviceKey").String()
  206. if sn == "" {
  207. ctx.JSON(http.StatusOK, resp)
  208. return
  209. }
  210. handleServiceTask := func() error {
  211. mreq := pb_v1.GateCommandUseRequest{Sn: sn, Protocol: GateProtocolYufanHttpV1}
  212. mreply, err := pb.Device.GateCommandUse(context.Background(), &mreq)
  213. if err != nil {
  214. s, _ := json.MarshalToString(mreq)
  215. logger.Error("func",
  216. zap.String("call", "pb.Device.GateCommandUse"),
  217. zap.String("params", s),
  218. zap.String("error", err.Error()))
  219. ctx.JSON(http.StatusOK, resp)
  220. return nil
  221. }
  222. params := ""
  223. if params == "" {
  224. ctx.JSON(http.StatusOK, resp)
  225. return nil
  226. }
  227. yufanTask := getYufanTask(params, mreply.Id)
  228. if yufanTask == nil {
  229. ctx.JSON(http.StatusOK, resp)
  230. return nil
  231. }
  232. ctx.JSON(http.StatusOK, yufanTask)
  233. return nil
  234. }
  235. // 执行任务
  236. httptasker.Exec(ctx, handleServiceTask)
  237. }
  238. func resultParse(info gjson.Result) (int64, string, string) {
  239. result := info.Get("result").Int()
  240. code := info.Get("code").String()
  241. msg := info.Get("msg").String()
  242. return result, code, msg
  243. }
  244. //
  245. // @Summary 宇泛任务结果
  246. // @Description 宇泛获取任务结果
  247. // @Tags 宇泛
  248. // @Accept json
  249. // @Produce json
  250. // @Failure 500 {object} base.HTTPError
  251. // @Router /api/yufan/task_result [post]
  252. func (c *Controller) YuFanTaskResult(ctx *gin.Context) {
  253. body, err := ioutil.ReadAll(ctx.Request.Body)
  254. resp := param_v1.YuFanHeartBeatResponse{Result: false}
  255. if err != nil {
  256. ctx.JSON(http.StatusOK, resp)
  257. return
  258. }
  259. fmt.Printf("任务结果body:%s\n", body)
  260. defer ctx.Request.Body.Close()
  261. sn := gjson.GetBytes(body, "deviceKey").String()
  262. cmdId := gjson.GetBytes(body, "taskNo").String()
  263. info := gjson.GetBytes(body, "result")
  264. if sn == "" {
  265. ctx.JSON(http.StatusOK, resp)
  266. return
  267. }
  268. handleServiceTask := func() error {
  269. result, code, msg := resultParse(info)
  270. // todo 服务
  271. fmt.Printf("结果:%v, %v,%v,%v\n", cmdId, result, code, msg)
  272. cmdIdInt, _ := strconv.ParseInt(cmdId, 10, 64)
  273. mreq := pb_v1.GateCommandResultRequest{
  274. Id: cmdIdInt,
  275. //CmdCode: int32(SaiboCommandToLocaolM[int32(req.CmdCode)]),
  276. ResultStatus: 1,
  277. ResultDesc: "",
  278. Sn: sn,
  279. Protocol: GateProtocolYufanHttpV1,
  280. Content: string(body),
  281. }
  282. // todo 测试是否有code
  283. if result != 1 {
  284. mreq.ResultStatus = 2
  285. mreq.ResultDesc = msg
  286. }
  287. mreply, err := pb.Device.GateCommandResult(context.Background(), &mreq)
  288. if err != nil {
  289. s, _ := json.MarshalToString(mreq)
  290. logger.Error("func",
  291. zap.String("call", "pb.Device.GateCommandResult"),
  292. zap.String("params", s),
  293. zap.String("error", err.Error()))
  294. ctx.JSON(http.StatusOK, resp)
  295. return nil
  296. }
  297. if mreply.HasTask {
  298. resp.Result = false
  299. }
  300. ctx.JSON(http.StatusOK, resp)
  301. return nil
  302. }
  303. // 执行任务
  304. httptasker.Exec(ctx, handleServiceTask)
  305. }
  306. //
  307. // @Summary 宇泛照片回调
  308. // @Description 宇泛照片回调
  309. // @Tags 宇泛
  310. // @Accept json
  311. // @Produce json
  312. // @Failure 500 {object} base.HTTPError
  313. // @Router /api/yufan/photo [post]
  314. func (c *Controller) YuFanPhotoCallback(ctx *gin.Context) {
  315. body, err := ioutil.ReadAll(ctx.Request.Body)
  316. resp := param_v1.CallbackResponse{Result: 1, Success: true}
  317. if err != nil {
  318. ctx.JSON(http.StatusOK, resp)
  319. return
  320. }
  321. fmt.Printf("照片回调body:%s\n", body)
  322. defer ctx.Request.Body.Close()
  323. deviceId := gjson.GetBytes(body, "deviceKey").String()
  324. uid := gjson.GetBytes(body, "personId").String()
  325. path := gjson.GetBytes(body, "newImgPath").String()
  326. faceId := gjson.GetBytes(body, "faceId").String()
  327. if deviceId == "" || uid == "" || faceId == "" || path == "" {
  328. ctx.JSON(http.StatusOK, resp)
  329. return
  330. }
  331. handleServiceTask := func() error {
  332. // todo 服务更新照片
  333. ctx.JSON(http.StatusOK, resp)
  334. return nil
  335. }
  336. // 执行任务
  337. httptasker.Exec(ctx, handleServiceTask)
  338. }
  339. //
  340. // @Summary 宇泛识别结果回调
  341. // @Description 宇泛识别结果回调
  342. // @Tags 宇泛
  343. // @Accept json
  344. // @Produce json
  345. // @Failure 500 {object} base.HTTPError
  346. // @Router /api/yufan/result [post]
  347. func (c *Controller) YuFanResultCallback(ctx *gin.Context) {
  348. body, err := ioutil.ReadAll(ctx.Request.Body)
  349. resp := param_v1.CallbackResponse{Result: 1, Success: true}
  350. if err != nil {
  351. ctx.JSON(http.StatusOK, resp)
  352. return
  353. }
  354. fmt.Printf("识别结果回调body:%s\n", body)
  355. defer ctx.Request.Body.Close()
  356. sn := gjson.GetBytes(body, "deviceKey").String()
  357. personId := gjson.GetBytes(body, "personId").String()
  358. idcardNum := gjson.GetBytes(body, "idcardNum").String()
  359. model := gjson.GetBytes(body, "model").String()
  360. identifyType := gjson.GetBytes(body, "identifyType").String()
  361. mstime := gjson.GetBytes(body, "time").String()
  362. mstimeInt, _ := strconv.ParseInt(mstime, 10, 64)
  363. t := time.UnixMilli(mstimeInt)
  364. if sn == "" {
  365. ctx.JSON(http.StatusOK, resp)
  366. return
  367. }
  368. if identifyType != "1" {
  369. ctx.JSON(http.StatusOK, resp)
  370. return
  371. }
  372. if model != "0" && model != "3" {
  373. ctx.JSON(http.StatusOK, resp)
  374. return
  375. }
  376. codeVal := personId
  377. codeType := 1
  378. uid := int64(0)
  379. uid, _ = strconv.ParseInt(personId, 10, 64)
  380. openType := int32(3)
  381. if model == "3" {
  382. codeVal = idcardNum
  383. codeType = 2
  384. openType = 2
  385. }
  386. // 检查白名单
  387. mreq := pb_v1.GateWhiteMatchRequest{
  388. CodeVal: codeVal,
  389. CodeType: int32(codeType),
  390. Sn: sn,
  391. Protocol: GateProtocolYufanHttpV1,
  392. }
  393. mreply, err := pb.Device.GateWhiteMatch(context.Background(), &mreq)
  394. if err != nil {
  395. s, _ := json.MarshalToString(mreq)
  396. logger.Error("func",
  397. zap.String("call", "pb.Device.GateWhiteMatch"),
  398. zap.String("params", s),
  399. zap.String("error", err.Error()))
  400. ctx.JSON(http.StatusOK, resp)
  401. return
  402. }
  403. if mreply.DeviceId == 0 {
  404. ctx.JSON(http.StatusOK, resp)
  405. return
  406. }
  407. handleServiceTask := func() error {
  408. fmt.Printf("%v,%v,%v,%v\n", personId, idcardNum, model, identifyType)
  409. recordReq := pb_v1.GateRecordAddRequest{
  410. DeviceId: mreply.DeviceId,
  411. Location: mreply.Location,
  412. Direction: mreply.Direction,
  413. HouseholdUser: mreply.Name,
  414. HouseholdIdNumber: mreply.IdNumber,
  415. HouseholdHousename: mreply.HouseName,
  416. CardNumber: mreply.CardNumber,
  417. CardOwner: mreply.Name,
  418. Online: 2,
  419. GardenId: mreply.GardenId,
  420. // 1 访客 2 非访客
  421. IsVisitor: 2,
  422. // 开门时间
  423. OpenTime: t.Unix(),
  424. HouseholdUid: uid,
  425. VisitorPhone: "vphone",
  426. VisitorName: "vname",
  427. Sn: sn,
  428. Protocol: GateProtocolYufanHttpV1,
  429. OpenType: openType,
  430. }
  431. _, _ = pb.Device.GateRecordAdd(context.Background(), &recordReq)
  432. ctx.JSON(http.StatusOK, resp)
  433. return nil
  434. }
  435. // 执行任务
  436. httptasker.Exec(ctx, handleServiceTask)
  437. }
  438. func checkQCode(codeStr string, gateKey string) (string, int32, string, string, int64) {
  439. loc, _ := time.LoadLocation("Local")
  440. visitor := int32(2)
  441. vname, vphone := "", ""
  442. vid := int64(0)
  443. text := Rc4Decrypt(codeStr, gateKey)
  444. if text == "" {
  445. return "", 0, "", "", 0
  446. }
  447. length := len(text)
  448. array := strings.Split(text[1:length-1], ",")
  449. uid := array[0]
  450. if len(array) < 4 {
  451. return "", 0, "", "", 0
  452. }
  453. subArray := strings.Split(array[0], "-")
  454. if len(subArray) > 3 {
  455. uid = subArray[0]
  456. visitor = 1
  457. vphone = subArray[1]
  458. vname = subArray[2]
  459. vid, _ = strconv.ParseInt(subArray[3], 10, 64)
  460. }
  461. start, _ := time.ParseInLocation("20060102150405", array[2], loc)
  462. end, _ := time.ParseInLocation("20060102150405", array[3], loc)
  463. now := time.Now()
  464. if now.Unix() < start.Unix() || now.Unix() > end.Unix() {
  465. return "", 0, "", "", 0
  466. }
  467. return uid, visitor, vname, vphone, vid
  468. }
  469. func whiteCheck(sn string, protocol int32, codeVal string, codeType int32) (*pb_v1.GateWhiteMatchReply, error) {
  470. mreq := pb_v1.GateWhiteMatchRequest{
  471. Sn: sn,
  472. Protocol: protocol,
  473. CodeVal: codeVal,
  474. CodeType: codeType,
  475. }
  476. return pb.Device.GateWhiteMatch(context.Background(), &mreq)
  477. }
  478. //
  479. // @Summary 二维码回调
  480. // @Description 二维码回调
  481. // @Tags 宇泛
  482. // @Accept json
  483. // @Produce json
  484. // @Failure 500 {object} base.HTTPError
  485. // @Router /api/yufan/qcode [post]
  486. func (c *Controller) YufanQcodeCallback(ctx *gin.Context) {
  487. body, err := ioutil.ReadAll(ctx.Request.Body)
  488. resp := param_v1.QcodeCallbackResponse{TttsModeContent: "自定义语音输出", DisplayModContent: "界面自定义显示", IsOpenRelay: 0}
  489. if err != nil {
  490. ctx.JSON(http.StatusOK, resp)
  491. return
  492. }
  493. fmt.Printf("识别结果回调body:%s\n", body)
  494. defer ctx.Request.Body.Close()
  495. sn := gjson.GetBytes(body, "deviceKey").String()
  496. qrdata := gjson.GetBytes(body, "QRdata").String()
  497. uidStr, visitor, vname, vphone, vid := checkQCode(qrdata, parser.Conf.GateKey)
  498. if uidStr == "" {
  499. ctx.JSON(http.StatusOK, resp)
  500. return
  501. }
  502. uid, _ := strconv.ParseInt(uidStr, 10, 64)
  503. whiteInfo, err := whiteCheck(sn, GateProtocolYufanHttpV1, uidStr, 1)
  504. if err != nil || whiteInfo.Status != 1 {
  505. ctx.JSON(http.StatusOK, resp)
  506. return
  507. }
  508. now := time.Now()
  509. if visitor == 1 {
  510. vreq := pb_v1.GateVisitorCheckRequest{
  511. Id: vid,
  512. OpenTime: now.Unix(),
  513. DeviceId: whiteInfo.DeviceId,
  514. }
  515. _, err := pb.Device.GateVisitorCheck(context.Background(), &vreq)
  516. if err != nil {
  517. ctx.JSON(http.StatusOK, resp)
  518. return
  519. }
  520. }
  521. handleServiceTask := func() error {
  522. recordReq := pb_v1.GateRecordAddRequest{
  523. Sn: sn,
  524. Protocol: GateProtocolSaiboMqttV1,
  525. OpenTime: now.Unix(),
  526. HouseholdUid: uid,
  527. Location: whiteInfo.Location,
  528. Direction: whiteInfo.Direction,
  529. HouseholdIdNumber: whiteInfo.IdNumber,
  530. HouseholdHousename: whiteInfo.HouseName,
  531. DeviceId: whiteInfo.DeviceId,
  532. HouseholdUser: whiteInfo.Name,
  533. IsVisitor: visitor,
  534. GardenId: whiteInfo.GardenId,
  535. OpenType: 1,
  536. CardNumber: "",
  537. VisitorPhone: vphone,
  538. VisitorName: vname,
  539. }
  540. _, _ = pb.Device.GateRecordAdd(context.Background(), &recordReq)
  541. resp.IsOpenRelay = 1
  542. ctx.JSON(http.StatusOK, resp)
  543. return nil
  544. }
  545. // 执行任务
  546. httptasker.Exec(ctx, handleServiceTask)
  547. }