Merge pull request #313 from OktopUSP/dev

Dev
This commit is contained in:
Leandro Antônio Farias Machado 2024-07-10 16:06:38 -03:00 committed by GitHub
commit 88027ae773
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
69 changed files with 1664 additions and 690 deletions

View File

@ -14,7 +14,7 @@ Oktopus is a multi-vendor management platform for CPEs and IoTs. <b>Any device t
<a href="https://www.inango.com/" target="_blank"><img src="https://github.com/OktopUSP/oktopus/assets/83298718/3b3e65d9-33fa-46c4-8b24-f9e2a84a04a6" width="100px"/></a> <a href="https://www.inango.com/" target="_blank"><img src="https://github.com/OktopUSP/oktopus/assets/83298718/3b3e65d9-33fa-46c4-8b24-f9e2a84a04a6" width="100px"/></a>
<p>If you'd like to become a sponsor, start a partnership or somehow to contribute to the project, email <a href="">leandro@oktopus.app.br</a>, every contribution is welcome, and the resources will help the project to move on. Also, if your company uses this project and you'd like your logo to appear up here, contact us. <p>If you'd like to become a sponsor, start a partnership or somehow to contribute to the project, email <a href="">contact@oktopus.app.br</a>, every contribution is welcome, and the resources will help the project to move on. Also, if your company uses this project and you'd like your logo to appear up here, contact us.
<ul> <ul>
<li> <li>
@ -23,7 +23,7 @@ Oktopus is a multi-vendor management platform for CPEs and IoTs. <b>Any device t
<p> <p>
Our solution has an open-source software license, meaning you can modify/study the code and use it for free. You can perform all the configurations, allocate servers, and set it up on your network with the classic "do it yourself" approach, or save time and money: contact us for a quote and get commercial support. Our solution has an open-source software license, meaning you can modify/study the code and use it for free. You can perform all the configurations, allocate servers, and set it up on your network with the classic "do it yourself" approach, or save time and money: contact us for a quote and get commercial support.
</p> </p>
<p>Contact <a href="">leandro@oktopus.app.br</a> via email and get a quote.</p> <p>Contact <a href="">sales@oktopus.app.br</a> via email and get a quote.</p>
</li> </li>
</ul> </ul>

View File

@ -16,7 +16,8 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
@ -40,6 +41,12 @@ type Config struct {
Nats Nats Nats Nats
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
func NewConfig() *Config { func NewConfig() *Config {
loadEnvVariables() loadEnvVariables()
@ -47,7 +54,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
acsPort := flag.String("acs_port", lookupEnvOrString("ACS_PORT", ":9292"), "port for acs server") acsPort := flag.String("acs_port", lookupEnvOrString("ACS_PORT", ":9292"), "port for acs server")
acsRoute := flag.String("acs_route", lookupEnvOrString("ACS_ROUTE", "/acs"), "route for acs server") acsRoute := flag.String("acs_route", lookupEnvOrString("ACS_ROUTE", "/acs"), "route for acs server")
connReqUser := flag.String("connrq_user", lookupEnvOrString("CONN_RQ_USER", ""), "Connection Request Username") connReqUser := flag.String("connrq_user", lookupEnvOrString("CONN_RQ_USER", ""), "Connection Request Username")
@ -79,8 +89,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Acs: Acs{ Acs: Acs{
Port: *acsPort, Port: *acsPort,

View File

@ -141,8 +141,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -15,7 +15,8 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
@ -29,6 +30,12 @@ type Config struct {
Nats Nats Nats Nats
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
func NewConfig() *Config { func NewConfig() *Config {
loadEnvVariables() loadEnvVariables()
@ -36,7 +43,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "4000"), "Rest api port") flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "4000"), "Rest api port")
flHelp := flag.Bool("help", false, "Help") flHelp := flag.Bool("help", false, "Help")
@ -64,8 +74,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
} }
} }

View File

