default_test.go 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. package test
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "path/filepath"
  8. "regexp"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. "sws_xcx/enums"
  13. "sws_xcx/models"
  14. _ "sws_xcx/routers"
  15. "sws_xcx/service"
  16. "sws_xcx/utils"
  17. "testing"
  18. "time"
  19. "unicode/utf8"
  20. //beego "github.com/beego/beego/v2/server/web"
  21. //"github.com/beego/beego/v2/core/logs"
  22. "github.com/astaxie/beego"
  23. "github.com/jinzhu/gorm"
  24. "github.com/medivhzhan/weapp/v3/auth"
  25. // "github.com/smartystreets/goconvey/convey"
  26. )
  27. func init() {
  28. _, file, _, _ := runtime.Caller(0)
  29. apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
  30. beego.TestBeegoInit(apppath)
  31. }
  32. // TestGet is a sample to run an endpoint test
  33. func TestGet(t *testing.T) {
  34. // r, _ := http.NewRequest("GET", "/v1/object", nil)
  35. // w := httptest.NewRecorder()
  36. // beego.BeeApp.Handlers.ServeHTTP(w, r)
  37. // logs.Info("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String())
  38. // Convey("Subject: Test Station Endpoint\n", t, func() {
  39. // Convey("Status Code Should Be 200", func() {
  40. // So(w.Code, ShouldEqual, 200)
  41. // })
  42. // Convey("The Result Should Not Be Empty", func() {
  43. // So(w.Body.Len(), ShouldBeGreaterThan, 0)
  44. // })
  45. // })
  46. t.Log("TestGet")
  47. }
  48. func TestWxappSessionCode(t *testing.T) {
  49. sdk := service.GetWxSdk()
  50. wxcli := sdk.NewAuth()
  51. code := "0d3eVp100qtUES1jgD300t5yN21eVp1t"
  52. resp, err := wxcli.Code2Session(&auth.Code2SessionRequest{JsCode: code, GrantType: "authorization_code", Appid: beego.AppConfig.String("appid"), Secret: beego.AppConfig.String("appsecret")})
  53. if err != nil {
  54. t.Error(err)
  55. return
  56. }
  57. if resp.CommonError.ErrCode != 0 {
  58. t.Errorf("err code:%v msg:%v", resp.CommonError.ErrCode, resp.CommonError.ErrMSG)
  59. return
  60. }
  61. t.Logf("resp: %+v", *resp)
  62. }
  63. func TestJson(t *testing.T) {
  64. req := `{"id":1,"nick_name":"zhangsan","ctime":"2019-11-20 16:49:08"}`
  65. u := models.UserInfoResp{}
  66. err := json.Unmarshal([]byte(req), &u)
  67. if err != nil {
  68. t.Error(err)
  69. }
  70. t.Logf("u:%+v", u)
  71. }
  72. func TestHandleMsg(t *testing.T) {
  73. req := []byte(`{"publish_received_at":1722839054218,"pub_props":{"User-Property":{}},"peerhost":"124.133.43.122","qos":0,"topic":"/CH-U100/09012201100010104/user/checkresult","clientid":"42915152F3F1","payload":"{\"productKey\":\"CH-U100\",\"deviceName\":\"09012201100010104\",\"acc\":12378,\"type\":0,\"count\":14,\"datatype\":0,\"verifycode\":212,\"data\":\"0,0,0,2,2,0,0,0,0,0,4,3,0,1\",\"origin\":\"4243305A0000010E0000000202000000000004030001D4\",\"len\":23}","username":"09012201100010104","event":"message.publish","metadata":{"rule_id":"checkresult"},"timestamp":1722839054218,"node":"emqx@127.0.0.1","id":"00061EE9B9D4F6AFF445000924860003","flags":{"retain":false,"dup":false}}`)
  74. msg := &models.OpenEmqMsgReqVO{}
  75. err := json.Unmarshal(req, msg)
  76. if err != nil {
  77. t.Error(err)
  78. return
  79. }
  80. ds := service.NewDeviceService()
  81. device, err := ds.GetDeviceByNo(msg.UserName)
  82. if err != nil && err != gorm.ErrRecordNotFound {
  83. utils.ErrorLog("GetDeviceByNo %v:", err)
  84. t.Error(err)
  85. return
  86. }
  87. if device.Id == 0 {
  88. utils.WarningLog("非本系统设备,数据废弃")
  89. return
  90. }
  91. err = ds.CreateDeviceMessageLog(models.DeviceMessageLog{
  92. DeviceName: msg.DeviceName,
  93. Content: string(req),
  94. EventType: enums.EventTypeEmqx,
  95. MessageId: msg.Id,
  96. Topic: msg.Topic,
  97. })
  98. if err != nil {
  99. utils.ErrorLog("CreateDeviceMessageLog %v:", err)
  100. t.Error(err)
  101. return
  102. }
  103. payload := &models.OpenEmqPayloadReqVO{}
  104. err = json.Unmarshal([]byte(msg.Payload), payload)
  105. if err != nil {
  106. utils.ErrorLog("json.Unmarshal %v:", err)
  107. t.Error(err)
  108. return
  109. }
  110. if payload.Len != 23 {
  111. utils.WarningLog("非标准数据,数据废弃:%v", msg.Payload)
  112. }
  113. dr, err := ds.GetDeviceRelateByDeviceId(device.Id)
  114. if err != nil {
  115. utils.ErrorLog("GetDeviceRelateByDeviceId %v:", err)
  116. t.Error(err)
  117. return
  118. }
  119. checkRecord := &models.CheckRecord{
  120. Acc: payload.Acc,
  121. PutSources: enums.EventTypeEmqx,
  122. MessageId: msg.Id,
  123. DeviceId: device.Id,
  124. UserId: dr.UserId,
  125. DeviceStatus: device.Status,
  126. }
  127. if dr.UserId > 0 {
  128. hp, err := service.NewUserHealthProfileService().GetUserHealthProfileByUserId(dr.UserId)
  129. if err != nil {
  130. utils.ErrorLog("GetUserHealthProfileByUserId %v:", err)
  131. t.Error(err)
  132. return
  133. }
  134. checkRecord.UserHealthProfileId = int64(hp.Id)
  135. }
  136. crs := service.NewCheckRecordService()
  137. err = crs.CreateCheckRecord(checkRecord)
  138. if err != nil {
  139. utils.ErrorLog("CreateCheckRecord %v:", err)
  140. t.Error(err)
  141. return
  142. }
  143. t.Log(checkRecord.Id)
  144. t.Log(payload.Data)
  145. da := strings.Split(payload.Data, ",")
  146. count := payload.Count
  147. if len(da) != count {
  148. t.Logf("数据长度不匹配,截取存储 %+v", payload)
  149. if len(da) < count {
  150. count = len(da)
  151. }
  152. }
  153. checkItems, err := service.NewCheckItemService().GetCheckItems("cn", device.DeviceType)
  154. if err != nil {
  155. utils.ErrorLog("GetCheckItems %v:", err)
  156. t.Error(err)
  157. return
  158. }
  159. if len(checkItems) < count {
  160. t.Error("接收的数据于检查项目配置不一致")
  161. return
  162. }
  163. alerts := make([]string, 0)
  164. for i := 0; i < count; i++ {
  165. vi, _ := strconv.Atoi(da[i])
  166. err = createCheckRecordItem(checkItems, checkRecord.Id, &alerts, vi, i+1, crs)
  167. if err != nil {
  168. utils.ErrorLog("createCheckRecordItem valule:%v, err:%v:", vi, err)
  169. }
  170. }
  171. if len(alerts) > 0 {
  172. alertItemIds := strings.Join(alerts, ",")
  173. err = crs.UpdateCheckRecordAlertItems(checkRecord.Id, alertItemIds)
  174. if err != nil {
  175. utils.ErrorLog("UpdateCheckRecordAlertItems %v:", err)
  176. t.Error(err)
  177. return
  178. }
  179. } else {
  180. utils.TraceLog("无异常数据")
  181. }
  182. }
  183. var DIGITS = []rune{
  184. 'S', 'V', 'X', '5', '0', '8', '-', 'N',
  185. 'i', 'm', 'd', 'u', 'H', 'O', 'Q', 'E',
  186. 'D', 'v', 't', '2', 'c', 'p', '1', '3',
  187. 'z', 'R', 'a', 'W', 'l', 'G', 'k', 'A',
  188. '9', 'o', 's', 'g', 'y', '4', 'w', 'L',
  189. 'T', 'Y', 'b', '+', 'J', 'x', '7', 'r',
  190. 'I', 'n', 'f', 'Z', 'e', 'M', 'C', 'P',
  191. 'U', 'B', 'j', '6', 'F', 'K', 'h', 'q',
  192. }
  193. func TestHandleQrCode(t *testing.T) {
  194. result := "http://d.j6c.cn/E0YUQ|XGU|5Vy.z6k&EZf"
  195. //result = "E0YUQ|XGU|5Vy.z6k&EZf"
  196. var userId uint64
  197. if result != "" {
  198. re := regexp.MustCompile(`(http.*/)?(.+)$`)
  199. matches := re.FindStringSubmatch(result)
  200. str := matches[2]
  201. parity := str[len(str)-1:]
  202. st := int8(0)
  203. result1 := result[:len(result)-1]
  204. for i := 0; i < utf8.RuneCountInString(result1); i++ {
  205. r, _ := utf8.DecodeRuneInString(result1[i:])
  206. st += int8(r)
  207. st = int8(getUint8(int(st)))
  208. }
  209. digit := DIGITS[getUint8(int(^st))%64]
  210. if string(digit) != parity {
  211. t.Error("检测数据校验不通过")
  212. return
  213. }
  214. item, err := strconv.ParseInt(str[:1], 16, 32)
  215. if err != nil {
  216. t.Error(err)
  217. return
  218. }
  219. if item != 14 && item != 11 {
  220. t.Error("无法解析检测结果")
  221. return
  222. }
  223. strs := str[1 : len(str)-1]
  224. strs = regexp.MustCompile(`[._&$|]`).ReplaceAllString(strs, " ")
  225. strsArray := strings.Fields(strs)
  226. if len(strsArray) < 5 {
  227. t.Error("无法解析检测结果")
  228. return
  229. }
  230. serialno := "09" + formatNumber(radixString(strsArray[0]), 8)
  231. serialno += formatNumber(radixString(strsArray[1]), 7)
  232. acc := int(radixString(strsArray[2]))
  233. checkResultStr := formatNumber(radixString(strsArray[3]), 7)
  234. if item == 14 {
  235. checkResultStr += formatNumber(radixString(strsArray[4]), 7)
  236. } else if item == 11 {
  237. checkResultStr += formatNumber(radixString(strsArray[4]), 4)
  238. }
  239. fmt.Println("Device Name:", serialno)
  240. fmt.Println("Acc:", acc)
  241. fmt.Println("Check Result String:", checkResultStr)
  242. device, err := service.NewDeviceService().GetDeviceByNo(serialno)
  243. if err != nil {
  244. t.Error(err)
  245. return
  246. }
  247. if device.Id == 0 {
  248. t.Error("不是本系统中的设备,无法解析结果")
  249. return
  250. }
  251. ds := service.NewDeviceService()
  252. dr, err := ds.GetDeviceRelateByDeviceId(device.Id)
  253. if err != nil {
  254. t.Error(err)
  255. return
  256. }
  257. var status int
  258. if dr.Id == 0 {
  259. //设备未绑定 提示绑定
  260. status = 1
  261. } else if dr.UserId != userId {
  262. //别人已经绑定设备,返回结果 并提示
  263. status = 2
  264. } else {
  265. //自己绑定的设备,返回结果不提示
  266. status = 3
  267. }
  268. da := strings.Split(checkResultStr, "")
  269. count := len(da)
  270. checkItems, err := service.NewCheckItemService().GetCheckItems("cn", device.DeviceType)
  271. if err != nil {
  272. utils.ErrorLog("GetCheckItems %v:", err)
  273. t.Error(err)
  274. return
  275. }
  276. crs := service.NewCheckRecordService()
  277. record, err := crs.GetCheckRecordByAcc(device.Id, acc)
  278. if err != nil {
  279. utils.ErrorLog("GetCheckRecordByAcc %v:", err)
  280. t.Error(err)
  281. }
  282. if record.Id == 0 {
  283. //创建记录
  284. err = ds.CreateDeviceMessageLog(models.DeviceMessageLog{
  285. DeviceName: device.DeviceName,
  286. Content: result,
  287. EventType: enums.EventTypeQrCode,
  288. })
  289. if err != nil {
  290. utils.ErrorLog("CreateDeviceMessageLog %v:", err)
  291. t.Error(err)
  292. return
  293. }
  294. if len(checkItems) < count {
  295. t.Error("接收的数据与检查项目配置不一致")
  296. return
  297. }
  298. checkRecord := &models.CheckRecord{
  299. Acc: acc,
  300. PutSources: enums.EventTypeQrCode,
  301. DeviceId: device.Id,
  302. UserId: dr.UserId,
  303. DeviceStatus: device.Status,
  304. Ctime: time.Now(),
  305. }
  306. if dr.UserId > 0 {
  307. hp, err := service.NewUserHealthProfileService().GetUserHealthProfileByUserId(dr.UserId)
  308. if err != nil {
  309. utils.ErrorLog("GetUserHealthProfileByUserId %v:", err)
  310. t.Error(err)
  311. return
  312. }
  313. checkRecord.UserHealthProfileId = int64(hp.Id)
  314. }
  315. err = crs.CreateCheckRecord(checkRecord)
  316. if err != nil {
  317. utils.ErrorLog("CreateCheckRecord %v:", err)
  318. t.Error(err)
  319. return
  320. }
  321. alerts := make([]string, 0)
  322. for i := 0; i < count; i++ {
  323. vi, _ := strconv.Atoi(da[i])
  324. err = createCheckRecordItem(checkItems, checkRecord.Id, &alerts, vi, i+1, crs)
  325. if err != nil {
  326. utils.ErrorLog("createCheckRecordItem valule:%v, err:%v:", vi, err)
  327. }
  328. }
  329. if len(alerts) > 0 {
  330. alertItemIds := strings.Join(alerts, ",")
  331. err = crs.UpdateCheckRecordAlertItems(checkRecord.Id, alertItemIds)
  332. if err != nil {
  333. utils.ErrorLog("UpdateCheckRecordAlertItems %v:", err)
  334. t.Error(err)
  335. return
  336. }
  337. } else {
  338. utils.TraceLog("无异常数据")
  339. }
  340. record = *checkRecord
  341. }
  342. recordItems, err := crs.GetCheckRecordItems(record.Id)
  343. if err != nil {
  344. utils.ErrorLog("GetCheckRecordItems %v:", err)
  345. t.Error(err)
  346. return
  347. }
  348. checkRecordItem, err := analyzeCheckRecord(recordItems, checkItems)
  349. if err != nil {
  350. t.Error(err)
  351. return
  352. }
  353. checkRecordItem.Status = status
  354. checkRecordItem.CheckDate = record.Ctime
  355. checkRecordItem.UserID = int64(record.UserId)
  356. checkRecordItem.Bind = checkRecordItem.UserID > 0
  357. checkRecordItem.CheckRecordID = record.Id
  358. t.Logf("result:%+v", checkRecordItem)
  359. }
  360. }
  361. func analyzeCheckRecord(ritems []*models.CheckRecordItem, citems []*models.CheckItem) (models.AppCheckRecordItemVO, error) {
  362. var result models.AppCheckRecordItemVO
  363. var details []models.AppCheckRecordItemDetailsVO
  364. for _, ri := range ritems {
  365. detail := models.AppCheckRecordItemDetailsVO{}
  366. item := findItem(citems, ri.CheckItemId)
  367. if item == nil {
  368. continue
  369. }
  370. if ri.CheckValue != "" && item.ScopeList != "" {
  371. var scopes []*models.CheckItemScopeVO
  372. err := json.Unmarshal([]byte(item.ScopeList), &scopes)
  373. if err != nil {
  374. return result, err
  375. }
  376. for _, scope := range scopes {
  377. if ri.CheckValueIndex == scope.Index {
  378. if scope.Type == 1 {
  379. result.NormalCount += 1
  380. detail.Alert = false
  381. } else {
  382. result.AlertCount += 1
  383. detail.Alert = true
  384. }
  385. detail.ValueIndex = strconv.Itoa(ri.CheckValueIndex)
  386. detail.ID = item.Id
  387. detail.Value = scope.Value
  388. detail.NameCn = item.NameCn
  389. detail.NameEn = item.NameEn
  390. detail.ReferenceValue = item.ReferenceValue
  391. //detail.Describe = item.Details
  392. detail.Unit = item.Unit
  393. details = append(details, detail)
  394. break
  395. }
  396. }
  397. result.Items = details
  398. if result.AlertCount > 1 {
  399. result.AlertGrade = enums.AlertGradeHIGH
  400. } else if result.AlertCount == 1 {
  401. result.AlertGrade = enums.AlertGradeMEDIUM
  402. } else {
  403. result.AlertGrade = enums.AlertGradeNORMAL
  404. }
  405. result.Describe = enums.AlertGradeMap[result.AlertGrade]
  406. }
  407. }
  408. return result, nil
  409. }
  410. func formatNumber(num int64, width int) string {
  411. format := fmt.Sprintf("%%0%dd", width)
  412. return fmt.Sprintf(format, num)
  413. }
  414. func getUint8(val int) uint8 {
  415. return uint8(val & 0xFF)
  416. }
  417. func indexDigits(ch rune) int {
  418. for i, digit := range DIGITS {
  419. if ch == digit {
  420. return i
  421. }
  422. }
  423. return -1
  424. }
  425. func radixString(str string) int64 {
  426. sum := int64(0)
  427. len := len(str)
  428. for i := 0; i < len; i++ {
  429. index := indexDigits(rune(str[len-i-1]))
  430. sum += int64(index) * int64(math.Pow(64, float64(i)))
  431. }
  432. return sum
  433. }
  434. func createCheckRecordItem(items []*models.CheckItem, crId int64, alerts *[]string, vi, n int, crs *service.CheckRecordService) error {
  435. item := findItem(items, n)
  436. if item == nil {
  437. return fmt.Errorf("检测项目不匹配,需要检查基础数据!序号:%v", n)
  438. }
  439. cri := models.CheckRecordItem{
  440. CheckId: crId,
  441. CheckItemId: n,
  442. CheckValueIndex: vi,
  443. }
  444. scopes := []*models.CheckItemScopeVO{}
  445. err := json.Unmarshal([]byte(item.ScopeList), &scopes)
  446. if err != nil {
  447. return fmt.Errorf("检测项目数值范围定义不正确 err:%v", err)
  448. }
  449. scope := findScope(scopes, vi)
  450. if scope == nil {
  451. return errors.New("检测结果不匹配")
  452. }
  453. cri.CheckValue = scope.Value
  454. if scope.Type == 1 {
  455. *alerts = append(*alerts, strconv.Itoa(n))
  456. }
  457. return crs.CreateCheckRecordItem(&cri)
  458. }
  459. func findScope(scopes []*models.CheckItemScopeVO, vi int) *models.CheckItemScopeVO {
  460. for _, scope := range scopes {
  461. if scope.Index == vi {
  462. return scope
  463. }
  464. }
  465. return nil
  466. }
  467. func findItem(items []*models.CheckItem, itemNumber int) *models.CheckItem {
  468. //循环items
  469. for _, item := range items {
  470. if item.CheckItemNumber == itemNumber {
  471. return item
  472. }
  473. }
  474. return nil
  475. }