diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59aedbf83..fcec29bf1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,33 +79,33 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: upload server darwin amd64 artifact - uses: softprops/action-gh-release@v1 - with: - files: /home/runner/work/smart-home/smart-home/server-darwin-10.6-amd64 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: upload server darwin arm64 artifact - uses: softprops/action-gh-release@v1 - with: - files: /home/runner/work/smart-home/smart-home/server-darwin-10.6-arm64 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: upload cli darwin arm64 artifact - uses: softprops/action-gh-release@v1 - with: - files: /home/runner/work/smart-home/smart-home/cli-darwin-10.6-arm64 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: upload cli darwin amd64 artifact - uses: softprops/action-gh-release@v1 - with: - files: /home/runner/work/smart-home/smart-home/cli-darwin-10.6-amd64 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# - name: upload server darwin amd64 artifact +# uses: softprops/action-gh-release@v1 +# with: +# files: /home/runner/work/smart-home/smart-home/server-darwin-10.6-amd64 +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# +# - name: upload server darwin arm64 artifact +# uses: softprops/action-gh-release@v1 +# with: +# files: /home/runner/work/smart-home/smart-home/server-darwin-10.6-arm64 +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# +# - name: upload cli darwin arm64 artifact +# uses: softprops/action-gh-release@v1 +# with: +# files: /home/runner/work/smart-home/smart-home/cli-darwin-10.6-arm64 +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# +# - name: upload cli darwin amd64 artifact +# uses: softprops/action-gh-release@v1 +# with: +# files: /home/runner/work/smart-home/smart-home/cli-darwin-10.6-amd64 +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: upload cli linux amd64 artifact uses: softprops/action-gh-release@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6890a8e61..a8dd82921 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,5 +85,5 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: trying to build - id: build-all - run: make build_server build_cli build_structure build_common_structure build_archive docker_image + id: build-linux + run: make build_linux build_structure build_common_structure build_archive docker_image diff --git a/Makefile b/Makefile index 6c334f5dd..55a8bc0a7 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,7 @@ .PHONY: get_deps fmt .DEFAULT_GOAL := build -build: build_public build_server build_cli tests: lint test -all: build build_structure build_common_structure build_archive docker_image +all: build_public build_linux build_structure build_common_structure build_archive docker_image deploy: docker_image_upload EXEC=server @@ -100,21 +99,34 @@ svgo: DIR=${ROOT}/data/icons/* cd ${ROOT} && svgo ${DIR} --enable=inlineStyles --config '{ "plugins": [ { "inlineStyles": { "onlyMatchedOnce": false } }] }' --pretty -build_server: - @echo MARK: build server +build_linux: + @echo MARK: build linux server ${GO_BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-linux-amd64 ${GO_BUILD_ENV} GOOS=linux GOARCH=arm GOARM=7 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-linux-arm-7 ${GO_BUILD_ENV} GOOS=linux GOARCH=arm GOARM=6 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-linux-arm-6 ${GO_BUILD_ENV} GOOS=linux GOARCH=arm GOARM=5 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-linux-arm-5 - ${GO_BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-darwin-10.6-amd64 - ${GO_BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-darwin-10.6-arm64 -build_cli: @echo MARK: build cli cd ${ROOT}/cmd/cli && ${GO_BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${CLI}-linux-amd64 + +build_darwin: + @echo MARK: build darwin server + CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-darwin-10.6-amd64 + CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-darwin-10.6-arm64 + + @echo MARK: build cli cd ${ROOT}/cmd/cli && ${GO_BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${CLI}-darwin-10.6-amd64 cd ${ROOT}/cmd/cli && ${GO_BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${CLI}-darwin-10.6-arm64 +build_windows: + @echo MARK: build windows server + CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-windows-amd64 + CGO_ENABLED=1 GOOS=windows GOARCH=arm64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${EXEC}-windows-arm64 + + @echo MARK: build cli + cd ${ROOT}/cmd/cli && ${GO_BUILD_ENV} GOOS=windows GOARCH=amd64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${CLI}-windows-amd64 + cd ${ROOT}/cmd/cli && ${GO_BUILD_ENV} GOOS=windows GOARCH=arm64 go build ${GO_BUILD_FLAGS} ${GO_BUILD_TAGS} -o ${ROOT}/${CLI}-windows-arm64 + build_public: @echo MARK: build public echo -e "node version.\n" && \ @@ -149,15 +161,8 @@ build_structure: cp ${ROOT}/CONTRIBUTING.md ${SERVER_DIR} cp ${ROOT}/bin/server-installer.sh ${SERVER_DIR} chmod +x ${SERVER_DIR}/data/scripts/ping.sh - cp ${ROOT}/${EXEC}-linux-amd64 ${SERVER_DIR} - cp ${ROOT}/${EXEC}-linux-arm-7 ${SERVER_DIR} - cp ${ROOT}/${EXEC}-linux-arm-6 ${SERVER_DIR} - cp ${ROOT}/${EXEC}-linux-arm-5 ${SERVER_DIR} - cp ${ROOT}/${EXEC}-darwin-10.6-amd64 ${SERVER_DIR} - cp ${ROOT}/${EXEC}-darwin-10.6-arm64 ${SERVER_DIR} - cp ${ROOT}/${CLI}-darwin-10.6-amd64 ${SERVER_DIR} - cp ${ROOT}/${CLI}-darwin-10.6-arm64 ${SERVER_DIR} - cp ${ROOT}/${CLI}-linux-amd64 ${SERVER_DIR} + cp ${ROOT}/${EXEC}-* ${SERVER_DIR} + cp ${ROOT}/${CLI}-* ${SERVER_DIR} cp ${ROOT}/bin/server ${SERVER_DIR} build_common_structure: @@ -228,15 +233,8 @@ docker_image_upload: clean: @echo MARK: clean rm -rf ${SERVER_DIR} - rm -f ${ROOT}/${EXEC}-linux-amd64 - rm -f ${ROOT}/${EXEC}-linux-arm-7 - rm -f ${ROOT}/${EXEC}-linux-arm-6 - rm -f ${ROOT}/${EXEC}-linux-arm-5 - rm -f ${ROOT}/${EXEC}-darwin-10.6-amd64 - rm -f ${ROOT}/${EXEC}-darwin-10.6-arm64 - rm -f ${ROOT}/${CLI}-linux-amd64 - rm -f ${ROOT}/${CLI}-darwin-10.6-amd64 - rm -f ${ROOT}/${CLI}-darwin-10.6-arm64 + rm -f ${ROOT}/${EXEC}-* + rm -f ${ROOT}/${CLI}-* rm -f ${HOME}/${ARCHIVE} front_client: diff --git a/Makefile.local b/Makefile.local index 7ce6c863c..574fa9519 100644 --- a/Makefile.local +++ b/Makefile.local @@ -24,7 +24,7 @@ BUILD_NUMBER_VALUE=$(shell echo ${TRAVIS_BUILD_NUMBER}) RELEASE_VERSION ?= v0.1.0 IMAGE=smart-home-${EXEC} -SERVER ?= 192.168.43.127 +SERVER ?= 192.168.0.170 DOCKER_ACCOUNT ?= ${SERVER}:5000 DOCKER_IMAGE_VER=${DOCKER_ACCOUNT}/${IMAGE}:${RELEASE_VERSION} DOCKER_IMAGE_LATEST=${DOCKER_ACCOUNT}/${IMAGE}:latest diff --git a/adaptors/plugin.go b/adaptors/plugin.go index 3fc5a73d6..c3d0a287a 100644 --- a/adaptors/plugin.go +++ b/adaptors/plugin.go @@ -33,7 +33,7 @@ type IPlugin interface { CreateOrUpdate(ctx context.Context, ver *m.Plugin) error Update(ctx context.Context, plugin *m.Plugin) error Delete(ctx context.Context, pluginId string) error - List(ctx context.Context, limit, offset int64, orderBy, sort string, onlyEnabled bool) (list []*m.Plugin, total int64, err error) + List(ctx context.Context, limit, offset int64, orderBy, sort string, enabled, triggers *bool) (list []*m.Plugin, total int64, err error) Search(ctx context.Context, query string, limit, offset int64) (list []*m.Plugin, total int64, err error) GetByName(ctx context.Context, name string) (ver *m.Plugin, err error) fromDb(dbVer *db.Plugin) (plugin *m.Plugin) @@ -80,9 +80,9 @@ func (p *Plugin) Delete(ctx context.Context, name string) (err error) { } // List ... -func (p *Plugin) List(ctx context.Context, limit, offset int64, orderBy, sort string, onlyEnabled bool) (list []*m.Plugin, total int64, err error) { +func (p *Plugin) List(ctx context.Context, limit, offset int64, orderBy, sort string, enabled, triggers *bool) (list []*m.Plugin, total int64, err error) { var dbList []*db.Plugin - if dbList, total, err = p.table.List(ctx, int(limit), int(offset), orderBy, sort, onlyEnabled); err != nil { + if dbList, total, err = p.table.List(ctx, int(limit), int(offset), orderBy, sort, enabled, triggers); err != nil { return } @@ -123,11 +123,12 @@ func (p *Plugin) GetByName(ctx context.Context, name string) (ver *m.Plugin, err func (p *Plugin) fromDb(dbVer *db.Plugin) (ver *m.Plugin) { ver = &m.Plugin{ - Name: dbVer.Name, - Version: dbVer.Version, - Enabled: dbVer.Enabled, - System: dbVer.System, - Actor: dbVer.Actor, + Name: dbVer.Name, + Version: dbVer.Version, + Enabled: dbVer.Enabled, + System: dbVer.System, + Actor: dbVer.Actor, + Triggers: dbVer.Triggers, } // deserialize settings @@ -141,11 +142,12 @@ func (p *Plugin) fromDb(dbVer *db.Plugin) (ver *m.Plugin) { func (p *Plugin) toDb(ver *m.Plugin) (dbVer *db.Plugin) { dbVer = &db.Plugin{ - Name: ver.Name, - Version: ver.Version, - Enabled: ver.Enabled, - System: ver.System, - Actor: ver.Actor, + Name: ver.Name, + Version: ver.Version, + Enabled: ver.Enabled, + System: ver.System, + Actor: ver.Actor, + Triggers: ver.Triggers, } // serialize settings diff --git a/api/api.swagger3.yaml b/api/api.swagger3.yaml index d5cfd9f0f..748a3c845 100644 --- a/api/api.swagger3.yaml +++ b/api/api.swagger3.yaml @@ -2505,6 +2505,11 @@ paths: required: true schema: type: string + - name: note + in: query + required: false + schema: + type: string - name: lang in: query required: false @@ -2536,6 +2541,16 @@ paths: - $ref: '#/components/parameters/listSort' - $ref: '#/components/parameters/listPage' - $ref: '#/components/parameters/listLimit' + - name: triggers + in: query + required: false + schema: + type: boolean + - name: enabled + in: query + required: false + schema: + type: boolean responses: 200: description: A successful response. @@ -6203,8 +6218,6 @@ components: type: array items: type: string - script: - $ref: '#/components/schemas/apiScript' scriptId: type: integer format: int64 @@ -6309,7 +6322,7 @@ components: apiPluginOptionsResult: type: object required: [ triggers, actors, actorCustomAttrs, actorAttrs, actorCustomActions, actorActions, actorCustomStates, - actorStates, actorCustomSetts, actorSetts, setts ] + actorStates, actorCustomSetts, actorSetts, setts, triggerParams ] properties: triggers: type: boolean @@ -6343,6 +6356,24 @@ components: type: object additionalProperties: $ref: '#/components/schemas/apiAttribute' + triggerParams: + $ref: '#/components/schemas/apiTriggerParams' + apiTriggerParams: + type: object + required: [script, entities, attributes, required] + properties: + required: + type: array + items: + type: string + script: + type: boolean + entities: + type: boolean + attributes: + type: object + additionalProperties: + $ref: '#/components/schemas/apiAttribute' apiPluginOptionsResultEntityAction: type: object required: [ name, description, imageUrl, icon ] diff --git a/api/controllers/plugin.go b/api/controllers/plugin.go index 852704701..5cbcda59d 100644 --- a/api/controllers/plugin.go +++ b/api/controllers/plugin.go @@ -41,7 +41,7 @@ func NewControllerPlugin(common *ControllerCommon) *ControllerPlugin { func (c ControllerPlugin) PluginServiceGetPluginList(ctx echo.Context, params stub.PluginServiceGetPluginListParams) error { pagination := c.Pagination(params.Page, params.Limit, params.Sort) - items, total, err := c.endpoint.Plugin.GetList(ctx.Request().Context(), pagination) + items, total, err := c.endpoint.Plugin.GetList(ctx.Request().Context(), pagination, params.Enabled, params.Triggers) if err != nil { return c.ERROR(ctx, err) } @@ -115,7 +115,7 @@ func (c ControllerPlugin) PluginServiceUpdatePluginSettings(ctx echo.Context, na // PluginServiceGetPluginReadme ... func (c ControllerPlugin) PluginServiceGetPluginReadme(ctx echo.Context, name string, params stub.PluginServiceGetPluginReadmeParams) error { - html, err := c.endpoint.Plugin.Readme(ctx.Request().Context(), name, params.Lang) + html, err := c.endpoint.Plugin.Readme(ctx.Request().Context(), name, params.Note, params.Lang) if err != nil { return c.ERROR(ctx, err) } diff --git a/api/dto/attributes.go b/api/dto/attributes.go index 8d0b551db..115eeb386 100644 --- a/api/dto/attributes.go +++ b/api/dto/attributes.go @@ -153,6 +153,8 @@ func AttributeToApi(attributes m.Attributes) (apiAttr map[string]stub.ApiAttribu case "encrypted": attr.Type = stub.ENCRYPTED attr.Encrypted = common.String(v.Decrypt()) + default: + attr.Type = stub.ApiTypes(v.Type) } apiAttr[k] = attr } diff --git a/api/dto/plugin.go b/api/dto/plugin.go index 2a6987749..7af3dc2c8 100644 --- a/api/dto/plugin.go +++ b/api/dto/plugin.go @@ -19,7 +19,7 @@ package dto import ( - stub "github.com/e154/smart-home/api/stub" + "github.com/e154/smart-home/api/stub" "github.com/e154/smart-home/common" m "github.com/e154/smart-home/models" ) @@ -85,7 +85,14 @@ func (p Plugin) Options(options m.PluginOptions) (result *stub.ApiPluginOptionsR ActorCustomSetts: options.ActorCustomSetts, ActorSetts: AttributeToApi(options.ActorSetts), Setts: AttributeToApi(options.Setts), + TriggerParams: stub.ApiTriggerParams{ + Attributes: AttributeToApi(options.TriggerParams.Attributes), + Entities: options.TriggerParams.Entities, + Script: options.TriggerParams.Script, + Required: options.TriggerParams.Required, + }, } + return } diff --git a/api/stub/server.go b/api/stub/server.go index 8ae41b175..05add9cac 100644 --- a/api/stub/server.go +++ b/api/stub/server.go @@ -2999,6 +2999,13 @@ func (w *ServerInterfaceWrapper) PluginServiceGetPluginReadme(ctx echo.Context) // Parameter object where we will unmarshal all parameters from the context var params PluginServiceGetPluginReadmeParams + // ------------- Optional query parameter "note" ------------- + + err = runtime.BindQueryParameter("form", true, false, "note", ctx.QueryParams(), ¶ms.Note) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter note: %s", err)) + } + // ------------- Optional query parameter "lang" ------------- err = runtime.BindQueryParameter("form", true, false, "lang", ctx.QueryParams(), ¶ms.Lang) @@ -3095,6 +3102,20 @@ func (w *ServerInterfaceWrapper) PluginServiceGetPluginList(ctx echo.Context) er return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } + // ------------- Optional query parameter "triggers" ------------- + + err = runtime.BindQueryParameter("form", true, false, "triggers", ctx.QueryParams(), ¶ms.Triggers) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter triggers: %s", err)) + } + + // ------------- Optional query parameter "enabled" ------------- + + err = runtime.BindQueryParameter("form", true, false, "enabled", ctx.QueryParams(), ¶ms.Enabled) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter enabled: %s", err)) + } + // Invoke the callback with all the unmarshalled arguments err = w.Handler.PluginServiceGetPluginList(ctx, params) return err diff --git a/api/stub/types.go b/api/stub/types.go index c954d45a3..9eaeecf16 100644 --- a/api/stub/types.go +++ b/api/stub/types.go @@ -890,7 +890,6 @@ type ApiNewTriggerRequest struct { EntityIds []string `json:"entityIds"` Name string `json:"name"` PluginName string `json:"pluginName"` - Script *ApiScript `json:"script,omitempty"` ScriptId *int64 `json:"scriptId,omitempty"` } @@ -963,6 +962,7 @@ type ApiPluginOptionsResult struct { ActorStates map[string]ApiPluginOptionsResultEntityState `json:"actorStates"` Actors bool `json:"actors"` Setts map[string]ApiAttribute `json:"setts"` + TriggerParams ApiTriggerParams `json:"triggerParams"` Triggers bool `json:"triggers"` } @@ -1207,6 +1207,14 @@ type ApiTrigger struct { UpdatedAt time.Time `json:"updatedAt"` } +// ApiTriggerParams defines model for apiTriggerParams. +type ApiTriggerParams struct { + Attributes map[string]ApiAttribute `json:"attributes"` + Entities bool `json:"entities"` + Required []string `json:"required"` + Script bool `json:"script"` +} + // ApiTypes defines model for apiTypes. type ApiTypes string @@ -1979,6 +1987,7 @@ type AuthServicePasswordResetParams struct { // PluginServiceGetPluginReadmeParams defines parameters for PluginServiceGetPluginReadme. type PluginServiceGetPluginReadmeParams struct { + Note *string `form:"note,omitempty" json:"note,omitempty"` Lang *string `form:"lang,omitempty" json:"lang,omitempty"` Accept *AcceptJSON `json:"Accept,omitempty"` } @@ -2002,7 +2011,9 @@ type PluginServiceGetPluginListParams struct { Page *ListPage `form:"page,omitempty" json:"page,omitempty"` // Limit The number of results returned on a page - Limit *ListLimit `form:"limit,omitempty" json:"limit,omitempty"` + Limit *ListLimit `form:"limit,omitempty" json:"limit,omitempty"` + Triggers *bool `form:"triggers,omitempty" json:"triggers,omitempty"` + Enabled *bool `form:"enabled,omitempty" json:"enabled,omitempty"` } // PluginServiceSearchPluginParams defines parameters for PluginServiceSearchPlugin. diff --git a/api/typedoc/assets/navigation.js b/api/typedoc/assets/navigation.js index 6785f0f24..ad3eb7c59 100644 --- a/api/typedoc/assets/navigation.js +++ b/api/typedoc/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE5WYX2/TMBTFv0ufB2OFDdjbWKetEvsjUoEAIeSmd421xAnx7VhBfHccJ12d9Prafc0552c7sZ1rf/87QnjC0enoDLGW8xXCbF3B6GBUCczMY1CrQh/2xJcZFrlxPEi1GJ2++3fwzLgGrcWSJDiSP3+WoizVNioVQn0vUjA9sFI/Oj4+ccM5PAk62yhc9FzkOdP2VuYhBdR0B1qJDZdqIf0d2KgBhC5z8AEajYtfKJS4JtOtFA637yjJyhoZjuMKIxMUCHeiFoVmkI4rEhnq5NbEAh9BoROggQNTEGhd55lQS1j4ia6LRT5BahbuJ9CVmQSeLvY9HO4KsWJZroEDdRsCyei0iPiVcRxzDGuIACXXCYcxcgRkBjkszSzkSBtPBO4LzKuVzjhaZ+FhZu9OJwLFFMHXNdcSht1WzRKmV2TPEY0KdM1xsUipoKYxjRKMmnm7yultwdFZzC/05I3ABe9KYyaTVuGiCZa1byV1Ghtfa/NaZ7VcLqHmViVl5MCdk2R1WkTc/rxnsgCuax5vBN7dRiNaIOwxjdg3F4N3jRHgyPcS+Uq+ja852FbmIJnZ/8l4I3BBVaK8p2dLK7HFXw1O6YWmyjRln3k2yLx6//boeOzmNoXtTngjRBM+i3zlx1g1mqW9nOGWusNoN8xhvn0ayrbTz5YX52VRCLUYcnYdIebFzWw6+/pzOtmiHkUtxTxvCo+N2Ke8dgHpsK7dxjvpxRETn0Barytna71fKVuB6sNO6odP3vQqRm+4k9iwqfkkaOp04XKGrhByHQFc74lLUlDA06wlCLsEpGbxENizxUATQJRqySM3pihgv2CnaLvVOoFK4gac7DVg4x6uYwJILWoaFhhsssdgrfHGHGjDuMbFIdtTx5leK3qcjh7GJDwl4SGXUE6kRqFS+AD4G0DZsov8oD5vHH5W9v9VJLc18UDb6FRpuQCGOHCxSBzeAbgkpG4BeoA7cxBx/g8UZmBhYGKFZSGalH+nG3qicMRNC0X0XLl4oG79yXNd5z5o+lKAacF/PxBoyH6euCasdR94U4hGoRsjAwbnJoniuTqDyeBpLOqaInQSEy5ErTORU+FO4sLmOOhdJc8iA6hqSYetwAT1g8zzWzU11TUN6BnCoI/CJDMG1BrCoMScLUzuQpHze8fEALG7YvHPj76DRRVV7vl3bjQmvlLMLHkWGcAfuZwDjNnpMvTs4H78B0N6X6TmFwAA" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE5WYW3PTMBCF/0ueyy3QAn3rbdrM0MvgDB1gGEZNtrGmtmzkTWlg+O/IstPIymqlvPqc81mSJXml739HCE84OhwdIWp5t0SYrmoY7Y1qgbl5DGpZNq8G4sscy8I4HqSajw4//Nt7ZlxC04gFSXCkcP5ohrJSm6hUCPpezMC0wErD6Hj/wA0X8CTobKtw0eMCPkNTV6oBEuDoHOZEFAXThY3MQ0rQdD86iQ1Xai7DDVirEURTFfQ49BoXP1MocUWmOyke7sYoyyuNDMdxxZEZCoQboUXZMEjHlYiMNXJjYoGPoNAJ0EDPFAVa10ku1ALmYaLrYpFPMDPrn10mnofDXSDWLMs1cKB+XyEZvZYQvzCOfY5hDQmg7DLjMEZOgEyhgIWZhRxp7UnA3cJdvWxyjtZbeJj5BcxOBYoJQqhpriUOu67bJUyvyIEjGRVpmuNikVKBpjGtEo2aebss6G3B0VnMLwzkjcAFbypjJpNW4aIZVjq0knqNja8aM6xTLRcL0NyqpIwcuHeSrF5LiNsaYCpL4JoW8CbgTYWQAN64EpDuzpzAJuwpL7EfIwXvGhPAiUOdOMrfxpccbCNzkNz8Ush4K3BBVaG8pydgJ7FlqQanmkNT/5qC1DzzMq8/vn+zP3Zz65J7K7wWkglfRLEMY6yazGqCHH+X3mJ0e7Cf757Gst30sxXLSVWWQs19zrYjxjy7mk6mX39OTjeoR6GluCvaWmYtDilvXcDML5U38V568YaJ21OFcDpyv1S2qO0PHMLrwcG7YfhWS3d2DNJWY+KnMNOrGql0LzHhMxUM9xIbNiWshIY6LLkc3xVDrhKAqx1x2QwUOcKeJRGmZWjQhp4o7hyQWpA+cWBLgWaAKNWCR65NScDhcYaibZ9lCFSW1uFspw4bt78lEUBqf6Jhkc5mO3TWGq/McT+Oa10csjuTHTUrRffT0eOYjKdkPOQcqlPZoFAzOAb8DaBsUUp+0JA3DT+thr9dktuZeKB96UQ1cg4M0XOxSPRvSFwSUnckA8CNOaY5vzoK41kYmFhiVYo2Fd44fU8SjriHooiBC6kA1K3Oea7r3AV9XJALjvLtgqVvYhh++FIm8iL71dNeYa27wNtSPQndGhkwONd3FM/VGUwOT2OhNUXoJSZcCt3koqDCvcSFzRk8uPieRQZQa0mHrcAEmwdZFNdqYs4fNGBgiIM+CZPMGVBniIMyc/oyuTNFzu8tEwPE/l4rPD+GDhZV1kXgl7zWmPhSMbPkWWQAf+TiDmDMThffs4X78R8f2fE+ohkAAA==" \ No newline at end of file diff --git a/api/typedoc/assets/search.js b/api/typedoc/assets/search.js index 1a125dc3d..0a68c9436 100644 --- a/api/typedoc/assets/search.js +++ b/api/typedoc/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAE7VdbXPbtrL+L9ZXX1cA3/stbXPSzDRNps7pmXMzHQ8tMTansqiKVFK30/9+8UKKi+UuCVK+nxqXi10Az+5i8QAi/746Vl/rq28//X31e7nfXn0bh9dX+/ypuPr26ik/1o/57ur66nTcqb8/n/abpqz29Tftk5vH5kk/3uzyui6Ulqurf64JRac9r+r8zFfZY/GnzI9HQlX7xFfR6z+Lzakpbp/3G0IZeDpT4at6VKN57K1yvzk+HxpKm33iq+iHglPUPvFV9KZoXu+bsnkmVJ2f+Q9PS98WzW2TNwU5SiiwTO3P+n9OqdZC89S/mer1m6W9ftU0x/JeuUo91u1eana/PQy8uciA6l5T7h9G1Xcys6fnXaH6RQaYKzFP8ff5bvfKKGI19yKzVJdFPa3cEZrf89tNsec98Szhq7gwzdgew8f+eaP6oaybfL8pPlavjkVO5g8ks0D5d0XztSj2H6py31D+x4nOMGUavN3X5bbgB4KEfNU3xdNhR2eV7pGvqsNR9YDQY/6/r5IPp/rx9rlWtl9/KUh1SMJ/oLvi4Zg/sU7mCviqrX8vd7v3+59ypeeR0Oo8n6n0tqhrpeS1esoq7mVmKn+7b+j5dZ77Kv2rfLgvCvn0R9NwuGERX9VjOmcry09N9ZTrxt9X+23JuAIhNd8A62hYZL7qj8fy4aE4vtoVf1LZgBZcbOZjSdYzpNxiI6Zy+f4x3z8UlLePyi83atKIlzkjOWookP06+fPHtx//e/f2h7PqL/mxzO93hVohu2ejytKzrnNV9PH50MNQ7E9P9TfOs1F9Ij4rfPvzx0k1KysEVF1fHfKjDkLcI9LG7cdf3v78ZtrMWW6xpX/99P6Vx3g6scV2vnv//qdpM63UYiuvfvnl1X+nzXRii+18fPvu9bSZVmqxlXevPkwbsUKLbbx99+qNx1A6scV2Prz3iptObJ4duc4SEclhzJ8NNqoBMDie8aIo6Dt+d9fAxEEpWp1lJroNp2Yt+8S6hzveEQs3reCEmZu2P4w13/Hc+A1qwtqXfHfyM9dJzrbHwl9zdid2DzMcoJ7nATXsdgTCo4K1v/p3cfycb5Qh82B8aYKzvQMVE6llZSXobtpecKrziQ6urISf6gFmcGPWzvHkNswDp07HJELaPjPyQ7V7fgATS6u+6cV4ExPBslEiTbG9A1PNGHMkF9s7Hbae9hzJxfaoRIctjee4aRvbot4cy4OzeWBMuaLLUSt0OEwi1kkttlNup2wYicX6/6qqpykLrcxiG8eirnYnH3AcyTn2YF61zOJ7A3H9Fm5WQAobCPnnW8ehJ1WuRn172NcZHj5t28fZvbuwqXbVcYbxTv5Cs80x39cO3TZtGra50Pwuvy92M0x38vPNsj48ad3fd0tl0lPfqpP1GMnoKH7Im3w8DDsJ/3G4Fea4wtV4kYk66Vlq+Ji8mag/UEPbTWbAT0b2DiwHEz2ADWYO3A2/cizbuTZb2ZnmcFmIzo7sUuFzXDRdGgItU8Vh2wvfZXmoeWxhbqVnF06EFY/lZXHxRJjzX1EmrFYot7EWe8FLxqjczmNwVuoCO14+N77J9rJz1CSux+Sd5S6wxW4YCHseWwYvm+ymiLDpsS3ibLIswq9jDIZ5+GJsQq/Nm1H4Fa0UcM1tD9g11f8hP+b0aj8QmlH9Fl/v6oYpx2i9K9iGHtqw14z5vJuDO7Nczhjdimh6YWfq9nrEHVuOMF0ZNLy0I011zB+Kuzr/MqsbbrP5nRg6nj2eu32sjiRzNBC6fNtFqxzfdg37umzbxdj2WSS9u1A+aYi0af8OwDaXmt/MGnorPt8ok8MmPKmXeSlHQhp9/Ah09BI3wpb9vWi6Ax5OhM37+pCH8VEXGtid9iDS5NCBeJszNszkhgtoWY2U+W03fGpFRvloPTCuftzNvZ37Ipee68jLPMjbby6IjnkxwVYvG5bQgWZ6sSVGTKU1aeMstdiEl4WlEzU8zuPmCkouGgu+B8sNp5dbNCJ42MWNxcosUW/pnslB9GJLjDyW220xGYhnKU8TTuK29+9/KeqDCgDaxVwR/1RenehCgtC3srLMAFAfGXPFkSTLSXNWdq45OHHE7WVg1PPastt/gxPDOCKFKyhMDwN0cDQ53nHrFjbpii812uR05GNrrdzisanI9pzKXnSGMegKPzbNYSyA4HN/d7ivtmRBNdC2aiXp3jud4yOHPmga2upELzT2rqhrtbLPsNm3mGUa4vSoRCiL+v+P4iLXYX/X8aEgs9pZycoK0L00XWAUH6p6QnMrsUA1nYmB5pH0O6Z4W+wKujDpdZ9l5qt/LPJtcSTzRa+/F5pv4D6vy82rU/M4bgKKLZik8qGom2krjtwCM9XX/a7KyZwHjPRSfiac40UTgz8qPRFlBT73T3Snuji+/eHWS+GqF+aIZ9BF9oSt2TFHbNhcJ7rcGJfGh7ZG0zhjikDnY/sTkRGjnYg/RpvHvGHPQoc6V7386HDOfWXMfi53evdXetsFDS43fMjpiOUtty0uMn14rJpq1qBhixcwPWvYTpOLjP9ePDMXJQizrfBFBici0zXoE5yEQSI+b9+NpTr11D8q1eTvxxJZp2zVCY52X3ds2VSd7fjMkmuGmKD/FPeHUz3mgq3ESy4xUKXvItN1dOEy45j0WmgmDE6g5NjzQWpoLh0sNsPf+4An4wCBDdTHdz9Fdz+///j2X/iHJVjbCsmOByT/25LXP71+88urd1PWgNxCS/95/d2Hf9/+OGWoF5tjh4ieEQfwjxf+5lWvaJwq73qzhOtwrEwTHROmxplNx5YHtTk0BjHYV035mdxJ2yf+u8x98XUEUKBt5UjSnW67xZiqiz0JAzTSyviqhzyZ2pBXdB5sH/lPyq56mNKzsjIMk9P2hVFf7j9Xk/pboUUGtsX9aXoEndQiE1/zI01IQgut0CIDLFfkWBiniYYmwO9SN8hh+l+ltk/+R4x7DHC+W3vfgupu+8jf+biaBCpatUL0sLve8MTSd88/M2SsYwVKLjJVF/lxMz2as5ivEd8bvISVG/sfBe7EpayurdOM59RIxs/FzMj4z6N7gw285eH76ukp3+OLqkMBb/f9Xv3nSB5i2Sf+zqtCpyn3p+pUv6voG0tA42ogzRHjpnucjzXV4ftZZskWvqbBtLmvHADGpl8x4B5U7qqGLBp6PatOhrlAaHoyPz6wgamYsPK2Lwwc1ak5nJrbQ1HQgQ9MIlG/obnulh/JkgIYaUUWKFelyK19ociECUdwgaHay0p9mYn9dqTOc8xASU9TcHtQ7ovjL0V92pFHAeDxjBNLrhbA2ibqAdg33tTYBoewNzVZHkaP3tO1OovOMTbAhzXln+n1JRB6p3PWs+pkRvrKl7BfprS3IguU1ye1Ph5pDgP0/iy1wMShqnZTA+hkFqjPt9sPqvWEgV5qgYkvxZHLSsBEL7XARLHXBfeEhbPQEi8qaw8LvdQiR+VOJh1XHT2aHHfWr2WzefRA2xFcYEillian7+QCK72UpwmQe/5XvhtJrv3TGcx0/swdRSJ1q16U7jjoHMdWVQfw87URU53gUkN/VGTqwGas2FIj29NhV26Y637YFBReapBdxbGx8UV82lB92ii1XlPYiy41NvqzGWxu+vcypEG3wP7dx5KRWmpis1ObXR8rneBiQ9WBXIUHdqzcUjMPRfOr34DOkktN1d6m6ktN/dv8JM/H1FlyjilYM/7R0MuC+v9ziK37Xcmct3WKVr0Qs7zorjDbcfaWpMcNSUQlo7chuvSjx0sQobr2rXmUsvbRXFVm/6XfMDiymjKiL7K0jumeXGe5MXCLrhVnb4+O9gU1fpEOjR4pjfZm+ohpuiuEN/g5wv+TDyyF/+WQvwj0F8J7OdTTKBtG93X/8yiqG1jmhS6Dk2o9xjboMmOc/3UtaXjiN7WeRvmfuJBGJ37s4ml04mcvpGWfH8D4jnnspzD0sCd/FONpWjVu7jboXbaT5lGrF+hC+wKDmV3oW83uwiCGybf64m54v8p33s/ESdWePxMf9J3bUFZ3+6oxyu6e3Fe9THeFbHxhhw6700PJ/+6E6Ynb6sIuTKfXYQc886uP+Wq3HXmnA20etrnQ/PgrJWjzHq+UGDFPlEdQcrpMIqRfslzi1PuWTdRgLiuf2B7NKaNmdMunnGL75F1WjXfIubphjs3bZiP+QcnNuOjGUYes2gkSkew2N+U6YFg/4HvgtHuhbizowVLjVC4wLTyyAJR70fgfKPaOfKfrF8b8sBezot2nK15xPuyHf4S7nfjtWunfFn9effv3+eTq2yt5E9xkqvHnsthtlaJPV934qqcnre639tmvxUbVQlrCinyzvrr+tL6O5M16Hfz22/WnroV5YP6HERPqL0GJCUdMqr8kJSYdsUD9FVBigSMWqr9CSix0xCL1V0SJRY5YrP6KKbHYEUvUXwklljhiqforpcRSR0yB8imjxDJ3evVsCxIHgYAwSNBQuFgIPeeCREO4cAg97YIERLiICD3zgsREuKAIPfmChEW4uAg9/4JERrjQCA2BIMERLjpCoyBIfIQLkNBACBIi4WIkNRCSxEi6GEkNhCQxkiheTMDQEeNiJDUQksRIuhhJDYQkMZIuRlIDIUmMpIuR1EBIEiPpYiQ1EJLESLoYSQ2EJDGSLkZSAyFJjKSLUaCBCEiMAhejQAMRkBgFLkaBBiIgMQpQWjN5jU5sLkaBBiIgMQpcjAINREBiFLgYBRqIgMQocDEKNBBBch0EN1EYuZIuRoEGIiAxClyMAg1EQGIUuBiFGoiQxCh0MQo1ECGJUehiFGogQhKj0MUo1ECEJEYhWn3M8hNeh/FNmrmzFLoYhRqIkMQodDEKNRAhiVHoYhRqIMKEtO5iFGogQhKj0MUo1ECE2XUQ3sRR4kq6GEUaiGh9HUQ32TpzF1UXo0gDEYnrUNyshaszcjGKNBCRvA6V16F12oUo0jhEAanShSgK2QFFqEaI2OmMXIgijUNEhmbkQhRpHCK68nAhijQOqkqnrLsQRTxEkQtRbCAiE23sQhQbiFLKeuxCFBuIMlLSxSgOWAeJXYxiDUSsJJObIHQFXYhijUNMRnuMKjlTylGeFLsIxRqGmAz22EUo1jDEJOqxi1CsYYhJ1GMXoYQPosRFKBHcHCUuQIlGISbzR+IClGgUYrqQdQFKDEBk/khchBKDEJnjExehROOQkDk+QeW2qbdJ1BMXoiTl8kfiIpTwMZS4CKUahoRcNlIXoVSwi0HqQpRqHBLS51IXojRg+5m6EKUh5/Cpi1AasS6XugilMedyqQtQagAiIyNFWyINQ0JGRuoilGbsopG6CGUGIdLhMxehTLC5K3MRyiSbDzMXoUzDkJBBlLkIZfxKlLkQZRqHhAy3zIUoM0GUEahnLkSZxiEloy1zIcrMtpWMtgxtXDUOqSQnCe9dNRApvX1co93rWrAOap9BWcm5qH0ERTUaaUhMlX0ERTUcaUSKoi3sWuOR0jvTNdrEruORgaFt7DrhB4b2seuUHxjayK4zfmAIMcMppPRGesA3CC73CEw4GFqBDmuBKQfBFxACkw6CLSEEZh0Mt0BPAqYdDLlATy3mHQy7kNJ0AmYeDL+Q0oQC5h4Mw5CtqSATiH0QhmOgq2KB+AdhWIZMkHolZokkW5sKxEEIwzRkDKWEQDNcQ0ZnBcRDCMM2ZDSthJgIYfiGjCaWEBchDOOQ0QGM2AhhOIeMjgnERwjDOtAbaIEYCWF4h4z2HcRJCMM8ZLTvIFZCGO5B5VdaGBN8huFb07Qh4iaEYSBUir0OMuVqAgkj6AwJoZIs6ZeIoRCGh1Bplu4GAs9QESrP0sIIPcNGqERLCyP4DCGhUi0tjPALLTVLA4gIC2FoCZVuyWhCnIUwzIRgWF9EWwhDTgiG+A0xS2sQZLhfRF4IQ1EIhv5F/IUwLIXgGGCEoCEqVN6lZwMhaLgKlXlpYYRgmI24KOIyhGEsBMMbIzpDRJZfp+FGjIaILIJ0wCJWQxjuQtAEskDEhjD0haA5ZBFhqt0gSNPIAtEbwpAYgmaSBWI4RJSMzDMiOYShMgTNPAvEcwjDZgiafBaI6hDxeqQbiO0QhtMQNFktEOEhYjnioojzEHEw4qKI9hDxWBZF1IeILYK0i8b4vMQiSLsoYkCE4TkETZ4LRIIIQ3UImj8XiAcRhu0QNIUuEBUiLBdCl4aIDBGG82BWV8SHCMN6MFURYkREYo+56DBBpIgw1IegyXyBeBFh2A9B8/kCUSPCECBqaSS9KMEnXgY+mtUXiCARiYWPOSBD8CUWPtqLEE8iDBsiaHpfIKpEpGKkJEBsiTCcCDcbiDARhhYR9NmBQJyJSO1ZJe2fiDcRhh0R9AmCQNSJMAyJoA8RBKJPhCFJaGZAIAJFGJpELdC0YgSgYUoEfewgEI0iDFki6JMHgZgUYfgStUDTwghAQ5kI+vxBID5FZBZA5rgVAWiIE7VA08IIQMOdMNOMeBVh6BO1mNOKEX6GQdEvKCGFEYCGRFGLOS2MT54NgPRRg0AkizREiqBPGyRiWaRhUtRiTgujI+i15MNVIqJFGjZF0McOElEtcm0BpI94Edki1/bCAH3Ki9gWubZ3BpjDeHQibTgVQZ8sSES4SMOqqJWfFkbn0oZXEfQBg0Ski7R3POgzBolYF2mvedDHDBLxLtLe9KCPBSQiXqS97EGfDEjEvEh734Pez0jEvUh75YM+SZCIfZHtrQ8absS/yPbiBw03ImCkvfuRCKrwkoiBkfb6R0LynBJfADE0i6C5fYnvgBieRdDEuRxcAxmLQXwTxDAtgibaJb4MYqgWkkSW+DaIYVoETbZLfCHEUC2C5sYlvhMiLX60Z+BrIdLiR3sGvhli2BZBc98SUTHS0C2Cpr8l4mKk4VtUBUILI/wsGUNz4BKRMdKSMSntGYiMkZaMSWmwERkjLRlDM9YSkTHSkjE0CywRGSMtGcMEFSJjpCVj0pT0ZkTGyIDn0iTiYqTlYmhyVSIuRlouhuky4mKk5WKYLiMuRhq6hekyomKkpWIy2kERFSMN28IpRvAZsoU8DpWIh5GGaqFpZoloGGmYFnpDJRELIw3RQtPMEpEw0pIwGR17iISRloShiWaJSBhpSRiaaZaIhJGGZ6GPtSTiYKTlYGhaWiIORloOhualJeJgpKFZGJwRBSMtBUOT2BJRMNKwLHS2RwSMtAQMTXhLRMBIS8AwsYQIGGkJGCaWEAEjDcfCTAXiX6TlX2guXSL+RVr+hVnZEf8iLf9CM+8S8S/SUCySZt4l4l+koVgkzbxLxL/IeKx0QfyLtPwLN80IQMOxMNPc8i/mZvmX4tgU27f2hvmnT+dX6v19dddeO1d7LKNTX0BXQf7t3/9cX6lgsP9t/07a/6otuflv1j7XG177D7UlU//4p7+grv/Svcrblxv0BvVKebao18exhu29/r51lvaN9XnLWOMaNkxhQ5FwDbfbg3kREehvDPsrWJP2pYqgHZxZvRlm2plPrPXN+h9//H2lYtxOryoZ+dbmRwfArvJkMEV8y2P+7DhCAByB7W33216nJZjaMJ1qef7YMcAG9DhjoQE/KwbTBXodBd10rdt/JNL+Q053C8dFAAYVTLZuf+LdN1eVdD8kdjZPTfWUa1cdhkn/xl9lnwXxrGDTv/sD6BBAh5jU0f6WZuDJAZhjPl6xGvNjyPNPoYG2CGhj08ZAm/nZjKMHBIoqbz31NKWbTwIQ3EHIaDGfN8rNd4dAnAkwu4KNGPshARieEoZnl0m71KtPYew/4s6JY7ZbKFOFQHPIucwm3+2G3pYBd9XH41xb+75dmORimOS45GhfZgqaRXAS2JDfFPqnV7BhDOY85pzn/HEdCBZM/xEXC+17oUA7GMd6H8y0q3aV208wLQkLBRWzem8IlkcO+/NbwEFLGFn65KFdo0fMt68SfjKvEoaoQnfI2Nkyb7eCk5XCyWJRVWuWKkru8sZJ5KBtLNo6g+v6Nm8cN0zAyFPOe9v3xsMJg05hixyy3eb4fHA6C9DlXKJ7dSKMfFgQhO0YNe3GaQBfKQa2wWIZt+kjaZWlHehr2f2jSycjZr44K6qAMSbXHIr2Y2zDpAgDO2Rtdm+uhGZhpAkunVLvWwBKMlirRaz58zfeYM8D2HMut4AXCkLHh2YlFy/dG0HhoGM4aM7di/3AA4HDc10t9tvzu5dh6oXjzLhgKfTvWUvlgeRyIWDW5yKgaL95Duo8mFbYSrrof0oL1mnQNOh8WnaLZuf/mmFqC76g+0fU/iNqY0NvQ+0/kvEeUFsX0P/RmWsb1+aT8HAG4OSvx+0zUw+TPA99p6BWayjyVZjzRts/FA1ddDtBzjttq6N/JQ9MvbAImtTQ4ICDW5zxWazZQcDyjQ/ZVgeRa0KYL6baD4YAXGnck7rGg50w2GCMK9CtD/kxf3LGDxdrdvsONAx9GSaBNavh6BRGGWzElgiq0VP3sgPo+nCJWLNuY1/DCr3F8baoK4y6pNEtlpLdZhuVVI/W0AnYXUj7Ooi+nYR7dM0xjbQbUCCa1wKN2YnXjQF+rgpon12mjQpuH6cpWrDWslNnvxae1897J3zAxLHmbdPj+dPRwI3gvEt2CqwCbBpuZ5mW4GuVMO3BtBONtjVfm4TJBtZ+7GR9VlWJ4yghSFIhl6QeikoVVE2+3xT3RfO1KPaHqtw3tetxMHSmFTUVJqacEXAZR2kwtst9XW4LrELCypIfTeOGGMwYLBOjWt0/DyIF7oj1tR+27bBWAamGy1Kq3Re8XYShye6jz19khg4CfYvdvT8Wf8rczahgiGyrcrst3P0+zIiSC0D9ZpPozny+zN3oSVgIsenLfk8cQglrl4CbVt2Minl93x0058Kv3LgFE9xP658EtfuirnRkayi3/ozBNMdtJZl2ytjyoXxCCwakS0Ju3kyrO/3yGTgMmPHWHdO57hhitgq332ODlZdTAHIuWroLVgD8OuCCv2wKVGIAn064DtpP1ULngr4Zcc12+X3hTFAMfDLhPNp9PyNMbjA1RVyCdN+tCJvDKGTppR2iPOAmjosG870+CB9MhwnfyomBCDgPO6NPuROtIegdux1+yo/1Y+7gADDnppGqpCBXra8bj7Y0iclNn041zg7RNq+fkMfBxhEXEm3j5vz9cGgeBhXrPp0GdNSgL4qDsbNzbVt/7T7/CxU4+3HO/YZ7mASEGssT2mZoP54Ah0/58eqWmqwrEXmfALRZJ7bNq8PgLC8G2Sjhpwu0xvZj4NwjzqY1OJYzZ+fLLUFP9ltFcOcC6wJ2r2TadV9Kgq0hS7Rm4TVvu4dsBUxK7PmPbjbYoAQgitlTVlxuRaBR1J5exO1KlbR/p93uay26f3ScJcsDgFdrAg+C+9+O2pHtiizZIFa6yOwD1xx29eg+XwsbQodIuBHor1rAKhHiye5ewAtN4UoD27KrBhE0kKNM2XYnxw0yWDuxpx/2e3h1+z086Lcwp2dc8/OLBOEMOTuFtsiRHfEnz+R5d0imb1Mw2u2n3WGydBg0LvhVu6YitoAQ74iDzjbGe0C4/REsOe28xxcCD8+FeMsVqtzgUU7Yzt9I693zAyodQPuYywTtF8EgQQzJgTU7yZW7QQjhQswe5ByqGm0R4frJlqeHI5oaWGiyufz8YQ+YWJ2G3Lo5WKXhZl6kLP6qmT3tHtJG8JiBb48mB+7VQg5B800mGIBwiCxhcNSFtJtlQHpij4PVElftToODLTA6NpzPn/GCvgYXV3YjRK2r8LxyzU1o95VfiCRcLlLOov0oOFwsoHuzhYtuRrKfMAGwZwfkkQ+0m3HxQfH0cFskZJd1wykVd4P7MClQxB461UNCBV4NkpK1+3u5U1ue0hCeTsRAhFmztvUuP+1dnGFZza5+bet23hHksLJn2e72G7kQMEgGZaxj4uIAsrpCnI/CWLuG1ndQghwfe8LVfh4TRqDDLrIz1VSHsUsHMFGxR/9198ly2BKOO+UyufvVADBosKRn3aSx7G6t9gR7Z0sOrbP59fzBNphjYUCzC9D5c55wvmFlv2ZxMh9WHN5nhDHB0l9gCdKPcpTKIDugf504pqS9ekXlNHidU8bcFDQ5ykrQTdmNDblRl7BpzEVG13R4/CqdKoxt/nTYodiEhSN7zoRvp8F6KGz3Nik73rJBtwucY/qwowr5abZvboceCjt9TijshbRG1QM1Hji818FukJruW2Mw9cPsy94UdF8ADptD1wq6LUTYnfXF5y0E57zwOqQGhvJfeKNBsud/xI1IMhigMnZj4lyIJNRISJNL3sX7+5DkwGBNxWY1zGTBDV/U3Uk6M+3dnST23sVpT/CJsALh2rXfCYT9h5PAMhgtlYuvooGxd5dF2Etwp7o4llt0lgOTY3i+0MlF/aBYgrcjo7YDydmDOS87f9IY5nqYrthjiq/50W0G6X7B0nsUEwmJI8FW8X9JynMFPC+Q7OWUv8qH+6KQJG8F0ztbLf5VVS4ZCKp5Ol5+u746lIdiV+6V0Kff/vnn/wBJT40EAs0AAA=="; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/api/typedoc/enums/AttributeType.html b/api/typedoc/enums/AttributeType.html index e3c2dfad6..94117049c 100644 --- a/api/typedoc/enums/AttributeType.html +++ b/api/typedoc/enums/AttributeType.html @@ -1,4 +1,4 @@ -AttributeType | Documentation

