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  }