[FL-1064] iButton CLI commands (#407)
* ibutton: add cli commands * ibutton/scene: add cli event send * ibutton: make separate scenes for cli commands * ibutton/scene: add timeout to cli scenes * ibutton: fix reading key data from cli * cli: add cli_delete_command to API * ibutton: delete cli command after app exit * cli: free allocated string Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									d1f523687e
								
							
						
					
					
						commit
						cfcdff8346
					
				| @ -176,6 +176,23 @@ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* con | ||||
|     string_clear(name_str); | ||||
| } | ||||
| 
 | ||||
| void cli_delete_command(Cli* cli, const char* name) { | ||||
|     string_t name_str; | ||||
|     string_init_set_str(name_str, name); | ||||
|     string_strim(name_str); | ||||
| 
 | ||||
|     size_t name_replace; | ||||
|     do { | ||||
|         name_replace = string_replace_str(name_str, " ", "_"); | ||||
|     } while(name_replace != STRING_FAILURE); | ||||
| 
 | ||||
|     furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); | ||||
|     CliCommandDict_erase(cli->commands, name_str); | ||||
|     furi_check(osMutexRelease(cli->mutex) == osOK); | ||||
| 
 | ||||
|     string_clear(name_str); | ||||
| } | ||||
| 
 | ||||
| int32_t cli_task(void* p) { | ||||
|     Cli* cli = cli_alloc(); | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,12 @@ typedef void (*CliCallback)(string_t args, void* context); | ||||
|  */ | ||||
| void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* context); | ||||
| 
 | ||||
| /* Delete cli command
 | ||||
|  * @param cli - pointer to cli instance | ||||
|  * @param name - command name | ||||
|  */ | ||||
| void cli_delete_command(Cli* cli, const char* name); | ||||
| 
 | ||||
