diff options
author | 2023-08-24 15:39:24 -0400 | |
---|---|---|
committer | 2023-08-24 15:42:30 -0400 | |
commit | 0a1426d097688912188bcb59ff59d9c596e82b4d (patch) | |
tree | 8032edef0f8a6c3bbebe8f4382486f679bb2143f /src/HvacCanHelper.cpp | |
parent | f0ac80936b73a44131564c4f65ecc0c9a9db7d39 (diff) |
Rework to switch to using KUKSA.val databroker
Rework to use the "VAL" gRPC API from the KUKSA.val databroker
instead of the older server's WebSocket interface. Some source
files have been renamed to match the class naming to provide
a bit more consistency.
Bug-AGL: SPEC-4762
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Change-Id: Ib1ec31af439a9b2d5244e2232ea7be1ed9a2574c
Diffstat (limited to 'src/HvacCanHelper.cpp')
-rw-r--r-- | src/HvacCanHelper.cpp | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/HvacCanHelper.cpp b/src/HvacCanHelper.cpp new file mode 100644 index 0000000..0c0f937 --- /dev/null +++ b/src/HvacCanHelper.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2022,2023 Konsulko Group + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "HvacCanHelper.h" +#include <iostream> +#include <iomanip> +#include <sstream> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/ini_parser.hpp> +#include <boost/property_tree/ini_parser.hpp> + +namespace property_tree = boost::property_tree; + +HvacCanHelper::HvacCanHelper() : + m_temp_left(21), + m_temp_right(21), + m_fan_speed(0), + m_port("can0"), + m_config_valid(false), + m_active(false), + m_verbose(0) +{ + read_config(); + + can_open(); +} + +HvacCanHelper::~HvacCanHelper() +{ + can_close(); +} + +void HvacCanHelper::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-can.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("can", property_tree::ptree()); + + m_port = settings.get("port", "can0"); + std::stringstream ss; + ss << m_port; + ss >> std::quoted(m_port); + if (m_port.empty()) { + std::cerr << "Invalid CAN port path" << std::endl; + return; + } + + 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 HvacCanHelper::can_open() +{ + if (!m_config_valid) + return; + + if (m_verbose > 1) + std::cout << "HvacCanHelper::HvacCanHelper: using port " << m_port << std::endl; + + // Open raw CAN socket + m_can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (m_can_socket < 0) { + return; + } + + // Look up port address + struct ifreq ifr; + strcpy(ifr.ifr_name, m_port.c_str()); + if (ioctl(m_can_socket, SIOCGIFINDEX, &ifr) < 0) { + close(m_can_socket); + return; + } + + m_can_addr.can_family = AF_CAN; + m_can_addr.can_ifindex = ifr.ifr_ifindex; + if (bind(m_can_socket, (struct sockaddr*) &m_can_addr, sizeof(m_can_addr)) < 0) { + close(m_can_socket); + return; + } + + m_active = true; + if (m_verbose > 1) + std::cout << "HvacCanHelper::HvacCanHelper: opened " << m_port << std::endl; +} + +void HvacCanHelper::can_close() +{ + if (m_active) + close(m_can_socket); +} + +void HvacCanHelper::set_left_temperature(uint8_t temp) +{ + m_temp_left = temp; + can_update(); +} + +void HvacCanHelper::set_right_temperature(uint8_t temp) +{ + m_temp_right = temp; + can_update(); +} + +void HvacCanHelper::set_fan_speed(uint8_t speed) +{ + // Scale incoming 0-100 VSS signal to 0-255 to match hardware expectations + double value = speed * 255.0 / 100.0; + m_fan_speed = (uint8_t) (value + 0.5); + can_update(); +} + +void HvacCanHelper::can_update() +{ + if (!m_active) + return; + + struct can_frame frame; + frame.can_id = 0x30; + frame.can_dlc = 8; + frame.data[0] = convert_temp(m_temp_left); + frame.data[1] = convert_temp(m_temp_right); + frame.data[2] = convert_temp((uint8_t) (((int) m_temp_left + (int) m_temp_right) >> 1)); + frame.data[3] = 0xF0; + frame.data[4] = m_fan_speed; + frame.data[5] = 1; + frame.data[6] = 0; + frame.data[7] = 0; + + auto written = sendto(m_can_socket, + &frame, + sizeof(struct can_frame), + 0, + (struct sockaddr*) &m_can_addr, + sizeof(m_can_addr)); + if (written < 0) { + std::cerr << "Write to " << m_port << " failed!" << std::endl; + close(m_can_socket); + m_active = false; + } +} + + |