temperature_sensor.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package devices
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math/rand"
  6. "time"
  7. "iot-base-station/pkg/mqtt"
  8. )
  9. // TemperatureSensor 温度传感器模拟器
  10. type TemperatureSensor struct {
  11. ID string
  12. Name string
  13. Location string
  14. MinTemp float64
  15. MaxTemp float64
  16. Interval time.Duration
  17. client mqtt.Client
  18. topic string
  19. running bool
  20. stopChan chan bool
  21. }
  22. // TemperatureData 温度数据
  23. type TemperatureData struct {
  24. DeviceID string `json:"device_id"`
  25. Temperature float64 `json:"temperature"`
  26. Humidity float64 `json:"humidity"`
  27. Timestamp time.Time `json:"timestamp"`
  28. Location string `json:"location"`
  29. Status string `json:"status"`
  30. }
  31. // NewTemperatureSensor 创建温度传感器模拟器
  32. func NewTemperatureSensor(id, name, location string, minTemp, maxTemp float64, interval time.Duration) *TemperatureSensor {
  33. return &TemperatureSensor{
  34. ID: id,
  35. Name: name,
  36. Location: location,
  37. MinTemp: minTemp,
  38. MaxTemp: maxTemp,
  39. Interval: interval,
  40. topic: fmt.Sprintf("iot/data/%s/temperature", id),
  41. stopChan: make(chan bool),
  42. }
  43. }
  44. // Connect 连接到MQTT代理
  45. func (s *TemperatureSensor) Connect(broker string) error {
  46. // 创建MQTT客户端
  47. opts := mqtt.NewClientOptions()
  48. opts.AddBroker(broker)
  49. opts.SetClientID(s.ID)
  50. opts.SetCleanSession(true)
  51. // 连接MQTT代理
  52. client := mqtt.NewClient(opts)
  53. if token := client.Connect(); token.Wait() && token.Error() != nil {
  54. return fmt.Errorf("failed to connect to MQTT broker: %w", token.Error())
  55. }
  56. s.client = client
  57. return nil
  58. }
  59. // Start 启动传感器
  60. func (s *TemperatureSensor) Start() {
  61. if s.running {
  62. return
  63. }
  64. s.running = true
  65. go s.run()
  66. }
  67. // Stop 停止传感器
  68. func (s *TemperatureSensor) Stop() {
  69. if !s.running {
  70. return
  71. }
  72. s.running = false
  73. s.stopChan <- true
  74. }
  75. // run 运行传感器
  76. func (s *TemperatureSensor) run() {
  77. ticker := time.NewTicker(s.Interval)
  78. defer ticker.Stop()
  79. // 发送初始状态
  80. s.sendStatus("online")
  81. for {
  82. select {
  83. case <-ticker.C:
  84. // 生成随机温度数据
  85. temp := s.MinTemp + rand.Float64()*(s.MaxTemp-s.MinTemp)
  86. humidity := 30.0 + rand.Float64()*40.0 // 30-70%湿度
  87. // 创建温度数据
  88. data := TemperatureData{
  89. DeviceID: s.ID,
  90. Temperature: temp,
  91. Humidity: humidity,
  92. Timestamp: time.Now(),
  93. Location: s.Location,
  94. Status: "normal",
  95. }
  96. // 检查温度是否异常
  97. if temp > s.MaxTemp*0.9 || temp < s.MinTemp*1.1 {
  98. data.Status = "warning"
  99. s.sendAlert(fmt.Sprintf("温度异常: %.2f°C", temp))
  100. }
  101. // 发送数据
  102. s.sendData(data)
  103. case <-s.stopChan:
  104. // 发送离线状态
  105. s.sendStatus("offline")
  106. return
  107. }
  108. }
  109. }
  110. // sendData 发送数据
  111. func (s *TemperatureSensor) sendData(data TemperatureData) {
  112. if s.client == nil {
  113. return
  114. }
  115. payload, err := json.Marshal(data)
  116. if err != nil {
  117. fmt.Printf("Failed to marshal temperature data: %v\n", err)
  118. return
  119. }
  120. if err := s.client.Publish(s.topic, 1, false, payload); err != nil {
  121. fmt.Printf("Failed to publish temperature data: %v\n", err)
  122. return
  123. }
  124. fmt.Printf("Sent temperature data from %s: %.2f°C\n", s.ID, data.Temperature)
  125. }
  126. // sendStatus 发送状态
  127. func (s *TemperatureSensor) sendStatus(status string) {
  128. if s.client == nil {
  129. return
  130. }
  131. topic := fmt.Sprintf("iot/status/%s", s.ID)
  132. payload := map[string]interface{}{
  133. "status": status,
  134. "timestamp": time.Now(),
  135. }
  136. data, err := json.Marshal(payload)
  137. if err != nil {
  138. fmt.Printf("Failed to marshal status data: %v\n", err)
  139. return
  140. }
  141. if err := s.client.Publish(topic, 1, true, data); err != nil {
  142. fmt.Printf("Failed to publish status data: %v\n", err)
  143. return
  144. }
  145. fmt.Printf("Sent status from %s: %s\n", s.ID, status)
  146. }
  147. // sendAlert 发送告警
  148. func (s *TemperatureSensor) sendAlert(message string) {
  149. if s.client == nil {
  150. return
  151. }
  152. topic := fmt.Sprintf("iot/event/%s", s.ID)
  153. payload := map[string]interface{}{
  154. "type": "alert",
  155. "severity": "warning",
  156. "message": message,
  157. "timestamp": time.Now(),
  158. }
  159. data, err := json.Marshal(payload)
  160. if err != nil {
  161. fmt.Printf("Failed to marshal alert data: %v\n", err)
  162. return
  163. }
  164. if err := s.client.Publish(topic, 1, false, data); err != nil {
  165. fmt.Printf("Failed to publish alert data: %v\n", err)
  166. return
  167. }
  168. fmt.Printf("Sent alert from %s: %s\n", s.ID, message)
  169. }
  170. // Disconnect 断开连接
  171. func (s *TemperatureSensor) Disconnect() {
  172. if s.client != nil {
  173. s.client.Disconnect(250)
  174. }
  175. }