diff --git a/internal/domains/sensors/handlers.go b/internal/domains/sensors/handlers.go index 98313db..77cea5c 100644 --- a/internal/domains/sensors/handlers.go +++ b/internal/domains/sensors/handlers.go @@ -21,12 +21,26 @@ const ( type Handlers struct { service *Service *iot.IoTDevice + simulator *Simulator } func NewHandlers(service *Service, iot *iot.IoTDevice) *Handlers { + + simulator := Start(iot.NATS) + activeSensors, err := service.repo.ReadAllSensors() + if err != nil { + slog.Error("reading all sensors", "error", err) + } + + for _, sensor := range activeSensors { + go simulator.SimulateSensor(sensor) + slog.Info("started simulator for sensor", "sensor_id", sensor.SensorID) + } + return &Handlers{ service: service, IoTDevice: iot, + simulator: simulator, } } @@ -85,6 +99,8 @@ func (h *Handlers) register() { return Sensor{}, err } + go h.simulator.SimulateSensor(req) + return req, nil }) }) diff --git a/internal/domains/sensors/simulator.go b/internal/domains/sensors/simulator.go index 76dbfc2..901dd53 100644 --- a/internal/domains/sensors/simulator.go +++ b/internal/domains/sensors/simulator.go @@ -1,3 +1,80 @@ package sensors -type Simulator struct{} +import ( + "encoding/json" + "log/slog" + "math/rand" + "nats-app/internal/broker" + "time" +) + +type Simulator struct { + *broker.NATS +} + +func Start(nats *broker.NATS) *Simulator { + return &Simulator{ + NATS: nats, + } +} + +func (s *Simulator) SimulateSensor(sensor Sensor) { + ticker := time.NewTicker(*sensor.SamplingInterval * time.Second) + defer ticker.Stop() + + for range ticker.C { + data := s.generateData(sensor) + + if data.SensorID == "" { + slog.Warn("sensor data generation failed", "sensor_id", sensor.SensorID) + continue + } + + payload, err := json.Marshal(data) + if err != nil { + slog.Error("failed to marshal sensor data", "error", err, "sensor_id", sensor.SensorID) + continue + } + + subject := subjectSensorsData + sensor.SensorID + if err := s.Publish(subject, payload); err != nil { + slog.Error("failed to publish sensor data", "error", err, "subject", subject) + } else { + slog.Debug("sensor data published", "sensor_id", sensor.SensorID, "value", data.Value) + } + } + +} + +func (s *Simulator) generateData(sensor Sensor) SensorData { + now := time.Now() + data := SensorData{ + SensorID: sensor.SensorID, + Timestamp: &now, + } + + if rand.Float64() < 0.05 { + return SensorData{} + } + + var value float64 + switch sensor.SensorType { + case Temperature: + value = -20 + rand.Float64()*100 + case Humidity: + value = 10 + rand.Float64()*90 + case CarbonDioxide: + value = 980 + rand.Float64()*60 + case Pressure: + value = 950 + rand.Float64()*100 + case Proximity: + value = rand.Float64() * 400 + case Light: + value = rand.Float64() * 10000 + default: + value = rand.Float64() * 100 + } + data.Value = &value + + return data +}