| @@ -18,6 +18,7 @@ import ( | |||||
| "github.com/AFASystems/presence/internal/pkg/common/appcontext" | "github.com/AFASystems/presence/internal/pkg/common/appcontext" | ||||
| "github.com/AFASystems/presence/internal/pkg/config" | "github.com/AFASystems/presence/internal/pkg/config" | ||||
| "github.com/AFASystems/presence/internal/pkg/controller" | "github.com/AFASystems/presence/internal/pkg/controller" | ||||
| "github.com/AFASystems/presence/internal/pkg/database" | |||||
| "github.com/AFASystems/presence/internal/pkg/kafkaclient" | "github.com/AFASystems/presence/internal/pkg/kafkaclient" | ||||
| "github.com/AFASystems/presence/internal/pkg/model" | "github.com/AFASystems/presence/internal/pkg/model" | ||||
| "github.com/AFASystems/presence/internal/pkg/service" | "github.com/AFASystems/presence/internal/pkg/service" | ||||
| @@ -32,7 +33,6 @@ var upgrader = websocket.Upgrader{ | |||||
| } | } | ||||
| var _ io.Writer = (*os.File)(nil) | var _ io.Writer = (*os.File)(nil) | ||||
| var wg sync.WaitGroup | var wg sync.WaitGroup | ||||
| func main() { | func main() { | ||||
| @@ -53,6 +53,11 @@ func main() { | |||||
| ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT) | ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT) | ||||
| defer stop() | defer stop() | ||||
| db, err := database.Connect(cfg) | |||||
| if err != nil { | |||||
| log.Fatalf("Failed to open database connection: %v\n", err) | |||||
| } | |||||
| headersOk := handlers.AllowedHeaders([]string{"X-Requested-With"}) | headersOk := handlers.AllowedHeaders([]string{"X-Requested-With"}) | ||||
| originsOk := handlers.AllowedOrigins([]string{"*"}) | originsOk := handlers.AllowedOrigins([]string{"*"}) | ||||
| methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"}) | methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"}) | ||||
| @@ -87,6 +92,11 @@ func main() { | |||||
| r.HandleFunc("/api/settings", controller.SettingsListController(appState, ctx)).Methods("GET") | r.HandleFunc("/api/settings", controller.SettingsListController(appState, ctx)).Methods("GET") | ||||
| r.HandleFunc("/api/settings", controller.SettingsEditController(settingsWriter, appState, ctx)).Methods("POST") | r.HandleFunc("/api/settings", controller.SettingsEditController(settingsWriter, appState, ctx)).Methods("POST") | ||||
| r.HandleFunc("/reslevis/getGateways", controller.GatewayListController(db)).Methods("GET") | |||||
| r.HandleFunc("/reslevis/postGateway", controller.GatewayAddController(db)).Methods("POST") | |||||
| r.HandleFunc("/reslevis/removeGateway/{gateway_id}", controller.GatewayDeleteController(db)).Methods("DELETE") | |||||
| r.HandleFunc("/reslevis/updateGateway/{gateway_id}", controller.GatewayUpdateController(db)).Methods("PUT") | |||||
| wsHandler := http.HandlerFunc(serveWs(appState, ctx)) | wsHandler := http.HandlerFunc(serveWs(appState, ctx)) | ||||
| restApiHandler := handlers.CORS(originsOk, headersOk, methodsOk)(r) | restApiHandler := handlers.CORS(originsOk, headersOk, methodsOk)(r) | ||||
| mainHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | mainHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| @@ -10,6 +10,10 @@ type Config struct { | |||||
| MQTTPass string | MQTTPass string | ||||
| MQTTClientID string | MQTTClientID string | ||||
| KafkaURL string | KafkaURL string | ||||
| DBHost string | |||||
| DBUser string | |||||
| DBPass string | |||||
| DBName string | |||||
| } | } | ||||
| // getEnv returns env var value or a default if not set. | // getEnv returns env var value or a default if not set. | ||||
| @@ -29,5 +33,9 @@ func Load() *Config { | |||||
| MQTTPass: getEnv("MQTT_PASSWORD", "pass"), | MQTTPass: getEnv("MQTT_PASSWORD", "pass"), | ||||
| MQTTClientID: getEnv("MQTT_CLIENT_ID", "presence-detector"), | MQTTClientID: getEnv("MQTT_CLIENT_ID", "presence-detector"), | ||||
| KafkaURL: getEnv("KAFKA_URL", "127.0.0.1:9092"), | KafkaURL: getEnv("KAFKA_URL", "127.0.0.1:9092"), | ||||
| DBHost: getEnv("DBHost", "127.0.0.1"), | |||||
| DBUser: getEnv("DBUser", "postgres"), | |||||
| DBPass: getEnv("DBPass", "postgres"), | |||||
| DBName: getEnv("DBName", "go_crud_db"), | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,77 @@ | |||||
| package controller | |||||
| import ( | |||||
| "encoding/json" | |||||
| "fmt" | |||||
| "net/http" | |||||
| "github.com/AFASystems/presence/internal/pkg/model" | |||||
| "github.com/gorilla/mux" | |||||
| "gorm.io/gorm" | |||||
| ) | |||||
| func GatewayAddController(db *gorm.DB) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| decoder := json.NewDecoder(r.Body) | |||||
| var gateway model.Gateway | |||||
| if err := decoder.Decode(&gateway); err != nil { | |||||
| http.Error(w, err.Error(), 400) | |||||
| return | |||||
| } | |||||
| db.Create(&gateway) | |||||
| w.Write([]byte("ok")) | |||||
| } | |||||
| } | |||||
| func GatewayListController(db *gorm.DB) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| var gateways []model.Gateway | |||||
| db.Find(&gateways) | |||||
| fmt.Printf("gateways: %+v", gateways) | |||||
| res, err := json.Marshal(gateways) | |||||
| if err != nil { | |||||
| http.Error(w, err.Error(), 400) | |||||
| return | |||||
| } | |||||
| w.Write(res) | |||||
| } | |||||
| } | |||||
| func GatewayDeleteController(db *gorm.DB) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| vars := mux.Vars(r) | |||||
| id := vars["gateway_id"] | |||||
| if res := db.Delete(&model.Gateway{}, "id = ?", id); res.RowsAffected == 0 { | |||||
| http.Error(w, "no gateway with such ID found", 400) | |||||
| return | |||||
| } | |||||
| w.Write([]byte("ok")) | |||||
| } | |||||
| } | |||||
| func GatewayUpdateController(db *gorm.DB) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| vars := mux.Vars(r) | |||||
| id := vars["gateway_id"] | |||||
| if err := db.First(&model.Gateway{}, id).Error; err != nil { | |||||
| http.Error(w, err.Error(), 400) | |||||
| return | |||||
| } | |||||
| decoder := json.NewDecoder(r.Body) | |||||
| var gateway model.Gateway | |||||
| if err := decoder.Decode(&gateway); err != nil { | |||||
| http.Error(w, err.Error(), 400) | |||||
| return | |||||
| } | |||||
| db.Save(&gateway) | |||||
| w.Write([]byte("ok")) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| package database | |||||
| import ( | |||||
| "fmt" | |||||
| "github.com/AFASystems/presence/internal/pkg/config" | |||||
| "github.com/AFASystems/presence/internal/pkg/model" | |||||
| "gorm.io/driver/postgres" | |||||
| "gorm.io/gorm" | |||||
| ) | |||||
| var DB *gorm.DB | |||||
| func Connect(cfg *config.Config) (*gorm.DB, error) { | |||||
| // Connect to PostgreSQL database | |||||
| dsn := fmt.Sprintf( | |||||
| "host=%s user=%s password=%s dbname=%s port=5432 sslmode=disable", | |||||
| cfg.DBHost, | |||||
| cfg.DBUser, | |||||
| cfg.DBPass, | |||||
| cfg.DBName, | |||||
| ) | |||||
| db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| if err := db.AutoMigrate(&model.Gateway{}); err != nil { | |||||
| return nil, err | |||||
| } | |||||
| fmt.Println("Database connection established") | |||||
| return db, nil | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package model | |||||
| type Gateway struct { | |||||
| ID string `json:"id" gorm:"primaryKey"` | |||||
| Name string `json:"name"` | |||||
| MAC string `json:"mac"` | |||||
| Status string `json:"status"` | |||||
| Model string `json:"model"` | |||||
| IP string `json:"ip"` | |||||
| Position string `json:"position"` | |||||
| X int `json:"x"` | |||||
| Y int `json:"y"` | |||||
| Notes string `json:"notes"` | |||||
| Floor string `json:"floor"` | |||||
| Building string `json:"building"` | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| package model | |||||
| type TrackerZones struct { | |||||
| ID string `json:"id"` | |||||
| ZoneList []string `json:"zoneList"` | |||||
| Tracker string `json:"tracker"` | |||||
| Days string `json:"days"` | |||||
| Time string `json:"time"` | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| package model | |||||
| type Zone struct { | |||||
| ID string `json:"id" gorm:"primaryKey"` | |||||
| Name string `json:"name"` | |||||
| Groups []string `json:"groups"` | |||||
| Floor string `json:"floor"` | |||||
| Building string `json:"building"` | |||||
| } | |||||