Esp32-RBGridUI
Library for creating UIs for the RBController app
Loading...
Searching...
No Matches
gridui.h
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <memory>
5#include <vector>
6
7#include <freertos/FreeRTOS.h>
8#include <freertos/timers.h>
9
10#include "esp_timer.h"
11
12#include "rbwebserver.h"
13
14#include "builder/arm.h"
15#include "builder/bar.h"
16#include "builder/button.h"
17#include "builder/camera.h"
18#include "builder/checkbox.h"
19#include "builder/circle.h"
20#include "builder/input.h"
21#include "builder/joystick.h"
22#include "builder/led.h"
23#include "builder/orientation.h"
24#include "builder/select.h"
25#include "builder/slider.h"
26#include "builder/spinedit.h"
27#include "builder/switcher.h"
28#include "builder/text.h"
29
30#include "gridui_version.h"
31
32namespace rb {
33class Protocol;
34};
35
36namespace gridui {
37
38class WidgetState;
39
40not_found_response_t webserverNotFoundCallback(const char *request_path);
41
42class _GridUi {
43 friend class WidgetState;
44
45public:
46 _GridUi();
47 ~_GridUi();
48
49 void begin(rb::Protocol* protocol, int cols = 12, int rows = 18, bool enableSplitting = true);
50
51 // Simplified variant of begin() that:
52 // * Creates rb::Protocol with both UDP and WebSocket enabled
53 // * Calls start() on it
54 // * Calls rb_web_start
55 // * Calls begin()
56 rb::Protocol* begin(const char* owner, const char* deviceName);
57
58 // Simplified variant of begin() that:
59 // * Connects to WiFi network
60 // * Creates rb::Protocol with both UDP and WebSocket enabled
61 // * Calls start() on it
62 // * Calls rb_web_start
63 // * Calls begin()
64 rb::Protocol* beginConnect(const char* owner, const char* deviceName, const char* wifiSSID, const char* wifiPassword = "");
65
66 // Simplified variant of begin() that:
67 // * Connects to WiFi network
68 // * Creates rb::Protocol with both UDP and WebSocket enabled
69 // * Calls start() on it
70 // * Calls rb_web_start
71 // * If withCaptivePortal == true (default), starts up DNS server so that devices will automatically open the controller on connection.
72 // * Calls begin()
73 rb::Protocol* beginStartAp(const char* owner, const char* deviceName, const char* wifiSSID, const char* wifiPassword = "", bool withCaptivePortal = true);
74
75 void commit();
76
77 // Deinitializes GridUi. Frees the protocol, if it was created by GridUI and not by the app.
78 void end();
79
80 bool handleRbPacket(const std::string& command, rbjson::Object* pkt);
81
82 rb::Protocol* protocol() const { return m_protocol.load(); }
83
84 void changeTab(uint16_t index);
85
86 builder::Arm& arm(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
87 return *newWidget<builder::Arm>(x, y, w, h, uuid, tab);
88 }
89
90 builder::Bar& bar(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
91 return *newWidget<builder::Bar>(x, y, w, h, uuid, tab);
92 }
93
94 builder::Button& button(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
95 return *newWidget<builder::Button>(x, y, w, h, uuid, tab);
96 }
97
98 builder::Camera& camera(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
99 return *newWidget<builder::Camera>(x, y, w, h, uuid, tab);
100 }
101
102 builder::Checkbox& checkbox(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
103 return *newWidget<builder::Checkbox>(x, y, w, h, uuid, tab);
104 }
105
106 builder::Circle& circle(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
107 return *newWidget<builder::Circle>(x, y, w, h, uuid, tab);
108 }
109
110 builder::Input& input(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
111 return *newWidget<builder::Input>(x, y, w, h, uuid, tab);
112 }
113
114 builder::Joystick& joystick(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
115 return *newWidget<builder::Joystick>(x, y, w, h, uuid, tab);
116 }
117
118 builder::Led& led(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
119 return *newWidget<builder::Led>(x, y, w, h, uuid, tab);
120 }
121
122 builder::Orientation& orientation(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
123 return *newWidget<builder::Orientation>(x, y, w, h, uuid, tab);
124 }
125
126 builder::Slider& slider(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
127 return *newWidget<builder::Slider>(x, y, w, h, uuid, tab);
128 }
129
130 builder::SpinEdit& spinedit(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
131 return *newWidget<builder::SpinEdit>(x, y, w, h, uuid, tab);
132 }
133
134 builder::Switcher& switcher(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
135 auto* switcher = newWidget<builder::Switcher>(x, y, w, h, uuid, tab);
136 switcher->addCallback("changed", [&](gridui::Switcher& w) {
137 changeTab(w.value());
138 });
139 return *switcher;
140 }
141
142 builder::Text& text(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
143 return *newWidget<builder::Text>(x, y, w, h, uuid, tab);
144 }
145
146 builder::Select& select(float x, float y, float w, float h, uint16_t uuid = 0, uint16_t tab = 0) {
147 return *newWidget<builder::Select>(x, y, w, h, uuid, tab);
148 }
149
150 template <typename T>
151 T* newWidget(float x, float y, float w, float h, uint16_t uuid, uint16_t tab) {
152 static_assert(std::is_base_of<builder::Widget, T>::value, "T must inherit from builder::Widget.");
153
154 std::lock_guard<std::mutex> l(m_states_mu);
155
156 if (!checkUuidFreeLocked(uuid))
157 uuid = generateUuidLocked();
158
159 auto* state = new WidgetState(uuid, x, y, w, h, tab);
160 m_states.emplace_back(std::unique_ptr<WidgetState>(state));
161
162 auto* widget = new T(T::name(), *state);
163 m_widgets.emplace_back(std::unique_ptr<T>(widget));
164 return widget;
165 }
166
167private:
168 inline WidgetState* stateByUuidLocked(uint16_t uuid) const {
169 for (auto& itr : m_states) {
170 if (itr->uuid() == uuid) {
171 return itr.get();
172 }
173 }
174 return nullptr;
175 }
176
177 static void stateChangeTask(void* self);
178 static void tabChangeTask(void* self);
179
180 void notifyStateChange() {
181 m_states_modified = true;
182 }
183
184 uint16_t generateUuidLocked() const;
185 inline bool checkUuidFreeLocked(uint16_t uuid) const {
186 return uuid != 0 && stateByUuidLocked(uuid) == nullptr;
187 }
188
189 std::vector<std::unique_ptr<builder::Widget>> m_widgets;
190 std::vector<std::unique_ptr<WidgetState>> m_states;
191
192 std::atomic<rb::Protocol*> m_protocol;
193 bool m_protocol_ours;
194
195 std::unique_ptr<rbjson::Object> m_layout;
196 esp_timer_handle_t m_update_timer;
197 TaskHandle_t m_web_server_task;
198
199 mutable std::mutex m_states_mu;
200 uint32_t m_state_mustarrive_id;
201 std::atomic<bool> m_states_modified;
202
203 mutable std::mutex m_tab_mu;
204 std::atomic<bool> m_tab_changed;
205 uint16_t m_tab;
206};
207
208extern _GridUi UI;
209
210};
builder::Arm & arm(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:86
builder::Text & text(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:142
builder::Led & led(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:118
builder::Select & select(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:146
rb::Protocol * protocol() const
Definition gridui.h:82
friend class WidgetState
Definition gridui.h:43
builder::Bar & bar(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:90
T * newWidget(float x, float y, float w, float h, uint16_t uuid, uint16_t tab)
Definition gridui.h:151
builder::Input & input(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:110
builder::Button & button(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:94
builder::Checkbox & checkbox(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:102
rb::Protocol * beginConnect(const char *owner, const char *deviceName, const char *wifiSSID, const char *wifiPassword="")
Definition gridui.cpp:99
builder::Slider & slider(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:126
builder::SpinEdit & spinedit(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:130
builder::Circle & circle(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:106
void begin(rb::Protocol *protocol, int cols=12, int rows=18, bool enableSplitting=true)
Definition gridui.cpp:63
builder::Camera & camera(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:98
bool handleRbPacket(const std::string &command, rbjson::Object *pkt)
Definition gridui.cpp:234
builder::Orientation & orientation(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:122
builder::Switcher & switcher(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:134
void changeTab(uint16_t index)
Definition gridui.cpp:267
builder::Joystick & joystick(float x, float y, float w, float h, uint16_t uuid=0, uint16_t tab=0)
Definition gridui.h:114
rb::Protocol * beginStartAp(const char *owner, const char *deviceName, const char *wifiSSID, const char *wifiPassword="", bool withCaptivePortal=true)
Definition gridui.cpp:104
void addCallback(const std::string &name, const callback_t &cb)
Definition widget.h:54
Definition arm.h:8
_GridUi UI
Definition gridui.cpp:14
not_found_response_t webserverNotFoundCallback(const char *request_path)
Definition gridui.cpp:45
Definition gridui.h:32