github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/automation/action.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 automation 20 21 import ( 22 "fmt" 23 "sync" 24 25 "github.com/e154/smart-home/common" 26 "github.com/e154/smart-home/common/events" 27 m "github.com/e154/smart-home/models" 28 "github.com/e154/smart-home/system/bus" 29 "github.com/e154/smart-home/system/scripts" 30 ) 31 32 // ActionFunc ... 33 const ActionFunc = "automationAction" 34 35 // Action ... 36 type Action struct { 37 model *m.Action 38 scriptService scripts.ScriptService 39 eventBus bus.Bus 40 scriptEngine *scripts.EngineWatcher 41 sync.Mutex 42 } 43 44 // NewAction ... 45 func NewAction(scriptService scripts.ScriptService, 46 eventBus bus.Bus, 47 model *m.Action) (action *Action, err error) { 48 49 action = &Action{ 50 scriptService: scriptService, 51 eventBus: eventBus, 52 model: model, 53 } 54 55 if model.Script != nil { 56 if action.scriptEngine, err = scriptService.NewEngineWatcher(model.Script); err != nil { 57 return 58 } 59 60 action.scriptEngine.PushStruct("Action", NewActionBind(action)) 61 action.scriptEngine.BeforeSpawn(func(engine *scripts.Engine) { 62 if model.EntityId != nil { 63 if _, err = engine.EvalString(fmt.Sprintf("const ENTITY_ID = \"%s\";", model.EntityId.String())); err != nil { 64 log.Error(err.Error()) 65 } 66 } 67 }) 68 action.scriptEngine.Spawn(func(engine *scripts.Engine) { 69 //if _, err = engine.Do(); err != nil { 70 // return 71 //} 72 }) 73 } 74 75 _ = eventBus.Subscribe(fmt.Sprintf("system/automation/actions/%d", model.Id), action.actionHandler, false) 76 77 return 78 } 79 80 func (a *Action) Remove() { 81 if a.scriptEngine != nil { 82 a.scriptEngine.Stop() 83 } 84 _ = a.eventBus.Unsubscribe(fmt.Sprintf("system/automation/actions/%d", a.model.Id), a.actionHandler) 85 } 86 87 // Run ... 88 func (a *Action) Run(entityId *common.EntityId) (result string, err error) { 89 a.Lock() 90 defer a.Unlock() 91 92 //log.Infof("run action") 93 94 if a.scriptEngine != nil { 95 if result, err = a.scriptEngine.Engine().AssertFunction(ActionFunc, entityId); err != nil { 96 log.Error(err.Error()) 97 } 98 } 99 100 if a.model.EntityId != nil && a.model.EntityActionName != nil { 101 id := *a.model.EntityId 102 action := *a.model.EntityActionName 103 a.eventBus.Publish("system/entities/"+id.String(), events.EventCallEntityAction{ 104 PluginName: common.String(id.PluginName()), 105 EntityId: id.Ptr(), 106 ActionName: action, 107 }) 108 } 109 110 a.eventBus.Publish(fmt.Sprintf("system/automation/actions/%d", a.model.Id), events.EventActionCompleted{ 111 Id: a.model.Id, 112 }) 113 114 return 115 } 116 117 func (a *Action) actionHandler(_ string, msg interface{}) { 118 switch msg.(type) { 119 case events.EventCallAction: 120 a.Run(nil) 121 } 122 }