Enumeration AttributeType

Enumeration Members

ARRAY +AttributeType | Documentation

Enumeration AttributeType

Enumeration Members

ARRAY BOOL FLOAT IMAGE @@ -7,4 +7,4 @@ POINT STRING TIME -

Enumeration Members

ARRAY: "array"
BOOL: "bool"
FLOAT: "float"
IMAGE: "image"
INT: "int"
MAP: "map"
POINT: "point"
STRING: "string"
TIME: "time"

Generated using TypeDoc

\ No newline at end of file +

Enumeration Members

ARRAY: "array"
BOOL: "bool"
FLOAT: "float"
IMAGE: "image"
INT: "int"
MAP: "map"
POINT: "point"
STRING: "string"
TIME: "time"

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/enums/MessageType.html b/api/typedoc/enums/MessageType.html index f9d2a4984..b87becf4e 100644 --- a/api/typedoc/enums/MessageType.html +++ b/api/typedoc/enums/MessageType.html @@ -1,5 +1,5 @@ MessageType | Documentation

Enumeration MessageType

Message type, which determines its format.

-

Enumeration Members

Enumeration Members

Enumeration Members

HTML5_NOTIFY: "html5_notify"
TELEGRAM: "telegram"
WEBPUSH: "webpush"

Generated using TypeDoc

\ No newline at end of file +

Enumeration Members

HTML5_NOTIFY: "html5_notify"
TELEGRAM: "telegram"
WEBPUSH: "webpush"

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/BleRead.html b/api/typedoc/functions/BleRead.html new file mode 100644 index 000000000..af57e937f --- /dev/null +++ b/api/typedoc/functions/BleRead.html @@ -0,0 +1,3 @@ +BleRead | Documentation

