Skip to content

Commit 256c1a1

Browse files
Astrrraskotopesgsurkov
authored
[FL-3917] Add the ability to send a signal once via RPC (#4000)
* Add the ability to send a signal once * Update protobuf * Fix sending infrared signals * Review changes * Update protobuf * Separate sending an IR signal once into a function * Update protobuf module --------- Co-authored-by: あく <[email protected]> Co-authored-by: Georgii Surkov <[email protected]>
1 parent 7d5358b commit 256c1a1

File tree

10 files changed

+181
-1
lines changed

10 files changed

+181
-1
lines changed

applications/main/infrared/infrared_app.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ static void infrared_rpc_command_callback(const RpcAppSystemEvent* event, void*
8888
view_dispatcher_send_custom_event(
8989
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPressIndex);
9090
}
91+
} else if(event->type == RpcAppEventTypeButtonPressRelease) {
92+
furi_assert(
93+
event->data.type == RpcAppSystemEventDataTypeString ||
94+
event->data.type == RpcAppSystemEventDataTypeInt32);
95+
if(event->data.type == RpcAppSystemEventDataTypeString) {
96+
furi_string_set(infrared->button_name, event->data.string);
97+
view_dispatcher_send_custom_event(
98+
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPressReleaseName);
99+
} else {
100+
infrared->app_state.current_button_index = event->data.i32;
101+
view_dispatcher_send_custom_event(
102+
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPressReleaseIndex);
103+
}
91104
} else if(event->type == RpcAppEventTypeButtonRelease) {
92105
view_dispatcher_send_custom_event(
93106
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease);
@@ -411,6 +424,26 @@ void infrared_tx_stop(InfraredApp* infrared) {
411424
infrared->app_state.last_transmit_time = furi_get_tick();
412425
}
413426

427+
void infrared_tx_send_once(InfraredApp* infrared) {
428+
if(infrared->app_state.is_transmitting) {
429+
return;
430+
}
431+
432+
dolphin_deed(DolphinDeedIrSend);
433+
infrared_signal_transmit(infrared->current_signal);
434+
}
435+
436+
InfraredErrorCode infrared_tx_send_once_button_index(InfraredApp* infrared, size_t button_index) {
437+
furi_assert(button_index < infrared_remote_get_signal_count(infrared->remote));
438+
439+
InfraredErrorCode error = infrared_remote_load_signal(
440+
infrared->remote, infrared->current_signal, infrared->app_state.current_button_index);
441+
if(!INFRARED_ERROR_PRESENT(error)) {
442+
infrared_tx_send_once(infrared);
443+
}
444+
445+
return error;
446+
}
414447
void infrared_blocking_task_start(InfraredApp* infrared, FuriThreadCallback callback) {
415448
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewLoading);
416449
furi_thread_set_callback(infrared->task_thread, callback);

applications/main/infrared/infrared_app_i.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ InfraredErrorCode infrared_tx_start_button_index(InfraredApp* infrared, size_t b
218218
*/
219219
void infrared_tx_stop(InfraredApp* infrared);
220220

221+
/**
222+
* @brief Transmit the currently loaded signal once.
223+
*
224+
* @param[in,out] infrared pointer to the application instance.
225+
*/
226+
void infrared_tx_send_once(InfraredApp* infrared);
227+
228+
/**
229+
* @brief Load the signal under the given index and transmit it once.
230+
*
231+
* @param[in,out] infrared pointer to the application instance.
232+
*/
233+
InfraredErrorCode infrared_tx_send_once_button_index(InfraredApp* infrared, size_t button_index);
234+
221235
/**
222236
* @brief Start a blocking task in a separate thread.
223237
*

applications/main/infrared/infrared_custom_event.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ enum InfraredCustomEventType {
2121
InfraredCustomEventTypeRpcButtonPressName,
2222
InfraredCustomEventTypeRpcButtonPressIndex,
2323
InfraredCustomEventTypeRpcButtonRelease,
24+
InfraredCustomEventTypeRpcButtonPressReleaseName,
25+
InfraredCustomEventTypeRpcButtonPressReleaseIndex,
2426
InfraredCustomEventTypeRpcSessionClose,
2527

2628
InfraredCustomEventTypeGpioTxPinChanged,

applications/main/infrared/scenes/infrared_scene_rpc.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,49 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
124124

125125
rpc_system_app_confirm(infrared->rpc_ctx, result);
126126

127+
} else if(
128+
event.event == InfraredCustomEventTypeRpcButtonPressReleaseName ||
129+
event.event == InfraredCustomEventTypeRpcButtonPressReleaseIndex) {
130+
bool result = false;
131+
132+
// Send the signal once and stop
133+
if(rpc_state == InfraredRpcStateLoaded) {
134+
if(event.event == InfraredCustomEventTypeRpcButtonPressReleaseName) {
135+
const char* button_name = furi_string_get_cstr(infrared->button_name);
136+
size_t index;
137+
const bool index_found =
138+
infrared_remote_get_signal_index(infrared->remote, button_name, &index);
139+
app_state->current_button_index = index_found ? (signed)index :
140+
InfraredButtonIndexNone;
141+
FURI_LOG_D(TAG, "Sending signal with name \"%s\"", button_name);
142+
} else {
143+
FURI_LOG_D(
144+
TAG, "Sending signal with index \"%ld\"", app_state->current_button_index);
145+
}
146+
if(infrared->app_state.current_button_index != InfraredButtonIndexNone) {
147+
InfraredErrorCode error = infrared_tx_send_once_button_index(
148+
infrared, app_state->current_button_index);
149+
if(!INFRARED_ERROR_PRESENT(error)) {
150+
const char* remote_name = infrared_remote_get_name(infrared->remote);
151+
infrared_text_store_set(infrared, 0, "emulating\n%s", remote_name);
152+
153+
infrared_scene_rpc_show(infrared);
154+
result = true;
155+
} else {
156+
rpc_system_app_set_error_code(
157+
infrared->rpc_ctx, RpcAppSystemErrorCodeInternalParse);
158+
rpc_system_app_set_error_text(
159+
infrared->rpc_ctx, "Cannot load button data");
160+
result = false;
161+
}
162+
}
163+
}
164+
165+
if(result) {
166+
scene_manager_set_scene_state(
167+
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
168+
}
169+
rpc_system_app_confirm(infrared->rpc_ctx, result);
127170
} else if(
128171
event.event == InfraredCustomEventTypeRpcExit ||
129172
event.event == InfraredCustomEventTypeRpcSessionClose ||

applications/main/subghz/helpers/subghz_custom_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef enum {
4949
SubGhzCustomEventSceneRpcLoad,
5050
SubGhzCustomEventSceneRpcButtonPress,
5151
SubGhzCustomEventSceneRpcButtonRelease,
52+
SubGhzCustomEventSceneRpcButtonPressRelease,
5253
SubGhzCustomEventSceneRpcSessionClose,
5354

5455
SubGhzCustomEventViewReceiverOK,

applications/main/subghz/scenes/subghz_scene_rpc.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,43 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
8585
scene_manager_set_scene_state(
8686
subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateIdle);
8787
rpc_system_app_confirm(subghz->rpc_ctx, result);
88+
} else if(event.event == SubGhzCustomEventSceneRpcButtonPressRelease) {
89+
bool result = false;
90+
if(state == SubGhzRpcStateLoaded) {
91+
switch(
92+
subghz_txrx_tx_start(subghz->txrx, subghz_txrx_get_fff_data(subghz->txrx))) {
93+
case SubGhzTxRxStartTxStateErrorOnlyRx:
94+
rpc_system_app_set_error_code(
95+
subghz->rpc_ctx, RpcAppSystemErrorCodeRegionLock);
96+
rpc_system_app_set_error_text(
97+
subghz->rpc_ctx,
98+
"Transmission on this frequency is restricted in your region");
99+
break;
100+
case SubGhzTxRxStartTxStateErrorParserOthers:
101+
rpc_system_app_set_error_code(
102+
subghz->rpc_ctx, RpcAppSystemErrorCodeInternalParse);
103+
rpc_system_app_set_error_text(
104+
subghz->rpc_ctx, "Error in protocol parameters description");
105+
break;
106+
107+
default: //if(SubGhzTxRxStartTxStateOk)
108+
result = true;
109+
subghz_blink_start(subghz);
110+
scene_manager_set_scene_state(
111+
subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateTx);
112+
break;
113+
}
114+
}
115+
116+
// Stop transmission
117+
if(state == SubGhzRpcStateTx) {
118+
subghz_txrx_stop(subghz->txrx);
119+
subghz_blink_stop(subghz);
120+
result = true;
121+
}
122+
scene_manager_set_scene_state(
123+
subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateIdle);
124+
rpc_system_app_confirm(subghz->rpc_ctx, result);
88125
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
89126
bool result = false;
90127
if(state == SubGhzRpcStateIdle) {

applications/main/subghz/subghz.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ static void subghz_rpc_command_callback(const RpcAppSystemEvent* event, void* co
4343
} else if(event->type == RpcAppEventTypeButtonRelease) {
4444
view_dispatcher_send_custom_event(
4545
subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease);
46+
} else if(event->type == RpcAppEventTypeButtonPressRelease) {
47+
view_dispatcher_send_custom_event(
48+
subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPressRelease);
4649
} else {
4750
rpc_system_app_confirm(subghz->rpc_ctx, false);
4851
}

applications/services/rpc/rpc_app.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,41 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context)
258258
}
259259
}
260260

261+
static void rpc_system_app_button_press_release(const PB_Main* request, void* context) {
262+
furi_assert(request);
263+
furi_assert(request->which_content == PB_Main_app_button_press_release_request_tag);
264+
265+
RpcAppSystem* rpc_app = context;
266+
furi_assert(rpc_app);
267+
268+
if(rpc_app->callback) {
269+
FURI_LOG_D(TAG, "ButtonPressRelease");
270+
271+
RpcAppSystemEvent event;
272+
event.type = RpcAppEventTypeButtonPressRelease;
273+
274+
if(strlen(request->content.app_button_press_release_request.args) != 0) {
275+
event.data.type = RpcAppSystemEventDataTypeString;
276+
event.data.string = request->content.app_button_press_release_request.args;
277+
} else {
278+
event.data.type = RpcAppSystemEventDataTypeInt32;
279+
event.data.i32 = request->content.app_button_press_release_request.index;
280+
}
281+
282+
rpc_system_app_error_reset(rpc_app);
283+
rpc_system_app_set_last_command(rpc_app, request->command_id, &event);
284+
285+
rpc_app->callback(&event, rpc_app->callback_context);
286+
287+
} else {
288+
rpc_system_app_send_error_response(
289+
rpc_app,
290+
request->command_id,
291+
PB_CommandStatus_ERROR_APP_NOT_RUNNING,
292+
"ButtonPressRelease");
293+
}
294+
}
295+
261296
static void rpc_system_app_get_error_process(const PB_Main* request, void* context) {
262297
furi_assert(request);
263298
furi_assert(request->which_content == PB_Main_app_get_error_request_tag);
@@ -332,6 +367,7 @@ void rpc_system_app_confirm(RpcAppSystem* rpc_app, bool result) {
332367
rpc_app->last_event_type == RpcAppEventTypeLoadFile ||
333368
rpc_app->last_event_type == RpcAppEventTypeButtonPress ||
334369
rpc_app->last_event_type == RpcAppEventTypeButtonRelease ||
370+
rpc_app->last_event_type == RpcAppEventTypeButtonPressRelease ||
335371
rpc_app->last_event_type == RpcAppEventTypeDataExchange);
336372

337373
const uint32_t last_command_id = rpc_app->last_command_id;
@@ -432,6 +468,9 @@ void* rpc_system_app_alloc(RpcSession* session) {
432468
rpc_handler.message_handler = rpc_system_app_button_release;
433469
rpc_add_handler(session, PB_Main_app_button_release_request_tag, &rpc_handler);
434470

471+
rpc_handler.message_handler = rpc_system_app_button_press_release;
472+
rpc_add_handler(session, PB_Main_app_button_press_release_request_tag, &rpc_handler);
473+
435474
rpc_handler.message_handler = rpc_system_app_get_error_process;
436475
rpc_add_handler(session, PB_Main_app_get_error_request_tag, &rpc_handler);
437476

applications/services/rpc/rpc_app.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ typedef enum {
9090
* all activities to be conducted while a button is being pressed.
9191
*/
9292
RpcAppEventTypeButtonRelease,
93+
/**
94+
* @brief The client has informed the application that a button has been pressed and released.
95+
*
96+
* This command's meaning is application-specific, e.g. to perform an action
97+
* once without repeating it.
98+
*/
99+
RpcAppEventTypeButtonPressRelease,
93100
/**
94101
* @brief The client has sent a byte array of arbitrary size.
95102
*
@@ -162,6 +169,7 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app);
162169
* - RpcAppEventTypeLoadFile
163170
* - RpcAppEventTypeButtonPress
164171
* - RpcAppEventTypeButtonRelease
172+
* - RpcAppEventTypeButtonPressRelease
165173
* - RpcAppEventTypeDataExchange
166174
*
167175
* Not confirming these events will result in a client-side timeout.

0 commit comments

Comments
 (0)