concentrator.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. package main
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "encoding/hex"
  6. "errors"
  7. "runtime/debug"
  8. "strconv"
  9. "sync"
  10. "time"
  11. "github.com/go-redis/redis/v7"
  12. "github.com/sirupsen/logrus"
  13. "github.com/valyala/bytebufferpool"
  14. "lc/common/mqtt"
  15. "lc/common/protocol"
  16. "lc/common/util"
  17. "lc/edge/ipole/zigbee"
  18. )
  19. var ConcentratorProtocol = "CHDDJK-Zigbee"
  20. var LampOotPrefix = "lamp_oot_"
  21. var LampSwitchPrefix = "lamp_switch_"
  22. var LampBroadcastPrefix = "lamp_broadcastauto_"
  23. var LampAlarmPrefix = "lamp_alarm_"
  24. func PoolPut(b *bytebufferpool.ByteBuffer) {
  25. if b != nil {
  26. bytebufferpool.Put(b)
  27. }
  28. }
  29. func GetPoleIDByte(PoleID uint32) []byte {
  30. tmp := make([]byte, 4)
  31. binary.BigEndian.PutUint32(tmp, PoleID)
  32. return tmp[2:4]
  33. }
  34. type LampTimeRange struct {
  35. Start util.MLTime `json:"start"`
  36. End util.MLTime `json:"end"`
  37. Brightness uint8 `json:"brightness"` //0熄灯,大于0都是开灯
  38. }
  39. func (o *LampTimeRange) isInTimeRange(t time.Time) bool {
  40. if t.After(time.Time(o.Start)) && t.Before(time.Time(o.End)) {
  41. return true
  42. }
  43. return false
  44. }
  45. type LampAlarmInfo struct {
  46. Alarm *protocol.LampAlarm `json:"alarm"`
  47. Send bool `json:"send"`
  48. }
  49. // Concentrator 集中器管理
  50. type Concentrator struct {
  51. seq uint8
  52. mutexSeq sync.Mutex
  53. devinfo *protocol.DevInfo
  54. model *protocol.IotModel
  55. ctx context.Context
  56. cancel context.CancelFunc
  57. downQueue *util.MlQueue
  58. readQueue *util.MlQueue //读取数据的队列,读完则发送
  59. mapLamps map[uint32]string
  60. mapTopicHandle map[string]func(m mqtt.Message)
  61. mapLamps2OOT map[uint32][]zigbee.OnOffTime //时控策略
  62. mapTempLampsOOT map[uint32]*LampTimeRange //临时手动控时间段,手动控制开关灯
  63. broadcastAutoTime time.Time //广播模式截止时间,过期自动恢复
  64. mapLampAlarm map[string]*LampAlarmInfo //告警数据
  65. chanDevInfo chan *protocol.DevInfo //设备管理更新
  66. chanModelInfo chan *ModelInfo //设备管理更新
  67. }
  68. func NewConcentrator(info *protocol.DevInfo) Device {
  69. ctx, cancel := context.WithCancel(context.Background())
  70. dev := &Concentrator{
  71. mapLamps: make(map[uint32]string),
  72. devinfo: info,
  73. ctx: ctx,
  74. cancel: cancel,
  75. downQueue: util.NewQueue(200),
  76. readQueue: util.NewQueue(200),
  77. mapTopicHandle: make(map[string]func(m mqtt.Message)),
  78. mapLamps2OOT: make(map[uint32][]zigbee.OnOffTime), //时控策略
  79. mapTempLampsOOT: make(map[uint32]*LampTimeRange), //临时时间段,手动控制开关灯
  80. broadcastAutoTime: time.Time{},
  81. mapLampAlarm: make(map[string]*LampAlarmInfo),
  82. chanDevInfo: make(chan *protocol.DevInfo),
  83. chanModelInfo: make(chan *ModelInfo),
  84. }
  85. iot, err := loadModel(info.TID)
  86. if err == nil && iot.TID == info.TID && iot.Protocol == ConcentratorProtocol {
  87. dev.model = iot
  88. }
  89. dev.SetTopicHandle()
  90. return dev
  91. }
  92. func (o *Concentrator) SetTopicHandle() {
  93. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_BROADCASTTIME)] = o.HandleTpChzbSetBroadcasttime
  94. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_WAITTIME)] = o.HandleTpChzbSetWaittime
  95. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_SWITCH)] = o.HandleTpChzbSetSwitch
  96. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_RECOVERY_AUTO)] = o.HandleTpChzbSetRecoveryAuto
  97. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_ONOFFTIME)] = o.HandleTpChzbSetOnofftime
  98. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_ONOFFTIME)] = o.HandleTpChzbQueryOnofftime
  99. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_UPDATE_LAMP)] = o.HandleTpChzbSetUpdateLamp
  100. o.mapTopicHandle[GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_TIME)] = o.HandleTpChzbQueryTime
  101. }
  102. func (o *Concentrator) MQTTSubscribe() {
  103. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_BROADCASTTIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //广播校时
  104. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_WAITTIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //设置zigbee集中器收发等待时间
  105. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_SWITCH), mqtt.ExactlyOnce, o.HandleCache, ToAll) //开关灯,广播开关灯
  106. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_RECOVERY_AUTO), mqtt.ExactlyOnce, o.HandleCache, ToAll) //广播开关灯
  107. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_ONOFFTIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //设置开关灯时间段
  108. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_ONOFFTIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //读取开关灯时间段
  109. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_UPDATE_LAMP), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //更新灯控末端
  110. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_TIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //读取单灯末端时间
  111. }
  112. func (o *Concentrator) Start() {
  113. o.MQTTSubscribe()
  114. retry := 3
  115. sleep := time.Duration(2)
  116. for i := 0; i < retry; i++ {
  117. if err := o.ReloadOOTFromRedis(); err == nil {
  118. break
  119. }
  120. time.Sleep(sleep * time.Second)
  121. }
  122. for i := 0; i < retry; i++ {
  123. if err := o.ReloadSwitchOOTFromRedis(); err == nil {
  124. break
  125. }
  126. time.Sleep(sleep * time.Second)
  127. }
  128. for i := 0; i < retry; i++ {
  129. if err := o.ReloadBroadCastFromRedis(); err == nil {
  130. break
  131. }
  132. time.Sleep(sleep * time.Second)
  133. }
  134. for i := 0; i < retry; i++ {
  135. if err := o.ReloadLampAlarmFromRedis(); err == nil {
  136. break
  137. }
  138. time.Sleep(sleep * time.Second)
  139. }
  140. go o.Handle()
  141. }
  142. func (o *Concentrator) Stop() {
  143. o.cancel()
  144. }
  145. func (o *Concentrator) UpdateInfo(devinfo protocol.DevInfo) {
  146. o.chanDevInfo <- &devinfo
  147. }
  148. func (o *Concentrator) GetDevInfo() *protocol.DevInfo {
  149. return o.devinfo
  150. }
  151. func (o *Concentrator) UpdateModel(tid uint16, flag int) {
  152. if tid > 0 {
  153. mi := ModelInfo{
  154. TID: tid,
  155. Flag: flag,
  156. }
  157. o.chanModelInfo <- &mi
  158. }
  159. }
  160. func (o *Concentrator) UpdateModel2(mi *ModelInfo) {
  161. if o.devinfo.TID != mi.TID {
  162. return
  163. }
  164. if mi.Flag == 0 {
  165. logrus.Errorf("Concentrator.UpdateModel2:设备[%s]的物模型[tid=%d]模型文件被删除,下次启动即将生效。", o.devinfo.DevCode, mi.TID)
  166. return
  167. }
  168. logrus.Debugf("Concentrator.UpdateModel2:更新设备[%s]的物模型[%d]", o.devinfo.DevCode, mi.TID)
  169. iot, err := loadModel(mi.TID)
  170. if err != nil {
  171. logrus.Errorf("Concentrator.UpdateModel2:加载模型[%d]文件错误:%s", mi.TID, err.Error())
  172. return
  173. }
  174. if iot.Protocol == ConcentratorProtocol { //合法的物模型
  175. o.model = iot
  176. logrus.Infof("Concentrator.UpdateModel2:更新设备[%s]的物模型[%d]成功", o.devinfo.DevCode, mi.TID)
  177. } else {
  178. logrus.Error("Concentrator.UpdateModel2:物模型错误,TID和文件名tid不一致或协议非ModbusRTU协议")
  179. }
  180. }
  181. func (o *Concentrator) ReloadOOTFromRedis() error {
  182. mapdata, err := redisEdgeData.HGetAll(LampOotPrefix + o.devinfo.DevCode).Result()
  183. if err != nil {
  184. if err == redis.Nil {
  185. return nil
  186. }
  187. logrus.Errorf("Concentrator.ReloadOOTFromRedis设备[%s]从redis加载时间策略失败:%s", o.devinfo.DevCode, err.Error())
  188. return err
  189. }
  190. for k, v := range mapdata {
  191. var oot []zigbee.OnOffTime
  192. lampid, errkey := strconv.Atoi(k)
  193. errval := json.UnmarshalFromString(v, &oot)
  194. if errkey == nil && errval == nil {
  195. o.mapLamps2OOT[uint32(lampid)] = oot
  196. }
  197. }
  198. return nil
  199. }
  200. func (o *Concentrator) ReloadSwitchOOTFromRedis() error {
  201. mapdata, err := redisEdgeData.HGetAll(LampSwitchPrefix + o.devinfo.DevCode).Result()
  202. if err != nil {
  203. if err == redis.Nil {
  204. return nil
  205. }
  206. logrus.Errorf("Concentrator.ReloadSwitchOOTFromRedis设备[%s]从redis加载时间策略失败:%s", o.devinfo.DevCode, err.Error())
  207. return err
  208. }
  209. for k, v := range mapdata {
  210. var ltr LampTimeRange
  211. lampid, errkey := strconv.Atoi(k)
  212. errval := json.UnmarshalFromString(v, &ltr)
  213. if errkey == nil && errval == nil {
  214. o.mapTempLampsOOT[uint32(lampid)] = &ltr
  215. }
  216. }
  217. return nil
  218. }
  219. func (o *Concentrator) ReloadBroadCastFromRedis() error {
  220. strTime, err := redisEdgeData.Get(LampBroadcastPrefix + o.devinfo.DevCode).Result()
  221. if err != nil {
  222. if err == redis.Nil {
  223. return nil
  224. }
  225. logrus.Errorf("Concentrator.ReloadBroadCastFromRedis设备[%s]从redis加载广播恢复截止时间失败:%s", o.devinfo.DevCode, err.Error())
  226. return err
  227. }
  228. if t, err := util.MlParseTime(strTime); err == nil {
  229. o.broadcastAutoTime = t
  230. }
  231. return nil
  232. }
  233. func (o *Concentrator) ReloadLampAlarmFromRedis() error {
  234. mapAlarm, err := redisEdgeData.HGetAll(LampAlarmPrefix + o.devinfo.DevCode).Result()
  235. if err != nil {
  236. if err == redis.Nil {
  237. return nil
  238. }
  239. logrus.Errorf("Concentrator.ReloadLampAlarmFromRedis设备[%s]从redis加载广播恢复截止时间失败:%s", o.devinfo.DevCode, err.Error())
  240. return err
  241. }
  242. for k, v := range mapAlarm {
  243. var lai LampAlarmInfo
  244. if err := json.UnmarshalFromString(v, &lai); err == nil {
  245. o.mapLampAlarm[k] = &lai
  246. } else {
  247. logrus.Errorf("从redis获取的告警信息还原失败,原内容:%s,失败原因:%s", v, err.Error())
  248. }
  249. }
  250. return nil
  251. }
  252. func (o *Concentrator) Handle() {
  253. defer func() {
  254. if err := recover(); err != nil {
  255. logrus.Errorf("Concentrator.Handle发生异常:%v", err)
  256. logrus.Errorf("Concentrator.Handle发生异常,堆栈信息:%s", string(debug.Stack()))
  257. go o.Handle()
  258. }
  259. }()
  260. o.queryPoleids()
  261. o.BroadcastTime()
  262. exit := false
  263. mapData := make(map[string]*protocol.CHZB_LampData)
  264. LastTime := util.MlNow()
  265. nextFillTime := time.Time{}
  266. for {
  267. select {
  268. case <-o.ctx.Done():
  269. logrus.Errorf("设备[%s]的HandlePole退出,原因:%v", o.devinfo.DevCode, o.ctx.Err())
  270. exit = true
  271. case devinfo_ := <-o.chanDevInfo:
  272. o.devinfo = devinfo_
  273. case mi := <-o.chanModelInfo:
  274. o.UpdateModel2(mi)
  275. default:
  276. //从队列钟获取指令执行
  277. if m, ok, _ := o.downQueue.Get(); ok {
  278. if mm, ok := m.(mqtt.Message); ok {
  279. if fn, ok := o.mapTopicHandle[mm.Topic()]; ok {
  280. fn(mm)
  281. } else {
  282. logrus.Errorf("Concentrator.Handle:不支持的主题:%s", mm.Topic())
  283. }
  284. }
  285. } else {
  286. if exit { //退出前全部恢复时控模式
  287. o.CheckRecoveryAuto(true)
  288. return
  289. }
  290. //每小时同步一次时间
  291. if time.Now().Sub(LastTime).Minutes() > 60 {
  292. o.queryPoleids() //每小时从服务端同步一次单灯编号
  293. o.BroadcastTime() //每小时广播一次时间同步消息
  294. LastTime = time.Now()
  295. }
  296. o.CheckRecoveryAuto(false)
  297. quantity, send := o.NextQueueRead(mapData)
  298. if quantity == 0 || send {
  299. if nextFillTime.IsZero() || nextFillTime.Before(util.MlNow()) {
  300. o.fillReadQueue()
  301. nextFillTime = util.MlNow().Add(time.Duration(o.devinfo.SendCloud) * time.Millisecond)
  302. }
  303. if send {
  304. mapData = make(map[string]*protocol.CHZB_LampData)
  305. o.UploadLampAlarm()
  306. }
  307. time.Sleep(300 * time.Millisecond)
  308. }
  309. }
  310. }
  311. }
  312. }
  313. // CheckRecoveryAuto force=true 强制全部恢复时控模式
  314. func (o *Concentrator) CheckRecoveryAuto(force bool) {
  315. //存在广播控时,如果广播控过期,则全部恢复时控模式,未过期,则不处理
  316. if (!o.broadcastAutoTime.IsZero() && o.broadcastAutoTime.Before(util.MlNow())) || force {
  317. for k := range o.mapTempLampsOOT {
  318. delete(o.mapTempLampsOOT, k)
  319. }
  320. if err := o.BroadcastAuto(); err != nil {
  321. logrus.Errorf("广播恢复时控失败:%s", err.Error())
  322. } else {
  323. o.broadcastAutoTime = time.Time{}
  324. //删除redis中所有临时开关灯记录
  325. if err := redisEdgeData.Del(LampSwitchPrefix + o.devinfo.DevCode).Err(); err != nil {
  326. logrus.Errorf("手动广播恢复时控,更新redis失败:%s", err.Error())
  327. }
  328. logrus.Info("广播恢复时控成功")
  329. }
  330. } else {
  331. //如果广播控模式未过期,则判断单灯是否手动控过期,过期则恢复
  332. var strList []string
  333. for k, v := range o.mapTempLampsOOT {
  334. if time.Time(v.End).Before(util.MlNow()) {
  335. if err := o.SetPoleAuto(k); err != nil {
  336. logrus.Errorf("单灯[%d]恢复时控失败:%s", k, err.Error())
  337. } else {
  338. logrus.Infof("单灯[%d]恢复时控成功", k)
  339. strList = append(strList, strconv.Itoa(int(k)))
  340. delete(o.mapTempLampsOOT, k)
  341. }
  342. }
  343. }
  344. if len(strList) > 0 {
  345. if err := redisEdgeData.HDel(LampSwitchPrefix+o.devinfo.DevCode, strList...).Err(); err != nil {
  346. logrus.Errorf("手动恢复灯控[%v]时控模式,更新redis失败:%s", strList, err.Error())
  347. }
  348. }
  349. }
  350. }
  351. func (o *Concentrator) queryPoleids() {
  352. var obj protocol.Pack_CHZB_EmptyObject
  353. if str, err := obj.EnCode(o.devinfo.DevCode, appConfig.GID, GetNextUint64()); err == nil {
  354. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_LAMP), str, mqtt.AtMostOnce, ToCloud)
  355. }
  356. }
  357. func ConvertExcept(except uint16) string {
  358. //-1初始值 0正常,1异常亮灯,2异常熄灯,3亮度异常
  359. switch except {
  360. case protocol.LE_OK: //正常(正常开灯或熄灯状态)
  361. return "正常"
  362. case protocol.LE_ON: //亮灯异常(本该关灯状态)
  363. return "熄灯时段亮灯"
  364. case protocol.LE_OFF: //亮灯,但亮度异常(本该开灯状态,但开灯亮度不对)
  365. return "亮灯时段熄灯"
  366. case protocol.LE_ON_BRIGHTNESS:
  367. return "亮灯但亮度异常"
  368. default:
  369. return "状态未知"
  370. }
  371. }
  372. type LampNumberDID struct {
  373. LampID uint32
  374. DID string
  375. }
  376. func (o *Concentrator) fillReadQueue() {
  377. for k, v := range o.mapLamps {
  378. o.readQueue.Put(LampNumberDID{LampID: k, DID: v})
  379. }
  380. }
  381. func (o *Concentrator) NextQueueRead(mapData map[string]*protocol.CHZB_LampData) (uint32, bool) {
  382. val, ok, quantity := o.readQueue.Get()
  383. if ok {
  384. lnd := val.(LampNumberDID)
  385. var err_ error
  386. var data protocol.CHZB_LampData
  387. data.Data = make(map[uint16]float64)
  388. if b1, b2, err := o.GetBrightness(lnd.LampID); err == nil {
  389. data.Data[1] = float64(b1)
  390. data.Data[2] = float64(b2)
  391. //判断灯亮是否正常
  392. o.CheckLampAlarm(lnd, b1, b2)
  393. } else {
  394. err_ = err
  395. }
  396. if e, err := o.ReadElectricalPara(lnd.LampID); err == nil {
  397. data.Data[3] = e.Voltage[0]
  398. data.Data[4] = e.Voltage[1]
  399. data.Data[5] = e.Voltage[2]
  400. data.Data[6] = e.Current[0]
  401. data.Data[7] = e.Current[1]
  402. data.Data[8] = float64(e.Degree[0])
  403. data.Data[9] = float64(e.Degree[1])
  404. } else {
  405. err_ = err
  406. }
  407. data.SetStateErrorData(err_)
  408. mapData[lnd.DID] = &data
  409. }
  410. if quantity == 0 && len(mapData) > 0 {
  411. var obj protocol.Pack_CHZB_UploadData
  412. if str, err := obj.EnCode(o.devinfo.DevCode, appConfig.GID, GetNextUint64(), o.devinfo.TID, mapData); err == nil {
  413. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_DATA), str, mqtt.AtMostOnce, ToCloud)
  414. }
  415. return quantity, true
  416. }
  417. return quantity, false
  418. }
  419. // UploadLampAlarm 告警开始上报和告警结束上报
  420. func (o *Concentrator) UploadLampAlarm() {
  421. var toDelete []string
  422. for k, v := range o.mapLampAlarm {
  423. if !v.Send && v.Alarm.EndTime == "" { //告警开始上报
  424. var obj protocol.Pack_CHZB_LampAlarm
  425. if str, err := obj.EnCode(o.devinfo.DevCode, appConfig.GID, GetNextUint64(), v.Alarm); err == nil {
  426. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_ALARM), str, mqtt.AtMostOnce, ToCloud)
  427. }
  428. v.Send = true
  429. //缓存到redis
  430. strAlarm, _ := json.MarshalToString(v)
  431. mapRedis := make(map[string]interface{})
  432. mapRedis[k] = strAlarm
  433. if err := redisEdgeData.HSet(LampAlarmPrefix+o.devinfo.DevCode, mapRedis).Err(); err != nil {
  434. logrus.Errorf("告警信息缓存入redis失败:%s", err.Error())
  435. }
  436. } else if v.Alarm.EndTime != "" { //告警结束上报
  437. var obj protocol.Pack_CHZB_LampAlarm
  438. if str, err := obj.EnCode(o.devinfo.DevCode, appConfig.GID, GetNextUint64(), v.Alarm); err == nil {
  439. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_ALARM), str, mqtt.AtMostOnce, ToCloud)
  440. }
  441. toDelete = append(toDelete, k)
  442. delete(o.mapLampAlarm, k)
  443. }
  444. }
  445. if len(toDelete) > 0 {
  446. if err := redisEdgeData.HDel(LampAlarmPrefix+o.devinfo.DevCode, toDelete...).Err(); err != nil {
  447. logrus.Errorf("告警信息从redis删除失败:%s", err.Error())
  448. }
  449. }
  450. }
  451. // CheckLampAlarm 检查开灯、关灯、亮度异常
  452. func (o *Concentrator) CheckLampAlarm(lnd LampNumberDID, b1, b2 uint8) {
  453. //真实数据时间
  454. now := util.MlNow().Add(-time.Duration(o.devinfo.WaitTime) * time.Millisecond)
  455. except := uint16(protocol.LE_UNKNOWN)
  456. //策略时间段检查
  457. if oots, ok := o.mapLamps2OOT[lnd.LampID]; ok {
  458. for _, oot := range oots { //亮灯时间段
  459. if oot.InTimeRange(util.MlNow()) {
  460. if b1 > 0 { //亮灯
  461. if oot.Brightness == b1 {
  462. except = protocol.LE_OK //亮灯正常
  463. } else {
  464. except = protocol.LE_ON_BRIGHTNESS //亮灯异常(亮度异常)
  465. }
  466. } else { //异常熄灯
  467. except = protocol.LE_OFF
  468. }
  469. break
  470. }
  471. }
  472. }
  473. //手动控检查
  474. if switchoot, ok := o.mapTempLampsOOT[lnd.LampID]; ok {
  475. if switchoot.isInTimeRange(now) {
  476. if switchoot.Brightness == b1 {
  477. except = protocol.LE_OK //正常亮灯/熄灯
  478. } else {
  479. if b1 > 0 {
  480. if switchoot.Brightness == 0 {
  481. except = protocol.LE_ON //异常亮灯
  482. } else {
  483. except = protocol.LE_ON_BRIGHTNESS //亮度异常
  484. }
  485. } else {
  486. except = protocol.LE_OFF //异常熄灯
  487. }
  488. }
  489. }
  490. }
  491. if except == protocol.LE_UNKNOWN {
  492. if b1 > 0 {
  493. except = protocol.LE_ON //异常亮灯
  494. } else {
  495. except = protocol.LE_OK
  496. }
  497. }
  498. if a, ok := o.mapLampAlarm[lnd.DID]; ok {
  499. if except == protocol.LE_OK { //告警结束
  500. a.Alarm.EndTime = now.Format("2006-01-02 15:04:05")
  501. a.Alarm.Brightness = b1
  502. logrus.Debugf("灯控[%s]状态[%s]", lnd.DID, ConvertExcept(except))
  503. }
  504. } else {
  505. if except != protocol.LE_OK { //告警开始
  506. a := protocol.LampAlarm{DID: lnd.DID, AlarmType: except, AlarmBrightness: b1, StartTime: now.Format("2006-01-02 15:04:05")}
  507. lai := LampAlarmInfo{Alarm: &a, Send: false}
  508. o.mapLampAlarm[lnd.DID] = &lai
  509. logrus.Debugf("灯控[%s]状态[%s]", lnd.DID, ConvertExcept(except))
  510. }
  511. }
  512. }
  513. func (o *Concentrator) nextSeq() uint8 {
  514. o.mutexSeq.Lock()
  515. defer o.mutexSeq.Unlock()
  516. o.seq++
  517. return o.seq
  518. }
  519. func (o *Concentrator) SendRecvData(aduRequest []byte, retry int) (aduResponse []byte, err error) {
  520. serial := GetSerialMgr().GetSerialPort(o.devinfo.Code)
  521. if serial == nil {
  522. return nil, ErrClosedConnection
  523. }
  524. if retry <= 0 {
  525. retry = 1
  526. }
  527. for ; retry > 0; retry-- {
  528. aduResponse, err = serial.SendRecvData(aduRequest, FlagChZigbee, o.devinfo.WaitTime)
  529. if err == nil {
  530. break
  531. }
  532. }
  533. return aduResponse, err
  534. }
  535. func (o *Concentrator) SendData(aduRequest []byte, retry int) (err error) {
  536. serial := GetSerialMgr().GetSerialPort(o.devinfo.Code)
  537. if serial == nil {
  538. return ErrClosedConnection
  539. }
  540. if retry <= 0 {
  541. retry = 1
  542. }
  543. for ; retry > 0; retry-- {
  544. if err = serial.SendData(aduRequest, FlagChZigbee, o.devinfo.WaitTime); err == nil {
  545. break
  546. }
  547. }
  548. return err
  549. }
  550. // BroadcastTime 广播校时
  551. func (o *Concentrator) BroadcastTime() error {
  552. t := protocol.BJNow()
  553. var pack zigbee.PackUpgradeFuncCommand
  554. pack.SetData(0x0000FEFE, zigbee.CmdSetBroadcastCorrectiontime, o.nextSeq(),
  555. []byte{0xFE, 0xFE, uint8(t.Hour()), uint8(t.Minute()), uint8(t.Second())})
  556. buff, err := pack.EnCode()
  557. defer PoolPut(buff)
  558. if buff != nil {
  559. err = o.SendData(buff.B, 2)
  560. }
  561. return err
  562. }
  563. // BroadcastOnOrOff 广播开关灯
  564. func (o *Concentrator) BroadcastOnOrOff(on, brightness uint8) error {
  565. var cmd = zigbee.CmdSetBroadcastOn
  566. if on == 0 {
  567. cmd = zigbee.CmdSetBroadcastOff
  568. }
  569. var pack zigbee.PackUpgradeFuncCommand
  570. //pack.SetData(0x0000FEFE, cmd, o.nextSeq(), []byte{0xFE, 0xFE, 0xFF})
  571. pack.SetData(0x0000FEFE, cmd, o.nextSeq(), []byte{0xFE, 0xFE, 0xFF, brightness, brightness}) //灯1和2
  572. buff, err := pack.EnCode()
  573. defer PoolPut(buff)
  574. if buff != nil {
  575. err = o.SendData(buff.B, 2)
  576. }
  577. return err
  578. }
  579. // BroadcastAuto 广播恢复时控模式
  580. func (o *Concentrator) BroadcastAuto() error {
  581. var pufc zigbee.PackUpgradeFuncCommand
  582. //pufc.SetData(0x0000fefe, zigbee.CMD_SET_BROADCAST_AUTO, o.nextSeq(), []byte{0xFE, 0xFE, 0xFF})
  583. pufc.SetData(0x0000fefe, zigbee.CmdSetBroadcastAuto, o.nextSeq(), []byte{0xFE, 0xFE, 0x03}) //灯1和2
  584. buff, err := pufc.EnCode()
  585. defer PoolPut(buff)
  586. if buff != nil {
  587. err = o.SendData(buff.B, 3)
  588. }
  589. return err
  590. }
  591. // SetOnOffTime 设置灯1开关灯时间段
  592. func (o *Concentrator) SetOnOffTime(PoleID uint32, Cmd uint8, data []zigbee.OnOffTime) error {
  593. buff0 := bytebufferpool.Get()
  594. defer PoolPut(buff0)
  595. buff0.Write(GetPoleIDByte(PoleID))
  596. len := len(data)
  597. for i := 0; i < 4; i++ {
  598. if i < len {
  599. buff0.Write(data[i].EnCode())
  600. } else {
  601. buff0.Write((&zigbee.OnOffTime{}).EnCode())
  602. }
  603. }
  604. var pgfc zigbee.PackGeneralFuncCommand
  605. pgfc.SetData(PoleID, Cmd, o.nextSeq(), buff0.B)
  606. buff, err := pgfc.EnCode()
  607. defer PoolPut(buff)
  608. if buff != nil {
  609. _, err = o.SendRecvData(buff.B, 3)
  610. }
  611. return err
  612. }
  613. // GetOnOffTime 读取灯1开关灯时间段
  614. func (o *Concentrator) GetOnOffTime(PoleID uint32, Cmd uint8) ([]zigbee.OnOffTime, error) {
  615. var pgfc zigbee.PackGeneralFuncCommand
  616. pgfc.SetData(PoleID, Cmd, o.nextSeq(), GetPoleIDByte(PoleID))
  617. buff, err := pgfc.EnCode()
  618. if err != nil {
  619. return nil, err
  620. }
  621. defer PoolPut(buff)
  622. var recvdata []byte
  623. recvdata, err = o.SendRecvData(buff.B, 1)
  624. if err != nil {
  625. return nil, err
  626. }
  627. var pgfcresp zigbee.PackGeneralFuncCommand
  628. err = pgfcresp.DeCode(recvdata)
  629. if err != nil {
  630. return nil, err
  631. }
  632. if len(pgfcresp.Data) >= 22 {
  633. oot := make([]zigbee.OnOffTime, 4)
  634. oot[0].DeCode(pgfcresp.Data[2:7])
  635. oot[1].DeCode(pgfcresp.Data[7:12])
  636. oot[2].DeCode(pgfcresp.Data[12:17])
  637. oot[3].DeCode(pgfcresp.Data[17:22])
  638. //时分都是0
  639. ret := make([]zigbee.OnOffTime, 0, 4)
  640. for _, v := range oot {
  641. if v.OnHour == v.OffHour && v.OnMinite == v.OffMinite &&
  642. v.OnHour == 0 && v.OnMinite == 0 {
  643. continue
  644. }
  645. ret = append(ret, v)
  646. }
  647. return ret, nil
  648. } else {
  649. logrus.Errorf("读取开关灯时间返回的内容错误:%s", hex.EncodeToString(recvdata))
  650. }
  651. return nil, errors.New("读取开关灯时间返回的内容错误")
  652. }
  653. // ReadPoleTime 读取单灯时间
  654. func (o *Concentrator) ReadPoleTime(PoleID uint32) (uint8, uint8, uint8, error) {
  655. //从4位带分组编号的灯杆编号中取2位灯杆编号
  656. var pgfc zigbee.PackGeneralFuncCommand
  657. pgfc.SetData(PoleID, zigbee.CmdReadTime, o.nextSeq(), GetPoleIDByte(PoleID))
  658. buff, err := pgfc.EnCode()
  659. if err != nil {
  660. return 0, 0, 0, err
  661. }
  662. defer PoolPut(buff)
  663. var recvdata []byte
  664. recvdata, err = o.SendRecvData(buff.B, 1)
  665. if err != nil {
  666. return 0, 0, 0, err
  667. }
  668. var pgfcresp zigbee.PackGeneralFuncCommand
  669. err = pgfcresp.DeCode(recvdata)
  670. if err != nil {
  671. return 0, 0, 0, err
  672. }
  673. if len(pgfcresp.Data) >= 5 {
  674. return pgfcresp.Data[2], pgfcresp.Data[3], pgfcresp.Data[4], nil
  675. } else {
  676. logrus.Errorf("读取单灯时间返回的内容错误:%s", hex.EncodeToString(recvdata))
  677. }
  678. return 0, 0, 0, errors.New("读取单灯时间返回的内容错误")
  679. }
  680. // ElecPara 读单灯电流电压
  681. type ElecPara struct {
  682. Voltage [3]float64
  683. Current [2]float64
  684. Degree [2]uint16
  685. }
  686. func (o *Concentrator) ReadElectricalPara(PoleID uint32) (*ElecPara, error) {
  687. var pgrc zigbee.PackGeneralFuncCommand
  688. pgrc.SetData(PoleID, zigbee.CmdReadDldy, o.nextSeq(), GetPoleIDByte(PoleID))
  689. buff, err := pgrc.EnCode()
  690. if err != nil {
  691. return nil, err
  692. }
  693. defer PoolPut(buff)
  694. var recvdata []byte
  695. recvdata, err = o.SendRecvData(buff.B, 1)
  696. if err != nil {
  697. return nil, err
  698. }
  699. var pgfcresp zigbee.PackGeneralFuncCommand
  700. err = pgfcresp.DeCode(recvdata)
  701. if err != nil {
  702. return nil, err
  703. }
  704. if pgfcresp.Cmd == zigbee.CmdReadDldy && len(pgfcresp.Data) >= 13 {
  705. var ep ElecPara
  706. ep.Voltage[0] = float64(pgfcresp.Data[2] * 2)
  707. ep.Voltage[1] = float64(pgfcresp.Data[3] * 2)
  708. ep.Voltage[2] = float64(pgfcresp.Data[4] * 2)
  709. ep.Current[0] = float64(pgfcresp.Data[5])*0.1 + float64(pgfcresp.Data[7])*0.001
  710. ep.Current[1] = float64(pgfcresp.Data[6])*0.1 + float64(pgfcresp.Data[8])*0.001
  711. ep.Degree[0] = binary.BigEndian.Uint16(pgfcresp.Data[9:11])
  712. ep.Degree[1] = binary.BigEndian.Uint16(pgfcresp.Data[11:13])
  713. return &ep, nil
  714. } else {
  715. logrus.Errorf("读取电流电压电度返回的内容错误:%s", hex.EncodeToString(recvdata))
  716. }
  717. return nil, errors.New("读取电流电压电度返回错误")
  718. }
  719. // SetBrightness 设单灯1,2亮度值
  720. func (o *Concentrator) SetBrightness(PoleID uint32, brightness1 uint8, brightness2 uint8) error {
  721. data := make([]byte, 0, 7)
  722. data = append(data, GetPoleIDByte(PoleID)...)
  723. data = append(data, brightness1, brightness2, 0xFF, 0xFF) //灯1,灯2亮度,后边灯3灯4保留
  724. var pgfc zigbee.PackGeneralFuncCommand
  725. pgfc.SetData(PoleID, zigbee.CmdSetBrightness, o.nextSeq(), data)
  726. buff, err := pgfc.EnCode()
  727. defer PoolPut(buff)
  728. if buff != nil {
  729. _, err = o.SendRecvData(buff.B, 1)
  730. }
  731. return err
  732. }
  733. // GetBrightness 查询单灯1,2亮度值
  734. func (o *Concentrator) GetBrightness(PoleID uint32) (uint8, uint8, error) {
  735. var pgfc zigbee.PackGeneralFuncCommand
  736. pgfc.SetData(PoleID, zigbee.CmdReadBrightness, o.nextSeq(), GetPoleIDByte(PoleID))
  737. buff, err := pgfc.EnCode()
  738. if err != nil {
  739. return 0, 0, err
  740. }
  741. defer PoolPut(buff)
  742. var recvdata []byte
  743. recvdata, err = o.SendRecvData(buff.B, 1)
  744. if err != nil {
  745. return 0, 0, err
  746. }
  747. var pgfcresp zigbee.PackGeneralFuncCommand
  748. err = pgfcresp.DeCode(recvdata)
  749. if err != nil {
  750. return 0, 0, err
  751. }
  752. if pgfcresp.Cmd == zigbee.CmdReadBrightness && len(pgfcresp.Data) >= 4 {
  753. return pgfcresp.Data[2], pgfcresp.Data[3], nil
  754. } else {
  755. logrus.Errorf("查询亮度返回的内容错误:%s", hex.EncodeToString(recvdata))
  756. }
  757. return 0, 0, errors.New("查询亮度返回错误")
  758. }
  759. // SetTime 单灯校时
  760. func (o *Concentrator) SetTime(PoleID uint32) error {
  761. t := protocol.BJNow()
  762. data := make([]byte, 0, 5)
  763. data = append(data, GetPoleIDByte(PoleID)...)
  764. data = append(data, uint8(t.Hour()), uint8(t.Minute()), uint8(t.Second()))
  765. var pack zigbee.PackGeneralFuncCommand
  766. pack.SetData(PoleID, zigbee.CmdSetCorrectiontime, o.nextSeq(), data)
  767. buff, err := pack.EnCode()
  768. defer PoolPut(buff)
  769. if buff != nil {
  770. _, err = o.SendRecvData(buff.B, 3)
  771. }
  772. return err
  773. }
  774. // SetPoleAuto 单灯恢复时控
  775. func (o *Concentrator) SetPoleAuto(PoleID uint32) error {
  776. var pack zigbee.PackGeneralFuncCommand
  777. pack.SetData(PoleID, zigbee.CmdSetAuto, o.nextSeq(), GetPoleIDByte(PoleID))
  778. buff, err := pack.EnCode()
  779. defer PoolPut(buff)
  780. if buff != nil {
  781. _, err = o.SendRecvData(buff.B, 3)
  782. }
  783. return err
  784. }
  785. func (o *Concentrator) HandleCache(m mqtt.Message) {
  786. o.downQueue.Put(m)
  787. }
  788. func (o *Concentrator) HandleTpChzbSetBroadcasttime(m mqtt.Message) {
  789. var obj protocol.Pack_CHZB_EmptyObject
  790. var ret protocol.Pack_Ack
  791. var err error
  792. if err = obj.DeCode(m.PayloadString()); err != nil {
  793. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  794. return
  795. }
  796. err = o.BroadcastTime()
  797. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, err); err == nil {
  798. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_BROADCASTTIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  799. }
  800. }
  801. func (o *Concentrator) HandleTpChzbSetWaittime(m mqtt.Message) {
  802. var obj protocol.Pack_CHZB_Waittime
  803. var ret protocol.Pack_Ack
  804. var err error
  805. if err = obj.DeCode(m.PayloadString()); err != nil {
  806. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  807. return
  808. }
  809. if obj.Data.Waittime < 1000 || obj.Data.Waittime > 15000 {
  810. err = errors.New("设置的等待时间不在[1000,15000]范围")
  811. } else {
  812. o.devinfo.WaitTime = obj.Data.Waittime
  813. }
  814. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, err); err == nil {
  815. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_WAITTIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  816. }
  817. }
  818. func (o *Concentrator) HandleTpChzbSetSwitch(m mqtt.Message) {
  819. var obj protocol.Pack_CHZB_Switch
  820. var ret protocol.Pack_CHZB_SeqLampAck
  821. var err error
  822. mapIpole := make(map[uint32]*protocol.StateError)
  823. if err = obj.DeCode(m.PayloadString()); err != nil {
  824. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  825. return
  826. }
  827. if obj.Id != o.devinfo.DevCode {
  828. return
  829. }
  830. Brightness := obj.Data.Brightness
  831. if obj.Data.Switch == 0 && Brightness > 0 {
  832. Brightness = 0
  833. }
  834. mapRedisTempLampsOOT := make(map[string]interface{}) //临时开关灯记录,用于排除异常亮灯正常亮灯的情况
  835. ltr := LampTimeRange{
  836. Start: util.MLTime(util.MlNow()),
  837. End: util.MLTime(util.MlNow().Add(time.Duration(obj.Data.Recovery) * time.Second)), //延迟2分钟,以防指令在队列中未及时执行
  838. Brightness: Brightness,
  839. }
  840. ltrstr, _ := json.MarshalToString(ltr)
  841. if len(obj.Data.LampIDs) == 0 { //广播
  842. err = o.BroadcastOnOrOff(obj.Data.Switch, Brightness)
  843. o.broadcastAutoTime = util.MlNow().Add(time.Duration(obj.Data.Recovery) * time.Second)
  844. for k := range o.mapLamps {
  845. mapRedisTempLampsOOT[strconv.Itoa(int(k))] = ltrstr //redis
  846. o.mapTempLampsOOT[k] = &ltr //内存
  847. }
  848. } else { //指定的灯
  849. for _, pid := range obj.Data.LampIDs {
  850. //过滤掉不正常的pid
  851. if pid == 0 || pid == 0x0000FEFE {
  852. continue
  853. }
  854. err = o.SetBrightness(pid, Brightness, Brightness)
  855. mapIpole[pid] = protocol.NewStateError(err)
  856. mapRedisTempLampsOOT[strconv.Itoa(int(pid))] = ltrstr //redis
  857. o.mapTempLampsOOT[pid] = &ltr //内存
  858. }
  859. }
  860. if err := redisEdgeData.HSet(LampSwitchPrefix+o.devinfo.DevCode, mapRedisTempLampsOOT).Err(); err != nil {
  861. logrus.Errorf("手动开关灯时间设置[内容:%v]缓存到redis失败:%s", mapRedisTempLampsOOT, err.Error())
  862. }
  863. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, mapIpole); err == nil {
  864. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_SWITCH_ACK), str, mqtt.AtMostOnce, ToAll)
  865. }
  866. }
  867. func (o *Concentrator) HandleTpChzbSetRecoveryAuto(m mqtt.Message) {
  868. var obj protocol.Pack_CHZB_Switch
  869. var ret protocol.Pack_CHZB_SeqLampAck
  870. var err error
  871. mapIpole := make(map[uint32]*protocol.StateError)
  872. if err = obj.DeCode(m.PayloadString()); err != nil {
  873. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  874. return
  875. }
  876. if obj.Id != o.devinfo.DevCode {
  877. return
  878. }
  879. if len(obj.Data.LampIDs) == 0 { //广播
  880. o.CheckRecoveryAuto(true)
  881. } else {
  882. strList := make([]string, 0, len(obj.Data.LampIDs))
  883. for _, v := range obj.Data.LampIDs {
  884. err := o.SetPoleAuto(v)
  885. if err == nil {
  886. delete(o.mapTempLampsOOT, v)
  887. strList = append(strList, strconv.Itoa(int(v)))
  888. } else {
  889. logrus.Errorf("手动单灯[%d]恢复时控失败:%s", v, err.Error())
  890. }
  891. mapIpole[v] = protocol.NewStateError(err)
  892. }
  893. if err := redisEdgeData.HDel(LampSwitchPrefix+o.devinfo.DevCode, strList...).Err(); err != nil {
  894. logrus.Errorf("手动恢复灯控[%v]时控模式,更新redis失败:%s", strList, err.Error())
  895. }
  896. }
  897. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, mapIpole); err == nil {
  898. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_RECOVERY_AUTO_ACK), str, mqtt.AtMostOnce, ToAll)
  899. }
  900. }
  901. func (o *Concentrator) HandleTpChzbSetOnofftime(m mqtt.Message) {
  902. var obj protocol.Pack_SetOnOffTime
  903. var ret protocol.Pack_CHZB_SeqLampAck
  904. var err error
  905. mapIpole := make(map[uint32]*protocol.StateError)
  906. if err = obj.DeCode(m.PayloadString()); err != nil {
  907. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  908. return
  909. }
  910. if obj.Id != o.devinfo.DevCode {
  911. return
  912. }
  913. if len(obj.Data.LampIDs) == 0 || len(obj.Data.OnOffTime) == 0 {
  914. logrus.Errorf("Handle_TP_CHZB_SET_ONOFFTIME:错误,灯控编号[%v],时间段个数:%v",
  915. obj.Data.LampIDs, obj.Data.OnOffTime)
  916. return
  917. }
  918. mapRedisOOT := make(map[string]interface{})
  919. var data []zigbee.OnOffTime
  920. for _, t := range obj.Data.OnOffTime {
  921. dat := zigbee.OnOffTime{
  922. OnHour: t.OnHour,
  923. OnMinite: t.OnMinite,
  924. OffHour: t.OffHour,
  925. OffMinite: t.OffMinite,
  926. Brightness: t.Brightness,
  927. }
  928. data = append(data, dat)
  929. }
  930. datastr, _ := json.MarshalToString(data)
  931. for _, v := range obj.Data.LampIDs {
  932. if v == 0 || v == 0x0000FEFE { //编号等于0或为广播地址则不处理
  933. continue
  934. }
  935. if err = o.SetOnOffTime(v, zigbee.CmdSetOnofftime, data); err != nil {
  936. logrus.Errorf("单灯[%d]设置开关灯时间失败:%s", v, err.Error())
  937. } else {
  938. logrus.Infof("单灯[%d]设置开关灯时间成功", v)
  939. }
  940. mapIpole[v] = protocol.NewStateError(err)
  941. mapRedisOOT[strconv.Itoa(int(v))] = datastr //缓存到redis
  942. o.mapLamps2OOT[v] = data //缓存在内存中
  943. }
  944. //持久缓存到redis,以便于重启后读取进内存中
  945. if err := redisEdgeData.HSet(LampOotPrefix+o.devinfo.DevCode, mapRedisOOT).Err(); err != nil {
  946. logrus.Errorf("灯控时间设置[内容:%v]缓存到redis失败:%s", mapRedisOOT, err.Error())
  947. }
  948. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, mapIpole); err == nil {
  949. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_ONOFFTIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  950. }
  951. }
  952. func (o *Concentrator) HandleTpChzbQueryOnofftime(m mqtt.Message) {
  953. var obj protocol.Pack_CHZB_QueryOnOffTime
  954. var oot []zigbee.OnOffTime
  955. var err error
  956. if err = obj.DeCode(m.PayloadString()); err != nil {
  957. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  958. return
  959. }
  960. if obj.Id != o.devinfo.DevCode {
  961. return
  962. }
  963. if obj.Data.Poleid > 0 {
  964. oot, err = o.GetOnOffTime(obj.Data.Poleid, zigbee.CmdReadOnofftime)
  965. }
  966. var ret protocol.Pack_CHZB_QueryOnOffTimeAck
  967. var poot []protocol.CHZB_OnOffTime
  968. for _, v := range oot {
  969. x := protocol.CHZB_OnOffTime{
  970. OnHour: v.OnHour,
  971. OnMinite: v.OnMinite,
  972. OffHour: v.OffHour,
  973. OffMinite: v.OffMinite,
  974. Brightness: v.Brightness,
  975. }
  976. poot = append(poot, x)
  977. }
  978. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, obj.Data.Poleid, err, poot); err == nil {
  979. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_ONOFFTIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  980. }
  981. }
  982. func (o *Concentrator) HandleTpChzbSetUpdateLamp(m mqtt.Message) {
  983. var obj protocol.Pack_CHZB_LampIDs
  984. var ret protocol.Pack_Ack
  985. var err error
  986. if err = obj.DeCode(m.PayloadString()); err != nil {
  987. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  988. return
  989. }
  990. if obj.Id != o.devinfo.DevCode {
  991. return
  992. }
  993. if len(obj.Data.MapLamps) > 0 {
  994. mapLampsTmp := make(map[uint32]string)
  995. for k, v := range obj.Data.MapLamps {
  996. //过滤掉不正常的数据
  997. if k > 0 && v != "" {
  998. mapLampsTmp[k] = v
  999. }
  1000. }
  1001. o.mapLamps = mapLampsTmp
  1002. }
  1003. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, err); err == nil {
  1004. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_SET_UPDATE_LAMP_ACK), str, mqtt.AtMostOnce, ToCloud)
  1005. }
  1006. }
  1007. func (o *Concentrator) HandleTpChzbQueryTime(m mqtt.Message) {
  1008. var obj protocol.Pack_CHZB_QueryTime
  1009. var ret protocol.Pack_CHZB_QueryTimeAck
  1010. if err := obj.DeCode(m.PayloadString()); err != nil {
  1011. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  1012. return
  1013. }
  1014. var pt *protocol.CHZB_LampTime = nil
  1015. hh, mm, ss, err := o.ReadPoleTime(obj.Data.LampID)
  1016. if err == nil {
  1017. pt = &protocol.CHZB_LampTime{Hour: hh, Minite: mm, Second: ss}
  1018. }
  1019. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, obj.Data.LampID, err, pt); err == nil {
  1020. GetMQTTMgr().Publish(GetTopic(protocol.DT_CONCENTRATOR, o.devinfo.DevCode, protocol.TP_CHZB_QUERY_TIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  1021. }
  1022. }