Function BleRead

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/BleWrite.html b/api/typedoc/functions/BleWrite.html new file mode 100644 index 000000000..83e47ebad --- /dev/null +++ b/api/typedoc/functions/BleWrite.html @@ -0,0 +1,5 @@ +BleWrite | Documentation

Function BleWrite

  • Write replaces the characteristic value with a new value. The call will return after all data has been written.

    +

    Parameters

    • char: string

      UUID Device characteristic.

      +
    • payload: Uint8Array

      Command.

      +
    • withResponse: boolean

      if a response is expected.

      +

    Returns BleResponse

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/Decrypt.html b/api/typedoc/functions/Decrypt.html index 663c809ea..6f28f8a85 100644 --- a/api/typedoc/functions/Decrypt.html +++ b/api/typedoc/functions/Decrypt.html @@ -3,4 +3,4 @@

Returns string

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/Encrypt.html b/api/typedoc/functions/Encrypt.html index 2e84ec124..956deb21b 100644 --- a/api/typedoc/functions/Encrypt.html +++ b/api/typedoc/functions/Encrypt.html @@ -3,4 +3,4 @@

Returns string

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntitiesCallAction.html b/api/typedoc/functions/EntitiesCallAction.html index 8c2bd7500..d05ae61bc 100644 --- a/api/typedoc/functions/EntitiesCallAction.html +++ b/api/typedoc/functions/EntitiesCallAction.html @@ -1,4 +1,4 @@ EntitiesCallAction | Documentation

Function EntitiesCallAction

  • Function to call an action on an entity (version 2).

    Parameters

    • params1: CallAction

      Parameters for calling the action.

    • Optional params2: {
          [key: string]: any;
      }

      Additional parameters.

      -
      • [key: string]: any

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityCallAction.html b/api/typedoc/functions/EntityCallAction.html index 150d2e1a9..f6f9bbb4f 100644 --- a/api/typedoc/functions/EntityCallAction.html +++ b/api/typedoc/functions/EntityCallAction.html @@ -2,4 +2,4 @@

Parameters

Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityCallScene.html b/api/typedoc/functions/EntityCallScene.html index 50929baea..64a6f03c5 100644 --- a/api/typedoc/functions/EntityCallScene.html +++ b/api/typedoc/functions/EntityCallScene.html @@ -1,4 +1,4 @@ EntityCallScene | Documentation

Function EntityCallScene

  • Calls the entity script.

    Parameters

    • entityId: string

      Entity identifier.

    • params: {
          [key: string]: any;
      }

      Parameters for the script.

      -
      • [key: string]: any

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityCallScript.html b/api/typedoc/functions/EntityCallScript.html new file mode 100644 index 000000000..26998eb40 --- /dev/null +++ b/api/typedoc/functions/EntityCallScript.html @@ -0,0 +1,5 @@ +EntityCallScript | Documentation

Function EntityCallScript

  • Calls a function or method of an entity's script.

    +

    Parameters

    • entityId: string

      Entity identifier.

      +
    • fn: string

      The name of the function.

      +
    • payload: any

      Parameters for the action.

      +

    Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityGetAttributes.html b/api/typedoc/functions/EntityGetAttributes.html index 83316c2a0..1d39e674a 100644 --- a/api/typedoc/functions/EntityGetAttributes.html +++ b/api/typedoc/functions/EntityGetAttributes.html @@ -3,4 +3,4 @@

Returns AttributeValue

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityGetSettings.html b/api/typedoc/functions/EntityGetSettings.html index 5d9b0bb39..9e0727daa 100644 --- a/api/typedoc/functions/EntityGetSettings.html +++ b/api/typedoc/functions/EntityGetSettings.html @@ -3,4 +3,4 @@

Returns AttributeValue

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntityGetState.html b/api/typedoc/functions/EntityGetState.html index 3d0369812..70ff03b5a 100644 --- a/api/typedoc/functions/EntityGetState.html +++ b/api/typedoc/functions/EntityGetState.html @@ -3,4 +3,4 @@

Returns EntityStateShort

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntitySetAttributes.html b/api/typedoc/functions/EntitySetAttributes.html index 290064c42..cf8568773 100644 --- a/api/typedoc/functions/EntitySetAttributes.html +++ b/api/typedoc/functions/EntitySetAttributes.html @@ -1,4 +1,4 @@ EntitySetAttributes | Documentation

Function EntitySetAttributes

  • Sets the attributes of an entity.

    Parameters

    • entityId: string

      Entity identifier.

    • params: AttributeValue

      Attributes to set.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntitySetMetric.html b/api/typedoc/functions/EntitySetMetric.html index a6653a1ab..ebb28b4be 100644 --- a/api/typedoc/functions/EntitySetMetric.html +++ b/api/typedoc/functions/EntitySetMetric.html @@ -1,4 +1,4 @@ EntitySetMetric | Documentation

Function EntitySetMetric

  • Sets the entity metric.

    Parameters

    • entityId: string

      Entity identifier.

    • params: {
          [key: string]: any;
      }

      Metric parameters.

      -
      • [key: string]: any

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntitySetState.html b/api/typedoc/functions/EntitySetState.html index a6949cfe5..85d958518 100644 --- a/api/typedoc/functions/EntitySetState.html +++ b/api/typedoc/functions/EntitySetState.html @@ -1,4 +1,4 @@ EntitySetState | Documentation

Function EntitySetState

  • Sets the state of an entity.

    Parameters

    • entityId: string

      Entity identifier.

    • params: EntityStateParams

      Parameters for setting the state.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/EntitySetStateName.html b/api/typedoc/functions/EntitySetStateName.html index 09c217e5f..3461ec01d 100644 --- a/api/typedoc/functions/EntitySetStateName.html +++ b/api/typedoc/functions/EntitySetStateName.html @@ -1,4 +1,4 @@ EntitySetStateName | Documentation

Function EntitySetStateName

  • Sets the entity state name.

    Parameters

    • entityId: string

      Entity identifier.

    • state: string

      State name.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/ExecuteAsync.html b/api/typedoc/functions/ExecuteAsync.html index c5799b516..158963aeb 100644 --- a/api/typedoc/functions/ExecuteAsync.html +++ b/api/typedoc/functions/ExecuteAsync.html @@ -4,4 +4,4 @@

Returns ExecuteResponse

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/ExecuteSync.html b/api/typedoc/functions/ExecuteSync.html index 1d7e6e140..cede767c8 100644 --- a/api/typedoc/functions/ExecuteSync.html +++ b/api/typedoc/functions/ExecuteSync.html @@ -4,4 +4,4 @@

Returns ExecuteResponse

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/GeoDistanceBetweenPoints.html b/api/typedoc/functions/GeoDistanceBetweenPoints.html index d463d704d..8462280f4 100644 --- a/api/typedoc/functions/GeoDistanceBetweenPoints.html +++ b/api/typedoc/functions/GeoDistanceBetweenPoints.html @@ -4,4 +4,4 @@

Returns number

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/GeoDistanceToArea.html b/api/typedoc/functions/GeoDistanceToArea.html index fefe9c628..7ec8a232f 100644 --- a/api/typedoc/functions/GeoDistanceToArea.html +++ b/api/typedoc/functions/GeoDistanceToArea.html @@ -4,4 +4,4 @@

Returns number

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/GeoPointInsideArea.html b/api/typedoc/functions/GeoPointInsideArea.html index 9a0479d65..fe168d872 100644 --- a/api/typedoc/functions/GeoPointInsideArea.html +++ b/api/typedoc/functions/GeoPointInsideArea.html @@ -4,4 +4,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/GetEntity.html b/api/typedoc/functions/GetEntity.html index 8783973ae..2f745629f 100644 --- a/api/typedoc/functions/GetEntity.html +++ b/api/typedoc/functions/GetEntity.html @@ -3,4 +3,4 @@

Returns Entity

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/PushSystemEvent.html b/api/typedoc/functions/PushSystemEvent.html index a3872427c..36a066617 100644 --- a/api/typedoc/functions/PushSystemEvent.html +++ b/api/typedoc/functions/PushSystemEvent.html @@ -1,4 +1,4 @@ PushSystemEvent | Documentation

Function PushSystemEvent

  • Function to send a system event.

    Parameters

    • command: SystemEventCommand

      System event command.

    • params: {
          [key: string]: any;
      }

      Parameters for the system event.

      -
      • [key: string]: any

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationAction.html b/api/typedoc/functions/automationAction.html index 9e334dac5..15d67a2ee 100644 --- a/api/typedoc/functions/automationAction.html +++ b/api/typedoc/functions/automationAction.html @@ -1,3 +1,3 @@ automationAction | Documentation

Function automationAction

  • A function called when an automation action is executed.

    Parameters

    • entityId: string

      The ID of the entity associated with the automation action.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationCondition.html b/api/typedoc/functions/automationCondition.html index 56f264a38..c5dcb576c 100644 --- a/api/typedoc/functions/automationCondition.html +++ b/api/typedoc/functions/automationCondition.html @@ -3,4 +3,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationTriggerAlexa.html b/api/typedoc/functions/automationTriggerAlexa.html index 74f030180..9e7501860 100644 --- a/api/typedoc/functions/automationTriggerAlexa.html +++ b/api/typedoc/functions/automationTriggerAlexa.html @@ -3,4 +3,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationTriggerBle.html b/api/typedoc/functions/automationTriggerBle.html new file mode 100644 index 000000000..92ceef9ac --- /dev/null +++ b/api/typedoc/functions/automationTriggerBle.html @@ -0,0 +1,6 @@ +automationTriggerBle | Documentation

Function automationTriggerBle

  • Function called when the Ble trigger event occurs.

    +

    Parameters

    Returns boolean

      +
    • The result of the trigger execution.
    • +
    +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationTriggerStateChanged.html b/api/typedoc/functions/automationTriggerStateChanged.html index cbbf386ac..6cbede1b2 100644 --- a/api/typedoc/functions/automationTriggerStateChanged.html +++ b/api/typedoc/functions/automationTriggerStateChanged.html @@ -3,4 +3,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationTriggerSystem.html b/api/typedoc/functions/automationTriggerSystem.html index 3f8e20234..9c280547e 100644 --- a/api/typedoc/functions/automationTriggerSystem.html +++ b/api/typedoc/functions/automationTriggerSystem.html @@ -3,4 +3,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/automationTriggerTime.html b/api/typedoc/functions/automationTriggerTime.html index 096f6fb07..349190d57 100644 --- a/api/typedoc/functions/automationTriggerTime.html +++ b/api/typedoc/functions/automationTriggerTime.html @@ -3,4 +3,4 @@

Returns boolean

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/entityAction.html b/api/typedoc/functions/entityAction.html index f1f23fc6b..ec7ea9898 100644 --- a/api/typedoc/functions/entityAction.html +++ b/api/typedoc/functions/entityAction.html @@ -2,4 +2,4 @@

Parameters

Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/hex2arr.html b/api/typedoc/functions/hex2arr.html index 772d30acd..b4aa59634 100644 --- a/api/typedoc/functions/hex2arr.html +++ b/api/typedoc/functions/hex2arr.html @@ -3,4 +3,4 @@

Returns number[]

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/marshal.html b/api/typedoc/functions/marshal.html index 30afc2856..39f7f6239 100644 --- a/api/typedoc/functions/marshal.html +++ b/api/typedoc/functions/marshal.html @@ -4,4 +4,4 @@

Returns string

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/mqttEvent.html b/api/typedoc/functions/mqttEvent.html index 370ed9d1f..cb3fe6189 100644 --- a/api/typedoc/functions/mqttEvent.html +++ b/api/typedoc/functions/mqttEvent.html @@ -1,4 +1,4 @@ mqttEvent | Documentation

Function mqttEvent

  • Function called on MQTT event.

    Parameters

    • entityId: string

      The ID of the entity associated with the MQTT event.

    • actionName: string

      The name of the action associated with the MQTT event.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/print.html b/api/typedoc/functions/print.html index b0478a44d..768edeb66 100644 --- a/api/typedoc/functions/print.html +++ b/api/typedoc/functions/print.html @@ -1,4 +1,4 @@ print | Documentation

Function print

  • Function to output a message to the console.

    Parameters

    • Optional message: any

      Message to display.

    • Rest ...optionalParams: any[]

      Additional parameters for output.

      -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/skillOnIntent.html b/api/typedoc/functions/skillOnIntent.html index 5a68f7628..e055f7dd6 100644 --- a/api/typedoc/functions/skillOnIntent.html +++ b/api/typedoc/functions/skillOnIntent.html @@ -1,2 +1,2 @@ skillOnIntent | Documentation

Function skillOnIntent

  • Function called when an Alexa skill intent is received.

    -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/skillOnLaunch.html b/api/typedoc/functions/skillOnLaunch.html index e944640db..ee71fa2ee 100644 --- a/api/typedoc/functions/skillOnLaunch.html +++ b/api/typedoc/functions/skillOnLaunch.html @@ -1,2 +1,2 @@ skillOnLaunch | Documentation

Function skillOnLaunch

  • Function called when the Alexa skill is launched.

    -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/skillOnSessionEnd.html b/api/typedoc/functions/skillOnSessionEnd.html index c508db193..01741eed7 100644 --- a/api/typedoc/functions/skillOnSessionEnd.html +++ b/api/typedoc/functions/skillOnSessionEnd.html @@ -1,2 +1,2 @@ skillOnSessionEnd | Documentation

Function skillOnSessionEnd

  • Function called when the Alexa skill session ends.

    -

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/telegramAction.html b/api/typedoc/functions/telegramAction.html index b0e89d253..6cb8238f9 100644 --- a/api/typedoc/functions/telegramAction.html +++ b/api/typedoc/functions/telegramAction.html @@ -2,4 +2,4 @@

Parameters

Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/template.html b/api/typedoc/functions/template.html index 3ba3606c8..4b93bf052 100644 --- a/api/typedoc/functions/template.html +++ b/api/typedoc/functions/template.html @@ -4,4 +4,4 @@

Returns any

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/unmarshal.html b/api/typedoc/functions/unmarshal.html index b911374e8..83140c7e8 100644 --- a/api/typedoc/functions/unmarshal.html +++ b/api/typedoc/functions/unmarshal.html @@ -5,4 +5,4 @@

Returns any[]

-

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/functions/zigbee2mqttEvent.html b/api/typedoc/functions/zigbee2mqttEvent.html index 67bf308f5..2f7dded54 100644 --- a/api/typedoc/functions/zigbee2mqttEvent.html +++ b/api/typedoc/functions/zigbee2mqttEvent.html @@ -1,3 +1,3 @@ zigbee2mqttEvent | Documentation

Function zigbee2mqttEvent

  • Function called on Zigbee2mqtt event.

    Parameters

    Returns void

Generated using TypeDoc

\ No newline at end of file +

Returns void

Generated using TypeDoc

\ No newline at end of file diff --git a/api/typedoc/index.html b/api/typedoc/index.html index e1868a53b..172d43cbe 100644 --- a/api/typedoc/index.html +++ b/api/typedoc/index.html @@ -1,9 +1,6 @@ Documentation

Documentation

smart home logo -

The Smart Home

Project site | -Node

-

Go Report Card -status +

The Smart Home

Go Report Card License: GPL v3 telegram group

