| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- package main
- import (
- "runtime/debug"
- "strconv"
- "strings"
- "sync"
- "time"
- "github.com/go-redis/redis/v7"
- "github.com/sirupsen/logrus"
- "lc/common/models"
- "lc/common/mqtt"
- "lc/common/protocol"
- "lc/common/util"
- )
- var _LampStrategyMgrOnce sync.Once
- var _LampStrategyMgrSingle *LampStrategyMgr
- func GetLampStrategyMgr() *LampStrategyMgr {
- _LampStrategyMgrOnce.Do(func() {
- _LampStrategyMgrSingle = &LampStrategyMgr{
- mapLampOOT: make(map[string][]protocol.CHZB_OnOffTime),
- mapLampHlOOT: make(map[string][]protocol.HLWLZB_OnOffTime),
- }
- })
- return _LampStrategyMgrSingle
- }
- // LampStrategyQueue redis缓存
- var LampStrategyQueue = "lamp_strategy_queue" //已修改的灯控编码列表,队列方式,先进先出
- // LampStrategyMgr 灯控时间策略管理
- type LampStrategyMgr struct {
- mapLampOOT map[string][]protocol.CHZB_OnOffTime //灯控策略时间,开灯时间段
- mapLampHlOOT map[string][]protocol.HLWLZB_OnOffTime //灯控策略时间,开灯时间段
- }
- func (o *LampStrategyMgr) Handler(args ...interface{}) interface{} {
- defer func() {
- if err := recover(); err != nil {
- gopool.Add(o.Handler, args)
- logrus.Errorf("LampStrategyMgr.Handler发生异常:%s", string(debug.Stack()))
- }
- }()
- IDList := make([]string, 0, 100)
- for {
- strID, err := redisCltRawData.RPop(LampStrategyQueue).Result() //灯控id
- if err != nil {
- if err != redis.Nil { //排除掉无数据的情况
- logrus.Errorf("读取redis队列lamp_strategy_queue发生错误:%s", err.Error())
- }
- } else {
- id := strings.Trim(strID, " ")
- if len(id) > 0 {
- IDList = append(IDList, id)
- }
- }
- //队列无数据并且IDList有数据,或IDList数据达到封顶值100,则进行处理
- if (err == redis.Nil && len(IDList) > 0) || len(IDList) == 100 {
- idlist := RemoveReplicaString(IDList)
- o.HandleZigbeeLampStrategy(idlist) //处理zigbee灯控
- o.HandleHLZigbeeLampStrategy(idlist) //处理海蓝zigbee灯控
- o.HandleYm485LampStrategy(idlist) //处理485灯控
- IDList = make([]string, 0, 100)
- }
- time.Sleep(1 * time.Second)
- }
- }
- type ConcentratorInfo struct {
- DID string
- Tenant string
- GID string
- LampIDs []uint32
- }
- // HandleZigbeeLampStrategy 处理Zigbee灯控策略
- func (o *LampStrategyMgr) HandleZigbeeLampStrategy(IDs []string) {
- zlsArr, err := models.GetZigbeeLampStrategyByIDs(IDs)
- if err != nil {
- oList := make([]interface{}, 0, len(IDs))
- for _, v := range IDs {
- oList = append(oList, v)
- }
- redisCltRawData.LPush(LampStrategyQueue, oList...)
- }
- if len(zlsArr) == 0 {
- return
- }
- //处理照明策略时间
- mapTime := make(map[string][]protocol.CHZB_OnOffTime) //策略编号->时间和亮度信息
- for _, v := range zlsArr {
- if _, ok := mapTime[v.Strategy]; ok {
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- continue
- }
- var ls []models.LampStrategy //time_info字段
- if err := json.UnmarshalFromString(v.TimeInfo, &ls); err != nil {
- logrus.Errorf("HandleZigbeeLampStrategy:策略时间字段解析错误,字段内容:%s,错误原因:%s", v.TimeInfo, err.Error())
- continue
- }
- if len(ls) == 0 {
- continue
- }
- //日出日落
- if v.Sunset == 1 {
- if rise, set, err := util.SunriseSunsetForChina(v.Latitude, v.Longitude); err == nil {
- onOffTimes := make([]protocol.CHZB_OnOffTime, 1)
- onOffTimes[0].Brightness = uint8(ls[0].Brightness)
- onHour, _ := strconv.Atoi(strings.Split(set, ":")[0])
- onMinute, _ := strconv.Atoi(strings.Split(set, ":")[1])
- offHour, _ := strconv.Atoi(strings.Split(rise, ":")[0])
- offMinute, _ := strconv.Atoi(strings.Split(rise, ":")[1])
- onOffTimes[0].OnHour = uint8(onHour)
- onOffTimes[0].OnMinite = uint8(onMinute)
- onOffTimes[0].OffHour = uint8(offHour)
- onOffTimes[0].OffMinite = uint8(offMinute)
- mapTime[v.Strategy] = append(mapTime[v.Strategy], onOffTimes...)
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- }
- } else {
- onOffTimes := make([]protocol.CHZB_OnOffTime, len(ls), len(ls))
- for i, v := range ls {
- onOffTimes[i].Brightness = uint8(v.Brightness)
- onHour, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[0])
- onMinute, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[1])
- offHour, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[0])
- offMinute, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[1])
- onOffTimes[i].OnHour = uint8(onHour)
- onOffTimes[i].OnMinite = uint8(onMinute)
- onOffTimes[i].OffHour = uint8(offHour)
- onOffTimes[i].OffMinite = uint8(offMinute)
- }
- mapTime[v.Strategy] = append(mapTime[v.Strategy], onOffTimes...)
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- }
- }
- //处理照明策略,集控器及末端编号
- mapStrategyToMapConcentratorToNumbers := make(map[string]map[string]*ConcentratorInfo)
- for _, v := range zlsArr {
- if _, ok := mapStrategyToMapConcentratorToNumbers[v.Strategy]; !ok {
- mapStrategyToMapConcentratorToNumbers[v.Strategy] = make(map[string]*ConcentratorInfo)
- }
- if pConcentratorInfo, ok := mapStrategyToMapConcentratorToNumbers[v.Strategy][v.Concentrator]; !ok {
- c := ConcentratorInfo{DID: v.Concentrator, Tenant: v.Tenant, GID: v.GID}
- c.LampIDs = append(c.LampIDs, uint32(v.Number))
- mapStrategyToMapConcentratorToNumbers[v.Strategy][v.Concentrator] = &c
- } else {
- pConcentratorInfo.LampIDs = append(pConcentratorInfo.LampIDs, uint32(v.Number))
- }
- }
- for k0, v0 := range mapStrategyToMapConcentratorToNumbers {
- oots, ok := mapTime[k0]
- if !ok {
- continue
- }
- for k1, v1 := range v0 {
- var obj protocol.Pack_SetOnOffTime
- seq := GetNextSeq()
- str, err := obj.EnCode(k1, v1.GID, seq, v1.LampIDs, oots)
- if err != nil {
- continue
- }
- topic := GetTopic(v1.Tenant, protocol.DT_CONCENTRATOR, k1, protocol.TP_CHZB_SET_ONOFFTIME)
- var msg string
- if msg0, errmsg := json.MarshalIndent(obj, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- odb := models.DeviceCmdRecord{
- ID: seq,
- GID: v1.GID,
- DID: k1,
- Topic: topic,
- Message: msg,
- State: 0,
- }
- if err := models.G_db.Create(&odb).Error; err != nil {
- logrus.Errorf("HandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落时间时指令入库错误:%s", k1, v1.LampIDs, err.Error())
- } else {
- logrus.Errorf("HandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落时间时指令入库成功", k1, v1.LampIDs)
- }
- err = GetMQTTMgr().Publish(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- logrus.Errorf("HandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落消息错误:%s", k1, v1.LampIDs, err.Error())
- }
- }
- }
- }
- // HandleHLZigbeeLampStrategy 处理海蓝Zigbee灯控策略
- func (o *LampStrategyMgr) HandleHLZigbeeLampStrategy(IDs []string) {
- zlsArr, err := models.GetHLZigbeeLampStrategyByIDs(IDs) ////海蓝根据灯控编码列表,获取所有hlzigbee灯控
- if err != nil {
- oList := make([]interface{}, 0, len(IDs))
- for _, v := range IDs {
- oList = append(oList, v)
- }
- redisCltRawData.LPush(LampStrategyQueue, oList...) //灯控ID入队列中,待处理的ids
- }
- if len(zlsArr) == 0 {
- return
- }
- //处理照明策略时间-从存入到数据库中的策略处理
- mapTime := make(map[string][]protocol.HLWLZB_OnOffTime) //策略编号->时间和亮度信息
- for _, v := range zlsArr {
- if _, ok := mapTime[v.Strategy]; ok {
- o.mapLampHlOOT[v.ID] = append(o.mapLampHlOOT[v.ID], mapTime[v.Strategy]...)
- continue
- }
- var ls []models.LampStrategy //time_info字段
- if err := json.UnmarshalFromString(v.TimeInfo, &ls); err != nil {
- logrus.Errorf("HandleZigbeeLampStrategy:策略时间字段解析错误,字段内容:%s,错误原因:%s", v.TimeInfo, err.Error())
- continue
- }
- if len(ls) == 0 {
- continue
- }
- //日出日落
- if v.Sunset == 1 {
- if rise, set, err := util.SunriseSunsetForChina(v.Latitude, v.Longitude); err == nil {
- oots := make([]protocol.HLWLZB_OnOffTime, 1)
- oots[0].Brightness = uint8(ls[0].Brightness)
- onhour, _ := strconv.Atoi(strings.Split(set, ":")[0])
- onminite, _ := strconv.Atoi(strings.Split(set, ":")[1])
- offhour, _ := strconv.Atoi(strings.Split(rise, ":")[0])
- offminite, _ := strconv.Atoi(strings.Split(rise, ":")[1])
- oots[0].OnHour = uint8(onhour)
- oots[0].OnMinite = uint8(onminite)
- oots[0].OffHour = uint8(offhour)
- oots[0].OffMinite = uint8(offminite)
- mapTime[v.Strategy] = append(mapTime[v.Strategy], oots...)
- o.mapLampHlOOT[v.ID] = append(o.mapLampHlOOT[v.ID], mapTime[v.Strategy]...)
- }
- } else {
- onOffTimes := make([]protocol.HLWLZB_OnOffTime, len(ls), len(ls))
- for i, v := range ls {
- onOffTimes[i].Brightness = uint8(v.Brightness)
- onHour, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[0])
- onMinute, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[1])
- offHour, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[0])
- offMinute, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[1])
- onOffTimes[i].OnHour = uint8(onHour)
- onOffTimes[i].OnMinite = uint8(onMinute)
- onOffTimes[i].OffHour = uint8(offHour)
- onOffTimes[i].OffMinite = uint8(offMinute)
- }
- mapTime[v.Strategy] = append(mapTime[v.Strategy], onOffTimes...)
- o.mapLampHlOOT[v.ID] = append(o.mapLampHlOOT[v.ID], mapTime[v.Strategy]...)
- }
- }
- //处理照明策略,集控器及末端编号
- mapStrategyToMapConcentratorToNumbers := make(map[string]map[string]*ConcentratorInfo)
- for _, v := range zlsArr {
- if _, ok := mapStrategyToMapConcentratorToNumbers[v.Strategy]; !ok {
- mapStrategyToMapConcentratorToNumbers[v.Strategy] = make(map[string]*ConcentratorInfo) //key为Strategy 没有就创建
- }
- if pConcentratorInfo, ok := mapStrategyToMapConcentratorToNumbers[v.Strategy][v.Concentrator]; !ok { //没有就创建
- c := ConcentratorInfo{DID: v.Concentrator, Tenant: v.Tenant, GID: v.GID}
- c.LampIDs = append(c.LampIDs, uint32(v.Number)) //灯加入进去
- mapStrategyToMapConcentratorToNumbers[v.Strategy][v.Concentrator] = &c
- } else {
- pConcentratorInfo.LampIDs = append(pConcentratorInfo.LampIDs, uint32(v.Number)) //加灯
- }
- }
- for k0, v0 := range mapStrategyToMapConcentratorToNumbers {
- oots, ok := mapTime[k0]
- if !ok {
- continue
- }
- for k1, v1 := range v0 {
- if len(oots) == 1 && (oots[0].OffHour == 0 && oots[0].OffMinite == 0 && oots[0].OnHour == 0 && oots[0].OnMinite == 0) { //清除策略
- var obj protocol.Pack_HLClearStrategy
- seq := GetNextSeq()
- str, err := obj.EnCode(k1)
- logrus.Debugf("%s", str)
- s, err := json.MarshalToString(oots)
- logrus.Debugf("%s", s)
- if err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器---[%s]对灯控[%v]发布清除策略指令入库错误:%s", k1, v1.LampIDs, err.Error())
- continue
- }
- topic := GetHLTopicDown(v1.Tenant, protocol.DT_CONCENTRATOR, k1, protocol.TP_CHZB_SET_ONOFFTIME)
- var msg string
- if msg0, errmsg := json.MarshalIndent(obj, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- odb := models.DeviceCmdRecord{ //记录入库
- ID: seq,
- GID: v1.GID,
- DID: k1,
- Topic: topic,
- Message: msg,
- State: 0,
- }
- if err := models.G_db.Create(&odb).Error; err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布清除策略时指令入库错误:%s", k1, v1.LampIDs, err.Error())
- } else {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布清除策略时指令入库成功", k1, v1.LampIDs)
- }
- err = GetHlMqttMgr().Publish(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布清除策略消息错误:%s", k1, v1.LampIDs, err.Error())
- }
- return
- }
- var obj protocol.Pack_HLSetOnOffTime
- seq := GetNextSeq()
- str, err := obj.EnCode(k1, v1.GID, seq, v1.LampIDs, oots)
- logrus.Debugf("%s", str)
- s, err := json.MarshalToString(oots)
- logrus.Debugf("%s", s)
- if err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器---[%s]对灯控[%v]发布日出日落时间时指令入库错误:%s", k1, v1.LampIDs, err.Error())
- continue
- }
- topic := GetHLTopicDown(v1.Tenant, protocol.DT_CONCENTRATOR, k1, protocol.TP_CHZB_SET_ONOFFTIME)
- var msg string
- if msg0, errMsg := json.MarshalIndent(obj, "", " "); errMsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- odb := models.DeviceCmdRecord{ //记录入库
- ID: seq,
- GID: v1.GID,
- DID: k1,
- Topic: topic,
- Message: msg,
- State: 0,
- }
- if err := models.G_db.Create(&odb).Error; err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落时间时指令入库错误:%s", k1, v1.LampIDs, err.Error())
- } else {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落时间时指令入库成功", k1, v1.LampIDs)
- }
- err = GetHlMqttMgr().Publish(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- logrus.Errorf("HLHandleZigbeeLampStrategy:集控器[%s]对灯控[%v]发布日出日落消息错误:%s", k1, v1.LampIDs, err.Error())
- }
- }
- }
- }
- // HandleYm485LampStrategy 处理裕明485灯控
- func (o *LampStrategyMgr) HandleYm485LampStrategy(IDs []string) {
- lsArr, err := models.GetYm485Lampstrategy(IDs)
- if err != nil {
- oList := make([]interface{}, 0, len(IDs))
- for _, v := range IDs {
- oList = append(oList, v)
- }
- redisCltRawData.LPush(LampStrategyQueue, oList...)
- }
- if len(lsArr) == 0 {
- return
- }
- //处理照明策略时间
- mapTime := make(map[string][]protocol.CHZB_OnOffTime) //策略编号->时间和亮度信息
- for _, v := range lsArr {
- if _, ok := mapTime[v.Strategy]; ok {
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- continue
- }
- var ls []models.LampStrategy //time_info字段
- if err := json.UnmarshalFromString(v.TimeInfo, &ls); err != nil {
- logrus.Errorf("HandleYm485LampStrategy:策略时间字段解析错误,字段内容:%s,错误原因:%s", v.TimeInfo, err.Error())
- continue
- }
- if len(ls) == 0 {
- continue
- }
- //日出日落
- if v.Sunset == 1 {
- if rise, set, err := util.SunriseSunsetForChina(v.Latitude, v.Longitude); err == nil {
- onOffTimes := make([]protocol.CHZB_OnOffTime, 1)
- onOffTimes[0].Brightness = uint8(ls[0].Brightness)
- onHour, _ := strconv.Atoi(strings.Split(set, ":")[0])
- onMinute, _ := strconv.Atoi(strings.Split(set, ":")[1])
- offHour, _ := strconv.Atoi(strings.Split(rise, ":")[0])
- offMinute, _ := strconv.Atoi(strings.Split(rise, ":")[1])
- onOffTimes[0].OnHour = uint8(onHour)
- onOffTimes[0].OnMinite = uint8(onMinute)
- onOffTimes[0].OffHour = uint8(offHour)
- onOffTimes[0].OffMinite = uint8(offMinute)
- mapTime[v.Strategy] = append(mapTime[v.Strategy], onOffTimes...)
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- }
- } else {
- onOffTimes := make([]protocol.CHZB_OnOffTime, len(ls), len(ls))
- for i, v := range ls {
- onOffTimes[i].Brightness = uint8(v.Brightness)
- onHour, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[0])
- onMinute, _ := strconv.Atoi(strings.Split(v.Ontime, ":")[1])
- offHour, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[0])
- offMinute, _ := strconv.Atoi(strings.Split(v.Offtime, ":")[1])
- onOffTimes[i].OnHour = uint8(onHour)
- onOffTimes[i].OnMinite = uint8(onMinute)
- onOffTimes[i].OffHour = uint8(offHour)
- onOffTimes[i].OffMinite = uint8(offMinute)
- }
- mapTime[v.Strategy] = append(mapTime[v.Strategy], onOffTimes...)
- o.mapLampOOT[v.ID] = append(o.mapLampOOT[v.ID], mapTime[v.Strategy]...)
- }
- }
- //处理照明策略,集控器及末端编号
- for _, v := range lsArr {
- oots, ok := mapTime[v.Strategy]
- if !ok {
- continue
- }
- var obj protocol.Pack_SetOnOffTime
- seq := GetNextSeq()
- str, err := obj.EnCode(v.ID, v.GID, seq, nil, oots)
- if err != nil {
- continue
- }
- topic := GetTopic(v.Tenant, protocol.DT_LAMPCONTROLLER, v.ID, protocol.TP_YM_SET_ONOFFTIME)
- var msg string
- if msg0, errMsg := json.MarshalIndent(obj, "", " "); errMsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- odb := models.DeviceCmdRecord{
- ID: seq,
- GID: v.GID,
- DID: v.ID,
- Topic: topic,
- Message: msg,
- State: 0,
- }
- if err := models.G_db.Create(&odb).Error; err != nil {
- logrus.Errorf("HandleYm485LampStrategy:对灯控[%s]发布日出日落时间时指令入库错误:%s", v.ID, err.Error())
- } else {
- logrus.Errorf("HandleYm485LampStrategy:对灯控[%s]发布日出日落时间时指令入库成功", v.ID)
- }
- err = GetMQTTMgr().Publish(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- logrus.Errorf("HandleYm485LampStrategy:对灯控[%s]发布日出日落消息错误:%s", v.ID, err.Error())
- }
- }
- }
- // RemoveReplicaString 字符串去重
- func RemoveReplicaString(slc []string) []string {
- result := make([]string, 0)
- tempMap := make(map[string]bool, len(slc))
- for _, e := range slc {
- if _, ok := tempMap[e]; !ok {
- tempMap[e] = true
- result = append(result, e)
- }
- }
- return result
- }
|