From ef7dc3a24bfa94799e090328fe57244cb1622887 Mon Sep 17 00:00:00 2001 From: Filippov Alex Date: Sun, 11 Aug 2024 23:46:14 +0530 Subject: [PATCH] added mdns plugin (#284) --- api/api.go | 44 ++++-- cmd/server/container/init.go | 1 + doc/content/en/docs/plugins/mdns.md | 10 ++ doc/content/ru/docs/plugins/mdns.md | 10 ++ go.mod | 2 + go.sum | 6 + plugins/mdns/Readme.md | 3 + plugins/mdns/Readme.ru.md | 3 + plugins/mdns/actor.go | 162 ++++++++++++++++++++++ plugins/mdns/mdns.go | 100 +++++++++++++ plugins/mdns/plugin.go | 133 ++++++++++++++++++ plugins/mdns/types.go | 96 +++++++++++++ plugins/plugins.go | 1 + system/gate/server/server.go | 10 ++ system/initial/local_migrations/m_mdns.go | 46 ++++++ system/mqtt/mqtt.go | 10 ++ 16 files changed, 625 insertions(+), 12 deletions(-) create mode 100755 doc/content/en/docs/plugins/mdns.md create mode 100755 doc/content/ru/docs/plugins/mdns.md create mode 100644 plugins/mdns/Readme.md create mode 100644 plugins/mdns/Readme.ru.md create mode 100644 plugins/mdns/actor.go create mode 100644 plugins/mdns/mdns.go create mode 100644 plugins/mdns/plugin.go create mode 100644 plugins/mdns/types.go create mode 100644 system/initial/local_migrations/m_mdns.go diff --git a/api/api.go b/api/api.go index 12dbe48eb..21467e8ad 100644 --- a/api/api.go +++ b/api/api.go @@ -26,13 +26,14 @@ import ( "strings" "time" + "github.com/e154/bus" + "github.com/grandcat/zeroconf" echopprof "github.com/hiko1129/echo-pprof" echoCacheMiddleware "github.com/kenshin579/echo-http-cache" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "go.uber.org/atomic" - "github.com/e154/bus" "github.com/e154/smart-home/adaptors" "github.com/e154/smart-home/api/controllers" "github.com/e154/smart-home/api/stub" @@ -48,17 +49,19 @@ var ( // Api ... type Api struct { - controllers *controllers.Controllers - echoFilter *rbac.EchoAccessFilter - echo *echo.Echo - cfg Config - certPublic string - certKey string - adaptors *adaptors.Adaptors - eventBus bus.Bus - httpServer http.Server - tlsServer http.Server - tlsStarted *atomic.Bool + controllers *controllers.Controllers + echoFilter *rbac.EchoAccessFilter + echo *echo.Echo + cfg Config + certPublic string + certKey string + adaptors *adaptors.Adaptors + eventBus bus.Bus + httpServer http.Server + tlsServer http.Server + tlsStarted *atomic.Bool + httpZeroconf *zeroconf.Server + httpsZeroconf *zeroconf.Server } // NewApi ... @@ -134,6 +137,7 @@ func (a *Api) Start() (err error) { go a.startTlsServer() go a.startServer() + go a.startZeroconf() a.eventBus.Subscribe("system/models/variables/+", a.eventHandler, false) a.eventBus.Publish("system/services/api", events.EventServiceStarted{Service: "Api"}) @@ -148,6 +152,12 @@ func (a *Api) Shutdown(ctx context.Context) (err error) { if a.echo != nil { err = a.echo.Shutdown(ctx) } + if a.httpZeroconf != nil { + a.httpZeroconf.Shutdown() + } + if a.httpsZeroconf != nil { + a.httpsZeroconf.Shutdown() + } a.eventBus.Unsubscribe("system/models/variables/+", a.eventHandler) a.eventBus.Publish("system/services/api", events.EventServiceStopped{Service: "Api"}) @@ -200,6 +210,16 @@ func (a *Api) startTlsServer() { } } +func (a *Api) startZeroconf() { + var err error + if a.httpZeroconf, err = zeroconf.Register("smart-home", "_http._tcp", "local.", a.cfg.HttpPort, nil, nil); err != nil { + log.Error(err.Error()) + } + if a.httpsZeroconf, err = zeroconf.Register("smart-home", "_https._tcp", "local.", a.cfg.HttpsPort, nil, nil); err != nil { + log.Error(err.Error()) + } +} + func (a *Api) registerHandlers() { // Swagger diff --git a/cmd/server/container/init.go b/cmd/server/container/init.go index 6335f994c..a55343600 100644 --- a/cmd/server/container/init.go +++ b/cmd/server/container/init.go @@ -62,5 +62,6 @@ func MigrationList(adaptors *adaptors.Adaptors, local_migrations.NewMigrationPachka(adaptors), local_migrations.NewMigrationWebhook(adaptors), local_migrations.NewMigrationRemoveTriggersPlugin(adaptors), + local_migrations.NewMigrationMdns(adaptors), } } diff --git a/doc/content/en/docs/plugins/mdns.md b/doc/content/en/docs/plugins/mdns.md new file mode 100755 index 000000000..47f220ac6 --- /dev/null +++ b/doc/content/en/docs/plugins/mdns.md @@ -0,0 +1,10 @@ + +--- +title: "mDNS" +linkTitle: "mDNS" +date: 2024-08-11 +description: > + +--- + +WIP diff --git a/doc/content/ru/docs/plugins/mdns.md b/doc/content/ru/docs/plugins/mdns.md new file mode 100755 index 000000000..47f220ac6 --- /dev/null +++ b/doc/content/ru/docs/plugins/mdns.md @@ -0,0 +1,10 @@ + +--- +title: "mDNS" +linkTitle: "mDNS" +date: 2024-08-11 +description: > + +--- + +WIP diff --git a/go.mod b/go.mod index f4aa7e350..d10a056b5 100644 --- a/go.mod +++ b/go.mod @@ -109,6 +109,7 @@ require ( github.com/bytedance/sonic v1.11.7 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect @@ -134,6 +135,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect github.com/gorilla/css v1.0.1 // indirect + github.com/grandcat/zeroconf v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect diff --git a/go.sum b/go.sum index daeccb87f..a7519793e 100644 --- a/go.sum +++ b/go.sum @@ -436,6 +436,8 @@ github.com/caddyserver/certmagic v0.21.2 h1:O18LtaYBGDooyy257cYePnhp4lPfz6TaJELi github.com/caddyserver/certmagic v0.21.2/go.mod h1:Zq6pklO9nVRl3DIFUw9gVUfXKdpc/0qwTUAQMBlfgtI= github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -722,6 +724,8 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE= +github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -927,6 +931,7 @@ github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3r github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= @@ -1595,6 +1600,7 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= diff --git a/plugins/mdns/Readme.md b/plugins/mdns/Readme.md new file mode 100644 index 000000000..63683f2f1 --- /dev/null +++ b/plugins/mdns/Readme.md @@ -0,0 +1,3 @@ +### mDns Plugin + +[Documentation](https://e154.github.io/smart-home/docs/plugins/mdns/) diff --git a/plugins/mdns/Readme.ru.md b/plugins/mdns/Readme.ru.md new file mode 100644 index 000000000..0aa73ad66 --- /dev/null +++ b/plugins/mdns/Readme.ru.md @@ -0,0 +1,3 @@ +### Плагин mDns + +[Документация](https://e154.github.io/smart-home/ru/docs/plugins/mdns/) diff --git a/plugins/mdns/actor.go b/plugins/mdns/actor.go new file mode 100644 index 000000000..3a9ecf6a1 --- /dev/null +++ b/plugins/mdns/actor.go @@ -0,0 +1,162 @@ +// 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 mdns + +import ( + "strings" + + "github.com/pkg/errors" + + "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 + dns *Dns +} + +// NewActor ... +func NewActor(entity *m.Entity, + service supervisor.Service) (actor *Actor) { + + actor = &Actor{ + BaseActor: supervisor.NewBaseActor(entity, service), + actionPool: make(chan events.EventCallEntityAction, 1000), + dns: NewDns(), + } + + // action worker + go func() { + for msg := range actor.actionPool { + actor.runAction(msg) + } + }() + + if actor.Setts == nil { + actor.Setts = NewSettings() + } + + if actor.Actions == nil { + actor.Actions = NewActions() + } + + return actor +} + +func (e *Actor) Destroy() { + e.dns.Shutdown() +} + +func (e *Actor) Spawn() { + + var instance string + if e.Setts[AttrInstance] != nil { + instance = e.Setts[AttrInstance].String() + } + + var service string + if e.Setts[AttrService] != nil { + service = e.Setts[AttrService].String() + } + + var ipAddr string + if e.Setts[AttrIpAddr] != nil { + ipAddr = e.Setts[AttrIpAddr].String() + } + + var domain string + if e.Setts[AttrDomain] != nil { + domain = e.Setts[AttrDomain].String() + } + + var host string + if e.Setts[AttrHost] != nil { + host = e.Setts[AttrHost].String() + } + + var text []string + if e.Setts[AttrText] != nil { + text = strings.Split(strings.TrimSpace(e.Setts[AttrText].String()), ",") + } + + var port int64 + if e.Setts[AttrPort] != nil { + port = e.Setts[AttrPort].Int64() + } + + if domain == "" { + domain = DefaultDomain + } + if !strings.Contains(domain, ".") { + domain += "." + } + + go e.dns.Register(instance, service, domain, ipAddr, host, port, text) + + 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) { + + var service string + if e.Setts[AttrService] != nil { + service = e.Setts[AttrService].String() + } + + var domain string + if e.Setts[AttrDomain] != nil { + domain = e.Setts[AttrDomain].String() + } + + if strings.ToUpper(msg.ActionName) == ActionScan { + e.dns.Scan(service, domain) + } + + 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/mdns/mdns.go b/plugins/mdns/mdns.go new file mode 100644 index 000000000..475df8754 --- /dev/null +++ b/plugins/mdns/mdns.go @@ -0,0 +1,100 @@ +// 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 mdns + +import ( + "context" + "encoding/json" + "time" + + "go.uber.org/atomic" + + "github.com/grandcat/zeroconf" +) + +type Dns struct { + server *zeroconf.Server + isScan *atomic.Bool +} + +func NewDns() *Dns { + return &Dns{ + isScan: atomic.NewBool(false), + } +} + +func (d *Dns) Scan(service, domain string) { + if !d.isScan.CompareAndSwap(false, true) { + return + } + + defer func() { + d.isScan.Store(false) + }() + + log.Info("Starting scanning ...") + + resolver, err := zeroconf.NewResolver(nil) + if err != nil { + log.Error(err.Error()) + return + } + + entries := make(chan *zeroconf.ServiceEntry) + go func(results <-chan *zeroconf.ServiceEntry) { + for entry := range results { + j, _ := json.MarshalIndent(entry, " ", " ") + log.Info(string(j)) + } + log.Info("No more entries.") + }(entries) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + err = resolver.Browse(ctx, service, domain, entries) + if err != nil { + log.Error(err.Error()) + } + + <-ctx.Done() + // Wait some additional time to see debug messages on go routine shutdown. + time.Sleep(1 * time.Second) +} + +func (d *Dns) Register(instance, service, domain, ipAddr, host string, port int64, text []string) { + var err error + if ipAddr != "" { + log.Infof("Registering proxy instance(%s) host(%s) service(%s) domain(%s) port(%d) text(%v) on network", instance, host, service, domain, port, text) + d.server, err = zeroconf.RegisterProxy(instance, service, domain, int(port), host, []string{ipAddr}, text, nil) + } else { + log.Infof("Published service instance(%s) service(%s) domain(%s) port(%d) text(%v) on network", instance, service, domain, port, text) + d.server, err = zeroconf.Register(instance, service, domain, int(port), text, nil) + } + if err != nil { + log.Error(err.Error()) + return + } +} + +func (d *Dns) Shutdown() { + if d.server != nil { + d.server.Shutdown() + } + d.server = nil +} diff --git a/plugins/mdns/plugin.go b/plugins/mdns/plugin.go new file mode 100644 index 000000000..59846bec7 --- /dev/null +++ b/plugins/mdns/plugin.go @@ -0,0 +1,133 @@ +// 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 mdns + +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.mdns") +) + +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 +} + +// 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 + } + + _ = 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) + 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: false, + Actors: true, + ActorCustomAttrs: false, + ActorAttrs: nil, + ActorCustomActions: false, + ActorActions: supervisor.ToEntityActionShort(NewActions()), + ActorCustomStates: false, + ActorStates: nil, + ActorCustomSetts: false, + ActorSetts: NewSettings(), + Setts: nil, + } +} diff --git a/plugins/mdns/types.go b/plugins/mdns/types.go new file mode 100644 index 000000000..13a1148e7 --- /dev/null +++ b/plugins/mdns/types.go @@ -0,0 +1,96 @@ +// 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 mdns + +import ( + "github.com/e154/smart-home/common" + m "github.com/e154/smart-home/models" + "github.com/e154/smart-home/system/supervisor" +) + +const ( + // Name ... + Name = "mdns" + // FuncEntityAction ... + FuncEntityAction = "entityAction" + + Version = "0.0.1" + + AttrInstance = "instance" + AttrService = "service" + AttrDomain = "domain" + AttrHost = "host" + AttrPort = "port" + AttrIpAddr = "ipAddr" + AttrText = "text" + ActionScan = "SCAN" + + DefaultService = "_workstation._tcp" + DefaultDomain = "local" +) + +// NewSettings ... +func NewSettings() map[string]*m.Attribute { + return map[string]*m.Attribute{ + AttrInstance: { + Name: AttrInstance, + Type: common.AttributeString, + Value: "escapepod", + }, + AttrService: { + Name: AttrService, + Type: common.AttributeString, + Value: DefaultService, + }, + AttrDomain: { + Name: AttrDomain, + Type: common.AttributeString, + Value: DefaultDomain, + }, + AttrIpAddr: { + Name: AttrIpAddr, + Type: common.AttributeString, + Value: "", + }, + AttrText: { + Name: AttrText, + Type: common.AttributeString, + Value: "txtv=0, lo=1, la=2", + }, + AttrHost: { + Name: AttrHost, + Type: common.AttributeString, + Value: "escapepod", + }, + AttrPort: { + Name: AttrPort, + Type: common.AttributeInt, + Value: 8084, + }, + } +} + +func NewActions() map[string]supervisor.ActorAction { + return map[string]supervisor.ActorAction{ + ActionScan: { + Name: ActionScan, + Description: "Scanning for devices begins. It stops after 10 seconds.", + }, + } +} diff --git a/plugins/plugins.go b/plugins/plugins.go index 51614b47c..a8dbb33cb 100644 --- a/plugins/plugins.go +++ b/plugins/plugins.go @@ -30,6 +30,7 @@ import ( _ "github.com/e154/smart-home/plugins/hdd" _ "github.com/e154/smart-home/plugins/html5_notify" _ "github.com/e154/smart-home/plugins/logs" + _ "github.com/e154/smart-home/plugins/mdns" _ "github.com/e154/smart-home/plugins/memory" _ "github.com/e154/smart-home/plugins/memory_app" _ "github.com/e154/smart-home/plugins/messagebird" diff --git a/system/gate/server/server.go b/system/gate/server/server.go index 7356fa411..2f1b5e546 100644 --- a/system/gate/server/server.go +++ b/system/gate/server/server.go @@ -23,6 +23,7 @@ import ( "net/http" "strings" + "github.com/grandcat/zeroconf" echopprof "github.com/hiko1129/echo-pprof" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" @@ -39,6 +40,7 @@ type Server struct { echo *echo.Echo proxy *wsp.Server cfg *Config + zeroconf *zeroconf.Server } func NewServer(cfg *Config, proxy *wsp.Server) *Server { @@ -122,6 +124,14 @@ func (a *Server) Start() (err error) { } }() + if a.zeroconf, _ = zeroconf.Register("smart-home-gate", "_https._tcp", "local.", a.cfg.HttpsPort, nil, nil); err != nil { + log.Error(err.Error()) + } + + if a.zeroconf, _ = zeroconf.Register("smart-home-gate", "_http._tcp", "local.", a.cfg.HttpPort, nil, nil); err != nil { + log.Error(err.Error()) + } + return } diff --git a/system/initial/local_migrations/m_mdns.go b/system/initial/local_migrations/m_mdns.go new file mode 100644 index 000000000..cbaa080f3 --- /dev/null +++ b/system/initial/local_migrations/m_mdns.go @@ -0,0 +1,46 @@ +// This file is part of the Smart Home +// Program complex distribution https://github.com/e154/smart-home +// Copyright (C) 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 local_migrations + +import ( + "context" + + "github.com/e154/smart-home/adaptors" + "github.com/e154/smart-home/plugins/webhook" +) + +type MigrationMdns struct { + Common +} + +func NewMigrationMdns(adaptors *adaptors.Adaptors) *MigrationMdns { + return &MigrationMdns{ + Common{ + adaptors: adaptors, + }, + } +} + +func (n *MigrationMdns) Up(ctx context.Context, adaptors *adaptors.Adaptors) error { + if adaptors != nil { + n.adaptors = adaptors + } + + return n.addPlugin(ctx, "mdns", false, false, true, webhook.Version) +} diff --git a/system/mqtt/mqtt.go b/system/mqtt/mqtt.go index 249e1193d..1564d555c 100644 --- a/system/mqtt/mqtt.go +++ b/system/mqtt/mqtt.go @@ -32,6 +32,7 @@ import ( "github.com/DrmagicE/gmqtt/pkg/packets" "github.com/DrmagicE/gmqtt/server" _ "github.com/DrmagicE/gmqtt/topicalias/fifo" + "github.com/grandcat/zeroconf" "go.uber.org/fx" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -61,6 +62,7 @@ type Mqtt struct { admin *admin.Admin scriptService scripts.ScriptService eventBus bus.Bus + zeroconf *zeroconf.Server } // NewMqtt ... @@ -115,6 +117,10 @@ func (m *Mqtt) Shutdown() (err error) { err = m.server.Stop(ctx) } + if m.zeroconf != nil { + m.zeroconf.Shutdown() + } + m.eventBus.Publish("system/services/mqtt", events.EventServiceStopped{Service: "Mqtt"}) return } @@ -168,6 +174,10 @@ func (m *Mqtt) Start() { } }() + if m.zeroconf, err = zeroconf.Register("smart-home", "_mqtt._tcp", "local.", m.cfg.Port, nil, nil); err != nil { + log.Error(err.Error()) + } + m.eventBus.Publish("system/services/mqtt", events.EventServiceStarted{Service: "Mqtt"}) }