@@ -74,7 +71,8 @@
  • Management web interface integrated into Smart home
  • Demo access

    dashboard:
    -dashboard (https://gate.e154.ru:8443)

    +dashboard (https://gate.e154.ru:8443)
    +dashboard (http://gate.e154.ru:8080)

    server id:
    cf4463fc-2f39-4271-a034-5c0c8087c56c

    user: admin@e154.ru
    @@ -133,4 +131,4 @@

  • Domoticz
  • LICENSE

    GPLv3 Public License

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Action.html b/api/typedoc/interfaces/Action.html index 295949cac..88262854f 100644 --- a/api/typedoc/interfaces/Action.html +++ b/api/typedoc/interfaces/Action.html @@ -1 +1 @@ -Action | Documentation

    Generated using TypeDoc

    \ No newline at end of file +Action | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Alexa.html b/api/typedoc/interfaces/Alexa.html index 67960a8af..cc47542cc 100644 --- a/api/typedoc/interfaces/Alexa.html +++ b/api/typedoc/interfaces/Alexa.html @@ -1,30 +1,30 @@ Alexa | Documentation

    Interface Alexa

    Interface for working with the Alexa skill.

    -
    interface Alexa {
        slots: {
            [key: string]: string;
        };
        card(title, content): Alexa;
        endSession(flag): Alexa;
        outputSpeech(text): Alexa;
        sendMessage(msg): void;
        session(): string;
    }

    Properties

    interface Alexa {
        slots: {
            [key: string]: string;
        };
        card(title, content): Alexa;
        endSession(flag): Alexa;
        outputSpeech(text): Alexa;
        sendMessage(msg): void;
        session(): string;
    }

    Properties

    slots: {
        [key: string]: string;
    }

    Type declaration

    • [key: string]: string

    Methods

    • Adds a card for the Alexa skill.

      +

    Properties

    slots: {
        [key: string]: string;
    }

    Type declaration

    • [key: string]: string

    Methods

    • Adds a card for the Alexa skill.

      Parameters

      • title: string

        Title of the card.

      • content: string

        Contents of the card.

      Returns Alexa

      • The Alexa object for the call chain.
      -
    • Sets the session end flag for the Alexa skill.

      Parameters

      • flag: boolean

        Session end flag.

      Returns Alexa

      • The Alexa object for the call chain.
      -
    • Sets the output speech for the Alexa skill.

      Parameters

      • text: string

        Speech text.

      Returns Alexa

      • The Alexa object for the call chain.
      -
    • Sends a message from the Alexa skill.

      +
    • Sends a message from the Alexa skill.

      Parameters

      • msg: any

        Message to send.

        -

      Returns void

    • Returns the current session status of the Alexa skill.

      +

    Returns void

    • Returns the current session status of the Alexa skill.

      Returns string

      • Session status.
      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/BleResponse.html b/api/typedoc/interfaces/BleResponse.html new file mode 100644 index 000000000..cbd4dd5ca --- /dev/null +++ b/api/typedoc/interfaces/BleResponse.html @@ -0,0 +1,4 @@ +BleResponse | Documentation

    Interface BleResponse

    Interface for responding to bluetooth commands.

    +
    interface BleResponse {
        error?: string;
        response?: Uint8Array;
    }

    Properties

    Properties

    error?: string
    response?: Uint8Array

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/CallAction.html b/api/typedoc/interfaces/CallAction.html index 7ba2c2284..c50bc20c3 100644 --- a/api/typedoc/interfaces/CallAction.html +++ b/api/typedoc/interfaces/CallAction.html @@ -1,6 +1,6 @@ CallAction | Documentation

    Interface CallAction

    Interface representing parameters for calling an action on an entity

    -
    interface CallAction {
        action_name: string;
        area_id?: number;
        entity_id?: string;
        tags?: string[];
    }

    Properties

    interface CallAction {
        action_name: string;
        area_id?: number;
        entity_id?: string;
        tags?: string[];
    }

    Properties

    action_name: string
    area_id?: number
    entity_id?: string
    tags?: string[]

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    action_name: string
    area_id?: number
    entity_id?: string
    tags?: string[]

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Camera.html b/api/typedoc/interfaces/Camera.html index a63cadaa1..fb5965946 100644 --- a/api/typedoc/interfaces/Camera.html +++ b/api/typedoc/interfaces/Camera.html @@ -1,8 +1,8 @@ Camera | Documentation

    Interface Camera

    Camera interface with control methods.

    -
    interface Camera {
        continuousMove(x, y): void;
        stopContinuousMove(): void;
    }

    Methods

    interface Camera {
        continuousMove(x, y): void;
        stopContinuousMove(): void;
    }

    Methods

    • Starts continuous camera movement along specified coordinates.

      Parameters

      • x: number

        X coordinate.

      • y: number

        Y coordinate.

        -

      Returns void

    • Stops continuous camera movement.

      -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    • Stops continuous camera movement.

      +

      Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Condition.html b/api/typedoc/interfaces/Condition.html index 7787bf5fd..c368999c8 100644 --- a/api/typedoc/interfaces/Condition.html +++ b/api/typedoc/interfaces/Condition.html @@ -1 +1 @@ -Condition | Documentation

    Generated using TypeDoc

    \ No newline at end of file +Condition | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Console.html b/api/typedoc/interfaces/Console.html index 5d4c6384d..1646f5086 100644 --- a/api/typedoc/interfaces/Console.html +++ b/api/typedoc/interfaces/Console.html @@ -1,5 +1,5 @@ Console | Documentation

    Interface Console

    Console output interface.

    -
    interface Console {
        debug(message?, ...optionalParams): void;
        error(message?, ...optionalParams): void;
        info(message?, ...optionalParams): void;
        log(message?, ...optionalParams): void;
        warn(message?, ...optionalParams): void;
    }

    Methods

    interface Console {
        debug(message?, ...optionalParams): void;
        error(message?, ...optionalParams): void;
        info(message?, ...optionalParams): void;
        log(message?, ...optionalParams): void;
        warn(message?, ...optionalParams): void;
    }

    Methods

    debug error info log @@ -7,16 +7,16 @@

    Methods

    • Prints a debug message to the console.

      Parameters

      • Optional message: any

        Message to display.

      • Rest ...optionalParams: any[]

        Additional parameters for output.

        -

      Returns void

    • Displays an error message to the console.

      +

    Returns void

    • Displays an error message to the console.

      Parameters

      • Optional message: any

        Message to display.

      • Rest ...optionalParams: any[]

        Additional parameters for output.

        -

      Returns void

    • Displays an informational message to the console.

      +

    Returns void

    • Displays an informational message to the console.

      Parameters

      • Optional message: any

        Message to display.

      • Rest ...optionalParams: any[]

        Additional parameters for output.

        -

      Returns void

    • Prints a message to the console with the level "log".

      +

    Returns void

    • Prints a message to the console with the level "log".

      Parameters

      • Optional message: any

        Message to display.

      • Rest ...optionalParams: any[]

        Additional parameters for output.

        -

      Returns void

    • Displays a warning to the console.

      +

    Returns void

    • Displays a warning to the console.

      Parameters

      • Optional message: any

        Message to display.

      • Rest ...optionalParams: any[]

        Additional parameters for output.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Entity.html b/api/typedoc/interfaces/Entity.html index 008465fd1..1df717a2c 100644 --- a/api/typedoc/interfaces/Entity.html +++ b/api/typedoc/interfaces/Entity.html @@ -1,4 +1,4 @@ -Entity | Documentation

    Interface Entity

    interface Entity {
        actions: EntityActionShort[];
        area?: Area;
        attributes: Attributes;
        description: string;
        hidden: boolean;
        icon?: string;
        id: string;
        image_url?: string;
        metrics: Metric[];
        name: string;
        settings: Attributes;
        state?: EntityStateShort;
        states: EntityStateShort[];
        type: string;
    }

    Properties

    actions +Entity | Documentation

    Interface Entity

    interface Entity {
        actions: EntityActionShort[];
        area?: Area;
        attributes: Attributes;
        description: string;
        hidden: boolean;
        icon?: string;
        id: string;
        image_url?: string;
        metrics: Metric[];
        name: string;
        settings: Attributes;
        state?: EntityStateShort;
        states: EntityStateShort[];
        type: string;
    }

    Properties

    Properties

    area?: Area
    attributes: Attributes
    description: string
    hidden: boolean
    icon?: string
    id: string
    image_url?: string
    metrics: Metric[]
    name: string
    settings: Attributes
    type: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    area?: Area
    attributes: Attributes
    description: string
    hidden: boolean
    icon?: string
    id: string
    image_url?: string
    metrics: Metric[]
    name: string
    settings: Attributes
    type: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/EntityActionShort.html b/api/typedoc/interfaces/EntityActionShort.html index ce668761f..ed19a82e2 100644 --- a/api/typedoc/interfaces/EntityActionShort.html +++ b/api/typedoc/interfaces/EntityActionShort.html @@ -1,5 +1,5 @@ -EntityActionShort | Documentation

    Interface EntityActionShort

    interface EntityActionShort {
        description: string;
        icon?: string;
        image_url?: string;
        name: string;
    }

    Properties

    description +EntityActionShort | Documentation

    Interface EntityActionShort

    interface EntityActionShort {
        description: string;
        icon?: string;
        image_url?: string;
        name: string;
    }

    Properties

    description: string
    icon?: string
    image_url?: string
    name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    description: string
    icon?: string
    image_url?: string
    name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/EntityStateParams.html b/api/typedoc/interfaces/EntityStateParams.html index 41edde475..263465048 100644 --- a/api/typedoc/interfaces/EntityStateParams.html +++ b/api/typedoc/interfaces/EntityStateParams.html @@ -1,5 +1,5 @@ -EntityStateParams | Documentation

    Interface EntityStateParams

    interface EntityStateParams {
        attribute_values?: AttributeValue;
        new_state?: string;
        settings_value?: AttributeValue;
        storage_save?: boolean;
    }

    Properties

    attribute_values? +EntityStateParams | Documentation

    Interface EntityStateParams

    interface EntityStateParams {
        attribute_values?: AttributeValue;
        new_state?: string;
        settings_value?: AttributeValue;
        storage_save?: boolean;
    }

    Properties

    attribute_values?: AttributeValue
    new_state?: string
    settings_value?: AttributeValue
    storage_save?: boolean

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    attribute_values?: AttributeValue
    new_state?: string
    settings_value?: AttributeValue
    storage_save?: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/EntityStateShort.html b/api/typedoc/interfaces/EntityStateShort.html index 0b5d95270..1c377a53f 100644 --- a/api/typedoc/interfaces/EntityStateShort.html +++ b/api/typedoc/interfaces/EntityStateShort.html @@ -1,5 +1,5 @@ -EntityStateShort | Documentation

    Interface EntityStateShort

    interface EntityStateShort {
        description: string;
        icon?: string;
        image_url?: string;
        name: string;
    }

    Properties

    description +EntityStateShort | Documentation

    Interface EntityStateShort

    interface EntityStateShort {
        description: string;
        icon?: string;
        image_url?: string;
        name: string;
    }

    Properties

    description: string
    icon?: string
    image_url?: string
    name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    description: string
    icon?: string
    image_url?: string
    name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/EventEntityState.html b/api/typedoc/interfaces/EventEntityState.html index c73e74928..a927d5446 100644 --- a/api/typedoc/interfaces/EventEntityState.html +++ b/api/typedoc/interfaces/EventEntityState.html @@ -1,9 +1,9 @@ EventEntityState | Documentation

    Interface EventEntityState

    Interface for the entity state change event.

    -
    interface EventEntityState {
        attributes: AttributeValue;
        entity_id: string;
        last_changed: Date;
        last_updated: Date;
        settings: AttributeValue;
        state: EntityStateShort;
        value: any;
    }

    Properties

    interface EventEntityState {
        attributes: AttributeValue;
        entity_id: string;
        last_changed: Date;
        last_updated: Date;
        settings: AttributeValue;
        state: EntityStateShort;
        value: any;
    }

    Properties

    attributes: AttributeValue
    entity_id: string
    last_changed: Date
    last_updated: Date
    settings: AttributeValue
    value: any

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    attributes: AttributeValue
    entity_id: string
    last_changed: Date
    last_updated: Date
    settings: AttributeValue
    value: any

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/EventStateChanged.html b/api/typedoc/interfaces/EventStateChanged.html index 686f9ba45..0ab2a1f9a 100644 --- a/api/typedoc/interfaces/EventStateChanged.html +++ b/api/typedoc/interfaces/EventStateChanged.html @@ -1,8 +1,8 @@ EventStateChanged | Documentation

    Interface EventStateChanged

    Interface for trigger state change event.

    -
    interface EventStateChanged {
        do_not_save_metric: boolean;
        entity_id: string;
        new_state: EventEntityState;
        old_state?: EventEntityState;
        plugin_name: string;
        storage_save: boolean;
    }

    Properties

    interface EventStateChanged {
        do_not_save_metric: boolean;
        entity_id: string;
        new_state: EventEntityState;
        old_state?: EventEntityState;
        plugin_name: string;
        storage_save: boolean;
    }

    Properties

    do_not_save_metric: boolean
    entity_id: string
    new_state: EventEntityState
    old_state?: EventEntityState
    plugin_name: string
    storage_save: boolean

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    do_not_save_metric: boolean
    entity_id: string
    new_state: EventEntityState
    old_state?: EventEntityState
    plugin_name: string
    storage_save: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/ExecuteResponse.html b/api/typedoc/interfaces/ExecuteResponse.html index 2318bfcc8..82bbc69ad 100644 --- a/api/typedoc/interfaces/ExecuteResponse.html +++ b/api/typedoc/interfaces/ExecuteResponse.html @@ -1,4 +1,4 @@ ExecuteResponse | Documentation

    Interface ExecuteResponse

    Response interface for command execution.

    -
    interface ExecuteResponse {
        err: string;
        out: string;
    }

    Properties

    err +
    interface ExecuteResponse {
        err: string;
        out: string;
    }

    Properties

    Properties

    err: string
    out: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    err: string
    out: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/HttpResponse.html b/api/typedoc/interfaces/HttpResponse.html index ab17ec759..3d00db626 100644 --- a/api/typedoc/interfaces/HttpResponse.html +++ b/api/typedoc/interfaces/HttpResponse.html @@ -1,5 +1,5 @@ HttpResponse | Documentation

    Interface HttpResponse

    Interface for responding to an HTTP request.

    -
    interface HttpResponse {
        body: string;
        error: boolean;
        errorMessage: string;
    }

    Properties

    interface HttpResponse {
        body: string;
        error: boolean;
        errorMessage: string;
    }

    Properties

    Properties

    body: string
    error: boolean
    errorMessage: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    body: string
    error: boolean
    errorMessage: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Message.html b/api/typedoc/interfaces/Message.html index cda915988..0d3bae031 100644 --- a/api/typedoc/interfaces/Message.html +++ b/api/typedoc/interfaces/Message.html @@ -1,5 +1,5 @@ Message | Documentation

    Interface Message

    Common message interface for different types of notifications.

    -
    interface Message {
        attributes: MessageHtml5 | MessageTelegram | MessageSMS | MessageWebpush;
        entity_id?: string;
        type?: MessageType;
    }

    Properties

    interface Message {
        attributes: MessageHtml5 | MessageTelegram | MessageSMS | MessageWebpush;
        entity_id?: string;
        type?: MessageType;
    }

    Properties

    entity_id?: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    entity_id?: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MessageHtml5.html b/api/typedoc/interfaces/MessageHtml5.html index b017e90c2..167f1a225 100644 --- a/api/typedoc/interfaces/MessageHtml5.html +++ b/api/typedoc/interfaces/MessageHtml5.html @@ -1,5 +1,5 @@ MessageHtml5 | Documentation

    Interface MessageHtml5

    Message interface for HTML5 notifications.

    -
    interface MessageHtml5 {
        body: string;
        title: string;
        userIDS?: string;
    }

    Properties

    interface MessageHtml5 {
        body: string;
        title: string;
        userIDS?: string;
    }

    Properties

    Properties

    body: string
    title: string
    userIDS?: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    body: string
    title: string
    userIDS?: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MessageSMS.html b/api/typedoc/interfaces/MessageSMS.html index 3a510ecb3..db70b4336 100644 --- a/api/typedoc/interfaces/MessageSMS.html +++ b/api/typedoc/interfaces/MessageSMS.html @@ -1,4 +1,4 @@ MessageSMS | Documentation

    Interface MessageSMS

    Message interface for SMS notifications.

    -
    interface MessageSMS {
        body: string;
        phone: string;
    }

    Properties

    interface MessageSMS {
        body: string;
        phone: string;
    }

    Properties

    Properties

    body: string
    phone: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    body: string
    phone: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MessageTelegram.html b/api/typedoc/interfaces/MessageTelegram.html index f4e377784..20b2e0bf0 100644 --- a/api/typedoc/interfaces/MessageTelegram.html +++ b/api/typedoc/interfaces/MessageTelegram.html @@ -1,9 +1,9 @@ MessageTelegram | Documentation

    Interface MessageTelegram

    Message interface for Telegram.

    -
    interface MessageTelegram {
        body: string;
        chat_id?: number;
        file_path?: string;
        file_uri?: string;
        keys?: string[];
        photo_path?: string;
        photo_uri?: string;
    }

    Properties

    interface MessageTelegram {
        body: string;
        chat_id?: number;
        file_path?: string;
        file_uri?: string;
        keys?: string[];
        photo_path?: string;
        photo_uri?: string;
    }

    Properties

    body: string
    chat_id?: number
    file_path?: string
    file_uri?: string
    keys?: string[]
    photo_path?: string
    photo_uri?: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    body: string
    chat_id?: number
    file_path?: string
    file_uri?: string
    keys?: string[]
    photo_path?: string
    photo_uri?: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MessageWebpush.html b/api/typedoc/interfaces/MessageWebpush.html index bf560be3a..9d327c2bc 100644 --- a/api/typedoc/interfaces/MessageWebpush.html +++ b/api/typedoc/interfaces/MessageWebpush.html @@ -1,5 +1,5 @@ MessageWebpush | Documentation

    Interface MessageWebpush

    Message interface for Web Push notifications.

    -
    interface MessageWebpush {
        body: string;
        title: string;
        userIDS?: string;
    }

    Properties

    interface MessageWebpush {
        body: string;
        title: string;
        userIDS?: string;
    }

    Properties

    Properties

    body: string
    title: string
    userIDS?: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    body: string
    title: string
    userIDS?: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MetricDataItem.html b/api/typedoc/interfaces/MetricDataItem.html index 3210f8369..fd46a54f2 100644 --- a/api/typedoc/interfaces/MetricDataItem.html +++ b/api/typedoc/interfaces/MetricDataItem.html @@ -1,4 +1,4 @@ -MetricDataItem | Documentation

    Interface MetricDataItem

    interface MetricDataItem {
        metric_id: number;
        time: Date;
        value: {
            [key: string]: any;
        };
    }

    Properties

    metric_id +MetricDataItem | Documentation

    Interface MetricDataItem

    interface MetricDataItem {
        metric_id: number;
        time: Date;
        value: {
            [key: string]: any;
        };
    }

    Properties

    Properties

    metric_id: number
    time: Date
    value: {
        [key: string]: any;
    }

    Type declaration

    • [key: string]: any

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    metric_id: number
    time: Date
    value: {
        [key: string]: any;
    }

    Type declaration

    • [key: string]: any

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MetricOptions.html b/api/typedoc/interfaces/MetricOptions.html index 579eb9ebc..36177e719 100644 --- a/api/typedoc/interfaces/MetricOptions.html +++ b/api/typedoc/interfaces/MetricOptions.html @@ -1,2 +1,2 @@ -MetricOptions | Documentation

    Generated using TypeDoc

    \ No newline at end of file +MetricOptions | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MetricOptionsItem.html b/api/typedoc/interfaces/MetricOptionsItem.html index 6b3a161b5..4c2440537 100644 --- a/api/typedoc/interfaces/MetricOptionsItem.html +++ b/api/typedoc/interfaces/MetricOptionsItem.html @@ -1,6 +1,6 @@ -MetricOptionsItem | Documentation

    Interface MetricOptionsItem

    interface MetricOptionsItem {
        color: string;
        description: string;
        label: string;
        name: string;
        translate: string;
    }

    Properties

    color +MetricOptionsItem | Documentation

    Interface MetricOptionsItem

    interface MetricOptionsItem {
        color: string;
        description: string;
        label: string;
        name: string;
        translate: string;
    }

    Properties

    color: string
    description: string
    label: string
    name: string
    translate: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    color: string
    description: string
    label: string
    name: string
    translate: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Miner.html b/api/typedoc/interfaces/Miner.html index b508e0da7..bc3f1b407 100644 --- a/api/typedoc/interfaces/Miner.html +++ b/api/typedoc/interfaces/Miner.html @@ -1,5 +1,5 @@ Miner | Documentation

    Interface Miner

    Miner interface with control methods.

    -
    interface Miner {
        addPool(url): MinerResult;
        delete(poolId): MinerResult;
        devs(): MinerResult;
        disable(poolId): MinerResult;
        enable(poolId): MinerResult;
        pools(): MinerResult;
        restart(): MinerResult;
        stats(): MinerResult;
        summary(): MinerResult;
        switchPool(poolId): MinerResult;
        version(): MinerResult;
    }

    Methods

    interface Miner {
        addPool(url): MinerResult;
        delete(poolId): MinerResult;
        devs(): MinerResult;
        disable(poolId): MinerResult;
        enable(poolId): MinerResult;
        pools(): MinerResult;
        restart(): MinerResult;
        stats(): MinerResult;
        summary(): MinerResult;
        switchPool(poolId): MinerResult;
        version(): MinerResult;
    }

    Methods

    addPool delete devs disable @@ -15,48 +15,48 @@

    Returns MinerResult

    • The result of the add pool operation.
    -
    • Deletes the pool with the specified ID.

      Parameters

      • poolId: number

        ID of the pool to delete.

      Returns MinerResult

      • The result of the pool deletion operation.
      -
    • Disables the pool with the specified ID.

      Parameters

      • poolId: number

        The pool ID to disable.

      Returns MinerResult

      • The result of the pool shutdown operation.
      -
    • Enables the pool with the specified ID.

      Parameters

      • poolId: number

        Pool ID to enable.

      Returns MinerResult

      • The result of the pool enable operation.
      -
    • Receives information about the pools to which the miner is connected.

      Returns MinerResult

      • The result of executing a request for information about pools.
      -
    • Switches to the pool with the specified ID.

      Parameters

      • poolId: number

        ID of the pool to switch.

      Returns MinerResult

      • The result of the switch to the pool operation.
      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/MinerResult.html b/api/typedoc/interfaces/MinerResult.html index caa2676d4..5e7addcce 100644 --- a/api/typedoc/interfaces/MinerResult.html +++ b/api/typedoc/interfaces/MinerResult.html @@ -1,5 +1,5 @@ MinerResult | Documentation

    Interface MinerResult

    Interface for interaction with the miner.

    -
    interface MinerResult {
        errMessage: string;
        error: boolean;
        result: string;
    }

    Properties

    interface MinerResult {
        errMessage: string;
        error: boolean;
        result: string;
    }

    Properties

    Properties

    errMessage: string
    error: boolean
    result: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    errMessage: string
    error: boolean
    result: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Mqtt.html b/api/typedoc/interfaces/Mqtt.html index 6640d3deb..48486b310 100644 --- a/api/typedoc/interfaces/Mqtt.html +++ b/api/typedoc/interfaces/Mqtt.html @@ -1,8 +1,8 @@ Mqtt | Documentation

    Interface Mqtt

    Interface for interacting with MQTT.

    -
    interface Mqtt {
        publish(topic, payload, qos, retain): void;
    }

    Methods

    interface Mqtt {
        publish(topic, payload, qos, retain): void;
    }

    Methods

    Methods

    • Publishes a message to MQTT.

      Parameters

      • topic: string

        The subject of the message.

      • payload: string

        Message body.

      • qos: number

        Message service level (0, 1, 2).

      • retain: boolean

        Message retention flag.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Point.html b/api/typedoc/interfaces/Point.html index e7170d371..7ee0f75b0 100644 --- a/api/typedoc/interfaces/Point.html +++ b/api/typedoc/interfaces/Point.html @@ -1,3 +1,3 @@ -Point | Documentation

    Interface Point

    interface Point {
        lat: bigint;
        lon: bigint;
    }

    Properties

    lat +Point | Documentation

    Interface Point

    interface Point {
        lat: bigint;
        lon: bigint;
    }

    Properties

    Properties

    lat: bigint
    lon: bigint

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    lat: bigint
    lon: bigint

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Storage.html b/api/typedoc/interfaces/Storage.html index 8a91f0d43..c04c3920a 100644 --- a/api/typedoc/interfaces/Storage.html +++ b/api/typedoc/interfaces/Storage.html @@ -1,5 +1,5 @@ Storage | Documentation

    Interface Storage

    Interface for storage management.

    -
    interface Storage {
        getByName(key): string;
        pop(key): string;
        push(key, value): string;
        search(key): {
            [key: string]: string;
        };
    }

    Methods

    interface Storage {
        getByName(key): string;
        pop(key): string;
        push(key, value): string;
        search(key): {
            [key: string]: string;
        };
    }

    Methods

    getByName pop push search @@ -8,20 +8,20 @@

    Returns string

    • The returned value.
    -
    • Removes and returns a value from storage for the specified key.

      +
    • Removes and returns a value from storage for the specified key.

      Parameters

      • key: string

        The key to delete the value.

      Returns string

      • The removed value.
      -
    • Adds a value to the store using the specified key.

      +
    • Adds a value to the store using the specified key.

      Parameters

      • key: string

        The key to add the value.

      • value: string

        The value to add.

      Returns string

      • Added value.
      -
    • Searches the storage for values using the specified key.

      +
    • Searches the storage for values using the specified key.

      Parameters

      • key: string

        Key to search for values.

      Returns {
          [key: string]: string;
      }

      • Found values as an object.
      -
      • [key: string]: string

    Generated using TypeDoc

    \ No newline at end of file +
    • [key: string]: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/SystemTriggerMessage.html b/api/typedoc/interfaces/SystemTriggerMessage.html index 8289ed8c3..c923782c3 100644 --- a/api/typedoc/interfaces/SystemTriggerMessage.html +++ b/api/typedoc/interfaces/SystemTriggerMessage.html @@ -1,5 +1,5 @@ SystemTriggerMessage | Documentation

    Interface SystemTriggerMessage

    Interface for system trigger message.

    -
    interface SystemTriggerMessage {
        event: any;
        event_name: string;
        topic: string;
    }

    Properties

    interface SystemTriggerMessage {
        event: any;
        event_name: string;
        topic: string;
    }

    Properties

    Properties

    event: any
    event_name: string
    topic: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    event: any
    event_name: string
    topic: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Trigger.html b/api/typedoc/interfaces/Trigger.html index 620dfe176..74d1316af 100644 --- a/api/typedoc/interfaces/Trigger.html +++ b/api/typedoc/interfaces/Trigger.html @@ -1 +1 @@ -Trigger | Documentation

    Generated using TypeDoc

    \ No newline at end of file +Trigger | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/TriggerAlexaTimeMessage.html b/api/typedoc/interfaces/TriggerAlexaTimeMessage.html index c2040d576..53ea37a40 100644 --- a/api/typedoc/interfaces/TriggerAlexaTimeMessage.html +++ b/api/typedoc/interfaces/TriggerAlexaTimeMessage.html @@ -1,5 +1,5 @@ TriggerAlexaTimeMessage | Documentation

    Interface TriggerAlexaTimeMessage

    Interface for Alexa Time trigger messages.

    -
    interface TriggerAlexaTimeMessage {
        entity_id: string;
        payload: any;
        trigger_name: string;
    }

    Properties

    interface TriggerAlexaTimeMessage {
        entity_id: string;
        payload: any;
        trigger_name: string;
    }

    Properties

    entity_id: string
    payload: any
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    entity_id: string
    payload: any
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/TriggerBleMessage.html b/api/typedoc/interfaces/TriggerBleMessage.html new file mode 100644 index 000000000..b46ef28b4 --- /dev/null +++ b/api/typedoc/interfaces/TriggerBleMessage.html @@ -0,0 +1,5 @@ +TriggerBleMessage | Documentation

    Interface TriggerBleMessage

    Interface for Ble trigger messages.

    +
    interface TriggerBleMessage {
        entity_id: string;
        payload: Uint8Array;
        trigger_name: string;
    }

    Properties

    entity_id: string
    payload: Uint8Array
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/TriggerStateChangedMessage.html b/api/typedoc/interfaces/TriggerStateChangedMessage.html index 1c8673f43..8ff47e6ff 100644 --- a/api/typedoc/interfaces/TriggerStateChangedMessage.html +++ b/api/typedoc/interfaces/TriggerStateChangedMessage.html @@ -1,5 +1,5 @@ TriggerStateChangedMessage | Documentation

    Interface TriggerStateChangedMessage

    Interface for trigger state change event.

    -
    interface TriggerStateChangedMessage {
        entity_id: string;
        payload?: EventStateChanged;
        trigger_name: string;
    }

    Properties

    interface TriggerStateChangedMessage {
        entity_id: string;
        payload?: EventStateChanged;
        trigger_name: string;
    }

    Properties

    entity_id: string
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    entity_id: string
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/TriggerSystemMessage.html b/api/typedoc/interfaces/TriggerSystemMessage.html index 09fe57e1d..105d5a860 100644 --- a/api/typedoc/interfaces/TriggerSystemMessage.html +++ b/api/typedoc/interfaces/TriggerSystemMessage.html @@ -1,5 +1,5 @@ TriggerSystemMessage | Documentation

    Interface TriggerSystemMessage

    Interface for system trigger message.

    -
    interface TriggerSystemMessage {
        entity_id: string;
        payload: SystemTriggerMessage;
        trigger_name: string;
    }

    Properties

    interface TriggerSystemMessage {
        entity_id: string;
        payload: SystemTriggerMessage;
        trigger_name: string;
    }

    Properties

    entity_id: string
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    entity_id: string
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/TriggerTimeMessage.html b/api/typedoc/interfaces/TriggerTimeMessage.html index 988fbb4e8..4829b9759 100644 --- a/api/typedoc/interfaces/TriggerTimeMessage.html +++ b/api/typedoc/interfaces/TriggerTimeMessage.html @@ -1,5 +1,5 @@ TriggerTimeMessage | Documentation

    Interface TriggerTimeMessage

    Interface for Time trigger messages.

    -
    interface TriggerTimeMessage {
        entity_id: string;
        payload: Date;
        trigger_name: string;
    }

    Properties

    interface TriggerTimeMessage {
        entity_id: string;
        payload: Date;
        trigger_name: string;
    }

    Properties

    entity_id: string
    payload: Date
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    entity_id: string
    payload: Date
    trigger_name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/Z2MMessage.html b/api/typedoc/interfaces/Z2MMessage.html index f23c3aa97..f1634d357 100644 --- a/api/typedoc/interfaces/Z2MMessage.html +++ b/api/typedoc/interfaces/Z2MMessage.html @@ -1,5 +1,5 @@ Z2MMessage | Documentation

    Interface Z2MMessage

    Interface for Zigbee2mqtt events.

    -
    interface Z2MMessage {
        duplicate: boolean;
        error: string;
        new_state: EntityStateParams;
        payload: string;
        qos: number;
        success: boolean;
        topic: string;
        Update(msg): void;
        clear(): boolean;
        copy(): Z2MMessage;
        getVar(key): string;
        ok(): boolean;
        setVar(key, value): void;
    }

    Properties

    interface Z2MMessage {
        duplicate: boolean;
        error: string;
        new_state: EntityStateParams;
        payload: string;
        qos: number;
        success: boolean;
        topic: string;
        Update(msg): void;
        clear(): boolean;
        copy(): Z2MMessage;
        getVar(key): string;
        ok(): boolean;
        setVar(key, value): void;
    }

    Properties

    Properties

    duplicate: boolean
    error: string
    payload: string
    qos: number
    success: boolean
    topic: string

    Methods

    • Updates Zigbee2mqtt event data based on another event.

      +

    Properties

    duplicate: boolean
    error: string
    payload: string
    qos: number
    success: boolean
    topic: string

    Methods

    • Updates Zigbee2mqtt event data based on another event.

      Parameters

      Returns void

    • Clears Zigbee2mqtt event data.

      +

    Returns void

    • Clears Zigbee2mqtt event data.

      Returns boolean

      • Result of data clearing.
      -
    • Gets the value of a variable by key from the Zigbee2mqtt event.

      +
    • Gets the value of a variable by key from the Zigbee2mqtt event.

      Parameters

      • key: string

        The key of the variable.

      Returns string

      • The value of the variable.
      -
    • Checks whether the Zigbee2mqtt event was successful.

      +
    • Checks whether the Zigbee2mqtt event was successful.

      Returns boolean

      • The result of the success check.
      -
    • Sets the value of a variable by key in the Zigbee2mqtt event.

      +
    • Sets the value of a variable by key in the Zigbee2mqtt event.

      Parameters

      • key: string

        The key of the variable.

      • value: string

        The value of the variable.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/http.html b/api/typedoc/interfaces/http.html index b069c165f..7c8f9f569 100644 --- a/api/typedoc/interfaces/http.html +++ b/api/typedoc/interfaces/http.html @@ -1,5 +1,5 @@ http | Documentation

    Interface http

    HTTP client interface with basic request methods.

    -
    interface http {
        basicAuth(username, password): http;
        delete(url): HttpResponse;
        digestAuth(username, password): http;
        download(post): HttpResponse;
        get(url): HttpResponse;
        headers(params): http;
        post(url, data): HttpResponse;
        put(url, data): HttpResponse;
    }

    Methods

    interface http {
        basicAuth(username, password): http;
        delete(url): HttpResponse;
        digestAuth(username, password): http;
        download(post): HttpResponse;
        get(url): HttpResponse;
        headers(params): http;
        post(url, data): HttpResponse;
        put(url, data): HttpResponse;
    }

    Methods

    basicAuth delete digestAuth download @@ -13,42 +13,42 @@

    Returns http

    • HTTP client with basic authorization set.
    -
    • Sets Digest protocol authentication for an HTTP request.

      +
    • Sets Digest protocol authentication for an HTTP request.

      Parameters

      • username: string

        Username.

      • password: string

        User password.

      Returns http

      • HTTP client with Digest protocol authentication installed.
      -
    • Performs an HTTP request to download a file.

      Parameters

      • post: string

        URL for downloading the file.

      Returns HttpResponse

      • Response to a file download request.
      -
    • Sets headers for an HTTP request.

      Parameters

      • params: {
            [key: string]: any;
        }

        Request headers.

        • [key: string]: any

      Returns http

      • HTTP client with set headers.
      -
    • Performs an HTTP POST request.

      Parameters

      • url: string

        URL for the POST request.

      • data: string

        Data for the POST request.

      Returns HttpResponse

      • Response to a POST request.
      -
    • Performs an HTTP PUT request.

      Parameters

      • url: string

        URL for the PUT request.

      • data: string

        Data for the PUT request.

      Returns HttpResponse

      • Response to the PUT request.
      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/interfaces/notifr.html b/api/typedoc/interfaces/notifr.html index 191e91380..101d091e1 100644 --- a/api/typedoc/interfaces/notifr.html +++ b/api/typedoc/interfaces/notifr.html @@ -1,10 +1,10 @@ notifr | Documentation

    Interface notifr

    Interface for sending notifications.

    -
    interface notifr {
        newMessage(): Message;
        send(msg): void;
    }

    Methods

    interface notifr {
        newMessage(): Message;
        send(msg): void;
    }

    Methods

    • Sends a notification.

      Parameters

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/modules.html b/api/typedoc/modules.html index a1f14db3b..0aae7bb49 100644 --- a/api/typedoc/modules.html +++ b/api/typedoc/modules.html @@ -2,6 +2,7 @@ MessageType

    Interfaces

    Variables

    Functions

    Functions

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/Area.html b/api/typedoc/types/Area.html index 7e6646d79..18ee5d7c0 100644 --- a/api/typedoc/types/Area.html +++ b/api/typedoc/types/Area.html @@ -1 +1 @@ -Area | Documentation

    Type alias Area

    Area: {
        center: Point;
        created_at: Date;
        description: string;
        id: number;
        name: string;
        polygon: Point[];
        resolution: number;
        updated_at: Date;
        zoom: number;
    }

    Type declaration

    • center: Point
    • created_at: Date
    • description: string
    • id: number
    • name: string
    • polygon: Point[]
    • resolution: number
    • updated_at: Date
    • zoom: number

    Generated using TypeDoc

    \ No newline at end of file +Area | Documentation

    Type alias Area

    Area: {
        center: Point;
        created_at: Date;
        description: string;
        id: number;
        name: string;
        polygon: Point[];
        resolution: number;
        updated_at: Date;
        zoom: number;
    }

    Type declaration

    • center: Point
    • created_at: Date
    • description: string
    • id: number
    • name: string
    • polygon: Point[]
    • resolution: number
    • updated_at: Date
    • zoom: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/Attribute.html b/api/typedoc/types/Attribute.html index 659342047..c8d6141a3 100644 --- a/api/typedoc/types/Attribute.html +++ b/api/typedoc/types/Attribute.html @@ -1 +1 @@ -Attribute | Documentation

    Type alias Attribute

    Attribute: {
        name: string;
        type: AttributeType;
        value: any | Attribute;
    }

    Type declaration

    Generated using TypeDoc

    \ No newline at end of file +Attribute | Documentation

    Type alias Attribute

    Attribute: {
        name: string;
        type: AttributeType;
        value: any | Attribute;
    }

    Type declaration

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/AttributeValue.html b/api/typedoc/types/AttributeValue.html index 262ba2027..bd6e088df 100644 --- a/api/typedoc/types/AttributeValue.html +++ b/api/typedoc/types/AttributeValue.html @@ -1 +1 @@ -AttributeValue | Documentation

    Type alias AttributeValue

    AttributeValue: {
        [key: string]: any;
    }

    Type declaration

    • [key: string]: any

    Generated using TypeDoc

    \ No newline at end of file +AttributeValue | Documentation

    Type alias AttributeValue

    AttributeValue: {
        [key: string]: any;
    }

    Type declaration

    • [key: string]: any

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/Attributes.html b/api/typedoc/types/Attributes.html index b9bfccfdf..3c3cc87cc 100644 --- a/api/typedoc/types/Attributes.html +++ b/api/typedoc/types/Attributes.html @@ -1 +1 @@ -Attributes | Documentation

    Generated using TypeDoc

    \ No newline at end of file +Attributes | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/Metric.html b/api/typedoc/types/Metric.html index 78d94b1f0..96c05ae7c 100644 --- a/api/typedoc/types/Metric.html +++ b/api/typedoc/types/Metric.html @@ -1 +1 @@ -Metric | Documentation

    Type alias Metric

    Metric: {
        created_at: Date;
        data: MetricDataItem[];
        description: string;
        id: number;
        name: string;
        options: MetricOptions;
        ranges: string[];
        type: "line" | "bar" | "doughnut" | "radar" | "pie" | "horizontal";
        updated_at: Date;
    }

    Type declaration

    • created_at: Date
    • data: MetricDataItem[]
    • description: string
    • id: number
    • name: string
    • options: MetricOptions
    • ranges: string[]
    • type: "line" | "bar" | "doughnut" | "radar" | "pie" | "horizontal"
    • updated_at: Date

    Generated using TypeDoc

    \ No newline at end of file +Metric | Documentation

    Type alias Metric

    Metric: {
        created_at: Date;
        data: MetricDataItem[];
        description: string;
        id: number;
        name: string;
        options: MetricOptions;
        ranges: string[];
        type: "line" | "bar" | "doughnut" | "radar" | "pie" | "horizontal";
        updated_at: Date;
    }

    Type declaration

    • created_at: Date
    • data: MetricDataItem[]
    • description: string
    • id: number
    • name: string
    • options: MetricOptions
    • ranges: string[]
    • type: "line" | "bar" | "doughnut" | "radar" | "pie" | "horizontal"
    • updated_at: Date

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/types/SystemEventCommand.html b/api/typedoc/types/SystemEventCommand.html index 4c568c7a9..94512b826 100644 --- a/api/typedoc/types/SystemEventCommand.html +++ b/api/typedoc/types/SystemEventCommand.html @@ -1,2 +1,2 @@ SystemEventCommand | Documentation

    Type alias SystemEventCommand

    SystemEventCommand: "command_enable_task" | "command_disable_task" | "command_enable_trigger" | "command_disable_trigger" | "event_call_trigger" | "event_call_action" | "command_load_entity" | "command_unload_entity"

    System event command type.

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/variables/ENTITY_ID.html b/api/typedoc/variables/ENTITY_ID.html index e0efeb64d..755f67b2f 100644 --- a/api/typedoc/variables/ENTITY_ID.html +++ b/api/typedoc/variables/ENTITY_ID.html @@ -1 +1 @@ -ENTITY_ID | Documentation

    Generated using TypeDoc

    \ No newline at end of file +ENTITY_ID | Documentation

    Generated using TypeDoc

    \ No newline at end of file diff --git a/api/typedoc/variables/console-1.html b/api/typedoc/variables/console-1.html index 40fecc503..f72042e5b 100644 --- a/api/typedoc/variables/console-1.html +++ b/api/typedoc/variables/console-1.html @@ -1,2 +1,2 @@ console | Documentation

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/cmd/server/container/init.go b/cmd/server/container/init.go index 57488e632..d3aea4329 100644 --- a/cmd/server/container/init.go +++ b/cmd/server/container/init.go @@ -61,5 +61,8 @@ func MigrationList(adaptors *adaptors.Adaptors, local_migrations.NewMigrationAutocert(adaptors), local_migrations.NewMigrationPachka(adaptors), local_migrations.NewMigrationWebhook(adaptors), + local_migrations.NewMigrationBle(adaptors), + local_migrations.NewMigrationTime(adaptors), + local_migrations.NewMigrationRemoveTriggersPlugin(adaptors), } } diff --git a/common/apperr/types.go b/common/apperr/types.go index 95296bdad..103de82ed 100644 --- a/common/apperr/types.go +++ b/common/apperr/types.go @@ -200,6 +200,7 @@ var ( ErrPluginIsLoaded = ErrorWithCode("PLUGIN_IS_LOADED", "plugin is loaded", ErrInvalidRequest) ErrPluginIsUnloaded = ErrorWithCode("PLUGIN_IS_UNLOADED", "plugin is unloaded", ErrInvalidRequest) ErrPluginNotLoaded = ErrorWithCode("PLUGIN_NOT_LOADED", "plugin not loaded", ErrInvalidRequest) + ErrPluginReadmeGet = ErrorWithCode("PLUGIN_README_GET_ERROR", "failed to get plugin readme", ErrInternal) ErrRoleAdd = ErrorWithCode("ROLE_ADD_ERROR", "failed to add role", ErrInternal) ErrRoleGet = ErrorWithCode("ROLE_GET_ERROR", "failed to get role", ErrInternal) diff --git a/common/types.go b/common/types.go index 6eca03541..7babfa2c2 100644 --- a/common/types.go +++ b/common/types.go @@ -206,7 +206,8 @@ const ( //DEPRECATED AttributeArray = AttributeType("array") //DEPRECATED - AttributeMap = AttributeType("map") + AttributeMap = AttributeType("map") + AttributeNotice = AttributeType("notice") ) // ConditionType ... diff --git a/data/scripts/global.d.ts b/data/scripts/global.d.ts index 1ab42b991..a3861f4cf 100644 --- a/data/scripts/global.d.ts +++ b/data/scripts/global.d.ts @@ -31,7 +31,7 @@ declare global { // Interface of a point on the map interface Point { - lon:bigint; + lon: bigint; lat: bigint; } @@ -265,6 +265,14 @@ declare global { */ function EntityCallAction(entityId: string, action: string, params: { [key: string]: any }): void; + /** + * Calls a function or method of an entity's script. + * @param {string} entityId - Entity identifier. + * @param {string} fn - The name of the function. + * @param {any} payload - Parameters for the action. + */ + function EntityCallScript(entityId: string, fn: string, payload: any): void; + /** * Interface representing parameters for calling an action on an entity */ @@ -981,4 +989,42 @@ declare global { */ function automationTriggerSystem(msg: TriggerSystemMessage): boolean; + /** + * Interface for Ble trigger messages. + */ + interface TriggerBleMessage { + payload: Uint8Array; + trigger_name: string; + entity_id: string; + } + + /** + * Function called when the Ble trigger event occurs. + * @param {TriggerBleMessage} msg - Ble trigger message. + * @returns {boolean} - The result of the trigger execution. + */ + function automationTriggerBle(msg: TriggerBleMessage): boolean; + + /** + * Interface for responding to bluetooth commands. + */ + interface BleResponse { + response?: Uint8Array; + error?: string; + } + + /** + * Write replaces the characteristic value with a new value. The call will return after all data has been written. + * @param {string} char - UUID Device characteristic. + * @param {Uint8Array} payload - Command. + * @param {boolean} withResponse - if a response is expected. + */ + function BleWrite(char: string, payload: Uint8Array, withResponse: boolean): BleResponse; + + /** + * Read reads the current characteristic value. + * @param {string} char - UUID Device characteristic. + */ + function BleRead(char: string): BleResponse; + } diff --git a/db/plugin.go b/db/plugin.go index 6f4727cfb..61ca6e9b6 100644 --- a/db/plugin.go +++ b/db/plugin.go @@ -22,7 +22,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/pkg/errors" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -42,6 +41,7 @@ type Plugin struct { Enabled bool System bool Actor bool + Triggers bool Settings json.RawMessage `gorm:"type:jsonb;not null"` } @@ -69,6 +69,7 @@ func (n Plugins) CreateOrUpdate(ctx context.Context, v *Plugin) (err error) { "system": v.System, "settings": v.Settings, "actor": v.Actor, + "triggers": v.Triggers, }), }).Create(&v).Error if err != nil { @@ -83,6 +84,7 @@ func (n Plugins) Update(ctx context.Context, m *Plugin) (err error) { "enabled": m.Enabled, "system": m.System, "actor": m.Actor, + "triggers": m.Triggers, "settings": m.Settings, }).Error; err != nil { err = errors.Wrap(apperr.ErrPluginUpdate, err.Error()) @@ -99,14 +101,18 @@ func (n Plugins) Delete(ctx context.Context, name string) (err error) { } // List ... -func (n Plugins) List(ctx context.Context, limit, offset int, orderBy, sort string, onlyEnabled bool) (list []*Plugin, total int64, err error) { +func (n Plugins) List(ctx context.Context, limit, offset int, orderBy, sort string, enabled, triggers *bool) (list []*Plugin, total int64, err error) { list = make([]*Plugin, 0) q := n.Db.WithContext(ctx).Model(&Plugin{}) - if onlyEnabled { + if enabled != nil { q = q. - Where("enabled is true") + Where("enabled = ?", *enabled) + } + + if triggers != nil { + q = q.Where("triggers = ?", *triggers) } if err = q.Count(&total).Error; err != nil { diff --git a/doc/content/en/docs/plugins/ble.md b/doc/content/en/docs/plugins/ble.md new file mode 100755 index 000000000..376dd0ff3 --- /dev/null +++ b/doc/content/en/docs/plugins/ble.md @@ -0,0 +1,10 @@ + +--- +title: "Bluetooth Low Energy Plugin" +linkTitle: "ble" +date: 2024-07-21 +description: > + +--- + +WIP diff --git a/doc/content/ru/docs/plugins/ble.md b/doc/content/ru/docs/plugins/ble.md new file mode 100755 index 000000000..2231ce99e --- /dev/null +++ b/doc/content/ru/docs/plugins/ble.md @@ -0,0 +1,10 @@ + +--- +title: "Bluetooth Low Energy Плагин" +linkTitle: "ble" +date: 2024-07-21 +description: > + +--- + +WIP diff --git a/endpoint/plugin.go b/endpoint/plugin.go index 38cc246e9..c9d26372f 100644 --- a/endpoint/plugin.go +++ b/endpoint/plugin.go @@ -20,6 +20,7 @@ package endpoint import ( "context" + "github.com/pkg/errors" "github.com/e154/smart-home/common" @@ -53,8 +54,8 @@ func (p *PluginEndpoint) Disable(ctx context.Context, pluginName string) (err er } // GetList ... -func (p *PluginEndpoint) GetList(ctx context.Context, pagination common.PageParams) (plugins []*m.Plugin, total int64, err error) { - if plugins, total, err = p.adaptors.Plugin.List(ctx, pagination.Limit, pagination.Offset, pagination.Order, pagination.SortBy, false); err != nil { +func (p *PluginEndpoint) GetList(ctx context.Context, pagination common.PageParams, enabled, triggers *bool) (plugins []*m.Plugin, total int64, err error) { + if plugins, total, err = p.adaptors.Plugin.List(ctx, pagination.Limit, pagination.Offset, pagination.Order, pagination.SortBy, enabled, triggers); err != nil { return } for _, plugin := range plugins { @@ -127,9 +128,9 @@ func (p *PluginEndpoint) UpdateSettings(ctx context.Context, name string, settin return } -func (p *PluginEndpoint) Readme(ctx context.Context, name string, lang *string) (result []byte, err error) { +func (p *PluginEndpoint) Readme(ctx context.Context, name string, note *string, lang *string) (result []byte, err error) { - result, err = p.supervisor.GetPluginReadme(ctx, name, lang) + result, err = p.supervisor.GetPluginReadme(ctx, name, note, lang) return } diff --git a/go.mod b/go.mod index 796a907da..f4aa7e350 100644 --- a/go.mod +++ b/go.mod @@ -87,12 +87,13 @@ require ( github.com/mholt/acmez/v2 v2.0.1 github.com/patrikeh/go-deep v0.0.0-20230427173908-a2775168ab3d github.com/robfig/cron/v3 v3.0.1 - github.com/shirou/gopsutil/v3 v3.24.4 + github.com/shirou/gopsutil/v4 v4.24.6 github.com/showwin/speedtest-go v1.7.7 github.com/spf13/afero v1.11.0 github.com/stretchr/testify v1.9.0 gopkg.in/telebot.v3 v3.2.1 gorm.io/driver/postgres v1.5.7 + tinygo.org/x/bluetooth v0.10.0 ) require ( @@ -126,6 +127,7 @@ require ( github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/goccy/go-json v0.10.3 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gomodule/redigo v1.9.2 // indirect @@ -172,12 +174,17 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/procfs v0.15.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796 // indirect + github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tdewolff/minify/v2 v2.20.31 // indirect github.com/tdewolff/parse/v2 v2.7.14 // indirect + github.com/tinygo-org/cbgo v0.0.4 // indirect + github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.8.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/go.sum b/go.sum index 384934f5b..daeccb87f 100644 --- a/go.sum +++ b/go.sum @@ -587,6 +587,8 @@ github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -884,7 +886,6 @@ github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/liip/sheriff v0.12.0 h1:/deCBoWPcsG5rN/NlHIwNjnj8/U4bN99NdWY8OmQ6RA= github.com/liip/sheriff v0.12.0/go.mod h1:TgdKuCGI/1qkwBjm96/hEN+gD2FEHf8is9YaqGq96o8= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI= github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= @@ -993,7 +994,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= @@ -1051,6 +1051,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b h1:du3zG5fd8snsFN6RBoLA7fpaYV9ZQIsyH9snlk2Zvik= +github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= @@ -1061,8 +1063,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/sevenNt/echo-pprof v0.1.0/go.mod h1:3B009ccno8WPXjh4Ut/B2+FOVt/ulHBV8w/cNdsodXA= github.com/sfreiberg/gotwilio v1.0.0 h1:wrI0vkXHiOIi3He4iVn9e8GNa7XWmqe88MwQkN1+9GM= github.com/sfreiberg/gotwilio v1.0.0/go.mod h1:BRG5BNMaZHiT3bYrtP9kHuUXL+sHNvec+ZMKNgvYWY8= -github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU= -github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8= +github.com/shirou/gopsutil/v4 v4.24.6 h1:9qqCSYF2pgOU+t+NgJtp7Co5+5mHF/HyKBUckySQL64= +github.com/shirou/gopsutil/v4 v4.24.6/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -1094,6 +1096,7 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -1106,6 +1109,10 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796 h1:1/r2URInjjFtWqT61gU7YGVCq3BRyXt/C7z4oLRF9Lo= +github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796/go.mod h1:1Otjk6PRhfzfcVHeWMEeku/VntFqWghUwuSQyivb2vE= +github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef h1:phH95I9wANjTYw6bSYLZDQfNvao+HqYDom8owbNa0P4= +github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef/go.mod h1:oCVCNGCHMKoBj97Zp9znLbQ1nHxpkmOY9X+UAGzOxc8= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= @@ -1154,10 +1161,12 @@ github.com/tdewolff/parse/v2 v2.7.14/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= +github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= +github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899 h1:/DyaXDEWMqoVUVEJVJIlNk1bXTbFs8s3Q4GdPInSKTQ= +github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899/go.mod h1:LU7Dw00NJ+N86QkeTGjMLNkYcEYMor6wTDpTCu0EaH8= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1535,9 +1544,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1937,3 +1943,5 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +tinygo.org/x/bluetooth v0.10.0 h1:42n8qj2tuF5AfdbAUR2Nv45EhtVmbDFH6UoWnt6lzZQ= +tinygo.org/x/bluetooth v0.10.0/go.mod h1:t/Vm2a/rslsBoqFQKCBsWQw/cmRicQq+8Tl3tj5RCRI= diff --git a/migrations/20240721_194705_update_plugins.sql b/migrations/20240721_194705_update_plugins.sql new file mode 100644 index 000000000..1ad46d6fe --- /dev/null +++ b/migrations/20240721_194705_update_plugins.sql @@ -0,0 +1,14 @@ +-- +migrate Up +-- SQL in section 'Up' is executed when this migration is applied +alter table plugins + add column triggers bool not null default false; + +update plugins +set triggers = true +where name in ('time', 'state_change', 'system', 'alexa', 'ble'); + +-- +migrate Down +-- SQL section 'Down' is executed when this migration is rolled back +alter table plugins + drop column triggers; + diff --git a/models/plugin.go b/models/plugin.go index 19190063b..645ecce3f 100644 --- a/models/plugin.go +++ b/models/plugin.go @@ -32,6 +32,7 @@ type Plugin struct { System bool `json:"system"` Actor bool `json:"actor"` IsLoaded bool `json:"is_loaded"` + Triggers bool `json:"triggers"` } // Plugins ... @@ -58,6 +59,13 @@ type PluginOptionsJs struct { Variables map[string]string `json:"variables"` } +type TriggerParams struct { + Entities bool `json:"entities"` + Script bool `json:"script"` + Attributes Attributes `json:"attributes"` + Required []string `json:"required"` +} + // PluginOptions ... type PluginOptions struct { Javascript PluginOptionsJs `json:"javascript"` @@ -67,6 +75,7 @@ type PluginOptions struct { ActorSetts Attributes `json:"actor_setts"` Setts Attributes `json:"setts"` Triggers bool `json:"triggers"` + TriggerParams TriggerParams `json:"trigger_params"` Actors bool `json:"actors"` ActorCustomAttrs bool `json:"actor_custom_attrs"` ActorCustomActions bool `json:"actor_custom_actions"` diff --git a/plugins/alexa/plugin.go b/plugins/alexa/plugin.go index bcdfbb36b..f197cd579 100644 --- a/plugins/alexa/plugin.go +++ b/plugins/alexa/plugin.go @@ -161,7 +161,8 @@ func (p *plugin) eventHandler(_ string, event interface{}) { // Options ... func (p *plugin) Options() m.PluginOptions { return m.PluginOptions{ - Actors: false, - Triggers: true, + Actors: false, + Triggers: true, + TriggerParams: NewTriggerParams(), } } diff --git a/plugins/alexa/types.go b/plugins/alexa/types.go index 6d0a99c21..e2b52f7d7 100644 --- a/plugins/alexa/types.go +++ b/plugins/alexa/types.go @@ -19,6 +19,7 @@ package alexa import ( + "github.com/e154/smart-home/common" m "github.com/e154/smart-home/models" "github.com/gin-gonic/gin" ) @@ -261,3 +262,16 @@ const ( // TriggerOptionSkillId ... TriggerOptionSkillId = "skillId" ) + +func NewTriggerParams() m.TriggerParams { + return m.TriggerParams{ + Script: true, + Required: []string{TriggerOptionSkillId}, + Attributes: m.Attributes{ + TriggerOptionSkillId: { + Name: TriggerOptionSkillId, + Type: common.AttributeInt, + }, + }, + } +} diff --git a/plugins/ble/Readme.md b/plugins/ble/Readme.md new file mode 100644 index 000000000..f28b28386 --- /dev/null +++ b/plugins/ble/Readme.md @@ -0,0 +1,3 @@ +### BLE Plugin + +[Documentation](https://e154.github.io/smart-home/docs/plugins/ble/) diff --git a/plugins/ble/Readme.ru.md b/plugins/ble/Readme.ru.md new file mode 100644 index 000000000..ac315a627 --- /dev/null +++ b/plugins/ble/Readme.ru.md @@ -0,0 +1,3 @@ +### Плагин ble + +[Документация](https://e154.github.io/smart-home/ru/docs/plugins/ble/) diff --git a/plugins/ble/SystemInfo.md b/plugins/ble/SystemInfo.md new file mode 100644 index 000000000..56ead7c14 --- /dev/null +++ b/plugins/ble/SystemInfo.md @@ -0,0 +1 @@ +[Introduction to Bluetooth Low Energy ](https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gap "adafruit"). diff --git a/plugins/ble/SystemInfo.ru.md b/plugins/ble/SystemInfo.ru.md new file mode 100644 index 000000000..56ead7c14 --- /dev/null +++ b/plugins/ble/SystemInfo.ru.md @@ -0,0 +1 @@ +[Introduction to Bluetooth Low Energy ](https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gap "adafruit"). diff --git a/plugins/ble/actor.go b/plugins/ble/actor.go new file mode 100644 index 000000000..59d63dec4 --- /dev/null +++ b/plugins/ble/actor.go @@ -0,0 +1,151 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "strings" + + "github.com/pkg/errors" + "tinygo.org/x/bluetooth" + + "github.com/e154/smart-home/common/events" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/system/supervisor" +) + +// Actor ... +type Actor struct { + *supervisor.BaseActor + actionPool chan events.EventCallEntityAction + ble *Ble +} + +// NewActor ... +func NewActor(entity *m.Entity, + service supervisor.Service) (actor *Actor) { + + actor = &Actor{ + BaseActor: supervisor.NewBaseActor(entity, service), + actionPool: make(chan events.EventCallEntityAction, 1000), + } + + // action worker + go func() { + for msg := range actor.actionPool { + actor.runAction(msg) + } + }() + + // Actions + for _, a := range actor.Actions { + if a.ScriptEngine != nil { + a.ScriptEngine.PushFunction("BleWrite", GetWriteBind(actor)) + a.ScriptEngine.PushFunction("BleRead", GetReadBind(actor)) + //a.ScriptEngine.PushFunction("BleSubscribe", GetSubscribeBind(actor)) + //a.ScriptEngine.PushFunction("BleDisconnect", GetDisconnectBind(actor)) + } + } + + if actor.ScriptsEngine != nil { + actor.ScriptsEngine.PushFunction("BleWrite", GetWriteBind(actor)) + actor.ScriptsEngine.PushFunction("BleRead", GetReadBind(actor)) + //actor.ScriptsEngine.PushFunction("BleSubscribe", GetSubscribeBind(actor)) + //actor.ScriptsEngine.PushFunction("BleDisconnect", GetDisconnectBind(actor)) + } + + if actor.Setts == nil { + actor.Setts = NewSettings() + } + + if actor.Actions == nil { + actor.Actions = NewActions() + } + + return actor +} + +func (e *Actor) Destroy() { + e.ble.Disconnect() +} + +func (e *Actor) Spawn() { + + var timeout, connectionTimeout int64 = 5, 5 + if e.Setts[AttrConnectionTimeoutSec] != nil { + connectionTimeout = e.Setts[AttrConnectionTimeoutSec].Int64() + } + + if e.Setts[AttrTimeoutSec] != nil { + connectionTimeout = e.Setts[AttrTimeoutSec].Int64() + } + + var address string + if e.Setts[AttrAddress] != nil { + address = e.Setts[AttrAddress].String() + } + + var debug bool + if e.Setts[AttrDebug] != nil { + debug = e.Setts[AttrDebug].Bool() + } + + e.ble = NewBle(address, timeout, connectionTimeout, debug) + + e.BaseActor.Spawn() +} + +// SetState ... +func (e *Actor) SetState(params supervisor.EntityStateParams) error { + + e.SetActorState(params.NewState) + e.DeserializeAttr(params.AttributeValues) + e.SaveState(false, params.StorageSave) + + return nil +} + +func (e *Actor) addAction(event events.EventCallEntityAction) { + e.actionPool <- event +} + +func (e *Actor) runAction(msg events.EventCallEntityAction) { + + if strings.ToUpper(msg.ActionName) == ActionScan { + address, err := bluetooth.ParseUUID(e.Setts[AttrAddress].String()) + if err != nil { + e.ble.Scan(nil) + } else { + e.ble.Scan(&address) + } + } + + if action, ok := e.Actions[msg.ActionName]; ok { + if action.ScriptEngine != nil && action.ScriptEngine.Engine() != nil { + if _, err := action.ScriptEngine.Engine().AssertFunction(FuncEntityAction, e.Id, action.Name, msg.Args); err != nil { + log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) + } + return + } + } + if e.ScriptsEngine != nil && e.ScriptsEngine.Engine() != nil { + if _, err := e.ScriptsEngine.AssertFunction(FuncEntityAction, e.Id, msg.ActionName, msg.Args); err != nil { + log.Error(errors.Wrapf(err, "entity id: %s ", e.Id).Error()) + } + } +} diff --git a/plugins/ble/ble.go b/plugins/ble/ble.go new file mode 100644 index 000000000..24d7f5083 --- /dev/null +++ b/plugins/ble/ble.go @@ -0,0 +1,117 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "go.uber.org/atomic" + "sync" + "tinygo.org/x/bluetooth" +) + +type Ble struct { + isScan *atomic.Bool + scanAddress *bluetooth.UUID + devMX sync.Mutex + device *bluetooth.Device + connected *atomic.Bool + adapter *bluetooth.Adapter + address string + timeout int64 + connectionTimeout int64 + debug bool +} + +func NewBle(address string, timeout, connectionTimeout int64, debug bool) *Ble { + ble := &Ble{ + isScan: atomic.NewBool(false), + connected: atomic.NewBool(false), + adapter: bluetooth.DefaultAdapter, + timeout: timeout, + connectionTimeout: connectionTimeout, + address: address, + debug: debug, + } + + ble.adapter.SetConnectHandler(func(device bluetooth.Device, connected bool) { + log.Infof("bluetooth device: %s, connected: %t", device.Address.String(), connected) + ble.connected.Store(connected) + ble.device = &device + }) + + return ble +} + +func (b *Ble) Disconnect() error { + if !b.connected.Load() || b.device == nil { + return nil + } + + b.connected.Store(false) + if err := b.device.Disconnect(); err != nil { + return err + } + b.device = nil + return nil +} + +func (b *Ble) GetServices() ([]bluetooth.DeviceService, error) { + device, err := b.Connect() + if err != nil { + return nil, err + } + + if b.debug { + log.Debugf("device %v get services", b.address) + } + + // Get a list of services + return device.DiscoverServices(nil) +} + +func (b *Ble) GetCharacteristics(chars []bluetooth.UUID) ([]bluetooth.DeviceCharacteristic, error) { + + if b.debug { + log.Debugf("device %v get characteristics %v", b.address, chars) + } + + var characteristic []bluetooth.DeviceCharacteristic + + services, err := b.GetServices() + if err != nil { + return nil, err + } + + for _, service := range services { + discoverCharacteristics, _ := service.DiscoverCharacteristics(chars) + if len(discoverCharacteristics) == 0 { + continue + } + characteristic = append(characteristic, discoverCharacteristics...) + } + + if b.debug { + log.Debugf("device %v found %d characteristics", b.address, len(characteristic)) + } + return characteristic, nil +} + +type Cache struct { + sync.Mutex + pull map[bluetooth.UUID]map[bluetooth.UUID]struct{} +} diff --git a/plugins/ble/ble_bind.go b/plugins/ble/ble_bind.go new file mode 100644 index 000000000..718c7e0a2 --- /dev/null +++ b/plugins/ble/ble_bind.go @@ -0,0 +1,82 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "tinygo.org/x/bluetooth" +) + +type Response struct { + Response []byte `json:"response"` + Error string `json:"error"` +} + +func GetWriteBind(actor *Actor) func(char string, payload []byte, withResponse bool) Response { + return func(c string, payload []byte, withResponse bool) Response { + char, err := bluetooth.ParseUUID(c) + if err != nil { + return Response{Error: err.Error()} + } + + response, err := actor.ble.Write(char, payload, withResponse) + if err != nil { + return Response{Error: err.Error()} + } + return Response{Response: response} + } +} + +func GetReadBind(actor *Actor) func(char string) Response { + return func(c string) Response { + char, err := bluetooth.ParseUUID(c) + if err != nil { + return Response{Error: err.Error()} + } + + response, err := actor.ble.Read(char) + if err != nil { + return Response{Error: err.Error()} + } + return Response{Response: response} + } +} + +func GetSubscribeBind(actor *Actor) func(char string, handler func([]byte)) Response { + return func(c string, handler func([]byte)) Response { + char, err := bluetooth.ParseUUID(c) + if err != nil { + return Response{Error: err.Error()} + } + + err = actor.ble.Subscribe(char, handler) + if err != nil { + return Response{Error: err.Error()} + } + return Response{} + } +} + +func GetDisconnectBind(actor *Actor) func() Response { + return func() Response { + if err := actor.ble.Disconnect(); err != nil { + return Response{Error: err.Error()} + } + return Response{} + } +} diff --git a/plugins/ble/ble_darwin.go b/plugins/ble/ble_darwin.go new file mode 100644 index 000000000..bfd69f183 --- /dev/null +++ b/plugins/ble/ble_darwin.go @@ -0,0 +1,240 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "time" + + "tinygo.org/x/bluetooth" +) + +func (b *Ble) Scan(address *bluetooth.UUID) { + if !b.isScan.CompareAndSwap(false, true) { + return + } + log.Info("Start scan") + b.scanAddress = address + + defer func() { + log.Info("Stop scan") + b.isScan.Store(false) + }() + + adapter := bluetooth.DefaultAdapter + _ = adapter.Enable() + + go func() { + // Start scanning and define callback for scan results + if err := adapter.Scan(b.onScan); err != nil { + log.Error(err.Error()) + } + }() + + select { + case <-time.After(time.Second * 10): + _ = adapter.StopScan() + } +} + +func (b *Ble) onScan(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) { + + // Start connecting in a goroutine to not block + go func() { + device, err := adapter.Connect(scanResult.Address, bluetooth.ConnectionParams{}) + if err != nil { + return + } + + if b.scanAddress == nil || device.Address.String() == "" { + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + } + + if b.scanAddress == nil || device.Address.String() != b.scanAddress.String() { + return + } + + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + + adapter.StopScan() + + // Call connect callback + b.onScanConnect(device) + }() +} + +func (b *Ble) onScanConnect(device bluetooth.Device) { + + defer func() { + if r := recover(); r != nil { + log.Warn("Recovered") + } + }() + + // Get a list of services + services, err := device.DiscoverServices(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate services + for _, service := range services { + + log.Infof("service: %s", service.UUID().String()) + + // Get a list of characteristics below the service + characteristics, err := service.DiscoverCharacteristics(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate characteristics + for _, char := range characteristics { + log.Infof("characteristic: %s", char.UUID().String()) + } + } + +} + +func (b *Ble) Connect() (*bluetooth.Device, error) { + + if b.debug { + log.Debugf("try connecting to %v", b.address) + } + + b.devMX.Lock() + defer b.devMX.Unlock() + + if b.connected.Load() { + if b.debug { + log.Debugf("there is still a connection %v", b.address) + } + return b.device, nil + } + + uuid, err := bluetooth.ParseUUID(b.address) + if err != nil { + return nil, err + } + + if b.debug { + log.Debugf("try to turn on the device") + if err := b.adapter.Enable(); err != nil { + log.Error(err.Error()) + } + } else { + b.adapter.Enable() + } + + if b.debug { + log.Debugf("Connect starts a connection attempt to %s", b.address) + } + device, err := b.adapter.Connect(bluetooth.Address{UUID: uuid}, bluetooth.ConnectionParams{ + ConnectionTimeout: bluetooth.NewDuration(time.Second * time.Duration(b.connectionTimeout)), + Timeout: bluetooth.NewDuration(time.Second * time.Duration(b.timeout)), + }) + if err != nil { + return nil, err + } + + return &device, nil +} + +func (b *Ble) Write(char bluetooth.UUID, request []byte, withResponse bool) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + log.Infof("write: %x --> %s", request, b.address) + + if withResponse { + payload := make([]byte, len(request)) + copy(payload, request) + i, err := characteristic.Write(payload) + if err != nil { + return nil, err + } + log.Infof("read: %x <-- %s", payload[:uint32(i)], b.address) + return payload[:uint32(i)], nil + } else { + if _, err = characteristic.WriteWithoutResponse(request); err != nil { + return nil, err + } + return []byte{}, nil + } + } + + return nil, nil +} + +func (b *Ble) Read(char bluetooth.UUID) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + payload := make([]byte, 1024) + i, err := characteristic.Read(payload) + if err != nil { + return nil, err + } + log.Infof("read: %x <-- %s", payload[:uint32(i)], b.address) + return payload[:uint32(i)], nil + } + + return nil, nil +} + +func (b *Ble) Subscribe(char bluetooth.UUID, handler func([]byte)) error { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + return characteristic.EnableNotifications(handler) + } + + return nil +} diff --git a/plugins/ble/ble_linux.go b/plugins/ble/ble_linux.go new file mode 100644 index 000000000..5554be475 --- /dev/null +++ b/plugins/ble/ble_linux.go @@ -0,0 +1,233 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "time" + + "tinygo.org/x/bluetooth" +) + +func (b *Ble) Scan(address *bluetooth.UUID) { + if !b.isScan.CompareAndSwap(false, true) { + return + } + log.Info("Start scan") + b.scanAddress = address + + defer func() { + log.Info("Stop scan") + b.isScan.Store(false) + }() + + adapter := bluetooth.DefaultAdapter + _ = adapter.Enable() + + go func() { + // Start scanning and define callback for scan results + if err := adapter.Scan(b.onScan); err != nil { + log.Error(err.Error()) + } + }() + + select { + case <-time.After(time.Second * 10): + _ = adapter.StopScan() + } +} + +func (b *Ble) onScan(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) { + + // Start connecting in a goroutine to not block + go func() { + device, err := adapter.Connect(scanResult.Address, bluetooth.ConnectionParams{}) + if err != nil { + return + } + + if b.scanAddress == nil || device.Address.String() == "" { + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + } + + if b.scanAddress == nil || device.Address.String() != b.scanAddress.String() { + return + } + + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + + adapter.StopScan() + + // Call connect callback + b.onScanConnect(device) + }() +} + +func (b *Ble) onScanConnect(device bluetooth.Device) { + + defer func() { + if r := recover(); r != nil { + log.Warn("Recovered") + } + }() + + // Get a list of services + services, err := device.DiscoverServices(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate services + for _, service := range services { + + log.Infof("service: %s", service.UUID().String()) + + // Get a list of characteristics below the service + characteristics, err := service.DiscoverCharacteristics(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate characteristics + for _, char := range characteristics { + log.Infof("characteristic: %s", char.UUID().String()) + } + } + +} + +func (b *Ble) Connect() (*bluetooth.Device, error) { + + if b.debug { + log.Debugf("try connecting to %v", b.address) + } + + b.devMX.Lock() + defer b.devMX.Unlock() + + if b.connected.Load() { + if b.debug { + log.Debugf("there is still a connection %v", b.address) + } + return b.device, nil + } + + mac, err := bluetooth.ParseMAC(b.address) + if err != nil { + return nil, err + } + + if b.debug { + log.Debugf("try to turn on the device") + if err := b.adapter.Enable(); err != nil { + log.Error(err.Error()) + } + } else { + b.adapter.Enable() + } + + if b.debug { + log.Debugf("Connect starts a connection attempt to %s", b.address) + } + device, err := b.adapter.Connect(bluetooth.Address{ + MACAddress: bluetooth.MACAddress{ + MAC: mac, + }, + }, bluetooth.ConnectionParams{ + ConnectionTimeout: bluetooth.NewDuration(time.Second * time.Duration(b.connectionTimeout)), + Timeout: bluetooth.NewDuration(time.Second * time.Duration(b.timeout)), + }) + if err != nil { + return nil, err + } + + return &device, nil +} + +func (b *Ble) Write(char bluetooth.UUID, request []byte, withResponse bool) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + log.Infof("write: %x --> %s", request, b.address) + + if _, err = characteristic.WriteWithoutResponse(request); err != nil { + return nil, err + } + return []byte{}, nil + } + + return nil, nil +} + +func (b *Ble) Read(char bluetooth.UUID) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + payload := make([]byte, 1024) + i, err := characteristic.Read(payload) + if err != nil { + return nil, err + } + log.Infof("read: %x <-- %s", payload[:uint32(i)], b.address) + return payload[:uint32(i)], nil + } + + return nil, nil +} + +func (b *Ble) Subscribe(char bluetooth.UUID, handler func([]byte)) error { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + return characteristic.EnableNotifications(handler) + } + + return nil +} diff --git a/plugins/ble/ble_windows.go b/plugins/ble/ble_windows.go new file mode 100644 index 000000000..090f5d87e --- /dev/null +++ b/plugins/ble/ble_windows.go @@ -0,0 +1,244 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "time" + + "tinygo.org/x/bluetooth" +) + +func (b *Ble) Scan(address *bluetooth.UUID) { + if !b.isScan.CompareAndSwap(false, true) { + return + } + log.Info("Start scan") + b.scanAddress = address + + defer func() { + log.Info("Stop scan") + b.isScan.Store(false) + }() + + adapter := bluetooth.DefaultAdapter + _ = adapter.Enable() + + go func() { + // Start scanning and define callback for scan results + if err := adapter.Scan(b.onScan); err != nil { + log.Error(err.Error()) + } + }() + + select { + case <-time.After(time.Second * 10): + _ = adapter.StopScan() + } +} + +func (b *Ble) onScan(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) { + + // Start connecting in a goroutine to not block + go func() { + device, err := adapter.Connect(scanResult.Address, bluetooth.ConnectionParams{}) + if err != nil { + return + } + + if b.scanAddress == nil || device.Address.String() == "" { + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + } + + if b.scanAddress == nil || device.Address.String() != b.scanAddress.String() { + return + } + + log.Infof("found device: %s, RSSI: %v, LocalName: %s, payload: %v", scanResult.Address.String(), scanResult.RSSI, scanResult.LocalName(), scanResult.AdvertisementPayload) + + adapter.StopScan() + + // Call connect callback + b.onScanConnect(device) + }() +} + +func (b *Ble) onScanConnect(device bluetooth.Device) { + + defer func() { + if r := recover(); r != nil { + log.Warn("Recovered") + } + }() + + // Get a list of services + services, err := device.DiscoverServices(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate services + for _, service := range services { + + log.Infof("service: %s", service.UUID().String()) + + // Get a list of characteristics below the service + characteristics, err := service.DiscoverCharacteristics(nil) + if err != nil { + log.Error(err.Error()) + return + } + + // Iterate characteristics + for _, char := range characteristics { + log.Infof("characteristic: %s", char.UUID().String()) + } + } + +} + +func (b *Ble) Connect() (*bluetooth.Device, error) { + + if b.debug { + log.Debugf("try connecting to %v", b.address) + } + + b.devMX.Lock() + defer b.devMX.Unlock() + + if b.connected.Load() { + if b.debug { + log.Debugf("there is still a connection %v", b.address) + } + return b.device, nil + } + + mac, err := bluetooth.ParseMAC(b.address) + if err != nil { + return nil, err + } + + if b.debug { + log.Debugf("try to turn on the device") + if err := b.adapter.Enable(); err != nil { + log.Error(err.Error()) + } + } else { + b.adapter.Enable() + } + + if b.debug { + log.Debugf("Connect starts a connection attempt to %s", b.address) + } + device, err := b.adapter.Connect(bluetooth.Address{ + MACAddress: bluetooth.MACAddress{ + MAC: mac, + }, + }, bluetooth.ConnectionParams{ + ConnectionTimeout: bluetooth.NewDuration(time.Second * time.Duration(b.connectionTimeout)), + Timeout: bluetooth.NewDuration(time.Second * time.Duration(b.timeout)), + }) + if err != nil { + return nil, err + } + + return &device, nil +} + +func (b *Ble) Write(char bluetooth.UUID, request []byte, withResponse bool) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + log.Infof("write: %x --> %s", request, b.address) + + if withResponse { + payload := make([]byte, len(request)) + copy(payload, request) + i, err := characteristic.Write(payload) + if err != nil { + return nil, err + } + log.Infof("read: %x <-- %s", payload[:uint32(i)], b.address) + return payload[:uint32(i)], nil + } else { + if _, err = characteristic.WriteWithoutResponse(request); err != nil { + return nil, err + } + return []byte{}, nil + } + } + + return nil, nil +} + +func (b *Ble) Read(char bluetooth.UUID) ([]byte, error) { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return nil, err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + payload := make([]byte, 1024) + i, err := characteristic.Read(payload) + if err != nil { + return nil, err + } + log.Infof("read: %x <-- %s", payload[:uint32(i)], b.address) + return payload[:uint32(i)], nil + } + + return nil, nil +} + +func (b *Ble) Subscribe(char bluetooth.UUID, handler func([]byte)) error { + + characteristics, err := b.GetCharacteristics([]bluetooth.UUID{char}) + if err != nil { + return err + } + + // Iterate characteristics + for _, characteristic := range characteristics { + + if characteristic.UUID() != char { + continue + } + + return characteristic.EnableNotifications(handler) + } + + return nil +} diff --git a/plugins/ble/plugin.go b/plugins/ble/plugin.go new file mode 100644 index 000000000..b4a93727d --- /dev/null +++ b/plugins/ble/plugin.go @@ -0,0 +1,160 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "context" + "embed" + + "github.com/e154/smart-home/common/events" + "github.com/e154/smart-home/common/logger" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/supervisor" +) + +var ( + log = logger.MustGetLogger("plugins.ble") +) + +var _ supervisor.Pluggable = (*plugin)(nil) + +//go:embed *.md +var F embed.FS + +func init() { + supervisor.RegisterPlugin(Name, New) +} + +type plugin struct { + *supervisor.Plugin + registrar triggers.IRegistrar + trigger *Trigger +} + +// New ... +func New() supervisor.Pluggable { + p := &plugin{ + Plugin: supervisor.NewPlugin(), + } + p.F = F + return p +} + +// Load ... +func (p *plugin) Load(ctx context.Context, service supervisor.Service) (err error) { + if err = p.Plugin.Load(ctx, service, p.ActorConstructor); err != nil { + return + } + + // register trigger + if triggersPlugin, ok := service.Plugins()[triggers.Name]; ok { + if p.registrar, ok = triggersPlugin.(triggers.IRegistrar); ok { + p.trigger = NewTrigger(p.Service.EventBus()) + if err = p.registrar.RegisterTrigger(p.trigger); err != nil { + log.Error(err.Error()) + return + } + } + } + + _ = p.Service.EventBus().Subscribe("system/entities/+", p.eventHandler) + return +} + +// Unload ... +func (p *plugin) Unload(ctx context.Context) (err error) { + _ = p.Service.EventBus().Unsubscribe("system/entities/+", p.eventHandler) + err = p.Plugin.Unload(ctx) + + p.trigger.Shutdown() + if err = p.registrar.UnregisterTrigger(Name); err != nil { + log.Error(err.Error()) + return err + } + + return +} + +// ActorConstructor ... +func (p *plugin) ActorConstructor(entity *m.Entity) (actor supervisor.PluginActor, err error) { + actor = NewActor(entity, p.Service) + return +} + +// Name ... +func (p *plugin) Name() string { + return Name +} + +func (p *plugin) eventHandler(topic string, msg interface{}) { + + switch v := msg.(type) { + case events.EventStateChanged: + case events.EventCallEntityAction: + values, ok := p.Check(v) + if !ok { + return + } + for _, value := range values { + actor := value.(*Actor) + actor.addAction(v) + } + } +} + +// Type ... +func (p *plugin) Type() supervisor.PluginType { + return supervisor.PluginInstallable +} + +// Depends ... +func (p *plugin) Depends() []string { + return nil +} + +// Version ... +func (p *plugin) Version() string { + return Version +} + +// Options ... +func (p *plugin) Options() m.PluginOptions { + return m.PluginOptions{ + Triggers: true, + Actors: true, + ActorCustomAttrs: true, + ActorAttrs: nil, + ActorCustomActions: true, + ActorActions: supervisor.ToEntityActionShort(NewActions()), + ActorCustomStates: true, + ActorStates: nil, + ActorCustomSetts: true, + ActorSetts: NewSettings(), + Setts: nil, + Javascript: m.PluginOptionsJs{ + Methods: map[string]string{ + "BleRead": "", + "BleWrite": "", + }, + Variables: nil, + }, + TriggerParams: NewTriggerParams(), + } +} diff --git a/plugins/ble/trigger.go b/plugins/ble/trigger.go new file mode 100644 index 000000000..c008be7e6 --- /dev/null +++ b/plugins/ble/trigger.go @@ -0,0 +1,204 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +// EventStateChanged + +package ble + +import ( + "fmt" + "reflect" + "sync" + "time" + + "github.com/e154/bus" + "tinygo.org/x/bluetooth" + + "github.com/e154/smart-home/plugins/triggers" +) + +var _ triggers.ITrigger = (*Trigger)(nil) + +type Trigger struct { + eventBus bus.Bus + msgQueue bus.Bus + functionName string + name string + ticker *time.Ticker + sync.Mutex + devices map[string]map[string]*TriggerParams +} + +func NewTrigger(eventBus bus.Bus) *Trigger { + trigger := &Trigger{ + eventBus: eventBus, + msgQueue: bus.NewBus(), + functionName: FunctionName, + name: Name, + devices: make(map[string]map[string]*TriggerParams), + } + + go func() { + const pause = 10 + trigger.ticker = time.NewTicker(time.Second * time.Duration(pause)) + + for range trigger.ticker.C { + trigger.Lock() + for _, device := range trigger.devices { + for _, characteristic := range device { + if !characteristic.connected.Load() { + trigger.Connect(characteristic, false) + } + } + } + trigger.Unlock() + } + }() + + return trigger +} + +func (t *Trigger) Name() string { + return t.name +} + +func (t *Trigger) Shutdown() { + if t.ticker != nil { + t.ticker.Stop() + t.ticker = nil + } + + t.Lock() + defer t.Unlock() + + for _, device := range t.devices { + for _, characteristic := range device { + characteristic.Disconnect() + } + } +} + +func (t *Trigger) AsyncAttach(wg *sync.WaitGroup) { + + wg.Done() +} + +// Subscribe ... +func (t *Trigger) Subscribe(options triggers.Subscriber) error { + + if options.Payload == nil { + return fmt.Errorf("payload is nil") + } + + address, ok := options.Payload[AttrAddress] + if !ok { + return fmt.Errorf("address attribute is nil") + } + + characteristic, ok := options.Payload[AttrCharacteristic] + if !ok { + return fmt.Errorf("characteristic attribute is nil") + } + + if _, ok := t.devices[address.String()][characteristic.String()]; ok { + return fmt.Errorf("a trigger with such parameters already exists") + } + + t.Lock() + defer t.Unlock() + + err := t.Connect(&TriggerParams{options: options}, true) + + return err +} + +// Unsubscribe ... +func (t *Trigger) Unsubscribe(options triggers.Subscriber) error { + + t.Lock() + defer t.Unlock() + + if options.Payload == nil { + return fmt.Errorf("payload is nil") + } + + address, ok := options.Payload[AttrAddress] + if !ok { + return fmt.Errorf("address attribute is nil") + } + + characteristic, ok := options.Payload[AttrCharacteristic] + if !ok { + return fmt.Errorf("characteristic attribute is nil") + } + + device, ok := t.devices[address.String()][characteristic.String()] + if !ok { + return nil + } + + if device != nil { + _ = device.Disconnect() + } + + delete(t.devices, address.String()) + + log.Infof("unsubscribe from %s", characteristic.String()) + + return nil +} + +// FunctionName ... +func (t *Trigger) FunctionName() string { + return t.functionName +} + +func (t *Trigger) Connect(params *TriggerParams, firstTime bool) error { + + options := params.options + address := options.Payload[AttrAddress].String() + characteristic := options.Payload[AttrCharacteristic].String() + + var timeout, connectionTimeout int64 = 5, 5 + params.Ble = NewBle(address, timeout, connectionTimeout, false) + + char, err := bluetooth.ParseUUID(characteristic) + if err != nil { + return err + } + + callback := reflect.ValueOf(options.Handler) + err = params.Subscribe(char, func(bytes []byte) { + callback.Call([]reflect.Value{reflect.ValueOf(""), reflect.ValueOf(bytes)}) + }) + + if err != nil && firstTime { + log.Infof("trigger '%s' is not subscribed to '%s' but we are trying", t.name, characteristic) + } + + if _, ok := t.devices[address]; !ok { + t.devices[address] = make(map[string]*TriggerParams) + } + t.devices[address][characteristic] = params + + if err == nil && firstTime { + log.Infof("trigger '%s' subscribed to '%s'", t.name, characteristic) + } + + return nil +} diff --git a/plugins/ble/types.go b/plugins/ble/types.go new file mode 100644 index 000000000..c8c5ac4e8 --- /dev/null +++ b/plugins/ble/types.go @@ -0,0 +1,111 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package ble + +import ( + "github.com/e154/smart-home/common" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/supervisor" +) + +const ( + // Name ... + Name = "ble" + // FuncEntityAction ... + FuncEntityAction = "entityAction" + + Version = "0.0.1" + + AttrAddress = "address" + AttrCharacteristic = "characteristic" + AttrService = "service" + AttrTimeoutSec = "timeout_sec" + AttrConnectionTimeoutSec = "connection_timeout_sec" + AttrDebug = "debug" + ActionScan = "SCAN" + AttrSystemInfo = "SystemInfo" + + FunctionName = "automationTriggerBle" +) + +// NewSettings ... +func NewSettings() map[string]*m.Attribute { + return map[string]*m.Attribute{ + AttrAddress: { + Name: AttrAddress, + Type: common.AttributeString, + Value: "", + }, + AttrTimeoutSec: { + Name: AttrTimeoutSec, + Type: common.AttributeInt, + Value: 5, + }, + AttrConnectionTimeoutSec: { + Name: AttrConnectionTimeoutSec, + Type: common.AttributeInt, + Value: 5, + }, + AttrDebug: { + Name: AttrDebug, + Type: common.AttributeBool, + Value: false, + }, + } +} + +func NewActions() map[string]supervisor.ActorAction { + return map[string]supervisor.ActorAction{ + ActionScan: { + Name: ActionScan, + Description: "Scan starts a BLE scan. It is stopped after 10 seconds.", + }, + } +} + +func NewTriggerParams() m.TriggerParams { + return m.TriggerParams{ + Script: true, + Required: []string{AttrAddress, AttrCharacteristic}, + Attributes: m.Attributes{ + AttrSystemInfo: { + Name: AttrSystemInfo, + Type: common.AttributeNotice, + }, + AttrAddress: { + Name: AttrAddress, + Type: common.AttributeString, + }, + //AttrService: { + // Name: AttrService, + // Type: common.AttributeString, + //}, + AttrCharacteristic: { + Name: AttrCharacteristic, + Type: common.AttributeString, + }, + }, + } +} + +type TriggerParams struct { + *Ble + options triggers.Subscriber +} diff --git a/plugins/cpuspeed/actor.go b/plugins/cpuspeed/actor.go index 851087f68..5be709400 100644 --- a/plugins/cpuspeed/actor.go +++ b/plugins/cpuspeed/actor.go @@ -22,7 +22,7 @@ import ( "sync" "github.com/rcrowley/go-metrics" - "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v4/cpu" "github.com/e154/smart-home/common" m "github.com/e154/smart-home/models" diff --git a/plugins/hdd/actor.go b/plugins/hdd/actor.go index fde3d21ac..d4bfb2a6d 100644 --- a/plugins/hdd/actor.go +++ b/plugins/hdd/actor.go @@ -22,7 +22,7 @@ import ( "sync" "github.com/rcrowley/go-metrics" - "github.com/shirou/gopsutil/v3/disk" + "github.com/shirou/gopsutil/v4/disk" "github.com/e154/smart-home/common/events" m "github.com/e154/smart-home/models" diff --git a/plugins/memory/actor.go b/plugins/memory/actor.go index 15ab95d31..32efcc17c 100644 --- a/plugins/memory/actor.go +++ b/plugins/memory/actor.go @@ -22,7 +22,7 @@ import ( "sync" "github.com/rcrowley/go-metrics" - "github.com/shirou/gopsutil/v3/mem" + "github.com/shirou/gopsutil/v4/mem" "github.com/e154/smart-home/common" m "github.com/e154/smart-home/models" diff --git a/plugins/plugins.go b/plugins/plugins.go index 672b19320..51614b47c 100644 --- a/plugins/plugins.go +++ b/plugins/plugins.go @@ -18,9 +18,12 @@ package plugins +import _ "github.com/e154/smart-home/plugins/triggers" + import ( _ "github.com/e154/smart-home/plugins/alexa" _ "github.com/e154/smart-home/plugins/autocert" + _ "github.com/e154/smart-home/plugins/ble" _ "github.com/e154/smart-home/plugins/cgminer" _ "github.com/e154/smart-home/plugins/cpuspeed" _ "github.com/e154/smart-home/plugins/email" @@ -44,9 +47,11 @@ import ( _ "github.com/e154/smart-home/plugins/sensor" _ "github.com/e154/smart-home/plugins/slack" _ "github.com/e154/smart-home/plugins/speedtest" + _ "github.com/e154/smart-home/plugins/state_change" _ "github.com/e154/smart-home/plugins/sun" + _ "github.com/e154/smart-home/plugins/system" _ "github.com/e154/smart-home/plugins/telegram" - _ "github.com/e154/smart-home/plugins/triggers" + _ "github.com/e154/smart-home/plugins/time" _ "github.com/e154/smart-home/plugins/twilio" _ "github.com/e154/smart-home/plugins/updater" _ "github.com/e154/smart-home/plugins/uptime" diff --git a/plugins/state_change/Readme.md b/plugins/state_change/Readme.md new file mode 100644 index 000000000..241ce872d --- /dev/null +++ b/plugins/state_change/Readme.md @@ -0,0 +1,3 @@ +### TRIGGERS Plugin + +[Documentation](https://e154.github.io/smart-home/docs/plugins/triggers/) diff --git a/plugins/state_change/Readme.ru.md b/plugins/state_change/Readme.ru.md new file mode 100644 index 000000000..11b3fd84b --- /dev/null +++ b/plugins/state_change/Readme.ru.md @@ -0,0 +1,3 @@ +### Плагин TRIGGERS + +[Документация](https://e154.github.io/smart-home/ru/docs/plugins/triggers/) diff --git a/plugins/state_change/plugin.go b/plugins/state_change/plugin.go new file mode 100644 index 000000000..1fa0ea1d5 --- /dev/null +++ b/plugins/state_change/plugin.go @@ -0,0 +1,120 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package state_change + +import ( + "context" + "embed" + "sync" + + "github.com/e154/smart-home/common/logger" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/supervisor" +) + +var ( + log = logger.MustGetLogger("plugins.state_change") +) + +var _ supervisor.Pluggable = (*plugin)(nil) + +//go:embed *.md +var F embed.FS + +func init() { + supervisor.RegisterPlugin(Name, New) +} + +type plugin struct { + *supervisor.Plugin + actorsLock *sync.Mutex + registrar triggers.IRegistrar +} + +// New ... +func New() supervisor.Pluggable { + p := &plugin{ + Plugin: supervisor.NewPlugin(), + actorsLock: &sync.Mutex{}, + } + p.F = F + return p +} + +// Load ... +func (p *plugin) Load(ctx context.Context, service supervisor.Service) (err error) { + if err = p.Plugin.Load(ctx, service, nil); err != nil { + return + } + + // register trigger + if triggersPlugin, ok := service.Plugins()[triggers.Name]; ok { + if p.registrar, ok = triggersPlugin.(triggers.IRegistrar); ok { + if err = p.registrar.RegisterTrigger(NewTrigger(p.Service.EventBus())); err != nil { + log.Error(err.Error()) + return + } + } + } + + return nil +} + +// Unload ... +func (p *plugin) Unload(ctx context.Context) (err error) { + if err = p.Plugin.Unload(ctx); err != nil { + return + } + + if err = p.registrar.UnregisterTrigger(Name); err != nil { + log.Error(err.Error()) + return err + } + + return nil +} + +// Name ... +func (p *plugin) Name() string { + return Name +} + +// Type ... +func (p *plugin) Type() supervisor.PluginType { + return supervisor.PluginInstallable +} + +// Depends ... +func (p *plugin) Depends() []string { + return []string{"triggers"} +} + +// Version ... +func (p *plugin) Version() string { + return Version +} + +// Options ... +func (p *plugin) Options() m.PluginOptions { + return m.PluginOptions{ + Triggers: true, + TriggerParams: NewTriggerParams(), + } +} diff --git a/plugins/triggers/state_change.go b/plugins/state_change/trigger.go similarity index 72% rename from plugins/triggers/state_change.go rename to plugins/state_change/trigger.go index 6fa731a2a..2300181b2 100644 --- a/plugins/triggers/state_change.go +++ b/plugins/state_change/trigger.go @@ -18,47 +18,43 @@ // EventStateChanged -package triggers +package state_change import ( "sync" + "github.com/e154/bus" "go.uber.org/atomic" - "github.com/e154/bus" "github.com/e154/smart-home/common/events" + "github.com/e154/smart-home/plugins/triggers" ) -const ( - // StateChangeName ... - StateChangeName = "state_change" - // StateChangeFunctionName ... - StateChangeFunctionName = "automationTriggerStateChanged" -) - -var _ ITrigger = (*StateChangeTrigger)(nil) +var _ triggers.ITrigger = (*Trigger)(nil) -// StateChangeTrigger ... -type StateChangeTrigger struct { - baseTrigger - counter *atomic.Int32 +type Trigger struct { + eventBus bus.Bus + msgQueue bus.Bus + counter *atomic.Int32 + functionName string + name string } -// NewStateChangedTrigger ... -func NewStateChangedTrigger(eventBus bus.Bus) ITrigger { - return &StateChangeTrigger{ - baseTrigger: baseTrigger{ - eventBus: eventBus, - msgQueue: bus.NewBus(), - functionName: StateChangeFunctionName, - name: StateChangeName, - }, - counter: atomic.NewInt32(0), +func NewTrigger(eventBus bus.Bus) triggers.ITrigger { + return &Trigger{ + eventBus: eventBus, + msgQueue: bus.NewBus(), + functionName: FunctionName, + name: Name, + counter: atomic.NewInt32(0), } } -// AsyncAttach ... -func (t *StateChangeTrigger) AsyncAttach(wg *sync.WaitGroup) { +func (t *Trigger) Name() string { + return t.name +} + +func (t *Trigger) AsyncAttach(wg *sync.WaitGroup) { if err := t.eventBus.Subscribe("system/entities/+", t.eventHandler); err != nil { log.Error(err.Error()) @@ -67,7 +63,7 @@ func (t *StateChangeTrigger) AsyncAttach(wg *sync.WaitGroup) { wg.Done() } -func (t *StateChangeTrigger) eventHandler(_ string, event interface{}) { +func (t *Trigger) eventHandler(_ string, event interface{}) { if t.counter.Load() <= 0 { return } @@ -102,15 +98,20 @@ func (t *StateChangeTrigger) eventHandler(_ string, event interface{}) { } // Subscribe ... -func (t *StateChangeTrigger) Subscribe(options Subscriber) error { +func (t *Trigger) Subscribe(options triggers.Subscriber) error { //log.Infof("subscribe topic %s", options.EntityId) t.counter.Inc() return t.msgQueue.Subscribe(options.EntityId.String(), options.Handler) } // Unsubscribe ... -func (t *StateChangeTrigger) Unsubscribe(options Subscriber) error { +func (t *Trigger) Unsubscribe(options triggers.Subscriber) error { //log.Infof("unsubscribe topic %s", options.EntityId) t.counter.Dec() return t.msgQueue.Unsubscribe(options.EntityId.String(), options.Handler) } + +// FunctionName ... +func (t *Trigger) FunctionName() string { + return t.functionName +} diff --git a/plugins/state_change/types.go b/plugins/state_change/types.go new file mode 100644 index 000000000..851e26beb --- /dev/null +++ b/plugins/state_change/types.go @@ -0,0 +1,59 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package state_change + +import ( + "time" + + "github.com/e154/smart-home/common" + "github.com/e154/smart-home/common/events" + m "github.com/e154/smart-home/models" +) + +const ( + Name = "state_change" + FunctionName = "automationTriggerStateChanged" + Version = "0.0.1" +) + +func NewTriggerParams() m.TriggerParams { + return m.TriggerParams{ + Script: true, + Entities: true, + } +} + +type EventEntityState struct { + EntityId common.EntityId `json:"entity_id"` + Value interface{} `json:"value"` + State *events.EntityState `json:"state"` + Attributes m.AttributeValue `json:"attributes"` + Settings m.AttributeValue `json:"settings"` + LastChanged *time.Time `json:"last_changed"` + LastUpdated *time.Time `json:"last_updated"` +} + +type TriggerStateChangedMessage struct { + StorageSave bool `json:"storage_save"` + DoNotSaveMetric bool `json:"do_not_save_metric"` + PluginName string `json:"plugin_name"` + EntityId common.EntityId `json:"entity_id"` + OldState EventEntityState `json:"old_state"` + NewState EventEntityState `json:"new_state"` +} diff --git a/plugins/system/Readme.md b/plugins/system/Readme.md new file mode 100644 index 000000000..241ce872d --- /dev/null +++ b/plugins/system/Readme.md @@ -0,0 +1,3 @@ +### TRIGGERS Plugin + +[Documentation](https://e154.github.io/smart-home/docs/plugins/triggers/) diff --git a/plugins/system/Readme.ru.md b/plugins/system/Readme.ru.md new file mode 100644 index 000000000..11b3fd84b --- /dev/null +++ b/plugins/system/Readme.ru.md @@ -0,0 +1,3 @@ +### Плагин TRIGGERS + +[Документация](https://e154.github.io/smart-home/ru/docs/plugins/triggers/) diff --git a/plugins/system/SystemInfo.md b/plugins/system/SystemInfo.md new file mode 100644 index 000000000..b7c209bcd --- /dev/null +++ b/plugins/system/SystemInfo.md @@ -0,0 +1,36 @@ +**System events list** + +--- + +**tasks** +event_task_completed event_created_task_model event_removed_task_model event_updated_task_model event_task_loaded event_task_unloaded event_trigger_completed event_call_trigger event_created_trigger_model event_removed_trigger_model event_updated_trigger_model event_trigger_loaded event_trigger_unloaded event_action_completed event_call_task_action event_call_action event_added_action_model event_removed_action_model event_updated_action_model event_action_loaded event_action_unloaded event_added_condition_model event_removed_condition_model event_updated_condition_model + +**backup** +event_created_backup event_removed_backup event_uploaded_backup event_started_restore + +**entity** +event_state_changed event_last_state_changed event_get_last_state event_call_entity_action event_call_scene event_added_actor event_created_entity_model event_updated_entity_model event_updated_metric event_entity_unloaded event_entity_loaded event_entity_set_state + +**mqtt** +event_mqtt_new_client + +**plugins** +event_plugin_loaded event_plugin_unloaded + +**scripts** +event_created_script_model event_updated_script_model event_removed_script_model + +**services** +event_service_started event_service_stopped event_service_restarted + +**users** +event_update_user_location event_direct_message event_user_signed_in + +**variables** +event_updated_variable_model event_removed_variable_model + +**server version** +event_server_version event_get_server_version + +**zigbee2mqtt** +event_created_zigbee2mqtt_model event_updated_zigbee2mqtt_model event_removed_zigbee2mqtt_model diff --git a/plugins/system/SystemInfo.ru.md b/plugins/system/SystemInfo.ru.md new file mode 100644 index 000000000..b7c209bcd --- /dev/null +++ b/plugins/system/SystemInfo.ru.md @@ -0,0 +1,36 @@ +**System events list** + +--- + +**tasks** +event_task_completed event_created_task_model event_removed_task_model event_updated_task_model event_task_loaded event_task_unloaded event_trigger_completed event_call_trigger event_created_trigger_model event_removed_trigger_model event_updated_trigger_model event_trigger_loaded event_trigger_unloaded event_action_completed event_call_task_action event_call_action event_added_action_model event_removed_action_model event_updated_action_model event_action_loaded event_action_unloaded event_added_condition_model event_removed_condition_model event_updated_condition_model + +**backup** +event_created_backup event_removed_backup event_uploaded_backup event_started_restore + +**entity** +event_state_changed event_last_state_changed event_get_last_state event_call_entity_action event_call_scene event_added_actor event_created_entity_model event_updated_entity_model event_updated_metric event_entity_unloaded event_entity_loaded event_entity_set_state + +**mqtt** +event_mqtt_new_client + +**plugins** +event_plugin_loaded event_plugin_unloaded + +**scripts** +event_created_script_model event_updated_script_model event_removed_script_model + +**services** +event_service_started event_service_stopped event_service_restarted + +**users** +event_update_user_location event_direct_message event_user_signed_in + +**variables** +event_updated_variable_model event_removed_variable_model + +**server version** +event_server_version event_get_server_version + +**zigbee2mqtt** +event_created_zigbee2mqtt_model event_updated_zigbee2mqtt_model event_removed_zigbee2mqtt_model diff --git a/plugins/system/plugin.go b/plugins/system/plugin.go new file mode 100644 index 000000000..826e1b80f --- /dev/null +++ b/plugins/system/plugin.go @@ -0,0 +1,120 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package system + +import ( + "context" + "embed" + "sync" + + "github.com/e154/smart-home/common/logger" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/supervisor" +) + +var ( + log = logger.MustGetLogger("plugins.system") +) + +var _ supervisor.Pluggable = (*plugin)(nil) + +//go:embed *.md +var F embed.FS + +func init() { + supervisor.RegisterPlugin(Name, New) +} + +type plugin struct { + *supervisor.Plugin + actorsLock *sync.Mutex + registrar triggers.IRegistrar +} + +// New ... +func New() supervisor.Pluggable { + p := &plugin{ + Plugin: supervisor.NewPlugin(), + actorsLock: &sync.Mutex{}, + } + p.F = F + return p +} + +// Load ... +func (p *plugin) Load(ctx context.Context, service supervisor.Service) (err error) { + if err = p.Plugin.Load(ctx, service, nil); err != nil { + return + } + + // register trigger + if triggersPlugin, ok := service.Plugins()[triggers.Name]; ok { + if p.registrar, ok = triggersPlugin.(triggers.IRegistrar); ok { + if err = p.registrar.RegisterTrigger(NewTrigger(p.Service.EventBus())); err != nil { + log.Error(err.Error()) + return + } + } + } + + return nil +} + +// Unload ... +func (p *plugin) Unload(ctx context.Context) (err error) { + if err = p.Plugin.Unload(ctx); err != nil { + return + } + + if err = p.registrar.UnregisterTrigger(Name); err != nil { + log.Error(err.Error()) + return err + } + + return nil +} + +// Name ... +func (p *plugin) Name() string { + return Name +} + +// Type ... +func (p *plugin) Type() supervisor.PluginType { + return supervisor.PluginInstallable +} + +// Depends ... +func (p *plugin) Depends() []string { + return []string{"triggers"} +} + +// Version ... +func (p *plugin) Version() string { + return Version +} + +// Options ... +func (p *plugin) Options() m.PluginOptions { + return m.PluginOptions{ + Triggers: true, + TriggerParams: NewTriggerParams(), + } +} diff --git a/plugins/triggers/system_trigger.go b/plugins/system/trigger.go similarity index 61% rename from plugins/triggers/system_trigger.go rename to plugins/system/trigger.go index fbf588682..141f6df63 100644 --- a/plugins/triggers/system_trigger.go +++ b/plugins/system/trigger.go @@ -1,6 +1,6 @@ // This file is part of the Smart Home // Program complex distribution https://github.com/e154/smart-home -// Copyright (C) 2016-2023, Filippov Alex +// Copyright (C) 2016-2024, Filippov Alex // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -16,48 +16,45 @@ // License along with this library. If not, see // . -package triggers +package system import ( "github.com/e154/smart-home/common/events" + "github.com/e154/smart-home/plugins/triggers" "go.uber.org/atomic" "sync" "github.com/e154/bus" ) -const ( - // TopicSystem ... - TopicSystem = "system/#" - // SystemName ... - SystemName = "system" - // SystemFunctionName ... - SystemFunctionName = "automationTriggerSystem" -) - -var _ ITrigger = (*SystemTrigger)(nil) +var _ triggers.ITrigger = (*Trigger)(nil) -// SystemTrigger ... -type SystemTrigger struct { - baseTrigger - counter *atomic.Int32 +// Trigger ... +type Trigger struct { + eventBus bus.Bus + msgQueue bus.Bus + functionName string + name string + counter *atomic.Int32 } -// NewSystemTrigger ... -func NewSystemTrigger(eventBus bus.Bus) ITrigger { - return &SystemTrigger{ - baseTrigger: baseTrigger{ - eventBus: eventBus, - msgQueue: bus.NewBus(), - functionName: SystemFunctionName, - name: SystemName, - }, - counter: atomic.NewInt32(0), +// NewTrigger ... +func NewTrigger(eventBus bus.Bus) triggers.ITrigger { + return &Trigger{ + eventBus: eventBus, + msgQueue: bus.NewBus(), + functionName: FunctionName, + name: Name, + counter: atomic.NewInt32(0), } } +func (t *Trigger) Name() string { + return t.name +} + // AsyncAttach ... -func (t *SystemTrigger) AsyncAttach(wg *sync.WaitGroup) { +func (t *Trigger) AsyncAttach(wg *sync.WaitGroup) { if err := t.eventBus.Subscribe(TopicSystem, t.eventHandler); err != nil { log.Error(err.Error()) @@ -66,7 +63,7 @@ func (t *SystemTrigger) AsyncAttach(wg *sync.WaitGroup) { wg.Done() } -func (t *SystemTrigger) eventHandler(topic string, event interface{}) { +func (t *Trigger) eventHandler(topic string, event interface{}) { if t.counter.Load() <= 0 { return } @@ -75,7 +72,7 @@ func (t *SystemTrigger) eventHandler(topic string, event interface{}) { return } - t.msgQueue.Publish(topic, &SystemTriggerMessage{ + t.msgQueue.Publish(topic, &TriggerMessage{ Topic: topic, EventName: events.EventName(event), Event: event, @@ -83,15 +80,20 @@ func (t *SystemTrigger) eventHandler(topic string, event interface{}) { } // Subscribe ... -func (t *SystemTrigger) Subscribe(options Subscriber) error { +func (t *Trigger) Subscribe(options triggers.Subscriber) error { //log.Infof("subscribe topic %s", TopicSystem) t.counter.Inc() return t.msgQueue.Subscribe(TopicSystem, options.Handler) } // Unsubscribe ... -func (t *SystemTrigger) Unsubscribe(options Subscriber) error { +func (t *Trigger) Unsubscribe(options triggers.Subscriber) error { //log.Infof("unsubscribe topic %s", TopicSystem) t.counter.Dec() return t.msgQueue.Unsubscribe(TopicSystem, options.Handler) } + +// FunctionName ... +func (t *Trigger) FunctionName() string { + return t.functionName +} diff --git a/plugins/system/types.go b/plugins/system/types.go new file mode 100644 index 000000000..27aa3ec61 --- /dev/null +++ b/plugins/system/types.go @@ -0,0 +1,55 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package system + +import ( + "github.com/e154/smart-home/common" + m "github.com/e154/smart-home/models" +) + +const ( + Name = "system" + AttrSystem = "system" + AttrSystemInfo = "SystemInfo" + FunctionName = "automationTriggerSystem" + TopicSystem = "system/#" + Version = "0.0.1" +) + +func NewTriggerParams() m.TriggerParams { + return m.TriggerParams{ + Script: true, + Attributes: m.Attributes{ + AttrSystemInfo: { + Name: AttrSystemInfo, + Type: common.AttributeNotice, + }, + AttrSystem: { + Name: AttrSystem, + Type: common.AttributeString, + }, + }, + } +} + +type TriggerMessage struct { + Topic string `json:"topic"` + EventName string `json:"event_name"` + Event interface{} `json:"event"` +} diff --git a/plugins/time/Readme.md b/plugins/time/Readme.md new file mode 100644 index 000000000..241ce872d --- /dev/null +++ b/plugins/time/Readme.md @@ -0,0 +1,3 @@ +### TRIGGERS Plugin + +[Documentation](https://e154.github.io/smart-home/docs/plugins/triggers/) diff --git a/plugins/time/Readme.ru.md b/plugins/time/Readme.ru.md new file mode 100644 index 000000000..11b3fd84b --- /dev/null +++ b/plugins/time/Readme.ru.md @@ -0,0 +1,3 @@ +### Плагин TRIGGERS + +[Документация](https://e154.github.io/smart-home/ru/docs/plugins/triggers/) diff --git a/plugins/time/SystemInfo.md b/plugins/time/SystemInfo.md new file mode 100644 index 000000000..6fddad197 --- /dev/null +++ b/plugins/time/SystemInfo.md @@ -0,0 +1,16 @@ +The cron expression is made of six fields. Each field can have the following values. + +| * | * | * | * | * | * | +|---------------|---------------|---------------|---------------------------|----------------|-------------------------| +| minute (0-59) | second (0-59) | hour (0 - 23) | day of the month (1 - 31) | month (1 - 12) | day of the week (0 - 6) | + +Here are some examples for you. + +| Cron expression | Schedule | +|-----------------|---------------------------------------| +| * * * * * * | Every second | +| 0 * * * * * | Every minute | +| 0 0 * * * * | Every hour | +| 0 0 0 * * * | Every day at 12:00 AM | +| 0 0 0 * * FRI | At 12:00 AM, only on Friday | +| 0 0 0 1 * * | At 12:00 AM, on day 1 of the month | diff --git a/plugins/time/SystemInfo.ru.md b/plugins/time/SystemInfo.ru.md new file mode 100644 index 000000000..6fddad197 --- /dev/null +++ b/plugins/time/SystemInfo.ru.md @@ -0,0 +1,16 @@ +The cron expression is made of six fields. Each field can have the following values. + +| * | * | * | * | * | * | +|---------------|---------------|---------------|---------------------------|----------------|-------------------------| +| minute (0-59) | second (0-59) | hour (0 - 23) | day of the month (1 - 31) | month (1 - 12) | day of the week (0 - 6) | + +Here are some examples for you. + +| Cron expression | Schedule | +|-----------------|---------------------------------------| +| * * * * * * | Every second | +| 0 * * * * * | Every minute | +| 0 0 * * * * | Every hour | +| 0 0 0 * * * | Every day at 12:00 AM | +| 0 0 0 * * FRI | At 12:00 AM, only on Friday | +| 0 0 0 1 * * | At 12:00 AM, on day 1 of the month | diff --git a/plugins/time/plugin.go b/plugins/time/plugin.go new file mode 100644 index 000000000..9b8e546e4 --- /dev/null +++ b/plugins/time/plugin.go @@ -0,0 +1,120 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2016-2023, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package time + +import ( + "context" + "embed" + "sync" + + "github.com/e154/smart-home/common/logger" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/supervisor" +) + +var ( + log = logger.MustGetLogger("plugins.time") +) + +var _ supervisor.Pluggable = (*plugin)(nil) + +//go:embed *.md +var F embed.FS + +func init() { + supervisor.RegisterPlugin(Name, New) +} + +type plugin struct { + *supervisor.Plugin + actorsLock *sync.Mutex + registrar triggers.IRegistrar +} + +// New ... +func New() supervisor.Pluggable { + p := &plugin{ + Plugin: supervisor.NewPlugin(), + actorsLock: &sync.Mutex{}, + } + p.F = F + return p +} + +// Load ... +func (p *plugin) Load(ctx context.Context, service supervisor.Service) (err error) { + if err = p.Plugin.Load(ctx, service, nil); err != nil { + return + } + + // register trigger + if triggersPlugin, ok := service.Plugins()[triggers.Name]; ok { + if p.registrar, ok = triggersPlugin.(triggers.IRegistrar); ok { + if err = p.registrar.RegisterTrigger(NewTrigger(p.Service.EventBus(), p.Service.Scheduler())); err != nil { + log.Error(err.Error()) + return + } + } + } + + return nil +} + +// Unload ... +func (p *plugin) Unload(ctx context.Context) (err error) { + if err = p.Plugin.Unload(ctx); err != nil { + return + } + + if err = p.registrar.UnregisterTrigger(Name); err != nil { + log.Error(err.Error()) + return err + } + + return nil +} + +// Name ... +func (p *plugin) Name() string { + return Name +} + +// Type ... +func (p *plugin) Type() supervisor.PluginType { + return supervisor.PluginInstallable +} + +// Depends ... +func (p *plugin) Depends() []string { + return []string{"triggers"} +} + +// Version ... +func (p *plugin) Version() string { + return Version +} + +// Options ... +func (p *plugin) Options() m.PluginOptions { + return m.PluginOptions{ + Triggers: true, + TriggerParams: NewTriggerParams(), + } +} diff --git a/plugins/triggers/time_trigger.go b/plugins/time/trigger.go similarity index 71% rename from plugins/triggers/time_trigger.go rename to plugins/time/trigger.go index ba44561ac..dbfe6a27d 100644 --- a/plugins/triggers/time_trigger.go +++ b/plugins/time/trigger.go @@ -16,7 +16,7 @@ // License along with this library. If not, see // . -package triggers +package time import ( "fmt" @@ -25,64 +25,61 @@ import ( "time" "github.com/e154/bus" - "github.com/e154/smart-home/system/scheduler" -) -const ( - // TimeName ... - TimeName = "time" - // TimeFunctionName ... - TimeFunctionName = "automationTriggerTime" - // TimeQueueSize ... - TimeQueueSize = 10 + "github.com/e154/smart-home/plugins/triggers" + "github.com/e154/smart-home/system/scheduler" ) -var _ ITrigger = (*TimeTrigger)(nil) +var _ triggers.ITrigger = (*Trigger)(nil) type subscribe struct { callback reflect.Value entryID scheduler.EntryID } -// TimeTrigger ... -type TimeTrigger struct { - baseTrigger - scheduler *scheduler.Scheduler +// Trigger ... +type Trigger struct { + eventBus bus.Bus + functionName string + name string + scheduler *scheduler.Scheduler sync.Mutex subscribers map[string][]*subscribe } -// NewTimeTrigger ... -func NewTimeTrigger(eventBus bus.Bus, - scheduler *scheduler.Scheduler) ITrigger { - - return &TimeTrigger{ - scheduler: scheduler, - subscribers: make(map[string][]*subscribe), - baseTrigger: baseTrigger{ - eventBus: eventBus, - msgQueue: bus.NewBus(), - functionName: TimeFunctionName, - name: TimeName, - }, +// NewTrigger ... +func NewTrigger(eventBus bus.Bus, + scheduler *scheduler.Scheduler) triggers.ITrigger { + + return &Trigger{ + eventBus: eventBus, + scheduler: scheduler, + subscribers: make(map[string][]*subscribe), + functionName: FunctionName, + name: Name, } } +// Name ... +func (t *Trigger) Name() string { + return t.name +} + // AsyncAttach ... -func (t *TimeTrigger) AsyncAttach(wg *sync.WaitGroup) { +func (t *Trigger) AsyncAttach(wg *sync.WaitGroup) { wg.Done() } // Subscribe ... -func (t *TimeTrigger) Subscribe(options Subscriber) error { +func (t *Trigger) Subscribe(options triggers.Subscriber) error { if options.Payload == nil { return fmt.Errorf("payload is nil") } - if _, ok := options.Payload[CronOptionTrigger]; !ok { + if _, ok := options.Payload[AttrCron]; !ok { return fmt.Errorf("cron attribute is nil") } - schedule := options.Payload[CronOptionTrigger].String() + schedule := options.Payload[AttrCron].String() if schedule == "" { return fmt.Errorf("error static cast to string %v", options.Payload) } @@ -107,11 +104,11 @@ func (t *TimeTrigger) Subscribe(options Subscriber) error { } // Unsubscribe ... -func (t *TimeTrigger) Unsubscribe(options Subscriber) error { +func (t *Trigger) Unsubscribe(options triggers.Subscriber) error { if options.Payload == nil { return fmt.Errorf("payload is nil") } - schedule := options.Payload[CronOptionTrigger].String() + schedule := options.Payload[AttrCron].String() if schedule == "" { return fmt.Errorf("error static cast to string %v", options.Payload) } @@ -136,3 +133,8 @@ func (t *TimeTrigger) Unsubscribe(options Subscriber) error { return nil } + +// FunctionName ... +func (t *Trigger) FunctionName() string { + return t.functionName +} diff --git a/plugins/time/types.go b/plugins/time/types.go new file mode 100644 index 000000000..0e2e3dd37 --- /dev/null +++ b/plugins/time/types.go @@ -0,0 +1,49 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 2024, Filippov Alex +// +// This library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library. If not, see +// . + +package time + +import ( + "github.com/e154/smart-home/common" + m "github.com/e154/smart-home/models" +) + +const ( + FunctionName = "automationTriggerTime" + Name = "time" + Version = "0.0.1" + AttrCron = "cron" + AttrSystemInfo = "SystemInfo" +) + +func NewTriggerParams() m.TriggerParams { + return m.TriggerParams{ + Script: true, + Required: []string{AttrCron}, + Attributes: m.Attributes{ + AttrSystemInfo: { + Name: AttrSystemInfo, + Type: common.AttributeNotice, + }, + AttrCron: { + Name: AttrCron, + Type: common.AttributeString, + }, + }, + } +} diff --git a/plugins/triggers/plugin.go b/plugins/triggers/plugin.go index 860be6177..f4f35e036 100644 --- a/plugins/triggers/plugin.go +++ b/plugins/triggers/plugin.go @@ -1,6 +1,6 @@ // This file is part of the Smart Home // Program complex distribution https://github.com/e154/smart-home -// Copyright (C) 2016-2023, Filippov Alex +// Copyright (C) 2016-2024, Filippov Alex // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,15 +24,12 @@ import ( "fmt" "sync" - "github.com/e154/smart-home/system/supervisor" + "github.com/pkg/errors" "github.com/e154/smart-home/common/apperr" - "github.com/e154/smart-home/common/logger" - - "github.com/pkg/errors" - m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/system/supervisor" ) var ( @@ -95,11 +92,6 @@ func (p *plugin) attachTrigger() { p.mu.Lock() defer p.mu.Unlock() - // init triggers ... - p.triggers[StateChangeName] = NewStateChangedTrigger(p.Service.EventBus()) - p.triggers[SystemName] = NewSystemTrigger(p.Service.EventBus()) - p.triggers[TimeName] = NewTimeTrigger(p.Service.EventBus(), p.Service.Scheduler()) - wg := &sync.WaitGroup{} for _, tr := range p.triggers { diff --git a/plugins/triggers/types.go b/plugins/triggers/types.go index 9d0da05e9..397d0c3e1 100644 --- a/plugins/triggers/types.go +++ b/plugins/triggers/types.go @@ -19,12 +19,9 @@ package triggers import ( - "sync" - "time" - "github.com/e154/smart-home/common" - "github.com/e154/smart-home/common/events" m "github.com/e154/smart-home/models" + "sync" ) const ( @@ -65,33 +62,3 @@ type Subscriber struct { Handler interface{} Payload m.Attributes } - -const ( - // CronOptionTrigger ... - CronOptionTrigger = "cron" -) - -type SystemTriggerMessage struct { - Topic string `json:"topic"` - EventName string `json:"event_name"` - Event interface{} `json:"event"` -} - -type EventEntityState struct { - EntityId common.EntityId `json:"entity_id"` - Value interface{} `json:"value"` - State *events.EntityState `json:"state"` - Attributes m.AttributeValue `json:"attributes"` - Settings m.AttributeValue `json:"settings"` - LastChanged *time.Time `json:"last_changed"` - LastUpdated *time.Time `json:"last_updated"` -} - -type TriggerStateChangedMessage struct { - StorageSave bool `json:"storage_save"` - DoNotSaveMetric bool `json:"do_not_save_metric"` - PluginName string `json:"plugin_name"` - EntityId common.EntityId `json:"entity_id"` - OldState EventEntityState `json:"old_state"` - NewState EventEntityState `json:"new_state"` -} diff --git a/plugins/uptime/uptime.go b/plugins/uptime/uptime.go index ad6193a2c..792e1539e 100644 --- a/plugins/uptime/uptime.go +++ b/plugins/uptime/uptime.go @@ -21,7 +21,7 @@ package uptime -import "github.com/shirou/gopsutil/v3/host" +import "github.com/shirou/gopsutil/v4/host" func GetUptime() (uint64, error) { return host.Uptime() diff --git a/static_source/admin/src/api/stub.ts b/static_source/admin/src/api/stub.ts index b8a3d6c7a..4390630b8 100644 --- a/static_source/admin/src/api/stub.ts +++ b/static_source/admin/src/api/stub.ts @@ -925,7 +925,6 @@ export interface ApiNewTriggerRequest { name: string; description: string; entityIds: string[]; - script?: ApiScript; /** @format int64 */ scriptId?: number; pluginName: string; @@ -993,6 +992,14 @@ export interface ApiPluginOptionsResult { actorCustomSetts: boolean; actorSetts: Record; setts: Record; + triggerParams: ApiTriggerParams; +} + +export interface ApiTriggerParams { + required: string[]; + script: boolean; + entities: boolean; + attributes: Record; } export interface ApiPluginOptionsResultEntityAction { @@ -4678,6 +4685,7 @@ export class Api extends HttpClient extends HttpClient diff --git a/static_source/admin/src/components/AreaSearch/src/AreaSearch.vue b/static_source/admin/src/components/AreaSearch/src/AreaSearch.vue index e78c3c8e0..ce286d7e9 100644 --- a/static_source/admin/src/components/AreaSearch/src/AreaSearch.vue +++ b/static_source/admin/src/components/AreaSearch/src/AreaSearch.vue @@ -23,6 +23,9 @@ watch( areaName.value = val?.name || null; currentArea.value = val || null; }, + { + immediate: true, + } ) // 监听 @@ -64,7 +67,7 @@ const handleSelect = (val: ApiArea) => { class="w-[100%]" v-model="areaName" :fetch-suggestions="querySearchAsync" - placeholder="Please input" + placeholder="Please select area" value-key="name" clearable @select="handleSelect" diff --git a/static_source/admin/src/components/CronFormHelper/index.ts b/static_source/admin/src/components/CronFormHelper/index.ts deleted file mode 100644 index ebbc50dc9..000000000 --- a/static_source/admin/src/components/CronFormHelper/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import CronFormHelper from './src/CronFormHelper.vue' - -export {CronFormHelper} diff --git a/static_source/admin/src/components/CronFormHelper/src/CronFormHelper.vue b/static_source/admin/src/components/CronFormHelper/src/CronFormHelper.vue deleted file mode 100644 index 9faddd80b..000000000 --- a/static_source/admin/src/components/CronFormHelper/src/CronFormHelper.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - - diff --git a/static_source/admin/src/components/Form/src/componentMap.ts b/static_source/admin/src/components/Form/src/componentMap.ts index 82b23fa9a..e88732a85 100644 --- a/static_source/admin/src/components/Form/src/componentMap.ts +++ b/static_source/admin/src/components/Form/src/componentMap.ts @@ -1,21 +1,21 @@ import type {Component} from 'vue' import { - ElAutocomplete, - ElCascader, - ElCheckboxGroup, - ElDatePicker, - ElDivider, - ElInput, - ElInputNumber, - ElRadioGroup, - ElRate, - ElSelect, - ElSelectV2, - ElSlider, - ElSwitch, - ElTimePicker, - ElTimeSelect, - ElTransfer + ElAutocomplete, + ElCascader, + ElCheckboxGroup, + ElDatePicker, + ElDivider, + ElInput, + ElInputNumber, + ElRadioGroup, + ElRate, + ElSelect, + ElSelectV2, + ElSlider, + ElSwitch, + ElTimePicker, + ElTimeSelect, + ElTransfer } from 'element-plus' import {InputPassword} from '@/components/InputPassword' import {ComponentName} from '@/types/components' @@ -30,8 +30,6 @@ import {ActionSearch} from '@/components/ActionSearch' import {ActionsSearch} from '@/components/ActionsSearch' import {ScriptsSearch} from '@/components/ScriptsSearch' import {ScriptFormHelper} from '@/components/ScriptFormHelper' -import {SystemEventsHelper} from '@/components/SystemEventsHelper' -import {CronFormHelper} from '@/components/CronFormHelper' import {TagsSearch} from '@/components/TagsSearch' import {ScriptSearch} from '@/components/ScriptSearch' import {RoleSearch} from '@/components/RoleSearch' @@ -42,46 +40,44 @@ import {VariableSearch} from "@/components/VariableSearch"; import {VariablesSearch} from "@/components/VariablesSearch"; const componentMap: Recordable = { - Radio: ElRadioGroup, - Checkbox: ElCheckboxGroup, - CheckboxButton: ElCheckboxGroup, - Input: ElInput, - Autocomplete: ElAutocomplete, - InputNumber: ElInputNumber, - Select: ElSelect, - Cascader: ElCascader, - Switch: ElSwitch, - Slider: ElSlider, - TimePicker: ElTimePicker, - DatePicker: ElDatePicker, - Rate: ElRate, - ColorPicker: ColorPicker, - Transfer: ElTransfer, - Divider: ElDivider, - TimeSelect: ElTimeSelect, - SelectV2: ElSelectV2, - RadioButton: ElRadioGroup, - InputPassword: InputPassword, - Image: ImageSearch, - Area: AreaSearch, - Role: RoleSearch, - Script: ScriptSearch, - Scripts: ScriptsSearch, - Tags: TagsSearch, - ScriptHelper: ScriptFormHelper, - SystemEventsHelper: SystemEventsHelper, - CronHelper: CronFormHelper, - Entity: EntitySearch, - Entities: EntitiesSearch, - Plugin: PluginSearch, - Trigger: TriggerSearch, - Triggers: TriggersSearch, - Condition: ConditionSearch, - Conditions: ConditionsSearch, - Action: ActionSearch, - Actions: ActionsSearch, - Variable: VariableSearch, - Variables: VariablesSearch, + Radio: ElRadioGroup, + Checkbox: ElCheckboxGroup, + CheckboxButton: ElCheckboxGroup, + Input: ElInput, + Autocomplete: ElAutocomplete, + InputNumber: ElInputNumber, + Select: ElSelect, + Cascader: ElCascader, + Switch: ElSwitch, + Slider: ElSlider, + TimePicker: ElTimePicker, + DatePicker: ElDatePicker, + Rate: ElRate, + ColorPicker: ColorPicker, + Transfer: ElTransfer, + Divider: ElDivider, + TimeSelect: ElTimeSelect, + SelectV2: ElSelectV2, + RadioButton: ElRadioGroup, + InputPassword: InputPassword, + Image: ImageSearch, + Area: AreaSearch, + Role: RoleSearch, + Script: ScriptSearch, + Scripts: ScriptsSearch, + Tags: TagsSearch, + ScriptHelper: ScriptFormHelper, + Entity: EntitySearch, + Entities: EntitiesSearch, + Plugin: PluginSearch, + Trigger: TriggerSearch, + Triggers: TriggersSearch, + Condition: ConditionSearch, + Conditions: ConditionsSearch, + Action: ActionSearch, + Actions: ActionsSearch, + Variable: VariableSearch, + Variables: VariablesSearch, } export {componentMap} diff --git a/static_source/admin/src/components/ScriptSearch/src/ScriptSearch.vue b/static_source/admin/src/components/ScriptSearch/src/ScriptSearch.vue index 3130c1881..1659313f8 100644 --- a/static_source/admin/src/components/ScriptSearch/src/ScriptSearch.vue +++ b/static_source/admin/src/components/ScriptSearch/src/ScriptSearch.vue @@ -23,6 +23,9 @@ watch( scriptName.value = val?.name || null; currentScript.value = val || null; }, + { + immediate: true + } ) // 监听 @@ -64,7 +67,7 @@ const handleSelect = (val: ApiScript) => { class="w-[100%]" v-model="scriptName" :fetch-suggestions="querySearchAsync" - placeholder="Please input" + placeholder="Please select script" value-key="name" @select="handleSelect" @change="handleChange" diff --git a/static_source/admin/src/components/SystemEventsHelper/index.ts b/static_source/admin/src/components/SystemEventsHelper/index.ts deleted file mode 100644 index a8d86c85a..000000000 --- a/static_source/admin/src/components/SystemEventsHelper/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import SystemEventsHelper from './src/SystemEventsHelper.vue' - -export {SystemEventsHelper} diff --git a/static_source/admin/src/components/SystemEventsHelper/src/SystemEventsHelper.vue b/static_source/admin/src/components/SystemEventsHelper/src/SystemEventsHelper.vue deleted file mode 100644 index 7bc5ffa41..000000000 --- a/static_source/admin/src/components/SystemEventsHelper/src/SystemEventsHelper.vue +++ /dev/null @@ -1,122 +0,0 @@ - - - - - diff --git a/static_source/admin/src/locales/en.ts b/static_source/admin/src/locales/en.ts index 3ede21e65..33b5d3dd1 100644 --- a/static_source/admin/src/locales/en.ts +++ b/static_source/admin/src/locales/en.ts @@ -351,8 +351,20 @@ export default { pluginName: 'Plugin name', addTrigger: 'Add Trigger', pluginOptions: 'Plugin Options', - timePluginOptions: 'Time Expression', - alexaSkillId: 'Alexa Skill ID' + ble: { + address: 'Address', + characteristic: 'Characteristic', + service: 'Service', + }, + time: { + cron: 'Cron', + }, + system: { + system: 'System', + }, + alexa: { + skillId: 'Skill Id' + }, }, conditions: { id: 'ID', diff --git a/static_source/admin/src/locales/ru.ts b/static_source/admin/src/locales/ru.ts index a42935178..6f71f6b41 100644 --- a/static_source/admin/src/locales/ru.ts +++ b/static_source/admin/src/locales/ru.ts @@ -351,8 +351,20 @@ export default { pluginName: "Название плагина", addTrigger: "Добавить триггер", pluginOptions: "Опции плагина", - timePluginOptions: "Выражение времени", - alexaSkillId: "Идентификатор навыка Alexa" + ble: { + address: 'Address', + characteristic: 'Characteristic', + service: 'Service', + }, + time: { + cron: 'Cron', + }, + system: { + system: 'System', + }, + alexa: { + skillId: 'Skill Id' + } }, conditions: { id: "ID", diff --git a/static_source/admin/src/types/components.d.ts b/static_source/admin/src/types/components.d.ts index 72d5cc34e..75e775624 100644 --- a/static_source/admin/src/types/components.d.ts +++ b/static_source/admin/src/types/components.d.ts @@ -31,8 +31,6 @@ export type ComponentName = | 'Scripts' | 'Tags' | 'ScriptHelper' - | 'SystemEventsHelper' - | 'CronHelper' | 'Trigger' | 'Action' | 'Condition' diff --git a/static_source/admin/src/views/Automation/Triggers/edit.vue b/static_source/admin/src/views/Automation/Triggers/edit.vue index e83e5f7ce..65637d41d 100644 --- a/static_source/admin/src/views/Automation/Triggers/edit.vue +++ b/static_source/admin/src/views/Automation/Triggers/edit.vue @@ -2,17 +2,13 @@ import {computed, ref, unref} from 'vue' import {useI18n} from '@/hooks/web/useI18n' import {ElButton, ElMessage, ElPopconfirm} from 'element-plus' -import {useForm} from '@/hooks/web/useForm' import {useRoute, useRouter} from 'vue-router' -import {useValidator} from '@/hooks/web/useValidator' import api from "@/api/api"; import Form from './components/Form.vue' -import {ApiTrigger} from "@/api/stub"; +import {ApiAttribute, ApiTrigger} from "@/api/stub"; import {ContentWrap} from "@/components/ContentWrap"; import TriggerForm from "@/views/Automation/components/TriggerForm.vue"; -const {register, elFormRef, methods} = useForm() -const {required} = useValidator() const {currentRoute, addRoute, push} = useRouter() const route = useRoute(); const {t} = useI18n() @@ -25,13 +21,21 @@ const currentRow = ref>(null) const fetch = async () => { loading.value = true const res = await api.v1.triggerServiceGetTriggerById(triggerId.value) - .catch(() => { - }) - .finally(() => { - loading.value = false - }) + .catch(() => { + }) + .finally(() => { + loading.value = false + }) if (res) { currentRow.value = res.data; + if (currentRow.value.attributes) { + for (const key in currentRow.value.attributes) { + if (key == 'notice') { + continue + } + currentRow.value.attributes[key].name = key + } + } } else { currentRow.value = null } @@ -39,48 +43,44 @@ const fetch = async () => { const save = async () => { const write = unref(writeRef) - const validate = await write?.elFormRef?.validate()?.catch(() => { + const validate = await write?.form?.validate()?.catch(() => { }) - if (validate) { - loading.value = true - const tr = (await write?.getFormData()) as ApiTrigger; - let data = { - name: tr.name, - description: tr.description, - entityIds: tr.entityIds || [], - scriptId: tr.script?.id || null, - areaId: tr.area?.id || null, - pluginName: tr.pluginName, - attributes: {}, - enabled: tr.enabled, - } - if (tr.pluginName === 'time') { - data.attributes['cron'] = { - string: tr?.timePluginOptions || '', - type: "STRING", - } - } - if (tr.pluginName === 'system') { - data.attributes['system'] = { - string: tr?.systemPluginOptions || '', - type: "STRING", - } - } - const res = await api.v1.triggerServiceUpdateTrigger(triggerId.value, data) - .catch(() => { - }) - .finally(() => { - loading.value = false - }) - if (res) { - ElMessage({ - title: t('Success'), - message: t('message.updatedSuccessfully'), - type: 'success', - duration: 2000 - }) - } + if (!validate) { + return } + + const tr = unref(currentRow) + let data = { + name: tr.name, + description: tr.description, + entityIds: tr.entityIds || [], + scriptId: tr.script?.id || null, + areaId: tr.area?.id || null, + pluginName: tr.pluginName, + attributes: {}, + enabled: tr.enabled, + } + + let attributes: { [key: string]: ApiAttribute } = {}; + for (const index in tr.attributes) { + attributes[tr.attributes[index].name] = tr.attributes[index]; + } + data.attributes = attributes + + const res = await api.v1.triggerServiceUpdateTrigger(triggerId.value, data) + .catch(() => { + }) + .finally(() => { + }) + if (res) { + ElMessage({ + title: t('Success'), + message: t('message.updatedSuccessfully'), + type: 'success', + duration: 2000 + }) + } + } const cancel = () => { @@ -90,11 +90,11 @@ const cancel = () => { const remove = async () => { loading.value = true const res = await api.v1.triggerServiceDeleteTrigger(triggerId.value) - .catch(() => { - }) - .finally(() => { - loading.value = false - }) + .catch(() => { + }) + .finally(() => { + loading.value = false + }) if (res) { cancel() } @@ -102,16 +102,16 @@ const remove = async () => { const callTrigger = async () => { await api.v1.developerToolsServiceCallTrigger({id: triggerId.value}) - .catch(() => { - }) - .finally(() => { - ElMessage({ - title: t('Success'), - message: t('message.callSuccessful'), - type: 'success', - duration: 2000 - }) + .catch(() => { + }) + .finally(() => { + ElMessage({ + title: t('Success'), + message: t('message.callSuccessful'), + type: 'success', + duration: 2000 }) + }) } fetch() @@ -138,12 +138,12 @@ fetch()