Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

180 righe
4.7 KiB

  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "log/slog"
  8. "slices"
  9. "strings"
  10. "time"
  11. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  12. "github.com/AFASystems/presence/internal/pkg/model"
  13. "github.com/google/uuid"
  14. "github.com/segmentio/kafka-go"
  15. "gorm.io/gorm"
  16. )
  17. func findTracker(msg model.HTTPLocation, db *gorm.DB) (model.Tracker, error) {
  18. fmt.Printf("Finding tracker for MAC: %s, ID: %s\n", msg.MAC, msg.ID)
  19. var tracker model.Tracker
  20. if msg.MAC != "" {
  21. if err := db.Where("mac = ?", strings.ToUpper(strings.ReplaceAll(msg.MAC, ":", ""))).Find(&tracker).Error; err != nil {
  22. return model.Tracker{}, err
  23. }
  24. return tracker, nil
  25. }
  26. if msg.ID != "" {
  27. if err := db.Where("id = ?", msg.ID).Find(&tracker).Error; err != nil {
  28. return model.Tracker{}, err
  29. }
  30. return tracker, nil
  31. }
  32. return model.Tracker{}, errors.New("both ID and MAC are not provided")
  33. }
  34. func findZones(trackerID string, db *gorm.DB) ([]string, error) {
  35. var zones []model.TrackerZones
  36. if err := db.Select("zoneList").Where("tracker = ?", trackerID).Find(&zones).Error; err != nil {
  37. return nil, err
  38. }
  39. var allowedZones []string
  40. for _, z := range zones {
  41. allowedZones = append(allowedZones, z.ZoneList...)
  42. }
  43. return allowedZones, nil
  44. }
  45. func LocationToBeaconService(msg model.HTTPLocation, db *gorm.DB, writer *kafka.Writer, ctx context.Context) {
  46. tracker, err := findTracker(msg, db)
  47. if err != nil {
  48. msg := fmt.Sprintf("Error in finding tracker: %v", err)
  49. slog.Error(msg)
  50. return
  51. }
  52. allowedZones, err := findZones(tracker.ID, db)
  53. if err != nil {
  54. msg := fmt.Sprintf("Error in finding zones: %v", err)
  55. slog.Error(msg)
  56. return
  57. }
  58. var gw model.Gateway
  59. mac := formatMac(msg.Location)
  60. if err := db.Select("*").Where("mac = ?", mac).First(&gw).Error; err != nil {
  61. msg := fmt.Sprintf("Gateway not found for MAC: %s", mac)
  62. slog.Error(msg)
  63. return
  64. }
  65. 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 {
  66. msg := fmt.Sprintf("Error in saving distance for beacon: %v", err)
  67. slog.Error(msg)
  68. return
  69. }
  70. err = db.Where("id = ?", msg.ID).Updates(model.Tracker{Position: gw.ID, X: gw.X, Y: gw.Y}).Error
  71. if err != nil {
  72. msg := fmt.Sprintf("Error in updating tracker: %v", err)
  73. slog.Error(msg)
  74. return
  75. }
  76. sendAlert(gw.ID, msg.ID, writer, ctx, allowedZones, db)
  77. }
  78. func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafka.Writer, ctx context.Context) {
  79. tracker, err := findTracker(msg, db)
  80. if err != nil {
  81. msg := fmt.Sprintf("Error in finding tracker: %v", err)
  82. slog.Error(msg)
  83. return
  84. }
  85. allowedZones, err := findZones(tracker.ID, db)
  86. if err != nil {
  87. msg := fmt.Sprintf("Error in finding zones: %v", err)
  88. slog.Error(msg)
  89. return
  90. }
  91. var gw model.Gateway
  92. if err := db.Order(fmt.Sprintf("POW(x - %f, 2) + POW(y - %f, 2)", msg.X, msg.Y)).First(&gw).Error; err != nil {
  93. msg := fmt.Sprintf("Error in finding gateway: %v", err)
  94. slog.Error(msg)
  95. return
  96. }
  97. 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 {
  98. msg := fmt.Sprintf("Error in saving distance for beacon: %v", err)
  99. slog.Error(msg)
  100. return
  101. }
  102. err = db.Where("id = ?", tracker.ID).Updates(model.Tracker{Position: gw.ID, X: msg.X, Y: msg.Y}).Error
  103. if err != nil {
  104. msg := fmt.Sprintf("Error in updating tracker: %v", err)
  105. slog.Error(msg)
  106. return
  107. }
  108. sendAlert(gw.ID, tracker.ID, writer, ctx, allowedZones, db)
  109. }
  110. func sendAlert(gwId, trackerId string, writer *kafka.Writer, ctx context.Context, allowedZones []string, db *gorm.DB) {
  111. if len(allowedZones) != 0 && !slices.Contains(allowedZones, gwId) {
  112. alert := model.Alert{
  113. ID: uuid.New().String(),
  114. TrackerID: trackerId,
  115. Type: "Restricted zone",
  116. Value: gwId,
  117. }
  118. if err := InsertAlert(alert, db, ctx); err != nil {
  119. msg := fmt.Sprintf("Error in inserting alert: %v", err)
  120. slog.Error(msg)
  121. return
  122. }
  123. eMsg, err := json.Marshal(alert)
  124. if err != nil {
  125. msg := "Error in marshaling"
  126. slog.Error(msg)
  127. return
  128. } else {
  129. msg := kafka.Message{
  130. Value: eMsg,
  131. }
  132. if err := kafkaclient.Write(ctx, writer, msg); err != nil {
  133. msg := fmt.Sprintf("Error in writing message: %v", err)
  134. slog.Error(msg)
  135. return
  136. }
  137. }
  138. }
  139. }
  140. func formatMac(MAC string) string {
  141. var res strings.Builder
  142. for i := 0; i < len(MAC); i += 2 {
  143. if i > 0 {
  144. res.WriteByte(':')
  145. }
  146. end := min(i+2, len(MAC))
  147. res.WriteString(MAC[i:end])
  148. }
  149. return res.String()
  150. }