github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/scripts/scripts.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 scripts
    20  
    21  import (
    22  	"context"
    23  
    24  	"github.com/e154/smart-home/common/encryptor"
    25  
    26  	"github.com/e154/smart-home/common/events"
    27  	"github.com/e154/smart-home/common/logger"
    28  	m "github.com/e154/smart-home/models"
    29  	"github.com/e154/smart-home/system/bus"
    30  	"github.com/e154/smart-home/system/scripts/bind"
    31  	"github.com/e154/smart-home/system/storage"
    32  	"go.uber.org/fx"
    33  )
    34  
    35  var (
    36  	log = logger.MustGetLogger("scripts")
    37  )
    38  
    39  // ScriptService ...
    40  type ScriptService interface {
    41  	NewEngine(s *m.Script) (*Engine, error)
    42  	NewEngineWatcher(*m.Script) (*EngineWatcher, error)
    43  	NewEnginesWatcher([]*m.Script) (*EnginesWatcher, error)
    44  	PushStruct(name string, s interface{})
    45  	PopStruct(name string)
    46  	PushFunctions(name string, s interface{})
    47  	PopFunction(name string)
    48  	Restart()
    49  }
    50  
    51  // scriptService ...
    52  type scriptService struct {
    53  	cfg        *m.AppConfig
    54  	functions  *Pull
    55  	structures *Pull
    56  	storage    *storage.Storage
    57  	eventBus   bus.Bus
    58  }
    59  
    60  // NewScriptService ...
    61  func NewScriptService(lc fx.Lifecycle,
    62  	cfg *m.AppConfig,
    63  	storage *storage.Storage,
    64  	eventBus bus.Bus) ScriptService {
    65  
    66  	s := &scriptService{
    67  		cfg:        cfg,
    68  		functions:  NewPull(),
    69  		structures: NewPull(),
    70  		storage:    storage,
    71  		eventBus:   eventBus,
    72  	}
    73  
    74  	s.bind()
    75  
    76  	lc.Append(fx.Hook{
    77  		OnStart: func(ctx context.Context) (err error) {
    78  			eventBus.Publish("system/services/scripts", events.EventServiceStarted{Service: "Scripts"})
    79  			return
    80  		},
    81  		OnStop: func(ctx context.Context) (err error) {
    82  			eventBus.Publish("system/services/scripts", events.EventServiceStopped{Service: "Scripts"})
    83  			return
    84  		},
    85  	})
    86  
    87  	return s
    88  }
    89  
    90  // NewEngine ...
    91  func (s *scriptService) NewEngine(scr *m.Script) (*Engine, error) {
    92  	return NewEngine(scr, s.structures, s.functions)
    93  }
    94  
    95  // NewEngineWatcher ...
    96  func (s *scriptService) NewEngineWatcher(script *m.Script) (*EngineWatcher, error) {
    97  	return NewEngineWatcher(script, s, s.eventBus), nil
    98  }
    99  
   100  // NewEnginesWatcher ...
   101  func (s *scriptService) NewEnginesWatcher(scripts []*m.Script) (*EnginesWatcher, error) {
   102  	return NewEnginesWatcher(scripts, s, s.eventBus), nil
   103  }
   104  
   105  // PushStruct ...
   106  func (s *scriptService) PushStruct(name string, str interface{}) {
   107  	log.Infof("register structure: '%s'", name)
   108  	s.structures.Push(name, str)
   109  }
   110  
   111  // PopStruct ...
   112  func (s *scriptService) PopStruct(name string) {
   113  	log.Infof("unregister structure: '%s'", name)
   114  	s.structures.Pop(name)
   115  }
   116  
   117  // PushFunctions ...
   118  func (s *scriptService) PushFunctions(name string, f interface{}) {
   119  	log.Infof("register function: '%s'", name)
   120  	s.functions.Push(name, f)
   121  }
   122  
   123  // PopFunction ...
   124  func (s *scriptService) PopFunction(name string) {
   125  	log.Infof("unregister function: '%s'", name)
   126  	s.functions.Pop(name)
   127  }
   128  
   129  // Restart ...
   130  func (s *scriptService) Restart() {
   131  	s.functions.Purge()
   132  	s.structures.Purge()
   133  	s.bind()
   134  	s.eventBus.Publish("system/services/scripts", events.EventServiceRestarted{})
   135  }
   136  
   137  func (s *scriptService) bind() {
   138  	s.PushStruct("Log", &bind.LogBind{})
   139  	s.PushFunctions("ExecuteSync", bind.ExecuteSync)
   140  	s.PushFunctions("ExecuteAsync", bind.ExecuteAsync)
   141  	s.PushFunctions("Encrypt", encryptor.EncryptBind)
   142  	s.PushFunctions("Decrypt", encryptor.DecryptBind)
   143  	s.PushStruct("Storage", bind.NewStorageBind(s.storage))
   144  	s.PushStruct("http", bind.NewHttpBind())
   145  	s.PushStruct("HTTP", bind.NewHttpBind())
   146  }