@ -70,8 +70,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -57,6 +57,13 @@ func (a *Api) StartApi() {
authentication.HandleFunc("/password", a.changePassword).Methods("PUT") authentication.HandleFunc("/password", a.changePassword).Methods("PUT")
authentication.HandleFunc("/admin/register", a.registerAdminUser).Methods("POST") authentication.HandleFunc("/admin/register", a.registerAdminUser).Methods("POST")
authentication.HandleFunc("/admin/exists", a.adminUserExists).Methods("GET") authentication.HandleFunc("/admin/exists", a.adminUserExists).Methods("GET")
if a.enterpise.Enable {
mapRoutes := r.PathPrefix("/api/map").Subrouter()
mapRoutes.HandleFunc("", a.devicesLocation).Methods("GET")
mapRoutes.Use(func(handler http.Handler) http.Handler {
return middleware.Middleware(handler)
})
}
iot := r.PathPrefix("/api/device").Subrouter() iot := r.PathPrefix("/api/device").Subrouter()
iot.HandleFunc("/alias", a.setDeviceAlias).Methods("PUT") iot.HandleFunc("/alias", a.setDeviceAlias).Methods("PUT")
iot.HandleFunc("/auth", a.deviceAuth).Methods("GET", "POST", "DELETE") iot.HandleFunc("/auth", a.deviceAuth).Methods("GET", "POST", "DELETE")

View File

@ -28,6 +28,22 @@ func (a *Api) getEnterpriseResource(
return err return err
} }
func (a *Api) getMapsResource(
action string,
w http.ResponseWriter,
body []byte,
) error {
err := bridge.NatsEnterpriseInteraction("geolocation.v1."+action, body, w, a.nc)
return err
}
func (a *Api) devicesLocation(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
a.getMapsResource("get", w, []byte{})
}
}
func (a *Api) deviceSiteSurvey(w http.ResponseWriter, r *http.Request) { func (a *Api) deviceSiteSurvey(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
sn := vars["sn"] sn := vars["sn"]

View File

@ -243,7 +243,6 @@ func adminUserExists(users []map[string]interface{}, supportEmail string) bool {
for _, x := range users { for _, x := range users {
if db.UserLevels(x["level"].(int32)) == db.AdminUser && x["email"].(string) != supportEmail { if db.UserLevels(x["level"].(int32)) == db.AdminUser && x["email"].(string) != supportEmail {
log.Println("Admin exists")
return true return true
} }
} }

View File

@ -263,7 +263,7 @@ func NatsEnterpriseInteraction(
if err != nil { if err != nil {
if err == nats.ErrNoResponders { if err == nats.ErrNoResponders {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write(utils.Marshall("You have no enterprise license, to get one contact: leandro@oktopus.app.br")) w.Write(utils.Marshall("You have no enterprise license, to get one contact: sales@oktopus.app.br"))
return err return err
} }
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)

View File

@ -15,7 +15,8 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
@ -42,6 +43,12 @@ type Config struct {
Enterprise Enterprise Enterprise Enterprise
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
func NewConfig() *Config { func NewConfig() *Config {
loadEnvVariables() loadEnvVariables()
@ -49,7 +56,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "controller"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "controller"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "8000"), "Rest api port") flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "8000"), "Rest api port")
mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server") mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server")
enterpise := flag.Bool("enterprise", lookupEnvOrBool("ENTERPRISE", false), "enterprise version enable") enterpise := flag.Bool("enterprise", lookupEnvOrBool("ENTERPRISE", false), "enterprise version enable")
@ -81,8 +91,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Mongo: Mongo{ Mongo: Mongo{
Uri: *mongoUri, Uri: *mongoUri,

View File

@ -77,8 +77,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -15,10 +15,17 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
type Mongo struct { type Mongo struct {
Uri string Uri string
Ctx context.Context Ctx context.Context
@ -42,7 +49,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server") mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server")
controllerId := flag.String("controller_id", lookupEnvOrString("CONTROLLER_ID", "oktopusController"), "usp controller endpoint id") controllerId := flag.String("controller_id", lookupEnvOrString("CONTROLLER_ID", "oktopusController"), "usp controller endpoint id")
controllerPassword := flag.String("controller_passwd", lookupEnvOrString("CONTROLLER_PASSWORD", ""), "usp controller endpoint password to connect to") controllerPassword := flag.String("controller_passwd", lookupEnvOrString("CONTROLLER_PASSWORD", ""), "usp controller endpoint password to connect to")
@ -68,8 +78,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Mongo: Mongo{ Mongo: Mongo{
Uri: *mongoUri, Uri: *mongoUri,

View File

@ -1,6 +1,7 @@
package cwmp_handler package cwmp_handler
import ( import (
"encoding/json"
"encoding/xml" "encoding/xml"
"log" "log"
@ -12,6 +13,10 @@ func (h *Handler) HandleDeviceInfo(device string, data []byte, ack func()) {
defer ack() defer ack()
log.Printf("Device %s info", device) log.Printf("Device %s info", device)
deviceInfo := parseDeviceInfoMsg(data) deviceInfo := parseDeviceInfoMsg(data)
if deviceExists, _ := h.db.DeviceExists(deviceInfo.SN); !deviceExists {
fmtDeviceInfo, _ := json.Marshal(deviceInfo)
h.nc.Publish("device.v1.new", fmtDeviceInfo)
}
err := h.db.CreateDevice(deviceInfo) err := h.db.CreateDevice(deviceInfo)
if err != nil { if err != nil {
log.Printf("Failed to create device: %v", err) log.Printf("Failed to create device: %v", err)

View File

@ -1,6 +1,7 @@
package usp_handler package usp_handler
import ( import (
"encoding/json"
"log" "log"
"github.com/OktopUSP/oktopus/backend/services/mtp/adapter/internal/db" "github.com/OktopUSP/oktopus/backend/services/mtp/adapter/internal/db"
@ -14,6 +15,10 @@ func (h *Handler) HandleDeviceInfo(device, subject string, data []byte, mtp stri
defer ack() defer ack()
log.Printf("Device %s info, mtp: %s", device, mtp) log.Printf("Device %s info, mtp: %s", device, mtp)
deviceInfo := parseDeviceInfoMsg(device, subject, data, getMtp(mtp)) deviceInfo := parseDeviceInfoMsg(device, subject, data, getMtp(mtp))
if deviceExists, _ := h.db.DeviceExists(deviceInfo.SN); !deviceExists {
fmtDeviceInfo, _ := json.Marshal(deviceInfo)
h.nc.Publish("device.v1.new", fmtDeviceInfo)
}
err := h.db.CreateDevice(deviceInfo) err := h.db.CreateDevice(deviceInfo)
if err != nil { if err != nil {
log.Printf("Failed to create device: %v", err) log.Printf("Failed to create device: %v", err)

View File

@ -150,8 +150,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -15,10 +15,17 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
type Mqtt struct { type Mqtt struct {
Url string Url string
UrlForTls string UrlForTls string
@ -42,7 +49,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "mqtt-adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "mqtt-adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
mqttUrl := flag.String("mqtt_url", lookupEnvOrString("MQTT_URL", "tcp://localhost:1883"), "url for mqtt server") mqttUrl := flag.String("mqtt_url", lookupEnvOrString("MQTT_URL", "tcp://localhost:1883"), "url for mqtt server")
mqttsUrl := flag.String("mqtts_url", lookupEnvOrString("MQTTS_URL", ""), "url for mqtts server") mqttsUrl := flag.String("mqtts_url", lookupEnvOrString("MQTTS_URL", ""), "url for mqtts server")
mqttsSkipVerify := flag.Bool("mqtts_skip_verify", lookupEnvOrBool("MQTTS_SKIP_VERIFY", false), "skip verification of server certificate for mqtts") mqttsSkipVerify := flag.Bool("mqtts_skip_verify", lookupEnvOrBool("MQTTS_SKIP_VERIFY", false), "skip verification of server certificate for mqtts")
@ -71,8 +81,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Mqtt: Mqtt{ Mqtt: Mqtt{
Url: *mqttUrl, Url: *mqttUrl,

View File

@ -92,8 +92,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -34,10 +34,17 @@ type Config struct {
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
func NewConfig() Config { func NewConfig() Config {
loadEnvVariables() loadEnvVariables()
@ -66,7 +73,10 @@ func NewConfig() Config {
logLevel := flag.Int("log_level", lookupEnvOrInt("LOG_LEVEL", 1), "0=DEBUG, 1=INFO, 2=WARNING, 3=ERROR") logLevel := flag.Int("log_level", lookupEnvOrInt("LOG_LEVEL", 1), "0=DEBUG, 1=INFO, 2=WARNING, 3=ERROR")
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
flag.Parse() flag.Parse()
flHelp := flag.Bool("help", false, "Help") flHelp := flag.Bool("help", false, "Help")
@ -101,8 +111,13 @@ func NewConfig() Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
} }

View File

@ -74,8 +74,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -15,10 +15,17 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
type Stomp struct { type Stomp struct {
Url string Url string
User string User string
@ -37,7 +44,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "mqtt-adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "mqtt-adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
stompAddr := flag.String("stomp_server", lookupEnvOrString("STOMP_SERVER", "localhost:61613"), "STOMP server endpoint") stompAddr := flag.String("stomp_server", lookupEnvOrString("STOMP_SERVER", "localhost:61613"), "STOMP server endpoint")
stompUser := flag.String("stomp_user", lookupEnvOrString("STOMP_USER", ""), "stomp server user") stompUser := flag.String("stomp_user", lookupEnvOrString("STOMP_USER", ""), "stomp server user")
stompPassword := flag.String("stomp_passsword", lookupEnvOrString("STOMP_PASSWD", ""), "stomp server password") stompPassword := flag.String("stomp_passsword", lookupEnvOrString("STOMP_PASSWD", ""), "stomp server password")
@ -63,8 +73,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Stomp: Stomp{ Stomp: Stomp{
Url: *stompAddr, Url: *stompAddr,

View File

@ -81,9 +81,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts
} }

View File

@ -15,10 +15,17 @@ const LOCAL_ENV = ".env.local"
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
type Ws struct { type Ws struct {
AuthEnable bool AuthEnable bool
Addr string Addr string
@ -42,7 +49,10 @@ func NewConfig() *Config {
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "ws-adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "ws-adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
wsAuthEnable := flag.Bool("ws_auth_enable", lookupEnvOrBool("WS_AUTH_ENABLE", false), "enable authentication for websocket server") wsAuthEnable := flag.Bool("ws_auth_enable", lookupEnvOrBool("WS_AUTH_ENABLE", false), "enable authentication for websocket server")
wsAddr := flag.String("ws_addr", lookupEnvOrString("WS_ADDR", "localhost"), "websocket server address (domain or ip)") wsAddr := flag.String("ws_addr", lookupEnvOrString("WS_ADDR", "localhost"), "websocket server address (domain or ip)")
wsPort := flag.String("ws_port", lookupEnvOrString("WS_PORT", ":8080"), "websocket server port") wsPort := flag.String("ws_port", lookupEnvOrString("WS_PORT", ":8080"), "websocket server port")
@ -70,8 +80,13 @@ func NewConfig() *Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
Ws: Ws{ Ws: Ws{
AuthEnable: *wsAuthEnable, AuthEnable: *wsAuthEnable,

View File

@ -91,8 +91,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -26,10 +26,17 @@ type Config struct {
type Nats struct { type Nats struct {
Url string Url string
Name string Name string
VerifyCertificates bool EnableTls bool
Cert Tls
Ctx context.Context Ctx context.Context
} }
type Tls struct {
CertFile string
KeyFile string
CaFile string
}
func NewConfig() Config { func NewConfig() Config {
//Defines log format //Defines log format
@ -47,7 +54,10 @@ func NewConfig() Config {
/* ------------------------------ define flags ------------------------------ */ /* ------------------------------ define flags ------------------------------ */
natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server") natsUrl := flag.String("nats_url", lookupEnvOrString("NATS_URL", "nats://localhost:4222"), "url for nats server")
natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "ws-adapter"), "name for nats client") natsName := flag.String("nats_name", lookupEnvOrString("NATS_NAME", "ws-adapter"), "name for nats client")
natsVerifyCertificates := flag.Bool("nats_verify_certificates", lookupEnvOrBool("NATS_VERIFY_CERTIFICATES", false), "verify validity of certificates from nats server") natsEnableTls := flag.Bool("nats_enable_tls", lookupEnvOrBool("NATS_ENABLE_TLS", false), "enbale TLS to nats server")
clientCrt := flag.String("client_crt", lookupEnvOrString("CLIENT_CRT", "cert.pem"), "client certificate file to TLS connection")
clientKey := flag.String("client_key", lookupEnvOrString("CLIENT_KEY", "key.pem"), "client key file to TLS connection")
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
flPort := flag.String("port", lookupEnvOrString("SERVER_PORT", ":8080"), "Server port") flPort := flag.String("port", lookupEnvOrString("SERVER_PORT", ":8080"), "Server port")
flAuth := flag.Bool("auth", lookupEnvOrBool("SERVER_AUTH_ENABLE", false), "Server auth enable/disable") flAuth := flag.Bool("auth", lookupEnvOrBool("SERVER_AUTH_ENABLE", false), "Server auth enable/disable")
flControllerEid := flag.String("controller-eid", lookupEnvOrString("CONTROLLER_EID", "oktopusController"), "Controller eid") flControllerEid := flag.String("controller-eid", lookupEnvOrString("CONTROLLER_EID", "oktopusController"), "Controller eid")
@ -83,8 +93,13 @@ func NewConfig() Config {
Nats: Nats{ Nats: Nats{
Url: *natsUrl, Url: *natsUrl,
Name: *natsName, Name: *natsName,
VerifyCertificates: *natsVerifyCertificates, EnableTls: *natsEnableTls,
Ctx: ctx, Ctx: ctx,
Cert: Tls{
CertFile: *clientCrt,
KeyFile: *clientKey,
CaFile: *serverCA,
},
}, },
} }
} }

View File

@ -66,8 +66,10 @@ func defineOptions(c config.Nats) []nats.Option {
opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) { opts = append(opts, nats.ClosedHandler(func(nc *nats.Conn) {
log.Printf("Connection closed. Reason: %q\n", nc.LastError()) log.Printf("Connection closed. Reason: %q\n", nc.LastError())
})) }))
if c.VerifyCertificates { if c.EnableTls {
opts = append(opts, nats.RootCAs()) log.Printf("Load certificates: %s and %s\n", c.Cert.CertFile, c.Cert.KeyFile)
opts = append(opts, nats.RootCAs(c.Cert.CaFile))
opts = append(opts, nats.ClientCert(c.Cert.CertFile, c.Cert.KeyFile))
} }
return opts return opts

View File

@ -1,2 +1,2 @@
DIRECTORY_PATH="./firmwares" DIRECTORY_PATH="."
SERVER_PORT=":8004" SERVER_PORT=":8004"

View File

@ -1,2 +1,3 @@
firmwares/ firmwares/
.env.local .env.local
images/

View File

@ -0,0 +1,8 @@
FROM golang:1.22.2@sha256:450e3822c7a135e1463cd83e51c8e2eb03b86a02113c89424e6f0f8344bb4168 as builder
WORKDIR /app
COPY ../ .
RUN CGO_ENABLED=0 GOOS=linux go build -o file-server main.go
FROM alpine:3.14@sha256:0f2d5c38dd7a4f4f733e688e3a6733cb5ab1ac6e3cb4603a5dd564e5bfb80eed
COPY --from=builder /app/file-server /
ENTRYPOINT ["/file-server"]

View File

@ -0,0 +1,61 @@
.PHONY: help build push start stop release remove delete run logs bash
DOCKER_USER ?= oktopusp
DOCKER_APP ?= file-server
DOCKER_TAG ?= $(shell git log --format="%h" -n 1)
CONTAINER_SHELL ?= /bin/sh
.DEFAULT_GOAL := help
help:
@echo "Makefile arguments:"
@echo ""
@echo "DOCKER_USER - docker user to build image"
@echo "DOCKER_APP - docker image name"
@echo "DOCKER_TAG - docker image tag"
@echo "CONTAINER_SHELL - container shell e.g:'/bin/bash'"
@echo ""
@echo "Makefile commands:"
@echo ""
@echo "build - docker image build"
@echo "push - push docker iamge to registry"
@echo "run - create and start docker container with the image"
@echo "start - start existent docker container with the image"
@echo "stop - stop docker container running the image"
@echo "remove - remove docker container running the image"
@echo "delete - delete docker image"
@echo "logs - show logs of docker container"
@echo "bash - access container shell"
@echo "release - tag image as latest and push to registry"
build:
@docker build -t ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} -f Dockerfile ../
run:
@docker run -d --name ${DOCKER_USER}-${DOCKER_APP} ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG}
stop:
@docker stop ${DOCKER_USER}-${DOCKER_APP}
remove: stop
@docker rm ${DOCKER_USER}-${DOCKER_APP}
delete:
@docker rmi ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG}
start:
@docker start ${DOCKER_USER}-${DOCKER_APP}
push:
@docker push ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG}
logs:
@docker logs -f ${DOCKER_USER}-${DOCKER_APP}
bash:
@docker exec -it ${DOCKER_USER}-${DOCKER_APP} ${CONTAINER_SHELL}
release: build
@docker push ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG}
@docker tag ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} ${DOCKER_USER}/${DOCKER_APP}:latest
@docker push ${DOCKER_USER}/${DOCKER_APP}:latest

View File

@ -42,7 +42,7 @@ func main() {
http.Handle("/", fileServer) http.Handle("/", fileServer)
port := os.Getenv("SERVER_PORT") port := os.Getenv("SERVER_PORT")
fmt.Printf("Server started at http://localhost:%s\n", port) fmt.Printf("Server started at http://localhost%s\n", port)
err = http.ListenAndServe(port, nil) err = http.ListenAndServe(port, nil)
if err != nil { if err != nil {
fmt.Printf("Error starting server: %s\n", err) fmt.Printf("Error starting server: %s\n", err)

View File

@ -26,6 +26,7 @@ build-backend:
@make build -C ../backend/services/controller/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/controller/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/acs/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/acs/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/utils/socketio/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/utils/socketio/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/utils/file-server/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/mtp/adapter/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/mtp/adapter/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/mtp/ws-adapter/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/mtp/ws-adapter/build/ DOCKER_USER=${DOCKER_USER}
@make build -C ../backend/services/mtp/ws/build/ DOCKER_USER=${DOCKER_USER} @make build -C ../backend/services/mtp/ws/build/ DOCKER_USER=${DOCKER_USER}
@ -43,6 +44,7 @@ release-backend:
@make release -C ../backend/services/controller/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/controller/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/acs/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/acs/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/utils/socketio/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/utils/socketio/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/utils/file-server/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/mtp/adapter/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/mtp/adapter/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/mtp/ws-adapter/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/mtp/ws-adapter/build/ DOCKER_USER=${DOCKER_USER}
@make release -C ../backend/services/mtp/ws/build/ DOCKER_USER=${DOCKER_USER} @make release -C ../backend/services/mtp/ws/build/ DOCKER_USER=${DOCKER_USER}

View File

@ -1 +1,5 @@
NATS_URL=nats://msg_broker:4222 NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1,2 +1,6 @@
NATS_URL=nats://msg_broker:4222
MONGO_URI=mongodb://mongo_usp:27017 MONGO_URI=mongodb://mongo_usp:27017
NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1,2 +1,6 @@
NATS_URL=nats://msg_broker:4222
MONGO_URI=mongodb://mongo_usp:27017 MONGO_URI=mongodb://mongo_usp:27017
NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -0,0 +1,2 @@
DIRECTORY_PATH="."
SERVER_PORT=":8004"

View File

@ -1,3 +1,7 @@
REDIS_ENABLE=false REDIS_ENABLE=false
REDIS_ADDR=redis_usp:6379 REDIS_ADDR=redis_usp:6379
NATS_URL=nats://msg_broker:4222 NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1,2 +1,6 @@
NATS_URL=nats://msg_broker:4222
MQTT_URL=tcp://mqtt:1883 MQTT_URL=tcp://mqtt:1883
NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

3
deploy/compose/.env.nats Normal file
View File

@ -0,0 +1,3 @@
NATS_NAME=oktopus
NATS_USER=oktopususer
NATS_PW=oktopuspw

View File

@ -1 +1,5 @@
NATS_URL=nats://msg_broker:4222 NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1,2 +1,6 @@
NATS_URL=nats://msg_broker:4222
STOMP_SERVER=stomp:61613 STOMP_SERVER=stomp:61613
NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1 +1,5 @@
NATS_URL=nats://msg_broker:4222 NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -1,2 +1,6 @@
NATS_URL=nats://msg_broker:4222
WS_ADDR=ws WS_ADDR=ws
NATS_URL=nats://oktopususer:oktopuspw@msg_broker:4222
NATS_ENABLE_TLS="true"
CLIENT_CRT=/tmp/nats/config/cert.pem
CLIENT_KEY=/tmp/nats/config/key.pem
SERVER_CA=/tmp/nats/config/rootCA.pem

View File

@ -4,3 +4,7 @@ mongo_data/*
!mongo_data/.gitkeep !mongo_data/.gitkeep
nats_data/* nats_data/*
!nats_data/.gitkeep !nats_data/.gitkeep
firmwares/*
!firmwares/.gitkeep
images/*
!images/logo.png

View File

@ -1,24 +1,26 @@
services: services:
#/* ----------------------------- Message Broker ----------------------------- */
#/* ----------------------------- Message Broker ----------------------------- */
msg_broker: msg_broker:
image: 'nats:latest' image: "nats:latest"
container_name: nats container_name: nats
ports: ports:
- 4222:4222 - 4222:4222
- 8222:8222 - 8222:8222
command: -n oktopus -m 8222 -js command: -c /tmp/nats/config/nats.cfg
env_file:
- .env.nats
volumes: volumes:
- ./nats_data:/tmp/nats/jetstream - ./nats_data:/tmp/nats/jetstream
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.2 ipv4_address: 172.16.235.2
profiles: [nats] profiles: [nats]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* ------------------------ API REST / USP Controller ----------------------- */ #/* ------------------------ API REST / USP Controller ----------------------- */
controller: controller:
image: 'oktopusp/controller' image: "oktopusp/controller"
container_name: controller container_name: controller
ports: ports:
- 8000:8000 - 8000:8000
@ -26,13 +28,15 @@ services:
- mongo_usp - mongo_usp
env_file: env_file:
- .env.controller - .env.controller
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.3 ipv4_address: 172.16.235.3
profiles: [controller] profiles: [controller]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* ---------------------------- Databases / Cache --------------------------- */ #/* ---------------------------- Databases / Cache --------------------------- */
mongo_usp: mongo_usp:
image: mongo image: mongo
container_name: mongo_usp container_name: mongo_usp
@ -43,38 +47,42 @@ services:
ipv4_address: 172.16.235.4 ipv4_address: 172.16.235.4
volumes: volumes:
- ./mongo_data:/data/db - ./mongo_data:/data/db
profiles: [controller,adapter] profiles: [controller, adapter]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* ----------------------- Message Transfer Protocols ----------------------- */ #/* ----------------------- Message Transfer Protocols ----------------------- */
mqtt: mqtt:
image: 'oktopusp/mqtt' image: "oktopusp/mqtt"
container_name: mqtt container_name: mqtt
ports: ports:
- 1883:1883 - 1883:1883
- 8883:8883 - 8883:8883
env_file: env_file:
- .env.mqtt - .env.mqtt
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.6 ipv4_address: 172.16.235.6
profiles: [mqtt] profiles: [mqtt]
ws: ws:
image: 'oktopusp/ws' image: "oktopusp/ws"
container_name: websockets container_name: websockets
ports: ports:
- 8080:8080 - 8080:8080
env_file: env_file:
- .env.ws - .env.ws
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.7 ipv4_address: 172.16.235.7
profiles: [ws] profiles: [ws]
stomp: stomp:
image: 'oktopusp/stomp' image: "oktopusp/stomp"
container_name: stomp container_name: stomp
ports: ports:
- 61613:61613 - 61613:61613
@ -82,76 +90,85 @@ services:
usp_network: usp_network:
ipv4_address: 172.16.235.8 ipv4_address: 172.16.235.8
profiles: [stomp] profiles: [stomp]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* --------------- Message transfer Protocols Adapters to NATS -------------- */ #/* --------------- Message transfer Protocols Adapters to NATS -------------- */
mqtt-adapter: mqtt-adapter:
image: 'oktopusp/mqtt-adapter' image: "oktopusp/mqtt-adapter"
container_name: mqtt-adapter container_name: mqtt-adapter
depends_on: depends_on:
- mqtt - mqtt
env_file: env_file:
- .env.mqtt-adapter - .env.mqtt-adapter
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.9 ipv4_address: 172.16.235.9
profiles: [mqtt] profiles: [mqtt]
ws-adapter: ws-adapter:
image: 'oktopusp/ws-adapter' image: "oktopusp/ws-adapter"
container_name: ws-adapter container_name: ws-adapter
depends_on: depends_on:
- ws - ws
env_file: env_file:
- .env.ws-adapter - .env.ws-adapter
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.10 ipv4_address: 172.16.235.10
profiles: [ws] profiles: [ws]
stomp-adapter: stomp-adapter:
image: 'oktopusp/stomp-adapter' image: "oktopusp/stomp-adapter"
container_name: stomp-adapter container_name: stomp-adapter
depends_on: depends_on:
- stomp - stomp
env_file: env_file:
- .env.stomp-adapter - .env.stomp-adapter
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.11 ipv4_address: 172.16.235.11
profiles: [stomp] profiles: [stomp]
adapter: adapter:
image: 'oktopusp/adapter' image: "oktopusp/adapter"
container_name: adapter container_name: adapter
depends_on: depends_on:
- mongo_usp - mongo_usp
env_file: env_file:
- .env.adapter - .env.adapter
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.12 ipv4_address: 172.16.235.12
profiles: [adapter] profiles: [adapter]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* ------------- SocketIO Real Time Communication With Frontend ------------- */ #/* ------------- SocketIO Real Time Communication With Frontend ------------- */
socketio: socketio:
image: 'oktopusp/socketio' image: "oktopusp/socketio"
container_name: socketio container_name: socketio
ports: ports:
- 5000:5000 - 5000:5000
env_file: env_file:
- .env.socketio - .env.socketio
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.13 ipv4_address: 172.16.235.13
profiles: [frontend] profiles: [frontend]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
#/* -------------------------------- Frontend -------------------------------- */ #/* -------------------------------- Frontend -------------------------------- */
frontend: frontend:
image: 'oktopusp/frontend-ce' image: "oktopusp/frontend-ce"
container_name: frontend container_name: frontend
ports: ports:
- 3000:3000 - 3000:3000
@ -159,7 +176,7 @@ services:
usp_network: usp_network:
ipv4_address: 172.16.235.14 ipv4_address: 172.16.235.14
profiles: [frontend] profiles: [frontend]
#/* -------------------------------------------------------------------------- */ #/* -------------------------------------------------------------------------- */
portainer: portainer:
image: portainer/portainer-ce:latest image: portainer/portainer-ce:latest
@ -175,12 +192,14 @@ services:
- ./portainer_data:/data - ./portainer_data:/data
acs: acs:
image: oktopusp/acs image: "oktopusp/acs"
container_name: acs container_name: acs
ports: ports:
- 9292:9292 - 9292:9292
env_file: env_file:
- .env.acs - .env.acs
volumes:
- ./nats_config:/tmp/nats/config
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.16 ipv4_address: 172.16.235.16
@ -191,16 +210,28 @@ services:
container_name: nginx container_name: nginx
ports: ports:
- 80:80 - 80:80
depends_on:
- frontend
- controller
- socketio
volumes: volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf - ./nginx.conf:/etc/nginx/conf.d/default.conf
extra_hosts:
- "host.docker.internal:host-gateway"
networks: networks:
usp_network: usp_network:
ipv4_address: 172.16.235.17 ipv4_address: 172.16.235.17
file-server:
image: oktopusp/file-server
container_name: file-server
ports:
- 8004:8004
volumes:
- ./firmwares:/app/firmwares
- ./images:/app/images
env_file:
- .env.file-server
networks:
usp_network:
ipv4_address: 172.16.235.18
networks: networks:
usp_network: usp_network:
driver: bridge driver: bridge

View File

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEeTCCAuGgAwIBAgIRAJenDys60PD3Cjh9VXeAzsowDQYJKoZIhvcNAQELBQAw
gY0xHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTExMC8GA1UECwwoY2hp
ZXNhQEFkcmlhbm9NYWMubG9jYWwgKEFkcmlhbm8gQ2hpZXNhKTE4MDYGA1UEAwwv
bWtjZXJ0IGNoaWVzYUBBZHJpYW5vTWFjLmxvY2FsIChBZHJpYW5vIENoaWVzYSkw
HhcNMjQwNzA2MTQzODQ2WhcNMjYxMDA2MTQzODQ2WjBcMScwJQYDVQQKEx5ta2Nl
cnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxMTAvBgNVBAsMKGNoaWVzYUBBZHJp
YW5vTWFjLmxvY2FsIChBZHJpYW5vIENoaWVzYSkwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCdQCgwn7M5jtkNzYv/yUelUV84ehsYjPTQspCXCjDdUltO
E6jafRM/2SopUWwzPTorIZkerIpqq/avi77e6wSdCKJZBA5DsrMSOmFjjMqG4H2b
euzr5b+ZKzKnw4nF/CuB2cmWkz/qAiluqVdRl+Gef/Ouyuer/NuhJhK6Mgy1VuAd
ynwizGsAgQ/oAGDuHWmcMhGw/2NVTnXqHei5ntr+F4r08YOgXnRsGId+16nJU5xd
Xs80sw2dFl+1zQiFJxWjVQk65CyZfLDcwC7e3PAMsT+8obzuBKCn6fW3JiIZ68tc
o8GZClHSkeS7IMp+/wtjMXf1iipE0bRWzzdl1xQnAgMBAAGjgYMwgYAwDgYDVR0P
AQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFH2KEsMw
S7/Qu1eE1DxRhZTI0Z7RMDgGA1UdEQQxMC+CCm1zZ19icm9rZXKCCWxvY2FsaG9z
dIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAYEAVr06
Kg/FaWxUbD6Q+e5OLzckeeFZOKcb/2mmEH+e99HebnCuydiiGebZVWcLsoOw+gmb
WG/4rFyp9D/ZYFiQxWNRm/nCcxiHIV+JHDxhBn3vKENxYNNbr+WTMBTqmaYqPARK
SelnX+XDRTZUnoRBo03wZFYwOYwHUFWrlMFz+o6jOo2KZa4J+pcEDbttkJEoVhiV
C8EKIxSsG9TuW4lh5UySfB62ZfQBNd8SyhD4LF5JHFbBV9ysnylg/8gVvavjHWtM
FleOk/lNi9oj2n8uQEGbBT6FpTaKKJDiF85E3J4fuv8iNiFy2nWhCpJFF9K5/hu6
s41Y2ZRb7luBoUj+CQWlTpGjCJPzzWmSkZUjf5kRP6b01bAXoLBzBBn50KWf8DWw
Rx7VaHtzbBRxfzESQxslGRgZvz2KxjY/x2jH6xdW+bzt93aHkgeGkDrjpY9q/uQF
SyEJYHIDt+FZupcc3KjvTY2p+icbckOrwQAtVWXzEjCsnDjf33+O7VGdACDm
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdQCgwn7M5jtkN
zYv/yUelUV84ehsYjPTQspCXCjDdUltOE6jafRM/2SopUWwzPTorIZkerIpqq/av
i77e6wSdCKJZBA5DsrMSOmFjjMqG4H2beuzr5b+ZKzKnw4nF/CuB2cmWkz/qAilu
qVdRl+Gef/Ouyuer/NuhJhK6Mgy1VuAdynwizGsAgQ/oAGDuHWmcMhGw/2NVTnXq
Hei5ntr+F4r08YOgXnRsGId+16nJU5xdXs80sw2dFl+1zQiFJxWjVQk65CyZfLDc
wC7e3PAMsT+8obzuBKCn6fW3JiIZ68tco8GZClHSkeS7IMp+/wtjMXf1iipE0bRW
zzdl1xQnAgMBAAECggEAMRDQuYNLJ/2DioQFV/WVDmdaf8PR6pIo3WmqJga/An/t
D2qg+DOoqvZ26leGnGJRYR3lqiWKNwibO2EuWF4anWkRRxc14DfFGj3vH2HR2832
Q2pSvLR+WSuabbBcr9MkPCsZdItTmQ+9n9Lk9QegFZW1Emgra4XFff3kQAbX4kjR
ATyEsvZsgnkK5jHi5bzVHEKY730MKyhYzmHmUgxH1ibD5x+tnFtRiBGK+qY24erW
rw+wu0YKu1ESp62orYDnaA8MH7aWlFZLniPB4liA0h0bElrgHA8Zndx+cEtXqF4m
5+igR3MjXbg2at80ah++z6EGUTtEPccRSpcA7qFqMQKBgQDFVp1msdn45Xwquw+8
CSZ45KAurvQEPNxtK/GMHtR5LjRZlKQEpNy3AVjz56azv72kqUfhNsP+ZNokMQTH
NTMvdkLzcwKe3qCnsfBRlSkRBVCwan266oCJW8SSX8pdaoME9lzc2BfMVAxJ1n+Y
289ZHXyyPYdNd+L4FxjreJDkKQKBgQDL/uD+kCSKZ/dYVZqwF06DIzYiBv1Xjne3
3H90J0h/2iU9/yX9UsCS7D5RWbVROUyMh64fpH0f2lVFT8Xo3SjBWISrMovOxEzl
C2wZwM2VQmrfhiUg9h46drJSl/JL9/V/QOnpuQe35bVWjROtFStaZagUK/3vx1hh
xCV4iVS/zwKBgQC2Ea3zvA/x9jlTa3ee84pNbBLmP4DgEA8Hos2fjCpZC+o85ElY
B4ukRVf+4TILEdM1AwJQpii6o+4oChnwegMZvTEUUH6QebMcRa4Gd2qGS7MgsYAD
XqztDoAU1NBu1ADCKVOQZse+O6WC0qazL8rk27Ha+a3GKeB9KUJSrtBv0QKBgCi5
IftPlSvYI2WL+Uxr6q19KwJR+OMwuq+Goh7y9KMpTkP5GoFesrjh1nLxAKRNVv26
3ETO1ne0Y09p5G1fMRKf9CQk/Anz4BHdXOArQB8q2iDzK5hP6arsJR8d3C3UOzsD
H28cE/FfNvsnQKVN05DBOHOGcLQcTIV/3acZa0S7AoGBAJqSujzhVkewH7wJWOOh
92F66vMnCsE4Qn10h84GQQWORgjr8z8d8UbW7VrobVfZP74IBqo3ZUBYm85+lUFu
FWHjTkXoZzwP8IvMW0gE2iC3W4QSr2Z96a6RlRJdxC70LB+Pm6FFwLTloKBGK8Bf
Kp53gUDjsvJcQGv6nOty0uHQ
-----END PRIVATE KEY-----

View File

@ -0,0 +1,18 @@
server_name: $NATS_NAME
port: 4222
http_port: 8222
authorization: {
users: [
{user: $NATS_USER, password: $NATS_PW}
]
}
tls: {
cert_file: "/tmp/nats/config/cert.pem"
key_file: "/tmp/nats/config/key.pem"
ca_file: "/tmp/nats/config/rootCA.pem"
}
// enables jetstream, an empty block will enable and use defaults
jetstream {
// jetstream data will be in /data/nats-server/jetstream
store_dir: "/tmp/nats/jetstream"
}

View File

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE6zCCA1OgAwIBAgIQcw3hWvi1nfQFSkUzrcdrhTANBgkqhkiG9w0BAQsFADCB
jTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTEwLwYDVQQLDChjaGll
c2FAQWRyaWFub01hYy5sb2NhbCAoQWRyaWFubyBDaGllc2EpMTgwNgYDVQQDDC9t
a2NlcnQgY2hpZXNhQEFkcmlhbm9NYWMubG9jYWwgKEFkcmlhbm8gQ2hpZXNhKTAe
Fw0yMjA4MTIxNTM1NDdaFw0zMjA4MTIxNTM1NDdaMIGNMR4wHAYDVQQKExVta2Nl
cnQgZGV2ZWxvcG1lbnQgQ0ExMTAvBgNVBAsMKGNoaWVzYUBBZHJpYW5vTWFjLmxv
Y2FsIChBZHJpYW5vIENoaWVzYSkxODA2BgNVBAMML21rY2VydCBjaGllc2FAQWRy
aWFub01hYy5sb2NhbCAoQWRyaWFubyBDaGllc2EpMIIBojANBgkqhkiG9w0BAQEF
AAOCAY8AMIIBigKCAYEA4HBEZqDbKPB0StZX/ILPU1q2Tm/U4j32/HvaWOGt528q
15y5eqa4OqpYQ7waVhkSR+M6258yAk9BCCOGrI+oXcllO7LKv4bg/y+HVhfEg4E0
fnZS583+VWrIcIKOENQQX1cbFnIqLldBL/ph6YNMDT8wOoLqtQ2vp1EiXFA3ghQs
fK3iqDL31SQ7cZhdw7hnNACgvIM6MipwFLYbMsm27eMa9fCL4ZB3xokhbYVBmEcT
RTdhGvcRBs+QF8fcP/Y6uC9y7q2ddeIYEAf5xCVc15QepPqVskuAM3rktzVpBKEl
lzJGtW3EWu3kojrrW8dYZkZFJkHy9ymZVNUPjpAGiIIylp1Rik/o9VttXi+BQmrV
l1tpkrU1JfhLcktjBtRxtvRJTARpSkMM8gVc1rA2KgNsULzF4Zaas12wUh7r/VzW
4lwKiV3vgAM0wE5Fo4NLmv53/j3w7yX9GtSq0Ck/cKu2k0cOe+PTlG9aQ5MdhLCx
+BwMij/ohBfh0qtgPVPdAgMBAAGjRTBDMA4GA1UdDwEB/wQEAwICBDASBgNVHRMB
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBR9ihLDMEu/0LtXhNQ8UYWUyNGe0TANBgkq
hkiG9w0BAQsFAAOCAYEAyGNw197jniIGfCpcArC2lHbzNIQCq97BXsOj4h+CaUB+
ZfTpTOdtS5DK2fSQ4jwH6nzm7VQvrnHcbP2pCgVDWW9da+Acnh1U6dYXI1VPDDVA
KZGDiK63M6PneX3IDl2N2fubRDP1ALkZQ6zwjtJLC2nT6IVjAJdRNt8egbCUAyMb
nOb4F+Zrr0L2SILM0jHq9diJVpX4Lxqggldmd+5HdVGHoR8BGzw4MReuoRWOZtf/
H+opFtJ2f8GNTWsWtmN7FsjrGOOBgREB/Tz7WCWgGEeXQveJEfkOIddVVgb/n9Ly
mEOTbtJj36o4JJzv0v42SdT1WUkdvc6AmLVmYFn0uaLohNLVelJmU+aGavuVFpFb
08uVsSl8JMBWwVO23CpuvZFbI/1BFVix85UZgDj8BnpAWlsJxPYV1HqxS2oJJJbn
zRf8/0xzFPrLirXzebIr4jiCRVBRamacQTxlvPUz6c6FLTQLaqQdUV/IZaXsXX38
byH1ABmJPGjXLm1r2RWD
-----END CERTIFICATE-----

View File

@ -11,19 +11,7 @@ server {
} }
location / { location / {
proxy_pass http://frontend:3000; proxy_pass http://host.docker.internal:3000;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
location /api {
proxy_pass http://controller:8000;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
location /socket.io {
proxy_pass http://socketio:5000;
proxy_read_timeout 60; proxy_read_timeout 60;
proxy_connect_timeout 60; proxy_connect_timeout 60;
proxy_redirect off; proxy_redirect off;
@ -34,6 +22,33 @@ server {
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade; proxy_cache_bypass $http_upgrade;
} }
location /api {
proxy_pass http://host.docker.internal:8000;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
location /custom-frontend {
proxy_pass http://host.docker.internal:8005;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
location /socket.io {
proxy_pass http://host.docker.internal:5000;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /companylink {
return 301 https://oktopus.app.br/controller;
}
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;
location = /50x.html { location = /50x.html {

View File

@ -1,6 +1,5 @@
# ----------------------------- Local Environment ---------------------------- # # ----------------------------- Local Environment ---------------------------- #
NEXT_PUBLIC_REST_ENDPOINT="http://localhost:8000"
NEXT_PUBLIC_WS_ENDPOINT="http://localhost:5000/" NEXT_PUBLIC_WS_ENDPOINT="http://localhost:5000/"
NEXT_PUBLIC_ENTERPRISE_VERSION="false" NEXT_PUBLIC_ENTERPRISE_VERSION="false"
NEXT_PUBLIC_GOOGLE_MAPS_KEY="" NEXT_PUBLIC_GOOGLE_MAPS_KEY=""

View File

@ -18,14 +18,14 @@
"@mui/system": "5.11.9", "@mui/system": "5.11.9",
"@mui/x-date-pickers": "5.0.19", "@mui/x-date-pickers": "5.0.19",
"@react-google-maps/api": "^2.19.3", "@react-google-maps/api": "^2.19.3",
"apexcharts": "3.37.0", "apexcharts": "^3.37.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"formik": "2.2.9", "formik": "2.2.9",
"next": "^14.2.4", "next": "^14.2.4",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-apexcharts": "1.4.0", "react-apexcharts": "^1.4.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"simple-peer": "^9.11.1", "simple-peer": "^9.11.1",
"simplebar-react": "^3.2.1", "simplebar-react": "^3.2.1",
@ -1480,6 +1480,11 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
} }
}, },
"node_modules/@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@ -1538,10 +1543,11 @@
} }
}, },
"node_modules/apexcharts": { "node_modules/apexcharts": {
"version": "3.37.0", "version": "3.50.0",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.37.0.tgz", "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.50.0.tgz",
"integrity": "sha512-0mg1gDKUo3JG00Q//LK0jEXBS6OLjpuglqZ8ec9cqfA5oP8owopD9n5EhfARbWROb5o8GSPzFuohTJiCm2ecWw==", "integrity": "sha512-LJT1PNAm+NoIU3aogL2P+ViC0y/Cjik54FdzzGV54UNnGQLBoLe5ok3fxsJDTgyez45BGYT8gqNpYKqhdfy5sg==",
"dependencies": { "dependencies": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2", "svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0", "svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2", "svg.filter.js": "^2.0.2",
@ -4722,14 +4728,14 @@
} }
}, },
"node_modules/react-apexcharts": { "node_modules/react-apexcharts": {
"version": "1.4.0", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz",
"integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==",
"dependencies": { "dependencies": {
"prop-types": "^15.5.7" "prop-types": "^15.8.1"
}, },
"peerDependencies": { "peerDependencies": {
"apexcharts": "^3.18.0", "apexcharts": "^3.41.0",
"react": ">=0.13" "react": ">=0.13"
} }
}, },
@ -7102,6 +7108,11 @@
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
}, },
"@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"acorn": { "acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@ -7142,10 +7153,11 @@
} }
}, },
"apexcharts": { "apexcharts": {
"version": "3.37.0", "version": "3.50.0",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.37.0.tgz", "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.50.0.tgz",
"integrity": "sha512-0mg1gDKUo3JG00Q//LK0jEXBS6OLjpuglqZ8ec9cqfA5oP8owopD9n5EhfARbWROb5o8GSPzFuohTJiCm2ecWw==", "integrity": "sha512-LJT1PNAm+NoIU3aogL2P+ViC0y/Cjik54FdzzGV54UNnGQLBoLe5ok3fxsJDTgyez45BGYT8gqNpYKqhdfy5sg==",
"requires": { "requires": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2", "svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0", "svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2", "svg.filter.js": "^2.0.2",
@ -9444,11 +9456,11 @@
} }
}, },
"react-apexcharts": { "react-apexcharts": {
"version": "1.4.0", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz",
"integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==",
"requires": { "requires": {
"prop-types": "^15.5.7" "prop-types": "^15.8.1"
} }
}, },
"react-dom": { "react-dom": {

View File

@ -24,14 +24,14 @@
"@mui/system": "5.11.9", "@mui/system": "5.11.9",
"@mui/x-date-pickers": "5.0.19", "@mui/x-date-pickers": "5.0.19",
"@react-google-maps/api": "^2.19.3", "@react-google-maps/api": "^2.19.3",
"apexcharts": "3.37.0", "apexcharts": "^3.37.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"formik": "2.2.9", "formik": "2.2.9",
"next": "^14.2.4", "next": "^14.2.4",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-apexcharts": "1.4.0", "react-apexcharts": "^1.4.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"simple-peer": "^9.11.1", "simple-peer": "^9.11.1",
"simplebar-react": "^3.2.1", "simplebar-react": "^3.2.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,13 +1,16 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import NextLink from 'next/link'; import NextLink from 'next/link';
import Link from 'next/link' import Link from 'next/link'
import { Box, Typography, Unstable_Grid2 as Grid } from '@mui/material'; import { Box, Typography, Unstable_Grid2 as Grid, Stack } from '@mui/material';
import { Logo } from 'src/components/logo'; import { Logo } from 'src/components/logo';
import { useTheme, useMediaQuery } from '@mui/material'
// TODO: Change subtitle text
export const Layout = (props) => { export const Layout = (props) => {
const { children } = props; const { children } = props;
const lgUp = useMediaQuery((theme) => theme.breakpoints.up('lg'));
const theme = useTheme();
console.log("logUp", lgUp)
return ( return (
<Box <Box
@ -60,7 +63,7 @@ export const Layout = (props) => {
lg={6} lg={6}
sx={{ sx={{
alignItems: 'center', alignItems: 'center',
background: 'radial-gradient(50% 50% at 50% 50%, #306D6F 0%, #255355 100%)', background: `radial-gradient(50% 50% at 50% 50%, ${theme.palette.primary.main} 0%, ${theme.palette.primary.dark } 100%)`,
color: 'white', color: 'white',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
@ -70,20 +73,32 @@ export const Layout = (props) => {
}} }}
> >
<Box sx={{ p: 3 }}> <Box sx={{ p: 3 }}>
<Link href="https://oktopus.app.br" target="_blank"> <Link href="http://localhost/companylink" target="_blank">
<img <img
alt="" alt=""
src="/assets/oktopus.png" src="http://localhost:8004/images/logo.png"
/> />
</Link> </Link>
<Typography
align="center"
sx={{ mb: 3 }}
>
</Typography>
</Box> </Box>
</Grid> </Grid>
</Grid> </Grid>
<Stack style={{position:"absolute", bottom:"2px", left:"2px"}} direction={"row"} spacing={"1"}>
<Typography
align="center"
color={lgUp ? 'neutral[900]' : 'primary.contrastText'}
component="footer"
variant="body2"
sx={{ p: 2 }}
>
Powered by
</Typography>
</Stack>
<a href='https://oktopus.app.br' style={{position:"absolute", bottom:"10px", left:"100px"}} target='_blank'>
<img
src="/assets/logo.png"
alt="Oktopus logo image"
width={80}/>
</a>
</Box> </Box>
); );
}; };

View File

@ -35,15 +35,15 @@ export const items = [
// </SvgIcon> // </SvgIcon>
// ) // )
// }, // },
// { {
// title: 'Map', title: 'Map',
// path: '/map', path: '/map',
// icon: ( icon: (
// <SvgIcon fontSize="small"> <SvgIcon fontSize="small">
// <MapIcon/> <MapIcon/>
// </SvgIcon> </SvgIcon>
// ), ),
// }, },
{ {
title: 'Credentials', title: 'Credentials',
path: '/credentials', path: '/credentials',

View File

@ -4,8 +4,6 @@ import { styled } from '@mui/material/styles';
import { withAuthGuard } from 'src/hocs/with-auth-guard'; import { withAuthGuard } from 'src/hocs/with-auth-guard';
import { SideNav } from './side-nav'; import { SideNav } from './side-nav';
import { TopNav } from './top-nav'; import { TopNav } from './top-nav';
import Image from 'next/image'
import { Link } from '@mui/material';
const SIDE_NAV_WIDTH = 280; const SIDE_NAV_WIDTH = 280;

View File

@ -2,8 +2,6 @@ import NextLink from 'next/link';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Link from 'next/link' import Link from 'next/link'
import ArrowTopRightOnSquareIcon from '@heroicons/react/24/solid/ArrowTopRightOnSquareIcon';
import ChevronUpDownIcon from '@heroicons/react/24/solid/ChevronUpDownIcon';
import { import {
Box, Box,
Button, Button,
@ -18,12 +16,15 @@ import { Logo } from 'src/components/logo';
import { Scrollbar } from 'src/components/scrollbar'; import { Scrollbar } from 'src/components/scrollbar';
import { items } from './config'; import { items } from './config';
import { SideNavItem } from './side-nav-item'; import { SideNavItem } from './side-nav-item';
import { useTheme } from '@mui/material';
export const SideNav = (props) => { export const SideNav = (props) => {
const { open, onClose } = props; const { open, onClose } = props;
const pathname = usePathname(); const pathname = usePathname();
const lgUp = useMediaQuery((theme) => theme.breakpoints.up('lg')); const lgUp = useMediaQuery((theme) => theme.breakpoints.up('lg'));
const theme = useTheme();
const isItemActive = (currentPath, itemPath) => { const isItemActive = (currentPath, itemPath) => {
if (currentPath === itemPath) { if (currentPath === itemPath) {
return true; return true;
@ -34,7 +35,6 @@ export const SideNav = (props) => {
} }
return false; return false;
//TODO: test frontend with color of the landing page
} }
const content = ( const content = (
@ -80,9 +80,9 @@ export const SideNav = (props) => {
p: '12px' p: '12px'
}} }}
> >
<Link href="https://oktopus.app.br" target="_blank"> <Link href="http://localhost/companylink" target="_blank">
<div style={{display:'flex',justifyContent:'center'}}> <div style={{display:'flex',justifyContent:'center'}}>
<img src="/assets/oktopus.png" <img src="http://localhost:8004/images/logo.png"
width={'60%'} width={'60%'}
/> />
</div> </div>
@ -113,6 +113,9 @@ export const SideNav = (props) => {
}} }}
> >
{items.map((item) => { {items.map((item) => {
if (item.title == "Map" && process.env.NEXT_PUBLIC_ENTERPRISE_VERSION != "true"){
return
}
const active = isItemActive(pathname, item.path); const active = isItemActive(pathname, item.path);
return ( return (
@ -129,7 +132,24 @@ export const SideNav = (props) => {
})} })}
</Stack> </Stack>
</Box> </Box>
<Divider sx={{ borderColor: 'neutral.700' }} /> <Stack style={{position:"absolute", bottom:"2px", left:"2px"}} direction={"row"} spacing={"1"} zIndex={9999}>
<Typography
align="center"
color="primary.contrastText"
component="footer"
variant="body2"
sx={{ p: 2 }}
>
Powered by
</Typography>
</Stack>
<a href='https://oktopus.app.br' style={{position:"absolute", bottom:"10px", left:"100px"}} target='_blank'>
<img
src="/assets/logo.png"
alt="Oktopus logo image"
width={80}
/>
</a>
</Box> </Box>
</Scrollbar> </Scrollbar>
); );
@ -141,7 +161,7 @@ export const SideNav = (props) => {
open open
PaperProps={{ PaperProps={{
sx: { sx: {
backgroundColor: 'neutral.800', background: `linear-gradient(0deg, ${theme.palette.neutral["800"]} 0%, ${theme.palette.primary.dark} 90%);`,
color: 'common.white', color: 'common.white',
width: 280 width: 280
} }
@ -160,7 +180,7 @@ export const SideNav = (props) => {
open={open} open={open}
PaperProps={{ PaperProps={{
sx: { sx: {
backgroundColor: 'neutral.800', background: `linear-gradient(0deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.dark} 90%);`,
color: 'common.white', color: 'common.white',
width: 280 width: 280
} }

View File

@ -10,21 +10,26 @@ import { createTheme } from 'src/theme';
import { createEmotionCache } from 'src/utils/create-emotion-cache'; import { createEmotionCache } from 'src/utils/create-emotion-cache';
import 'simplebar-react/dist/simplebar.min.css'; import 'simplebar-react/dist/simplebar.min.css';
import { WsProvider } from 'src/contexts/socketio-context'; import { WsProvider } from 'src/contexts/socketio-context';
import '../utils/map.css';
import { useEffect, useState } from 'react';
const clientSideEmotionCache = createEmotionCache(); const clientSideEmotionCache = createEmotionCache();
const SplashScreen = () => null; const SplashScreen = () => null;
const App = (props) => { const App = (props) => {
const [theme, setTheme] = useState(null);
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props; const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
useNProgress(); useNProgress();
const getLayout = Component.getLayout ?? ((page) => page); const getLayout = Component.getLayout ?? ((page) => page);
const theme = createTheme(); useEffect(() => {
setTheme(createTheme());
}, []);
return ( return theme && (
<CacheProvider value={emotionCache}> <CacheProvider value={emotionCache}>
<Head> <Head>
<title> <title>

View File

@ -1,16 +1,140 @@
import Head from 'next/head'; import Head from 'next/head';
import { GoogleMap, useLoadScript } from "@react-google-maps/api" import { GoogleMap, useLoadScript, Marker, OverlayView } from "@react-google-maps/api"
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout'; import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import mapStyles from '../utils/mapStyles.json'; import mapStyles from '../utils/mapStyles.json';
import { useRouter } from 'next/router';
const getPixelPositionOffset = pixelOffset => (width, height) => ({
x: -(width / 2) + pixelOffset.x,
y: -(height / 2) + pixelOffset.y
});
const Popup = props => {
return (
<OverlayView
position={props.anchorPosition}
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
getPixelPositionOffset={getPixelPositionOffset(props.markerPixelOffset)}
>
<div className="popup-tip-anchor">
<div className="popup-bubble-anchor">
<div className="popup-bubble-content">{props.content}</div>
</div>
</div>
</OverlayView>
);
};
const Page = () => { const Page = () => {
const libraries = useMemo(() => ['places'], []); const libraries = useMemo(() => ['places'], []);
const router = useRouter();
const [mapRef, setMapRef] = useState(null);
const [mapCenter, setMapCenter] = useState(null); const [mapCenter, setMapCenter] = useState(null);
const [markers, setMarkers] = useState([]);
const [activeMarker, setActiveMarker] = useState(null);
const [activeMarkerdata, setActiveMarkerdata] = useState(null);
const [zoom, setZoom] = useState(null)
const handleDragEnd = () => {
if (mapRef) {
const newCenter = mapRef.getCenter();
console.log("newCenter:",newCenter.lat(), newCenter.lng());
localStorage.setItem("mapCenter", JSON.stringify({"lat":newCenter.lat(),"lng":newCenter.lng()}))
}
}
const handleZoomChange = () => {
if (mapRef) {
const newZoom = mapRef.getZoom();
console.log("new zoom", newZoom)
localStorage.setItem("zoom", newZoom)
}
}
const handleOnLoad = map => {
setMapRef(map);
};
const fetchMarkers = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/map`, requestOptions)
if (result.status == 200) {
const content = await result.json()
setMarkers(content)
}else if (result.status == 403) {
console.log("num tenx permissão, seu boca de sandália")
return router.push("/403")
}else if (result.status == 401){
console.log("taix nem autenticado, sai fora oh")
return router.push("/auth/login")
} else {
setMarkers([])
console.log("error to get map markers")
}
}
const fetchActiveMarkerData = async (id) => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device?id=`+id, requestOptions)
if (result.status == 200) {
const content = await result.json()
setActiveMarkerdata(content)
}else if (result.status == 403) {
return router.push("/403")
}else if (result.status == 401){
return router.push("/auth/login")
} else {
console.log("no device info found")
const content = await result.json()
}
}
useEffect(()=> { useEffect(()=> {
fetchMarkers();
let zoomFromLocalStorage = localStorage.getItem("zoom")
if (zoomFromLocalStorage) {
setZoom(Number(zoomFromLocalStorage))
}else{
setZoom(25)
}
let mapCenterFromLocalStorage = localStorage.getItem("mapCenter")
if (mapCenterFromLocalStorage){
let fmtMapCenter = JSON.parse(localStorage.getItem("mapCenter"))
console.log("mapCenterFromLocalStorage:", fmtMapCenter)
setMapCenter({
lat: Number(fmtMapCenter.lat),
lng: Number(fmtMapCenter.lng),
})
return
}
// Check if geolocation is supported by the browser // Check if geolocation is supported by the browser
if ("geolocation" in navigator) { if ("geolocation" in navigator) {
// Prompt user for permission to access their location // Prompt user for permission to access their location
@ -27,12 +151,12 @@ const Page = () => {
// Error callback function // Error callback function
function(error) { function(error) {
// Handle errors, e.g. user denied location sharing permissions // Handle errors, e.g. user denied location sharing permissions
console.error("Error getting user location:", error); console.log("Error getting user location:", error);
} }
); );
} else { } else {
// Geolocation is not supported by the browser // Geolocation is not supported by the browser
console.error("Geolocation is not supported by this browser."); console.log("Geolocation is not supported by this browser, or the user denied access");
} }
},[]) },[])
@ -59,7 +183,7 @@ const Page = () => {
return <p>Loading...</p>; return <p>Loading...</p>;
} }
return ( mapCenter && return ( markers && zoom &&
<> <>
<Head> <Head>
<title> <title>
@ -68,12 +192,61 @@ const Page = () => {
</Head> </Head>
<GoogleMap <GoogleMap
options={mapOptions} options={mapOptions}
zoom={14} zoom={zoom}
center={mapCenter} center={mapCenter ? mapCenter : {
lat: 0.0,
lng: 0.0,
}}
mapContainerStyle={{ width: '100%', height: '100%' }} mapContainerStyle={{ width: '100%', height: '100%' }}
onLoad={() => console.log('Map Component Loaded...')} onLoad={handleOnLoad}
clickableIcons={false} clickableIcons={false}
/> onDragEnd={handleDragEnd}
onZoomChanged={handleZoomChange}
>
{
markers.map((marker, index) => (
<Marker
key={index}
position={{ lat: marker.coordinates.lat, lng: marker.coordinates.lng }}
icon={{
url: marker.img,
scaledSize: new window.google.maps.Size(50, 50),
anchor: new window.google.maps.Point(25, 25),
}}
draggable={false}
clickable={true}
onClick={() => {
setActiveMarkerdata(null);
if (activeMarker?.sn === marker.sn) {
setActiveMarker(null);
return;
}
fetchActiveMarkerData(marker.sn);
setActiveMarker({
sn: marker.sn,
position: { lat: marker.coordinates.lat, lng: marker.coordinates.lng }
});
}}
>
</Marker>
))
}
{activeMarker &&
<Popup
anchorPosition={activeMarker.position}
markerPixelOffset={{ x: 0, y: -32 }}
content={activeMarkerdata ?
<div>
<div>SN: {activeMarker.sn}</div>
<div>
<div>Model: {activeMarkerdata.Model?activeMarkerdata.Model:activeMarkerdata.ProductClass}</div>
<div>Alias: {activeMarkerdata.Alias}</div>
<div>Status: {activeMarkerdata.Status == 2 ? <span style={{color:"green"}}>online</span> : <span style={{color:"red"}}>offline</span>}</div>
</div>
</div>
: <p>no device info found</p>}
/>}
</GoogleMap>
</> </>
)}; )};

View File

@ -16,6 +16,19 @@ export const ConnectedDevices = () => {
const [interfaces, setInterfaces] = useState([]); const [interfaces, setInterfaces] = useState([]);
const [interfaceValue, setInterfaceValue] = useState(null); const [interfaceValue, setInterfaceValue] = useState(null);
const getConnectionState = (rssi) => {
let connectionStatus = "Signal "
if (rssi > -30) {
return connectionStatus + "Excellent"
} else if (rssi > -60) {
return connectionStatus + "Good"
} else if (rssi > -70) {
return connectionStatus + "Bad"
} else {
return connectionStatus + "Awful"
}
}
const fetchConnectedDevicesData = async () => { const fetchConnectedDevicesData = async () => {
var myHeaders = new Headers(); var myHeaders = new Headers();
@ -47,19 +60,19 @@ export const ConnectedDevices = () => {
useEffect(() => { useEffect(() => {
fetchConnectedDevicesData(); fetchConnectedDevicesData();
},[]) }, [])
return ( return (
<Stack <Stack
justifyContent="center" justifyContent="center"
alignItems={(!content || interfaces.length == 0) &&"center"} alignItems={(!content || interfaces.length == 0) && "center"}
> >
{content && interfaces.length > 0 ? {content && interfaces.length > 0 ?
<Card> <Card>
<CardContent> <CardContent>
<Grid mb={3}> <Grid mb={3}>
<InputLabel> Interface </InputLabel> <InputLabel> Interface </InputLabel>
<Select label="interface" variant="standard" value={interfaceValue} onChange={(e)=> setInterfaceValue(e.target.value)}> <Select label="interface" variant="standard" value={interfaceValue} onChange={(e) => setInterfaceValue(e.target.value)}>
{( {(
interfaces.map((item, index) => ( interfaces.map((item, index) => (
<MenuItem key={index} value={item}> <MenuItem key={index} value={item}>
@ -70,13 +83,13 @@ export const ConnectedDevices = () => {
</Select> </Select>
</Grid> </Grid>
{ {
content[interfaceValue].map((property,index) => ( content[interfaceValue].map((property, index) => (
<Card key={index}> <Card key={index}>
<CardContent> <CardContent>
<Grid container justifyContent={"center"}> <Grid container justifyContent={"center"}>
<Stack direction="row" spacing={5}> <Stack direction="row" spacing={5}>
<Stack justifyItems={"center"} direction={"row"} mt={2}> <Stack justifyItems={"center"} direction={"row"} mt={2}>
<Tooltip title={property.active ? "Online": "Offline"}> <Tooltip title={property.active ? "Online" : "Offline"}>
<SvgIcon> <SvgIcon>
<CpuChipIcon color={property.active ? theme.palette.success.main : theme.palette.error.main}></CpuChipIcon> <CpuChipIcon color={property.active ? theme.palette.success.main : theme.palette.error.main}></CpuChipIcon>
</SvgIcon> </SvgIcon>
@ -85,7 +98,7 @@ export const ConnectedDevices = () => {
{property.hostname} {property.hostname}
</Typography> </Typography>
</Stack> </Stack>
<Divider orientation="vertical"/> <Divider orientation="vertical" />
<Stack spacing={2}> <Stack spacing={2}>
<Typography> <Typography>
IP address: {property.ip_adress} IP address: {property.ip_adress}
@ -95,12 +108,30 @@ export const ConnectedDevices = () => {
</Typography> </Typography>
</Stack> </Stack>
<Stack spacing={2}> <Stack spacing={2}>
<Typography>
RSSI: {property.rssi} dbm
</Typography>
<Typography> <Typography>
Source: {property.adress_source} Source: {property.adress_source}
</Typography> </Typography>
<Tooltip title={getConnectionState(property.rssi)}>
<Typography display={"flex"} color={() => {
let rssi = property.rssi
if(rssi == 0){
return theme.palette.neutral[900]
} else if (rssi > -30) {
return theme.palette.success.main
} else if (rssi > -60) {
return theme.palette.success.main
} else if (rssi > -70) {
return theme.palette.warning.main
} else {
return theme.palette.error.main
}
}}>
<Typography color={theme.palette.neutral[900]} sx={{pr:"5px"}}>
RSSI:
</Typography>
{property.rssi} dbm
</Typography>
</Tooltip>
</Stack> </Stack>
</Stack> </Stack>
</Grid> </Grid>
@ -109,8 +140,8 @@ export const ConnectedDevices = () => {
)) ))
} }
</CardContent> </CardContent>
</Card>: ( </Card> : (
content ? <Typography> No connected devices found </Typography> : <CircularProgress/> content ? <Typography> No connected devices found </Typography> : <CircularProgress />
)} )}
</Stack> </Stack>
) )

View File

@ -80,9 +80,9 @@ export const DevicesWiFi = () => {
.catch(error => console.log('error', error)); .catch(error => console.log('error', error));
}; };
useEffect(()=>{ useEffect(() => {
fetchWifiData() fetchWifiData()
},[]) }, [])
return (<div> return (<div>
<Stack <Stack
@ -99,24 +99,24 @@ export const DevicesWiFi = () => {
title={item.name.value} title={item.name.value}
avatar={ avatar={
<SvgIcon> <SvgIcon>
<GlobeAltIcon/> <GlobeAltIcon />
</SvgIcon> </SvgIcon>
} }
/> />
<CardContent> <CardContent>
<Stack spacing={3}> <Stack spacing={3}>
{ item.enable.value != null && {item.enable.value != null &&
<FormControlLabel control={<Checkbox defaultChecked={item.enable.value == 1 ? true : false} <FormControlLabel control={<Checkbox defaultChecked={item.enable.value == 1 ? true : false}
onChange={(e) => { onChange={(e) => {
let enable = item.enable.value == 1 ? "0" : "1" let enable = item.enable.value == 1 ? "0" : "1"
console.log(enable) console.log(enable)
applyContent[index].hasChanges = true applyContent[index].hasChanges = true
applyContent[index].enable = { applyContent[index].enable = {
value : enable value: enable
} }
setApplyContent([...applyContent]) setApplyContent([...applyContent])
item.enable.value = enable item.enable.value = enable
}}/>} }} />}
label="Enabled" />} label="Enabled" />}
{item.ssid.value != null && <TextField {item.ssid.value != null && <TextField
fullWidth fullWidth
@ -126,7 +126,7 @@ export const DevicesWiFi = () => {
onChange={(e) => { onChange={(e) => {
applyContent[index].hasChanges = true applyContent[index].hasChanges = true
applyContent[index].ssid = { applyContent[index].ssid = {
value : e.target.value value: e.target.value
} }
setApplyContent([...applyContent]) setApplyContent([...applyContent])
item.ssid.value = e.target.value item.ssid.value = e.target.value
@ -148,17 +148,41 @@ export const DevicesWiFi = () => {
onChange={(e) => { onChange={(e) => {
if (e.target.value.length >= 8) { if (e.target.value.length >= 8) {
applyContent[index].hasChanges = true applyContent[index].hasChanges = true
}else{ } else {
applyContent[index].hasChanges = false applyContent[index].hasChanges = false
} }
applyContent[index].password = { applyContent[index].password = {
value : e.target.value value: e.target.value
} }
setApplyContent([...applyContent]) setApplyContent([...applyContent])
item.password.value = e.target.value item.password.value = e.target.value
console.log("applyContent: ", applyContent) console.log("applyContent: ", applyContent)
}} }}
/>} />}
{item.channel?.value != null && item.possibleChannels?.value != null &&
<FormControl variant='filled'>
<InputLabel id="channel">Channel</InputLabel>
<Select
fullWidth
defaultValue={item.channel.value}
value={item.channel.value}
onChange={(e) => {
applyContent[index].hasChanges = true
applyContent[index].channel = {
value: e.target.value
}
setApplyContent([...applyContent])
item.channel.value = e.target.value
}}
label="Channel"
>
{item.possibleChannels.value.map((channel, index) => {
return (
<MenuItem key={index} value={channel}>{channel}</MenuItem>)
})}
</Select>
</FormControl>
}
{item.standard.value != null && {item.standard.value != null &&
<TextField <TextField
fullWidth fullWidth
@ -168,20 +192,20 @@ export const DevicesWiFi = () => {
onChange={(e) => { onChange={(e) => {
applyContent[index].hasChanges = true applyContent[index].hasChanges = true
applyContent[index].standard = { applyContent[index].standard = {
value : e.target.value value: e.target.value
} }
setApplyContent([...applyContent]) setApplyContent([...applyContent])
item.standard.value = e.target.value item.standard.value = e.target.value
}} }}
/>} />}
</Stack> </Stack>
<CardActions sx={{display:"flex", justifyContent:"flex-end"}}> <CardActions sx={{ display: "flex", justifyContent: "flex-end" }}>
<Button <Button
variant="contained" variant="contained"
disabled={!applyContent[index].hasChanges} disabled={!applyContent[index].hasChanges}
endIcon={<SvgIcon><Check /></SvgIcon>} endIcon={<SvgIcon><Check /></SvgIcon>}
onClick={ onClick={
()=>{ () => {
setApply(true) setApply(true)
var myHeaders = new Headers(); var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json"); myHeaders.append("Content-Type", "application/json");
@ -221,7 +245,7 @@ export const DevicesWiFi = () => {
.catch(error => console.log('error', error)); .catch(error => console.log('error', error));
} }
} }
sx={{mt:'25px', mb:'-15px'}} sx={{ mt: '25px', mb: '-15px' }}
> >
Apply Apply
</Button> </Button>
@ -229,7 +253,7 @@ export const DevicesWiFi = () => {
</CardContent> </CardContent>
</Card> </Card>
) )
})): })) :
<CircularProgress /> <CircularProgress />
} }
</Stack> </Stack>
@ -241,7 +265,7 @@ export const DevicesWiFi = () => {
</Backdrop> </Backdrop>
<Dialog open={errorModal && errorModalText != ""} <Dialog open={errorModal && errorModalText != ""}
slotProps={{ backdrop: { style: { backgroundColor: 'rgba(255,255,255,0.5)' } } }} slotProps={{ backdrop: { style: { backgroundColor: 'rgba(255,255,255,0.5)' } } }}
fullWidth={ true } fullWidth={true}
maxWidth={"md"} maxWidth={"md"}
scroll={"paper"} scroll={"paper"}
aria-labelledby="scroll-dialog-title" aria-labelledby="scroll-dialog-title"
@ -251,27 +275,27 @@ export const DevicesWiFi = () => {
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
<Box flexGrow={1} >Response</Box> <Box flexGrow={1} >Response</Box>
<Box> <Box>
<IconButton onClick={()=>{ <IconButton onClick={() => {
setErrorModalText("") setErrorModalText("")
setErrorModal(false) setErrorModal(false)
}}> }}>
<SvgIcon <SvgIcon
> >
< XMarkIcon/> < XMarkIcon />
</SvgIcon> </SvgIcon>
</IconButton> </IconButton>
</Box> </Box>
</Box> </Box>
</DialogTitle> </DialogTitle>
<DialogContent dividers={scroll === 'paper'}> <DialogContent dividers={scroll === 'paper'}>
<DialogContentText id="scroll-dialog-description"tabIndex={-1}> <DialogContentText id="scroll-dialog-description" tabIndex={-1}>
<pre style={{color: 'black'}}> <pre style={{ color: 'black' }}>
{errorModalText} {errorModalText}
</pre> </pre>
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={()=>{ <Button onClick={() => {
setErrorModalText("") setErrorModalText("")
setErrorModal(false) setErrorModal(false)
}}>OK</Button> }}>OK</Button>

View File

@ -1,6 +1,3 @@
import PropTypes from 'prop-types';
import ArrowPathIcon from '@heroicons/react/24/solid/ArrowPathIcon';
import ArrowRightIcon from '@heroicons/react/24/solid/ArrowRightIcon';
import { import {
Button, Button,
Card, Card,
@ -22,12 +19,11 @@ import {
TableHead, TableHead,
TableRow, TableRow,
TableContainer, TableContainer,
Paper, CircularProgress,
Container, ToggleButton,
CircularProgress ToggleButtonGroup
} from '@mui/material'; } from '@mui/material';
import { Scrollbar } from 'src/components/scrollbar'; import { useTheme } from '@mui/material/styles';
import { alpha, useTheme } from '@mui/material/styles';
import { Chart } from 'src/components/chart'; import { Chart } from 'src/components/chart';
import ChartBarSquareIcon from '@heroicons/react/24/outline/ChartBarSquareIcon'; import ChartBarSquareIcon from '@heroicons/react/24/outline/ChartBarSquareIcon';
import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon'; import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon';
@ -35,7 +31,103 @@ import { useRouter } from 'next/router';
import { Stack } from '@mui/system'; import { Stack } from '@mui/system';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
const useChartOptions = () => { export const SiteSurvey = (props) => {
// const getMaxChannel = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 128;
// }
// }
// const geMinChannel = () => {
// if (frequency == "2.4GHz") {
// return 0;
// } else {
// return 36;
// }
// }
// const getChannelSpacing = () => {
// if (frequency == "2.4GHz") {
// return 1;
// } else {
// return 4;
// }
// }
// const getChannelAmount = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 20;
// }
// }
const getCategories = () => {
}
const router = useRouter();
const [frequency, setFrequency] = useState("2.4GHz");
const [view, setView] = useState("chart");
const [content, setContent] = useState(null);
const getSeries = () => {
let series = []
content[frequency].map((network) => {
let data = []
if (frequency == "2.4GHz") {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -2, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +2, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
}else {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -8, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +8, "y": -100})
}
if (Number(network.bandwidth) == 80) {
data.push({"x": Number(network.channel) -16, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +16, "y": -100})
}
if (Number(network.bandwidth) == 160) {
data.push({"x": Number(network.channel) -32, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +32, "y": -100})
}
}
let ssid = network.ssid
if ( ssid == "") {
ssid = " "
}
return series.push({
name: ssid,
data: data
})
})
return series;
}
const useChartOptions = () => {
const theme = useTheme(); const theme = useTheme();
return { return {
@ -44,100 +136,151 @@ const useChartOptions = () => {
stacked: false, stacked: false,
toolbar: { toolbar: {
show: true show: true
}
}, },
zoom: {
enabled: false
},
},
title: {
text: 'Site Survey Results',
},
// markers: {
// size: 5,
// hover: {
// size: 9
// }
// },
colors: [ colors: [
theme.palette.graphics.dark, theme.palette.graphics.dark,
theme.palette.warning.main,
theme.palette.graphics.darkest, theme.palette.graphics.darkest,
theme.palette.graphics.light,
theme.palette.graphics.main, theme.palette.graphics.main,
theme.palette.info.light,
theme.palette.graphics.lightest, theme.palette.graphics.lightest,
theme.palette.primary.main,
theme.palette.graphics.light,
theme.palette.error.light,
theme.palette.error.dark
], ],
dataLabels: { dataLabels: {
enabled: false enabled: false
}, },
fill: {
opacity: 1,
type: 'solid'
},
grid: { grid: {
borderColor: theme.palette.divider, //borderColor: theme.palette.divider,
strokeDashArray: 2, strokeDashArray: 2,
xaxis: { xaxis: {
lines: { lines: {
show: false show: true
} }
}, },
yaxis: { yaxis: {
lines: { lines: {
show: true show: true
} },
} },
}, },
legend: { legend: {
show: true show: true,
showForSingleSeries: true,
}, },
plotOptions: { plotOptions: {
bar: { area: {
columnWidth: '40px' fillTo: 'end',
} }
}, },
stroke: { stroke: {
colors: ['transparent'],
show: true, show: true,
width: 2 curve: 'smooth',
lineCap: 'round',
}, },
theme: { theme: {
mode: theme.palette.mode mode: theme.palette.mode
}, },
xaxis: {
axisBorder: {
color: theme.palette.divider,
show: true
},
axisTicks: {
color: theme.palette.divider,
show: true
},
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
],
labels: {
offsetY: 5,
style: {
colors: theme.palette.text.secondary
}
}
},
yaxis: { yaxis: {
min: -100,
max: 0,
labels: { labels: {
formatter: (value) => (value > 0 ? `${value}K` : `${value}`), formatter: function (value) {
offsetX: -10, return value + ' dBm';
},
//offsetY: -10,
style: { style: {
colors: theme.palette.text.secondary //colors: theme.palette.text.secondary
} }
},
},
// annotations: {
// xaxis: [
// {
// x: 9,
// x2: 10,
// borderColor: '#0b54ff',
// label: {
// style: {
// color: 'black',
// },
// text: 'Channel 10',
// offsetX: 45,
// borderColor: 'transparent',
// style: {
// background: 'transparent',
// color: theme.palette.text.secondary,
// fontSize: '17px',
// },
// }
// }
// ]
// },
// annotations: {
// points: [{
// x: 9,
// y: -5,
// label: {
// borderColor: '#775DD0',
// offsetY: 0,
// style: {
// color: '#fff',
// background: '#775DD0',
// },
// rotate: -45,
// text: 'Bananas are good',
// }
// }]
// },
xaxis: {
// tickPlacement: 'on',
// tickAmount: getChannelAmount(),
tickPlacement: 'on',
labels: {
show: true,
style: {
//colors: theme.palette.text.secondary
},
trim: true,
},
// max: getMaxChannel(),
// min: geMinChannel(),
// stepSize: getChannelSpacing(),
//type: 'category',
//categories: [getCategories()],
type: 'numeric',
decimalsInFloat: 0,
},
tooltip: {
x: {
show: true,
formatter: (seriesName) => "Channel "+ seriesName,
},
followCursor: false,
intersect: false,
shared: true,
enabled: true,
onDatasetHover: {
highlightDataSeries: true,
} }
} }
}; };
}; };
export const SiteSurvey = (props) => {
const chartSeries = [{ name: 'This year', data: [18, 16, 5, 8, 3, 14, 14, 16, 17, 19, 18, 20] }, { name: 'Last year', data: [12, 11, 4, 6, 2, 9, 9, 10, 11, 12, 13, 13] }]
const router = useRouter();
const [content, setContent] = useState(null);
const [frequency, setFrequency] = useState("2.4GHz");
const chartOptions = useChartOptions(); const chartOptions = useChartOptions();
@ -181,23 +324,30 @@ export const SiteSurvey = (props) => {
<Grid spacing={1}> <Grid spacing={1}>
<Grid container> <Grid container>
<Card> <Card>
<Button <ToggleButtonGroup
color="inherit" value={view}
exclusive
onChange={(e, value) => {
setView(value)
}}
>
<ToggleButton
size="small" size="small"
disabled="true" value="chart"
> >
<SvgIcon> <SvgIcon>
<ChartBarSquareIcon /> <ChartBarSquareIcon />
</SvgIcon> </SvgIcon>
</Button> </ToggleButton>
<Button <ToggleButton
color="inherit"
size="small" size="small"
value="list"
> >
<SvgIcon> <SvgIcon>
<ListBulletIcon /> <ListBulletIcon />
</SvgIcon> </SvgIcon>
</Button> </ToggleButton>
</ToggleButtonGroup>
</Card> </Card>
</Grid> </Grid>
<Box display="flex" <Box display="flex"
@ -221,7 +371,7 @@ export const SiteSurvey = (props) => {
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
</Box> </Box>
<Card sx={{ height: '100%' }}> {view == "list" && <Card sx={{ height: '100%' }}>
<Box sx={{ minWidth: 800, }}> <Box sx={{ minWidth: 800, }}>
<TableContainer sx={{ maxHeight: 600 }}> <TableContainer sx={{ maxHeight: 600 }}>
<Table exportButton={true}> <Table exportButton={true}>
@ -273,31 +423,18 @@ export const SiteSurvey = (props) => {
</Table> </Table>
</TableContainer> </TableContainer>
</Box> </Box>
{/* <CardContent> </Card>}
{view == "chart" && <Card>
<CardContent>
<Chart <Chart
height={500} height={500}
options={chartOptions} options={chartOptions}
series={chartSeries} series={getSeries()}
type="bar" type="area"
width="100%" width="100%"
/> />
</CardContent> </CardContent>
<Divider /> </Card>}
<CardActions sx={{ justifyContent: 'center' }}>
<FormControl xs={2}>
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={"2.4GHz"}
>
<Grid container>
<FormControlLabel value="2.4GHz" control={<Radio />} label="2.4GHz" />
<FormControlLabel value="5GHz" control={<Radio />} label="5GHz" />
</Grid>
</RadioGroup>
</FormControl>
</CardActions> */}
</Card>
</Grid>: <CircularProgress></CircularProgress>} </Grid>: <CircularProgress></CircularProgress>}
</Stack> </Stack>
); );

View File

@ -97,7 +97,7 @@ const showIcon = (mtpType) => {
</Stack> </Stack>
<Avatar <Avatar
sx={{ sx={{
backgroundColor: '#f28950', backgroundColor: 'primary.darkest',
height: 56, height: 56,
width: 56 width: 56
}} }}

View File

@ -70,7 +70,6 @@ const useChartOptions = (labels,title) => {
} }
else{ else{
options.colors = [ options.colors = [
theme.palette.primary.main,
theme.palette.info.main, theme.palette.info.main,
theme.palette.warning.main, theme.palette.warning.main,
theme.palette.graphics.lightest, theme.palette.graphics.lightest,

View File

@ -11,8 +11,16 @@ const withAlphas = (color) => {
}; };
}; };
export const neutral = { export const neutral = (colors) => {
50: '#306d6f', console.log("neutral colors:", colors);
let parsedColors = JSON.parse(colors);
let tableColor = parsedColors["tables"]
let sidebarColorInitial = parsedColors["sidebar_initial"]
let wordsOutsideSidebarColor = parsedColors["words_outside_sidebar"]
return {
50: tableColor,
100: '#F3F4F6', 100: '#F3F4F6',
200: '#E5E7EB', 200: '#E5E7EB',
300: '#D2D6DB', 300: '#D2D6DB',
@ -20,18 +28,29 @@ export const neutral = {
500: '#6C737F', 500: '#6C737F',
600: '#4D5761', 600: '#4D5761',
700: '#FFFFFF', 700: '#FFFFFF',
800: '#306d6f', 800: sidebarColorInitial,
900: '#30596f' 900: wordsOutsideSidebarColor,
}
}; };
export const indigo = withAlphas({ export const indigo = (colors) => {
console.log("indigo colors:", colors);
let parsedColors = JSON.parse(colors);
let buttonColor = parsedColors["buttons"]
let sidebarColorEnd = parsedColors["sidebar_end"]
let mtpsColor = parsedColors["connected_mtps_color"]
return withAlphas({
lightest: '#FFFFFF', lightest: '#FFFFFF',
light: '#306D6F', light: '#ff3383',
main: '#306D6F', main: buttonColor,
dark: '#255355', dark: sidebarColorEnd,
darkest: '#00a0b8', darkest: mtpsColor,
contrastText: '#FFFFFF' contrastText: '#FFFFFF'
}); });
}
export const success = withAlphas({ export const success = withAlphas({
lightest: '#F0FDF9', lightest: '#F0FDF9',

View File

@ -2,15 +2,62 @@ import { common } from '@mui/material/colors';
import { alpha } from '@mui/material/styles'; import { alpha } from '@mui/material/styles';
import { error, indigo, info, neutral, success, warning, graphics } from './colors'; import { error, indigo, info, neutral, success, warning, graphics } from './colors';
const getColorScheme = async () => {
let result = await fetch('http://localhost/custom-frontend/colors').catch((error) => {
console.log('Error fetching colors');
sessionStorage.setItem('colors', JSON.stringify({
"buttons": "#306d6f",
"sidebar_end": "#306d6f",
"sidebar_initial": "#306d6f",
"tables": "#306d6f",
"words_outside_sidebar": "#30596f",
"connected_mtps_color": "#f28950"
}));
location.reload();
return
});
if (result.status!=200) {
console.log('Error fetching colors');
sessionStorage.setItem('colors', JSON.stringify({
"buttons": "#306d6f",
"sidebar_end": "#306d6f",
"sidebar_initial": "#306d6f",
"tables": "#306d6f",
"words_outside_sidebar": "#30596f",
"connected_mtps_color": "#f28950"
}));
location.reload();
return
}
let response = await result.json();
let fmtresponse = JSON.stringify(response);
sessionStorage.setItem('colors', fmtresponse);
location.reload();
}
export function createPalette() { export function createPalette() {
let colors = sessionStorage.getItem('colors');
if (colors !== null) {
console.log('colors already fetched');
} else {
getColorScheme();
}
console.log("colors scheme:", colors);
let neutralColors = neutral(colors);
return { return {
action: { action: {
active: neutral[500], active: neutralColors[500],
disabled: alpha(neutral[900], 0.38), disabled: alpha(neutralColors[900], 0.38),
disabledBackground: alpha(neutral[900], 0.12), disabledBackground: alpha(neutralColors[900], 0.12),
focus: alpha(neutral[900], 0.16), focus: alpha(neutralColors[900], 0.16),
hover: alpha(neutral[900], 0.04), hover: alpha(neutralColors[900], 0.04),
selected: alpha(neutral[900], 0.12) selected: alpha(neutralColors[900], 0.12)
}, },
background: { background: {
default: common.white, default: common.white,
@ -21,13 +68,13 @@ export function createPalette() {
graphics, graphics,
info, info,
mode: 'light', mode: 'light',
neutral, neutral: neutralColors,
primary: indigo, primary: indigo(colors),
success, success,
text: { text: {
primary: neutral[900], primary: neutralColors[900],
secondary: neutral[500], secondary: neutralColors[500],
disabled: alpha(neutral[900], 0.38) disabled: alpha(neutralColors[900], 0.38)
}, },
warning warning
}; };

View File

@ -0,0 +1,47 @@
/* The location pointed to by the popup tip. */
.popup-tip-anchor {
height: 0;
position: absolute;
/* The max width of the info window. */
width: 200px;
}
/* The bubble is anchored above the tip. */
.popup-bubble-anchor {
position: absolute;
width: 100%;
bottom: /* TIP_HEIGHT= */ 8px;
left: 0;
}
/* Draw the tip. */
.popup-bubble-anchor::after {
content: "";
position: absolute;
top: 0;
left: 0;
/* Center the tip horizontally. */
transform: translate(-50%, 0);
/* The tip is a https://css-tricks.com/snippets/css/css-triangle/ */
width: 0;
height: 0;
/* The tip is 8px high, and 12px wide. */
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: /* TIP_HEIGHT= */ 8px solid white;
}
/* The popup bubble itself. */
.popup-bubble-content {
position: absolute;
top: 0;
left: 0;
transform: translate(-50%, -100%);
/* Style the info window. */
background-color: white;
padding: 5px;
border-radius: 5px;
font-family: sans-serif;
font-size: 14px ;
overflow-y: auto;
max-height: 80px;
box-shadow: 0px 2px 10px 1px rgba(0, 0, 0, 0.5);
}