code_gate.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. package v1
  2. import (
  3. "context"
  4. "crypto/rc4"
  5. "encoding/hex"
  6. "fmt"
  7. "git.getensh.com/common/gopkgs/logger"
  8. "git.getensh.com/common/gopkgs/tasker/httptasker"
  9. "github.com/gin-gonic/gin"
  10. "go.uber.org/zap"
  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. /*
  21. var commandCodeMap = map[int32]string{
  22. 1: "远程开门",
  23. 2: "重启设备",
  24. 4: "获取设备参数",
  25. 5: "设置设备参数",
  26. 6: "下发白名单",
  27. 7: "清空设备白名单",
  28. 8: "清空设备刷卡记录",
  29. 9: "扫码显示参数",
  30. 10: "查询是否存在白名单",
  31. 99: "恢复出厂",
  32. }
  33. */
  34. const (
  35. SaiboOpenCommand = 1
  36. SaiboRebootCommand = 2
  37. SaiboDownCommand = 6
  38. SaiboQueryCommand = 10
  39. )
  40. const (
  41. OpenCommand = 1
  42. RebootCommand = 2
  43. DownCommand = 3
  44. DelCommand = 4
  45. QueryCommand = 5
  46. UpdatePicCommand = 6
  47. AddPicCommand = 7
  48. )
  49. var LocalCommandToSaiboM = map[int32]int32{
  50. OpenCommand: SaiboOpenCommand,
  51. RebootCommand: SaiboRebootCommand,
  52. DownCommand: SaiboDownCommand,
  53. QueryCommand: SaiboQueryCommand,
  54. }
  55. var SaiboCommandToLocaolM = map[int32]int32{
  56. SaiboOpenCommand: OpenCommand,
  57. SaiboRebootCommand: RebootCommand,
  58. SaiboDownCommand: DownCommand,
  59. SaiboQueryCommand: QueryCommand,
  60. }
  61. func Rc4Test() {
  62. //miwen := "05F459B27337BE46B7E42584860382A5203DE5853026309693C0ED0ABE5427C212BE338B1DC3E289AAFE66"
  63. //miwen,_ := hex.DecodeString("05F459B27337BE46B7E42584860382A5203DE5853026309693C0ED0ABE5427C212BE338B1DC3E289AAFE66")
  64. miwen := "[1,123,20180101143618,20240114144618]"
  65. dest := make([]byte, len(miwen))
  66. cipher2, _ := rc4.NewCipher([]byte("CB1712345678"))
  67. cipher2.XORKeyStream(dest, []byte(miwen))
  68. fmt.Printf("%X\n", dest)
  69. }
  70. func Rc4Decrypt(encrypt string, key string) string {
  71. if len(encrypt) < 4 {
  72. return ""
  73. }
  74. if encrypt[:4] != "CB01" {
  75. return ""
  76. }
  77. miwen, _ := hex.DecodeString(encrypt[4:])
  78. dest := make([]byte, len(miwen))
  79. cipher2, _ := rc4.NewCipher([]byte(key))
  80. cipher2.XORKeyStream(dest, []byte(miwen))
  81. return string(dest)
  82. }
  83. func checkCode(req *param_v1.CodeGateCheckCodeRequest) (int, int32, string, string, int64) {
  84. loc, _ := time.LoadLocation("Local")
  85. if req.CodeType != "Q" && req.CodeType != "C" {
  86. return 0, 0, "", "", 0
  87. }
  88. visitor := int32(2)
  89. vname, vphone := "", ""
  90. vid := int64(0)
  91. if req.CodeType == "Q" {
  92. text := Rc4Decrypt(req.CodeVal, parser.Conf.GateKey)
  93. if text == "" {
  94. if req.IsOnline == "0" {
  95. return 1, 0, "", "", 0
  96. }
  97. return 0, 0, "", "", 0
  98. }
  99. length := len(text)
  100. array := strings.Split(text[1:length-1], ",")
  101. req.CodeVal = array[0]
  102. if len(array) < 4 {
  103. return 0, 0, "", "", 0
  104. }
  105. subArray := strings.Split(array[0], "-")
  106. if len(subArray) > 3 {
  107. req.CodeVal = subArray[0]
  108. visitor = 1
  109. vphone = subArray[1]
  110. vname = subArray[2]
  111. vid, _ = strconv.ParseInt(subArray[3], 10, 64)
  112. }
  113. start, _ := time.ParseInLocation("20060102150405", array[2], loc)
  114. end, _ := time.ParseInLocation("20060102150405", array[3], loc)
  115. now := time.Now()
  116. if now.Unix() < start.Unix() || now.Unix() > end.Unix() {
  117. return 0, 0, "", "", 0
  118. }
  119. }
  120. return 1, visitor, vname, vphone, vid
  121. }
  122. func addRecord(req *param_v1.CodeGateCheckCodeRequest, mreply *pb_v1.GateWhiteMatchReply, visitor int32, vname string, vphone string) {
  123. recordReq := pb_v1.GateRecordAddRequest{
  124. DeviceId: mreply.DeviceId,
  125. Location: mreply.Location,
  126. Direction: mreply.Direction,
  127. HouseholdUser: "",
  128. HouseholdIdNumber: "",
  129. HouseholdHousename: "",
  130. CardNumber: "",
  131. CardOwner: "",
  132. Online: 1,
  133. GardenId: mreply.GardenId,
  134. // 1 访客 2 非访客
  135. IsVisitor: visitor,
  136. // 开门时间
  137. OpenTime: 0,
  138. HouseholdUid: 0,
  139. VisitorPhone: vphone,
  140. VisitorName: vname,
  141. Sn: req.UID,
  142. Protocol: GateProtocolSaiboHttpV1,
  143. OpenType: 1,
  144. }
  145. if req.CodeType == "C" {
  146. recordReq.OpenType = 2
  147. }
  148. if req.IsOnline == "0" {
  149. recordReq.Online = 2
  150. }
  151. loc, _ := time.LoadLocation("Local")
  152. t, _ := time.ParseInLocation("2006-01-02 15:04:05", req.BrushTime, loc)
  153. recordReq.OpenTime = t.Unix()
  154. if req.CodeType == "Q" {
  155. recordReq.HouseholdUid, _ = strconv.ParseInt(mreply.Uid, 10, 64)
  156. recordReq.HouseholdUser = mreply.Name
  157. recordReq.HouseholdIdNumber = mreply.IdNumber
  158. recordReq.HouseholdHousename = mreply.HouseName
  159. } else {
  160. recordReq.CardNumber = mreply.CardNumber
  161. recordReq.CardOwner = mreply.Name
  162. }
  163. _, _ = pb.Device.GateRecordAdd(context.Background(), &recordReq)
  164. }
  165. //
  166. // @Summary 设备上传数据
  167. // @Description 设备上传数据
  168. // @Tags 二维码门禁
  169. // @Accept json
  170. // @Produce json
  171. // @Param body body v1.CodeGateCheckCodeBody true " "
  172. // @Success 200 {object} v1.CodeGateCheckCodeResponse
  173. // @Failure 500 {object} base.HTTPError
  174. // @Router /api/CheckCode [post]
  175. func (c *Controller) CodeGateCheckCode(ctx *gin.Context) {
  176. // 解析参数
  177. req := &param_v1.CodeGateCheckCodeRequest{}
  178. parseParamTask := func() error {
  179. str := ctx.Request.FormValue("paramaters")
  180. fmt.Printf("check code:%v\n", str)
  181. json.Unmarshal([]byte(str), &req.CodeGateCheckCodeBody)
  182. return nil
  183. }
  184. // 业务处理
  185. handleServiceTask := func() error {
  186. // 响应数据
  187. resp := param_v1.CodeGateCheckCodeResponse{}
  188. // 解析并检查数据
  189. status, visitor, vname, vphone, vid := checkCode(req)
  190. if status == 0 {
  191. resp.UID = req.UID
  192. resp.Status = 0
  193. ctx.JSON(http.StatusOK, resp)
  194. return nil
  195. }
  196. // 检查白名单
  197. mreq := pb_v1.GateWhiteMatchRequest{
  198. CodeVal: req.CodeVal,
  199. CodeType: 1,
  200. Sn: req.UID,
  201. Protocol: GateProtocolSaiboHttpV1,
  202. }
  203. if req.CodeType == "C" {
  204. mreq.CodeType = 2
  205. }
  206. mreply, err := pb.Device.GateWhiteMatch(context.Background(), &mreq)
  207. if err != nil {
  208. s, _ := json.MarshalToString(req)
  209. logger.Error("func",
  210. zap.String("call", "pb.Device.GateWhiteMatch"),
  211. zap.String("params", s),
  212. zap.String("error", err.Error()))
  213. resp.UID = req.UID
  214. resp.Status = 0
  215. ctx.JSON(http.StatusOK, resp)
  216. return nil
  217. }
  218. // 白名单不匹配
  219. if mreply.Status != 1 {
  220. resp.UID = req.UID
  221. resp.Status = 0
  222. ctx.JSON(http.StatusOK, resp)
  223. return nil
  224. }
  225. // 检查访客
  226. if visitor == 1 {
  227. mreq := pb_v1.GateVisitorCheckRequest{Id: vid, DeviceId: mreply.DeviceId}
  228. loc, _ := time.LoadLocation("Local")
  229. t, _ := time.ParseInLocation("2006-01-02 15:04:05", req.BrushTime, loc)
  230. mreq.OpenTime = t.Unix()
  231. _, err = pb.Device.GateVisitorCheck(context.Background(), &mreq)
  232. if err != nil {
  233. s, _ := json.MarshalToString(req)
  234. logger.Error("func",
  235. zap.String("call", "pb.Device.GateVisitorCheck"),
  236. zap.String("params", s),
  237. zap.String("error", err.Error()))
  238. resp.UID = req.UID
  239. resp.Status = 0
  240. ctx.JSON(http.StatusOK, resp)
  241. return nil
  242. }
  243. }
  244. // 开门记录
  245. resp.UID = req.UID
  246. resp.Status = int(mreply.Status)
  247. addRecord(req, mreply, visitor, vname, vphone)
  248. ctx.JSON(http.StatusOK, resp)
  249. return nil
  250. }
  251. // 执行任务
  252. httptasker.Exec(ctx, parseParamTask, handleServiceTask)
  253. }
  254. //
  255. // @Summary 心跳
  256. // @Description 心跳
  257. // @Tags 二维码门禁
  258. // @Accept json
  259. // @Produce json
  260. // @Param body body v1.CodeGateIsConnectBody true " "
  261. // @Success 200 {object} v1.CodeGateIsConnectResponse
  262. // @Failure 500 {object} base.HTTPError
  263. // @Router /api/IsConnect [post]
  264. func (c *Controller) CodeGateIsConnect(ctx *gin.Context) {
  265. // 解析参数
  266. req := &param_v1.CodeGateIsConnectRequest{}
  267. parseParamTask := func() error {
  268. str := ctx.Request.FormValue("paramaters")
  269. //fmt.Printf("is connect:%v\n", str)
  270. json.Unmarshal([]byte(str), &req.CodeGateIsConnectBody)
  271. return nil
  272. }
  273. // 业务处理
  274. handleServiceTask := func() error {
  275. // 响应数据
  276. mreq := pb_v1.GateOnlineRequest{Sn: req.UID, Protocol: GateProtocolSaiboHttpV1}
  277. _, err := pb.Device.GateOnline(context.Background(), &mreq)
  278. if err != nil {
  279. s, _ := json.MarshalToString(req)
  280. logger.Error("func",
  281. zap.String("call", "pb.Device.GateOnline"),
  282. zap.String("params", s),
  283. zap.String("error", err.Error()))
  284. }
  285. resp := param_v1.CodeGateIsConnectResponse{}
  286. resp.DateTime = time.Now().Format("2006-01-02 15:04:05")
  287. ctx.JSON(http.StatusOK, resp)
  288. return nil
  289. }
  290. // 执行任务
  291. httptasker.Exec(ctx, parseParamTask, handleServiceTask)
  292. }
  293. var TestCount = 0
  294. //
  295. // @Summary 轮询是否有命令
  296. // @Description 轮询是否有命令
  297. // @Tags 二维码门禁
  298. // @Accept json
  299. // @Produce json
  300. // @Param body body v1.CodeGateQueryCmdBody true " "
  301. // @Success 200 {object} v1.CodeGateQueryCmdResponse
  302. // @Failure 500 {object} base.HTTPError
  303. // @Router /api/QueryCmd [post]
  304. func (c *Controller) CodeGateQueryCmd(ctx *gin.Context) {
  305. // 解析参数
  306. req := &param_v1.CodeGateQueryCmdRequest{}
  307. parseParamTask := func() error {
  308. str := ctx.Request.FormValue("paramaters")
  309. //fmt.Printf("qury cmd:%v\n", str)
  310. json.Unmarshal([]byte(str), &req.CodeGateQueryCmdBody)
  311. return nil
  312. }
  313. // 业务处理
  314. // 0 无命令;
  315. //1 远程开门;
  316. //2 重启设备;
  317. //4 获取设备参数;
  318. //5 设置设备参数; 6 下载白名单;
  319. //7 清空本地所有白名单;
  320. //8 清空本地所有刷卡记录;
  321. //9 扫码显示参数;
  322. //10 查询卡号是否存在白名单
  323. //99 恢复出厂;
  324. handleServiceTask := func() error {
  325. // 响应数据
  326. resp := param_v1.CodeGateQueryCmdResponse{}
  327. mreq := pb_v1.GateCommandUseRequest{Sn: req.UID, Protocol: GateProtocolSaiboHttpV1}
  328. mreply, err := pb.Device.GateCommandUse(context.Background(), &mreq)
  329. if err != nil {
  330. s, _ := json.MarshalToString(req)
  331. logger.Error("func",
  332. zap.String("call", "pb.Device.GateCommandUse"),
  333. zap.String("params", s),
  334. zap.String("error", err.Error()))
  335. resp.CmdID = "0"
  336. resp.CmdCode = 0
  337. ctx.JSON(http.StatusOK, resp)
  338. return nil
  339. }
  340. if mreply.CmdCode == 0 {
  341. resp.CmdID = "0"
  342. resp.CmdCode = 0
  343. ctx.JSON(http.StatusOK, resp)
  344. return nil
  345. }
  346. resp.CmdID = fmt.Sprintf("%d", mreply.Id)
  347. resp.CmdCode = int(LocalCommandToSaiboM[mreply.CmdCode])
  348. resp.CmdParams = []map[string]string{}
  349. if mreply.CmdParams != "" {
  350. json.Unmarshal([]byte(mreply.CmdParams), &resp.CmdParams)
  351. }
  352. ctx.JSON(http.StatusOK, resp)
  353. return nil
  354. }
  355. // 执行任务
  356. httptasker.Exec(ctx, parseParamTask, handleServiceTask)
  357. }
  358. //
  359. // @Summary 命令执行结果
  360. // @Description 命令执行结果
  361. // @Tags 二维码门禁
  362. // @Accept json
  363. // @Produce json
  364. // @Param body body v1.CodeGateQueryCmdPostDataBody true " "
  365. // @Success 200 {object} v1.CodeGateQueryCmdPostDataResponse
  366. // @Failure 500 {object} base.HTTPError
  367. // @Router /api/QueryCmdPostData [post]
  368. func (c *Controller) CodeGateQueryCmdPostData(ctx *gin.Context) {
  369. // 解析参数
  370. req := &param_v1.CodeGateQueryCmdPostDataRequest{}
  371. content := ""
  372. parseParamTask := func() error {
  373. str := ctx.Request.FormValue("paramaters")
  374. fmt.Printf("qury cmd post data:%v\n", str)
  375. json.Unmarshal([]byte(str), &req.CodeGateQueryCmdPostDataBody)
  376. content = string(str)
  377. return nil
  378. }
  379. handleServiceTask := func() error {
  380. // 响应数据
  381. resp := param_v1.CodeGateQueryCmdPostDataResponse{}
  382. resp.CmdStatus = req.CmdStatus
  383. id, _ := strconv.ParseInt(req.CmdID, 10, 64)
  384. mreq := pb_v1.GateCommandResultRequest{
  385. Id: id,
  386. CmdCode: int32(SaiboCommandToLocaolM[int32(req.CmdCode)]),
  387. ResultStatus: int32(req.CmdStatus),
  388. ResultDesc: "",
  389. Sn: req.UID,
  390. Protocol: GateProtocolSaiboHttpV1,
  391. Content: content,
  392. }
  393. _, err := pb.Device.GateCommandResult(context.Background(), &mreq)
  394. if err != nil {
  395. s, _ := json.MarshalToString(req)
  396. logger.Error("func",
  397. zap.String("call", "pb.Device.GateCommandResult"),
  398. zap.String("params", s),
  399. zap.String("error", err.Error()))
  400. ctx.JSON(http.StatusOK, resp)
  401. return nil
  402. }
  403. ctx.JSON(http.StatusOK, resp)
  404. return nil
  405. }
  406. // 执行任务
  407. httptasker.Exec(ctx, parseParamTask, handleServiceTask)
  408. }