| /* Read from terminal
 | ||||
|  * Do it only from inside of cli call. | ||||
|  * @param cli - Cli instance | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| #include "ibutton-app.h" | ||||
| #include <stdarg.h> | ||||
| #include <callback-connector.h> | ||||
| #include <m-string.h> | ||||
| 
 | ||||
| void iButtonApp::run(void) { | ||||
|     iButtonEvent event; | ||||
| @ -23,13 +25,167 @@ void iButtonApp::run(void) { | ||||
|     scenes[current_scene]->on_exit(this); | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::print_key_data(void) { | ||||
|     uint8_t* key_data = key.get_data(); | ||||
|     switch(key.get_key_type()) { | ||||
|     case iButtonKeyType::KeyDallas: | ||||
|         printf( | ||||
|             "Dallas %02X %02X %02X %02X %02X %02X %02X %02X\r\n", | ||||
|             key_data[0], | ||||
|             key_data[1], | ||||
|             key_data[2], | ||||
|             key_data[3], | ||||
|             key_data[4], | ||||
|             key_data[5], | ||||
|             key_data[6], | ||||
|             key_data[7]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyCyfral: | ||||
|         printf("Cyfral %02X %02X\r\n", key_data[0], key_data[1]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyMetakom: | ||||
|         printf( | ||||
|             "Metakom %02X %02X %02X %02X\r\n", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool iButtonApp::read_hex_byte(string_t args, uint8_t* byte) { | ||||
|     char* endptr; | ||||
|     *byte = strtoul(string_get_cstr(args), &endptr, 16); | ||||
|     if(*endptr == '\0') { | ||||
|         return false; | ||||
|     } | ||||
|     size_t ws = string_search_char(args, ' '); | ||||
|     if(ws != 2) { | ||||
|         return false; | ||||
|     } | ||||
|     string_right(args, ws); | ||||
|     string_strim(args); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::cli_cmd_callback(string_t args, void* context) { | ||||
|     iButtonApp::Scene scene; | ||||
|     string_t cmd; | ||||
|     string_init(cmd); | ||||
|     if(!string_cmp_str(args, "read")) { | ||||
|         scene = iButtonApp::Scene::SceneCliRead; | ||||
|         printf("Reading key ...\r\n"); | ||||
|     } else { | ||||
|         // Parse write / emulate commands
 | ||||
|         size_t ws = string_search_char(args, ' '); | ||||
|         if(ws == STRING_FAILURE) { | ||||
|             printf("Incorrect input. Try tm <read | write | emulate> [key_type] [key_data]\r\n"); | ||||
|             string_clear(cmd); | ||||
|             return; | ||||
|         } else { | ||||
|             string_set_n(cmd, args, 0, ws); | ||||
|             string_right(args, ws); | ||||
|             string_strim(args); | ||||
|         } | ||||
|         if(!string_cmp_str(cmd, "write")) { | ||||
|             scene = iButtonApp::Scene::SceneCliWrite; | ||||
|         } else if(!string_cmp_str(cmd, "emulate")) { | ||||
|             scene = iButtonApp::Scene::SceneCliEmulate; | ||||
|         } else { | ||||
|             printf("Incorrect input. Try tm <write | emulate> <key_type> <key_data>\r\n"); | ||||
|             string_clear(cmd); | ||||
|             return; | ||||
|         } | ||||
|         string_clear(cmd); | ||||
|         // Parse key type
 | ||||
|         string_t key_type; | ||||
|         string_init(key_type); | ||||
|         ws = string_search_char(args, ' '); | ||||
|         string_set_n(key_type, args, 0, ws); | ||||
|         uint8_t bytes_to_read = 0; | ||||
|         if(!string_cmp_str(key_type, "0")) { | ||||
|             key.set_type(iButtonKeyType::KeyDallas); | ||||
|             bytes_to_read = 8; | ||||
|         } else if(!string_cmp_str(key_type, "1")) { | ||||
|             key.set_type(iButtonKeyType::KeyCyfral); | ||||
|             bytes_to_read = 2; | ||||
|         } else if(!string_cmp_str(key_type, "2")) { | ||||
|             key.set_type(iButtonKeyType::KeyMetakom); | ||||
|             bytes_to_read = 4; | ||||
|         } else { | ||||
|             printf("Incorrect key type. Try 0 - KeyDallas, 1 - KeyCyfral, 2 - KeyMetakom"); | ||||
|             string_clear(key_type); | ||||
|             return; | ||||
|         } | ||||
|         string_clear(key_type); | ||||
|         // Read key data
 | ||||
|         string_right(args, 1); | ||||
|         string_strim(args); | ||||
|         uint8_t key_data[8] = {}; | ||||
|         uint8_t i = 0; | ||||
|         bool ret = true; | ||||
|         while((i < bytes_to_read) && ret) { | ||||
|             ret = read_hex_byte(args, &key_data[i++]); | ||||
|         } | ||||
|         if(i != bytes_to_read) { | ||||
|             printf("Incorrect key data\r\n"); | ||||
|             return; | ||||
|         } | ||||
|         key.set_data(key_data, bytes_to_read); | ||||
|         if(scene == iButtonApp::Scene::SceneCliWrite) { | ||||
|             printf("Writing key "); | ||||
|         } else { | ||||
|             printf("Emulating key "); | ||||
|         } | ||||
|         print_key_data(); | ||||
|     } | ||||
|     switch_to_next_scene(scene); | ||||
|     // Wait return event
 | ||||
|     iButtonApp::CliEvent result; | ||||
|     if(osMessageQueueGet(cli_event_result, &result, NULL, osWaitForever) != osOK) { | ||||
|         printf("Command execution error\r\n"); | ||||
|         return; | ||||
|     } | ||||
|     // Process return event
 | ||||
|     switch(result) { | ||||
|     case iButtonApp::CliEvent::CliReadSuccess: | ||||
|         print_key_data(); | ||||
|     case iButtonApp::CliEvent::CliReadCRCError: | ||||
|         printf("Read error: invalid CRC\r\n"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliReadNotKeyError: | ||||
|         printf("Read error: not a key\r\n"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliTimeout: | ||||
|         printf("Timeout error\r\n"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliInterrupt: | ||||
|         printf("Command interrupted\r\n"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliWriteSuccess: | ||||
|         printf("Write success\r\n"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliWriteFail: | ||||
|         printf("Write fail\r\n"); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::cli_send_event(iButtonApp::CliEvent scene) { | ||||
|     osMessageQueuePut(cli_event_result, &scene, 0, osWaitForever); | ||||
| } | ||||
| 
 | ||||
| iButtonApp::iButtonApp() { | ||||
|     notify_init(); | ||||
|     api_hal_power_insomnia_enter(); | ||||
| 
 | ||||
|     cli_event_result = osMessageQueueNew(1, sizeof(iButtonApp::Scene), NULL); | ||||
|     key_worker = new KeyWorker(&ibutton_gpio); | ||||
|     sd_ex_api = static_cast<SdCard_Api*>(furi_record_open("sdcard-ex")); | ||||
|     fs_api = static_cast<FS_Api*>(furi_record_open("sdcard")); | ||||
|     cli = static_cast<Cli*>(furi_record_open("cli")); | ||||
|     auto callback = cbc::obtain_connector(this, &iButtonApp::cli_cmd_callback); | ||||
|     cli_add_command(cli, "tm", callback, cli); | ||||
| 
 | ||||
|     // we need random
 | ||||
|     srand(DWT->CYCCNT); | ||||
| @ -38,6 +194,9 @@ iButtonApp::iButtonApp() { | ||||
| iButtonApp::~iButtonApp() { | ||||
|     furi_record_close("sdcard-ex"); | ||||
|     furi_record_close("sdcard"); | ||||
|     cli_delete_command(cli, "tm"); | ||||
|     furi_record_close("cli"); | ||||
|     osMessageQueueDelete(cli_event_result); | ||||
|     api_hal_power_insomnia_exit(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -6,16 +6,19 @@ | ||||
| #include "scene/ibutton-scene-generic.h" | ||||
| #include "scene/ibutton-scene-start.h" | ||||
| #include "scene/ibutton-scene-read.h" | ||||
| #include "scene/ibutton-scene-cli-read.h" | ||||
| #include "scene/ibutton-scene-read-crc-error.h" | ||||
| #include "scene/ibutton-scene-read-not-key-error.h" | ||||
| #include "scene/ibutton-scene-read-success.h" | ||||
| #include "scene/ibutton-scene-readed-key-menu.h" | ||||
| #include "scene/ibutton-scene-write.h" | ||||
| #include "scene/ibutton-scene-cli-write.h" | ||||
| #include "scene/ibutton-scene-write-success.h" | ||||
| #include "scene/ibutton-scene-saved-key-menu.h" | ||||
| #include "scene/ibutton-scene-delete-confirm.h" | ||||
| #include "scene/ibutton-scene-delete-success.h" | ||||
| #include "scene/ibutton-scene-emulate.h" | ||||
| #include "scene/ibutton-scene-cli-emulate.h" | ||||
| #include "scene/ibutton-scene-save-name.h" | ||||
| #include "scene/ibutton-scene-save-success.h" | ||||
| #include "scene/ibutton-scene-info.h" | ||||
| @ -26,6 +29,7 @@ | ||||
| 
 | ||||
| #include <sd-card-api.h> | ||||
| #include <filesystem-api.h> | ||||
| #include "../cli/cli.h" | ||||
| 
 | ||||
| #include "one_wire_master.h" | ||||
| #include "maxim_crc.h" | ||||
| @ -42,13 +46,16 @@ public: | ||||
|         SceneExit, | ||||
|         SceneStart, | ||||
|         SceneRead, | ||||
|         SceneCliRead, | ||||
|         SceneReadNotKeyError, | ||||
|         SceneReadCRCError, | ||||
|         SceneReadSuccess, | ||||
|         SceneReadedKeyMenu, | ||||
|         SceneWrite, | ||||
|         SceneCliWrite, | ||||
|         SceneWriteSuccess, | ||||
|         SceneEmulate, | ||||
|         SceneCliEmulate, | ||||
|         SceneSavedKeyMenu, | ||||
|         SceneDeleteConfirm, | ||||
|         SceneDeleteSuccess, | ||||
| @ -59,6 +66,16 @@ public: | ||||
|         SceneAddValue, | ||||
|     }; | ||||
| 
 | ||||
|     enum class CliEvent : uint8_t { | ||||
|         CliReadSuccess, | ||||
|         CliReadCRCError, | ||||
|         CliReadNotKeyError, | ||||
|         CliWriteSuccess, | ||||
|         CliWriteFail, | ||||
|         CliTimeout, | ||||
|         CliInterrupt, | ||||
|     }; | ||||
| 
 | ||||
|     iButtonAppViewManager* get_view_manager(); | ||||
|     void switch_to_next_scene(Scene index); | ||||
|     void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list); | ||||
| @ -93,23 +110,30 @@ public: | ||||
|     char* get_file_name(); | ||||
|     uint8_t get_file_name_size(); | ||||
| 
 | ||||
|     void cli_cmd_callback(string_t args, void* context); | ||||
|     void cli_send_event(CliEvent scene); | ||||
| 
 | ||||
|     void generate_random_name(char* name, uint8_t max_name_size); | ||||
| 
 | ||||
| private: | ||||
|     std::list<Scene> previous_scenes_list = {Scene::SceneExit}; | ||||
|     Scene current_scene = Scene::SceneStart; | ||||
|     iButtonAppViewManager view; | ||||
|     osMessageQueueId_t cli_event_result; | ||||
| 
 | ||||
|     std::map<Scene, iButtonScene*> scenes = { | ||||
|         {Scene::SceneStart, new iButtonSceneStart()}, | ||||
|         {Scene::SceneRead, new iButtonSceneRead()}, | ||||
|         {Scene::SceneCliRead, new iButtonSceneCliRead()}, | ||||
|         {Scene::SceneReadCRCError, new iButtonSceneReadCRCError()}, | ||||
|         {Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()}, | ||||
|         {Scene::SceneReadSuccess, new iButtonSceneReadSuccess()}, | ||||
|         {Scene::SceneReadedKeyMenu, new iButtonSceneReadedKeyMenu()}, | ||||
|         {Scene::SceneWrite, new iButtonSceneWrite()}, | ||||
|         {Scene::SceneCliWrite, new iButtonSceneCliWrite()}, | ||||
|         {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, | ||||
|         {Scene::SceneEmulate, new iButtonSceneEmulate()}, | ||||
|         {Scene::SceneCliEmulate, new iButtonSceneCliEmulate()}, | ||||
|         {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, | ||||
|         {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, | ||||
|         {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, | ||||
| @ -126,6 +150,7 @@ private: | ||||
| 
 | ||||
|     SdCard_Api* sd_ex_api; | ||||
|     FS_Api* fs_api; | ||||
|     Cli* cli; | ||||
|     static const uint8_t file_name_size = 100; | ||||
|     char file_name[file_name_size]; | ||||
| 
 | ||||
| @ -133,4 +158,6 @@ private: | ||||
|     char text_store[text_store_size + 1]; | ||||
| 
 | ||||
|     void notify_init(); | ||||
|     bool read_hex_byte(string_t arg, uint8_t* byte); | ||||
|     void print_key_data(void); | ||||
| }; | ||||
							
								
								
									
										102
									
								
								applications/ibutton/scene/ibutton-scene-cli-emulate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								applications/ibutton/scene/ibutton-scene-cli-emulate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| #include "ibutton-scene-cli-emulate.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| #include "../ibutton-key.h" | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| void iButtonSceneCliEmulate::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     iButtonKey* key = app->get_key(); | ||||
|     uint8_t* key_data = key->get_data(); | ||||
|     const char* key_name = key->get_name(); | ||||
|     uint8_t line_count = 2; | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     // check that stored key has name
 | ||||
|     if(strcmp(key_name, "") != 0) { | ||||
|         app->set_text_store("emulating\n%s", key_name); | ||||
|         line_count = 2; | ||||
|     } else { | ||||
|         // if not, show key data
 | ||||
|         switch(key->get_key_type()) { | ||||
|         case iButtonKeyType::KeyDallas: | ||||
|             app->set_text_store( | ||||
|                 "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3], | ||||
|                 key_data[4], | ||||
|                 key_data[5], | ||||
|                 key_data[6], | ||||
|                 key_data[7]); | ||||
|             line_count = 3; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyCyfral: | ||||
|             app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyMetakom: | ||||
|             app->set_text_store( | ||||
|                 "emulating\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     switch(line_count) { | ||||
|     case 3: | ||||
|         popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
|     app->get_key_worker()->start_emulate(app->get_key()); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliEmulate::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|         } else { | ||||
|             if(app->get_key_worker()->emulated()) { | ||||
|                 app->notify_yellow_blink(); | ||||
|             } else { | ||||
|                 app->notify_red_blink(); | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliEmulate::on_exit(iButtonApp* app) { | ||||
|     app->get_key_worker()->stop_emulate(); | ||||
| 
 | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| } | ||||
							
								
								
									
										13
									
								
								applications/ibutton/scene/ibutton-scene-cli-emulate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								applications/ibutton/scene/ibutton-scene-cli-emulate.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| #include "../helpers/key-emulator.h" | ||||
| 
 | ||||
| class iButtonSceneCliEmulate : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
							
								
								
									
										65
									
								
								applications/ibutton/scene/ibutton-scene-cli-read.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								applications/ibutton/scene/ibutton-scene-cli-read.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| #include "ibutton-scene-cli-read.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| 
 | ||||
| void iButtonSceneCliRead::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, 0, 5, I_DolphinWait_61x59); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
|     app->get_key()->set_name(""); | ||||
| 
 | ||||
|     app->get_key_worker()->start_read(); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliRead::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         app->notify_red_blink(); | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|             return consumed; | ||||
|         } else { | ||||
|             switch(app->get_key_worker()->read(app->get_key())) { | ||||
|             case KeyReader::Error::EMPTY: | ||||
|                 break; | ||||
|             case KeyReader::Error::OK: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadSuccess); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyReader::Error::CRC_ERROR: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadCRCError); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyReader::Error::NOT_ARE_KEY: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadNotKeyError); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliRead::on_exit(iButtonApp* app) { | ||||
|     app->get_key_worker()->stop_read(); | ||||
| 
 | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| } | ||||
							
								
								
									
										12
									
								
								applications/ibutton/scene/ibutton-scene-cli-read.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/ibutton/scene/ibutton-scene-cli-read.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| 
 | ||||
| class iButtonSceneCliRead : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
							
								
								
									
										109
									
								
								applications/ibutton/scene/ibutton-scene-cli-write.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								applications/ibutton/scene/ibutton-scene-cli-write.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| #include "ibutton-scene-cli-write.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| #include "../ibutton-key.h" | ||||
| 
 | ||||
| void iButtonSceneCliWrite::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     iButtonKey* key = app->get_key(); | ||||
|     uint8_t* key_data = key->get_data(); | ||||
|     const char* key_name = key->get_name(); | ||||
|     uint8_t line_count = 2; | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     // check that stored key has name
 | ||||
|     if(strcmp(key_name, "") != 0) { | ||||
|         app->set_text_store("writing\n%s", key_name); | ||||
|         line_count = 2; | ||||
|     } else { | ||||
|         // if not, show key data
 | ||||
|         switch(key->get_key_type()) { | ||||
|         case iButtonKeyType::KeyDallas: | ||||
|             app->set_text_store( | ||||
|                 "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3], | ||||
|                 key_data[4], | ||||
|                 key_data[5], | ||||
|                 key_data[6], | ||||
|                 key_data[7]); | ||||
|             line_count = 3; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyCyfral: | ||||
|             app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyMetakom: | ||||
|             app->set_text_store( | ||||
|                 "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     switch(line_count) { | ||||
|     case 3: | ||||
|         popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
| 
 | ||||
|     app->get_key_worker()->start_write(); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliWrite::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|         } else { | ||||
|             KeyWriter::Error result = app->get_key_worker()->write(app->get_key()); | ||||
| 
 | ||||
|             switch(result) { | ||||
|             case KeyWriter::Error::SAME_KEY: | ||||
|             case KeyWriter::Error::OK: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliWriteSuccess); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyWriter::Error::NO_DETECT: | ||||
|                 app->notify_red_blink(); | ||||
|                 break; | ||||
|             case KeyWriter::Error::CANNOT_WRITE: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliWriteFail); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliWrite::on_exit(iButtonApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| 
 | ||||
|     app->get_key_worker()->stop_write(); | ||||
| } | ||||
							
								
								
									
										12
									
								
								applications/ibutton/scene/ibutton-scene-cli-write.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/ibutton/scene/ibutton-scene-cli-write.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| 
 | ||||
| class iButtonSceneCliWrite : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich