123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- package service
- import (
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "github.com/tarm/serial"
- "log"
- "smart_tunnel_edge/util/config"
- "smart_tunnel_edge/util/logger"
- "strconv"
- "time"
- )
- var (
- parity = map[string]serial.Parity{
- "N": serial.ParityNone, // 无校验
- "E": serial.ParityEven, // 偶校验
- "O": serial.ParityOdd, // 奇校验
- "M": serial.ParityMark, // 标记校验
- "S": serial.ParitySpace, // 空格校验
- }
- serialPort = make(map[int8]*serial.Port)
- env = make(map[string]int64) //存储环境传感器光照的切片
- opt = make(map[string]int64) //存储光照传感器光照的切片
- )
- var (
- isLightOperate bool // 标记是否进行开灯或调节亮度操作
- timer *time.Timer // 用于延时关闭灯的计时器
- lastCarTime time.Time // 记录上次来车的时间
- lightDuration = 2 * time.Minute // 灯亮的持续时间(2分钟)
- )
- func GetSerialPort(serialID int8) (*serial.Port, error) {
- port, exists := serialPort[serialID]
- if !exists {
- return nil, errors.New("serial port not found")
- }
- return port, nil
- }
- func OpenSerialPort(portMap map[int8]*config.SerialPort) error {
- fmt.Println("打开串口...")
- var lastError error
- // 遍历串口配置
- for _, port := range portMap {
- // 串口配置
- c := &serial.Config{
- Name: port.Address,
- Baud: port.BaudRate,
- Size: port.DataBits,
- StopBits: serial.StopBits(port.StopBits),
- Parity: parity[port.Parity],
- ReadTimeout: time.Duration(port.Timeout),
- }
- // 打开串口
- pt, err := serial.OpenPort(c)
- serialPort[port.Code] = pt
- if err != nil {
- logger.Logger.Errorf("无法打开串口 %s: %v", port.Address, err)
- if lastError == nil {
- lastError = err
- }
- continue
- }
- go listenPort(port.Code, pt) //开启线程监听串口
- }
- return lastError
- }
- func listenPort(portCode int8, port *serial.Port) {
- fmt.Println("监听串口...")
- buf := make([]byte, 128)
- for {
- // 读取数据
- n, err := port.Read(buf)
- if err != nil {
- log.Printf("读取串口数据失败: %v", err)
- return
- }
- if n > 0 {
- dataString := hex.EncodeToString(buf[:n])
- //fmt.Println("数据:", dataString)
- switch {
- case len(dataString) == 42 && dataString[2:6] == "0310": //环境传感器数据
- //fmt.Print("环境传感:")
- shiDu, _ := strconv.ParseInt(dataString[6:10], 16, 0)
- wenDu, _ := strconv.ParseInt(dataString[10:14], 16, 0)
- gz, _ := strconv.ParseInt(dataString[30:38], 16, 0)
- if _, exists := env[dataString[0:2]]; !exists {
- env[dataString[0:2]] = gz
- }
- data := EnvData{Temperature: float64(wenDu) / 10.0, Humidity: float64(shiDu) / 10.0, Illuminance: gz}
- for _, dev := range config.DevConfig.EnvDevs {
- if dev.Address == dataString[0:2] {
- data.Sn = dev.Sn
- break
- }
- }
- jsonData, _ := json.Marshal(data)
- topic := MqttService.GetTopic(TopicGatherDataEnv)
- err := MqttService.Publish(topic, jsonData)
- if err != nil {
- logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
- continue
- }
- case len(dataString) == 14 && dataString[2:6] == "0302": //光照传感器数据
- //fmt.Printf("光传感:")
- gz, _ := strconv.ParseInt(dataString[6:10], 16, 0)
- if _, exists := env[dataString[0:2]]; !exists {
- opt[dataString[0:2]] = gz
- }
- data := OpticalData{Illuminance: gz}
- for _, dev := range config.DevConfig.EnvDevs {
- if dev.Address == dataString[0:2] {
- data.Sn = dev.Sn
- break
- }
- }
- jsonData, _ := json.Marshal(data)
- topic := MqttService.GetTopic(TopicGatherDataOpt)
- err := MqttService.Publish(topic, jsonData)
- if err != nil {
- logger.Logger.Errorf("MQTT Publish err = %s", err.Error())
- continue
- }
- case len(dataString) == 16 && dataString[0:2] == "78" && dataString[8:16] == "40790d0a": //雷达数据
- dataBytes, _ := hex.DecodeString(dataString)
- speed, _ := strconv.Atoi(string(dataBytes)[1:4])
- // 配置实例
- policy := config.Instance().Policy
- if speed > 5 && policy.Id == 2 { // 速度大于5且策略为根据来车调光(2代表根据来车改变光照)
- now := time.Now() // 记录来车时间
- // 如果已经操作过灯
- if isLightOperate {
- // 如果在两分钟内再来车,延长计时
- if now.Sub(lastCarTime) <= lightDuration {
- timer.Reset(lightDuration)
- }
- } else {
- OperationLampSwitchJudge(portCode, HighLightLevel, 2, 1) //brightness代表亮度,way代表开关继电器回路数,turnOf代表开还是关,1代表开,0代表关
- isLightOperate = true
- timer = time.AfterFunc(lightDuration, func() {
- OperationLampSwitchJudge(portCode, LowLightLevel, 2, 0)
- isLightOperate = false
- })
- }
- // 更新最后来车时间
- lastCarTime = now
- }
- continue
- //default:
- // // 其他情况可以处理默认数据
- // fmt.Printf("错误数据: %s \n", dataString)
- }
- if config.Instance().Policy.Id == 1 && config.Instance().Nums.EnvNum == len(env) && config.Instance().Nums.OptNum == len(opt) {
- envAverage := calculateAverage(env)
- optAverage := calculateAverage(opt)
- control := config.Instance().Policy.Control
- if envAverage-optAverage >= 20000 { //如果相差20000Lux开两路或者调节亮度为90%
- if control == RegulateLight {
- go SetLampBright(1, 90)
- go SetLampBright(2, 90)
- } else if control == RegulateSwitch {
- go SetSwitchMultiRelay(1, 1, []int{1, 2, 3}) //int[]{}表达控制的回路
- go SetSwitchMultiRelay(2, 1, []int{1, 2, 3})
- }
- } else if envAverage-optAverage >= 10000 { //如果相差10000Lux开两路或者调节亮度为60%
- if control == RegulateLight {
- go SetLampBright(1, 60)
- go SetLampBright(2, 60)
- } else if control == RegulateSwitch {
- go SetSwitchRelay(1, 3, 0) //不管如何先将第三路关闭
- go SetSwitchRelay(2, 3, 0)
- go SetSwitchMultiRelay(1, 1, []int{1, 2})
- go SetSwitchMultiRelay(2, 1, []int{1, 2})
- }
- } else {
- if control == RegulateLight {
- go SetLampBright(1, 30)
- go SetLampBright(2, 30)
- } else if control == RegulateSwitch {
- go SetSwitchMultiRelay(1, 0, []int{2, 3})
- go SetSwitchMultiRelay(2, 0, []int{2, 3})
- }
- }
- env = make(map[string]int64)
- opt = make(map[string]int64)
- }
- }
- time.Sleep(100 * time.Millisecond) // 设置延迟,避免CPU占用过高
- }
- }
- func calculateAverage(data map[string]int64) float64 {
- var sum int64
- for _, value := range data {
- sum += value
- }
- if len(data) == 0 {
- return 0 // 防止除以零
- }
- return float64(sum) / float64(len(data))
- }
|