feat(api): dashboard and general info [ close #125 ]
This commit is contained in:
parent
2d9257f21c
commit
8843cd9dab
|
|
@ -62,7 +62,12 @@ func StartApi(a Api) {
|
|||
iot.HandleFunc("/{sn}/fw_update", a.deviceFwUpdate).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/wifi", a.deviceWifi).Methods("PUT", "GET")
|
||||
mtp := r.PathPrefix("/api/mtp").Subrouter()
|
||||
mtp.HandleFunc("/mqtt", a.MqttInfo).Methods("GET")
|
||||
mtp.HandleFunc("", a.mtpInfo).Methods("GET")
|
||||
dash := r.PathPrefix("/api/info").Subrouter()
|
||||
dash.HandleFunc("/vendors", a.vendorsInfo).Methods("GET")
|
||||
dash.HandleFunc("/status", a.statusInfo).Methods("GET")
|
||||
dash.HandleFunc("/device_class", a.productClassInfo).Methods("GET")
|
||||
dash.HandleFunc("/general", a.generalInfo).Methods("GET")
|
||||
users := r.PathPrefix("/api/users").Subrouter()
|
||||
users.HandleFunc("", a.retrieveUsers).Methods("GET")
|
||||
|
||||
|
|
@ -75,6 +80,10 @@ func StartApi(a Api) {
|
|||
return middleware.Middleware(handler)
|
||||
})
|
||||
|
||||
dash.Use(func(handler http.Handler) http.Handler {
|
||||
return middleware.Middleware(handler)
|
||||
})
|
||||
|
||||
users.Use(func(handler http.Handler) http.Handler {
|
||||
return middleware.Middleware(handler)
|
||||
})
|
||||
|
|
|
|||
146
backend/services/controller/internal/api/info.go
Normal file
146
backend/services/controller/internal/api/info.go
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/leandrofars/oktopus/internal/db"
|
||||
"github.com/leandrofars/oktopus/internal/utils"
|
||||
)
|
||||
|
||||
type StatusCount struct {
|
||||
Online int
|
||||
Offline int
|
||||
}
|
||||
|
||||
type GeneralInfo struct {
|
||||
MqttRtt time.Duration
|
||||
ProductClassCount []db.ProductClassCount
|
||||
StatusCount StatusCount
|
||||
VendorsCount []db.VendorsCount
|
||||
}
|
||||
|
||||
func (a *Api) generalInfo(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var result GeneralInfo
|
||||
|
||||
productclasscount, err := a.Db.RetrieveProductsClassInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
vendorcount, err := a.Db.RetrieveVendorsInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
statuscount, err := a.Db.RetrieveStatusInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range statuscount {
|
||||
switch v.Status {
|
||||
case utils.Online:
|
||||
result.StatusCount.Online = v.Count
|
||||
case utils.Offline:
|
||||
result.StatusCount.Offline = v.Count
|
||||
}
|
||||
}
|
||||
|
||||
result.VendorsCount = vendorcount
|
||||
result.ProductClassCount = productclasscount
|
||||
|
||||
/* ------------ TODO: [mqtt rtt] create common function for this ------------ */
|
||||
//TODO: address with value from env or something like that
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:1883")
|
||||
if err != nil {
|
||||
json.NewEncoder(w).Encode("Error to connect to broker")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
info, err := tcpInfo(conn.(*net.TCPConn))
|
||||
if err != nil {
|
||||
json.NewEncoder(w).Encode("Error to get TCP socket info")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
rtt := time.Duration(info.Rtt) * time.Microsecond
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
result.MqttRtt = rtt / 1000
|
||||
|
||||
err = json.NewEncoder(w).Encode(result)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Api) vendorsInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vendors, err := a.Db.RetrieveVendorsInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(vendors)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Api) productClassInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vendors, err := a.Db.RetrieveProductsClassInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(vendors)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Api) statusInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vendors, err := a.Db.RetrieveStatusInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var status StatusCount
|
||||
for _, v := range vendors {
|
||||
switch v.Status {
|
||||
case utils.Online:
|
||||
status.Online = v.Count
|
||||
case utils.Offline:
|
||||
status.Offline = v.Count
|
||||
}
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(status)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -10,10 +10,10 @@ import (
|
|||
)
|
||||
|
||||
type mqttInfo struct {
|
||||
Rtt time.Duration
|
||||
MqttRtt time.Duration
|
||||
}
|
||||
|
||||
func (a *Api) MqttInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (a *Api) mtpInfo(w http.ResponseWriter, r *http.Request) {
|
||||
//TODO: address with value from env or something like that
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:1883")
|
||||
if err != nil {
|
||||
|
|
@ -31,7 +31,7 @@ func (a *Api) MqttInfo(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
rtt := time.Duration(info.Rtt) * time.Microsecond
|
||||
json.NewEncoder(w).Encode(mqttInfo{
|
||||
Rtt: rtt / 1000,
|
||||
MqttRtt: rtt / 1000,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ type Device struct {
|
|||
Customer string
|
||||
Vendor string
|
||||
Version string
|
||||
ProductClass string
|
||||
Status uint8
|
||||
MTP []map[string]string
|
||||
}
|
||||
|
|
|
|||
97
backend/services/controller/internal/db/info.go
Normal file
97
backend/services/controller/internal/db/info.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type VendorsCount struct {
|
||||
Vendor string `bson:"_id" json:"vendor"`
|
||||
Count int `bson:"count" json:"count"`
|
||||
}
|
||||
|
||||
type ProductClassCount struct {
|
||||
ProductClass string `bson:"_id" json:"productClass"`
|
||||
Count int `bson:"count" json:"count"`
|
||||
}
|
||||
|
||||
type StatusCount struct {
|
||||
Status int `bson:"_id" json:"status"`
|
||||
Count int `bson:"count" json:"count"`
|
||||
}
|
||||
|
||||
func (d *Database) RetrieveVendorsInfo() ([]VendorsCount, error) {
|
||||
var results []VendorsCount
|
||||
cursor, err := d.devices.Aggregate(d.ctx, []bson.M{
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$vendor",
|
||||
"count": bson.M{"$sum": 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(d.ctx)
|
||||
if err := cursor.All(d.ctx, &results); err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
for _, result := range results {
|
||||
log.Println(result)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (d *Database) RetrieveStatusInfo() ([]StatusCount, error) {
|
||||
var results []StatusCount
|
||||
cursor, err := d.devices.Aggregate(d.ctx, []bson.M{
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$status",
|
||||
"count": bson.M{"$sum": 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(d.ctx)
|
||||
if err := cursor.All(d.ctx, &results); err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
for _, result := range results {
|
||||
log.Println(result)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (d *Database) RetrieveProductsClassInfo() ([]ProductClassCount, error) {
|
||||
var results []ProductClassCount
|
||||
cursor, err := d.devices.Aggregate(d.ctx, []bson.M{
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$productclass",
|
||||
"count": bson.M{"$sum": 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(d.ctx)
|
||||
if err := cursor.All(d.ctx, &results); err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
for _, result := range results {
|
||||
log.Println(result)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"log"
|
||||
)
|
||||
|
||||
// TODO: fix this function to also change device status at different mtp
|
||||
func (d *Database) UpdateStatus(sn string, status uint8) error {
|
||||
var result bson.M
|
||||
err := d.devices.FindOneAndUpdate(d.ctx, bson.D{{"sn", sn}}, bson.D{{"$set", bson.D{{"status", status}}}}).Decode(&result)
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ func (m *Mqtt) handleNewDevice(deviceMac string) {
|
|||
"Device.DeviceInfo.ModelName",
|
||||
"Device.DeviceInfo.SoftwareVersion",
|
||||
"Device.DeviceInfo.SerialNumber",
|
||||
"Device.DeviceInfo.ProductClass",
|
||||
},
|
||||
MaxDepth: 1,
|
||||
},
|
||||
|
|
@ -284,6 +285,7 @@ func (m *Mqtt) handleNewDevicesResponse(p []byte, sn string) {
|
|||
device.Vendor = msg.ReqPathResults[0].ResolvedPathResults[0].ResultParams["Manufacturer"]
|
||||
device.Model = msg.ReqPathResults[1].ResolvedPathResults[0].ResultParams["ModelName"]
|
||||
device.Version = msg.ReqPathResults[2].ResolvedPathResults[0].ResultParams["SoftwareVersion"]
|
||||
device.ProductClass = msg.ReqPathResults[4].ResolvedPathResults[0].ResultParams["ProductClass"]
|
||||
device.SN = sn
|
||||
|
||||
mtp := map[string]string{
|
||||
|
|
@ -291,6 +293,7 @@ func (m *Mqtt) handleNewDevicesResponse(p []byte, sn string) {
|
|||
}
|
||||
|
||||
device.MTP = append(device.MTP, mtp)
|
||||
device.Status = utils.Online
|
||||
|
||||
err = m.DB.CreateDevice(device)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user