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