ym485.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. package main
  2. import (
  3. "context"
  4. "errors"
  5. "runtime/debug"
  6. "time"
  7. "github.com/go-redis/redis/v7"
  8. "github.com/sirupsen/logrus"
  9. "lc/common/mqtt"
  10. "lc/common/protocol"
  11. "lc/common/util"
  12. "lc/edge/ipole/ym485"
  13. "strings"
  14. "sync"
  15. )
  16. var YmProtocol = "yuming485"
  17. var mutex sync.Mutex
  18. var oldstate uint8
  19. type YmLampController struct {
  20. devinfo *protocol.DevInfo
  21. model *protocol.IotModel
  22. downQueue *util.MlQueue
  23. mapTopicHandle map[string]func(m mqtt.Message)
  24. mapLamps2OOT []protocol.CHZB_OnOffTime //时控策略
  25. mapTempLampsOOT *LampTimeRange //临时手动控时间段,手动控制开关灯
  26. mapLampAlarm *LampAlarmInfo //告警数据
  27. State []ym485.DeviceState //当前灯控状态 开关灯,电流,电压,电度
  28. ctx context.Context
  29. cancel context.CancelFunc
  30. chanDevInfo chan *protocol.DevInfo //设备管理更新
  31. chanModelInfo chan *ModelInfo //设备管理更新
  32. tswitch time.Time //手动控执行时间
  33. }
  34. func NewYmLampController(info *protocol.DevInfo) Device {
  35. ctx, cancel := context.WithCancel(context.Background())
  36. dev := &YmLampController{
  37. devinfo: info,
  38. downQueue: util.NewQueue(200),
  39. mapTopicHandle: make(map[string]func(m mqtt.Message)),
  40. ctx: ctx,
  41. cancel: cancel,
  42. chanDevInfo: make(chan *protocol.DevInfo),
  43. chanModelInfo: make(chan *ModelInfo),
  44. }
  45. iot, err := loadModel(info.TID)
  46. if err != nil {
  47. logrus.Errorf("NewYmLampController:加载模型[tid=%d]文件发生错误:%s", info.TID, err.Error())
  48. } else {
  49. if iot.Protocol == YmProtocol {
  50. dev.model = iot
  51. } else {
  52. logrus.Error("NewYmLampController:物模型错误,非YmProtocol协议")
  53. }
  54. }
  55. dev.SetTopicHandle()
  56. return dev
  57. }
  58. func (o *YmLampController) SetTopicHandle() {
  59. o.mapTopicHandle[GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_SWITCH)] = o.HandleTpYmSetSwitch
  60. o.mapTopicHandle[GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_ONOFFTIME)] = o.HandleTpYmSetOnofftime
  61. }
  62. func (o *YmLampController) MQTTSubscribe() {
  63. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_SWITCH), mqtt.ExactlyOnce, o.HandleCache, ToAll) //开关灯
  64. GetMQTTMgr().Subscribe(GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_ONOFFTIME), mqtt.ExactlyOnce, o.HandleCache, ToCloud) //设置时间
  65. }
  66. func (o *YmLampController) HandleCache(m mqtt.Message) {
  67. logrus.Infof("Topic:%v,message:%v\n", m.Topic(), m.PayloadString())
  68. o.downQueue.Put(m)
  69. }
  70. func (o *YmLampController) Start() {
  71. o.MQTTSubscribe()
  72. retry := 3
  73. sleep := time.Duration(2)
  74. for i := 0; i < retry; i++ {
  75. if err := o.ReloadOOTFromRedis(); err == nil {
  76. break
  77. }
  78. time.Sleep(sleep * time.Second)
  79. }
  80. for i := 0; i < retry; i++ {
  81. if err := o.ReloadSwitchOOTFromRedis(); err == nil {
  82. break
  83. }
  84. time.Sleep(sleep * time.Second)
  85. }
  86. for i := 0; i < retry; i++ {
  87. if err := o.ReloadLampAlarmFromRedis(); err == nil {
  88. break
  89. }
  90. time.Sleep(sleep * time.Second)
  91. }
  92. go o.HandleData()
  93. }
  94. func (o *YmLampController) Stop() {
  95. //停止采集和处理
  96. o.cancel()
  97. }
  98. func (o *YmLampController) UpdateInfo(devinfo protocol.DevInfo) {
  99. o.chanDevInfo <- &devinfo
  100. }
  101. func (o *YmLampController) GetDevInfo() *protocol.DevInfo {
  102. return o.devinfo
  103. }
  104. func (o *YmLampController) UpdateModel(tid uint16, flag int) {
  105. if tid > 0 {
  106. mi := ModelInfo{
  107. TID: tid,
  108. Flag: flag,
  109. }
  110. o.chanModelInfo <- &mi
  111. }
  112. }
  113. func (o *YmLampController) UpdateModel2(mi *ModelInfo) {
  114. if o.devinfo.TID != mi.TID {
  115. return
  116. }
  117. if mi.Flag == 0 {
  118. logrus.Errorf("设备[%s]的物模型[tid=%d]模型文件被删除,下次启动即将生效。", o.devinfo.DevCode, mi.TID)
  119. return
  120. }
  121. logrus.Debugf("YmLampController.UpdateModel2:更新设备[%s]的物模型[%d]", o.devinfo.DevCode, mi.TID)
  122. iot, err := loadModel(mi.TID)
  123. if err != nil {
  124. logrus.Errorf("YmLampController.UpdateModel2:加载模型[%d]文件错误:%s", mi.TID, err.Error())
  125. return
  126. }
  127. if iot.Protocol == YmProtocol { //合法的物模型
  128. o.model = iot
  129. logrus.Infof("YmLampController.UpdateModel2:更新设备[%s]的物模型[%d]成功", o.devinfo.DevCode, mi.TID)
  130. } else {
  131. logrus.Error("YmLampController.UpdateModel2:物模型错误,TID和文件名tid不一致或协议非ModbusRTU协议")
  132. }
  133. }
  134. func (o *YmLampController) GetDevType() string {
  135. if o.devinfo.DevType == 3 {
  136. return protocol.DT_LAMPCONTROLLER
  137. }
  138. return "unknown"
  139. }
  140. // HandleData 数据处理协程
  141. func (o *YmLampController) HandleData() {
  142. defer func() {
  143. if err := recover(); err != nil {
  144. logrus.Error("YmLampController.HandleData:panic:", err)
  145. logrus.Error("stack:", string(debug.Stack()))
  146. time.Sleep(5 * time.Second)
  147. go o.HandleData()
  148. }
  149. }()
  150. o.QueryLampControllerAddr() //线上挂了两个灯控,则不能
  151. logrus.Infof("lamp state:%d", oldstate)
  152. nextFillTime := time.Time{}
  153. for {
  154. select {
  155. case <-o.ctx.Done():
  156. logrus.Errorf("设备[%s]的HandleData退出,原因:%v", o.devinfo.DevCode, o.ctx.Err())
  157. return
  158. case devinfo_ := <-o.chanDevInfo:
  159. o.devinfo = devinfo_
  160. case mi := <-o.chanModelInfo:
  161. o.UpdateModel2(mi)
  162. default:
  163. //从队列钟获取指令执行
  164. if m, ok, _ := o.downQueue.Get(); ok {
  165. if mm, ok := m.(mqtt.Message); ok {
  166. if fn, ok := o.mapTopicHandle[mm.Topic()]; ok {
  167. fn(mm)
  168. } else {
  169. logrus.Errorf("YmLampController.Handle:不支持的主题:%s", mm.Topic())
  170. }
  171. }
  172. } else {
  173. if nextFillTime.IsZero() || nextFillTime.Before(util.MlNow()) { //定时读取和发送
  174. t := util.MlNow()
  175. o.QueryDeviceState() //获取灯的数据
  176. // QueryDeviceState失败时State为过期数据,跳过ConfirmState避免误操作
  177. if len(o.State) > 0 {
  178. o.ConfirmState(t) //获取设置灯的开/关
  179. }
  180. nextFillTime = util.MlNow().Add(time.Duration(o.devinfo.SendCloud) * time.Millisecond)
  181. }
  182. time.Sleep(time.Millisecond * 1000)
  183. }
  184. }
  185. }
  186. }
  187. func (o *YmLampController) SendRecvData(aduRequest []byte, retry int) (aduResponse []byte, err error) {
  188. defer mutex.Unlock()
  189. mutex.Lock()
  190. // time.Sleep(time.Millisecond * 10)
  191. serial := GetSerialMgr().GetSerialPort(o.devinfo.Code)
  192. if serial == nil {
  193. logrus.Errorf("YM串口未找到: Code=%d", o.devinfo.Code) // ← 加这行
  194. return nil, ErrClosedConnection
  195. }
  196. if !serial.IsConnected() {
  197. logrus.Errorf("YM串口未连接: Code=%d", o.devinfo.Code) // ← 加这行
  198. }
  199. if retry <= 0 {
  200. retry = 1
  201. }
  202. for ; retry > 0; retry-- {
  203. aduResponse, err = serial.SendRecvData(aduRequest, FlagYm485, o.devinfo.WaitTime)
  204. if err == nil {
  205. break
  206. }
  207. }
  208. return aduResponse, err
  209. }
  210. func (o *YmLampController) SendData(aduRequest []byte, retry int) (err error) {
  211. serial := GetSerialMgr().GetSerialPort(o.devinfo.Code)
  212. if serial == nil {
  213. return ErrClosedConnection
  214. }
  215. if retry <= 0 {
  216. retry = 1
  217. }
  218. for ; retry > 0; retry-- {
  219. if err = serial.SendData(aduRequest, FlagYm485, o.devinfo.WaitTime); err == nil {
  220. break
  221. }
  222. }
  223. return err
  224. }
  225. func (o *YmLampController) QueryLampControllerAddr() {
  226. var obj ym485.QueryAddr
  227. buf, err := obj.EnCode()
  228. defer ym485.ReleaseByteBuffer(buf)
  229. if err != nil {
  230. return
  231. }
  232. recvbuf, err := o.SendRecvData(buf.Bytes(), 2)
  233. if err != nil {
  234. return
  235. }
  236. var ret ym485.QueryAddrACK
  237. if err = ret.DeCode(recvbuf); err == nil {
  238. logrus.Infof("灯控地址:%s", ret.Addr)
  239. }
  240. if ret.Addr != o.devinfo.DevCode {
  241. logrus.Errorf("请将DevCode配置为灯控地址!")
  242. }
  243. }
  244. func (o *YmLampController) QuerySoftVer() {
  245. var obj ym485.PackingMark
  246. buf, err := obj.EnCode(o.devinfo.DevCode, 0x1E, [4]byte{0x00, 0x00, 0x60, 0x12})
  247. defer ym485.ReleaseByteBuffer(buf)
  248. if err != nil {
  249. return
  250. }
  251. recvbuf, err := o.SendRecvData(buf.Bytes(), 1)
  252. if err != nil {
  253. return
  254. }
  255. var ret ym485.QuerySoftVerAck
  256. if err = ret.DeCode(recvbuf); err == nil {
  257. logrus.Infof("灯控型号:%s,软件版本:%s", ret.Model, ret.Version)
  258. }
  259. }
  260. func (o *YmLampController) QueryBasicsettings() {
  261. var obj ym485.PackingMark
  262. buf, err := obj.EnCode(o.devinfo.DevCode, 0x1E, [4]byte{0x00, 0x00, 0x60, 0x02})
  263. defer ym485.ReleaseByteBuffer(buf)
  264. if err != nil {
  265. return
  266. }
  267. recvbuf, err := o.SendRecvData(buf.Bytes(), 1)
  268. if err != nil {
  269. return
  270. }
  271. var ret ym485.PackingBasic
  272. if err = ret.DeCode(recvbuf); err == nil {
  273. logrus.Infof("灯控使能状态:%d,是否上电开灯:%d", ret.Enabled, ret.OnOff)
  274. }
  275. }
  276. // QueryDeviceState 查询设备状态
  277. func (o *YmLampController) QueryDeviceState() {
  278. var obj ym485.DataPack //串口协议
  279. buf, err := obj.EnCode(o.devinfo.DevCode, 0x1E, []byte{0x00, 0x00, 0x60, 0x13, 0x01})
  280. defer ym485.ReleaseByteBuffer(buf)
  281. if err != nil {
  282. return
  283. }
  284. recvbuf, err := o.SendRecvData(buf.Bytes(), 1) //根据地址得到数据
  285. if err != nil {
  286. logrus.Errorf("单灯状态数据查询错误,DevCode=%s,err=%v", o.devinfo.DevCode, err)
  287. return
  288. }
  289. var ret ym485.QueryDeviceStateAck
  290. if err = ret.DeCode(recvbuf); err == nil { //解码串口返回的数据
  291. // if ret.Dp.Addr != o.devinfo.DevCode { //不是本灯数据
  292. if !strings.Contains(o.devinfo.DevCode, ret.Dp.Addr) { //不是本灯数据
  293. o.State = nil
  294. return
  295. }
  296. if len(ret.State) == 0 {
  297. o.State = nil
  298. return
  299. }
  300. if len(o.State) != len(ret.State) {
  301. o.State = make([]ym485.DeviceState, len(ret.State))
  302. }
  303. copy(o.State, ret.State)
  304. //状态改变记录日志
  305. if oldstate != o.State[0].State {
  306. oldstate = o.State[0].State
  307. logrus.Infof("lamp state:%d", oldstate)
  308. }
  309. }
  310. mapData := make(map[string]*protocol.CHZB_LampData)
  311. var data protocol.CHZB_LampData
  312. data.Data = make(map[uint16]float64)
  313. data.SetStateErrorData(err)
  314. if len(o.State) > 0 { //只要第一路
  315. if o.State[0].State == 1 { //开灯
  316. data.Data[1] = float64(o.State[0].BrightnessState)
  317. } else {
  318. data.Data[1] = 0.0
  319. }
  320. data.Data[2] = float64(0)
  321. data.Data[3] = o.State[0].Voltage
  322. data.Data[4] = 0.0
  323. data.Data[5] = 0.0
  324. data.Data[6] = o.State[0].Current
  325. data.Data[7] = 0.0
  326. data.Data[8] = o.State[0].Degree //by hxz 1,2,3,6,8为有效
  327. data.Data[9] = 0.0
  328. }
  329. mapData[o.devinfo.DevCode] = &data
  330. var ret1 protocol.Pack_CHZB_UploadData
  331. if str, err := ret1.EnCode(o.devinfo.DevCode, appConfig.GID, GetNextUint64(), o.devinfo.TID, mapData); err == nil {
  332. topic := GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_DATA)
  333. logrus.Infof("QueryDeviceState:发布灯控数据,topic=%s,payload=%s", topic, str)
  334. GetMQTTMgr().Publish(topic, str, mqtt.AtLeastOnce, ToCloud)
  335. }
  336. }
  337. func (o *YmLampController) TurnOnOff(flag uint8) error {
  338. kenabled := uint8(0x00)
  339. if flag > 0 {
  340. kenabled = 0xff
  341. }
  342. var obj ym485.PackingTurnOnOff
  343. buf, err := obj.EnCode(o.devinfo.DevCode, [4]byte{0x00, 0x00, 0x60, 0x07}, 0xff, kenabled)
  344. defer ym485.ReleaseByteBuffer(buf)
  345. if err != nil {
  346. return err
  347. }
  348. recvbuf, err := o.SendRecvData(buf.Bytes(), 3)
  349. if err != nil {
  350. logrus.Errorf("TurnOnOff:串口通信失败,DevCode=%s,flag=%d,err=%v", o.devinfo.DevCode, flag, err)
  351. return err
  352. }
  353. var ret ym485.PackingResult
  354. err = ret.DeCode(recvbuf)
  355. if err == nil {
  356. if ret.Result == 89 { //字母Y
  357. return nil
  358. }
  359. }
  360. logrus.Errorf("TurnOnOff:设备返回失败,DevCode=%s,flag=%d,Result=0x%02X", o.devinfo.DevCode, flag, ret.Result)
  361. return errors.New(protocol.FAILED_STR)
  362. }
  363. func (o *YmLampController) SetBrightness(brightness uint8) error {
  364. var obj ym485.PackingBrightnessColor
  365. buf, err := obj.EnCode(o.devinfo.DevCode, [4]byte{0x00, 0x00, 0x60, 0x09}, 0xff, []byte{brightness})
  366. defer ym485.ReleaseByteBuffer(buf)
  367. if err != nil {
  368. return err
  369. }
  370. recvbuf, err := o.SendRecvData(buf.Bytes(), 1)
  371. if err != nil {
  372. return err
  373. }
  374. var ret ym485.PackingResult
  375. err = ret.DeCode(recvbuf)
  376. if err == nil {
  377. if ret.Result == 89 { //字母'Y'
  378. return nil
  379. }
  380. }
  381. return errors.New(protocol.FAILED_STR)
  382. }
  383. func (o *YmLampController) SetBasicsettings(enabled, on uint8) {
  384. var obj ym485.PackingBasic
  385. buf, err := obj.EnCode(o.devinfo.DevCode, 0x1E, [4]byte{0x00, 0x00, 0x60, 0x01}, enabled, on, nil)
  386. defer ym485.ReleaseByteBuffer(buf)
  387. if err != nil {
  388. return
  389. }
  390. recvbuf, err := o.SendRecvData(buf.Bytes(), 1)
  391. if err != nil {
  392. return
  393. }
  394. var ret ym485.PackingResult
  395. if err = ret.DeCode(recvbuf); err == nil {
  396. if ret.Result == 89 { //字母'Y'
  397. logrus.Infoln("设置灯控基本信息执行成功")
  398. } else {
  399. logrus.Errorln("设置灯控基本信息执行失败")
  400. }
  401. }
  402. }
  403. func (o *YmLampController) Switch(Switch, Brightness uint8) error {
  404. if Switch == 0 {
  405. return o.TurnOnOff(0)
  406. } else {
  407. err := o.SetBrightness(Brightness)
  408. if err != nil {
  409. logrus.Errorf("调节亮度失败:%s", err.Error())
  410. }
  411. return o.TurnOnOff(Switch)
  412. }
  413. }
  414. func (o *YmLampController) ConfirmState(t time.Time) {
  415. //刚开/关灯,则不判断,避免采集数据误差导致误判
  416. if !o.tswitch.IsZero() {
  417. if t.After(o.tswitch) && t.Sub(o.tswitch).Seconds() < float64(o.devinfo.SendCloud/1000.0) {
  418. return
  419. }
  420. if t.Before(o.tswitch) && o.tswitch.Sub(t).Seconds() < float64(o.devinfo.SendCloud/1000.0) {
  421. return
  422. }
  423. }
  424. if len(o.State) == 0 {
  425. return
  426. }
  427. s := o.State[0]
  428. if o.mapTempLampsOOT != nil { //优先手动控制
  429. if t.After(time.Time(o.mapTempLampsOOT.End)) { //过时,则清除
  430. if err := redisEdgeData.Del(LampSwitchPrefix + o.devinfo.DevCode).Err(); err == nil {
  431. o.mapTempLampsOOT = nil
  432. o.tswitch = time.Time{}
  433. }
  434. } else if o.mapTempLampsOOT.isInTimeRange(t) {
  435. if o.mapTempLampsOOT.Brightness > 0 && s.State == 0 { //应开未开
  436. o.Switch(1, o.mapTempLampsOOT.Brightness) //开灯
  437. } else if o.mapTempLampsOOT.Brightness == 0 && s.State == 1 { //应关闭未关
  438. o.Switch(0, o.mapTempLampsOOT.Brightness) //关灯
  439. }
  440. return
  441. }
  442. }
  443. isInRange := false
  444. for _, v := range o.mapLamps2OOT { //其次时间策略
  445. if v.InTimeRange(t) { //在开灯区间
  446. if v.Brightness > 0 && s.State == 0 { //应开未开
  447. o.Switch(1, v.Brightness) //开灯
  448. } else if v.Brightness == 0 && s.State == 1 { //应关闭未关
  449. o.Switch(0, v.Brightness) //关灯
  450. }
  451. isInRange = true
  452. break
  453. }
  454. }
  455. if isInRange {
  456. return
  457. }
  458. if s.State == 1 {
  459. o.Switch(0, 0)
  460. }
  461. }
  462. func (o *YmLampController) HandleTpYmSetSwitch(m mqtt.Message) {
  463. var obj protocol.Pack_CHZB_Switch
  464. if err := obj.DeCode(m.PayloadString()); err != nil {
  465. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  466. return
  467. }
  468. if obj.Id != o.devinfo.DevCode {
  469. return
  470. }
  471. brightness := uint8(0)
  472. if obj.Data.Switch == 1 {
  473. brightness = obj.Data.Brightness
  474. }
  475. err := o.Switch(obj.Data.Switch, obj.Data.Brightness)
  476. if err != nil {
  477. logrus.Errorf("HandleTpYmSetSwitch:开关灯失败,DevCode=%s,Switch=%d,err=%v", o.devinfo.DevCode, obj.Data.Switch, err)
  478. } else {
  479. o.tswitch = util.MlNow()
  480. mapRedisTempLampsOOT := make(map[string]interface{}) //临时开关灯记录,用于排除异常亮灯正常亮灯的情况
  481. ltr := LampTimeRange{
  482. Start: util.MLTime(o.tswitch),
  483. End: util.MLTime(o.tswitch.Add(time.Duration(obj.Data.Recovery) * time.Second)), //延迟2分钟,以防指令在队列中未及时执行
  484. Brightness: brightness,
  485. }
  486. ltrstr, _ := json.MarshalToString(ltr)
  487. o.mapTempLampsOOT = &ltr //内存
  488. mapRedisTempLampsOOT[o.devinfo.DevCode] = ltrstr //redis
  489. if err := redisEdgeData.HSet(LampSwitchPrefix+o.devinfo.DevCode, mapRedisTempLampsOOT).Err(); err != nil {
  490. logrus.Errorf("手动开关灯时间设置[内容:%v]缓存到redis失败:%s", mapRedisTempLampsOOT, err.Error())
  491. }
  492. }
  493. var ret protocol.Pack_Ack
  494. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, err); err == nil {
  495. GetMQTTMgr().Publish(GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_SWITCH_ACK), str, mqtt.AtMostOnce, ToAll)
  496. }
  497. }
  498. func (o *YmLampController) HandleTpYmSetOnofftime(m mqtt.Message) {
  499. var obj protocol.Pack_SetOnOffTime
  500. if err := obj.DeCode(m.PayloadString()); err != nil {
  501. logrus.Errorf("协议解析错误:%s,协议主题:%s,协议内容:%s", err.Error(), m.Topic(), m.PayloadString())
  502. return
  503. }
  504. if obj.Id != o.devinfo.DevCode {
  505. return
  506. }
  507. if len(obj.Data.OnOffTime) == 0 {
  508. logrus.Errorf("Handle_TP_YM_SET_ONOFFTIME:错误,灯控编号[%v],时间段个数:%v", obj.Id, obj.Data.OnOffTime)
  509. return
  510. }
  511. mapRedisOOT := make(map[string]interface{})
  512. datastr, _ := json.MarshalToString(obj.Data.OnOffTime)
  513. mapRedisOOT[obj.Id] = datastr //缓存到redis
  514. o.mapLamps2OOT = obj.Data.OnOffTime //缓存在内存中
  515. //持久缓存到redis,以便于重启后读取进内存中
  516. err := redisEdgeData.HSet(LampOotPrefix+o.devinfo.DevCode, mapRedisOOT).Err()
  517. if err != nil {
  518. logrus.Errorf("灯控时间设置[内容:%v]缓存到redis失败:%s", mapRedisOOT, err.Error())
  519. }
  520. var ret protocol.Pack_Ack
  521. if str, err := ret.EnCode(o.devinfo.DevCode, appConfig.GID, obj.Seq, err); err == nil {
  522. GetMQTTMgr().Publish(GetTopic(protocol.DT_LAMPCONTROLLER, o.devinfo.DevCode, protocol.TP_YM_SET_ONOFFTIME_ACK), str, mqtt.AtMostOnce, ToCloud)
  523. }
  524. }
  525. func (o *YmLampController) ReloadOOTFromRedis() error {
  526. mapdata, err := redisEdgeData.HGetAll(LampOotPrefix + o.devinfo.DevCode).Result()
  527. if err != nil {
  528. if err == redis.Nil {
  529. return nil
  530. }
  531. logrus.Errorf("YmLampController.ReloadOOTFromRedis设备[%s]从redis加载时间策略失败:%s", o.devinfo.DevCode, err.Error())
  532. return err
  533. }
  534. for k, v := range mapdata {
  535. if k == o.devinfo.DevCode {
  536. var oot []protocol.CHZB_OnOffTime
  537. if err := json.UnmarshalFromString(v, &oot); err == nil {
  538. o.mapLamps2OOT = oot
  539. }
  540. break
  541. }
  542. }
  543. return nil
  544. }
  545. func (o *YmLampController) ReloadSwitchOOTFromRedis() error {
  546. mapdata, err := redisEdgeData.HGetAll(LampSwitchPrefix + o.devinfo.DevCode).Result()
  547. if err != nil {
  548. if err == redis.Nil {
  549. return nil
  550. }
  551. logrus.Errorf("YmLampController.ReloadSwitchOOTFromRedis设备[%s]从redis加载时间策略失败:%s", o.devinfo.DevCode, err.Error())
  552. return err
  553. }
  554. for k, v := range mapdata {
  555. if k == o.devinfo.DevCode {
  556. var ltr LampTimeRange
  557. if err := json.UnmarshalFromString(v, &ltr); err == nil {
  558. o.mapTempLampsOOT = &ltr
  559. }
  560. break
  561. }
  562. }
  563. return nil
  564. }
  565. func (o *YmLampController) ReloadLampAlarmFromRedis() error {
  566. mapAlarm, err := redisEdgeData.HGetAll(LampAlarmPrefix + o.devinfo.DevCode).Result()
  567. if err != nil {
  568. if err == redis.Nil {
  569. return nil
  570. }
  571. logrus.Errorf("YmLampController.ReloadLampAlarmFromRedis设备[%s]从redis加载广播恢复截止时间失败:%s", o.devinfo.DevCode, err.Error())
  572. return err
  573. }
  574. for k, v := range mapAlarm {
  575. if k == o.devinfo.DevCode {
  576. var lai LampAlarmInfo
  577. if err := json.UnmarshalFromString(v, &lai); err == nil {
  578. o.mapLampAlarm = &lai
  579. }
  580. break
  581. }
  582. }
  583. return nil
  584. }