| @@ -40,14 +40,15 @@ func mqtthandler(writer *kafka.Writer, topic string, message []byte, appState *a | |||
| if reading.Type == "Gateway" { | |||
| continue | |||
| } | |||
| val, ok := appState.BeaconExists(reading.MAC) | |||
| // fmt.Printf("reading: %+v\n", reading) | |||
| if !appState.BeaconExists(reading.MAC) { | |||
| if !ok { | |||
| continue | |||
| } | |||
| fmt.Printf("Tracking beacon: %s\n", reading.MAC) | |||
| adv := model.BeaconAdvertisement{ | |||
| ID: val, | |||
| Hostname: hostname, | |||
| MAC: reading.MAC, | |||
| RSSI: int64(reading.RSSI), | |||
| @@ -63,6 +64,7 @@ func mqtthandler(writer *kafka.Writer, topic string, message []byte, appState *a | |||
| msg := kafka.Message{ | |||
| Value: encodedMsg, | |||
| } | |||
| err = writer.WriteMessages(context.Background(), msg) | |||
| if err != nil { | |||
| fmt.Println("Error in writing to Kafka: ", err) | |||
| @@ -167,12 +169,17 @@ eventloop: | |||
| case msg := <-chApi: | |||
| switch msg.Method { | |||
| case "POST": | |||
| id := msg.Beacon.ID | |||
| appState.AddBeaconToLookup(id) | |||
| id := msg.ID | |||
| appState.AddBeaconToLookup(msg.MAC, id) | |||
| lMsg := fmt.Sprintf("Beacon added to lookup: %s", id) | |||
| slog.Info(lMsg) | |||
| case "DELETE": | |||
| id := msg.Beacon.ID | |||
| id := msg.MAC | |||
| if id == "all" { | |||
| appState.CleanLookup() | |||
| fmt.Println("cleaned up lookup map") | |||
| continue | |||
| } | |||
| appState.RemoveBeaconFromLookup(id) | |||
| lMsg := fmt.Sprintf("Beacon removed from lookup: %s", id) | |||
| slog.Info(lMsg) | |||
| @@ -83,7 +83,7 @@ func processIncoming(adv model.BeaconAdvertisement, appState *appcontext.AppStat | |||
| func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, writer *kafka.Writer) error { | |||
| beacon := strings.TrimSpace(adv.Data) | |||
| id := adv.MAC | |||
| id := adv.ID | |||
| if beacon == "" { | |||
| return nil | |||
| } | |||
| @@ -109,6 +109,7 @@ func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, | |||
| } | |||
| eMsg, err := event.ToJSON() | |||
| fmt.Printf("event: %+v\n", eMsg) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| @@ -86,6 +86,7 @@ func getLikelyLocations(appState *appcontext.AppState, writer *kafka.Writer) { | |||
| settings := appState.GetSettingsValue() | |||
| for _, beacon := range beacons { | |||
| fmt.Println("id: ", beacon.ID) | |||
| // Shrinking the model because other properties have nothing to do with the location | |||
| r := model.HTTPLocation{ | |||
| Method: "Standard", | |||
| @@ -175,6 +176,8 @@ func getLikelyLocations(appState *appcontext.AppState, writer *kafka.Writer) { | |||
| Value: js, | |||
| } | |||
| fmt.Println("sending message") | |||
| err = writer.WriteMessages(context.Background(), msg) | |||
| if err != nil { | |||
| eMsg := fmt.Sprintf("Error in sending Kafka message: %v", err) | |||
| @@ -184,7 +187,7 @@ func getLikelyLocations(appState *appcontext.AppState, writer *kafka.Writer) { | |||
| } | |||
| func assignBeaconToList(adv model.BeaconAdvertisement, appState *appcontext.AppState) { | |||
| id := adv.MAC | |||
| id := adv.ID | |||
| now := time.Now().Unix() | |||
| settings := appState.GetSettingsValue() | |||
| @@ -15,13 +15,13 @@ import ( | |||
| "syscall" | |||
| "time" | |||
| "github.com/AFASystems/presence/internal/pkg/apiclient" | |||
| "github.com/AFASystems/presence/internal/pkg/common/appcontext" | |||
| "github.com/AFASystems/presence/internal/pkg/config" | |||
| "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/model" | |||
| "github.com/AFASystems/presence/internal/pkg/service" | |||
| "github.com/gorilla/handlers" | |||
| "github.com/gorilla/mux" | |||
| "github.com/gorilla/websocket" | |||
| @@ -66,6 +66,10 @@ func main() { | |||
| settingsWriter := appState.AddKafkaWriter(cfg.KafkaURL, "settings") | |||
| slog.Info("Kafka writers topics: apibeacons, settings initialized") | |||
| if err := apiclient.UpdateDB(db, ctx, cfg, writer); err != nil { | |||
| fmt.Printf("Error in getting token: %v\n", err) | |||
| } | |||
| locationReader := appState.AddKafkaReader(cfg.KafkaURL, "locevents", "gid-loc-server") | |||
| alertsReader := appState.AddKafkaReader(cfg.KafkaURL, "alertbeacons", "gid-alert-serv") | |||
| slog.Info("Kafka readers topics: locevents, alertbeacons initialized") | |||
| @@ -92,10 +96,10 @@ func main() { | |||
| r.HandleFunc("/reslevis/removeZone/{id}", controller.ZoneDeleteController(db)).Methods("DELETE") | |||
| r.HandleFunc("/reslevis/updateZone", controller.ZoneUpdateController(db)).Methods("PUT") | |||
| r.HandleFunc("/reslevis/getTrackerZones", controller.TrackerListController(db)).Methods("GET") | |||
| r.HandleFunc("/reslevis/postTrackerZone", controller.TrackerAddController(db)).Methods("POST") | |||
| r.HandleFunc("/reslevis/removeTrackerZone/{id}", controller.TrackerDeleteController(db)).Methods("DELETE") | |||
| r.HandleFunc("/reslevis/updateTrackerZone", controller.TrackerUpdateController(db)).Methods("PUT") | |||
| r.HandleFunc("/reslevis/getTrackerZones", controller.TrackerZoneListController(db)).Methods("GET") | |||
| r.HandleFunc("/reslevis/postTrackerZone", controller.TrackerZoneAddController(db)).Methods("POST") | |||
| r.HandleFunc("/reslevis/removeTrackerZone/{id}", controller.TrackerZoneDeleteController(db)).Methods("DELETE") | |||
| r.HandleFunc("/reslevis/updateTrackerZone", controller.TrackerZoneUpdateController(db)).Methods("PUT") | |||
| r.HandleFunc("/reslevis/getTrackers", controller.TrackerList(db)).Methods("GET") | |||
| r.HandleFunc("/reslevis/postTracker", controller.TrackerAdd(db, writer, ctx)).Methods("POST") | |||
| @@ -126,15 +130,36 @@ eventLoop: | |||
| case <-ctx.Done(): | |||
| break eventLoop | |||
| case msg := <-chLoc: | |||
| if err := service.LocationToBeaconService(msg, appState, ctx); err != nil { | |||
| eMsg := fmt.Sprintf("Error in writing location change to beacon: %v\n", err) | |||
| slog.Error(eMsg) | |||
| id := msg.ID | |||
| if err := db.First(&model.Tracker{}, "id = ?", id).Error; err != nil { | |||
| fmt.Printf("Location event for untracked beacon: %s\n", id) | |||
| continue | |||
| } | |||
| if err := db.Updates(&model.Tracker{ID: id, Location: msg.Location, Distance: msg.Distance}).Error; err != nil { | |||
| fmt.Println("Error in saving distance for beacon: ", err) | |||
| continue | |||
| } | |||
| // if err := service.LocationToBeaconService(msg, appState, ctx); err != nil { | |||
| // eMsg := fmt.Sprintf("Error in writing location change to beacon: %v\n", err) | |||
| // slog.Error(eMsg) | |||
| // } | |||
| case msg := <-chEvents: | |||
| if err := service.EventToBeaconService(msg, appState, ctx); err != nil { | |||
| eMsg := fmt.Sprintf("Error in writing event change to beacon: %v\n", err) | |||
| slog.Error(eMsg) | |||
| fmt.Printf("event: %+v\n", msg) | |||
| id := msg.ID | |||
| if err := db.First(&model.Tracker{}, "id = ?", id).Error; err != nil { | |||
| fmt.Printf("Decoder event for untracked beacon: %s\n", id) | |||
| continue | |||
| } | |||
| if err := db.Updates(&model.Tracker{ID: id, Battery: msg.Battery}).Error; err != nil { | |||
| fmt.Printf("Error in saving decoder event for beacon: %s\n", id) | |||
| continue | |||
| } | |||
| // if err := service.EventToBeaconService(msg, appState, ctx); err != nil { | |||
| // eMsg := fmt.Sprintf("Error in writing event change to beacon: %v\n", err) | |||
| // slog.Error(eMsg) | |||
| // } | |||
| } | |||
| } | |||
| @@ -0,0 +1,161 @@ | |||
| package main | |||
| import ( | |||
| "context" | |||
| "crypto/tls" | |||
| "encoding/json" | |||
| "fmt" | |||
| "net/http" | |||
| "net/url" | |||
| "strings" | |||
| "github.com/AFASystems/presence/internal/pkg/model" | |||
| ) | |||
| type response struct { | |||
| A string `json:"access_token"` | |||
| } | |||
| func main() { | |||
| ctx := context.Background() | |||
| tr := &http.Transport{ | |||
| TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | |||
| } | |||
| client := &http.Client{Transport: tr} | |||
| formData := url.Values{} | |||
| formData.Set("grant_type", "password") | |||
| formData.Set("client_id", "Fastapi") | |||
| formData.Set("client_secret", "wojuoB7Z5xhlPFrF2lIxJSSdVHCApEgC") | |||
| formData.Set("username", "core") | |||
| formData.Set("password", "C0r3_us3r_Cr3d3nt14ls") | |||
| formData.Set("audience", "Fastapi") | |||
| req, err := http.NewRequest("POST", "https://10.251.0.30:10002/realms/API.Server.local/protocol/openid-connect/token", strings.NewReader(formData.Encode())) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | |||
| req = req.WithContext(ctx) | |||
| res, err := client.Do(req) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| var j response | |||
| err = json.NewDecoder(res.Body).Decode(&j) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| token := j.A | |||
| trackers, err := GetTrackers(token, client) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| fmt.Printf("trackers: %+v\n", trackers) | |||
| gateways, err := getGateways(token, client) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| fmt.Printf("gateways: %+v\n", gateways) | |||
| zones, err := GetZones(token, client) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| fmt.Printf("zones: %+v\n", zones) | |||
| trackerZones, err := GetTrackerZones(token, client) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| fmt.Printf("tracker zones: %+v\n", trackerZones) | |||
| } | |||
| func GetTrackers(token string, client *http.Client) ([]model.Tracker, error) { | |||
| res, err := getRequest(token, "getTrackers", client) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var i []model.Tracker | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func getGateways(token string, client *http.Client) ([]model.Gateway, error) { | |||
| res, err := getRequest(token, "getGateways", client) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var i []model.Gateway | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func GetTrackerZones(token string, client *http.Client) ([]model.TrackerZones, error) { | |||
| res, err := getRequest(token, "getTrackerZones", client) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var i []model.TrackerZones | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func GetZones(token string, client *http.Client) ([]model.Zone, error) { | |||
| res, err := getRequest(token, "getZones", client) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var i []model.Zone | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func getRequest(token, route string, client *http.Client) (*http.Response, error) { | |||
| url := fmt.Sprintf("https://10.251.0.30:5050/reslevis/%s", route) | |||
| req, err := http.NewRequest("GET", url, nil) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| header := fmt.Sprintf("Bearer %s", token) | |||
| req.Header.Add("Authorization", header) | |||
| res, err := client.Do(req) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return res, nil | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| package apiclient | |||
| import ( | |||
| "context" | |||
| "encoding/json" | |||
| "net/http" | |||
| "net/url" | |||
| "strings" | |||
| "github.com/AFASystems/presence/internal/pkg/config" | |||
| ) | |||
| type response struct { | |||
| Token string `json:"access_token"` | |||
| } | |||
| func GetToken(ctx context.Context, cfg *config.Config, client *http.Client) (string, error) { | |||
| formData := url.Values{} | |||
| formData.Set("grant_type", "password") | |||
| formData.Set("client_id", "Fastapi") | |||
| formData.Set("client_secret", "wojuoB7Z5xhlPFrF2lIxJSSdVHCApEgC") | |||
| formData.Set("username", "core") | |||
| formData.Set("password", "C0r3_us3r_Cr3d3nt14ls") | |||
| formData.Set("audience", "Fastapi") | |||
| req, err := http.NewRequest("POST", "https://10.251.0.30:10002/realms/API.Server.local/protocol/openid-connect/token", strings.NewReader(formData.Encode())) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | |||
| req = req.WithContext(ctx) | |||
| res, err := client.Do(req) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| var j response | |||
| if err := json.NewDecoder(res.Body).Decode(&j); err != nil { | |||
| return "", err | |||
| } | |||
| return j.Token, nil | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| package apiclient | |||
| import ( | |||
| "encoding/json" | |||
| "fmt" | |||
| "net/http" | |||
| "github.com/AFASystems/presence/internal/pkg/model" | |||
| ) | |||
| func GetTrackers(token string, client *http.Client) ([]model.Tracker, error) { | |||
| res, err := getRequest(token, "getTrackers", client) | |||
| if err != nil { | |||
| return []model.Tracker{}, err | |||
| } | |||
| var i []model.Tracker | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return []model.Tracker{}, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func GetGateways(token string, client *http.Client) ([]model.Gateway, error) { | |||
| res, err := getRequest(token, "getGateways", client) | |||
| if err != nil { | |||
| return []model.Gateway{}, err | |||
| } | |||
| var i []model.Gateway | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return []model.Gateway{}, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func GetTrackerZones(token string, client *http.Client) ([]model.TrackerZones, error) { | |||
| res, err := getRequest(token, "getTrackerZones", client) | |||
| if err != nil { | |||
| return []model.TrackerZones{}, err | |||
| } | |||
| var i []model.TrackerZones | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return []model.TrackerZones{}, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func GetZones(token string, client *http.Client) ([]model.Zone, error) { | |||
| res, err := getRequest(token, "getZones", client) | |||
| if err != nil { | |||
| return []model.Zone{}, err | |||
| } | |||
| var i []model.Zone | |||
| err = json.NewDecoder(res.Body).Decode(&i) | |||
| if err != nil { | |||
| return []model.Zone{}, err | |||
| } | |||
| return i, nil | |||
| } | |||
| func getRequest(token, route string, client *http.Client) (*http.Response, error) { | |||
| url := fmt.Sprintf("https://10.251.0.30:5050/reslevis/%s", route) | |||
| req, err := http.NewRequest("GET", url, nil) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| header := fmt.Sprintf("Bearer %s", token) | |||
| req.Header.Add("Authorization", header) | |||
| res, err := client.Do(req) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return res, nil | |||
| } | |||
| @@ -0,0 +1,79 @@ | |||
| package apiclient | |||
| import ( | |||
| "context" | |||
| "crypto/tls" | |||
| "fmt" | |||
| "net/http" | |||
| "github.com/AFASystems/presence/internal/pkg/config" | |||
| "github.com/AFASystems/presence/internal/pkg/controller" | |||
| "github.com/AFASystems/presence/internal/pkg/model" | |||
| "github.com/segmentio/kafka-go" | |||
| "gorm.io/gorm" | |||
| "gorm.io/gorm/clause" | |||
| ) | |||
| func UpdateDB(db *gorm.DB, ctx context.Context, cfg *config.Config, writer *kafka.Writer) error { | |||
| tr := &http.Transport{ | |||
| TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | |||
| } | |||
| client := &http.Client{Transport: tr} | |||
| token, err := GetToken(ctx, cfg, client) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| trackers, err := GetTrackers(token, client) | |||
| if err != nil { | |||
| fmt.Printf("Error in getting trackers: %+v\n", err) | |||
| } | |||
| if err := controller.SendKafkaMessage(writer, &model.ApiUpdate{Method: "DELETE", MAC: "all"}, ctx); err != nil { | |||
| fmt.Printf("Error in sending delete all from lookup message: %v", err) | |||
| } | |||
| for _, v := range trackers { | |||
| apiUpdate := model.ApiUpdate{ | |||
| Method: "POST", | |||
| ID: v.ID, | |||
| MAC: v.MAC, | |||
| } | |||
| if err := controller.SendKafkaMessage(writer, &apiUpdate, ctx); err != nil { | |||
| fmt.Printf("Error in sending POST kafka message: %v", err) | |||
| } | |||
| } | |||
| gateways, err := GetGateways(token, client) | |||
| if err != nil { | |||
| fmt.Printf("Error in getting gateways: %+v\n", err) | |||
| } | |||
| zones, err := GetZones(token, client) | |||
| if err != nil { | |||
| fmt.Printf("Error in getting zones: %+v\n", err) | |||
| } | |||
| trackerZones, err := GetTrackerZones(token, client) | |||
| if err != nil { | |||
| fmt.Printf("Error in getting tracker zones: %+v\n", err) | |||
| } | |||
| db.Clauses(clause.OnConflict{ | |||
| Columns: []clause.Column{{Name: "id"}}, | |||
| UpdateAll: true, | |||
| }).Create(&trackers) | |||
| db.Clauses(clause.OnConflict{ | |||
| Columns: []clause.Column{{Name: "id"}}, | |||
| UpdateAll: true, | |||
| }).Create(&gateways) | |||
| db.Clauses(clause.OnConflict{ | |||
| Columns: []clause.Column{{Name: "id"}}, | |||
| UpdateAll: true, | |||
| }).Create(&zones) | |||
| db.Clauses(clause.OnConflict{ | |||
| Columns: []clause.Column{{Name: "id"}}, | |||
| UpdateAll: true, | |||
| }).Create(&trackerZones) | |||
| return nil | |||
| } | |||
| @@ -15,7 +15,7 @@ type AppState struct { | |||
| httpResults model.HTTPResultList | |||
| settings model.Settings | |||
| beaconEvents model.BeaconEventList | |||
| beaconsLookup map[string]struct{} | |||
| beaconsLookup map[string]string | |||
| latestList model.LatestBeaconsList | |||
| kafkaReadersList model.KafkaReadersList | |||
| kafkaWritersList model.KafkaWritersList | |||
| @@ -44,7 +44,7 @@ func NewAppState() *AppState { | |||
| beaconEvents: model.BeaconEventList{ | |||
| Beacons: make(map[string]model.BeaconEvent), | |||
| }, | |||
| beaconsLookup: make(map[string]struct{}), | |||
| beaconsLookup: make(map[string]string), | |||
| latestList: model.LatestBeaconsList{ | |||
| LatestList: make(map[string]model.Beacon), | |||
| }, | |||
| @@ -129,7 +129,7 @@ func (m *AppState) GetBeaconEvents() *model.BeaconEventList { | |||
| } | |||
| // GetBeaconsLookup returns thread-safe access to beacon lookup map | |||
| func (m *AppState) GetBeaconsLookup() map[string]struct{} { | |||
| func (m *AppState) GetBeaconsLookup() map[string]string { | |||
| return m.beaconsLookup | |||
| } | |||
| @@ -139,8 +139,8 @@ func (m *AppState) GetLatestList() *model.LatestBeaconsList { | |||
| } | |||
| // AddBeaconToLookup adds a beacon ID to the lookup map | |||
| func (m *AppState) AddBeaconToLookup(id string) { | |||
| m.beaconsLookup[id] = struct{}{} | |||
| func (m *AppState) AddBeaconToLookup(id, value string) { | |||
| m.beaconsLookup[id] = value | |||
| } | |||
| // RemoveBeaconFromLookup removes a beacon ID from the lookup map | |||
| @@ -148,6 +148,10 @@ func (m *AppState) RemoveBeaconFromLookup(id string) { | |||
| delete(m.beaconsLookup, id) | |||
| } | |||
| func (m *AppState) CleanLookup() { | |||
| clear(m.beaconsLookup) | |||
| } | |||
| func (m *AppState) RemoveBeacon(id string) { | |||
| m.beacons.Lock.Lock() | |||
| delete(m.beacons.Beacons, id) | |||
| @@ -161,9 +165,9 @@ func (m *AppState) RemoveHTTPResult(id string) { | |||
| } | |||
| // BeaconExists checks if a beacon exists in the lookup | |||
| func (m *AppState) BeaconExists(id string) bool { | |||
| _, exists := m.beaconsLookup[id] | |||
| return exists | |||
| func (m *AppState) BeaconExists(id string) (string, bool) { | |||
| val, exists := m.beaconsLookup[id] | |||
| return val, exists | |||
| } | |||
| // GetBeacon returns a beacon by ID (thread-safe) | |||
| @@ -14,6 +14,11 @@ type Config struct { | |||
| DBUser string | |||
| DBPass string | |||
| DBName string | |||
| HTTPClientID string | |||
| ClientSecret string | |||
| HTTPUsername string | |||
| HTTPPassword string | |||
| HTTPAudience string | |||
| } | |||
| // getEnv returns env var value or a default if not set. | |||
| @@ -37,5 +42,10 @@ func Load() *Config { | |||
| DBUser: getEnv("DBUser", "postgres"), | |||
| DBPass: getEnv("DBPass", "postgres"), | |||
| DBName: getEnv("DBName", "go_crud_db"), | |||
| HTTPClientID: getEnv("HTTPClientID", "Fastapi"), | |||
| ClientSecret: getEnv("ClientSecret", "wojuoB7Z5xhlPFrF2lIxJSSdVHCApEgC"), | |||
| HTTPUsername: getEnv("HTTPUsername", "core"), | |||
| HTTPPassword: getEnv("HTTPPassword", "C0r3_us3r_Cr3d3nt14ls"), | |||
| HTTPAudience: getEnv("HTTPAudience", "Fastapi"), | |||
| } | |||
| } | |||
| @@ -12,7 +12,7 @@ import ( | |||
| "gorm.io/gorm" | |||
| ) | |||
| func sendKafkaMessage(writer *kafka.Writer, value *model.ApiUpdate, ctx context.Context) error { | |||
| func SendKafkaMessage(writer *kafka.Writer, value *model.ApiUpdate, ctx context.Context) error { | |||
| valueStr, err := json.Marshal(&value) | |||
| if err != nil { | |||
| fmt.Println("error in encoding: ", err) | |||
| @@ -42,9 +42,10 @@ func TrackerAdd(db *gorm.DB, writer *kafka.Writer, ctx context.Context) http.Han | |||
| apiUpdate := model.ApiUpdate{ | |||
| Method: "POST", | |||
| ID: tracker.ID, | |||
| MAC: tracker.MAC, | |||
| } | |||
| if err := sendKafkaMessage(writer, &apiUpdate, ctx); err != nil { | |||
| if err := SendKafkaMessage(writer, &apiUpdate, ctx); err != nil { | |||
| fmt.Println("error in sending Kafka POST message") | |||
| http.Error(w, "Error in sending kafka message", 500) | |||
| return | |||
| @@ -90,6 +91,9 @@ func TrackerUpdate(db *gorm.DB) http.HandlerFunc { | |||
| func TrackerDelete(db *gorm.DB, writer *kafka.Writer, ctx context.Context) http.HandlerFunc { | |||
| return func(w http.ResponseWriter, r *http.Request) { | |||
| id := mux.Vars(r)["id"] | |||
| var tracker model.Tracker | |||
| db.Find(&tracker, "id = ?", id) | |||
| if res := db.Delete(&model.Tracker{}, "id = ?", id); res.RowsAffected == 0 { | |||
| http.Error(w, "no tracker with such ID found", 400) | |||
| return | |||
| @@ -97,12 +101,12 @@ func TrackerDelete(db *gorm.DB, writer *kafka.Writer, ctx context.Context) http. | |||
| apiUpdate := model.ApiUpdate{ | |||
| Method: "Delete", | |||
| ID: id, | |||
| ID: tracker.ID, | |||
| } | |||
| fmt.Printf("Sending DELETE tracker id: %s message\n", id) | |||
| if err := sendKafkaMessage(writer, &apiUpdate, ctx); err != nil { | |||
| if err := SendKafkaMessage(writer, &apiUpdate, ctx); err != nil { | |||
| fmt.Println("error in sending Kafka DELETE message") | |||
| http.Error(w, "Error in sending kafka message", 500) | |||
| return | |||
| @@ -10,7 +10,7 @@ import ( | |||
| ) | |||
| // controller/tracker_controller.go | |||
| func TrackerAddController(db *gorm.DB) http.HandlerFunc { | |||
| func TrackerZoneAddController(db *gorm.DB) http.HandlerFunc { | |||
| return func(w http.ResponseWriter, r *http.Request) { | |||
| var tz model.TrackerZones | |||
| if err := json.NewDecoder(r.Body).Decode(&tz); err != nil { | |||
| @@ -22,7 +22,7 @@ func TrackerAddController(db *gorm.DB) http.HandlerFunc { | |||
| } | |||
| } | |||
| func TrackerListController(db *gorm.DB) http.HandlerFunc { | |||
| func TrackerZoneListController(db *gorm.DB) http.HandlerFunc { | |||
| return func(w http.ResponseWriter, r *http.Request) { | |||
| var list []model.TrackerZones | |||
| db.Find(&list) | |||
| @@ -30,7 +30,7 @@ func TrackerListController(db *gorm.DB) http.HandlerFunc { | |||
| } | |||
| } | |||
| func TrackerUpdateController(db *gorm.DB) http.HandlerFunc { | |||
| func TrackerZoneUpdateController(db *gorm.DB) http.HandlerFunc { | |||
| return func(w http.ResponseWriter, r *http.Request) { | |||
| var tz model.TrackerZones | |||
| @@ -55,7 +55,7 @@ func TrackerUpdateController(db *gorm.DB) http.HandlerFunc { | |||
| } | |||
| } | |||
| func TrackerDeleteController(db *gorm.DB) http.HandlerFunc { | |||
| func TrackerZoneDeleteController(db *gorm.DB) http.HandlerFunc { | |||
| return func(w http.ResponseWriter, r *http.Request) { | |||
| id := mux.Vars(r)["id"] | |||
| if res := db.Delete(&model.TrackerZones{}, "id = ?", id); res.RowsAffected == 0 { | |||
| @@ -1,16 +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"` | |||
| 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 float32 `json:"x"` | |||
| Y float32 `json:"y"` | |||
| Notes string `json:"notes"` | |||
| Floor string `json:"floor"` | |||
| Building string `json:"building"` | |||
| } | |||
| @@ -1,15 +1,18 @@ | |||
| package model | |||
| type Tracker struct { | |||
| ID string `json:"id" gorm:"primaryKey` | |||
| Name string `json:"name"` | |||
| MAC string `json:"mac"` | |||
| Status string `json:"status"` | |||
| Model string `json:"model"` | |||
| Position string `json:"position"` | |||
| Notes string `json:"notes"` | |||
| X int `json:"x"` | |||
| Y int `json:"y"` | |||
| Floor string `json:"floor" gorm:"type:uuid"` | |||
| Building string `json:"building" gorm:"type:uuid"` | |||
| ID string `json:"id" gorm:"primaryKey"` | |||
| Name string `json:"name"` | |||
| MAC string `json:"mac"` | |||
| Status string `json:"status"` | |||
| Model string `json:"model"` | |||
| Position string `json:"position"` | |||
| Notes string `json:"notes"` | |||
| X float32 `json:"x"` | |||
| Y float32 `json:"y"` | |||
| Floor string `json:"floor"` | |||
| Building string `json:"building"` | |||
| Location string `json:"location"` | |||
| Distance float64 `json:"distance"` | |||
| Battery uint32 `json:"battery"` | |||
| } | |||
| @@ -24,6 +24,7 @@ type Settings struct { | |||
| // BeaconAdvertisement represents the JSON payload received from beacon advertisements. | |||
| type BeaconAdvertisement struct { | |||
| ID string | |||
| Hostname string `json:"hostname"` | |||
| MAC string `json:"mac"` | |||
| RSSI int64 `json:"rssi"` | |||
| @@ -169,8 +170,8 @@ type LatestBeaconsList struct { | |||
| type ApiUpdate struct { | |||
| Method string | |||
| Beacon HTTPResult | |||
| ID string | |||
| MAC string | |||
| } | |||
| type KafkaReadersList struct { | |||