diff --git a/Distr/nrf24batch/CO2_mini.txt b/Distr/nrf24batch/CO2_mini.txt index 4087ca0e55f..90300da3444 100644 --- a/Distr/nrf24batch/CO2_mini.txt +++ b/Distr/nrf24batch/CO2_mini.txt @@ -15,6 +15,8 @@ R default: ,EEPROM,0xC1 W default: n,,0x81 Write start: 0,0,0x8F +Listen: C8C8C1=CO2,Alarm,- + R: ID*=,ID R: OSCCAL=0x51,RAM R: OSCCAL_EMEM=0 diff --git a/nrf24batch.c b/nrf24batch.c index 91708099bea..4482bba2c81 100644 --- a/nrf24batch.c +++ b/nrf24batch.c @@ -14,7 +14,7 @@ #include #define TAG "nrf24batch" -#define VERSION "1.2" +#define VERSION "1.3" #define SCAN_APP_PATH_FOLDER "/ext/nrf24batch" #define LOG_FILEEXT ".txt" @@ -41,17 +41,19 @@ const char SettingsFld_Write[] = "W:"; // Write cmd const char SettingsFld_Set[] = "S:"; // Set cmd (like Write but without "Write start" packet) const char SettingsFld_ReadBatch[] = "RBatch:"; const char SettingsFld_WriteBatch[] = "WBatch:"; +const char SettingsFld_Listen[] = "Listen:"; const char AskQuestion_Save[] = "SAVE BATCH?"; #define Settings_i 'i' #define Settings_n 'n' #define VAR_EMPTY ((int32_t)0x80000000) nRF24Batch* APP; -uint8_t what_doing = 0; // 0 - setup, 1 - cmd list, 2 - view send cmd +uint8_t what_doing = 0; // 0 - setup, 1 - cmd list, 2 - read/write/listen cmd enum { rwt_read_batch = 0, rwt_read_cmd, - rwt_write_batch + rwt_write_batch, + rwt_listen }; uint8_t rw_type = rwt_read_batch; // What to do: rwt_* enum { @@ -110,6 +112,10 @@ FuriString *ReadDefault = NULL; FuriString *WriteDefault = NULL; FuriString *WriteStart = NULL; FuriString *Constants = NULL; // text of STR=x +char *ListenAddr = NULL; +char *ListenFields = NULL; // ptr to string: field1,field2,... max 5 field now +bool ListenNew; +FuriHalRtcDateTime ListenLastTime = { 0 }; FuriString **Read_cmd = NULL; // Names of read cmd uint16_t Read_cmd_Total = 0; FuriString **Log = NULL; // Strings: var=n @@ -201,6 +207,14 @@ static void add_to_str_hex_bytes(char *out, uint8_t *arr, int bytes) } while(--bytes); } +int32_t get_payload_receive_field(uint8_t size) +{ + if(size <= 1) return *payload_receive; + else if(size == 2) return *(int16_t*)payload_receive; + else if(size == 3) return (*(uint32_t*)payload_receive) & 0xFFFFFF; + else return *(int32_t*)payload_receive; +} + void free_Log() { if(Log_Total) { @@ -231,6 +245,14 @@ void free_store(void) furi_string_free(WriteStart); WriteDefault = NULL; } + if(ListenAddr) { + free(ListenAddr); + ListenAddr = NULL; + } + if(ListenFields) { + free(ListenFields); + ListenFields = NULL; + } if(Read_cmd_Total) { for(uint16_t i = 0; i < Read_cmd_Total; i++) furi_string_free(Read_cmd[i]); Read_cmd_Total = 0; @@ -370,11 +392,7 @@ bool nrf24_read_newpacket() { if(size > 4) size = 0; } } - int32_t var; - if(size <= 1) var = *payload_receive; - else if(size == 2) var = *(int16_t*)payload_receive; - else if(size == 3) var = (*(uint32_t*)payload_receive) & 0xFFFFFF; - else var = *(int32_t*)payload_receive; + int32_t var = get_payload_receive_field(size); //FURI_LOG_D(TAG, "VAR(%d): %ld", size, var); if(size == 0) furi_string_cat_printf(str, "%c", (char)var); else { @@ -710,7 +728,7 @@ static uint8_t load_settings_file() { char *p = (char*)furi_string_get_cstr(str); if(*p <= ' ') continue; //char* delim_eq = strchr(p, '='); - char* delim_col = strchr(p, ':'); + char *delim_col = strchr(p, ':'); if(delim_col == NULL) { // Constant found - no ':' if(Constants == NULL) { Constants = furi_string_alloc_set(str); @@ -796,6 +814,21 @@ static uint8_t load_settings_file() { break; } WriteBatch_cmd[WriteBatch_cmd_Total++] = furi_string_alloc_set_str(p); + } else if(strncmp(p, SettingsFld_Listen, sizeof(SettingsFld_Listen)-1) == 0) { + p += sizeof(SettingsFld_Listen); + char *p2 = strchr(p, '='); + if(p2) { + uint8_t len = p2 - p; + ListenAddr = malloc(len + 1); + if(ListenAddr) { + memcpy(ListenAddr, p, len); + ListenAddr[len] = '\0'; + p2++; + len = strlen(p2); + ListenFields = malloc(len + 1); + if(ListenFields) memcpy(ListenFields, p2, len); + } + } } } } @@ -893,6 +926,22 @@ void display_remove_asterisk(char *fsp, uint8_t vx) } } +void display_edit_ttf_font(Canvas* const canvas, uint8_t start_x, uint8_t start_y) +{ + screen_buf[0] = *Edit_pos; screen_buf[1] = '\0'; + int n = canvas_string_width(canvas, screen_buf); + int len = Edit_pos - Edit_start; + memcpy(screen_buf, Edit_start, len); + screen_buf[len] = '\0'; + int x = start_x + canvas_string_width(canvas, screen_buf); + int len2 = strlen(Edit_pos); + memcpy(screen_buf + len, Edit_pos, len2); + screen_buf[len + len2] = '\0'; + canvas_draw_str(canvas, start_x, start_y, screen_buf); + start_y += 1; + canvas_draw_line(canvas, x + (len ? 1 : 0), start_y, x + n + (*Edit_pos == '1' && len ? 1 : 0), start_y); +} + static void render_callback(Canvas* const canvas, void* ctx) { const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); if(plugin_state == NULL) return; @@ -903,20 +952,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas_draw_str(canvas, 8, 10, screen_buf); if(addr_len) { if(Edit) { - screen_buf[0] = *Edit_pos; screen_buf[1] = '\0'; - int n = canvas_string_width(canvas, screen_buf); - int len = Edit_pos - Edit_start; - memcpy(screen_buf, Edit_start, len); - screen_buf[len] = '\0'; - int x = setup_cursor == 1 ? 45 : 55; - x += canvas_string_width(canvas, screen_buf); - int len2 = strlen(Edit_pos); - memcpy(screen_buf + len, Edit_pos, len2); - screen_buf[len + len2] = '\0'; - int y = 10 + setup_cursor * 10; - if(setup_cursor == 1) canvas_draw_str(canvas, 45, 20, screen_buf); - else if(setup_cursor == 2) canvas_draw_str(canvas, 55, 30, screen_buf); - canvas_draw_line(canvas, x + (len ? 1 : 0), y + 1, x + n + (*Edit_pos == '1' && len ? 1 : 0), y + 1); + if(setup_cursor == 1) display_edit_ttf_font(canvas, 45, 20); + else if(setup_cursor == 2) display_edit_ttf_font(canvas, 55, 30); } if(!Edit || setup_cursor != 1) { screen_buf[0] = '\0'; @@ -940,19 +977,25 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas_draw_str(canvas, 0, 10, ">"); } } else if(what_doing == 1){ - canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines, 25 cols - if(rw_type == rwt_read_batch) { - canvas_draw_str(canvas, 0, 7, "Read Batch:"); - render_display_list(canvas, &ReadBatch_cmd, ':', view_cmd[rw_type], ReadBatch_cmd_Total); - } else if(rw_type == rwt_read_cmd) { - canvas_draw_str(canvas, 0, 7, "Read Command:"); - render_display_list(canvas, &Read_cmd, '=', view_cmd[rw_type], Read_cmd_Total); - } else { // rwt_write_batch - if(!ask_fill_screen_buf()) strcpy(screen_buf, "Write Batch:"); - canvas_draw_str(canvas, 0, 7, screen_buf); - render_display_list(canvas, &WriteBatch_cmd, ':', view_cmd[rw_type], WriteBatch_cmd_Total); + if(rw_type == rwt_listen) { + canvas_set_font(canvas, FontSecondary); // 8x10 font, 6 lines + canvas_draw_str(canvas, 0, 10, "Listen mode"); + canvas_draw_str(canvas, 0, 25, "Address:"); + if(Edit) display_edit_ttf_font(canvas, 40, 25); else if(ListenAddr) canvas_draw_str(canvas, 40, 25, ListenAddr); + } else { + canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines, 25 cols + if(rw_type == rwt_read_batch) { + canvas_draw_str(canvas, 0, 7, "Read Batch:"); + render_display_list(canvas, &ReadBatch_cmd, ':', view_cmd[rw_type], ReadBatch_cmd_Total); + } else if(rw_type == rwt_read_cmd) { + canvas_draw_str(canvas, 0, 7, "Read Command:"); + render_display_list(canvas, &Read_cmd, '=', view_cmd[rw_type], Read_cmd_Total); + } else if(rw_type == rwt_write_batch) { + if(!ask_fill_screen_buf()) strcpy(screen_buf, "Write Batch:"); + canvas_draw_str(canvas, 0, 7, screen_buf); + render_display_list(canvas, &WriteBatch_cmd, ':', view_cmd[rw_type], WriteBatch_cmd_Total); + } } - if(NRF_ERROR) canvas_draw_str(canvas, 70, 7, "nRF24 ERROR!"); } else { // what_doing == 2 if(rw_type == rwt_read_cmd) { // Read command canvas_set_font(canvas, FontSecondary); // 8x10 font, 6 lines @@ -975,6 +1018,35 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas_draw_str(canvas, 0, 15 + 10, screen_buf); } + } else if(rw_type == rwt_listen) { + canvas_set_font(canvas, FontSecondary); // 8x10 font, 6 lines + strcpy(screen_buf, "Listen: "); + if(NRF_ERROR) strcat(screen_buf, "nRF24 ERROR!"); + else if(ListenNew) snprintf(screen_buf + strlen(screen_buf), 16, "%02d:%02d:%02d", ListenLastTime.hour, ListenLastTime.minute, ListenLastTime.second); + else strcat(screen_buf, "receiving"); + canvas_draw_str(canvas, 0, 10, screen_buf); + if(ListenFields) { + char *p2, *p = ListenFields; + uint8_t hex, len, *pld = payload_receive; + for(uint8_t i = 0; i < 5 && *p; i++) { + hex = false; + p2 = strchr(p, ','); + if(p2 == NULL) p2 = p + strlen(p); else if(*(p2 - 1) == '#') hex = true; + memcpy(screen_buf, p, len = p2 - p); + strcpy(screen_buf + len, ": "); + if(ListenNew) { + len = payload_struct[i]; + if(hex) strcat(screen_buf, "0x"); + else snprintf(screen_buf, strlen(screen_buf), "%ld (", get_payload_receive_field(len)); + add_to_str_hex_bytes(screen_buf, pld, len); + if(!hex) strcat(screen_buf, ")"); + pld += len; + } + canvas_draw_str(canvas, 0, 20 + i * 10, screen_buf); + if(*p2 == '\0') break; + p = p2 + 1; + } + } } else { // if(rw_type == rwt_read_batch || rw_type == rwt_write_batch) canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines, 25 cols if(!ask_fill_screen_buf()) { @@ -1069,8 +1141,11 @@ void work_timer_callback(void* ctx) for(uint8_t i = 0; i < 3; i++) { bool new = nrf24_read_newpacket(); if(new) { - if(send_status != sst_receiving) break; - } else if(furi_get_tick() - NRF_time > NRF_READ_TIMEOUT) { + if(rw_type == rwt_listen) { + furi_hal_rtc_get_datetime(&ListenLastTime); + ListenNew = true; + } else if(send_status != sst_receiving) break; + } else if(rw_type != rwt_listen && furi_get_tick() - NRF_time > NRF_READ_TIMEOUT) { if(NRF_repeat++ < NRF_resend) { send_status = sst_sending; nrf24_resend_read_packet(); @@ -1192,11 +1267,11 @@ int32_t nrf24batch_app(void* p) { else if(*(Edit_pos - 1) == ',') Edit_pos -= 2; } } else if(what_doing == 0) { - rw_type = rwt_write_batch; + rw_type = rwt_listen; what_doing = 1; } else if(what_doing == 1) { if(event.input.type == InputTypeShort) { - if(--rw_type > rwt_write_batch) rw_type = rwt_write_batch; + if(--rw_type > rwt_listen) rw_type = rwt_listen; } else if(view_x) view_x--; } else if(what_doing == 2) { if(view_x) view_x--; @@ -1224,7 +1299,7 @@ int32_t nrf24batch_app(void* p) { what_doing = 1; } else if(what_doing == 1) { if(event.input.type == InputTypeShort) { - if(++rw_type > rwt_write_batch) rw_type = rwt_read_batch; + if(++rw_type > rwt_listen) rw_type = rwt_read_batch; } else view_x++; } else if(what_doing == 2) { view_x++; @@ -1331,6 +1406,15 @@ int32_t nrf24batch_app(void* p) { view_Batch = 0; what_doing = 2; } + } else if(rw_type == rwt_listen) { + free_Log(); + prepare_nrf24(); + if(!NRF_ERROR) { + nrf24_set_rx_mode(nrf24_HANDLE); + ListenNew = false; + send_status = sst_receiving; // receiving + } + what_doing = 2; } } else if(what_doing == 2) { if(Log_Total) { @@ -1339,8 +1423,7 @@ int32_t nrf24batch_app(void* p) { ask_question_answer = 0; } else if(rw_type == rwt_write_batch) { if(!Edit) { - Edit = 1; - Edited = true; + Edit = 0; Edit_hex = 0; char *s = (char*)furi_string_get_cstr(Log[view_Batch]); char *p = strchr(s, '='); @@ -1351,8 +1434,14 @@ int32_t nrf24batch_app(void* p) { p += 2; Edit_hex = 1; // hex } - Edit_start = Edit_pos = p; - } else Edit = 0; + if(is_digit(p, Edit_hex)) { + Edit_start = p; + while(is_digit(p, Edit_hex)) p++; + Edit_pos = p - 1; + Edited = true; + Edit = 1; + } + } } } } @@ -1371,6 +1460,14 @@ int32_t nrf24batch_app(void* p) { furi_string_left(fs, furi_string_size(fs) - 1); } } + } else if(what_doing == 1) { + if(rw_type == rwt_listen) { + NRF_INITED = false; + Edit_start = ListenAddr; + Edit_pos = ListenAddr + strlen(ListenAddr) - 1; + Edit_hex = true; + Edit = 1; + } } else if(what_doing == 2 && Log_Total) { if(rw_type == rwt_write_batch) { ask_question = ask_write_batch;