Feature/infrared add remote to cli (#1856)
* Initial testing of remote using cli * More fixes for cli ir remote * Fixes. Turns off power now * Finished adding other tv remote commands * Changed if-else formatting * Cleaned up unused variables * Updating cli unviersal remote to accept tv, ac and more modular. Listing signals still does not work properly * Using mlib dictionary to get unique signals from files for ir universal list * Fixing progress bar * Added error checking for invalid signal to stop freezing cli * Added error checking for arg length * Api symbols was changed somehow.. changed back and updated the argument check to account for newline * Fixing string compares and argument length issue * Freeing InfraredBruteForce in cli brute force signals Co-authored-by: sqlsquirreltm <sqlsquirreltm> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									5e35e51c57
								
							
						
					
					
						commit
						f61a8fda53
					
				| @ -1,4 +1,5 @@ | ||||
| #include <cli/cli.h> | ||||
| #include <cli/cli_i.h> | ||||
| #include <infrared.h> | ||||
| #include <infrared_worker.h> | ||||
| #include <furi_hal_infrared.h> | ||||
| @ -6,12 +7,24 @@ | ||||
| #include <toolbox/args.h> | ||||
| 
 | ||||
| #include "infrared_signal.h" | ||||
| #include "infrared_brute_force.h" | ||||
| 
 | ||||
| #include "m-dict.h" | ||||
| #include "m-string.h" | ||||
| 
 | ||||
| #define INFRARED_CLI_BUF_SIZE 10 | ||||
| 
 | ||||
| DICT_DEF2(dict_signals, string_t, STRING_OPLIST, int, M_DEFAULT_OPLIST) | ||||
| 
 | ||||
| enum RemoteTypes { TV = 0, AC = 1 }; | ||||
| 
 | ||||
| static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args); | ||||
| static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args); | ||||
| static void infrared_cli_process_decode(Cli* cli, FuriString* args); | ||||
| static void infrared_cli_process_universal(Cli* cli, FuriString* args); | ||||
| static void infrared_cli_list_remote_signals(enum RemoteTypes remote_type); | ||||
| static void | ||||
|     infrared_cli_brute_force_signals(Cli* cli, enum RemoteTypes remote_type, FuriString* signal); | ||||
| 
 | ||||
