diff options
author | Skorpionm <85568270+Skorpionm@users.noreply.github.com> | 2021-12-08 16:42:01 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-08 16:42:01 +0300 |
commit | f0aed7e58331557fe41b7617b8dff49b63645f40 (patch) | |
tree | d9f0365ea6846a3c9909f8de4c8ba66ca967b7b3 /applications/subghz | |
parent | 7170864fe41f783ea84892f2e326ab120e2ee446 (diff) |
SubGhz: add GFSK modulation, refactoring subghz_chat (#866)
* SubGhz: add GFSK modulation, refactoring subghz_chat
* SubGhz: off echo subghz_chat
* SubGhz: subghz_chat add sending and receiving formatted text, translation of the chat to events
* SubGhz: add UTF support in subghz_chat_worker_alloc
Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/subghz')
-rw-r--r-- | applications/subghz/helpers/subghz_chat.c | 141 | ||||
-rw-r--r-- | applications/subghz/helpers/subghz_chat.h | 29 | ||||
-rw-r--r-- | applications/subghz/subghz_cli.c | 157 |
3 files changed, 279 insertions, 48 deletions
diff --git a/applications/subghz/helpers/subghz_chat.c b/applications/subghz/helpers/subghz_chat.c new file mode 100644 index 00000000..15e08dde --- /dev/null +++ b/applications/subghz/helpers/subghz_chat.c @@ -0,0 +1,141 @@ +#include "subghz_chat.h" +#include <lib/subghz/subghz_tx_rx_worker.h> + +#define TAG "SubGhzChat" +#define SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES 500 + +struct SubGhzChatWorker { + FuriThread* thread; + SubGhzTxRxWorker* subghz_txrx; + + volatile bool worker_running; + volatile bool worker_stoping; + osMessageQueueId_t event_queue; + uint32_t last_time_rx_data; +}; + +/** Worker thread + * + * @param context + * @return exit code + */ +static int32_t subghz_chat_worker_thread(void* context) { + SubGhzChatWorker* instance = context; + FURI_LOG_I(TAG, "Worker start"); + char c; + SubghzChatEvent event; + event.event = SubghzChatEventUserEntrance; + osMessageQueuePut(instance->event_queue, &event, 0, 0); + while(instance->worker_running) { + if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, osWaitForever) == 1) { + event.event = SubghzChatEventInputData; + event.c = c; + osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); + } + } + + FURI_LOG_I(TAG, "Worker stop"); + return 0; +} + +static void subghz_chat_worker_update_rx_event_chat(void* context) { + furi_assert(context); + SubGhzChatWorker* instance = context; + SubghzChatEvent event; + if((millis() - instance->last_time_rx_data) > SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES) { + event.event = SubghzChatEventNewMessage; + osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); + } + instance->last_time_rx_data = millis(); + event.event = SubghzChatEventRXData; + osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); +} + +SubGhzChatWorker* subghz_chat_worker_alloc() { + SubGhzChatWorker* instance = furi_alloc(sizeof(SubGhzChatWorker)); + + instance->thread = furi_thread_alloc(); + furi_thread_set_name(instance->thread, "SubghzChat"); + furi_thread_set_stack_size(instance->thread, 2048); + furi_thread_set_context(instance->thread, instance); + furi_thread_set_callback(instance->thread, subghz_chat_worker_thread); + instance->subghz_txrx = subghz_tx_rx_worker_alloc(); + instance->event_queue = osMessageQueueNew(80, sizeof(SubghzChatEvent), NULL); + return instance; +} + +void subghz_chat_worker_free(SubGhzChatWorker* instance) { + furi_assert(instance); + furi_assert(!instance->worker_running); + osMessageQueueDelete(instance->event_queue); + subghz_tx_rx_worker_free(instance->subghz_txrx); + furi_thread_free(instance->thread); + + free(instance); +} + +bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) { + furi_assert(instance); + furi_assert(!instance->worker_running); + bool res = false; + + if(subghz_tx_rx_worker_start(instance->subghz_txrx, frequency)) { + osMessageQueueReset(instance->event_queue); + subghz_tx_rx_worker_set_callback_have_read( + instance->subghz_txrx, subghz_chat_worker_update_rx_event_chat, instance); + + instance->worker_running = true; + instance->last_time_rx_data = 0; + + res = furi_thread_start(instance->thread); + } + return res; +} + +void subghz_chat_worker_stop(SubGhzChatWorker* instance) { + furi_assert(instance); + furi_assert(instance->worker_running); + if(subghz_tx_rx_worker_is_running(instance->subghz_txrx)) { + subghz_tx_rx_worker_stop(instance->subghz_txrx); + } + + instance->worker_running = false; + + furi_thread_join(instance->thread); +} + +bool subghz_chat_worker_is_running(SubGhzChatWorker* instance) { + furi_assert(instance); + return instance->worker_running; +} + +SubghzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance) { + furi_assert(instance); + SubghzChatEvent event; + if(osMessageQueueGet(instance->event_queue, &event, NULL, osWaitForever) == osOK) { + return event; + } else { + event.event = SubghzChatEventNoEvent; + return event; + } +} + +void subghz_chat_worker_put_event_chat(SubGhzChatWorker* instance, SubghzChatEvent* event) { + furi_assert(instance); + osMessageQueuePut(instance->event_queue, event, 0, osWaitForever); +} + +size_t subghz_chat_worker_available(SubGhzChatWorker* instance) { + furi_assert(instance); + return subghz_tx_rx_worker_available(instance->subghz_txrx); +} + +size_t subghz_chat_worker_read(SubGhzChatWorker* instance, uint8_t* data, size_t size) { + furi_assert(instance); + return subghz_tx_rx_worker_read(instance->subghz_txrx, data, size); +} + +bool subghz_chat_worker_write(SubGhzChatWorker* instance, uint8_t* data, size_t size) { + furi_assert(instance); + return subghz_tx_rx_worker_write(instance->subghz_txrx, data, size); +}
\ No newline at end of file diff --git a/applications/subghz/helpers/subghz_chat.h b/applications/subghz/helpers/subghz_chat.h new file mode 100644 index 00000000..89f82ef3 --- /dev/null +++ b/applications/subghz/helpers/subghz_chat.h @@ -0,0 +1,29 @@ +#pragma once +#include "../subghz_i.h" + +typedef struct SubGhzChatWorker SubGhzChatWorker; + +typedef enum { + SubghzChatEventNoEvent, + SubghzChatEventUserEntrance, + SubghzChatEventUserExit, + SubghzChatEventInputData, + SubghzChatEventRXData, + SubghzChatEventNewMessage, +} SubghzChatEventType; + +typedef struct { + SubghzChatEventType event; + char c; +} SubghzChatEvent; + +SubGhzChatWorker* subghz_chat_worker_alloc(); +void subghz_chat_worker_free(SubGhzChatWorker* instance); +bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency); +void subghz_chat_worker_stop(SubGhzChatWorker* instance); +bool subghz_chat_worker_is_running(SubGhzChatWorker* instance); +SubghzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance); +void subghz_chat_worker_put_event_chat(SubGhzChatWorker* instance, SubghzChatEvent* event); +size_t subghz_chat_worker_available(SubGhzChatWorker* instance); +size_t subghz_chat_worker_read(SubGhzChatWorker* instance, uint8_t* data, size_t size); +bool subghz_chat_worker_write(SubGhzChatWorker* instance, uint8_t* data, size_t size); diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 2578fb26..2f9d698e 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -9,7 +9,8 @@ #include <lib/subghz/subghz_keystore.h> #include <lib/subghz/protocols/subghz_protocol_common.h> #include <lib/subghz/protocols/subghz_protocol_princeton.h> -#include <lib/subghz/subghz_tx_rx_worker.h> + +#include "helpers/subghz_chat.h" #include <notification/notification-messages.h> @@ -377,23 +378,34 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { return; } - SubGhzTxRxWorker* subghz_txrx = subghz_tx_rx_worker_alloc(); - subghz_tx_rx_worker_start(subghz_txrx, frequency); + SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(); + if(!subghz_chat_worker_start(subghz_chat, frequency)) { + printf("Startup error SubGhzChatWorker\r\n"); + + if(subghz_chat_worker_is_running(subghz_chat)) { + subghz_chat_worker_stop(subghz_chat); + subghz_chat_worker_free(subghz_chat); + } + return; + } printf("Receiving at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); furi_hal_power_suppress_charge_enter(); + size_t message_max_len = 64; uint8_t message[64] = {0}; string_t input; string_init(input); string_t name; string_init(name); + string_t output; + string_init(output); string_t sysmsg; string_init(sysmsg); - char c; bool exit = false; + SubghzChatEvent chat_event; NotificationApp* notification = furi_record_open("notification"); @@ -402,71 +414,120 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { printf("%s", string_get_cstr(input)); fflush(stdout); - string_printf(sysmsg, "\033[0;34m%s joined chat.\033[0m", furi_hal_version_get_name_ptr()); - subghz_tx_rx_worker_write( - subghz_txrx, (uint8_t*)string_get_cstr(sysmsg), strlen(string_get_cstr(sysmsg))); - while(!exit) { - if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) { - if(c == CliSymbolAsciiETX) { + chat_event = subghz_chat_worker_get_event_chat(subghz_chat); + switch(chat_event.event) { + case SubghzChatEventInputData: + if(chat_event.c == CliSymbolAsciiETX) { printf("\r\n"); - exit = true; + chat_event.event = SubghzChatEventUserExit; + subghz_chat_worker_put_event_chat(subghz_chat, &chat_event); break; - } else if((c >= 0x20 && c < 0x7F) || (c >= 0x80 && c < 0xF0)) { - putc(c, stdout); - fflush(stdout); - string_push_back(input, c); - } else if((c == CliSymbolAsciiBackspace) || (c == CliSymbolAsciiDel)) { - size_t len = string_size(input); - if(len > string_size(name)) { + } else if( + (chat_event.c == CliSymbolAsciiBackspace) || (chat_event.c == CliSymbolAsciiDel)) { + size_t len = string_length_u(input); + if(len > string_length_u(name)) { printf("%s", "\e[D\e[1P"); fflush(stdout); - string_set_strn(input, string_get_cstr(input), len - 1); + //delete 1 char UTF + const char* str = string_get_cstr(input); + size_t size = 0; + m_str1ng_utf8_state_e s = M_STRING_UTF8_STARTING; + string_unicode_t u = 0; + string_reset(sysmsg); + while(*str) { + m_str1ng_utf8_decode(*str, &s, &u); + if((s == M_STRING_UTF8_ERROR) || s == M_STRING_UTF8_STARTING) { + string_push_u(sysmsg, u); + if(++size >= len - 1) break; + s = M_STRING_UTF8_STARTING; + } + str++; + } + string_set(input, sysmsg); } - } else if(c == CliSymbolAsciiCR) { + } else if(chat_event.c == CliSymbolAsciiCR) { printf("\r\n"); - subghz_tx_rx_worker_write( - subghz_txrx, (uint8_t*)string_get_cstr(input), strlen(string_get_cstr(input))); + string_push_back(input, '\r'); + string_push_back(input, '\n'); + while(!subghz_chat_worker_write( + subghz_chat, + (uint8_t*)string_get_cstr(input), + strlen(string_get_cstr(input)))) { + delay(10); + } + string_printf(input, "%s", string_get_cstr(name)); printf("%s", string_get_cstr(input)); fflush(stdout); + } else if(chat_event.c == CliSymbolAsciiLF) { + //cut out the symbol \n + } else { + putc(chat_event.c, stdout); + fflush(stdout); + string_push_back(input, chat_event.c); + break; + case SubghzChatEventRXData: + do { + memset(message, 0x00, message_max_len); + size_t len = subghz_chat_worker_read(subghz_chat, message, message_max_len); + for(size_t i = 0; i < len; i++) { + string_push_back(output, message[i]); + if(message[i] == '\n') { + printf("\r"); + for(uint8_t i = 0; i < 80; i++) { + printf(" "); + } + printf("\r %s", string_get_cstr(output)); + printf("%s", string_get_cstr(input)); + fflush(stdout); + string_reset(output); + } + } + } while(subghz_chat_worker_available(subghz_chat)); + break; + case SubghzChatEventNewMessage: + notification_message(notification, &sequence_single_vibro); + break; + case SubghzChatEventUserEntrance: + string_printf( + sysmsg, + "\033[0;34m%s joined chat.\033[0m\r\n", + furi_hal_version_get_name_ptr()); + subghz_chat_worker_write( + subghz_chat, + (uint8_t*)string_get_cstr(sysmsg), + strlen(string_get_cstr(sysmsg))); + break; + case SubghzChatEventUserExit: + string_printf( + sysmsg, "\033[0;31m%s left chat.\033[0m\r\n", furi_hal_version_get_name_ptr()); + subghz_chat_worker_write( + subghz_chat, + (uint8_t*)string_get_cstr(sysmsg), + strlen(string_get_cstr(sysmsg))); + delay(10); + exit = true; + break; + default: + FURI_LOG_W("SubGhzChat", "Error event"); + break; } } - - if(subghz_tx_rx_worker_available(subghz_txrx)) { - memset(message, 0x00, message_max_len); - subghz_tx_rx_worker_read(subghz_txrx, message, message_max_len); - printf("\r"); - for(uint8_t i = 0; i < 80; i++) { - printf(" "); - } - - printf("\r %s\r\n", message); - - printf("%s", string_get_cstr(input)); - fflush(stdout); - - notification_message(notification, &sequence_single_vibro); - } - osDelay(1); } - string_printf(sysmsg, "\033[0;31m%s left chat.\033[0m", furi_hal_version_get_name_ptr()); - subghz_tx_rx_worker_write( - subghz_txrx, (uint8_t*)string_get_cstr(sysmsg), strlen(string_get_cstr(sysmsg))); - osDelay(10); - - printf("\r\nExit chat\r\n"); string_clear(input); string_clear(name); + string_clear(output); string_clear(sysmsg); furi_hal_power_suppress_charge_exit(); furi_record_close("notification"); - if(subghz_tx_rx_worker_is_running(subghz_txrx)) { - subghz_tx_rx_worker_stop(subghz_txrx); - subghz_tx_rx_worker_free(subghz_txrx); + if(subghz_chat_worker_is_running(subghz_chat)) { + subghz_chat_worker_stop(subghz_chat); + subghz_chat_worker_free(subghz_chat); } + printf("\r\nExit chat\r\n"); } static void subghz_cli_command(Cli* cli, string_t args, void* context) { |