intelligentbuildingcontrol.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. package handler
  2. import (
  3. "city_chips/internal/model"
  4. "city_chips/internal/service"
  5. "city_chips/pkg/helper/obix"
  6. "city_chips/pkg/helper/resp"
  7. "encoding/json"
  8. "fmt"
  9. "go.uber.org/zap"
  10. "math/rand"
  11. "net/http"
  12. "regexp"
  13. "strconv"
  14. "time"
  15. "github.com/spf13/viper"
  16. "github.com/gin-gonic/gin"
  17. )
  18. type IntelligentBuildingControlHandler struct {
  19. *Handler
  20. intelligentBuildingControlService service.IntelligentBuildingControlService
  21. conf *viper.Viper
  22. }
  23. func NewIntelligentBuildingControlHandler(
  24. handler *Handler,
  25. intelligentBuildingControlService service.IntelligentBuildingControlService,
  26. conf *viper.Viper,
  27. ) *IntelligentBuildingControlHandler {
  28. return &IntelligentBuildingControlHandler{
  29. Handler: handler,
  30. intelligentBuildingControlService: intelligentBuildingControlService,
  31. conf: conf,
  32. }
  33. }
  34. // 智能楼宇控制系统
  35. // 示例:创建一个报警记录
  36. func generateAlarm() model.AlarmList {
  37. return model.AlarmList{
  38. Id: rand.Intn(100),
  39. Name: model.GetRandomItem(model.DeviceNames),
  40. State: rand.Intn(2), // 假设0为正常,1为报警
  41. Date: time.Now().Format("2006-01-02 15:04:05"),
  42. Location: model.GetRandomItem(model.Locations),
  43. AlarmContent: model.GetRandomItem(model.AlarmContents),
  44. }
  45. }
  46. func (h *IntelligentBuildingControlHandler) GetIntelligentBuildingControl(ctx *gin.Context) {
  47. m := make(map[string]any)
  48. var device []model.AlarmList
  49. for i := 0; i < 20; i++ {
  50. alarm := generateAlarm()
  51. device = append(device, alarm)
  52. }
  53. count, err := h.intelligentBuildingControlService.DeviceCount()
  54. if err != nil {
  55. resp.HandleError(ctx, 1201, "查询设备总数失败", nil)
  56. return
  57. }
  58. m["DeviceCount"] = count //设备总数
  59. m["StopState"] = rand.Intn(100) //停止状态
  60. m["RunState"] = rand.Intn(100) //运行状态
  61. m["FaultState"] = rand.Intn(1000) //故障状态
  62. m["DeviceList"] = device //设备列表
  63. resp.HandleSuccess(ctx, m)
  64. }
  65. func (h *IntelligentBuildingControlHandler) GetPoint(ctx *gin.Context) {
  66. pointName := ctx.PostForm("pointName")
  67. deviceType := ctx.PostForm("deviceType")
  68. building := ctx.PostForm("building")
  69. floor := ctx.PostForm("floor")
  70. section := ctx.PostForm("section")
  71. device_name := ctx.PostForm("deviceName")
  72. pageNum, err := strconv.Atoi(ctx.PostForm("pageNum"))
  73. pageSize, err := strconv.Atoi(ctx.PostForm("pageSize"))
  74. conds := make(map[string]any)
  75. //var pointType []model.PointType
  76. if pointName != "" {
  77. conds["point_name"] = pointName
  78. }
  79. if deviceType != "" {
  80. conds["device_type"] = deviceType
  81. }
  82. if building != "" {
  83. conds["building"] = building
  84. }
  85. if floor != "" {
  86. conds["floor"] = floor
  87. }
  88. if section != "" {
  89. conds["section"] = section
  90. }
  91. if device_name != "" {
  92. conds["device_name"] = device_name
  93. }
  94. //baseUrl := h.conf.GetString("obix.baseUrl")
  95. point, total, err := h.intelligentBuildingControlService.GetPoint(conds, pageNum, pageSize)
  96. if err != nil {
  97. resp.HandleError(ctx, 1201, "查询点位失败", nil)
  98. return
  99. }
  100. //
  101. //var wg sync.WaitGroup
  102. //var mutex sync.Mutex // 保护切片并发写入
  103. //m := make(map[string]string)
  104. //sem := make(chan struct{}, 10) // 最大并发数为10
  105. //
  106. //for _, v := range *points {
  107. // url := baseUrl + v.FullPath
  108. // wg.Add(1)
  109. // sem <- struct{}{}
  110. // go func(url string, pointName string) {
  111. // defer func() {
  112. // <-sem
  113. // wg.Done()
  114. // }()
  115. //
  116. // request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password"))
  117. // if err != nil {
  118. // h.logger.Error("发送请求失败", zap.Error(err))
  119. // return
  120. // }
  121. //
  122. // re := regexp.MustCompile(`val="([^"]+)"`)
  123. // matches := re.FindStringSubmatch(request)
  124. //
  125. // mutex.Lock()
  126. // defer mutex.Unlock()
  127. //
  128. // if len(matches) > 1 {
  129. // s := model.PointName[pointName]
  130. // m[s] = matches[1]
  131. // pointType = append(pointType, model.PointType{Type: m})
  132. // } else {
  133. // h.logger.Warn("未找到 val 值", zap.String("url", url))
  134. // }
  135. // }(url, v.PointName)
  136. //}
  137. //
  138. //// 等待所有协程完成
  139. //wg.Wait()
  140. // 统一返回结果
  141. resp.PageHandleSuccess(ctx, point, total, pageNum, pageSize)
  142. }
  143. // GetGetPoint 获取点位设备数据
  144. func (h *IntelligentBuildingControlHandler) GetGetPoint(ctx *gin.Context) {
  145. pointName := ctx.Query("pointName")
  146. deviceType := ctx.Query("deviceType")
  147. building := ctx.Query("building")
  148. floor := ctx.Query("floor")
  149. section := ctx.Query("section")
  150. device_name := ctx.Query("deviceName")
  151. conds := make(map[string]any)
  152. if pointName != "" {
  153. conds["point_name"] = pointName
  154. }
  155. if deviceType != "" {
  156. conds["device_type"] = deviceType
  157. }
  158. if building != "" {
  159. conds["building"] = building
  160. }
  161. if floor != "" {
  162. conds["floor"] = floor
  163. }
  164. if section != "" {
  165. conds["section"] = section
  166. }
  167. if device_name != "" {
  168. conds["device_name"] = device_name
  169. }
  170. baseUrl := h.conf.GetString("obix.baseUrl")
  171. m := make(map[string]any)
  172. points, _, err := h.intelligentBuildingControlService.GetPoint(conds, 1, 100)
  173. if err != nil {
  174. resp.HandleError(ctx, 1201, "查询点位失败", nil)
  175. }
  176. for _, v := range *points {
  177. url := baseUrl + v.FullPath
  178. request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password"))
  179. if err != nil {
  180. h.logger.Error("发送请求失败", zap.Error(err))
  181. return
  182. }
  183. re := regexp.MustCompile(`val="([^"]+)"`)
  184. matches := re.FindStringSubmatch(request)
  185. if len(matches) > 1 {
  186. s := model.PointName[v.PointName]
  187. if s != "" {
  188. value := matches[1]
  189. switch val := obix.DetectType(value).(type) {
  190. case int:
  191. m[s] = val
  192. case float64:
  193. m[s] = fmt.Sprintf("%.2f", val) // 保留两位小数输出
  194. case bool:
  195. if val {
  196. m[s] = "是"
  197. } else {
  198. m[s] = "否"
  199. }
  200. default:
  201. m[s] = value // 原样输出字符串
  202. }
  203. }
  204. } else {
  205. h.logger.Warn("未找到 val 值", zap.String("url", url))
  206. }
  207. }
  208. resp.HandleSuccess(ctx, m)
  209. }
  210. func (h *IntelligentBuildingControlHandler) GetGetPointSSE(ctx *gin.Context) {
  211. // 设置响应头
  212. ctx.Header("Content-Type", "text/event-stream")
  213. ctx.Header("Cache-Control", "no-cache")
  214. ctx.Header("Connection", "keep-alive")
  215. // 监听客户端断开连接
  216. conn := true
  217. notify := ctx.Writer.CloseNotify()
  218. type Response struct {
  219. RequestId string `protobuf:"bytes,1,opt,name=requestId,proto3" json:"requestId,omitempty"`
  220. Code int32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"`
  221. Msg string `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"`
  222. Data any `json:"data"`
  223. }
  224. pointName := ctx.Query("pointName")
  225. deviceType := ctx.Query("deviceType")
  226. building := ctx.Query("building")
  227. floor := ctx.Query("floor")
  228. section := ctx.Query("section")
  229. device_name := ctx.Query("deviceName")
  230. conds := make(map[string]any)
  231. if pointName != "" {
  232. conds["point_name"] = pointName
  233. }
  234. if deviceType != "" {
  235. conds["device_type"] = deviceType
  236. }
  237. if building != "" {
  238. conds["building"] = building
  239. }
  240. if floor != "" {
  241. conds["floor"] = floor
  242. }
  243. if section != "" {
  244. conds["section"] = section
  245. }
  246. if device_name != "" {
  247. conds["device_name"] = device_name
  248. }
  249. baseUrl := h.conf.GetString("obix.baseUrl")
  250. var response Response
  251. for conn {
  252. select {
  253. case <-notify:
  254. conn = false
  255. fmt.Println("断开连接")
  256. return
  257. default:
  258. m := make(map[string]any)
  259. points, _, err := h.intelligentBuildingControlService.GetPoint(conds, 1, 100)
  260. if err != nil {
  261. resp.HandleError(ctx, 1201, "查询点位失败", nil)
  262. conn = false
  263. }
  264. for _, v := range *points {
  265. url := baseUrl + v.FullPath
  266. request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password"))
  267. if err != nil {
  268. h.logger.Error("发送请求失败", zap.Error(err))
  269. conn = false
  270. return
  271. }
  272. re := regexp.MustCompile(`val="([^"]+)"`)
  273. matches := re.FindStringSubmatch(request)
  274. if len(matches) > 1 {
  275. s := model.PointName[v.PointName]
  276. if s != "" {
  277. value := matches[1]
  278. switch val := obix.DetectType(value).(type) {
  279. case int:
  280. m[s] = val
  281. case float64:
  282. m[s] = fmt.Sprintf("%.2f", val) // 保留两位小数输出
  283. case bool:
  284. if val {
  285. m[s] = "是"
  286. } else {
  287. m[s] = "否"
  288. }
  289. default:
  290. m[s] = value // 原样输出字符串
  291. }
  292. }
  293. } else {
  294. h.logger.Warn("未找到 val 值", zap.String("url", url))
  295. conn = false
  296. }
  297. }
  298. response.Code = 200
  299. response.RequestId = ctx.ClientIP()
  300. response.Msg = "success"
  301. response.Data = m
  302. res, _ := json.Marshal(&response)
  303. fmt.Fprintf(ctx.Writer, "data: %s\n\n", string(res))
  304. ctx.Writer.Flush()
  305. time.Sleep(10 * time.Second)
  306. }
  307. }
  308. }
  309. //func (h *IntelligentBuildingControlHandler) GetGetPointSSE(ctx *gin.Context) {
  310. // // 设置响应头
  311. // ctx.Header("Content-Type", "text/event-stream")
  312. // ctx.Header("Cache-Control", "no-cache")
  313. // ctx.Header("Connection", "keep-alive")
  314. //
  315. // // 监听客户端断开连接
  316. // conn := true
  317. // notify := ctx.Writer.CloseNotify()
  318. //
  319. // type Response struct {
  320. // RequestId string `json:"requestId,omitempty"`
  321. // Code int32 `json:"code,omitempty"`
  322. // Msg string `json:"msg,omitempty"`
  323. // Data any `json:"data"`
  324. // }
  325. //
  326. // pointName := ctx.Query("pointName")
  327. // deviceType := ctx.Query("deviceType")
  328. // building := ctx.Query("building")
  329. // floor := ctx.Query("floor")
  330. // section := ctx.Query("section")
  331. // device_name := ctx.Query("deviceName")
  332. //
  333. // conds := make(map[string]any)
  334. // if pointName != "" {
  335. // conds["point_name"] = pointName
  336. // }
  337. // if deviceType != "" {
  338. // conds["device_type"] = deviceType
  339. // }
  340. // if building != "" {
  341. // conds["building"] = building
  342. // }
  343. // if floor != "" {
  344. // conds["floor"] = floor
  345. // }
  346. // if section != "" {
  347. // conds["section"] = section
  348. // }
  349. // if device_name != "" {
  350. // conds["device_name"] = device_name
  351. // }
  352. //
  353. // baseUrl := h.conf.GetString("obix.baseUrl")
  354. //
  355. // var response Response
  356. // for conn {
  357. // select {
  358. // case <-notify:
  359. // conn = false
  360. // fmt.Println("客户端断开连接")
  361. // return
  362. // default:
  363. // m := make(map[string]any)
  364. // points, _, err := h.intelligentBuildingControlService.GetPoint(conds, 1, 100)
  365. // if err != nil {
  366. // resp.HandleError(ctx, 1201, "查询点位失败", nil)
  367. // conn = false
  368. // continue
  369. // }
  370. //
  371. // var wg sync.WaitGroup
  372. // var mutex sync.Mutex
  373. // sem := make(chan struct{}, 10) // 控制最大并发数为10
  374. //
  375. // for _, v := range *points {
  376. // select {
  377. // case sem <- struct{}{}:
  378. // default:
  379. // <-sem
  380. // sem <- struct{}{}
  381. // }
  382. // wg.Add(1)
  383. // go func(v model.Point) {
  384. // defer func() {
  385. // <-sem
  386. // wg.Done()
  387. // }()
  388. //
  389. // url := baseUrl + v.FullPath
  390. // request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password"))
  391. // if err != nil {
  392. // h.logger.Error("发送请求失败", zap.String("url", url), zap.Error(err))
  393. // return
  394. // }
  395. //
  396. // re := regexp.MustCompile(`val="([^"]+)"`)
  397. // matches := re.FindStringSubmatch(request)
  398. //
  399. // if len(matches) > 1 {
  400. // s := model.PointName[v.PointName]
  401. // if s != "" {
  402. // value := matches[1]
  403. // result := obix.DetectType(value)
  404. //
  405. // mutex.Lock()
  406. // defer mutex.Unlock()
  407. //
  408. // switch val := result.(type) {
  409. // case int:
  410. // m[s] = val
  411. // case float64:
  412. // m[s] = fmt.Sprintf("%.2f", val)
  413. // case bool:
  414. // if val {
  415. // m[s] = "是"
  416. // } else {
  417. // m[s] = "否"
  418. // }
  419. // default:
  420. // m[s] = value
  421. // }
  422. // }
  423. // } else {
  424. // h.logger.Warn("未找到 val 值", zap.String("url", url))
  425. // }
  426. // }(v)
  427. // }
  428. //
  429. // wg.Wait() // 等待所有 goroutine 完成
  430. //
  431. // response.Code = 200
  432. // response.RequestId = ctx.ClientIP()
  433. // response.Msg = "success"
  434. // response.Data = m
  435. //
  436. // res, _ := json.Marshal(&response)
  437. // fmt.Fprintf(ctx.Writer, "data: %s\n\n", string(res))
  438. // ctx.Writer.Flush()
  439. // time.Sleep(10 * time.Second)
  440. // }
  441. // }
  442. //}
  443. // GetPointType 获取点位类型
  444. func (h *IntelligentBuildingControlHandler) GetPointType(ctx *gin.Context) {
  445. points, err := h.intelligentBuildingControlService.GetPointType()
  446. if err != nil {
  447. resp.HandleError(ctx, 1201, "查询点位类型失败", nil)
  448. return
  449. }
  450. resp.HandleSuccess(ctx, points)
  451. }
  452. // GetDeviceType 获取设备类型
  453. func (h *IntelligentBuildingControlHandler) GetDeviceType(ctx *gin.Context) {
  454. points, err := h.intelligentBuildingControlService.DeviceType()
  455. if err != nil {
  456. resp.HandleError(ctx, 1201, "查询设备类型失败", nil)
  457. return
  458. }
  459. m := make(map[string]string)
  460. for _, v := range points {
  461. m[v] = model.DeviceType[v]
  462. }
  463. resp.HandleSuccess(ctx, m)
  464. }
  465. // GetDevices 获取设备列表
  466. func (h *IntelligentBuildingControlHandler) GetDevices(ctx *gin.Context) {
  467. conds := make(map[string]any)
  468. pageNum, err := strconv.Atoi(ctx.Query("pageNum"))
  469. pageSize, err := strconv.Atoi(ctx.Query("pageSize"))
  470. device_type := ctx.Query("device_type")
  471. if len(device_type) == 0 || device_type == "" {
  472. resp.HandleError(ctx, 1201, "设备类型不能为空", nil)
  473. }
  474. conds["device_type"] = device_type
  475. if err != nil {
  476. resp.HandleError(ctx, 1201, "获取分页参数失败", nil)
  477. return
  478. }
  479. devices, total, err := h.intelligentBuildingControlService.GetDevices(conds, pageNum, pageSize)
  480. if err != nil {
  481. resp.HandleError(ctx, 1201, "查询设备类型失败", nil)
  482. return
  483. }
  484. resp.PageHandleSuccess(ctx, devices, total, pageNum, pageSize)
  485. }
  486. // ConfigurationDiagram 获取设备组态图
  487. func (h *IntelligentBuildingControlHandler) ConfigurationDiagram(c *gin.Context) {
  488. // 获取查询参数
  489. deviceName := c.Query("deviceName")
  490. if deviceName == "" {
  491. c.String(http.StatusBadRequest, "缺少 deviceName 参数")
  492. return
  493. }
  494. // 传递变量给模板
  495. c.HTML(http.StatusOK, "PAU.html", gin.H{
  496. "deviceName": deviceName,
  497. })
  498. }