serialmgr.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package service
  2. import (
  3. "encoding/hex"
  4. "encoding/json"
  5. "errors"
  6. "github.com/tarm/serial"
  7. "io"
  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. //logger.Logger.Infof("监听串口:【%v】 \n", portCode)
  68. buf := make([]byte, 512)
  69. for {
  70. // 读取数据
  71. n, err := port.Read(buf)
  72. if err != nil {
  73. if err == io.EOF {
  74. continue
  75. }
  76. //打印错误并重新开启监听
  77. logger.Logger.Errorf("读取串口失败,错误:%v", err)
  78. time.Sleep(2 * time.Second)
  79. go listenPort(portCode, port)
  80. return
  81. }
  82. if n > 0 {
  83. dataString := hex.EncodeToString(buf[:n])
  84. //logger.Logger.Infof("串口=【%v】,读取到的数据:%v", portCode, dataString)
  85. switch {
  86. case len(dataString) == 42 && dataString[2:6] == "0310": //环境传感器数据
  87. shiDu, _ := strconv.ParseInt(dataString[6:10], 16, 0)
  88. wenDu, _ := strconv.ParseInt(dataString[10:14], 16, 0)
  89. gz, _ := strconv.ParseInt(dataString[30:38], 16, 0)
  90. if _, exists := env[dataString[0:2]]; !exists {
  91. env[dataString[0:2]] = gz
  92. }
  93. data := EnvData{Temperature: float64(wenDu) / 10.0, Humidity: float64(shiDu) / 10.0, Illuminance: gz}
  94. for _, dev := range config.DevConfig.EnvDevs {
  95. if dev.Address == dataString[0:2] {
  96. data.Sn = dev.Sn
  97. break
  98. }
  99. }
  100. jsonData, _ := json.Marshal(data)
  101. topic := MqttService.GetTopic(TopicGatherDataEnv)
  102. err := MqttService.Publish(topic, jsonData)
  103. if err != nil {
  104. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  105. continue
  106. }
  107. case len(dataString) == 14 && dataString[2:6] == "0302": //光照传感器数据
  108. gz, _ := strconv.ParseInt(dataString[6:10], 16, 0)
  109. if _, exists := env[dataString[0:2]]; !exists {
  110. opt[dataString[0:2]] = gz
  111. }
  112. data := OpticalData{Illuminance: gz}
  113. for _, dev := range config.DevConfig.EnvDevs {
  114. if dev.Address == dataString[0:2] {
  115. data.Sn = dev.Sn
  116. break
  117. }
  118. }
  119. jsonData, _ := json.Marshal(data)
  120. topic := MqttService.GetTopic(TopicGatherDataOpt)
  121. err := MqttService.Publish(topic, jsonData)
  122. if err != nil {
  123. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  124. continue
  125. }
  126. case len(dataString) == 170 && dataString[2:6] == "0350": //电感数据
  127. totalPower, _ := strconv.ParseInt(dataString[42:50], 16, 0)
  128. data := InductanceData{TotalPower: totalPower}
  129. for _, dev := range config.DevConfig.EnvDevs {
  130. if dev.Address == dataString[0:2] {
  131. data.Sn = dev.Sn
  132. break
  133. }
  134. }
  135. jsonData, _ := json.Marshal(data)
  136. topic := MqttService.GetTopic(TopicGatherDataDG)
  137. err := MqttService.Publish(topic, jsonData)
  138. if err != nil {
  139. logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
  140. continue
  141. }
  142. case len(dataString) == 16 && dataString[0:2] == "78" && dataString[8:16] == "40790d0a": //雷达数据
  143. dataBytes, _ := hex.DecodeString(dataString)
  144. speed, _ := strconv.Atoi(string(dataBytes)[1:4])
  145. // 配置实例
  146. policy := config.Instance().Policy
  147. if speed > 5 && policy.Id == 2 { // 速度大于5且策略为根据来车调光(2代表根据来车改变光照)
  148. now := time.Now() // 记录来车时间
  149. // 如果已经操作过灯
  150. if isLightOperate {
  151. // 如果在两分钟内再来车,延长计时
  152. if now.Sub(lastCarTime) <= lightDuration {
  153. timer.Reset(lightDuration)
  154. }
  155. } else {
  156. OperationLampSwitchJudge([]int8{portCode}, MediumLightLevel, MediumPower) //brightness代表亮度,way代表开关继电器回路数,turnOf代表开还是关,1代表开,0代表关
  157. isLightOperate = true
  158. timer = time.AfterFunc(lightDuration, func() {
  159. OperationLampSwitchJudge([]int8{portCode}, LowLightLevel, LowPower)
  160. isLightOperate = false
  161. })
  162. }
  163. // 更新最后来车时间
  164. lastCarTime = now
  165. }
  166. continue
  167. //default:
  168. // // 其他情况可以处理默认数据
  169. // fmt.Printf("错误数据: %s \n", dataString)
  170. }
  171. if config.Instance().Policy.Id == 1 && config.Instance().Nums.EnvNum == len(env) && config.Instance().Nums.OptNum == len(opt) {
  172. if len(dataString) == 16 && dataString[2:6] == "0500" && dataString[10:12] == "00" {
  173. continue
  174. }
  175. envAverage := calculateAverage(env)
  176. optAverage := calculateAverage(opt)
  177. if envAverage-optAverage >= 20000 { //如果相差20000Lux开两路或者调节亮度为90%
  178. OperationLampSwitchJudge([]int8{1, 2}, FullLightLevel, FullPower)
  179. } else if envAverage-optAverage >= 10000 { //如果相差10000Lux开两路或者调节亮度为60%
  180. OperationLampSwitchJudge([]int8{1, 2}, MediumLightLevel, MediumPower)
  181. } else {
  182. OperationLampSwitchJudge([]int8{1, 2}, LowLightLevel, LowPower)
  183. }
  184. env = make(map[string]int64)
  185. opt = make(map[string]int64)
  186. }
  187. }
  188. time.Sleep(100 * time.Millisecond) // 设置延迟,避免CPU占用过高
  189. }
  190. }
  191. func calculateAverage(data map[string]int64) float64 {
  192. var sum int64
  193. for _, value := range data {
  194. sum += value
  195. }
  196. if len(data) == 0 {
  197. return 0 // 防止除以零
  198. }
  199. return float64(sum) / float64(len(data))
  200. }