From 096908375ecbfc6388d0aec69a35b2a8ffc53d47 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 16 Jun 2022 00:28:36 -0400 Subject: Repurpose into VIS client Repurpose repository for a spiritual successor of the previous binding. The replacement is a daemon that demonstrates servicing HVAC actuators from the VSS schema via VIS signals from KUKSA.val. Currently the connection to KUKSA.val is websocket based using the boost::asio framework, but the plan is to migrate to grpc as that becomes more robust in KUKSA.val. Notable changes: - New code is completely C++, partly to leverage using Boost, but also to futureproof future work with grpc. - Switch from CMake to meson for ease of development and some degree of futureproofing. - Use with systemd is assumed; behavior follows the systemd daemon guidelines barring the use of journald logging prefixes, which may be addressed with future work. A systemd unit is also installed as part of the build. - SPDX license headers using SPDX "short identifiers" are used in source files rather than the full copyright headers used in the previous codebase. This follows the direction that projects such as the Linux kernel are going in. - The JSON configuration file for the LED control files for the demo platform has been migrated to a INI format configuration file matching what has been done for the VIS client configuration in other recent work. Bug-AGL: SPEC-4409 Signed-off-by: Scott Murray Change-Id: Ic2061bca9670b1e461d6f1e6591471e257fff5b9 --- src/hvac-led-helper.cpp | 194 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 src/hvac-led-helper.cpp (limited to 'src/hvac-led-helper.cpp') 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 +#include +#include +#include +#include + +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; + } +} -- cgit 1.2.3-korg