30#if FL_PLATFORM_HAS_LARGE_MEMORY
31 mResponseStreamSink =
fl::move(sink);
52#if FL_PLATFORM_HAS_LARGE_MEMORY
77#if FL_PLATFORM_HAS_LARGE_MEMORY
83 entry.mIsStreaming =
true;
112#if FL_PLATFORM_HAS_LARGE_MEMORY
113# define FL_RPC_ERR_NO_METHOD "Invalid Request: missing 'method'"
114# define FL_RPC_ERR_METHOD_NOT_STR "Invalid Request: 'method' must be a string"
115# define FL_RPC_ERR_METHOD_NOT_FOUND_PREFIX "Method not found: "
116# define FL_RPC_ERR_PARAMS_NOT_ARRAY "Invalid params: must be an array"
117# define FL_RPC_ERR_INVALID_PARAMS_PREFIX "Invalid params: "
119# define FL_RPC_ERR_NO_METHOD "method"
120# define FL_RPC_ERR_METHOD_NOT_STR "method"
121# define FL_RPC_ERR_METHOD_NOT_FOUND_PREFIX "404: "
122# define FL_RPC_ERR_PARAMS_NOT_ARRAY "params"
123# define FL_RPC_ERR_INVALID_PARAMS_PREFIX "params: "
128 if (!request.contains(
"method")) {
129 FL_ERROR(
"RPC: Invalid Request - missing 'method' field");
133 auto methodOpt = request[
"method"].as_string();
134 if (!methodOpt.has_value()) {
135 FL_ERROR(
"RPC: Invalid Request - 'method' must be a string");
140#if FL_PLATFORM_HAS_LARGE_MEMORY
147 if (methodName ==
"rpc.discover") {
149 response.set(
"jsonrpc",
"2.0");
150 response.set(
"result",
schema());
151 if (request.contains(
"id")) {
152 response.set(
"id", request[
"id"]);
161 FL_WARN(
"RPC: Method not found: " << methodName.
c_str());
168 FL_ERROR(
"RPC: Invalid params - must be an array for method: " << methodName.
c_str());
174#if FL_PLATFORM_HAS_LARGE_MEMORY
175 if (entry.mIsStreaming) {
176 if (!mResponseStreamSink) {
183 const bool includeId = request.contains(
"id");
191 streamFn(resultWriter, paramsCopy,
requestId);
199 skip.set(
"noEnqueue",
true);
211 ack.
set(
"jsonrpc",
"2.0");
212 ack.
set(
"id", request[
"id"]);
215 ackResult.
set(
"acknowledged",
true);
216 ack.
set(
"result", ackResult);
219 FL_DBG(
"RPC: Sent ACK for async method: " << methodName.
c_str());
225#if FL_PLATFORM_HAS_LARGE_MEMORY
227 if (isResponseAware) {
239 resultTuple = entry.
mInvoker->invoke(params);
245 resultTuple = entry.
mInvoker->invoke(params);
252 if (!convResult.
ok()) {
259 response.set(
"jsonrpc",
"2.0");
260 response.set(
"result", returnVal);
263 if (request.contains(
"id")) {
264 response.set(
"id", request[
"id"]);
267#if FL_PLATFORM_HAS_LARGE_MEMORY
275 for (fl::size i = 0; i < convResult.
warnings().size(); ++i) {
278 response.set(
"warnings", warnings);
286 response.set(
"ackOnly",
true);
299 if (!request.contains(
"id")) {
301 if (request.contains(
"method")) {
302 auto methodOpt = request[
"method"].as_string();
303 if (methodOpt.has_value()) {
309 it->second.mInvoker->invoke(params);
327 for (fl::size i = 0; i < it->second.mTags.size(); ++i) {
329 for (fl::size j = 0; j <
result.size(); ++j) {
330 if (
result[j] == it->second.mTags[i]) {
336 result.push_back(it->second.mTags[i]);
352 methodTuple.
push_back(it->first.c_str());
353 methodTuple.
push_back(it->second.mSchemaGenerator->resultTypeName());
354 methodTuple.
push_back(it->second.mSchemaGenerator->params());
357 const char* modeStr = (it->second.mMode ==
RpcMode::ASYNC) ?
"async" :
"sync";
void valueNull() FL_NO_EXCEPT
Helper class for sending responses in async/streaming RPC methods.
void bindAsync(const char *name, fl::function< void(ResponseSend &, const json &)> fn, fl::RpcMode mode=fl::RpcMode::ASYNC) FL_NO_EXCEPT
Bind async method with ResponseSend& parameter (for ASYNC/ASYNC_STREAM modes) Signature: void(Respons...
fl::unordered_map< fl::string, detail::RpcEntry > mRegistry
void bindStreaming(const char *name, fl::StreamingRpcHandler fn) FL_NO_EXCEPT
Bind a method that streams its JSON-RPC result directly to the transport.
fl::optional< json > handle_maybe(const json &request) FL_NO_EXCEPT
For notifications (no id), returns nullopt.
void setResponseStreamSink(fl::ResponseStreamSink sink) FL_NO_EXCEPT
Set response stream sink for methods registered with bindStreaming().
fl::function< void(const fl::json &)> mResponseSink
json schema() const FL_NO_EXCEPT
Returns flat schema document.
json handle(const json &request) FL_NO_EXCEPT
Process a JSON-RPC request.
void setResponseSink(fl::function< void(const fl::json &)> sink) FL_NO_EXCEPT
Set response sink for sending ACK responses (used by async functions)
fl::vector< fl::string > tags() const FL_NO_EXCEPT
Returns list of unique tags used across all methods.
json methods() const FL_NO_EXCEPT
Returns flat method array: [["name", "returnType", [["param1", "type1"], ...]], .....
bool hasWarning() const FL_NO_EXCEPT
const fl::vector< fl::string > & warnings() const FL_NO_EXCEPT
const fl::string & errorMessage() const FL_NO_EXCEPT
static TypeConversionResult success() FL_NO_EXCEPT
bool ok() const FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
void set(const fl::string &key, const json &value) FL_NO_EXCEPT
bool is_array() const FL_NO_EXCEPT
void push_back(const json &value) FL_NO_EXCEPT
bool contains(size_t idx) const FL_NO_EXCEPT
static json parse(const fl::string &txt) FL_NO_EXCEPT
static json object() FL_NO_EXCEPT
static json array() FL_NO_EXCEPT
FastLED's Elegant JSON Library: fl::json
Centralized logging categories for FastLED hardware interfaces and subsystems.
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
tuple< typename fl::decay< Ts >::type... > make_tuple(Ts &&... args) FL_NO_EXCEPT
auto invoke(F &&f, T1 &&t1, Args &&... args) FL_NO_EXCEPT -> enable_if_t< is_member_function_pointer< typename remove_reference< F >::type >::value &&!detail::use_pointer_syntax< T1 >::value, decltype((fl::forward< T1 >(t1).*f)(fl::forward< Args >(args)...))>
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
json makeJsonRpcError(int code, const fl::string &message, const json &id) FL_NO_EXCEPT
fl::shared_ptr< ErasedInvoker > mInvoker
fl::function< void(ResponseSend &, const json &)> mResponseAwareFn
fl::shared_ptr< ErasedSchemaGenerator > mSchemaGenerator
fl::vector< fl::string > mTags
u8 u8 fract8 blur_amount FL_NO_EXCEPT
fl::function< void(fl::JsonStreamWriter &, const fl::json &, const fl::json &)> StreamingRpcHandler
expected< T, E > result
Alias for expected (Rust-style naming)
void streamJsonRpcResultEnvelope(fl::JsonStreamWriter &writer, const fl::json &requestId, bool includeId, const fl::JsonStreamCallback &writeResult) FL_NO_EXCEPT
constexpr nullopt_t nullopt
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) FL_NO_EXCEPT
fl::function< void(fl::JsonStreamCallback)> ResponseStreamSink
Base definition for an LED controller.
#define FL_RPC_ERR_NO_METHOD
#define FL_RPC_ERR_INVALID_PARAMS_PREFIX
#define FL_RPC_ERR_METHOD_NOT_STR
#define FL_RPC_ERR_PARAMS_NOT_ARRAY
#define FL_RPC_ERR_METHOD_NOT_FOUND_PREFIX