FastLED 3.9.15
Loading...
Searching...
No Matches
RpcServer.ino
Go to the documentation of this file.
1// @filter: (platform is native)
2
34
35#include <FastLED.h>
36#include "fl/remote/remote.h"
45
46#define NUM_LEDS 10
47#define DATA_PIN 3
48#define SERVER_PORT 8080
49
51
52// Static pointers to allow setup initialization
54static fl::Remote* pRemote = nullptr;
55
56void setup() {
57 Serial.begin(115200);
58 while (!Serial) {
59 ; // Wait for serial port to connect (needed for some boards)
60 }
61
62 Serial.println("\n==============================================");
63 Serial.println(" HTTP RPC SERVER - Streaming Example");
64 Serial.println("==============================================\n");
65
66 FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
67
68 // Allocate transport and remote on heap
70 auto& transport = *pTransport;
71
72 pRemote = new fl::Remote( // ok bare allocation
73 // RequestSource: read from HTTP server
74 [&transport]() { return transport->readRequest(); },
75 // ResponseSink: write to HTTP server
76 [&transport](const fl::json& r) { transport->writeResponse(r); }
77 );
78 auto& remote = *pRemote;
79
80 // Configure heartbeat and timeout
81 transport->setHeartbeatInterval(30000); // 30 seconds
82 transport->setTimeout(60000); // 60 seconds
83
84 // Connection callbacks
85 transport->setOnConnect([]() {
86 Serial.println("✓ Client connected");
87 });
88
89 transport->setOnDisconnect([]() {
90 Serial.println("✗ Client disconnected");
91 });
92
93 // ========== SYNC MODE: Immediate response ==========
94
95 remote.bind("add", [](int a, int b) -> int {
96 Serial.print("add(");
97 Serial.print(a);
98 Serial.print(", ");
99 Serial.print(b);
100 Serial.print(") = ");
101 Serial.println(a + b);
102 return a + b;
103 });
104
105 remote.bind("setLed", [](int index, int r, int g, int b) {
106 if (index >= 0 && index < NUM_LEDS) {
107 leds[index] = CRGB(r, g, b);
108 Serial.print("✓ Set LED ");
109 Serial.print(index);
110 Serial.print(" to RGB(");
111 Serial.print(r);
112 Serial.print(", ");
113 Serial.print(g);
114 Serial.print(", ");
115 Serial.print(b);
116 Serial.println(")");
117 } else {
118 Serial.print("✗ LED index ");
119 Serial.print(index);
120 Serial.println(" out of range");
121 }
122 });
123
124 remote.bind("fill", [](int r, int g, int b) {
125 fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
126 Serial.print("✓ Filled all LEDs with RGB(");
127 Serial.print(r);
128 Serial.print(", ");
129 Serial.print(g);
130 Serial.print(", ");
131 Serial.print(b);
132 Serial.println(")");
133 });
134
135 remote.bind("getStatus", []() -> fl::json {
136 fl::json result = fl::json::object();
137 result.set("numLeds", NUM_LEDS);
138 result.set("brightness", FastLED.getBrightness());
139 result.set("millis", static_cast<int64_t>(millis()));
140 Serial.println("✓ Status requested");
141 return result;
142 });
143
144 // ========== ASYNC MODE: ACK immediately, result later ==========
145
146 remote.bindAsync("longTask", [](fl::ResponseSend& send, const fl::json& params) {
147 // Send ACK immediately
149 ack.set("ack", true);
150 send.send(ack);
151
152 Serial.println("⏳ Long task started (ASYNC mode)");
153
154 // Extract duration from params (array format: [duration])
155 int duration = 1000; // default 1 second
156 if (params.is_array() && params.size() > 0) {
157 auto durationOpt = params[0].as_int();
158 if (durationOpt) {
159 duration = *durationOpt;
160 }
161 }
162
163 // Simulate long-running task
164 uint32_t startTime = millis();
165 while (millis() - startTime < static_cast<uint32_t>(duration)) {
166 delay(100);
167 }
168
169 // Send final result
170 fl::json result = fl::json::object();
171 result.set("value", 42);
172 result.set("duration", duration);
173 send.send(result);
174
175 Serial.print("✓ Long task complete (");
176 Serial.print(duration);
177 Serial.println(" ms)");
179
180 // ========== ASYNC_STREAM MODE: ACK + multiple updates + final ==========
181
182 remote.bindAsync("streamData", [](fl::ResponseSend& send, const fl::json& params) {
183 // Send ACK immediately
185 ack.set("ack", true);
186 send.send(ack);
187
188 Serial.println("📊 Stream started (ASYNC_STREAM mode)");
189
190 // Extract count from params (array format: [count])
191 int count = 10; // default 10 updates
192 if (params.is_array() && params.size() > 0) {
193 auto countOpt = params[0].as_int();
194 if (countOpt) {
195 count = *countOpt;
196 }
197 }
198
199 // Send multiple updates
200 for (int i = 0; i < count; i++) {
201 fl::json update = fl::json::object();
202 update.set("update", i);
203 update.set("progress", (i * 100) / count);
204 send.sendUpdate(update);
205
206 Serial.print(" Update ");
207 Serial.print(i);
208 Serial.print(" (");
209 Serial.print((i * 100) / count);
210 Serial.println("%)");
211
212 delay(100);
213 }
214
215 // Send final result with "stop" marker
216 fl::json final = fl::json::object();
217 final.set("done", true);
218 final.set("count", count);
219 send.sendFinal(final);
220
221 Serial.println("✓ Stream complete");
223
224 // Start the HTTP server
225 if (transport->connect()) {
226 Serial.print("✓ HTTP server listening on port ");
227 Serial.println(SERVER_PORT);
228 } else {
229 Serial.print("✗ Failed to start HTTP server on port ");
230 Serial.println(SERVER_PORT);
231 }
232
233 Serial.println("\n=== Available RPC Methods ===");
234 Serial.println("SYNC:");
235 Serial.println(" add(a, b) -> sum");
236 Serial.println(" setLed(index, r, g, b)");
237 Serial.println(" fill(r, g, b)");
238 Serial.println(" getStatus() -> {numLeds, brightness, millis}");
239 Serial.println("ASYNC:");
240 Serial.println(" longTask(duration) -> ACK + {value, duration}");
241 Serial.println("ASYNC_STREAM:");
242 Serial.println(" streamData(count) -> ACK + updates + {done, count}");
243 Serial.println();
244
245 Serial.println("Test with curl:");
246 Serial.println(" curl -X POST http://localhost:8080/rpc \\");
247 Serial.println(" -H \"Content-Type: application/json\" \\");
248 Serial.println(" -H \"Transfer-Encoding: chunked\" \\");
249 Serial.println(" -d '{\"jsonrpc\":\"2.0\",\"method\":\"add\",\"params\":[2,3],\"id\":1}'");
250 Serial.println();
251 Serial.println("Ready for incoming HTTP connections...\n");
252}
253
254void loop() {
255 if (!pTransport || !pRemote) {
256 return;
257 }
258
259 // Update transport (handle heartbeat, timeouts, reconnection)
260 (*pTransport)->update(millis());
261
262 // Update remote (process incoming requests)
263 pRemote->update(millis());
264
265 // Update LEDs
266 FastLED.show();
267
268 delay(10);
269}
#define NUM_LEDS
fl::CRGB leds[NUM_LEDS]
#define DATA_PIN
Definition ClientReal.h:82
#define SERVER_PORT
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
fl::unique_ptr< fl::Remote > remote
Definition RpcClient.ino:43
fl::unique_ptr< fl::net::http::HttpStreamClient > transport
Definition RpcClient.ino:42
void setup()
Definition RpcServer.ino:56
static fl::shared_ptr< fl::net::http::HttpStreamServer > * pTransport
Definition RpcServer.ino:53
static fl::Remote * pRemote
Definition RpcServer.ino:54
void loop()
JSON-RPC server with scheduling support.
Definition remote.h:40
void send(const fl::json &result)
Send a single response (for ASYNC mode)
void sendFinal(const fl::json &result)
Send final response and mark stream as complete (for ASYNC_STREAM mode)
void sendUpdate(const fl::json &update)
Send intermediate streaming update (for ASYNC_STREAM mode)
Helper class for sending responses in async/streaming RPC methods.
fl::optional< i64 > as_int() const FL_NOEXCEPT
Definition json.h:255
bool is_array() const FL_NOEXCEPT
Definition json.h:246
size_t size() const FL_NOEXCEPT
Definition json.h:633
void set(const fl::string &key, const json &value) FL_NOEXCEPT
Definition json.h:701
static json object() FL_NOEXCEPT
Definition json.h:692
void fill_solid(CRGB *targetArray, int numToFill, const CRGB &color) FL_NOEXCEPT
Fill a range of LEDs with a solid color.
Definition fill.cpp.hpp:9
constexpr EOrder GRB
Definition eorder.h:19
fl::CRGB CRGB
Definition crgb.h:25
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
#define Serial
Definition serial.h:304