serialmgr.go 6.4 KB

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