Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

202 lignes
4.7 KiB

  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/AFASystems/presence/internal/pkg/model"
  9. "github.com/AFASystems/presence/internal/pkg/mqttclient"
  10. "github.com/redis/go-redis/v9"
  11. "github.com/segmentio/kafka-go"
  12. )
  13. func main() {
  14. // Load global context to init beacons and latest list
  15. appCtx := model.AppContext{
  16. Beacons: model.BeaconsList{
  17. Beacons: make(map[string]model.Beacon),
  18. },
  19. LatestList: model.LatestBeaconsList{
  20. LatestList: make(map[string]model.Beacon),
  21. },
  22. }
  23. // Kafka writer idk why yet
  24. writer := kafkaWriter("127.0.0.1:9092", "beacons")
  25. // Kafka reader for Raw MQTT beacons
  26. rawReader := kafkaReader("127.0.0.1:9092", "rawbeacons", "someID")
  27. defer rawReader.Close()
  28. // Kafka reader for API server updates
  29. apiReader := kafkaReader("127.0.0.1:9092", "apibeacons", "someID")
  30. defer apiReader.Close()
  31. // Kafka reader for latest list updates
  32. latestReader := kafkaReader("127.0.0.1:9092", "latestbeacons", "someID")
  33. defer latestReader.Close()
  34. defer writer.Close()
  35. ctx := context.Background()
  36. // Init Redis Client
  37. client := redis.NewClient(&redis.Options{
  38. Addr: "127.0.0.1:6379",
  39. Password: "",
  40. })
  41. // Initialize list values from Redis
  42. beaconsList, err := client.Get(ctx, "beaconsList").Result()
  43. if err == redis.Nil {
  44. fmt.Println("no beacons list, starting empty")
  45. } else if err != nil {
  46. panic(err)
  47. } else {
  48. json.Unmarshal([]byte(beaconsList), &appCtx.Beacons.Beacons)
  49. }
  50. // Initialize list values from Redis
  51. latestList, err := client.Get(ctx, "latestList").Result()
  52. if err == redis.Nil {
  53. fmt.Println("no latest list, starting empty")
  54. } else if err != nil {
  55. panic(err)
  56. } else {
  57. json.Unmarshal([]byte(latestList), &appCtx.LatestList.LatestList)
  58. }
  59. // declare channel for collecting Kafka messages
  60. chRaw := make(chan model.Incoming_json, 2000)
  61. chApi := make(chan model.ApiUpdate, 2000)
  62. chLatest := make(chan model.Incoming_json, 2000)
  63. go consume(rawReader, chRaw)
  64. go consume(apiReader, chApi)
  65. go consume(latestReader, chLatest)
  66. go func() {
  67. ticker := time.NewTicker(1 * time.Second)
  68. defer ticker.Stop()
  69. for range ticker.C {
  70. appCtx.Beacons.Lock.Lock()
  71. data, _ := json.Marshal(appCtx.Beacons.Beacons)
  72. appCtx.Beacons.Lock.Unlock()
  73. err := client.Set(ctx, "beaconsList", data, 0).Err()
  74. if err != nil {
  75. fmt.Println("error saving to redis:", err)
  76. }
  77. appCtx.LatestList.Lock.Lock()
  78. ldata, _ := json.Marshal(appCtx.LatestList.LatestList)
  79. appCtx.LatestList.Lock.Unlock()
  80. err = client.Set(ctx, "latestList", ldata, 0).Err()
  81. if err != nil {
  82. fmt.Println("error saving latest list:", err)
  83. }
  84. }
  85. }()
  86. for {
  87. select {
  88. case msg := <-chRaw:
  89. processIncoming(msg, &appCtx)
  90. case msg := <-chApi:
  91. switch msg.Method {
  92. case "POST":
  93. fmt.Println("method POST")
  94. appCtx.Beacons.Lock.Lock()
  95. appCtx.Beacons.Beacons[msg.Beacon.Beacon_id] = msg.Beacon
  96. case "DELETE":
  97. _, exists := appCtx.Beacons.Beacons[msg.ID]
  98. if exists {
  99. appCtx.Beacons.Lock.Lock()
  100. delete(appCtx.Beacons.Beacons, msg.ID)
  101. }
  102. fmt.Println("method DELETE")
  103. default:
  104. fmt.Println("unknown method: ", msg.Method)
  105. }
  106. appCtx.Beacons.Lock.Unlock()
  107. case msg := <-chLatest:
  108. fmt.Println("latest msg: ", msg)
  109. }
  110. }
  111. }
  112. func kafkaWriter(kafkaURL, topic string) *kafka.Writer {
  113. return &kafka.Writer{
  114. Addr: kafka.TCP(kafkaURL),
  115. Topic: topic,
  116. Balancer: &kafka.LeastBytes{},
  117. BatchSize: 100,
  118. BatchTimeout: 10 * time.Millisecond,
  119. }
  120. }
  121. func kafkaReader(kafkaURL, topic, groupID string) *kafka.Reader {
  122. brokers := strings.Split(kafkaURL, ",")
  123. return kafka.NewReader(kafka.ReaderConfig{
  124. Brokers: brokers,
  125. GroupID: groupID,
  126. Topic: topic,
  127. MinBytes: 1,
  128. MaxBytes: 10e6,
  129. })
  130. }
  131. func consume[T any](r *kafka.Reader, ch chan<- T) {
  132. for {
  133. msg, err := r.ReadMessage(context.Background())
  134. if err != nil {
  135. fmt.Println("error reading message:", err)
  136. continue
  137. }
  138. var data T
  139. if err := json.Unmarshal(msg.Value, &data); err != nil {
  140. fmt.Println("error decoding:", err)
  141. continue
  142. }
  143. ch <- data
  144. }
  145. }
  146. func processIncoming(incoming model.Incoming_json, ctx *model.AppContext) {
  147. defer func() {
  148. if err := recover(); err != nil {
  149. fmt.Println("work failed:", err)
  150. }
  151. }()
  152. incoming = mqttclient.IncomingBeaconFilter(incoming)
  153. id := mqttclient.GetBeaconID(incoming)
  154. now := time.Now().Unix()
  155. beacons := &ctx.Beacons
  156. beacons.Lock.Lock()
  157. defer beacons.Lock.Unlock()
  158. latestList := &ctx.LatestList
  159. latestList.Lock.Lock()
  160. defer latestList.Lock.Unlock()
  161. beacon, exists := beacons.Beacons[id]
  162. if !exists {
  163. fmt.Println("beacon does not yet exist")
  164. fmt.Println("time now: ", now)
  165. return
  166. }
  167. fmt.Println("Beacon does exist: ", beacon)
  168. }