[FL-1946] RPC App launch (#758)
* RPC: Add App start, lock status - Add RPC commands Application start, lock status acquiring. - Write tests for RPC App system. - Replace Unit Tests application with CLI command. This is for CI needs and for tests that run application. * Fix NDEBUG build * Update PB submodule * Fix RPC print (ENABLE DEBUG PRINT!) * snprintf -> string_t * Fix Hard Fault (early mutex free) * printf -> string_t, format, enable tests * Update submodule: protobuf * Applications: rollback unit test naming scheme. Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
a643bd14be
commit
1db29eaea8
@ -20,7 +20,7 @@ extern int32_t desktop_srv(void* p);
|
||||
extern int32_t accessor_app(void* p);
|
||||
extern int32_t archive_app(void* p);
|
||||
extern int32_t blink_test_app(void* p);
|
||||
extern int32_t flipper_test_app(void* p);
|
||||
extern int32_t delay_test_app(void* p);
|
||||
extern int32_t gpio_app(void* p);
|
||||
extern int32_t ibutton_app(void* p);
|
||||
extern int32_t irda_app(void* p);
|
||||
@ -49,6 +49,7 @@ extern void nfc_cli_init();
|
||||
extern void storage_cli_init();
|
||||
extern void subghz_cli_init();
|
||||
extern void power_cli_init();
|
||||
extern void unit_tests_cli_init();
|
||||
|
||||
// Settings
|
||||
extern int32_t notification_settings_app(void* p);
|
||||
@ -183,6 +184,10 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = {
|
||||
#ifdef SRV_STORAGE
|
||||
storage_cli_init,
|
||||
#endif
|
||||
|
||||
#ifdef APP_UNIT_TESTS
|
||||
unit_tests_cli_init,
|
||||
#endif
|
||||
};
|
||||
|
||||
const size_t FLIPPER_ON_SYSTEM_START_COUNT =
|
||||
@ -220,10 +225,6 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
|
||||
{.app = usb_test_app, .name = "USB Test", .stack_size = 1024, .icon = &A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_UNIT_TESTS
|
||||
{.app = flipper_test_app, .name = "Unit Tests", .stack_size = 1024 * 8, .icon = &A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_IRDA_MONITOR
|
||||
{.app = irda_monitor_app, .name = "Irda Monitor", .stack_size = 1024, .icon = &A_Plugins_14},
|
||||
#endif
|
||||
@ -239,6 +240,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
|
||||
#ifdef SRV_BT
|
||||
{.app = bt_debug_app, .name = "Bluetooth Debug", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef APP_UNIT_TESTS
|
||||
{.app = delay_test_app, .name = "Delay Test App", .stack_size = 1024, .icon = &A_Plugins_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);
|
||||
|
@ -42,7 +42,6 @@ APP_BLINK = 1
|
||||
APP_IRDA_MONITOR = 1
|
||||
APP_KEYPAD_TEST = 1
|
||||
APP_SD_TEST = 1
|
||||
APP_UNIT_TESTS = 0
|
||||
APP_VIBRO_DEMO = 1
|
||||
APP_USB_TEST = 1
|
||||
endif
|
||||
@ -60,7 +59,7 @@ SRV_GUI = 1
|
||||
endif
|
||||
|
||||
|
||||
APP_UNIT_TESTS ?= 0
|
||||
APP_UNIT_TESTS ?= 0
|
||||
ifeq ($(APP_UNIT_TESTS), 1)
|
||||
CFLAGS += -DAPP_UNIT_TESTS
|
||||
endif
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "loader/loader.h"
|
||||
#include "loader_i.h"
|
||||
|
||||
#define LOADER_THREAD_FLAG_SHOW_MENU (1 << 0)
|
||||
@ -56,7 +57,7 @@ static void loader_cli_callback(Cli* cli, string_t args, void* _ctx) {
|
||||
furi_thread_start(loader_instance->thread);
|
||||
}
|
||||
|
||||
bool loader_start(Loader* instance, const char* name, const char* args) {
|
||||
LoaderStatus loader_start(Loader* instance, const char* name, const char* args) {
|
||||
furi_assert(name);
|
||||
|
||||
const FlipperApplication* flipper_app = NULL;
|
||||
@ -79,14 +80,15 @@ bool loader_start(Loader* instance, const char* name, const char* args) {
|
||||
|
||||
if(!flipper_app) {
|
||||
FURI_LOG_E(LOADER_LOG_TAG, "Can't find application with name %s", name);
|
||||
return false;
|
||||
return LoaderStatusErrorUnknownApp;
|
||||
}
|
||||
|
||||
loader_lock(instance);
|
||||
bool locked = loader_lock(instance);
|
||||
|
||||
if(furi_thread_get_state(instance->thread) != FuriThreadStateStopped) {
|
||||
if(!locked || (furi_thread_get_state(instance->thread) != FuriThreadStateStopped)) {
|
||||
FURI_LOG_E(LOADER_LOG_TAG, "Can't start app. %s is running", instance->current_app->name);
|
||||
return false;
|
||||
/* no need to call loader_unlock() - it is called as soon as application stops */
|
||||
return LoaderStatusErrorAppStarted;
|
||||
}
|
||||
|
||||
instance->current_app = flipper_app;
|
||||
@ -106,7 +108,8 @@ bool loader_start(Loader* instance, const char* name, const char* args) {
|
||||
furi_thread_set_context(instance->thread, thread_args);
|
||||
furi_thread_set_callback(instance->thread, flipper_app->app);
|
||||
|
||||
return furi_thread_start(instance->thread);
|
||||
bool thread_started = furi_thread_start(instance->thread);
|
||||
return thread_started ? LoaderStatusOk : LoaderStatusErrorInternal;
|
||||
}
|
||||
|
||||
bool loader_lock(Loader* instance) {
|
||||
@ -127,6 +130,10 @@ void loader_unlock(Loader* instance) {
|
||||
furi_check(osMutexRelease(instance->mutex) == osOK);
|
||||
}
|
||||
|
||||
bool loader_is_locked(Loader* instance) {
|
||||
return (instance->lock_semaphore > 0);
|
||||
}
|
||||
|
||||
static void loader_thread_state_callback(FuriThreadState thread_state, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
|
@ -4,12 +4,19 @@
|
||||
|
||||
typedef struct Loader Loader;
|
||||
|
||||
typedef enum {
|
||||
LoaderStatusOk,
|
||||
LoaderStatusErrorAppStarted,
|
||||
LoaderStatusErrorUnknownApp,
|
||||
LoaderStatusErrorInternal,
|
||||
} LoaderStatus;
|
||||
|
||||
/** Start application
|
||||
* @param name - application name
|
||||
* @param args - application arguments
|
||||
* @retval true on success
|
||||
*/
|
||||
bool loader_start(Loader* instance, const char* name, const char* args);
|
||||
LoaderStatus loader_start(Loader* instance, const char* name, const char* args);
|
||||
|
||||
/** Lock application start
|
||||
* @retval true on success
|
||||
@ -19,5 +26,8 @@ bool loader_lock(Loader* instance);
|
||||
/** Unlock application start */
|
||||
void loader_unlock(Loader* instance);
|
||||
|
||||
/** Get loader lock status */
|
||||
bool loader_is_locked(Loader* instance);
|
||||
|
||||
/** Show primary loader */
|
||||
void loader_show_menu();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "furi-hal-delay.h"
|
||||
#include "furi/check.h"
|
||||
#include "furi/log.h"
|
||||
#include <m-string.h>
|
||||
#include "pb.h"
|
||||
#include "pb_decode.h"
|
||||
#include "pb_encode.h"
|
||||
@ -42,6 +43,10 @@ static RpcSystemCallbacks rpc_systems[] = {
|
||||
.alloc = rpc_system_storage_alloc,
|
||||
.free = rpc_system_storage_free,
|
||||
},
|
||||
{
|
||||
.alloc = rpc_system_app_alloc,
|
||||
.free = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
struct RpcSession {
|
||||
@ -65,31 +70,28 @@ struct Rpc {
|
||||
|
||||
static bool content_callback(pb_istream_t* stream, const pb_field_t* field, void** arg);
|
||||
|
||||
static size_t rpc_sprint_msg_file(
|
||||
char* str,
|
||||
size_t str_size,
|
||||
static size_t rpc_sprintf_msg_file(
|
||||
string_t str,
|
||||
const char* prefix,
|
||||
const PB_Storage_File* msg_file,
|
||||
size_t msg_files_size) {
|
||||
size_t cnt = 0;
|
||||
|
||||
for(int i = 0; i < msg_files_size; ++i, ++msg_file) {
|
||||
cnt += snprintf(
|
||||
str + cnt,
|
||||
str_size - cnt,
|
||||
string_cat_printf(
|
||||
str,
|
||||
"%s[%c] size: %5ld",
|
||||
prefix,
|
||||
msg_file->type == PB_Storage_File_FileType_DIR ? 'd' : 'f',
|
||||
msg_file->size);
|
||||
|
||||
if(msg_file->name) {
|
||||
cnt += snprintf(str + cnt, str_size - cnt, " \'%s\'", msg_file->name);
|
||||
string_cat_printf(str, " \'%s\'", msg_file->name);
|
||||
}
|
||||
|
||||
if(msg_file->data && msg_file->data->size) {
|
||||
cnt += snprintf(
|
||||
str + cnt,
|
||||
str_size - cnt,
|
||||
string_cat_printf(
|
||||
str,
|
||||
" (%d):\'%.*s%s\'",
|
||||
msg_file->data->size,
|
||||
MIN(msg_file->data->size, 30),
|
||||
@ -97,23 +99,18 @@ static size_t rpc_sprint_msg_file(
|
||||
msg_file->data->size > 30 ? "..." : "");
|
||||
}
|
||||
|
||||
cnt += snprintf(str + cnt, str_size - cnt, "\r\n");
|
||||
string_cat_printf(str, "\r\n");
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#define ADD_STR(s, c, ...) snprintf(s + c, sizeof(s) - c, ##__VA_ARGS__);
|
||||
|
||||
#define ADD_STR_ELEMENT(s, c, ...) rpc_sprint_msg_file(s + c, sizeof(s) - c, ##__VA_ARGS__);
|
||||
|
||||
void rpc_print_message(const PB_Main* message) {
|
||||
char str[500];
|
||||
size_t cnt = 0;
|
||||
string_t str;
|
||||
string_init(str);
|
||||
|
||||
cnt += snprintf(
|
||||
str + cnt,
|
||||
sizeof(str) - cnt,
|
||||
string_cat_printf(
|
||||
str,
|
||||
"PB_Main: {\r\n\tresult: %d cmd_id: %ld (%s)\r\n",
|
||||
message->command_status,
|
||||
message->command_id,
|
||||
@ -121,88 +118,112 @@ void rpc_print_message(const PB_Main* message) {
|
||||
switch(message->which_content) {
|
||||
default:
|
||||
/* not implemented yet */
|
||||
cnt += ADD_STR(str, cnt, "\tNOT_IMPLEMENTED (%d) {\r\n", message->which_content);
|
||||
string_cat_printf(str, "\tNOT_IMPLEMENTED (%d) {\r\n", message->which_content);
|
||||
break;
|
||||
case PB_Main_app_start_tag: {
|
||||
string_cat_printf(str, "\tapp_start {\r\n");
|
||||
const char* name = message->content.app_start.name;
|
||||
const char* args = message->content.app_start.args;
|
||||
if(name) {
|
||||
string_cat_printf(str, "\t\tname: %s\r\n", name);
|
||||
}
|
||||
if(args) {
|
||||
string_cat_printf(str, "\t\targs: %s\r\n", args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_app_lock_status_request_tag: {
|
||||
string_cat_printf(str, "\tapp_lock_status_request {\r\n");
|
||||
break;
|
||||
}
|
||||
case PB_Main_app_lock_status_response_tag: {
|
||||
string_cat_printf(str, "\tapp_lock_status_response {\r\n");
|
||||
bool lock_status = message->content.app_lock_status_response.locked;
|
||||
string_cat_printf(str, "\t\tlocked: %s\r\n", lock_status ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_md5sum_request_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\tmd5sum_request {\r\n");
|
||||
string_cat_printf(str, "\tmd5sum_request {\r\n");
|
||||
const char* path = message->content.storage_md5sum_request.path;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tpath: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tpath: %s\r\n", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_md5sum_response_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\tmd5sum_response {\r\n");
|
||||
string_cat_printf(str, "\tmd5sum_response {\r\n");
|
||||
const char* path = message->content.storage_md5sum_response.md5sum;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tmd5sum: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tmd5sum: %s\r\n", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_ping_request_tag:
|
||||
cnt += ADD_STR(str, cnt, "\tping_request {\r\n");
|
||||
string_cat_printf(str, "\tping_request {\r\n");
|
||||
break;
|
||||
case PB_Main_ping_response_tag:
|
||||
cnt += ADD_STR(str, cnt, "\tping_response {\r\n");
|
||||
string_cat_printf(str, "\tping_response {\r\n");
|
||||
break;
|
||||
case PB_Main_storage_mkdir_request_tag:
|
||||
cnt += ADD_STR(str, cnt, "\tmkdir {\r\n");
|
||||
string_cat_printf(str, "\tmkdir {\r\n");
|
||||
break;
|
||||
case PB_Main_storage_delete_request_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\tdelete {\r\n");
|
||||
string_cat_printf(str, "\tdelete {\r\n");
|
||||
const char* path = message->content.storage_delete_request.path;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tpath: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tpath: %s\r\n", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_empty_tag:
|
||||
cnt += ADD_STR(str, cnt, "\tempty {\r\n");
|
||||
string_cat_printf(str, "\tempty {\r\n");
|
||||
break;
|
||||
case PB_Main_storage_list_request_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\tlist_request {\r\n");
|
||||
string_cat_printf(str, "\tlist_request {\r\n");
|
||||
const char* path = message->content.storage_list_request.path;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tpath: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tpath: %s\r\n", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_read_request_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\tread_request {\r\n");
|
||||
string_cat_printf(str, "\tread_request {\r\n");
|
||||
const char* path = message->content.storage_read_request.path;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tpath: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tpath: %s\r\n", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_write_request_tag: {
|
||||
cnt += ADD_STR(str, cnt, "\twrite_request {\r\n");
|
||||
string_cat_printf(str, "\twrite_request {\r\n");
|
||||
const char* path = message->content.storage_write_request.path;
|
||||
if(path) {
|
||||
cnt += ADD_STR(str, cnt, "\t\tpath: %s\r\n", path);
|
||||
string_cat_printf(str, "\t\tpath: %s\r\n", path);
|
||||
}
|
||||
if(message->content.storage_write_request.has_file) {
|
||||
const PB_Storage_File* msg_file = &message->content.storage_write_request.file;
|
||||
cnt += ADD_STR_ELEMENT(str, cnt, "\t\t\t", msg_file, 1);
|
||||
rpc_sprintf_msg_file(str, "\t\t\t", msg_file, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_read_response_tag:
|
||||
cnt += ADD_STR(str, cnt, "\tread_response {\r\n");
|
||||
string_cat_printf(str, "\tread_response {\r\n");
|
||||
if(message->content.storage_read_response.has_file) {
|
||||
const PB_Storage_File* msg_file = &message->content.storage_read_response.file;
|
||||
cnt += ADD_STR_ELEMENT(str, cnt, "\t\t\t", msg_file, 1);
|
||||
rpc_sprintf_msg_file(str, "\t\t\t", msg_file, 1);
|
||||
}
|
||||
break;
|
||||
case PB_Main_storage_list_response_tag: {
|
||||
const PB_Storage_File* msg_file = message->content.storage_list_response.file;
|
||||
size_t msg_file_count = message->content.storage_list_response.file_count;
|
||||
cnt += ADD_STR(str, cnt, "\tlist_response {\r\n");
|
||||
cnt += ADD_STR_ELEMENT(str, cnt, "\t\t", msg_file, msg_file_count);
|
||||
string_cat_printf(str, "\tlist_response {\r\n");
|
||||
rpc_sprintf_msg_file(str, "\t\t", msg_file, msg_file_count);
|
||||
}
|
||||
}
|
||||
cnt += ADD_STR(str, cnt, "\t}\r\n}\r\n");
|
||||
printf("%s", str);
|
||||
string_cat_printf(str, "\t}\r\n}\r\n");
|
||||
printf("%s", string_get_cstr(str));
|
||||
|
||||
string_clear(str);
|
||||
}
|
||||
|
||||
static Rpc* rpc_alloc(void) {
|
||||
@ -253,7 +274,6 @@ void rpc_close_session(RpcSession* session) {
|
||||
furi_assert(session->rpc);
|
||||
furi_assert(session->rpc->busy);
|
||||
|
||||
osMutexDelete(session->send_bytes_mutex);
|
||||
rpc_set_send_bytes_callback(session, NULL, NULL);
|
||||
osEventFlagsSet(session->rpc->events, RPC_EVENT_DISCONNECT);
|
||||
}
|
||||
@ -328,22 +348,31 @@ void rpc_encode_and_send(Rpc* rpc, PB_Main* main_message) {
|
||||
pb_encode_ex(&ostream, &PB_Main_msg, main_message, PB_ENCODE_DELIMITED);
|
||||
|
||||
{
|
||||
osMutexAcquire(session->send_bytes_mutex, osWaitForever);
|
||||
|
||||
#if DEBUG_PRINT
|
||||
printf("\r\nREPONSE DEC(%d): {", ostream.bytes_written);
|
||||
for(int i = 0; i < ostream.bytes_written; ++i) {
|
||||
printf("%d, ", buffer[i]);
|
||||
}
|
||||
printf("}\r\n");
|
||||
string_t str;
|
||||
string_init(str);
|
||||
string_reserve(str, 100 + ostream.bytes_written * 5);
|
||||
|
||||
printf("REPONSE HEX(%d): {", ostream.bytes_written);
|
||||
string_cat_printf(str, "\r\nREPONSE DEC(%d): {", ostream.bytes_written);
|
||||
for(int i = 0; i < ostream.bytes_written; ++i) {
|
||||
printf("%02X", buffer[i]);
|
||||
string_cat_printf(str, "%d, ", buffer[i]);
|
||||
}
|
||||
printf("}\r\n\r\n");
|
||||
string_cat_printf(str, "}\r\n");
|
||||
|
||||
printf("%s", string_get_cstr(str));
|
||||
string_clean(str);
|
||||
string_reserve(str, 100 + ostream.bytes_written * 3);
|
||||
|
||||
string_cat_printf(str, "REPONSE HEX(%d): {", ostream.bytes_written);
|
||||
for(int i = 0; i < ostream.bytes_written; ++i) {
|
||||
string_cat_printf(str, "%02X", buffer[i]);
|
||||
}
|
||||
string_cat_printf(str, "}\r\n\r\n");
|
||||
|
||||
printf("%s", string_get_cstr(str));
|
||||
#endif // DEBUG_PRINT
|
||||
|
||||
osMutexAcquire(session->send_bytes_mutex, osWaitForever);
|
||||
if(session->send_bytes_callback) {
|
||||
session->send_bytes_callback(
|
||||
session->send_bytes_context, buffer, ostream.bytes_written);
|
||||
@ -408,6 +437,7 @@ int32_t rpc_srv(void* p) {
|
||||
}
|
||||
}
|
||||
free(session->system_contexts);
|
||||
osMutexDelete(session->send_bytes_mutex);
|
||||
RpcHandlerDict_clean(rpc->handlers);
|
||||
rpc->busy = false;
|
||||
} else {
|
||||
|
78
applications/rpc/rpc_app.c
Normal file
78
applications/rpc/rpc_app.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include "flipper.pb.h"
|
||||
#include "furi/record.h"
|
||||
#include "status.pb.h"
|
||||
#include "rpc_i.h"
|
||||
#include <furi.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
void rpc_system_app_start_process(const PB_Main* request, void* context) {
|
||||
Rpc* rpc = context;
|
||||
furi_assert(rpc);
|
||||
furi_assert(request);
|
||||
furi_assert(request->which_content == PB_Main_app_start_tag);
|
||||
PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
|
||||
|
||||
Loader* loader = furi_record_open("loader");
|
||||
const char* app_name = request->content.app_start.name;
|
||||
if(app_name) {
|
||||
const char* app_args = request->content.app_start.args;
|
||||
LoaderStatus status = loader_start(loader, app_name, app_args);
|
||||
if(status == LoaderStatusErrorAppStarted) {
|
||||
result = PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED;
|
||||
} else if(status == LoaderStatusErrorInternal) {
|
||||
result = PB_CommandStatus_ERROR_APP_CANT_START;
|
||||
} else if(status == LoaderStatusErrorUnknownApp) {
|
||||
result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||
} else if(status == LoaderStatusOk) {
|
||||
result = PB_CommandStatus_OK;
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
} else {
|
||||
result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
furi_record_close("loader");
|
||||
|
||||
rpc_encode_and_send_empty(rpc, request->command_id, result);
|
||||
}
|
||||
|
||||
void rpc_system_app_lock_status_process(const PB_Main* request, void* context) {
|
||||
Rpc* rpc = context;
|
||||
furi_assert(rpc);
|
||||
furi_assert(request);
|
||||
furi_assert(request->which_content == PB_Main_app_lock_status_request_tag);
|
||||
|
||||
Loader* loader = furi_record_open("loader");
|
||||
|
||||
PB_Main response = {
|
||||
.has_next = false,
|
||||
.command_status = PB_CommandStatus_OK,
|
||||
.command_id = request->command_id,
|
||||
.which_content = PB_Main_app_lock_status_response_tag,
|
||||
};
|
||||
|
||||
response.content.app_lock_status_response.locked = loader_is_locked(loader);
|
||||
|
||||
furi_record_close("loader");
|
||||
|
||||
rpc_encode_and_send(rpc, &response);
|
||||
}
|
||||
|
||||
void* rpc_system_app_alloc(Rpc* rpc) {
|
||||
furi_assert(rpc);
|
||||
|
||||
RpcHandler rpc_handler = {
|
||||
.message_handler = NULL,
|
||||
.decode_submessage = NULL,
|
||||
.context = rpc,
|
||||
};
|
||||
|
||||
rpc_handler.message_handler = rpc_system_app_start_process;
|
||||
rpc_add_handler(rpc, PB_Main_app_start_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_system_app_lock_status_process;
|
||||
rpc_add_handler(rpc, PB_Main_app_lock_status_request_tag, &rpc_handler);
|
||||
|
||||
return NULL;
|
||||
}
|
@ -22,4 +22,6 @@ void rpc_add_handler(Rpc* rpc, pb_size_t message_tag, RpcHandler* handler);
|
||||
void* rpc_system_status_alloc(Rpc* rpc);
|
||||
void* rpc_system_storage_alloc(Rpc* rpc);
|
||||
void rpc_system_storage_free(void* ctx);
|
||||
void* rpc_system_app_alloc(Rpc* rpc);
|
||||
|
||||
void rpc_print_message(const PB_Main* message);
|
||||
|
@ -340,6 +340,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
||||
|
||||
char* md5sum = response.content.storage_md5sum_response.md5sum;
|
||||
size_t md5sum_size = sizeof(response.content.storage_md5sum_response.md5sum);
|
||||
(void)md5sum_size;
|
||||
furi_assert(hash_size <= ((md5sum_size - 1) / 2));
|
||||
for(uint8_t i = 0; i < hash_size; i++) {
|
||||
md5sum += sprintf(md5sum, "%02x", hash[i]);
|
||||
|
@ -41,7 +41,7 @@ static uint32_t subghz_frequency_analyzer_worker_expRunningAverageAdaptive(
|
||||
static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
SubGhzFrequencyAnalyzerWorker* instance = context;
|
||||
|
||||
FrequencyRSSI frequency_rssi;
|
||||
FrequencyRSSI frequency_rssi = {.frequency = 0, .rssi = 0};
|
||||
float rssi;
|
||||
uint32_t frequency;
|
||||
uint32_t frequency_start;
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <pb_encode.h>
|
||||
#include <m-list.h>
|
||||
#include <lib/toolbox/md5.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
||||
#define M_OPL_MsgList_t() LIST_OPLIST(MsgList)
|
||||
@ -108,6 +110,7 @@ static void clean_directory(Storage* fs_api, const char* clean_dir) {
|
||||
free(name);
|
||||
} else {
|
||||
FS_Error error = storage_common_mkdir(fs_api, clean_dir);
|
||||
(void)error;
|
||||
furi_assert(error == FSE_OK);
|
||||
}
|
||||
|
||||
@ -172,6 +175,7 @@ static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size
|
||||
StreamBufferHandle_t stream_buffer = ctx;
|
||||
|
||||
size_t bytes_sent = xStreamBufferSend(stream_buffer, got_bytes, got_size, osWaitForever);
|
||||
(void)bytes_sent;
|
||||
furi_assert(bytes_sent == got_size);
|
||||
}
|
||||
|
||||
@ -346,6 +350,12 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
||||
/* rpc doesn't send it */
|
||||
mu_check(0);
|
||||
break;
|
||||
case PB_Main_app_lock_status_response_tag: {
|
||||
bool result_locked = result->content.app_lock_status_response.locked;
|
||||
bool expected_locked = expected->content.app_lock_status_response.locked;
|
||||
mu_check(result_locked == expected_locked);
|
||||
break;
|
||||
}
|
||||
case PB_Main_storage_read_response_tag: {
|
||||
bool result_has_msg_file = result->content.storage_read_response.has_file;
|
||||
bool expected_has_msg_file = expected->content.storage_read_response.has_file;
|
||||
@ -588,6 +598,7 @@ static void test_storage_read_run(const char* path, uint32_t command_id) {
|
||||
static void test_create_dir(const char* path) {
|
||||
Storage* fs_api = furi_record_open("storage");
|
||||
FS_Error error = storage_common_mkdir(fs_api, path);
|
||||
(void)error;
|
||||
furi_assert((error == FSE_OK) || (error == FSE_EXIST));
|
||||
furi_record_close("storage");
|
||||
}
|
||||
@ -717,7 +728,7 @@ MU_TEST(test_storage_write) {
|
||||
++command_id,
|
||||
PB_CommandStatus_ERROR_STORAGE_NOT_EXIST);
|
||||
test_storage_write_run(TEST_DIR "test2.txt", 1, 50, ++command_id, PB_CommandStatus_OK);
|
||||
test_storage_write_run(TEST_DIR "test2.txt", 4096, 1, ++command_id, PB_CommandStatus_OK);
|
||||
test_storage_write_run(TEST_DIR "test2.txt", 512, 3, ++command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
MU_TEST(test_storage_interrupt_continuous_same_system) {
|
||||
@ -866,6 +877,7 @@ MU_TEST(test_storage_mkdir) {
|
||||
|
||||
Storage* fs_api = furi_record_open("storage");
|
||||
FS_Error error = storage_common_remove(fs_api, TEST_DIR "dir1");
|
||||
(void)error;
|
||||
furi_assert(error == FSE_OK);
|
||||
furi_record_close("storage");
|
||||
|
||||
@ -1018,10 +1030,134 @@ MU_TEST_SUITE(test_rpc_storage) {
|
||||
MU_RUN_TEST(test_storage_interrupt_continuous_another_system);
|
||||
}
|
||||
|
||||
static void test_app_create_request(
|
||||
PB_Main* request,
|
||||
const char* app_name,
|
||||
const char* app_args,
|
||||
uint32_t command_id) {
|
||||
request->command_id = command_id;
|
||||
request->command_status = PB_CommandStatus_OK;
|
||||
request->cb_content.funcs.encode = NULL;
|
||||
request->which_content = PB_Main_app_start_tag;
|
||||
request->has_next = false;
|
||||
|
||||
if(app_name) {
|
||||
char* msg_app_name = furi_alloc(strlen(app_name) + 1);
|
||||
strcpy(msg_app_name, app_name);
|
||||
request->content.app_start.name = msg_app_name;
|
||||
} else {
|
||||
request->content.app_start.name = NULL;
|
||||
}
|
||||
|
||||
if(app_args) {
|
||||
char* msg_app_args = furi_alloc(strlen(app_args) + 1);
|
||||
strcpy(msg_app_args, app_args);
|
||||
request->content.app_start.args = msg_app_args;
|
||||
} else {
|
||||
request->content.app_start.args = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_app_start_run(
|
||||
const char* app_name,
|
||||
const char* app_args,
|
||||
PB_CommandStatus status,
|
||||
uint32_t command_id) {
|
||||
PB_Main request;
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_app_create_request(&request, app_name, app_args, command_id);
|
||||
test_rpc_add_empty_to_list(expected_msg_list, status, command_id);
|
||||
|
||||
test_rpc_encode_and_feed_one(&request);
|
||||
test_rpc_decode_and_compare(expected_msg_list);
|
||||
|
||||
pb_release(&PB_Main_msg, &request);
|
||||
test_rpc_free_msg_list(expected_msg_list);
|
||||
}
|
||||
|
||||
static void test_app_get_status_lock_run(bool locked_expected, uint32_t command_id) {
|
||||
PB_Main request = {
|
||||
.command_id = command_id,
|
||||
.command_status = PB_CommandStatus_OK,
|
||||
.which_content = PB_Main_app_lock_status_request_tag,
|
||||
.has_next = false,
|
||||
};
|
||||
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
PB_Main* response = MsgList_push_new(expected_msg_list);
|
||||
response->command_id = command_id;
|
||||
response->command_status = PB_CommandStatus_OK;
|
||||
response->which_content = PB_Main_app_lock_status_response_tag;
|
||||
response->has_next = false;
|
||||
response->content.app_lock_status_response.locked = locked_expected;
|
||||
|
||||
test_rpc_encode_and_feed_one(&request);
|
||||
test_rpc_decode_and_compare(expected_msg_list);
|
||||
|
||||
pb_release(&PB_Main_msg, &request);
|
||||
test_rpc_free_msg_list(expected_msg_list);
|
||||
}
|
||||
|
||||
MU_TEST(test_app_start_and_lock_status) {
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
test_app_start_run(NULL, "/ext/file", PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id);
|
||||
test_app_start_run(NULL, NULL, PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id);
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
test_app_start_run(
|
||||
"skynet_destroy_world_app", NULL, PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id);
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
|
||||
test_app_start_run("Delay Test App", "0", PB_CommandStatus_OK, ++command_id);
|
||||
delay(100);
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
|
||||
test_app_start_run("Delay Test App", "200", PB_CommandStatus_OK, ++command_id);
|
||||
test_app_get_status_lock_run(true, ++command_id);
|
||||
delay(100);
|
||||
test_app_get_status_lock_run(true, ++command_id);
|
||||
test_app_start_run(
|
||||
"Delay Test App", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id);
|
||||
delay(200);
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
|
||||
test_app_start_run("Delay Test App", "500", PB_CommandStatus_OK, ++command_id);
|
||||
delay(100);
|
||||
test_app_get_status_lock_run(true, ++command_id);
|
||||
test_app_start_run("Infrared", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id);
|
||||
delay(100);
|
||||
test_app_get_status_lock_run(true, ++command_id);
|
||||
test_app_start_run(
|
||||
"2_girls_1_app", "0", PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id);
|
||||
delay(100);
|
||||
test_app_get_status_lock_run(true, ++command_id);
|
||||
delay(500);
|
||||
test_app_get_status_lock_run(false, ++command_id);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_rpc_app) {
|
||||
MU_SUITE_CONFIGURE(&test_rpc_storage_setup, &test_rpc_storage_teardown);
|
||||
|
||||
MU_RUN_TEST(test_app_start_and_lock_status);
|
||||
}
|
||||
|
||||
int run_minunit_test_rpc() {
|
||||
MU_RUN_SUITE(test_rpc_storage);
|
||||
MU_RUN_SUITE(test_rpc_status);
|
||||
MU_RUN_SUITE(test_rpc_app);
|
||||
MU_REPORT();
|
||||
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
||||
int32_t delay_test_app(void* p) {
|
||||
int timeout = atoi((const char*)p);
|
||||
|
||||
if(timeout > 0) {
|
||||
delay(timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,33 +1,51 @@
|
||||
#include "m-string.h"
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include "minunit_vars.h"
|
||||
#include <notification/notification-messages.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
int run_minunit();
|
||||
int run_minunit_test_irda_decoder_encoder();
|
||||
int run_minunit_test_rpc();
|
||||
|
||||
int32_t flipper_test_app(void* p) {
|
||||
void unit_tests_cli(Cli* cli, string_t args, void* context) {
|
||||
uint32_t test_result = 0;
|
||||
minunit_run = 0;
|
||||
minunit_assert = 0;
|
||||
minunit_fail = 0;
|
||||
minunit_status = 0;
|
||||
|
||||
Loader* loader = furi_record_open("loader");
|
||||
furi_record_close("loader");
|
||||
|
||||
NotificationApp* notification = furi_record_open("notification");
|
||||
|
||||
notification_message_block(notification, &sequence_set_only_blue_255);
|
||||
|
||||
// test_result |= run_minunit(); // disabled as it fails randomly
|
||||
test_result |= run_minunit_test_irda_decoder_encoder();
|
||||
test_result |= run_minunit_test_rpc();
|
||||
|
||||
if(test_result == 0) {
|
||||
// test passed
|
||||
notification_message(notification, &sequence_success);
|
||||
} else {
|
||||
// test failed
|
||||
notification_message(notification, &sequence_error);
|
||||
}
|
||||
|
||||
furi_record_close("notification");
|
||||
|
||||
return 0;
|
||||
if(loader_is_locked(loader)) {
|
||||
FURI_LOG_E("UNIT_TESTS", "RPC: stop all applications to run tests");
|
||||
notification_message(notification, &sequence_blink_magenta_100);
|
||||
} else {
|
||||
notification_message_block(notification, &sequence_set_only_blue_255);
|
||||
|
||||
test_result |= run_minunit();
|
||||
test_result |= run_minunit_test_irda_decoder_encoder();
|
||||
test_result |= run_minunit_test_rpc();
|
||||
|
||||
if(test_result == 0) {
|
||||
notification_message(notification, &sequence_success);
|
||||
FURI_LOG_I("UNIT_TESTS", "PASSED");
|
||||
} else {
|
||||
notification_message(notification, &sequence_error);
|
||||
FURI_LOG_E("UNIT_TESTS", "FAILED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unit_tests_cli_init() {
|
||||
Cli* cli = furi_record_open("cli");
|
||||
cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL);
|
||||
furi_record_close("cli");
|
||||
}
|
||||
|
18
assets/compiled/application.pb.c
Normal file
18
assets/compiled/application.pb.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#include "application.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(PB_App_Start, PB_App_Start, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_App_LockStatusRequest, PB_App_LockStatusRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_App_LockStatusResponse, PB_App_LockStatusResponse, AUTO)
|
||||
|
||||
|
||||
|
79
assets/compiled/application.pb.h
Normal file
79
assets/compiled/application.pb.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_PB_APP_APPLICATION_PB_H_INCLUDED
|
||||
#define PB_PB_APP_APPLICATION_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _PB_App_LockStatusRequest {
|
||||
char dummy_field;
|
||||
} PB_App_LockStatusRequest;
|
||||
|
||||
typedef struct _PB_App_Start {
|
||||
char *name;
|
||||
char *args;
|
||||
} PB_App_Start;
|
||||
|
||||
typedef struct _PB_App_LockStatusResponse {
|
||||
bool locked;
|
||||
} PB_App_LockStatusResponse;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define PB_App_Start_init_default {NULL, NULL}
|
||||
#define PB_App_LockStatusRequest_init_default {0}
|
||||
#define PB_App_LockStatusResponse_init_default {0}
|
||||
#define PB_App_Start_init_zero {NULL, NULL}
|
||||
#define PB_App_LockStatusRequest_init_zero {0}
|
||||
#define PB_App_LockStatusResponse_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define PB_App_Start_name_tag 1
|
||||
#define PB_App_Start_args_tag 2
|
||||
#define PB_App_LockStatusResponse_locked_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define PB_App_Start_FIELDLIST(X, a) \
|
||||
X(a, POINTER, SINGULAR, STRING, name, 1) \
|
||||
X(a, POINTER, SINGULAR, STRING, args, 2)
|
||||
#define PB_App_Start_CALLBACK NULL
|
||||
#define PB_App_Start_DEFAULT NULL
|
||||
|
||||
#define PB_App_LockStatusRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PB_App_LockStatusRequest_CALLBACK NULL
|
||||
#define PB_App_LockStatusRequest_DEFAULT NULL
|
||||
|
||||
#define PB_App_LockStatusResponse_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, locked, 1)
|
||||
#define PB_App_LockStatusResponse_CALLBACK NULL
|
||||
#define PB_App_LockStatusResponse_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t PB_App_Start_msg;
|
||||
extern const pb_msgdesc_t PB_App_LockStatusRequest_msg;
|
||||
extern const pb_msgdesc_t PB_App_LockStatusResponse_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define PB_App_Start_fields &PB_App_Start_msg
|
||||
#define PB_App_LockStatusRequest_fields &PB_App_LockStatusRequest_msg
|
||||
#define PB_App_LockStatusResponse_fields &PB_App_LockStatusResponse_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* PB_App_Start_size depends on runtime parameters */
|
||||
#define PB_App_LockStatusRequest_size 0
|
||||
#define PB_App_LockStatusResponse_size 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#include <pb.h>
|
||||
#include "storage.pb.h"
|
||||
#include "status.pb.h"
|
||||
#include "application.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
@ -28,7 +29,9 @@ typedef enum _PB_CommandStatus {
|
||||
PB_CommandStatus_ERROR_STORAGE_INVALID_NAME = 10, /* *< Invalid name/path */
|
||||
PB_CommandStatus_ERROR_STORAGE_INTERNAL = 11, /* *< Internal error */
|
||||
PB_CommandStatus_ERROR_STORAGE_NOT_IMPLEMENTED = 12, /* *< Functon not implemented */
|
||||
PB_CommandStatus_ERROR_STORAGE_ALREADY_OPEN = 13 /* *< File/Dir already opened */
|
||||
PB_CommandStatus_ERROR_STORAGE_ALREADY_OPEN = 13, /* *< File/Dir already opened */
|
||||
PB_CommandStatus_ERROR_APP_CANT_START = 16, /* *< Can't start app - either wrong name, or internal error */
|
||||
PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17 /* *< Another app is running */
|
||||
} PB_CommandStatus;
|
||||
|
||||
/* Struct definitions */
|
||||
@ -58,14 +61,17 @@ typedef struct _PB_Main {
|
||||
PB_Storage_MkdirRequest storage_mkdir_request;
|
||||
PB_Storage_Md5sumRequest storage_md5sum_request;
|
||||
PB_Storage_Md5sumResponse storage_md5sum_response;
|
||||
PB_App_Start app_start;
|
||||
PB_App_LockStatusRequest app_lock_status_request;
|
||||
PB_App_LockStatusResponse app_lock_status_response;
|
||||
} content;
|
||||
} PB_Main;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _PB_CommandStatus_MIN PB_CommandStatus_OK
|
||||
#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_INVALID_PARAMETERS
|
||||
#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_INVALID_PARAMETERS+1))
|
||||
#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED
|
||||
#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -94,6 +100,9 @@ extern "C" {
|
||||
#define PB_Main_storage_mkdir_request_tag 13
|
||||
#define PB_Main_storage_md5sum_request_tag 14
|
||||
#define PB_Main_storage_md5sum_response_tag 15
|
||||
#define PB_Main_app_start_tag 16
|
||||
#define PB_Main_app_lock_status_request_tag 17
|
||||
#define PB_Main_app_lock_status_response_tag 18
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define PB_Empty_FIELDLIST(X, a) \
|
||||
@ -116,7 +125,10 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_write_request,content.storag
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_delete_request,content.storage_delete_request), 12) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_mkdir_request,content.storage_mkdir_request), 13) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_request,content.storage_md5sum_request), 14) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_response,content.storage_md5sum_response), 15)
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_response,content.storage_md5sum_response), 15) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,app_start,content.app_start), 16) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_request,content.app_lock_status_request), 17) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_response,content.app_lock_status_response), 18)
|
||||
#define PB_Main_CALLBACK NULL
|
||||
#define PB_Main_DEFAULT NULL
|
||||
#define PB_Main_content_empty_MSGTYPE PB_Empty
|
||||
@ -131,6 +143,9 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_response,content.stor
|
||||
#define PB_Main_content_storage_mkdir_request_MSGTYPE PB_Storage_MkdirRequest
|
||||
#define PB_Main_content_storage_md5sum_request_MSGTYPE PB_Storage_Md5sumRequest
|
||||
#define PB_Main_content_storage_md5sum_response_MSGTYPE PB_Storage_Md5sumResponse
|
||||
#define PB_Main_content_app_start_MSGTYPE PB_App_Start
|
||||
#define PB_Main_content_app_lock_status_request_MSGTYPE PB_App_LockStatusRequest
|
||||
#define PB_Main_content_app_lock_status_response_MSGTYPE PB_App_LockStatusResponse
|
||||
|
||||
extern const pb_msgdesc_t PB_Empty_msg;
|
||||
extern const pb_msgdesc_t PB_Main_msg;
|
||||
@ -141,9 +156,9 @@ extern const pb_msgdesc_t PB_Main_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define PB_Empty_size 0
|
||||
#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size)
|
||||
#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_Start_size)
|
||||
#define PB_Main_size (10 + sizeof(union PB_Main_content_size_union))
|
||||
union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f0[36];};
|
||||
union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_Start_size)]; char f0[36];};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 41599b8e6a6b33a229e8f5fa58de1a2cfcc8184a
|
||||
Subproject commit 8e6db414beed5aff0902f2cca2f4146a0dffb7a1
|
@ -56,7 +56,7 @@ void subghz_protocol_came_twee_free(SubGhzProtocolCameTwee* instance) {
|
||||
LevelDuration subghz_protocol_came_twee_add_duration_to_upload(
|
||||
SubGhzProtocolCameTwee* instance,
|
||||
ManchesterEncoderResult result) {
|
||||
LevelDuration data;
|
||||
LevelDuration data = {.duration = 0, .level = 0};
|
||||
switch(result) {
|
||||
case ManchesterEncoderResultShortLow:
|
||||
data.duration = instance->common.te_short;
|
||||
|
Loading…
Reference in New Issue
Block a user