-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathentity_manager.hpp
More file actions
234 lines (194 loc) · 7.83 KB
/
entity_manager.hpp
File metadata and controls
234 lines (194 loc) · 7.83 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#ifndef MQTT_MANAGER_ENTITY_MANAGER
#define MQTT_MANAGER_ENTITY_MANAGER
#include "protobuf_nspanel.pb.h"
#include "room/room_entities_page.hpp"
#include "websocket_server/websocket_server.hpp"
#include <boost/signals2.hpp>
#include <condition_variable>
#include <entity/entity.hpp>
#include <expected>
#include <memory>
#include <mqtt_manager/mqtt_manager.hpp>
#include <mutex>
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#include <nspanel/nspanel.hpp>
#include <spdlog/spdlog.h>
#include <vector>
#include <weather/weather.hpp>
// Forward declare entities:
class Room;
class Light;
class EntityManager {
public:
// Error that are used within std::expected to indicate what went wrong.
enum EntityError {
NOT_FOUND, // The entity was not found
NONE_LOADED, // No entities loaded of the type requested
};
/**
* Setup function callbacks and other prerequisites for the EntityManager
*/
static void
init();
/*
* Load entities from database, update any already loaded entities.
*/
static void load_entities();
/**
* Attach callback for when a new entity is added
*/
static void attach_entity_added_listener(void (*listener)(std::shared_ptr<MqttManagerEntity>));
/**
* Detach an existing callback for when an entity is added
*/
static void detach_entity_added_listener(void (*listener)(std::shared_ptr<MqttManagerEntity>));
/**
* Remove an entity from the list of managed entities.
*/
static void remove_entity(std::shared_ptr<MqttManagerEntity> entity);
/*
* Load all rooms from the DB and remove any existing room that no longer exist.
*/
static void load_rooms();
/*
* Load all NSPanels from the DB and remove any existing panel that no longer exist.
*/
static void load_nspanels();
/*
* Load all lights from the DB and remove any existing light that no longer exist.
*/
static void load_lights();
/*
* Load all buttons from the DB and remove any existing button that no longer exist.
*/
static void load_buttons();
/*
* Load all thermostats from the DB and remove any existing thermostat that no longer exist.
*/
static void load_thermostats();
/*
* Load all switches from the DB and remove any existing switch that no longer exist.
*/
static void load_switches();
/*
* Load all scenes from the DB and remove any existing scene that no longer exist.
*/
static void load_scenes();
/*
* Load global RoomEntitiesPages from the DB and remove any existing page that no longer exist.
* This is primarily used for global scenes pages. Any page associated with a room is ignored and is instead handled within each room itself.
*/
static void load_global_room_entities_pages();
/**
* Get a room with the given ID if it existing.
*/
static std::expected<std::shared_ptr<Room>, EntityError> get_room(uint32_t room_id);
/**
* Get all currently registered rooms
*/
static std::expected<std::vector<std::shared_ptr<Room>>, EntityError> get_all_rooms();
/*
* Get all currently registered room entities pages.
*/
static std::expected<std::vector<std::shared_ptr<RoomEntitiesPage>>, EntityError> get_all_global_room_entities_pages();
/*
* Get number of register entities pages.
*/
static std::expected<int32_t, EntityError> get_number_of_global_room_entities_pages();
/*
* When a room is updated, update the "All rooms" status for when the panel is in the "All rooms" mode.
*/
static void update_all_rooms_status();
/*
* Handle commands that are sent to the MQTTManager but are not
* neccesarily handled by other entities directly.
*/
static void _command_callback(NSPanelMQTTManagerCommand &command);
/**
* Get an item by the specified type that has the specified ID.
* Return pointer to entity if found, otherwise a nullptr
*/
template <class EntityClass>
static std::expected<std::shared_ptr<EntityClass>, EntityError> get_entity_by_id(MQTT_MANAGER_ENTITY_TYPE type, int id) {
std::lock_guard<std::mutex> mutex_guard(EntityManager::_entities_mutex);
auto rit = EntityManager::_entities.cbegin();
while (rit != EntityManager::_entities.cend()) {
if ((type == MQTT_MANAGER_ENTITY_TYPE::ANY || (*rit)->get_type() == type) && (*rit)->get_id() == id) {
return std::static_pointer_cast<EntityClass>(*rit);
} else {
++rit;
}
}
return std::unexpected(EntityError::NOT_FOUND);
}
/**
* Get an MqttManagerEntity that is placed in the given slot on the given page.
* Returns shared_ptr to MqttManagerEntity object if found, otherwise nullptr.
*/
static std::expected<std::shared_ptr<MqttManagerEntity>, EntityError> get_entity_by_page_id_and_slot(uint32_t page_id, uint8_t page_slot) {
std::lock_guard<std::mutex> mutex_guard(EntityManager::_entities_mutex);
auto rit = EntityManager::_entities.cbegin();
while (rit != EntityManager::_entities.cend()) {
if ((*rit)->get_entity_page_id() == page_id && (*rit)->get_entity_page_slot() == page_slot) {
return (*rit);
} else {
++rit;
}
}
return std::unexpected(EntityError::NOT_FOUND);
}
/**
* Get all entities matching the specified type that has the specified ID.
* Return std::list of pointers to entities.
*/
template <class EntityClass>
static std::expected<std::vector<std::shared_ptr<EntityClass>>, EntityError> get_all_entities_by_type(MQTT_MANAGER_ENTITY_TYPE type) {
std::lock_guard<std::mutex> mutex_guard(EntityManager::_entities_mutex);
std::vector<std::shared_ptr<EntityClass>> entities;
for (auto entity : EntityManager::_entities) {
if (entity->get_type() == type) {
entities.push_back(std::static_pointer_cast<EntityClass>(entity));
}
}
if (entities.size() > 0) {
return entities;
} else {
return std::unexpected(EntityError::NONE_LOADED);
}
}
/**
* Process MQTT Message. Return true if message was handled.
*/
static bool mqtt_callback(const std::string &topic, const std::string &payload);
/**
* Callback from MQTT Manager for when a message was received on a subscribed topic.
*/
static void mqtt_topic_callback(const std::string &topic, const std::string &payload);
/**
* Process any incomming message from the websocket. Return true if message was handled.
*/
static void websocket_callback(StompFrame frame);
static std::expected<std::shared_ptr<NSPanel>, EntityError> get_nspanel_by_id(uint id);
static std::expected<std::shared_ptr<NSPanel>, EntityError> get_nspanel_by_mac(std::string mac);
private:
static inline std::vector<std::shared_ptr<MqttManagerEntity>> _entities;
static inline std::mutex _entities_mutex;
static inline std::vector<std::shared_ptr<Room>> _rooms;
static inline std::mutex _rooms_mutex;
static inline std::vector<std::shared_ptr<NSPanel>> _nspanels;
static inline std::mutex _nspanels_mutex;
static inline std::vector<std::shared_ptr<RoomEntitiesPage>> _global_room_entities_pages;
static inline std::mutex _global_room_entities_pages_mutex;
static inline std::atomic<bool> _all_rooms_status_updated;
static inline void _room_updated_callback(Room *room);
static inline std::thread _update_all_rooms_status_thread;
static inline std::atomic<std::chrono::time_point<std::chrono::system_clock>> _last_room_update_time;
static inline std::condition_variable _room_update_condition_variable; // Notify thread that handles "All rooms" status updates
static bool _process_message(const std::string &topic, const std::string &payload);
static void _handle_register_request(const nlohmann::json &data);
static inline MQTTManagerWeather _weather_manager;
static inline boost::signals2::signal<void(std::shared_ptr<MqttManagerEntity>)> _entity_added_signal;
static inline boost::signals2::signal<void(std::shared_ptr<MqttManagerEntity>)> _entity_removed_signal;
};
#endif // !MQTT_MANAGER_ENTITY_MANAGER