intelligentbuildingcontrol.go 14 KB

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