| /* |
| * |
| * Copyright (c) 2023 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "SensorManagerCommon.h" |
| #include "PWMManager.h" |
| #ifdef CONFIG_CHIP_USE_MARS_SENSOR |
| #include <zephyr/drivers/sensor.h> |
| #endif // CONFIG_CHIP_USE_MARS_SENSOR |
| |
| LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); |
| |
| using namespace chip; |
| using namespace ::chip::DeviceLayer; |
| |
| constexpr float kMinTempDelta = 0.5; // 0.5 degree Celsius |
| |
| #ifdef CONFIG_CHIP_USE_MARS_SENSOR |
| k_timer sSensorBanForNextMeasurTimer; |
| volatile bool mSensorBanForNextMeasurFlag = false; |
| constexpr uint16_t kSensorBanForNextMeasurTimeout = 1000; // 1s timeout |
| |
| const struct device * const sht3xd_dev = DEVICE_DT_GET_ONE(sensirion_sht3xd); |
| |
| #ifdef USE_COLOR_TEMPERATURE_LIGHT |
| |
| #define TEMP_LOW_LIM 0 // °C |
| #define TEMP_HIGH_LIM 40 // °C |
| #endif // USE_COLOR_TEMPERATURE_LIGHT |
| #else |
| constexpr float kSimulatedHum = 55.5; // percents |
| constexpr uint16_t kSimulatedReadingFrequency = 4; // change simulated number |
| static float mSimulatedTemp[] = { 23.01, 24.02, 28.03, 25.50, 22.05, 21.25, 21.07, 26.08, 18.09, 27.11 }; |
| #endif // CONFIG_CHIP_USE_MARS_SENSOR |
| |
| SensorManager SensorManager::sSensorManager; |
| |
| CHIP_ERROR SensorManager::Init() |
| { |
| #ifdef CONFIG_CHIP_USE_MARS_SENSOR |
| if (!device_is_ready(sht3xd_dev)) |
| { |
| LOG_ERR("Device %s is not ready", sht3xd_dev->name); |
| return CHIP_ERROR_INCORRECT_STATE; |
| } |
| |
| #ifdef USE_COLOR_TEMPERATURE_LIGHT |
| RgbColor_t rgb = { 0 }; |
| #endif // USE_COLOR_TEMPERATURE_LIGHT |
| |
| // Initialise the timer to ban sensor measurement |
| k_timer_init(&sSensorBanForNextMeasurTimer, &SensorManager::SensorBanForNextMeasurTimerTimeoutCallback, nullptr); |
| k_timer_user_data_set(&sSensorBanForNextMeasurTimer, this); |
| #endif // CONFIG_CHIP_USE_MARS_SENSOR |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR SensorManager::GetTempAndHumMeasurValue(int16_t * pTempMeasured, uint16_t * pHumMeasured) |
| { |
| static float lastTemp = 0.0; |
| float temp = 0.0; |
| float hum = 0.0; |
| |
| #ifdef CONFIG_CHIP_USE_MARS_SENSOR |
| static struct sensor_value sensorTemp = { 0 }; |
| static struct sensor_value sensorHum = { 0 }; |
| |
| if (!mSensorBanForNextMeasurFlag) |
| { |
| int status = sensor_sample_fetch(sht3xd_dev); |
| if (status) |
| { |
| LOG_ERR("Device %s is not ready to fetch the sensor samples (status: %d)", sht3xd_dev->name, status); |
| return System::MapErrorZephyr(status); |
| } |
| |
| status = sensor_channel_get(sht3xd_dev, SENSOR_CHAN_AMBIENT_TEMP, &sensorTemp); |
| if (status) |
| { |
| LOG_ERR("Device %s is not ready to temperature measurement (status: %d)", sht3xd_dev->name, status); |
| return System::MapErrorZephyr(status); |
| } |
| |
| status = sensor_channel_get(sht3xd_dev, SENSOR_CHAN_HUMIDITY, &sensorHum); |
| if (status) |
| { |
| LOG_ERR("Device %s is not ready to humidity measurement (status: %d)", sht3xd_dev->name, status); |
| return System::MapErrorZephyr(status); |
| } |
| |
| mSensorBanForNextMeasurFlag = true; |
| |
| // Start next timer to measurement the air quality sensor |
| k_timer_start(&sSensorBanForNextMeasurTimer, K_MSEC(kSensorBanForNextMeasurTimeout), K_NO_WAIT); |
| } |
| |
| temp = (float) sensor_value_to_double(&sensorTemp); |
| hum = (float) sensor_value_to_double(&sensorHum); |
| |
| #ifdef USE_COLOR_TEMPERATURE_LIGHT |
| SetColorTemperatureLight(temp); |
| #endif // USE_COLOR_TEMPERATURE_LIGHT |
| #else |
| /* Temperature simulation is used */ |
| static uint8_t nbOfRepetition = 0; |
| static uint8_t simulatedIndex = 0; |
| if (simulatedIndex >= ArraySize(mSimulatedTemp)) |
| { |
| simulatedIndex = 0; |
| } |
| temp = mSimulatedTemp[simulatedIndex]; |
| |
| nbOfRepetition++; |
| |
| if (nbOfRepetition >= kSimulatedReadingFrequency) |
| { |
| simulatedIndex++; |
| nbOfRepetition = 0; |
| } |
| |
| /* Humidity simulation is used */ |
| hum = kSimulatedHum; |
| |
| #endif // CONFIG_CHIP_USE_MARS_SENSOR |
| |
| if ((temp >= (lastTemp + kMinTempDelta)) || temp <= (lastTemp - kMinTempDelta)) |
| { |
| lastTemp = temp; |
| } |
| else |
| { |
| temp = lastTemp; |
| } |
| |
| if (pTempMeasured != NULL) |
| { |
| // Per spec Application Clusters 2.3.4.1. : MeasuredValue = 100 x temperature [°C] |
| *pTempMeasured = (int16_t) 100 * temp; |
| } |
| |
| if (pHumMeasured != NULL) |
| { |
| *pHumMeasured = (uint16_t) hum; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| int16_t SensorManager::GetMinMeasuredTempValue() |
| { |
| return mMinMeasuredTempCelsius; |
| } |
| |
| int16_t SensorManager::GetMaxMeasuredTempValue() |
| { |
| return mMaxMeasuredTempCelsius; |
| } |
| |
| #ifdef CONFIG_CHIP_USE_MARS_SENSOR |
| void SensorManager::SensorBanForNextMeasurTimerTimeoutCallback(k_timer * timer) |
| { |
| if (!timer) |
| { |
| return; |
| } |
| |
| mSensorBanForNextMeasurFlag = false; |
| } |
| |
| #ifdef USE_COLOR_TEMPERATURE_LIGHT |
| void SensorManager::SetColorTemperatureLight(int8_t temp) |
| { |
| RgbColor_t rgb = { 0 }; |
| |
| if (temp >= mMinMeasuredTempCelsius && temp <= TEMP_LOW_LIM) |
| { |
| /* Set Color Temperature Light in range -40...0°C */ |
| rgb.b = RGB_MAX_VALUE * (1 - ((float) temp - TEMP_LOW_LIM) / (mMinMeasuredTempCelsius - TEMP_LOW_LIM)); |
| } |
| else if (temp >= TEMP_HIGH_LIM && temp <= mMaxMeasuredTempCelsius) |
| { |
| /* Set Color Temperature Light in range 40...125°C */ |
| rgb.r = RGB_MAX_VALUE * (1 - ((float) temp - TEMP_HIGH_LIM) / (mMaxMeasuredTempCelsius - TEMP_HIGH_LIM)); |
| } |
| else if (temp > TEMP_LOW_LIM && temp < TEMP_HIGH_LIM) |
| { |
| uint8_t steps_in_part = (TEMP_HIGH_LIM - TEMP_LOW_LIM) / 4; |
| uint8_t step_num = temp % steps_in_part; |
| float step_val = (float) RGB_MAX_VALUE / steps_in_part; |
| |
| if (temp < steps_in_part) |
| { |
| /* Set Color Temperature Light in range 1...9°C */ |
| rgb.b = RGB_MAX_VALUE; |
| rgb.g = step_num * step_val; |
| } |
| else if (temp < 2 * steps_in_part) |
| { |
| /* Set Color Temperature Light in range 10...19°C */ |
| rgb.b = RGB_MAX_VALUE; |
| rgb.g = RGB_MAX_VALUE; |
| rgb.r = step_num * step_val; |
| } |
| else if (temp < 3 * steps_in_part) |
| { |
| /* Set Color Temperature Light in range 20...29°C */ |
| rgb.r = RGB_MAX_VALUE; |
| rgb.g = RGB_MAX_VALUE; |
| rgb.b = RGB_MAX_VALUE - (step_num * step_val); |
| } |
| else |
| { |
| /* Set Color Temperature Light in range 30...39°C */ |
| rgb.r = RGB_MAX_VALUE; |
| rgb.g = RGB_MAX_VALUE - (step_num * step_val); |
| } |
| } |
| else |
| { |
| LOG_ERR("Couldn't set the Color Temperature Light"); |
| } |
| |
| PwmManager::getInstance().setPwm(PwmManager::EAppPwm_Red, ((uint32_t) rgb.r * 1000) / 0xff); |
| PwmManager::getInstance().setPwm(PwmManager::EAppPwm_Green, ((uint32_t) rgb.g * 1000) / 0xff); |
| PwmManager::getInstance().setPwm(PwmManager::EAppPwm_Blue, ((uint32_t) rgb.b * 1000) / 0xff); |
| } |
| #endif // USE_COLOR_TEMPERATURE_LIGHT |
| #endif // CONFIG_CHIP_USE_MARS_SENSOR |