concentrator.go 36 KB

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