github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/plugins/modbus_rtu/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 modbus_rtu 20 21 import ( 22 "fmt" 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/plugins/node" 30 "github.com/e154/smart-home/system/scripts" 31 "github.com/e154/smart-home/system/supervisor" 32 ) 33 34 // Actor ... 35 type Actor struct { 36 *supervisor.BaseActor 37 scriptService scripts.ScriptService 38 actionPool chan events.EventCallEntityAction 39 stateMu *sync.Mutex 40 } 41 42 // NewActor ... 43 func NewActor(entity *m.Entity, 44 service supervisor.Service) (actor *Actor) { 45 46 actor = &Actor{ 47 BaseActor: supervisor.NewBaseActor(entity, service), 48 actionPool: make(chan events.EventCallEntityAction, 1000), 49 stateMu: &sync.Mutex{}, 50 } 51 52 if actor.Attrs == nil { 53 actor.Attrs = NewAttr() 54 } 55 56 if actor.Setts == nil { 57 actor.Setts = NewSettings() 58 } 59 60 actor.DeserializeAttr(entity.Attributes.Serialize()) 61 62 // Actions 63 for _, a := range actor.Actions { 64 if a.ScriptEngine != nil && a.ScriptEngine.Engine() != nil { 65 // bind 66 a.ScriptEngine.PushFunction("ModbusRtu", NewModbusRtu(service.EventBus(), actor)) 67 } 68 } 69 70 if actor.ScriptsEngine != nil { 71 actor.ScriptsEngine.PushFunction("ModbusRtu", NewModbusRtu(service.EventBus(), actor)) 72 } 73 74 // action worker 75 go func() { 76 for msg := range actor.actionPool { 77 actor.runAction(msg) 78 } 79 }() 80 81 return actor 82 } 83 84 func (e *Actor) Destroy() { 85 86 } 87 88 // SetState ... 89 func (e *Actor) SetState(params supervisor.EntityStateParams) error { 90 91 e.SetActorState(params.NewState) 92 e.DeserializeAttr(params.AttributeValues) 93 e.SaveState(false, params.StorageSave) 94 95 return nil 96 } 97 98 func (e *Actor) addAction(event events.EventCallEntityAction) { 99 e.actionPool <- event 100 } 101 102 func (e *Actor) runAction(msg events.EventCallEntityAction) { 103 if action, ok := e.Actions[msg.ActionName]; ok { 104 if action.ScriptEngine != nil && action.ScriptEngine.Engine() != nil { 105 if _, err := action.ScriptEngine.Engine().AssertFunction(FuncEntityAction, e.Id, action.Name, msg.Args); err != nil { 106 log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) 107 } 108 return 109 } 110 } 111 if e.ScriptsEngine != nil && e.ScriptsEngine.Engine() != nil { 112 if _, err := e.ScriptsEngine.AssertFunction(FuncEntityAction, e.Id, msg.ActionName, msg.Args); err != nil { 113 log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) 114 } 115 } 116 } 117 118 func (e *Actor) localTopic(r string) string { 119 var parent string 120 if e.ParentId != nil { 121 parent = e.ParentId.Name() 122 } 123 return fmt.Sprintf("%s/%s/%s", node.TopicPluginNode, parent, r) 124 }