siteInfoManageServices.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. package services
  2. import (
  3. "context"
  4. "fmt"
  5. "fwh-toolbox-server/domain"
  6. "fwh-toolbox-server/dto"
  7. "fwh-toolbox-server/repositories"
  8. "fwh-toolbox-server/task/queue/fwhQueue"
  9. "fwh-toolbox-server/utils/global"
  10. "math"
  11. "regexp"
  12. "strconv"
  13. "time"
  14. "github.com/xuri/excelize/v2"
  15. "go.uber.org/zap"
  16. )
  17. var VERSION_REGEX = regexp.MustCompile(`V(\d+)R(\d+)B(\d+)D(\d+)`)
  18. // 获取更新状态
  19. func GetSiteInfoUpdateStatus() (*domain.SiteInfoUpdateRecord, error) {
  20. return repositories.GetSiteInfoUpdateNewRecord()
  21. }
  22. // 请求更新站点信息表
  23. func UpdateSiteInfoDate() error {
  24. id, err := repositories.CreateSiteInfoUpdateInfo()
  25. if err != nil {
  26. return err
  27. }
  28. if err := fwhQueue.EnqueueSiteInfoUpdateTask(domain.TaskSiteInfoUpdate{
  29. Id: *id,
  30. }); err != nil {
  31. return err
  32. }
  33. return nil
  34. }
  35. // 获取站点信息表
  36. func QuerySiteInfoDataList(para dto.SiteInfoRequest) (*dto.ResPage[dto.SiteInfoDTO], error) {
  37. res, err := repositories.GetSiteInfoManageList(para.PageNum, para.PageSize, para.Filter, para.Search)
  38. if err != nil {
  39. return nil, err
  40. }
  41. idList := []string{}
  42. for _, data := range res.Data {
  43. if data.ExtTags != nil {
  44. idList = append(idList, *data.ExtTags...)
  45. }
  46. }
  47. tagMap, err := repositories.GetSiteInfoTagsFromId(idList)
  48. if err != nil {
  49. zap.L().Error("QuerySiteInfoDataList GetSiteInfoTagsFromId failed.", zap.String("err", err.Error()), zap.Strings("idList", idList))
  50. return nil, err
  51. }
  52. result := dto.ResPage[dto.SiteInfoDTO]{
  53. Data: dto.SiteInfoDomainListToSiteInfoDTOList(res.Data, &tagMap),
  54. PageSize: res.PageSize,
  55. PageNum: res.PageNum,
  56. Total: res.Total,
  57. }
  58. return &result, nil
  59. }
  60. // 导出站点信息表
  61. func ExportSiteInfoDataList(filer *domain.SiteInfoFilter) (*excelize.File, error) {
  62. res, err := repositories.GetSiteInfoManageList(0, 0, filer, "")
  63. if err != nil {
  64. return nil, err
  65. }
  66. record, err := repositories.GetSiteInfoUpdateNewRecord()
  67. if err != nil {
  68. return nil, err
  69. }
  70. // 创建新的excel文件
  71. f := excelize.NewFile()
  72. // 写标题行
  73. f.SetCellValue("Sheet1", "A1", "SN")
  74. f.SetCellValue("Sheet1", "B1", "Installer")
  75. f.SetCellValue("Sheet1", "C1", "ActiveTime")
  76. f.SetCellValue("Sheet1", "D1", "Status")
  77. f.SetCellValue("Sheet1", "E1", "OnLineTime")
  78. f.SetCellValue("Sheet1", "F1", "OffLineTime")
  79. f.SetCellValue("Sheet1", "G1", "FhpSn")
  80. f.SetCellValue("Sheet1", "H1", "Version")
  81. f.SetCellValue("Sheet1", "I1", "SlVersion")
  82. f.SetCellValue("Sheet1", "J1", "SlVersionJson")
  83. f.SetCellValue("Sheet1", "K1", "MeterVersion")
  84. f.SetCellValue("Sheet1", "L1", "MbVersion")
  85. f.SetCellValue("Sheet1", "M1", "AwsVersion")
  86. f.SetCellValue("Sheet1", "N1", "AppVersion")
  87. f.SetCellValue("Sheet1", "O1", "ProtocolVer")
  88. f.SetCellValue("Sheet1", "P1", "SysHdVersion")
  89. f.SetCellValue("Sheet1", "Q1", "Remark")
  90. f.SetCellValue("Sheet1", "R1", "Country")
  91. f.SetCellValue("Sheet1", "S1", "Province")
  92. f.SetCellValue("Sheet1", "T1", "ManufactureDate")
  93. f.SetCellValue("Sheet1", "U1", "HardwareVersion")
  94. f.SetCellValue("Sheet1", "V1", "CveStatus")
  95. f.SetCellValue("Sheet1", "W1", "SecurityPatchLevel")
  96. f.SetCellValue("Sheet1", "X1", "TargetVersion")
  97. f.SetCellValue("Sheet1", "Y1", "LastUpgradeTime")
  98. f.SetCellValue("Sheet1", "Z1", "UpgradeStatus")
  99. f.SetCellValue("Sheet1", "AA1", "Owner/Maintainer")
  100. f.SetCellValue("Sheet1", "AB1", "DataSource")
  101. f.SetCellValue("Sheet1", "AC1", "LastUpdated")
  102. f.SetCellValue("Sheet1", "AD1", "ConnectType")
  103. f.SetCellValue("Sheet1", "AE1", "WifiSignal")
  104. f.SetCellValue("Sheet1", "AF1", "4GSignal")
  105. // 写入数据
  106. for i, d := range res.Data {
  107. f.SetCellValue("Sheet1", "A"+strconv.Itoa(i+2), d.Sn)
  108. f.SetCellValue("Sheet1", "B"+strconv.Itoa(i+2), global.Deref(d.InstallerName, ""))
  109. f.SetCellValue("Sheet1", "C"+strconv.Itoa(i+2), d.ActiveTime)
  110. f.SetCellValue("Sheet1", "D"+strconv.Itoa(i+2), func() string {
  111. switch d.Status {
  112. case 0:
  113. return "离线(0)"
  114. case 1:
  115. return "在线(1)"
  116. default:
  117. return fmt.Sprintf("未知(%d)", d.Status)
  118. }
  119. }())
  120. f.SetCellValue("Sheet1", "E"+strconv.Itoa(i+2), global.Deref(d.OnLineTime, ""))
  121. f.SetCellValue("Sheet1", "F"+strconv.Itoa(i+2), global.Deref(d.OffLineTime, ""))
  122. f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+2), d.FhpSn)
  123. f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+2), d.Version)
  124. f.SetCellValue("Sheet1", "I"+strconv.Itoa(i+2), d.SlVersion)
  125. f.SetCellValue("Sheet1", "J"+strconv.Itoa(i+2), d.SlVersionJson)
  126. f.SetCellValue("Sheet1", "K"+strconv.Itoa(i+2), global.Deref(d.MeterVersion, ""))
  127. f.SetCellValue("Sheet1", "L"+strconv.Itoa(i+2), global.Deref(d.MbVersion, ""))
  128. f.SetCellValue("Sheet1", "M"+strconv.Itoa(i+2), global.Deref(d.AwsVersion, ""))
  129. f.SetCellValue("Sheet1", "N"+strconv.Itoa(i+2), global.Deref(d.AppVersion, ""))
  130. f.SetCellValue("Sheet1", "O"+strconv.Itoa(i+2), d.ProtocolVer)
  131. f.SetCellValue("Sheet1", "P"+strconv.Itoa(i+2), d.SysHdVersion)
  132. f.SetCellValue("Sheet1", "Q"+strconv.Itoa(i+2), global.Deref(d.Remark, ""))
  133. f.SetCellValue("Sheet1", "R"+strconv.Itoa(i+2), d.Country)
  134. f.SetCellValue("Sheet1", "S"+strconv.Itoa(i+2), d.Province)
  135. var manufactureDate string = ""
  136. if len(d.Sn) > 9 {
  137. year := d.Sn[len(d.Sn)-8 : len(d.Sn)-6]
  138. week := d.Sn[len(d.Sn)-6 : len(d.Sn)-4]
  139. manufactureDate = fmt.Sprintf("%s年%s周", year, week)
  140. }
  141. f.SetCellValue("Sheet1", "T"+strconv.Itoa(i+2), manufactureDate)
  142. f.SetCellValue("Sheet1", "U"+strconv.Itoa(i+2), "V"+strconv.Itoa(d.SysHdVersion))
  143. f.SetCellValue("Sheet1", "V"+strconv.Itoa(i+2), "无")
  144. f.SetCellValue("Sheet1", "W"+strconv.Itoa(i+2), "安全")
  145. f.SetCellValue("Sheet1", "X"+strconv.Itoa(i+2), d.Version)
  146. f.SetCellValue("Sheet1", "Y"+strconv.Itoa(i+2), global.Deref(d.FirmUpgradeTime, ""))
  147. f.SetCellValue("Sheet1", "Z"+strconv.Itoa(i+2), "成功")
  148. f.SetCellValue("Sheet1", "AA"+strconv.Itoa(i+2), "Jerry Liang/LMT")
  149. f.SetCellValue("Sheet1", "AB"+strconv.Itoa(i+2), "Fleetview")
  150. f.SetCellValue("Sheet1", "AC"+strconv.Itoa(i+2), record.UpdateTime.Format(time.DateTime))
  151. f.SetCellValue("Sheet1", "AD"+strconv.Itoa(i+2), func() string {
  152. switch d.ConnType {
  153. case 0:
  154. return "未连接(0)"
  155. case 1:
  156. return "eth0(1)"
  157. case 2:
  158. return "eth1(2)"
  159. case 3:
  160. return "WIFI(3)"
  161. case 4:
  162. return "4G(4)"
  163. default:
  164. return fmt.Sprintf("未知(%d)", d.Status)
  165. }
  166. }())
  167. f.SetCellValue("Sheet1", "AE"+strconv.Itoa(i+2), func() string {
  168. s, err := strconv.ParseInt(d.WifiSignal, 10, 64)
  169. if err != nil {
  170. zap.L().Warn("WifiSignal ParseInt failed", zap.String("WifiSignal", d.WifiSignal), zap.String("err", err.Error()))
  171. return fmt.Sprintf("未知信号(%s)", d.WifiSignal)
  172. }
  173. if s < 0 {
  174. return fmt.Sprintf("Disable(%s)", d.WifiSignal)
  175. } else if s < 40 {
  176. return fmt.Sprintf("很弱/不可用(%s) %ddBm", d.WifiSignal, s/2-100)
  177. } else if s < 60 {
  178. return fmt.Sprintf("弱(%s) %ddBm", d.WifiSignal, s/2-100)
  179. } else if s < 80 {
  180. return fmt.Sprintf("中等/一般(%s) %ddBm", d.WifiSignal, s/2-100)
  181. } else {
  182. return fmt.Sprintf("强/良好(%s) > -50dBm", d.WifiSignal)
  183. }
  184. }())
  185. f.SetCellValue("Sheet1", "AF"+strconv.Itoa(i+2), func() string {
  186. if d.Signal == nil {
  187. return "Not Signal"
  188. }
  189. s, err := strconv.ParseInt(*d.Signal, 10, 64)
  190. if err != nil {
  191. zap.L().Warn("Signal ParseInt failed", zap.String("4GSignal", *d.Signal), zap.String("err", err.Error()))
  192. return fmt.Sprintf("未知信号(%s)", *d.Signal)
  193. }
  194. // 判断软件版本
  195. isNew := false
  196. if d.AppVersion != nil && *d.AppVersion != "" {
  197. match := VERSION_REGEX.FindStringSubmatch(*d.AppVersion)
  198. if match != nil {
  199. v := match[1]
  200. r := match[2]
  201. b := match[3]
  202. d := match[4]
  203. _ = d // 当前逻辑未使用
  204. if v == "10" {
  205. rInt, _ := strconv.Atoi(r)
  206. bInt, _ := strconv.Atoi(b)
  207. if rInt > 5 {
  208. isNew = true
  209. } else if rInt == 4 && bInt >= 14 {
  210. isNew = true
  211. }
  212. }
  213. }
  214. }
  215. if isNew {
  216. if s < 0 {
  217. return fmt.Sprintf("Disable(%s)", *d.Signal)
  218. } else if s <= 12 {
  219. return fmt.Sprintf("很差(%s) %ddBm", *d.Signal, int(math.Round(float64(s)/2.5-115)))
  220. } else if s <= 37 {
  221. return fmt.Sprintf("较差(%s) %ddBm", *d.Signal, int(math.Round(float64(s)/2.5-115)))
  222. } else if s <= 62 {
  223. return fmt.Sprintf("一般(%s) %ddBm", *d.Signal, int(math.Round(float64(s)/2.5-115)))
  224. } else if s <= 87 {
  225. return fmt.Sprintf("良好(%s) %ddBm", *d.Signal, int(math.Round(float64(s)/2.5-115)))
  226. } else {
  227. return fmt.Sprintf("极好(%s) %ddBm", *d.Signal, int(math.Round(float64(s)/2.5-115)))
  228. }
  229. } else {
  230. if s < 0 {
  231. return fmt.Sprintf("Disable(%s)", *d.Signal)
  232. } else if s <= 1 {
  233. return fmt.Sprintf("很差(%s) %ddBm", *d.Signal, s*2-113)
  234. } else if s <= 6 {
  235. return fmt.Sprintf("较差(%s) %ddBm", *d.Signal, s*2-113)
  236. } else if s <= 11 {
  237. return fmt.Sprintf("一般(%s) %ddBm", *d.Signal, s*2-113)
  238. } else if s <= 16 {
  239. return fmt.Sprintf("良好(%s) %ddBm", *d.Signal, s*2-113)
  240. } else {
  241. return fmt.Sprintf("极好(%s) %ddBm", *d.Signal, s*2-113)
  242. }
  243. }
  244. }())
  245. }
  246. return f, err
  247. }
  248. // 查询单个站点实时信息(同时更新单个站点数据)
  249. func GetSiteInfoData(sn string) (*dto.SiteInfoDTO, error) {
  250. res, err := repositories.QuerySiteInfoList(dto.SiteInfoPara{
  251. SN: &sn,
  252. PageSize: 10,
  253. PageNum: 1,
  254. })
  255. if err != nil {
  256. return nil, err
  257. }
  258. if res.Result == nil {
  259. return nil, fmt.Errorf("code: %s, msg: %s", strconv.Itoa(res.Code), res.Message)
  260. }
  261. if len(*res.Result) == 0 {
  262. return nil, fmt.Errorf("code: %s, msg: %s", strconv.Itoa(res.Code), res.Message)
  263. }
  264. domainData := domain.FwhSiteInfoToSiteInfoDomain(&(*res.Result)[0])
  265. // 数据插入数据库
  266. if err := repositories.InsertSiteInfoData(*domainData); err != nil {
  267. zap.L().Error("保存站点信息失败", zap.String("err", err.Error()), zap.String("sn", sn))
  268. }
  269. tagMap := make(map[string]*dto.SiteTagDTO)
  270. if domainData.ExtTags != nil {
  271. tagMap, err = repositories.GetSiteInfoTagsFromId(*domainData.ExtTags)
  272. if err != nil {
  273. zap.L().Error("GetSiteInfoData GetSiteInfoTagsFromId failed.", zap.String("err", err.Error()), zap.Strings("idList", *domainData.ExtTags))
  274. return nil, err
  275. }
  276. }
  277. dtoData := dto.SiteInfoDomainToSiteInfoDTO(domainData, &tagMap)
  278. return dtoData, nil
  279. }
  280. // 使能站点xlog
  281. func OperateSiteInfoEnableXlog(ctx context.Context, sn string) (string, error) {
  282. return repositories.FwhMqttEnableXlog(ctx, sn)
  283. }
  284. // 获取站点信息标签列表
  285. func GetSiteInfoTags(page uint, size uint, search string) (*dto.ResPage[dto.SiteTagDTO], error) {
  286. tags, err := repositories.GetSiteInfoTags(page, size, search)
  287. if err != nil {
  288. return nil, err
  289. }
  290. result := dto.ResPage[dto.SiteTagDTO]{
  291. Data: []dto.SiteTagDTO{},
  292. PageSize: tags.PageSize,
  293. PageNum: tags.PageNum,
  294. Total: tags.Total,
  295. }
  296. for _, tag := range tags.Data {
  297. result.Data = append(result.Data, *dto.SiteTagDomainToSiteTagDTO(&tag))
  298. }
  299. return &result, nil
  300. }
  301. // 创建或更新站点信息标签
  302. func UpdateSiteInfoTag(tag dto.SiteTagDTO) error {
  303. return repositories.UpdateSiteInfoTag(*dto.SiteSiteTagDTOToTagDomain(&tag))
  304. }