diff options
Diffstat (limited to 'src/hvac-led-helper.cpp')
-rw-r--r-- | src/hvac-led-helper.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/hvac-led-helper.cpp b/src/hvac-led-helper.cpp new file mode 100644 index 0000000..3c86c81 --- /dev/null +++ b/src/hvac-led-helper.cpp @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include "hvac-led-helper.hpp" +#include <iostream> +#include <iomanip> +#include <sstream> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/ini_parser.hpp> + +namespace property_tree = boost::property_tree; + +#define RED "/sys/class/leds/blinkm-3-9-red/brightness" +#define GREEN "/sys/class/leds/blinkm-3-9-green/brightness" +#define BLUE "/sys/class/leds/blinkm-3-9-blue/brightness" + +// RGB temperature mapping +static struct { + const int temperature; + const int rgb[3]; +} degree_colours[] = { + {15, {0, 0, 229} }, + {16, {22, 0, 204} }, + {17, {34, 0, 189} }, + {18, {46, 0, 175} }, + {19, {58, 0, 186} }, + {20, {70, 0, 146} }, + {21, {82, 0, 131} }, + {22, {104, 0, 116} }, + {23, {116, 0, 102} }, + {24, {128, 0, 87} }, + {25, {140, 0, 73} }, + {26, {152, 0, 58} }, + {27, {164, 0, 43} }, + {28, {176, 0, 29} }, + {29, {188, 0, 14} }, + {30, {201, 0, 5} } +}; + + +HvacLedHelper::HvacLedHelper() : + m_temp_left(21), + m_temp_right(21), + m_config_valid(false), + m_verbose(0) +{ + read_config(); +} + +void HvacLedHelper::read_config() +{ + // Using a separate configuration file now, it may make sense + // to revisit this if a workable scheme to handle overriding + // values for the full demo setup can be come up with. + std::string config("/etc/xdg/AGL/agl-service-hvac-leds.conf"); + char *home = getenv("XDG_CONFIG_HOME"); + if (home) { + config = home; + config += "/AGL/agl-service-hvac.conf"; + } + + std::cout << "Using configuration " << config << std::endl; + property_tree::ptree pt; + try { + property_tree::ini_parser::read_ini(config, pt); + } + catch (std::exception &ex) { + // Continue with defaults if file missing/broken + std::cerr << "Could not read " << config << std::endl; + m_config_valid = true; + return; + } + const property_tree::ptree &settings = + pt.get_child("leds", property_tree::ptree()); + + m_led_path_red = settings.get("red", RED); + std::stringstream ss; + ss << m_led_path_red; + ss >> std::quoted(m_led_path_red); + if (m_led_path_red.empty()) { + std::cerr << "Invalid red LED path" << std::endl; + return; + } + // stat file here? + std::cout << "Using red LED path " << m_led_path_red << std::endl; + + m_led_path_green = settings.get("green", GREEN); + std::stringstream().swap(ss); + ss << m_led_path_green; + ss >> std::quoted(m_led_path_green); + if (m_led_path_green.empty()) { + std::cerr << "Invalid green LED path" << std::endl; + return; + } + // stat file here? + std::cout << "Using green LED path " << m_led_path_red << std::endl; + + m_led_path_blue = settings.get("blue", BLUE); + std::stringstream().swap(ss); + ss << m_led_path_blue; + ss >> std::quoted(m_led_path_blue); + if (m_led_path_blue.empty()) { + std::cerr << "Invalid blue LED path" << std::endl; + return; + } + // stat file here? + std::cout << "Using blue LED path " << m_led_path_red << std::endl; + + m_verbose = 0; + std::string verbose = settings.get("verbose", ""); + std::stringstream().swap(ss); + ss << verbose; + ss >> std::quoted(verbose); + if (!verbose.empty()) { + if (verbose == "true" || verbose == "1") + m_verbose = 1; + if (verbose == "2") + m_verbose = 2; + } + + m_config_valid = true; +} + +void HvacLedHelper::set_left_temperature(uint8_t temp) +{ + m_temp_left = temp; + led_update(); +} + +void HvacLedHelper::set_right_temperature(uint8_t temp) +{ + m_temp_right = temp; + led_update(); +} + +void HvacLedHelper::led_update() +{ + if (!m_config_valid) + return; + + // Calculates average colour value taken from the temperature toggles, + // limiting to our 15 degree range + int temp_left = m_temp_left - 15; + if (temp_left < 0) + temp_left = 0; + else if (temp_left > 15) + temp_left = 15; + + int temp_right = m_temp_right - 15; + if (temp_right < 0) + temp_right = 0; + else if (temp_right > 15) + temp_right = 15; + + int red_value = (degree_colours[temp_left].rgb[0] + degree_colours[temp_right].rgb[0]) / 2; + int green_value = (degree_colours[temp_left].rgb[1] + degree_colours[temp_right].rgb[1]) / 2; + int blue_value = (degree_colours[temp_left].rgb[2] + degree_colours[temp_right].rgb[2]) / 2; + + // + // Push colour mapping out + // + + std::ofstream led_red; + led_red.open(m_led_path_red); + if (led_red.is_open()) { + led_red << std::to_string(red_value); + led_red.close(); + } else { + std::cerr << "Could not write red LED path " << m_led_path_red << std::endl; + m_config_valid = false; + return; + } + + std::ofstream led_green; + led_green.open(m_led_path_green); + if (led_green.is_open()) { + led_green << std::to_string(green_value); + led_green.close(); + } else { + std::cerr << "Could not write green LED path " << m_led_path_green << std::endl; + m_config_valid = false; + return; + } + + std::ofstream led_blue; + led_blue.open(m_led_path_blue); + if (led_blue.is_open()) { + led_blue << std::to_string(blue_value); + led_blue.close(); + } else { + std::cerr << "Could not write blue LED path " << m_led_path_blue << std::endl; + m_config_valid = false; + return; + } +} |