github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/plugins/zigbee2mqtt/actor.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package zigbee2mqtt 20 21 import ( 22 "context" 23 "sync" 24 25 "github.com/pkg/errors" 26 27 "github.com/e154/smart-home/common/events" 28 m "github.com/e154/smart-home/models" 29 "github.com/e154/smart-home/system/mqtt" 30 "github.com/e154/smart-home/system/supervisor" 31 ) 32 33 // Actor ... 34 type Actor struct { 35 *supervisor.BaseActor 36 zigbee2mqttDevice *m.Zigbee2mqttDevice 37 mqttMessageQueue chan *Message 38 actionPool chan events.EventCallEntityAction 39 newMsgMu *sync.Mutex 40 stateMu *sync.Mutex 41 } 42 43 // NewActor ... 44 func NewActor(entity *m.Entity, 45 service supervisor.Service) (actor *Actor, err error) { 46 47 var zigbee2mqttDevice *m.Zigbee2mqttDevice 48 if zigbee2mqttDevice, err = service.Adaptors().Zigbee2mqttDevice.GetById(context.Background(), entity.Id.Name()); err != nil { 49 return 50 } 51 52 actor = &Actor{ 53 BaseActor: supervisor.NewBaseActor(entity, service), 54 mqttMessageQueue: make(chan *Message, 10), 55 actionPool: make(chan events.EventCallEntityAction, 1000), 56 newMsgMu: &sync.Mutex{}, 57 stateMu: &sync.Mutex{}, 58 zigbee2mqttDevice: zigbee2mqttDevice, 59 } 60 61 // mqtt worker 62 go func() { 63 for message := range actor.mqttMessageQueue { 64 actor.mqttNewMessage(message) 65 } 66 }() 67 68 // action worker 69 go func() { 70 for msg := range actor.actionPool { 71 actor.runAction(msg) 72 } 73 }() 74 75 return 76 } 77 78 func (e *Actor) Destroy() { 79 80 } 81 82 // SetState ... 83 func (e *Actor) SetState(params supervisor.EntityStateParams) error { 84 85 e.SetActorState(params.NewState) 86 e.DeserializeAttr(params.AttributeValues) 87 e.SaveState(false, params.StorageSave) 88 89 return nil 90 } 91 92 func (e *Actor) mqttOnPublish(client mqtt.MqttCli, msg mqtt.Message) { 93 message := NewMessage() 94 message.Payload = string(msg.Payload) 95 message.Topic = msg.Topic 96 message.Qos = msg.Qos 97 message.Duplicate = msg.Dup 98 99 e.mqttMessageQueue <- message 100 } 101 102 func (e *Actor) mqttNewMessage(message *Message) { 103 e.newMsgMu.Lock() 104 defer e.newMsgMu.Unlock() 105 106 if _, err := e.ScriptsEngine.AssertFunction(FuncZigbee2mqttEvent, message); err != nil { 107 log.Error(err.Error()) 108 return 109 } 110 } 111 112 func (e *Actor) addAction(event events.EventCallEntityAction) { 113 e.actionPool <- event 114 } 115 116 func (e *Actor) runAction(msg events.EventCallEntityAction) { 117 if action, ok := e.Actions[msg.ActionName]; ok { 118 if action.ScriptEngine != nil && action.ScriptEngine.Engine() != nil { 119 if _, err := action.ScriptEngine.Engine().AssertFunction(FuncEntityAction, e.Id, action.Name, msg.Args); err != nil { 120 log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) 121 } 122 return 123 } 124 } 125 if e.ScriptsEngine != nil && e.ScriptsEngine.Engine() != nil { 126 if _, err := e.ScriptsEngine.AssertFunction(FuncEntityAction, e.Id, msg.ActionName, msg.Args); err != nil { 127 log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) 128 } 129 } 130 }