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