serialmgr.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package service
  2. import (
  3. "encoding/hex"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/tarm/serial"
  8. "log"
  9. "smart_tunnel_edge/util/config"
  10. "smart_tunnel_edge/util/logger"
  11. "strconv"
  12. "time"
  13. )
  14. var (
  15. parity = map[string]serial.Parity{
  16. "N": serial.ParityNone, // 无校验
  17. "E": serial.ParityEven, // 偶校验
  18. "O": serial.ParityOdd, // 奇校验
  19. "M": serial.ParityMark, // 标记校验
  20. "S": serial.ParitySpace, // 空格校验
  21. }
  22. serialPort = make(map[int8]*serial.Port)
  23. env = make(map[string]int64) //存储环境传感器光照的切片
  24. opt = make(map[string]int64) //存储光照传感器光照的切片
  25. )
  26. var (
  27. isLightOperate bool // 标记是否进行开灯或调节亮度操作
  28. timer *time.Timer // 用于延时关闭灯的计时器
  29. lastCarTime time.Time // 记录上次来车的时间
  30. lightDuration = 2 * time.Minute // 灯亮的持续时间(2分钟)
  31. )
  32. func GetSerialPort(serialID int8) (*serial.Port, error) {
  33. port, exists := serialPort[serialID]
  34. if !exists {
  35. return nil, errors.New("serial port not found")
  36. }
  37. return port, nil
  38. }
  39. func OpenSerialPort(portMap map[int8]*config.SerialPort) error {
  40. fmt.Println("打开串口...")
  41. var lastError error
  42. // 遍历串口配置
  43. for _, port := range portMap {
  44. // 串口配置
  45. c := &serial.Config{
  46. Name: port.Address,
  47. Baud: port.BaudRate,
  48. Size: port.DataBits,
  49. StopBits: serial.StopBits(port.StopBits),
  50. Parity: parity[port.Parity],
  51. ReadTimeout: time.Duration(port.Timeout),
  52. }
  53. // 打开串口
  54. pt, err := serial.OpenPort(c)
  55. serialPort[port.Code] = pt
  56. if err != nil {
  57. logger.Logger.Errorf("无法打开串口 %s: %v", port.Address, err)
  58. if lastError == nil {
  59. lastError = err
  60. }
  61. continue
  62. }
  63. go listenPort(port.Code, pt) //开启线程监听串口
  64. }
  65. return lastError
  66. }
  67. func listenPort(portCode int8, port *serial.Port) {
  68. fmt.Println("监听串口...")
  69. buf := make([]byte, 512)
  70. for {
  71. // 读取数据
  72. n, err := port.Read(buf)
  73. if err != nil {
  74. log.Printf("读取串口数据失败: %v", err)
  75. return
  76. }
  77. if n > 0 {
  78. dataString := hex.EncodeToString(buf[:n])
  79. switch {
  80. case len(dataString) == 42 && dataString[2:6] == "0310": //环境传感器数据
  81. shiDu, _ := strconv.ParseInt(dataString[6:10], 16, 0)
  82. wenDu, _ := strconv.ParseInt(dataString[10:14], 16, 0)
  83. gz, _ := strconv.ParseInt(dataString[30:38], 16, 0)
  84. if _, exists := env[dataString[0:2]]; !exists {
  85. env[dataString[0:2]] = gz
  86. }
  87. data := EnvData{Temperature: float64(wenDu) / 10.0, Humidity: float64(shiDu) / 10.0, Illuminance: gz}
  88. for _, dev := range config.DevConfig.EnvDevs {
  89. if dev.Address == dataString[0:2] {
  90. data.Sn = dev.Sn
  91. break
  92. }
  93. }
  94. jsonData, _ := json.Marshal(data)
  95. topic := MqttService.GetTopic(TopicGatherDataEnv)
  96. err := MqttService.Publish(topic, jsonData)
  97. if err != nil {
  98. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  99. continue
  100. }
  101. case len(dataString) == 14 && dataString[2:6] == "0302": //光照传感器数据
  102. gz, _ := strconv.ParseInt(dataString[6:10], 16, 0)
  103. if _, exists := env[dataString[0:2]]; !exists {
  104. opt[dataString[0:2]] = gz
  105. }
  106. data := OpticalData{Illuminance: gz}
  107. for _, dev := range config.DevConfig.EnvDevs {
  108. if dev.Address == dataString[0:2] {
  109. data.Sn = dev.Sn
  110. break
  111. }
  112. }
  113. jsonData, _ := json.Marshal(data)
  114. topic := MqttService.GetTopic(TopicGatherDataOpt)
  115. err := MqttService.Publish(topic, jsonData)
  116. if err != nil {
  117. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  118. continue
  119. }
  120. case len(dataString) == 170 && dataString[2:6] == "0350": //电感数据
  121. totalPower, _ := strconv.ParseInt(dataString[42:50], 16, 0)
  122. data := InductanceData{TotalPower: totalPower}
  123. for _, dev := range config.DevConfig.EnvDevs {
  124. if dev.Address == dataString[0:2] {
  125. data.Sn = dev.Sn
  126. break
  127. }
  128. }
  129. jsonData, _ := json.Marshal(data)
  130. topic := MqttService.GetTopic(TopicGatherDataDG)
  131. err := MqttService.Publish(topic, jsonData)
  132. if err != nil {
  133. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  134. continue
  135. }
  136. case len(dataString) == 16 && dataString[0:2] == "78" && dataString[8:16] == "40790d0a": //雷达数据
  137. dataBytes, _ := hex.DecodeString(dataString)
  138. speed, _ := strconv.Atoi(string(dataBytes)[1:4])
  139. // 配置实例
  140. policy := config.Instance().Policy
  141. if speed > 5 && policy.Id == 2 { // 速度大于5且策略为根据来车调光(2代表根据来车改变光照)
  142. now := time.Now() // 记录来车时间
  143. // 如果已经操作过灯
  144. if isLightOperate {
  145. // 如果在两分钟内再来车,延长计时
  146. if now.Sub(lastCarTime) <= lightDuration {
  147. timer.Reset(lightDuration)
  148. }
  149. } else {
  150. OperationLampSwitchJudge([]int8{portCode}, MediumLightLevel, MediumPower) //brightness代表亮度,way代表开关继电器回路数,turnOf代表开还是关,1代表开,0代表关
  151. isLightOperate = true
  152. timer = time.AfterFunc(lightDuration, func() {
  153. OperationLampSwitchJudge([]int8{portCode}, LowLightLevel, LowPower)
  154. isLightOperate = false
  155. })
  156. }
  157. // 更新最后来车时间
  158. lastCarTime = now
  159. }
  160. continue
  161. //default:
  162. // // 其他情况可以处理默认数据
  163. // fmt.Printf("错误数据: %s \n", dataString)
  164. }
  165. if config.Instance().Policy.Id == 1 && config.Instance().Nums.EnvNum == len(env) && config.Instance().Nums.OptNum == len(opt) {
  166. envAverage := calculateAverage(env)
  167. optAverage := calculateAverage(opt)
  168. if envAverage-optAverage >= 20000 { //如果相差20000Lux开两路或者调节亮度为90%
  169. OperationLampSwitchJudge([]int8{1, 2}, FullLightLevel, FullPower)
  170. } else if envAverage-optAverage >= 10000 { //如果相差10000Lux开两路或者调节亮度为60%
  171. OperationLampSwitchJudge([]int8{1, 2}, MediumLightLevel, MediumPower)
  172. } else {
  173. OperationLampSwitchJudge([]int8{1, 2}, LowLightLevel, LowPower)
  174. }
  175. env = make(map[string]int64)
  176. opt = make(map[string]int64)
  177. }
  178. }
  179. time.Sleep(100 * time.Millisecond) // 设置延迟,避免CPU占用过高
  180. }
  181. }
  182. func calculateAverage(data map[string]int64) float64 {
  183. var sum int64
  184. for _, value := range data {
  185. sum += value
  186. }
  187. if len(data) == 0 {
  188. return 0 // 防止除以零
  189. }
  190. return float64(sum) / float64(len(data))
  191. }