| static const struct { | ||||
|     const char* cmd; | ||||
| @ -20,6 +33,7 @@ static const struct { | ||||
|     {.cmd = "rx", .process_function = infrared_cli_start_ir_rx}, | ||||
|     {.cmd = "tx", .process_function = infrared_cli_start_ir_tx}, | ||||
|     {.cmd = "decode", .process_function = infrared_cli_process_decode}, | ||||
|     {.cmd = "universal", .process_function = infrared_cli_process_universal}, | ||||
| }; | ||||
| 
 | ||||
| static void signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { | ||||
| @ -90,6 +104,8 @@ static void infrared_cli_print_usage(void) { | ||||
|         INFRARED_MIN_FREQUENCY, | ||||
|         INFRARED_MAX_FREQUENCY); | ||||
|     printf("\tir decode <input_file> [<output_file>]\r\n"); | ||||
|     printf("\tir universal <tv, ac> <signal name>\r\n"); | ||||
|     printf("\tir universal list <tv, ac>\r\n"); | ||||
| } | ||||
| 
 | ||||
| static bool infrared_cli_parse_message(const char* str, InfraredSignal* signal) { | ||||
| @ -328,6 +344,168 @@ static void infrared_cli_process_decode(Cli* cli, FuriString* args) { | ||||
|     furi_record_close(RECORD_STORAGE); | ||||
| } | ||||
| 
 | ||||
| static void infrared_cli_process_universal(Cli* cli, FuriString* args) { | ||||
|     enum RemoteTypes Remote; | ||||
| 
 | ||||
|     FuriString* command; | ||||
|     FuriString* remote; | ||||
|     FuriString* signal; | ||||
|     command = furi_string_alloc(); | ||||
|     remote = furi_string_alloc(); | ||||
|     signal = furi_string_alloc(); | ||||
| 
 | ||||
|     do { | ||||
|         if(!args_read_string_and_trim(args, command)) { | ||||
|             infrared_cli_print_usage(); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         if(furi_string_cmp_str(command, "list") == 0) { | ||||
|             args_read_string_and_trim(args, remote); | ||||
|             if(furi_string_cmp_str(remote, "tv") == 0) { | ||||
|                 Remote = TV; | ||||
|             } else if(furi_string_cmp_str(remote, "ac") == 0) { | ||||
|                 Remote = AC; | ||||
|             } else { | ||||
|                 printf("Invalid remote type.\r\n"); | ||||
|                 break; | ||||
|             } | ||||
|             infrared_cli_list_remote_signals(Remote); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         if(furi_string_cmp_str(command, "tv") == 0) { | ||||
|             Remote = TV; | ||||
|         } else if(furi_string_cmp_str(command, "ac") == 0) { | ||||
|             Remote = AC; | ||||
|         } else { | ||||
|             printf("Invalid remote type.\r\n"); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         args_read_string_and_trim(args, signal); | ||||
|         if(furi_string_empty(signal)) { | ||||
|             printf("Must supply a valid signal for type of remote selected.\r\n"); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         infrared_cli_brute_force_signals(cli, Remote, signal); | ||||
|         break; | ||||
| 
 | ||||
|     } while(false); | ||||
| 
 | ||||
|     furi_string_free(command); | ||||
|     furi_string_free(remote); | ||||
|     furi_string_free(signal); | ||||
| } | ||||
| 
 | ||||
| static void infrared_cli_list_remote_signals(enum RemoteTypes remote_type) { | ||||
|     Storage* storage = furi_record_open(RECORD_STORAGE); | ||||
|     FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); | ||||
|     dict_signals_t signals_dict; | ||||
|     string_t key; | ||||
|     const char* remote_file = NULL; | ||||
|     bool success = false; | ||||
|     int max = 1; | ||||
| 
 | ||||
|     switch(remote_type) { | ||||
|     case TV: | ||||
|         remote_file = EXT_PATH("infrared/assets/tv.ir"); | ||||
|         break; | ||||
|     case AC: | ||||
|         remote_file = EXT_PATH("infrared/assets/ac.ir"); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     dict_signals_init(signals_dict); | ||||
|     string_init(key); | ||||
| 
 | ||||
|     success = flipper_format_buffered_file_open_existing(ff, remote_file); | ||||
|     if(success) { | ||||
|         FuriString* signal_name; | ||||
|         signal_name = furi_string_alloc(); | ||||
|         printf("Valid signals:\r\n"); | ||||
|         while(flipper_format_read_string(ff, "name", signal_name)) { | ||||
|             string_set_str(key, furi_string_get_cstr(signal_name)); | ||||
|             int* v = dict_signals_get(signals_dict, key); | ||||
|             if(v != NULL) { | ||||
|                 (*v)++; | ||||
|                 max = M_MAX(*v, max); | ||||
|             } else { | ||||
|                 dict_signals_set_at(signals_dict, key, 1); | ||||
|             } | ||||
|         } | ||||
|         dict_signals_it_t it; | ||||
|         for(dict_signals_it(it, signals_dict); !dict_signals_end_p(it); dict_signals_next(it)) { | ||||
|             const struct dict_signals_pair_s* pair = dict_signals_cref(it); | ||||
|             printf("\t%s\r\n", string_get_cstr(pair->key)); | ||||
|         } | ||||
|         furi_string_free(signal_name); | ||||
|     } | ||||
| 
 | ||||
|     string_clear(key); | ||||
|     dict_signals_clear(signals_dict); | ||||
|     flipper_format_free(ff); | ||||
|     furi_record_close(RECORD_STORAGE); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
|     infrared_cli_brute_force_signals(Cli* cli, enum RemoteTypes remote_type, FuriString* signal) { | ||||
|     InfraredBruteForce* brute_force = infrared_brute_force_alloc(); | ||||
|     const char* remote_file = NULL; | ||||
|     uint32_t i = 0; | ||||
|     bool success = false; | ||||
| 
 | ||||
|     switch(remote_type) { | ||||
|     case TV: | ||||
|         remote_file = EXT_PATH("infrared/assets/tv.ir"); | ||||
|         break; | ||||
|     case AC: | ||||
|         remote_file = EXT_PATH("infrared/assets/ac.ir"); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     infrared_brute_force_set_db_filename(brute_force, remote_file); | ||||
|     infrared_brute_force_add_record(brute_force, i++, furi_string_get_cstr(signal)); | ||||
| 
 | ||||
|     success = infrared_brute_force_calculate_messages(brute_force); | ||||
|     if(success) { | ||||
|         uint32_t record_count; | ||||
|         uint32_t index = 0; | ||||
|         int records_sent = 0; | ||||
|         bool running = false; | ||||
| 
 | ||||
|         running = infrared_brute_force_start(brute_force, index, &record_count); | ||||
|         if(record_count <= 0) { | ||||
|             printf("Invalid signal.\n"); | ||||
|             infrared_brute_force_reset(brute_force); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         printf("Sending %ld codes to the tv.\r\n", record_count); | ||||
|         printf("Press Ctrl-C to stop.\r\n"); | ||||
|         while(running) { | ||||
|             running = infrared_brute_force_send_next(brute_force); | ||||
| 
 | ||||
|             if(cli_cmd_interrupt_received(cli)) break; | ||||
| 
 | ||||
|             printf("\r%d%% complete.", (int)((float)records_sent++ / (float)record_count * 100)); | ||||
|             fflush(stdout); | ||||
|         } | ||||
| 
 | ||||
|         infrared_brute_force_stop(brute_force); | ||||
|     } else { | ||||
|         printf("Invalid signal.\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     infrared_brute_force_reset(brute_force); | ||||
|     infrared_brute_force_free(brute_force); | ||||
| } | ||||
| 
 | ||||
| static void infrared_cli_start_ir(Cli* cli, FuriString* args, void* context) { | ||||
|     UNUSED(context); | ||||
|     if(furi_hal_infrared_is_busy()) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Travis Montoya
						Travis Montoya