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  }