Browse Source

update quac

MX 1 year ago
parent
commit
7d76a79f13

+ 6 - 0
CHANGELOG.md

@@ -1,3 +1,9 @@
+## 0.7.0
+
+- Addded support for iButton
+- Added IR Import All
+- Updated for firmware SDK 1.0.1
+
 ## 0.6.3
 
 - Updated for firmware SDK 0.105.0

+ 12 - 6
README.md

@@ -2,7 +2,7 @@
 
 ## Quick Action Remote Control for Flipperzero
 
-[Latest Version: 0.6.3](https://github.com/rdefeo/quac/releases)
+[Latest Version: 0.7.0](https://github.com/rdefeo/quac/releases)
 
 ![build status badge](https://github.com/rdefeo/quac/actions/workflows/build.yml/badge.svg)
 
@@ -10,11 +10,11 @@ This app allows you to organize previously recorded signals, of any type*, so th
 
 The app does not provide any recording functionality - you must use the existing Flipperzero apps to create the saved files for your action/device. Quac! provides some basic functionality to manage your files. Or, you can manage the folder structure manually on your SD card.
 
-> Support files include: Sub-Ghz (.sub), RFID (.rfid), Infrared (.ir), and NFC (.nfc)
+> Supported files include: Sub-Ghz (.sub), RFID (.rfid), Infrared (.ir), NFC (.nfc), and iButton (.ibtn)
 
 ## Features
 
-* [Playback of rfid, sub-ghz, IR, NFC signals](README.md#signal-playback)
+* [Playback of rfid, sub-ghz, IR, NFC, iButton signals](README.md#signal-playback)
 * [Easy navigation](README.md#navigation--controls)
 * [Flexible signal organization](README.md#signal-organization) - utilizing the SDcard filesystem
 * [In-app file management](README.md#action-settings) - rename, delete, import
@@ -38,7 +38,7 @@ The app does not provide any recording functionality - you must use the existing
 
 ## Signal playback
 
-The signal files are played back as recorded. During playback/transmit, the LED light will flash blue until the action is complete. For RFID and NFC signals, they are continuously played back for their defined durations: RFID - 2.5 seconds and NFC - 1 second. These defaults can be changed in [application Settings](README.md#application-settings).
+The signal files are played back as recorded. During playback/transmit, the LED light will flash blue until the action is complete. For RFID, NFC, and iButton signals, they are continuously played back for their defined durations: RFID - 2.5 seconds, NFC - 1 second, iButton - 1 second. These defaults can be changed in [application Settings](README.md#application-settings).
 
 ## Signal Organization
 
@@ -70,7 +70,8 @@ Long pressing the `Right` button will launch a settings menu for the currently s
 * Rename: Allows you to rename the selected item. Useful for changing sorting order. The file extension is preserved on signal files. **Note: folder renaming is broken right now**
 * Delete: Deletes files and folders - folders must be empty
 * Import Here: Launches file browser to let you select a signal file from anywhere on the SDcard and then copies it to the current folder.
-  * When importing an IR file, you are prompted to select which IR command to import. This individual command is imported as it's own `.ir` file into the current location.
+  * When importing an IR file, you are prompted to select which IR command to import. This individual command is imported as it's own `.ir` file into the current location. You can also select `* IMPORT ALL *` to, well, import all commands.
+  * If an Import fails, the Flipperzero will flash red and buzz - this may be caused by a duplicate filename (i.e. that file/IR command already exists in the current folder) or the target file can not be read.
 * Create Group: Prompts for the name of a new folder that will be created at that point in the folder structure.
 
 ## Playlists
@@ -118,17 +119,22 @@ The settings menu will appear as the last item when you are viewing the "root" d
 * Show Headers: Toggles display of header/folder text at the top, giving you room for one more item on screen!
 * RFID Duration: Changes the length of time a RFID signal is transmitted. Within playlists, this can be overridden per `.rfid` file.
 * NFC Duration: Changes the length of time a NFC signal is transmitted. Within playlists, this can be overridden per `.nfc` file.
+* iButton Duration: Changes the length of time a iButton signal is transmitted. Within playlists, this can be overridden per `.ibtn` file.
 * SubGhz Ext Ant: Whether to try using the external antenna for sub-ghz signals. If this is "Enabled" but no external antenna is attached, or the external antenna can't be accessed, Quac! will fall back to using the internal antenna.
 * IR Ext Ant: Whether to use the external device for IR signals. If enabled, but no external IR device is attached to TX, then the internal IR device will be used.
 * Show Hidden: Will display files and folders that start with a period (`.`)
 * About: Application info
 
+## Troubleshooting
+
+For some errors, Quac! will show an error message on screen. In other cases, it may simply flash the LED red and vibrate. To get more information on what may be happening, it is helpful to connect your Flipperzero to your computer and view the logs. Quac! will print useful information and error information to the log file as it performs its actions. The handy `ufbt cli` command, followed by `log` will show all log statements in real time, and can be very useful if you need to report an error. Check out the [ufbt](https://github.com/flipperdevices/flipperzero-ufbt) page for more information.
+
 ## On deck
 
 * suggestions??
 
 ## Building / Install
 
-This app is currently built with `ufbt`, intended for the stock firmware. I have not tested this on other firmwares. The `.fap` file can be found in the Releases section on the right.
+This app is currently built with [ufbt](https://github.com/flipperdevices/flipperzero-ufbt), intended for the stock firmware. I have not tested this on other firmwares. The `.fap` file can be found in the Releases section on the right.
 
 <a href="https://www.buymeacoffee.com/rdefeo" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>

+ 4 - 3
README_flipperlab.md

@@ -6,11 +6,11 @@ This app allows you to organize previously recorded signals, of any type, so tha
 
 The app does not provide any recording functionality - you can use the existing Flipperzero apps to create the saved files or import from existing files. Quac! provides some basic functionality to manage your files. Or, you can manage the folder structure manually on your SD card on your PC.
 
-* Supported files include: Sub-Ghz (.sub), RFID (.rfid), Infrared (.ir), and NFC (.nfc)
+* Supported files include: Sub-Ghz (.sub), RFID (.rfid), Infrared (.ir), NFC (.nfc), and iButton (.ibtn)
 
 ## Features
 
-* Playback of rfid, sub-ghz, IR, and NFC signals
+* Playback of rfid, sub-ghz, IR, NFC, and iButton signals
 * Easy navigation
 * Flexible signal organization
 * In-app file management
@@ -20,7 +20,7 @@ The app does not provide any recording functionality - you can use the existing
 
 ## Signal playback
 
-The signal files are played back as recorded. During playback/transmit, the LED light will flash blue until the action is complete. For RFID and NFC signals, they are continuously played back for the durations specified in the Settings.
+The signal files are played back as recorded. During playback/transmit, the LED light will flash blue until the action is complete. For RFID, NFC, anbd iButton signals, they are continuously played back for the durations specified in the Settings.
 
 ## Signal Organization
 
@@ -45,6 +45,7 @@ The settings menu will appear as the last item when you are viewing the "root" d
 * Show Headers: Toggles display of header/folder text at the top, giving you room for one more item on screen!
 * RFID Duration: Changes the length of time a RFID signal is transmitted. Can be overridden, per RFID file in a Playlist
 * NFC Duration: Changes the length of time a NFC signal is transmitted. Can be overridden, per NFC file in a Playlist
+* iButton Duration: Changes the length of time a iButton signal is transmitted. Can be overridden, per iButton file in a Playlist
 * SubGhz Ext Ant: Enables / Disables use of external sub-ghz antenna
 * IR Ext Ant: Enables / Disables use of external IR antenna
 * Show Hidden: Toggles display of files/folders that start with a period.

+ 2 - 0
actions/action.c

@@ -14,6 +14,8 @@ void action_tx(void* context, Item* item, FuriString* error) {
         action_rfid_tx(context, item->path, error);
     } else if(!strcmp(item->ext, ".nfc")) {
         action_nfc_tx(context, item->path, error);
+    } else if(!strcmp(item->ext, ".ibtn")) {
+        action_ibutton_tx(context, item->path, error);
     } else if(!strcmp(item->ext, ".qpl")) {
         action_qpl_tx(context, item->path, error);
     } else {

+ 1 - 0
actions/action_i.h

@@ -9,4 +9,5 @@ void action_subghz_tx(void* context, const FuriString* action_path, FuriString*
 void action_rfid_tx(void* context, const FuriString* action_path, FuriString* error);
 void action_ir_tx(void* context, const FuriString* action_path, FuriString* error);
 void action_nfc_tx(void* context, const FuriString* action_path, FuriString* error);
+void action_ibutton_tx(void* context, const FuriString* action_path, FuriString* error);
 void action_qpl_tx(void* context, const FuriString* action_path, FuriString* error);

+ 48 - 0
actions/action_ibutton.c

@@ -0,0 +1,48 @@
+// Methods for iButton transmission
+
+#include <furi.h>
+#include <furi_hal.h>
+
+#include <ibutton/ibutton_key.h>
+#include <ibutton/ibutton_worker.h>
+#include <ibutton/ibutton_protocols.h>
+
+#include "action_i.h"
+#include "quac.h"
+
+void action_ibutton_tx(void* context, const FuriString* action_path, FuriString* error) {
+    App* app = context;
+    const char* cpath = furi_string_get_cstr(action_path);
+
+    FURI_LOG_I(TAG, "iButton: Tx %s", cpath);
+
+    iButtonProtocols* protocols = ibutton_protocols_alloc();
+    iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
+
+    const bool success = ibutton_protocols_load(protocols, key, cpath);
+    if(!success) {
+        FURI_LOG_E(TAG, "Error loading iButton file %s", cpath);
+        ACTION_SET_ERROR("Error loading %s", cpath);
+    } else {
+        FURI_LOG_I(TAG, "iButton: Starting...");
+        iButtonWorker* worker = ibutton_worker_alloc(protocols);
+        ibutton_worker_start_thread(worker);
+
+        ibutton_worker_emulate_start(worker, key);
+
+        int16_t time_ms = app->settings.ibutton_duration;
+        const int16_t interval_ms = 100;
+        while(time_ms > 0) {
+            furi_delay_ms(interval_ms);
+            time_ms -= interval_ms;
+        }
+
+        FURI_LOG_I(TAG, "iButton: Done");
+        ibutton_worker_stop(worker);
+        ibutton_worker_stop_thread(worker);
+        ibutton_worker_free(worker);
+    }
+
+    ibutton_key_free(key);
+    ibutton_protocols_free(protocols);
+}

+ 13 - 2
actions/action_qpl.c

@@ -30,9 +30,10 @@
 void action_qpl_tx(void* context, const FuriString* action_path, FuriString* error) {
     App* app = context;
 
-    // Save the current RFID and NFC Durations, in case the are changed during playback
+    // Save the current durations, in case the are changed during playback
     uint32_t orig_rfid_duration = app->settings.rfid_duration;
     uint32_t orig_nfc_duration = app->settings.nfc_duration;
+    uint32_t orig_ibutton_duration = app->settings.ibutton_duration;
 
     FuriString* buffer;
     buffer = furi_string_alloc();
@@ -84,7 +85,7 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
                     break;
                 }
 
-                // First token wasn't "pause", so maybe args_tmp is a .rfid filename followed
+                // First token wasn't "pause", so maybe args_tmp is a filename followed
                 // by a transmit duration in ms in buffer
                 // Note: Not using path_extract_extension since it expects to find slashes in the
                 // path, and thus won't work if we have a relative path file
@@ -109,6 +110,12 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
                         FURI_LOG_I(TAG, "NFC duration = %lu", nfc_duration);
                         app->settings.nfc_duration = nfc_duration;
                     }
+                } else if(!strcmp(ext, ".ibtn")) {
+                    uint32_t ibutton_duration = 0;
+                    if(sscanf(furi_string_get_cstr(buffer), "%lu", &ibutton_duration) == 1) {
+                        FURI_LOG_I(TAG, "iButton duration = %lu", ibutton_duration);
+                        app->settings.ibutton_duration = ibutton_duration;
+                    }
                 }
 
             } while(false);
@@ -145,6 +152,10 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
                 action_nfc_tx(context, buffer, error);
                 // Reset our default duration back - in case it was changed during playback
                 app->settings.nfc_duration = orig_nfc_duration;
+            } else if(!strcmp(ext, ".ibtn")) {
+                action_ibutton_tx(context, buffer, error);
+                // Reset our default duration back - in case it was changed during playback
+                app->settings.ibutton_duration = orig_ibutton_duration;
             } else if(!strcmp(ext, ".qpl")) {
                 ACTION_SET_ERROR("Playlist: Can't call playlist from playlist");
             } else {

+ 1 - 1
application.fam

@@ -8,7 +8,7 @@ App(
     stack_size=2 * 1024,
     fap_category="Tools",
     # Optional values
-    fap_version="0.6.3",
+    fap_version="0.7.0",
     fap_icon="images/quac.png",  # 10x10 1-bit PNG
     fap_description="Quick Action remote control app",
     fap_author="Roberto De Feo",

BIN
images/iButton_10px.png


+ 2 - 0
item.c

@@ -163,6 +163,8 @@ ItemType item_get_item_type_from_extension(const char* ext) {
         type = Item_IR;
     } else if(!strcmp(ext, ".nfc")) {
         type = Item_NFC;
+    } else if(!strcmp(ext, ".ibtn")) {
+        type = Item_iButton;
     } else if(!strcmp(ext, ".qpl")) {
         type = Item_Playlist;
     }

+ 1 - 0
item.h

@@ -16,6 +16,7 @@ typedef enum {
     Item_RFID,
     Item_IR,
     Item_NFC,
+    Item_iButton,
     Item_Playlist,
     Item_Group,
     Item_Settings,

+ 2 - 1
quac.h

@@ -17,7 +17,7 @@
 #include "item.h"
 
 #define QUAC_NAME    "Quac!"
-#define QUAC_VERSION "v0.6.3"
+#define QUAC_VERSION "v0.7.0"
 #define QUAC_ABOUT                                    \
     "Quick Action remote control\n" QUAC_VERSION "\n" \
     "github.com/rdefeo/quac"
@@ -60,6 +60,7 @@ typedef struct App {
         bool show_headers; // Defaults to True
         uint32_t rfid_duration; // Defaults to 2500 ms
         uint32_t nfc_duration; // Defaults to 1000 ms
+        uint32_t ibutton_duration; // Defaults to 1000 ms
         uint32_t subghz_repeat; // Defaults to 10, just like the CLI
         bool subghz_use_ext_antenna; // Defaults to False
         bool ir_use_ext_module; // Defaults to False

+ 12 - 0
quac_settings.c

@@ -12,6 +12,7 @@ void quac_set_default_settings(App* app) {
     app->settings.show_headers = true;
     app->settings.rfid_duration = 2500;
     app->settings.nfc_duration = 1000;
+    app->settings.ibutton_duration = 1000;
     app->settings.subghz_repeat = 10;
     app->settings.subghz_use_ext_antenna = false;
     app->settings.ir_use_ext_module = false;
@@ -83,6 +84,12 @@ void quac_load_settings(App* app) {
             app->settings.nfc_duration = temp_data32;
         }
 
+        if(!flipper_format_read_uint32(fff_settings, "iButton Duration", &temp_data32, 1)) {
+            FURI_LOG_W(TAG, "SETTINGS: Missing 'iButton Duration'");
+        } else {
+            app->settings.ibutton_duration = temp_data32;
+        }
+
         if(!flipper_format_read_uint32(fff_settings, "SubGHz Repeat", &temp_data32, 1)) {
             FURI_LOG_W(TAG, "SETTINGS: Missing 'SubGHz Repeat'");
         } else {
@@ -158,6 +165,11 @@ void quac_save_settings(App* app) {
             FURI_LOG_E(TAG, "SETTINGS: Failed to write 'NFC Duration'");
             break;
         }
+        if(!flipper_format_write_uint32(
+               fff_settings, "iButton Duration", &app->settings.ibutton_duration, 1)) {
+            FURI_LOG_E(TAG, "SETTINGS: Failed to write 'iButton Duration'");
+            break;
+        }
         if(!flipper_format_write_uint32(
                fff_settings, "SubGHz Repeat", &app->settings.subghz_repeat, 1)) {
             FURI_LOG_E(TAG, "SETTINGS: Failed to write 'SubGHz Repeat'");

+ 1 - 0
scenes/scene_items.c

@@ -19,6 +19,7 @@ static const ActionMenuItemType ItemToMenuItem[] = {
     [Item_RFID] = ActionMenuItemTypeRFID,
     [Item_IR] = ActionMenuItemTypeIR,
     [Item_NFC] = ActionMenuItemTypeNFC,
+    [Item_iButton] = ActionMenuItemTypeiButton,
     [Item_Playlist] = ActionMenuItemTypePlaylist,
     [Item_Group] = ActionMenuItemTypeGroup,
     [Item_Settings] = ActionMenuItemTypeSettings,

+ 14 - 0
scenes/scene_settings.c

@@ -99,6 +99,13 @@ static void scene_settings_nfc_duration_changed(VariableItem* item) {
     app->settings.nfc_duration = duration_value[index];
 }
 
+static void scene_settings_ibutton_duration_changed(VariableItem* item) {
+    App* app = variable_item_get_context(item);
+    uint8_t index = variable_item_get_current_value_index(item);
+    variable_item_set_current_value_text(item, duration_text[index]);
+    app->settings.ibutton_duration = duration_value[index];
+}
+
 static void scene_settings_subghz_repeat_changed(VariableItem* item) {
     App* app = variable_item_get_context(item);
     uint8_t index = variable_item_get_current_value_index(item);
@@ -171,6 +178,13 @@ void scene_settings_on_enter(void* context) {
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, duration_text[value_index]);
 
+    item = variable_item_list_add(
+        vil, "iButton Duration", V_DURATION_COUNT, scene_settings_ibutton_duration_changed, app);
+    value_index =
+        value_index_uint32(app->settings.ibutton_duration, duration_value, V_DURATION_COUNT);
+    variable_item_set_current_value_index(item, value_index);
+    variable_item_set_current_value_text(item, duration_text[value_index]);
+
     item = variable_item_list_add(
         vil, "SubGHz Repeat", V_REPEAT_COUNT, scene_settings_subghz_repeat_changed, app);
     value_index = value_index_uint32(app->settings.subghz_repeat, repeat_value, V_REPEAT_COUNT);

+ 1 - 0
views/action_menu.c

@@ -25,6 +25,7 @@ static const Icon* ActionMenuIcons[] = {
     [ActionMenuItemTypeRFID] = &I_RFID_10px,
     [ActionMenuItemTypeIR] = &I_IR_10px,
     [ActionMenuItemTypeNFC] = &I_NFC_10px,
+    [ActionMenuItemTypeiButton] = &I_iButton_10px,
     [ActionMenuItemTypePlaylist] = &I_Playlist_10px,
     [ActionMenuItemTypeGroup] = &I_Directory_10px,
     [ActionMenuItemTypeSettings] = &I_Settings_10px,

+ 1 - 0
views/action_menu.h

@@ -22,6 +22,7 @@ typedef enum {
     ActionMenuItemTypeRFID,
     ActionMenuItemTypeIR,
     ActionMenuItemTypeNFC,
+    ActionMenuItemTypeiButton,
     ActionMenuItemTypePlaylist,
     ActionMenuItemTypeGroup,
     ActionMenuItemTypeSettings,