package sensor import ( "context" "fmt" "sync" "github.com/go-flucky/flucky/pkg/internal/collect" "github.com/go-flucky/flucky/pkg/internal/prittyprint" "github.com/go-flucky/flucky/pkg/types" ) // ReadHumidities returns a list of measured humidities by humidity sensors func ReadHumidities(humiditySensors []HumiditySensor, round float64) ([]*types.Humidity, error) { humidityChannel := make(chan *types.Humidity, len(humiditySensors)) errorChannel := make(chan error, len(humiditySensors)) wg := new(sync.WaitGroup) wg.Add(len(humiditySensors)) for _, humiditySensor := range humiditySensors { go humiditySensor.ReadHumidityWriteIntoChannel(round, humidityChannel, errorChannel, wg) } wg.Wait() errors := collect.Errors(errorChannel) if len(errors) > 0 { return nil, prittyprint.FormatErrors(errors) } humidities := collect.Humidities(humidityChannel) return humidities, nil } // ReadHumiditiesWriteIntoChannel reads the humidity values of humidity sensors and writes them into a channel func ReadHumiditiesWriteIntoChannel(ctx context.Context, humiditySensors []HumiditySensor, round float64, humidityChannel chan<- *types.Humidity, errorChannel chan<- error, wg *sync.WaitGroup) { for _, humiditySensor := range humiditySensors { humiditySensor.ReadHumidityWriteIntoChannel(round, humidityChannel, errorChannel, wg) } } // ReadHumiditiesContinuously reads the humidity values of humidity sensors continuously and writes them into a channel func ReadHumiditiesContinuously(ctx context.Context, humiditySensors []HumiditySensor, round float64, humidityChannel chan<- *types.Humidity, errorChannel chan<- error) { for { select { case <-ctx.Done(): errorChannel <- fmt.Errorf("Context closed: %v", ctx.Err()) return default: ReadHumiditiesWriteIntoChannel(ctx, humiditySensors, round, humidityChannel, errorChannel, nil) } } } // ReadTemperatures returns a list of measured temperatures by temperature sensors func ReadTemperatures(temperatureSensors []TemperatureSensor, degree types.Degree, round float64) ([]*types.Temperature, error) { temperatureChannel := make(chan *types.Temperature, len(temperatureSensors)) errorChannel := make(chan error, len(temperatureSensors)) wg := new(sync.WaitGroup) wg.Add(len(temperatureSensors)) for _, temperatureSensor := range temperatureSensors { go temperatureSensor.ReadTemperatureWriteIntoChannel(degree, round, temperatureChannel, errorChannel, wg) } wg.Wait() errors := collect.Errors(errorChannel) if len(errors) > 0 { return nil, prittyprint.FormatErrors(errors) } temperatures := collect.Temperatures(temperatureChannel) return temperatures, nil } // ReadTemperaturesWriteIntoChannel reads the temperature values of temperature sensors and writes them into a channel func ReadTemperaturesWriteIntoChannel(ctx context.Context, temperatureSensors []TemperatureSensor, degree types.Degree, round float64, temperatureChannel chan<- *types.Temperature, errorChannel chan<- error, wg *sync.WaitGroup) { for _, temperatureSensor := range temperatureSensors { temperatureSensor.ReadTemperatureWriteIntoChannel(degree, round, temperatureChannel, errorChannel, wg) } } // ReadTemperaturesContinuously reads the temperature values of temperature sensors continuously and writes them into a chann func ReadTemperaturesContinuously(ctx context.Context, temperatureSensors []TemperatureSensor, degree types.Degree, round float64, temperatureChannel chan<- *types.Temperature, errorChannel chan<- error) { for { select { case <-ctx.Done(): errorChannel <- fmt.Errorf("Context closed: %v", ctx.Err()) return default: ReadTemperaturesWriteIntoChannel(ctx, temperatureSensors, degree, round, temperatureChannel, errorChannel, nil) } } } func convertTemperatureMeasurementUnit(value float64, fromDegree types.Degree, toDegree types.Degree) float64 { switch fromDegree { // Celsius case types.DegreeCelsius: switch toDegree { // Celsius -> Celsius case types.DegreeCelsius: return value // Celsius -> Fahrenheit case types.DegreeFahrenheit: return (value * 9 / 5) + 32 // Celsius -> Kelvin case types.DegreeKelvin: return value + 273.15 } // Fahrenheit case types.DegreeFahrenheit: switch toDegree { // Fahrenheit -> Celsius case types.DegreeCelsius: return (value - 32) * 5 / 9 // Fahrenheit -> Fahrenheit case types.DegreeFahrenheit: return value // Fahrenheit -> Kelvin case types.DegreeKelvin: return (value-32)*5/9 + 273.15 } case types.DegreeKelvin: switch toDegree { // Kelvin -> Celsius case types.DegreeCelsius: return value - 273.15 // Kelvin -> Fahrenheit case types.DegreeFahrenheit: return (value-273.15)*9/5 + 32 // Kevin -> Kelvin case types.DegreeKelvin: return value } } return value } func SelectTemperatureMeasurementUnit(unit string) (types.Degree, error) { switch unit { case "celsius": return types.DegreeCelsius, nil case "fahrenheit": return types.DegreeFahrenheit, nil case "kelvin": return types.DegreeKelvin, nil default: return "", fmt.Errorf("Can not determine temperature measurement unit") } }