github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/tests/plugins/sensor/sensor_test.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 sensor
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/e154/smart-home/common/events"
    28  
    29  	"github.com/e154/smart-home/adaptors"
    30  	"github.com/e154/smart-home/common"
    31  	m "github.com/e154/smart-home/models"
    32  	"github.com/e154/smart-home/system/bus"
    33  	"github.com/e154/smart-home/system/scripts"
    34  	"github.com/e154/smart-home/system/supervisor"
    35  	. "github.com/e154/smart-home/tests/plugins"
    36  	. "github.com/smartystreets/goconvey/convey"
    37  )
    38  
    39  func TestSensor(t *testing.T) {
    40  
    41  	const sensorSourceScript = `
    42  checkStatus =->
    43      res = HTTP.get("http://%s:%d/?t=12345678")
    44      if res.error 
    45          EntitySetStateName ENTITY_ID, 'ERROR'
    46          return
    47      p = unmarshal res.body
    48      attrs =
    49          paid_rewards: p.user.paid_rewards
    50      EntitySetState ENTITY_ID,
    51          new_state: 'ENABLED'
    52          attribute_values: attrs
    53          storage_save: true
    54  
    55  entityAction = (entityId, actionName)->
    56      switch actionName
    57          when 'CHECK' then checkStatus()
    58  `
    59  
    60  	const response1 = `{"user": {"paid_rewards": 9.08}}`
    61  
    62  	Convey("sensor", t, func(ctx C) {
    63  		_ = container.Invoke(func(adaptors *adaptors.Adaptors,
    64  			scriptService scripts.ScriptService,
    65  			supervisor supervisor.Supervisor,
    66  			eventBus bus.Bus) {
    67  
    68  			// register plugins
    69  			AddPlugin(adaptors, "sensor")
    70  
    71  			serviceCh := WaitService(eventBus, time.Second*5, "Supervisor")
    72  			pluginsCh := WaitPlugins(eventBus, time.Second*5, "sensor")
    73  			supervisor.Start(context.Background())
    74  			defer supervisor.Shutdown(context.Background())
    75  			So(<-serviceCh, ShouldBeTrue)
    76  			So(<-pluginsCh, ShouldBeTrue)
    77  
    78  			// bind convey
    79  			RegisterConvey(scriptService, ctx)
    80  
    81  			// test server
    82  			var port = GetPort()
    83  			var host = "127.0.0.1"
    84  
    85  			// add scripts
    86  			// ------------------------------------------------
    87  
    88  			plugScript, err := AddScript("sensor script", fmt.Sprintf(sensorSourceScript, host, port), adaptors, scriptService)
    89  			So(err, ShouldBeNil)
    90  
    91  			// add entity
    92  			// ------------------------------------------------
    93  
    94  			sensorEnt := GetNewSensor("device1")
    95  			sensorEnt.Actions = []*m.EntityAction{
    96  				{
    97  					Name:        "CHECK",
    98  					Description: "condition check",
    99  					Script:      plugScript,
   100  				},
   101  			}
   102  			sensorEnt.States = []*m.EntityState{
   103  				{
   104  					Name:        "ENABLED",
   105  					Description: "enabled state",
   106  				},
   107  				{
   108  					Name:        "DISABLED",
   109  					Description: "disabled state",
   110  				},
   111  				{
   112  					Name:        "ERROR",
   113  					Description: "error state",
   114  				},
   115  			}
   116  			sensorEnt.Attributes = m.Attributes{
   117  				"paid_rewards": {
   118  					Name: "paid_rewards",
   119  					Type: common.AttributeFloat,
   120  				},
   121  			}
   122  			err = adaptors.Entity.Add(context.Background(), sensorEnt)
   123  			ctx.So(err, ShouldBeNil)
   124  			_, err = adaptors.EntityStorage.Add(context.Background(), &m.EntityStorage{
   125  				EntityId:   sensorEnt.Id,
   126  				Attributes: sensorEnt.Attributes.Serialize(),
   127  			})
   128  			So(err, ShouldBeNil)
   129  
   130  			eventBus.Publish("system/models/entities/"+sensorEnt.Id.String(), events.EventCreatedEntityModel{
   131  				EntityId: sensorEnt.Id,
   132  			})
   133  
   134  			time.Sleep(time.Second)
   135  
   136  			// ------------------------------------------------
   137  
   138  			t.Run("sensor stats", func(t *testing.T) {
   139  				Convey("stats", t, func(ctx C) {
   140  
   141  					ctx2, cancel := context.WithCancel(context.Background())
   142  					go func() { _ = MockHttpServer(ctx2, host, port, []byte(response1)) }()
   143  					time.Sleep(time.Millisecond * 500)
   144  					supervisor.CallAction(sensorEnt.Id, "CHECK", nil)
   145  					time.Sleep(time.Second)
   146  					cancel()
   147  
   148  					lastState, err := adaptors.EntityStorage.GetLastByEntityId(context.Background(), sensorEnt.Id)
   149  					ctx.So(err, ShouldBeNil)
   150  
   151  					ctx.So(lastState.Attributes["paid_rewards"], ShouldEqual, 9.08)
   152  				})
   153  			})
   154  
   155  		})
   156  	})
   157  }