diff --git a/CHANGELOG.md b/CHANGELOG.md index 584ee3627..441823a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - Add SmartRider Parser (#203 by @jaylikesbunda) - Add API to enforce ISO15693 mode (#225 by @aaronjamt) - OFW: H World Hotel Chain Room Key Parser and MFC keys (by @zinongli) + - OFW: Parser for Tianjin Railway Transit (by @zinongli) - Infrared: - Bluray/DVD Universal Remote (#250 by @jaylikesbunda) - Option to "Load from Library File" for Universal Remotes (#255 by @zxkmm) diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 6e4d16263..0104c078c 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -290,6 +290,15 @@ App( sources=["plugins/supported_cards/hworld.c"], ) +App( + appid="trt_parser", + apptype=FlipperAppType.PLUGIN, + entry_point="trt_plugin_ep", + targets=["f7"], + requires=["nfc"], + sources=["plugins/supported_cards/trt.c"], +) + App( appid="sonicare_parser", apptype=FlipperAppType.PLUGIN, diff --git a/applications/main/nfc/plugins/supported_cards/trt.c b/applications/main/nfc/plugins/supported_cards/trt.c new file mode 100644 index 000000000..5407ab1f7 --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/trt.c @@ -0,0 +1,94 @@ +// Flipper Zero parser for for Tianjin Railway Transit (TRT) +// https://en.wikipedia.org/wiki/Tianjin_Metro +// Reverse engineering and parser development by @Torron (Github: @zinongli) + +#include "nfc_supported_card_plugin.h" +#include +#include +#include + +#define TAG "TrtParser" +#define LATEST_SALE_MARKER 0x02 +#define FULL_SALE_TIME_STAMP_PAGE 0x09 +#define BALANCE_PAGE 0x08 +#define SALE_RECORD_TIME_STAMP_A 0x0C +#define SALE_RECORD_TIME_STAMP_B 0x0E +#define SALE_YEAR_OFFSET 2000 + +static bool trt_parse(const NfcDevice* device, FuriString* parsed_data) { + furi_assert(device); + furi_assert(parsed_data); + + const MfUltralightData* data = nfc_device_get_data(device, NfcProtocolMfUltralight); + + bool parsed = false; + + do { + uint8_t latest_sale_page = 0; + + // Look for sale record signature + if(data->page[SALE_RECORD_TIME_STAMP_A].data[0] == LATEST_SALE_MARKER) { + latest_sale_page = SALE_RECORD_TIME_STAMP_A; + } else if(data->page[SALE_RECORD_TIME_STAMP_B].data[0] == LATEST_SALE_MARKER) { + latest_sale_page = SALE_RECORD_TIME_STAMP_B; + } else { + break; + } + + // Check if the sale record was backed up + const uint8_t* partial_record_pointer = &data->page[latest_sale_page - 1].data[0]; + const uint8_t* full_record_pointer = &data->page[FULL_SALE_TIME_STAMP_PAGE].data[0]; + uint32_t latest_sale_record = bit_lib_get_bits_32(partial_record_pointer, 3, 20); + uint32_t latest_sale_full_record = bit_lib_get_bits_32(full_record_pointer, 0, 27); + if(latest_sale_record != (latest_sale_full_record & 0xFFFFF)) break; + + // Parse date + // yyy yyyymmmm dddddhhh hhnnnnnn + uint16_t sale_year = ((latest_sale_full_record & 0x7F00000) >> 20) + SALE_YEAR_OFFSET; + uint8_t sale_month = (latest_sale_full_record & 0xF0000) >> 16; + uint8_t sale_day = (latest_sale_full_record & 0xF800) >> 11; + uint8_t sale_hour = (latest_sale_full_record & 0x7C0) >> 6; + uint8_t sale_minute = latest_sale_full_record & 0x3F; + + // Parse balance + uint16_t balance = bit_lib_get_bits_16(&data->page[BALANCE_PAGE].data[2], 0, 16); + uint16_t balance_yuan = balance / 100; + uint8_t balance_cent = balance % 100; + + // Format string for rendering + furi_string_cat_printf(parsed_data, "\e#TRT Tianjin Metro\n"); + furi_string_cat_printf(parsed_data, "Single-Use Ticket\n"); + furi_string_cat_printf(parsed_data, "Balance: %u.%02u RMB\n", balance_yuan, balance_cent); + furi_string_cat_printf( + parsed_data, + "Sale Date: \n%04u-%02d-%02d %02d:%02d", + sale_year, + sale_month, + sale_day, + sale_hour, + sale_minute); + parsed = true; + } while(false); + + return parsed; +} + +/* Actual implementation of app<>plugin interface */ +static const NfcSupportedCardsPlugin trt_plugin = { + .protocol = NfcProtocolMfUltralight, + .verify = NULL, + .read = NULL, + .parse = trt_parse, +}; + +/* Plugin descriptor to comply with basic plugin specification */ +static const FlipperAppPluginDescriptor trt_plugin_descriptor = { + .appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID, + .ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION, + .entry_point = &trt_plugin, +}; + +/* Plugin entry point - must return a pointer to const descriptor */ +const FlipperAppPluginDescriptor* trt_plugin_ep(void) { + return &trt_plugin_descriptor; +} diff --git a/documentation/devboard/Firmware update on Developer Board.md b/documentation/devboard/Firmware update on Developer Board.md index 0b88e52be..9cc9a8ea0 100644 --- a/documentation/devboard/Firmware update on Developer Board.md +++ b/documentation/devboard/Firmware update on Developer Board.md @@ -9,7 +9,7 @@ It's important to regularly update your Developer Board to ensure that you have ## Step 1. Install the micro Flipper Build Tool - is a cross-platform tool developed and supported by our team that enables basic development tasks for Flipper Zero, such as building and debugging applications, flashing firmware, creating VS Code development configurations, and flashing firmware to the Wi-Fi Developer Board. +[micro Flipper Build Tool (uFBT)](https://pypi.org/project/ufbt/) is a cross-platform tool developed and supported by our team that enables basic development tasks for Flipper Zero, such as building and debugging applications, flashing firmware, creating VS Code development configurations, and flashing firmware to the Wi-Fi Developer Board. **On Linux & macOS:** @@ -43,15 +43,15 @@ To update the firmware, you need to switch your Developer Board to Bootloader mo - **Windows:** Go to **Device Manager** and expand the **Ports (COM & LPT)** section. 2. Connect the Developer Board to your computer using a USB-C cable. - \image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_update_wired_connection.jpg width=700 3. Switch your Developer Board to Bootloader mode: - 1. Press and hold the **BOOT** button. - 2. Press the **RESET** button while holding the **BOOT** button. - 3. Release the **BOOT** button. + 3.1. Press and hold the **BOOT** button. + 3.2. Press the **RESET** button while holding the **BOOT** button. + + 3.3. Release the **BOOT** button. \image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_reboot_to_bootloader.png width=700 4. Repeat **Step 1** and view the name of your Developer Board that appeared in the list. @@ -101,7 +101,6 @@ To fix it, try doing the following: ## Step 4. Finish the installation 1. Reboot the Developer Board by pressing the **RESET** button. - \image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_reboot_after_flashing.jpg width=700 2. Disconnect and reconnect the USB-C cable. diff --git a/documentation/devboard/Get started with the Dev Board.md b/documentation/devboard/Get started with the Dev Board.md index 141bf6411..f9458cb83 100644 --- a/documentation/devboard/Get started with the Dev Board.md +++ b/documentation/devboard/Get started with the Dev Board.md @@ -1,4 +1,4 @@ -# Get started with the Dev Board {#dev_board_get_started} +# Get started with the Devboard {#dev_board_get_started} \image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_developer_board_box_CDN.jpg width=700 diff --git a/documentation/devboard/Reading logs via the Dev Board.md b/documentation/devboard/Reading logs via the Dev Board.md index 011b331e8..ceec76c87 100644 --- a/documentation/devboard/Reading logs via the Dev Board.md +++ b/documentation/devboard/Reading logs via the Dev Board.md @@ -1,4 +1,4 @@ -# Reading logs via the Dev Board {#dev_board_reading_logs} +# Reading logs via the Devboard {#dev_board_reading_logs} The Developer Board allows you to read Flipper Zero logs via UART. Unlike reading logs via the command-line interface (CLI), the Developer Board enables you to collect logs from the device directly to a serial console independently from the operating system of Flipper Zero. It allows you to see the device's logs when it's loading, updating, or crashing. It's useful for debugging and troubleshooting during software development. diff --git a/documentation/devboard/Wi-Fi connection to the Devboard.md b/documentation/devboard/Wi-Fi connection to the Devboard.md index fd3bc3249..838964645 100644 --- a/documentation/devboard/Wi-Fi connection to the Devboard.md +++ b/documentation/devboard/Wi-Fi connection to the Devboard.md @@ -54,7 +54,6 @@ To connect the Developer Board in **Wi-Fi client** mode, you need to configure i 4. Select the **STA** mode and enter your network's **SSID** (name) and **password**. For convenience, you can click the **+** button to see the list of nearby 2.4 GHz networks (5 GHz networks aren't supported). 5. Save the configuration and reboot the Developer Board. - \image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_connect_to_WiFi_CDN.jpg width=700 6. Now, you can access the Devboard's web interface at [http://blackmagic.local](https://blackmagic.local) via the existing Wi-Fi network without losing connection to the internet.