9#if FL_PLATFORM_HAS_LARGE_MEMORY
12#define DEBUG_PRINT(x) do {} while(0)
13#define DEBUG_PRINTLN(x) do {} while(0)
58 remote.bind(
"testAsync", [
this](
const fl::json&
args) -> fl::json {
63 fl::string requested_driver;
65 if (
args.is_object()) {
67 }
else if (
args.is_array() &&
args.size() >= 1 &&
args[0].is_object()) {
71 if (config.
contains(
"numLeds") && config[
"numLeds"].is_int()) {
72 num_leds =
static_cast<int>(config[
"numLeds"].
as_int().value());
74 if (config.
contains(
"driver") && config[
"driver"].is_string()) {
75 requested_driver = config[
"driver"].
as_string().value();
80 if (!requested_driver.
empty()) {
83 response.set(
"error",
"DriverSetupFailed");
85 msg <<
"Failed to set '" << requested_driver.
c_str() <<
"' as exclusive driver";
91 if (num_leds < 10 || num_leds > 1000) {
93 response.set(
"error",
"InvalidNumLeds");
94 response.set(
"message",
"numLeds must be 10-1000");
99 fl::vector<CRGB>
leds(num_leds);
100 for (
int i = 0; i < num_leds; i++) {
104 fl::ChannelConfig channel_config(
114 response.set(
"error",
"ChannelCreationFailed");
115 response.set(
"message",
"Failed to create channel");
148 bool passed = (total2_us > 0) && (show2_us < total2_us / 2);
151 fl::string driver_name =
"unknown";
152 for (fl::size i = 0; i <
mState->drivers_available.size(); i++) {
153 if (
mState->drivers_available[i].enabled) {
154 driver_name =
mState->drivers_available[i].name;
162 response.set(
"show1_us",
static_cast<int64_t
>(show1_us));
163 response.set(
"wait1_us",
static_cast<int64_t
>(wait1_us));
164 response.set(
"total1_us",
static_cast<int64_t
>(total1_us));
166 response.set(
"show2_us",
static_cast<int64_t
>(show2_us));
167 response.set(
"wait2_us",
static_cast<int64_t
>(wait2_us));
168 response.set(
"total2_us",
static_cast<int64_t
>(total2_us));
169 response.set(
"num_leds",
static_cast<int64_t
>(num_leds));
174 msg <<
"Async OK: draw2 show()=" << show2_us
175 <<
"us, wait()=" << wait2_us
176 <<
"us, total=" << total2_us <<
"us"
177 <<
" (draw1 show=" << show1_us <<
"us)";
179 msg <<
"Async FAIL: draw2 show()=" << show2_us
180 <<
"us out of " << total2_us
181 <<
"us total (expected <50%)"
182 <<
" (draw1 show=" << show1_us <<
"us)";
194 remote.bind(
"startNetServer", [
this](
const fl::json&
args) -> fl::json {
195 mState->net_server_active =
true;
200 remote.bind(
"startNetClient", [
this](
const fl::json&
args) -> fl::json {
201 mState->net_client_active =
true;
207 remote.bind(
"runNetClientTest", [](
const fl::json&
args) -> fl::json {
211 if (!
args.is_object()) {
213 response.set(
"error",
"Expected object with host_ip and port");
217 fl::json host_ip_val =
args[fl::string(
"host_ip")];
218 fl::json port_val =
args[fl::string(
"port")];
222 response.set(
"error",
"Expected {host_ip: string, port: int}");
226 fl::string host_ip = host_ip_val.
as_string().value();
232 response.set(
"error",
"port must be in [1, 65535]");
241 remote.bind(
"netServerStats", [](
const fl::json&
args) -> fl::json {
246 remote.bind(
"runNetLoopback", [](
const fl::json&
args) -> fl::json {
251 remote.bind(
"stopNet", [
this](
const fl::json&
args) -> fl::json {
252 mState->net_server_active =
false;
253 mState->net_client_active =
false;
262 remote.bind(
"wifiConnect", [](
const fl::json&
args) -> fl::json {
264 fl::string ssid, pass;
265 if (
args.contains(
"ssid") &&
args[
"ssid"].is_string()) {
266 ssid =
args[
"ssid"].as_string().value();
268 if (
args.contains(
"password") &&
args[
"password"].is_string()) {
269 pass =
args[
"password"].as_string().value();
273 response.set(
"error",
"MissingSsid");
283 remote.bind(
"wifiAp", [](
const fl::json&
args) -> fl::json {
285 fl::string ssid, pass;
287 if (
args.contains(
"ssid") &&
args[
"ssid"].is_string()) {
288 ssid =
args[
"ssid"].as_string().value();
290 if (
args.contains(
"password") &&
args[
"password"].is_string()) {
291 pass =
args[
"password"].as_string().value();
293 if (
args.contains(
"channel") &&
args[
"channel"].is_int()) {
294 channel =
static_cast<int>(
args[
"channel"].as_int().value());
298 response.set(
"error",
"MissingSsid");
302 static_cast<fl::u8>(channel));
309 remote.bind(
"wifiStatus", [](
const fl::json&
args) -> fl::json {
320 remote.bind(
"wifiStop", [](
const fl::json&
args) -> fl::json {
329 remote.bind(
"netActivity", [](
const fl::json&
args) -> fl::json {
346 remote.bind(
"startOta", [](
const fl::json&
args) -> fl::json {
351 remote.bind(
"stopOta", [](
const fl::json&
args) -> fl::json {
355 remote.bind(
"beginOtaArtifact", [](
const fl::json&
args) -> fl::json {
356 if (!
args.contains(
"size") || !
args[
"size"].is_int() ||
357 !
args.contains(
"sha256") || !
args[
"sha256"].is_string()) {
360 response.set(
"error",
"Expected size and sha256");
363 const int64_t size =
args[
"size"].as_int().value();
365 args[
"sha256"].as_string().value().c_str());
368 remote.bind(
"writeOtaArtifact", [](fl::vector<fl::u8> bytes) -> fl::json {
372 remote.bind(
"finishOtaArtifact", [](
const fl::json&
args) -> fl::json {
376 remote.bind(
"startOtaArtifactServer", [](
const fl::json&
args) -> fl::json {
380 remote.bind(
"otaArtifactStatus", [](
const fl::json&
args) -> fl::json {
384 remote.bind(
"rpOtaUpdateStatus", [](
const fl::json&
args) -> fl::json {
388 remote.bind(
"applyOtaArtifact", [](
const fl::json&
args) -> fl::json {
389 if (!
args.contains(
"host") || !
args[
"host"].is_string() ||
390 !
args.contains(
"port") || !
args[
"port"].is_int()) {
393 response.set(
"error",
"Expected host and port");
403 response.set(
"error",
"port must be in [1, 65535]");
415 remote.bind(
"startBle", [
this](
const fl::json&
args) -> fl::json {
420 remote.bind(
"stopBle", [
this](
const fl::json&
args) -> fl::json {
426 remote.bind(
"decodeFile", [](fl::vector<fl::u8> data, fl::string ext) -> fl::json {
431 response.set(
"error",
"Only .mp4 supported for device decode");
448 response.set(
"error",
"H264 decoder not supported on this platform");
453 fl::string dec_error;
464 if (!decoder->begin(stream)) {
466 decoder->hasError(&msg);
472 auto result = decoder->decode();
475 response.set(
"error",
"Decode returned non-success");
476 response.set(
"decode_result",
static_cast<int64_t
>(
static_cast<int>(result)));
481 fl::Frame frame = decoder->getCurrentFrame();
486 response.set(
"error",
"Decoded frame is invalid");
495 auto pixels = frame.
rgb();
497 int count = pixels.size() < 16 ?
static_cast<int>(pixels.size()) : 16;
498 for (
int i = 0; i < count; i++) {
500 px.
push_back(
static_cast<int64_t
>(pixels[i].r));
501 px.
push_back(
static_cast<int64_t
>(pixels[i].g));
502 px.
push_back(
static_cast<int64_t
>(pixels[i].b));
505 response.set(
"pixels", pixel_array);
511 remote.bind(
"bleStatus", [
this](
const fl::json&
args) -> fl::json {
bool autoResearchSetExclusiveDriverByName(const char *name)
AutoResearch-style helper: set an exclusive driver by name.
fl::json runNetLoopback()
Run self-contained loopback test: start HTTP server, client GETs localhost.
fl::json startNetClient()
Start WiFi Soft AP only (for net-client mode).
fl::json runNetClientTest(const char *host_ip, uint16_t port)
Run HTTP client tests against a host server.
fl::json startNetServer()
Start WiFi Soft AP and HTTP server with test endpoints.
fl::json stopNet()
Stop WiFi AP and HTTP server/client, release all resources.
fl::json netServerStats()
Why the RP peer server last abandoned a request (FastLED#3899 diagnostics).
fl::json queueOtaArtifactUpdate(const char *host, uint16_t port)
Queue an RP2350W HTTP update so the RPC response can be sent first.
fl::json writeOtaArtifact(fl::vector< fl::u8 > bytes)
fl::json otaArtifactStatus()
fl::json stopOta()
Stop OTA server and WiFi AP, release all resources.
fl::json finishOtaArtifact()
fl::json startOtaArtifactServer()
fl::json rpOtaUpdateStatus()
Outcome of the last pollOtaArtifactUpdate fetch, readable after the host reconnects.
fl::json startOta()
Start WiFi Soft AP and OTA HTTP server.
fl::json beginOtaArtifact(size_t expected_size, const char *sha256)
Stage one RP2350W firmware artifact on the ESP32-C6 fixture.
Full PARLIO encode bench for ESP32-P4 (post-byte-LUT, #2526 landed).
PARLIO ISR-streaming functional validation (#2548 deep-dive follow-up).
Issue #2994 repro: compounded per-sequence timing drift vs 3.10.3.
Wave8 expansion micro-benchmark for #2526.
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
fl::unique_ptr< fl::Remote > remote
fl::net::ble — BLE GATT transport layer for JSON-RPC
SPI encoder configuration for clocked LED chipsets.
void bindNetworkMethods(fl::Remote &remote)
fl::json stopBleRemote()
Stop BLE remote (destroys BLE Remote + GATT server)
fl::net::ble::TransportState * mBleState
fl::shared_ptr< AutoResearchState > mState
fl::json startBleRemote()
Start BLE remote (creates BLE GATT server + second Remote instance)
void show(fl::u8 scale)
Update all our controllers with the current led colors, using the passed in brightness.
static void add(fl::ChannelPtr channel)
Add a Channel-based LED controller (from ChannelPtr)
void wait()
Wait for all channel bus transmissions to complete.
void clear(bool writeData=false)
Clear the leds, wiping the local array of data.
fl::u16 getHeight() const
static IDecoderPtr createDecoder(const H264Config &config, fl::string *error_message=nullptr)
static H264Info parseH264Info(fl::span< const fl::u8 > mp4Data, fl::string *error_message=nullptr)
static bool isSupported()
bool has_value() const FL_NO_EXCEPT
JSON-RPC server with scheduling support.
bool empty() const FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
fl::optional< fl::string > as_string() const FL_NO_EXCEPT
fl::optional< i64 > as_int() const FL_NO_EXCEPT
bool is_int() const FL_NO_EXCEPT
bool is_null() const FL_NO_EXCEPT
void push_back(const json &value) FL_NO_EXCEPT
bool contains(size_t idx) const FL_NO_EXCEPT
bool is_string() const FL_NO_EXCEPT
static json object() FL_NO_EXCEPT
static json array() FL_NO_EXCEPT
static bool isWiFiActive() FL_NO_EXCEPT
static bool isAnyNetworkConnected() FL_NO_EXCEPT
static bool isWiFiConnected() FL_NO_EXCEPT
static bool isAnyNetworkActive() FL_NO_EXCEPT
static bool isBluetoothActive() FL_NO_EXCEPT
string str() const FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
Task executor — runs registered task runners and manages the run loop.
@ CHANNELS
Remove all channels from controller list.
Platform-abstracted heap memory query functions.
FastLED's Elegant JSON Library: fl::json
StatusInfo queryStatus(const TransportState *) FL_NO_EXCEPT
Query BLE connection/subscription diagnostics.
bool isConnected() FL_NO_EXCEPT
True when the station interface has an IP.
const char * toString(Status s) FL_NO_EXCEPT
Human-readable name for a Status value.
void stop() FL_NO_EXCEPT
Stop WiFi entirely (STA and AP).
bool startAp(const char *, const char *, u8) FL_NO_EXCEPT
Bring up a SoftAP.
Status status() FL_NO_EXCEPT
Current connection state.
bool connectSta(const char *, const char *) FL_NO_EXCEPT
Start an asynchronous station-mode join.
fl::string ipAddress() FL_NO_EXCEPT
Dotted-quad IP of the station interface ("" until connected).
fl::string apIpAddress() FL_NO_EXCEPT
Dotted-quad IP of the SoftAP interface ("" when AP is down).
fl::optional< u16 > tryParsePort(i64 value)
Convert an untrusted integer to a port number.
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
constexpr ChipsetTimingConfig makeTimingConfig() FL_NO_EXCEPT
Convert compile-time CHIPSET type to runtime timing config.
fl::u32 micros()
Universal microsecond timer - returns microseconds since system startup.
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
expected< T, E > result
Alias for expected (Rust-style naming)
Cross-platform facade for runtime network activity detection.
Range-checked conversion of an untrusted integer to a TCP/UDP port.
Promise-based fluent API for FastLED - standalone async primitives.
Umbrella header for SIMD subsystem.
fl::net::wifi — platform-neutral WiFi connection API (FastLED#3576 Phase 6).