| @@ -3,7 +3,6 @@ package server | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | |||||
| "log/slog" | "log/slog" | ||||
| "time" | "time" | ||||
| @@ -57,7 +56,6 @@ func RunEventLoop(ctx context.Context, a *ServerApp) { | |||||
| continue | continue | ||||
| } | } | ||||
| if msg.Type == "Eddystone" && msg.Battery < 3000 { | if msg.Type == "Eddystone" && msg.Battery < 3000 { | ||||
| fmt.Printf("Sending alert for battery low: %+v\n", msg) | |||||
| service.SendAlert(id, "BatteryLow", a.KafkaManager.GetWriter("alert"), ctx, a.DB) | service.SendAlert(id, "BatteryLow", a.KafkaManager.GetWriter("alert"), ctx, a.DB) | ||||
| } | } | ||||
| case <-beaconTicker.C: | case <-beaconTicker.C: | ||||
| @@ -57,8 +57,14 @@ func (a *ServerApp) RegisterRoutes() http.Handler { | |||||
| r.HandleFunc("/reslevis/alerts/{id}", controller.AlertUpdateStatusController(a.DB, a.ctx)).Methods("PATCH") | r.HandleFunc("/reslevis/alerts/{id}", controller.AlertUpdateStatusController(a.DB, a.ctx)).Methods("PATCH") | ||||
| r.HandleFunc("/reslevis/alerts/{id}", controller.AlertDeleteController(a.DB, a.ctx)).Methods("DELETE") | r.HandleFunc("/reslevis/alerts/{id}", controller.AlertDeleteController(a.DB, a.ctx)).Methods("DELETE") | ||||
| r.HandleFunc("/reslevis/getFloors", controller.FloorListController(a.DB, a.ctx)).Methods("GET") | |||||
| r.HandleFunc("/reslevis/postFloor", controller.FloorAddController(a.DB, a.ctx)).Methods("POST") | |||||
| r.HandleFunc("/reslevis/updateFloor", controller.FloorUpdateController(a.DB, a.ctx)).Methods("PUT") | |||||
| r.HandleFunc("/reslevis/removeFloor/{id}", controller.FloorDeleteController(a.DB, a.ctx)).Methods("DELETE") | |||||
| // Tracks | // Tracks | ||||
| r.HandleFunc("/reslevis/getTracks/{id}", controller.TracksListController(a.DB, a.ctx)).Methods("GET") | r.HandleFunc("/reslevis/getTracks/{id}", controller.TracksListController(a.DB, a.ctx)).Methods("GET") | ||||
| r.HandleFunc("/reslevis/getTracks", controller.TracksListAllController(a.DB, a.ctx)).Methods("GET") | |||||
| r.HandleFunc("/reslevis/health", controller.HealthController(a.AppState, a.ctx)).Methods("GET") | r.HandleFunc("/reslevis/health", controller.HealthController(a.AppState, a.ctx)).Methods("GET") | ||||
| @@ -26,7 +26,6 @@ func GetToken(ctx context.Context, cfg *config.Config, client *http.Client) (str | |||||
| req, err := http.NewRequest("POST", fmt.Sprintf("%s/realms/API.Server.local/protocol/openid-connect/token", cfg.APIAuthURL), strings.NewReader(formData.Encode())) | req, err := http.NewRequest("POST", fmt.Sprintf("%s/realms/API.Server.local/protocol/openid-connect/token", cfg.APIAuthURL), strings.NewReader(formData.Encode())) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Println("error", err) | |||||
| return "", err | return "", err | ||||
| } | } | ||||
| req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | ||||
| @@ -34,16 +33,16 @@ func GetToken(ctx context.Context, cfg *config.Config, client *http.Client) (str | |||||
| req = req.WithContext(ctx) | req = req.WithContext(ctx) | ||||
| res, err := client.Do(req) | res, err := client.Do(req) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Println("error", err) | |||||
| return "", err | return "", err | ||||
| } | } | ||||
| var j response | var j response | ||||
| if err := json.NewDecoder(res.Body).Decode(&j); err != nil { | if err := json.NewDecoder(res.Body).Decode(&j); err != nil { | ||||
| fmt.Println("error", err) | |||||
| return "", err | return "", err | ||||
| } | } | ||||
| fmt.Printf("token: %s\n", j.Token) | |||||
| return j.Token, nil | return j.Token, nil | ||||
| } | } | ||||
| @@ -12,14 +12,12 @@ import ( | |||||
| func GetTrackers(token string, client *http.Client, cfg *config.Config) ([]model.Tracker, error) { | func GetTrackers(token string, client *http.Client, cfg *config.Config) ([]model.Tracker, error) { | ||||
| res, err := getRequest(token, "getTrackers", client, cfg) | res, err := getRequest(token, "getTrackers", client, cfg) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error get trackers: %+v\n", err) | |||||
| return []model.Tracker{}, err | return []model.Tracker{}, err | ||||
| } | } | ||||
| var i []model.Tracker | var i []model.Tracker | ||||
| err = json.NewDecoder(res.Body).Decode(&i) | err = json.NewDecoder(res.Body).Decode(&i) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error decode trackers: %+v\n", err) | |||||
| return []model.Tracker{}, err | return []model.Tracker{}, err | ||||
| } | } | ||||
| @@ -29,7 +27,6 @@ func GetTrackers(token string, client *http.Client, cfg *config.Config) ([]model | |||||
| func GetGateways(token string, client *http.Client, cfg *config.Config) ([]model.Gateway, error) { | func GetGateways(token string, client *http.Client, cfg *config.Config) ([]model.Gateway, error) { | ||||
| res, err := getRequest(token, "getGateways", client, cfg) | res, err := getRequest(token, "getGateways", client, cfg) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error get gateways: %+v\n", err) | |||||
| return []model.Gateway{}, err | return []model.Gateway{}, err | ||||
| } | } | ||||
| @@ -76,7 +73,6 @@ func InferPosition(token string, client *http.Client, cfg *config.Config) (model | |||||
| url := fmt.Sprintf("%s/ble-ai/infer", cfg.APIBaseURL) | url := fmt.Sprintf("%s/ble-ai/infer", cfg.APIBaseURL) | ||||
| req, err := http.NewRequest("GET", url, nil) | req, err := http.NewRequest("GET", url, nil) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error new request: %+v\n", err) | |||||
| return model.PositionResponse{}, err | return model.PositionResponse{}, err | ||||
| } | } | ||||
| @@ -84,20 +80,16 @@ func InferPosition(token string, client *http.Client, cfg *config.Config) (model | |||||
| res, err := client.Do(req) | res, err := client.Do(req) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error do request: %+v\n", err) | |||||
| return model.PositionResponse{}, err | return model.PositionResponse{}, err | ||||
| } | } | ||||
| fmt.Printf("res.status: %s\n", res.Status) | |||||
| if res.StatusCode != 200 { | if res.StatusCode != 200 { | ||||
| fmt.Printf("error status code: %d\n", res.StatusCode) | |||||
| return model.PositionResponse{}, fmt.Errorf("status code: %d", res.StatusCode) | return model.PositionResponse{}, fmt.Errorf("status code: %d", res.StatusCode) | ||||
| } | } | ||||
| var i model.PositionResponse | var i model.PositionResponse | ||||
| err = json.NewDecoder(res.Body).Decode(&i) | err = json.NewDecoder(res.Body).Decode(&i) | ||||
| if err != nil { | if err != nil { | ||||
| fmt.Printf("error decode response: %+v\n", err) | |||||
| return model.PositionResponse{}, err | return model.PositionResponse{}, err | ||||
| } | } | ||||
| @@ -31,8 +31,7 @@ func UpdateDB(db *gorm.DB, ctx context.Context, cfg *config.Config, writer *kafk | |||||
| if trackers, err := GetTrackers(token, client, cfg); err == nil { | if trackers, err := GetTrackers(token, client, cfg); err == nil { | ||||
| syncTable(db, trackers) | syncTable(db, trackers) | ||||
| if err := controller.SendKafkaMessage(writer, &model.ApiUpdate{Method: "DELETE", MAC: "all"}, ctx); err != nil { | if err := controller.SendKafkaMessage(writer, &model.ApiUpdate{Method: "DELETE", MAC: "all"}, ctx); err != nil { | ||||
| msg := fmt.Sprintf("Error in sending delete all from lookup message: %v", err) | |||||
| slog.Error(msg) | |||||
| slog.Error("Error in sending delete all from lookup message", "error", err) | |||||
| } | } | ||||
| for _, v := range trackers { | for _, v := range trackers { | ||||
| @@ -64,7 +63,6 @@ func UpdateDB(db *gorm.DB, ctx context.Context, cfg *config.Config, writer *kafk | |||||
| if inferredPosition, err := InferPosition(token, client, cfg); err == nil { | if inferredPosition, err := InferPosition(token, client, cfg); err == nil { | ||||
| for _, v := range inferredPosition.Items { | for _, v := range inferredPosition.Items { | ||||
| mac := convertMac(v.Mac) | mac := convertMac(v.Mac) | ||||
| fmt.Println(mac) | |||||
| db.Model(&model.Tracker{}).Where("mac = ?", mac).Update("x", v.X).Update("y", v.Y) | db.Model(&model.Tracker{}).Where("mac = ?", mac).Update("x", v.X).Update("y", v.Y) | ||||
| } | } | ||||
| } | } | ||||
| @@ -14,7 +14,6 @@ func setHeader(req *http.Request, token string) { | |||||
| func getRequest(token, route string, client *http.Client, cfg *config.Config) (*http.Response, error) { | func getRequest(token, route string, client *http.Client, cfg *config.Config) (*http.Response, error) { | ||||
| url := fmt.Sprintf("%s/reslevis/%s", cfg.APIBaseURL, route) | url := fmt.Sprintf("%s/reslevis/%s", cfg.APIBaseURL, route) | ||||
| fmt.Printf("url: %s\n", url) | |||||
| req, err := http.NewRequest("GET", url, nil) | req, err := http.NewRequest("GET", url, nil) | ||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| @@ -3,7 +3,6 @@ package bridge | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | |||||
| "log/slog" | "log/slog" | ||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| @@ -60,7 +59,7 @@ func HandleMQTTMessage(topic string, payload []byte, appState *appcontext.AppSta | |||||
| } | } | ||||
| return | return | ||||
| } else { | } else { | ||||
| fmt.Println("CSV message: ", msgStr) | |||||
| slog.Debug("CSV message received", "topic", topic, "message", msgStr) | |||||
| } | } | ||||
| // CSV format: validate minimum fields (e.g. 6 columns); full parsing can be added later | // CSV format: validate minimum fields (e.g. 6 columns); full parsing can be added later | ||||
| s := strings.Split(msgStr, ",") | s := strings.Split(msgStr, ",") | ||||
| @@ -1,8 +1,6 @@ | |||||
| package utils | package utils | ||||
| import ( | import ( | ||||
| "fmt" | |||||
| "github.com/AFASystems/presence/internal/pkg/common/appcontext" | "github.com/AFASystems/presence/internal/pkg/common/appcontext" | ||||
| "github.com/AFASystems/presence/internal/pkg/model" | "github.com/AFASystems/presence/internal/pkg/model" | ||||
| ) | ) | ||||
| @@ -45,14 +43,11 @@ func LoopADStructures(b []byte, i [][2]int, id string, parserRegistry *model.Par | |||||
| for _, r := range i { | for _, r := range i { | ||||
| ad := b[r[0]:r[1]] | ad := b[r[0]:r[1]] | ||||
| if !isValidADStructure(ad) { | if !isValidADStructure(ad) { | ||||
| fmt.Println("invalid ad structure: ", beacon) | |||||
| break | break | ||||
| } | } | ||||
| for name, parser := range parserRegistry.ParserList { | for name, parser := range parserRegistry.ParserList { | ||||
| if parser.CanParse(ad) { | if parser.CanParse(ad) { | ||||
| event, ok := parser.Parse(name, ad) | event, ok := parser.Parse(name, ad) | ||||
| fmt.Println("beacon id: ", id) | |||||
| fmt.Println("parser can parse: ", name) | |||||
| if ok { | if ok { | ||||
| event.ID = id | event.ID = id | ||||
| event.Name = id | event.Name = id | ||||
| @@ -60,7 +55,6 @@ func LoopADStructures(b []byte, i [][2]int, id string, parserRegistry *model.Par | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // fmt.Println("no parser can parse: ", beacon) | |||||
| } | } | ||||
| return be | return be | ||||
| @@ -0,0 +1,75 @@ | |||||
| package controller | |||||
| import ( | |||||
| "context" | |||||
| "encoding/json" | |||||
| "net/http" | |||||
| "github.com/AFASystems/presence/internal/pkg/api/response" | |||||
| "github.com/AFASystems/presence/internal/pkg/model" | |||||
| "github.com/AFASystems/presence/internal/pkg/validation" | |||||
| "github.com/gorilla/mux" | |||||
| "gorm.io/gorm" | |||||
| ) | |||||
| func FloorAddController(db *gorm.DB, context context.Context) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| var floor model.Floor | |||||
| if err := json.NewDecoder(r.Body).Decode(&floor); err != nil { | |||||
| response.BadRequest(w, "invalid request body") | |||||
| return | |||||
| } | |||||
| if err := validation.Struct(&floor); err != nil { | |||||
| response.BadRequest(w, err.Error()) | |||||
| return | |||||
| } | |||||
| if err := db.WithContext(context).Create(&floor).Error; err != nil { | |||||
| response.InternalError(w, "failed to create floor", err) | |||||
| return | |||||
| } | |||||
| response.JSON(w, http.StatusCreated, map[string]string{"status": "created"}) | |||||
| } | |||||
| } | |||||
| func FloorListController(db *gorm.DB, context context.Context) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| var floors []model.Floor | |||||
| if err := db.WithContext(context).Find(&floors).Error; err != nil { | |||||
| response.InternalError(w, "failed to list floors", err) | |||||
| return | |||||
| } | |||||
| if err := db.WithContext(context).Find(&floors).Error; err != nil { | |||||
| response.InternalError(w, "failed to list floors", err) | |||||
| return | |||||
| } | |||||
| response.JSON(w, http.StatusOK, floors) | |||||
| } | |||||
| } | |||||
| func FloorUpdateController(db *gorm.DB, context context.Context) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| var floor model.Floor | |||||
| if err := json.NewDecoder(r.Body).Decode(&floor); err != nil { | |||||
| response.BadRequest(w, "invalid request body") | |||||
| return | |||||
| } | |||||
| } | |||||
| } | |||||
| func FloorDeleteController(db *gorm.DB, context context.Context) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| id := mux.Vars(r)["id"] | |||||
| res := db.WithContext(context).Delete(&model.Floor{}, "id = ?", id) | |||||
| if res.RowsAffected == 0 { | |||||
| response.NotFound(w, "floor not found") | |||||
| return | |||||
| } | |||||
| if res.Error != nil { | |||||
| response.InternalError(w, "failed to delete floor", res.Error) | |||||
| return | |||||
| } | |||||
| response.JSON(w, http.StatusOK, map[string]string{"status": "deleted"}) | |||||
| } | |||||
| } | |||||
| @@ -2,6 +2,7 @@ package controller | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "log/slog" | |||||
| "net/http" | "net/http" | ||||
| "strconv" | "strconv" | ||||
| "time" | "time" | ||||
| @@ -42,3 +43,53 @@ func TracksListController(db *gorm.DB, context context.Context) http.HandlerFunc | |||||
| response.JSON(w, http.StatusOK, tracks) | response.JSON(w, http.StatusOK, tracks) | ||||
| } | } | ||||
| } | } | ||||
| func TracksListAllController(db *gorm.DB, context context.Context) http.HandlerFunc { | |||||
| return func(w http.ResponseWriter, r *http.Request) { | |||||
| query := r.URL.Query() | |||||
| lStr := query.Get("limit") | |||||
| if lStr == "" { | |||||
| lStr = "100" | |||||
| } | |||||
| limit, err := strconv.Atoi(lStr) | |||||
| if err != nil { | |||||
| slog.Error("Error in converting limit string to integer value") | |||||
| response.InternalError(w, "internal server error", err) | |||||
| return | |||||
| } | |||||
| offsetStr := query.Get("offset") | |||||
| if offsetStr == "" { | |||||
| offsetStr = "0" | |||||
| } | |||||
| offset, err := strconv.Atoi(offsetStr) | |||||
| if err != nil { | |||||
| slog.Error("Error in converting offset string to integer value") | |||||
| response.InternalError(w, "internal server error", err) | |||||
| return | |||||
| } | |||||
| var tracks []model.Tracks | |||||
| // Subquery to get the latest timestamp per tracker | |||||
| subQuery := db.Model(&model.Tracks{}). | |||||
| Select("tracker, MAX(timestamp) AS max_timestamp"). | |||||
| Group("tracker") | |||||
| if err := db.WithContext(context). | |||||
| Table("tracks"). | |||||
| Select("tracks.*"). | |||||
| Joins("JOIN (?) AS latest ON tracks.tracker = latest.tracker AND tracks.timestamp = latest.max_timestamp", subQuery). | |||||
| Order("tracks.timestamp DESC"). | |||||
| Limit(limit). | |||||
| Offset(offset). | |||||
| Find(&tracks).Error; err != nil { | |||||
| response.InternalError(w, "failed to list tracks", err) | |||||
| return | |||||
| } | |||||
| response.JSON(w, http.StatusOK, tracks) | |||||
| } | |||||
| } | |||||
| @@ -26,7 +26,7 @@ func Connect(cfg *config.Config) (*gorm.DB, error) { | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| if err := db.AutoMigrate(&model.Gateway{}, model.Zone{}, model.TrackerZones{}, model.Tracker{}, model.Config{}, appcontext.Settings{}, model.Tracks{}, &model.Alert{}); err != nil { | |||||
| if err := db.AutoMigrate(&model.Gateway{}, model.Zone{}, model.TrackerZones{}, model.Tracker{}, model.Config{}, appcontext.Settings{}, model.Tracks{}, &model.Alert{}, model.Floor{}); err != nil { | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -0,0 +1,11 @@ | |||||
| package model | |||||
| type Floor struct { | |||||
| ID string `gorm:"unique;primaryKey"` | |||||
| Name string `json:"name"` | |||||
| FloorNumber int `json:"floornumber"` | |||||
| Image string `json:"image"` | |||||
| Description string `json:"description"` | |||||
| Scale int `json:"scale"` | |||||
| Building string `json:"building"` | |||||
| } | |||||
| @@ -17,4 +17,7 @@ type Tracks struct { | |||||
| Floor string `json:"floor"` | Floor string `json:"floor"` | ||||
| Signal int64 `json:"signal"` | Signal int64 `json:"signal"` | ||||
| Building string `json:"building"` | Building string `json:"building"` | ||||
| X float32 `json:"x"` | |||||
| Y float32 `json:"y"` | |||||
| Z float32 `json:"z"` | |||||
| } | } | ||||
| @@ -75,7 +75,29 @@ func LocationToBeaconService(msg model.HTTPLocation, db *gorm.DB, writer *kafka. | |||||
| return | return | ||||
| } | } | ||||
| if err := db.Create(&model.Tracks{UUID: msg.ID, Timestamp: time.Now(), Gateway: gw.ID, GatewayMac: gw.MAC, Tracker: msg.ID, Floor: gw.Floor, Building: gw.Building, TrackerMac: tracker.MAC, Signal: msg.RSSI}).Error; err != nil { | |||||
| var floor model.Floor | |||||
| if err := db.Where("id = ?", gw.Floor).First(&floor).Error; err != nil { | |||||
| msg := fmt.Sprintf("Floor not found for ID: %s", gw.Floor) | |||||
| slog.Error(msg) | |||||
| return | |||||
| } | |||||
| fmt.Printf("floor: %d\n", floor.FloorNumber) | |||||
| if err := db.Create(&model.Tracks{ | |||||
| UUID: msg.ID, | |||||
| Timestamp: time.Now(), | |||||
| Gateway: gw.ID, | |||||
| GatewayMac: gw.MAC, | |||||
| Tracker: msg.ID, | |||||
| Floor: gw.Floor, | |||||
| Building: gw.Building, | |||||
| TrackerMac: tracker.MAC, | |||||
| Signal: msg.RSSI, | |||||
| X: gw.X, | |||||
| Y: gw.Y, | |||||
| Z: float32(floor.FloorNumber), | |||||
| }).Error; err != nil { | |||||
| msg := fmt.Sprintf("Error in saving distance for beacon: %v", err) | msg := fmt.Sprintf("Error in saving distance for beacon: %v", err) | ||||
| slog.Error(msg) | slog.Error(msg) | ||||
| return | return | ||||
| @@ -92,6 +114,7 @@ func LocationToBeaconService(msg model.HTTPLocation, db *gorm.DB, writer *kafka. | |||||
| } | } | ||||
| func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafka.Writer, ctx context.Context) { | func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafka.Writer, ctx context.Context) { | ||||
| fmt.Printf("msg: %+v\n", msg) | |||||
| tracker, err := findTracker(msg, db) | tracker, err := findTracker(msg, db) | ||||
| if err != nil { | if err != nil { | ||||
| msg := fmt.Sprintf("Error in finding tracker: %v", err) | msg := fmt.Sprintf("Error in finding tracker: %v", err) | ||||
| @@ -113,7 +136,9 @@ func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafk | |||||
| return | return | ||||
| } | } | ||||
| if err := db.Create(&model.Tracks{UUID: tracker.ID, Timestamp: time.Now(), Gateway: gw.ID, GatewayMac: gw.MAC, Tracker: tracker.ID, Floor: gw.Floor, Building: gw.Building, TrackerMac: tracker.MAC}).Error; err != nil { | |||||
| // fmt.Printf("gw: %+v\n", gw) | |||||
| if err := db.Create(&model.Tracks{UUID: tracker.ID, Timestamp: time.Now(), Gateway: gw.ID, GatewayMac: gw.MAC, Tracker: tracker.ID, Floor: gw.Floor, Building: gw.Building, TrackerMac: tracker.MAC, X: msg.X, Y: msg.Y, Z: msg.Z}).Error; err != nil { | |||||
| msg := fmt.Sprintf("Error in saving distance for beacon: %v", err) | msg := fmt.Sprintf("Error in saving distance for beacon: %v", err) | ||||
| slog.Error(msg) | slog.Error(msg) | ||||
| return | return | ||||
| @@ -31,3 +31,12 @@ echo "===================================" | |||||
| echo "Query Parameters: limit, from (RFC3339), to (RFC3339)" | echo "Query Parameters: limit, from (RFC3339), to (RFC3339)" | ||||
| echo "Get tracker UUIDs from: GET /reslevis/getTrackers" | echo "Get tracker UUIDs from: GET /reslevis/getTrackers" | ||||
| echo "===================================" | echo "===================================" | ||||
| echo "4. Get all latest positions for all trackers:" | |||||
| curl -s -X GET "${BASE_URL}/reslevis/getTracks" | jq '.' | |||||
| echo -e "\n" | |||||
| echo "===================================" | |||||
| echo "Query Parameters: limit, from (RFC3339), to (RFC3339)" | |||||
| echo "Get tracker UUIDs from: GET /reslevis/getTrackers" | |||||
| echo "===================================" | |||||
| @@ -1,20 +1,20 @@ | |||||
| #!/bin/bash | #!/bin/bash | ||||
| # Build the server | # Build the server | ||||
| docker build -t afasystemadmin/ble-ai-localizer:server_v1.1 -f ../../build/package/Dockerfile.server ../../ | |||||
| ¸ | |||||
| docker build -t afasystemadmin/ble-ai-localizer:server_v1.2 -f ../../build/package/Dockerfile.server ../../ | |||||
| # Build the location | # Build the location | ||||
| docker build -t afasystemadmin/ble-ai-localizer:location_v1.1 -f ../../build/package/Dockerfile.location ../../ | |||||
| docker build -t afasystemadmin/ble-ai-localizer:location_v1.2 -f ../../build/package/Dockerfile.location ../../ | |||||
| # Build the decoder | # Build the decoder | ||||
| docker build -t afasystemadmin/ble-ai-localizer:decoder_v1.1 -f ../../build/package/Dockerfile.decoder ../../ | |||||
| docker build -t afasystemadmin/ble-ai-localizer:decoder_v1.2 -f ../../build/package/Dockerfile.decoder ../../ | |||||
| # Build the bridge | # Build the bridge | ||||
| docker build -t afasystemadmin/ble-ai-localizer:bridge_v1.1 -f ../../build/package/Dockerfile.bridge ../../ | |||||
| docker build -t afasystemadmin/ble-ai-localizer:bridge_v1.2 -f ../../build/package/Dockerfile.bridge ../../ | |||||
| docker image ls | docker image ls | ||||
| docker push afasystemadmin/ble-ai-localizer:server_v1.1 | |||||
| docker push afasystemadmin/ble-ai-localizer:location_v1.1 | |||||
| docker push afasystemadmin/ble-ai-localizer:decoder_v1.1 | |||||
| docker push afasystemadmin/ble-ai-localizer:bridge_v1.1 | |||||
| docker push afasystemadmin/ble-ai-localizer:server_v1.2 | |||||
| docker push afasystemadmin/ble-ai-localizer:location_v1.2 | |||||
| docker push afasystemadmin/ble-ai-localizer:decoder_v1.2 | |||||
| docker push afasystemadmin/ble-ai-localizer:bridge_v1.2 | |||||