You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

105 lines
2.5 KiB

  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "log/slog"
  7. "slices"
  8. "strings"
  9. "time"
  10. "github.com/AFASystems/presence/internal/pkg/model"
  11. "github.com/segmentio/kafka-go"
  12. "gorm.io/gorm"
  13. )
  14. // KafkaWriter defines the interface for writing Kafka messages (allows mocking in tests)
  15. type KafkaWriter interface {
  16. WriteMessages(ctx context.Context, msgs ...kafka.Message) error
  17. }
  18. func LocationToBeaconService(msg model.HTTPLocation, db *gorm.DB, writer KafkaWriter, ctx context.Context) {
  19. if msg.ID == "" {
  20. msg := "empty ID"
  21. slog.Error(msg)
  22. return
  23. }
  24. var zones []model.TrackerZones
  25. if err := db.Select("zoneList").Where("tracker = ?", msg.ID).Find(&zones).Error; err != nil {
  26. msg := fmt.Sprintf("Error in selecting zones: %v", err)
  27. slog.Error(msg)
  28. return
  29. }
  30. var tracker model.Tracker
  31. if err := db.Where("id = ?", msg.ID).Find(&tracker).Error; err != nil {
  32. msg := fmt.Sprintf("Error in selecting tracker: %v", err)
  33. slog.Error(msg)
  34. return
  35. }
  36. var allowedZones []string
  37. for _, z := range zones {
  38. allowedZones = append(allowedZones, z.ZoneList...)
  39. }
  40. var gw model.Gateway
  41. mac := formatMac(msg.Location)
  42. if err := db.Select("id").Where("mac = ?", mac).First(&gw).Error; err != nil {
  43. msg := fmt.Sprintf("Gateway not found for MAC: %s", mac)
  44. slog.Error(msg)
  45. return
  46. }
  47. if len(allowedZones) != 0 && !slices.Contains(allowedZones, gw.ID) {
  48. alert := model.Alert{
  49. ID: msg.ID,
  50. Type: "Restricted zone",
  51. Value: gw.ID,
  52. }
  53. eMsg, err := json.Marshal(alert)
  54. if err != nil {
  55. msg := "Error in marshaling"
  56. slog.Error(msg)
  57. return
  58. } else {
  59. msg := kafka.Message{
  60. Value: eMsg,
  61. }
  62. writer.WriteMessages(ctx, msg)
  63. return
  64. }
  65. }
  66. // status, subject, subject name?
  67. 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 {
  68. msg := fmt.Sprintf("Error in saving distance for beacon: %v", err)
  69. slog.Error(msg)
  70. return
  71. }
  72. if err := db.Updates(&model.Tracker{ID: msg.ID, Location: gw.ID, Distance: msg.Distance, X: gw.X, Y: gw.Y}).Error; err != nil {
  73. msg := fmt.Sprintf("Error in saving distance for beacon: %v", err)
  74. slog.Error(msg)
  75. return
  76. }
  77. }
  78. func formatMac(MAC string) string {
  79. var res strings.Builder
  80. for i := 0; i < len(MAC); i += 2 {
  81. if i > 0 {
  82. res.WriteByte(':')
  83. }
  84. end := min(i+2, len(MAC))
  85. res.WriteString(MAC[i:end])
  86. }
  87. return res.String()
  88. }