-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathhomey_button.cpp
More file actions
123 lines (107 loc) · 4.51 KB
/
homey_button.cpp
File metadata and controls
123 lines (107 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "homey_button.hpp"
#include "database_manager/database_manager.hpp"
#include "entity/entity.hpp"
#include "web_helper/WebHelper.hpp"
#include "mqtt_manager/mqtt_manager.hpp"
#include "mqtt_manager_config/mqtt_manager_config.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/bind.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <chrono>
#include <cstdint>
#include <homey_manager/homey_manager.hpp>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <string>
#include <switch/switch.hpp>
HomeyButton::HomeyButton(uint32_t button_id) : ButtonEntity(button_id)
{
if (this->_controller != MQTT_MANAGER_ENTITY_CONTROLLER::HOMEY)
{
SPDLOG_ERROR("HomeyButton has not been recognized as controlled by HOMEY. Will stop processing button.");
return;
}
nlohmann::json entity_data;
try
{
auto button_entity = database_manager::database.get<database_manager::Entity>(this->_id);
entity_data = button_entity.get_entity_data_json();
}
catch (const std::exception &e)
{
SPDLOG_ERROR("Failed to load button {}: {}", this->_id, e.what());
return;
}
if (entity_data.contains("homey_device_id"))
{
this->_homey_device_id = entity_data["homey_device_id"];
}
else
{
SPDLOG_ERROR("No homey_device_id defined for Button {}::{}", this->_id, this->_name);
return;
}
SPDLOG_DEBUG("Loaded Homey button {}::{}, device ID: {}", this->_id, this->_name, this->_homey_device_id);
HomeyManager::attach_event_observer(this->_homey_device_id, boost::bind(&HomeyButton::homey_event_callback, this, _1));
}
HomeyButton::~HomeyButton()
{
HomeyManager::detach_event_observer(this->_homey_device_id, boost::bind(&HomeyButton::homey_event_callback, this, _1));
}
void HomeyButton::send_state_update_to_controller()
{
SPDLOG_DEBUG("Homey button {}::{} send_state_update_to_controller (trigger button press). State: {}", this->_id, this->_name, this->_requested_state);
// Get Homey connection settings
auto homey_address = MqttManagerConfig::get_setting_with_default<std::string>(MQTT_MANAGER_SETTING::HOMEY_ADDRESS);
auto homey_token = MqttManagerConfig::get_setting_with_default<std::string>(MQTT_MANAGER_SETTING::HOMEY_TOKEN);
if (homey_address.empty() || homey_token.empty())
{
SPDLOG_ERROR("Homey address or token not configured for button {}::{}", this->_id, this->_name);
return;
}
// Construct URL: http://{homey_address}/api/manager/devices/device/{device_id}/capability/onoff
std::string url = fmt::format("http://{}/api/manager/devices/device/{}/capability/onoff", homey_address, this->_homey_device_id);
// Create request body - button trigger uses null value
nlohmann::json request_body;
request_body["value"] = this->_requested_state;
// Send HTTP PUT request with bearer token authentication
try
{
// Create header strings with proper lifetime management
std::string auth_header = fmt::format("Authorization: Bearer {}", homey_token);
std::list<const char *> headers = {
auth_header.c_str(),
"Content-Type: application/json"};
std::string response_data;
std::string put_data = request_body.dump();
if (WebHelper::perform_put_request(&url, &response_data, &headers, &put_data))
{
SPDLOG_DEBUG("Homey button {}::{} trigger response: {}", this->_id, this->_name, response_data);
}
else
{
SPDLOG_ERROR("Failed to trigger Homey button {}::{}", this->_id, this->_name);
}
}
catch (const std::exception &e)
{
SPDLOG_ERROR("Failed to trigger Homey button {}::{}: {}", this->_id, this->_name, e.what());
}
// Buttons don't have persistent state, so no optimistic mode handling needed
}
void HomeyButton::homey_event_callback(nlohmann::json data)
{
try
{
// Homey WebSocket sends: {"id": "device-uuid", "capabilitiesObj": {...}}
// Buttons typically don't send state updates, but we'll handle them if they do
SPDLOG_DEBUG("Got event update for Homey button {}::{}.", this->_id, this->_name);
// Buttons are typically one-way (trigger only), so no state to process
// But we keep this callback for potential future use
}
catch (std::exception &e)
{
SPDLOG_ERROR("Caught exception when processing Homey event for button {}::{}: {}",
this->_id, this->_name, boost::diagnostic_information(e, true));
}
}