Merge branch 'fz-dev' into dev

This commit is contained in:
MX 2022-10-28 18:03:31 +03:00
commit 2cfb5bdfc6
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
81 changed files with 396 additions and 19 deletions

56
.github/workflows/unit_tests.yml vendored Normal file
View file

@ -0,0 +1,56 @@
name: 'Unit tests'
on:
pull_request:
env:
TARGETS: f7
DEFAULT_TARGET: f7
jobs:
main:
runs-on: [self-hosted, FlipperZeroTest]
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Get flipper from device manager (mock)'
id: device
run: |
echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT
- name: 'Compile unit tests firmware'
id: compile
continue-on-error: true
run: |
FBT_TOOLCHAIN_PATH=/opt ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1
- name: 'Wait for flipper to finish updating'
id: connect
if: steps.compile.outcome == 'success'
continue-on-error: true
run: |
python3 ./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}}
- name: 'Format flipper SD card'
id: format
if: steps.connect.outcome == 'success'
continue-on-error: true
run: |
./scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext
- name: 'Copy unit tests to flipper'
id: copy
if: steps.format.outcome == 'success'
continue-on-error: true
run: |
./scripts/storage.py -p ${{steps.device.outputs.flipper}} send assets/unit_tests /ext/unit_tests
- name: 'Run units and validate results'
if: steps.copy.outcome == 'success'
continue-on-error: true
run: |
python3 ./scripts/testing/units.py ${{steps.device.outputs.flipper}}

View file

@ -8,4 +8,5 @@ App(
stack_size=2 * 1024,
order=150,
fap_category="Debug",
fap_icon_assets="icons",
)

View file

@ -1,4 +1,4 @@
#include "assets_icons.h"
#include <file_browser_test_icons.h>
#include "file_browser_app_i.h"
#include "gui/modules/file_browser.h"
#include <furi.h>

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

View file

@ -0,0 +1,24 @@
# Application icons
To use icons, do the following:
* add a line to the application manifest: `fap_icon_assets="folder"`, where `folder` points to the folder where your icons are located
* add `#include "application_id_icons.h"` to the application code, where `application_id` is the appid from the manifest
* every icon in the folder will be available as a `I_icon_name` variable, where `icon_name` is the name of the icon file without the extension
## Example
We have an application with the following manifest:
```
App(
appid="example_images",
...
fap_icon_assets="images",
)
```
So the icons are in the `images` folder and will be available in the generated `example_images_icons.h` file.
The example code is located in `example_images_main.c` and contains the following line:
```
#include "example_images_icons.h"
```
Image `dolphin_71x25.png` is available as `I_dolphin_71x25`.

View file

@ -5,6 +5,7 @@
#include "bad_usb_script.h"
#include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>

View file

@ -2,6 +2,7 @@
#include "../bad_usb_script.h"
#include <toolbox/path.h>
#include <gui/elements.h>
#include <assets_icons.h>
#define MAX_NAME_LEN 64

View file

@ -1,5 +1,6 @@
#include <furi.h>
#include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <storage/storage.h>
#include <gui/modules/loading.h>

View file

@ -15,6 +15,7 @@
#include <gui/modules/widget.h>
#include "views/gpio_test.h"
#include "views/gpio_usb_uart.h"
#include <assets_icons.h>
struct GpioApp {
Gui* gui;

View file

@ -4,6 +4,7 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <notification/notification_messages.h>

View file

@ -2,6 +2,7 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_stack.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>

View file

@ -5,6 +5,7 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <cli/cli.h>

View file

@ -1,5 +1,6 @@
#include "lfrfid_view_read.h"
#include <gui/elements.h>
#include <assets_icons.h>
#define TEMP_STR_LEN 128

View file

@ -7,6 +7,7 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <cli/cli.h>

View file

@ -1,5 +1,5 @@
#include "detect_reader.h"
#include <assets_icons.h>
#include <gui/elements.h>
struct DetectReader {

View file

@ -14,6 +14,7 @@
#include "views/subghz_test_packet.h"
#endif
#include <gui/gui.h>
#include <assets_icons.h>
#include <dialogs/dialogs.h>
#include <gui/scene_manager.h>
#include <notification/notification_messages.h>

View file

@ -4,6 +4,7 @@
#include "scenes/u2f_scene.h"
#include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>

View file

@ -1,5 +1,6 @@
#include "u2f_view.h"
#include <gui/elements.h>
#include <assets_icons.h>
struct U2fView {
View* view;

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -10,8 +10,9 @@ App(
],
provides=["music_player_start"],
stack_size=2 * 1024,
order=45,
fap_icon="../../../assets/icons/Archive/music_10px.png",
order=20,
fap_icon="icons/music_10px.png",
fap_icon_assets="icons",
fap_category="Music",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

View file

@ -3,7 +3,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <assets_icons.h>
#include <music_player_icons.h>
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#include <storage/storage.h>

View file

@ -17,4 +17,5 @@ App(
name="loclass",
),
],
fap_icon_assets="icons",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -2,6 +2,7 @@
#include <toolbox/path.h>
#include <flipper_format/flipper_format.h>
#include <picopass_icons.h>
#define TAG "PicopassDevice"

View file

@ -24,6 +24,7 @@
#include <storage/storage.h>
#include <lib/toolbox/path.h>
#include <picopass_icons.h>
#define PICOPASS_TEXT_STORE_SIZE 128

View file

@ -9,4 +9,5 @@ App(
order=50,
fap_icon="signal_gen_10px.png",
fap_category="Tools",
fap_icon_assets="icons",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -1,6 +1,7 @@
#include "../signal_gen_app_i.h"
#include "furi_hal.h"
#include <gui/elements.h>
#include <signal_generator_icons.h>
typedef enum {
LineIndexChannel,

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -29,6 +29,40 @@ static const SubGhzBlockConst ws_oregon2_const = {
// bit indicating the low battery
#define OREGON2_FLAG_BAT_LOW 0x4
/// Documentation for Oregon Scientific protocols can be found here:
/// http://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf
// Sensors ID
#define ID_THGR122N 0x1d20
#define ID_THGR968 0x1d30
#define ID_BTHR918 0x5d50
#define ID_BHTR968 0x5d60
#define ID_RGR968 0x2d10
#define ID_THR228N 0xec40
#define ID_THN132N 0xec40 // same as THR228N but different packet size
#define ID_RTGN318 0x0cc3 // warning: id is from 0x0cc3 and 0xfcc3
#define ID_RTGN129 0x0cc3 // same as RTGN318 but different packet size
#define ID_THGR810 0xf824 // This might be ID_THGR81, but what's true is lost in (git) history
#define ID_THGR810a 0xf8b4 // unconfirmed version
#define ID_THN802 0xc844
#define ID_PCR800 0x2914
#define ID_PCR800a 0x2d14 // Different PCR800 ID - AU version I think
#define ID_WGR800 0x1984
#define ID_WGR800a 0x1994 // unconfirmed version
#define ID_WGR968 0x3d00
#define ID_UV800 0xd874
#define ID_THN129 0xcc43 // THN129 Temp only
#define ID_RTHN129 0x0cd3 // RTHN129 Temp, clock sensors
#define ID_BTHGN129 0x5d53 // Baro, Temp, Hygro sensor
#define ID_UVR128 0xec70
#define ID_THGR328N 0xcc23 // Temp & Hygro sensor similar to THR228N with 5 channel instead of 3
#define ID_RTGR328N_1 0xdcc3 // RTGR328N_[1-5] RFclock(date &time)&Temp&Hygro sensor
#define ID_RTGR328N_2 0xccc3
#define ID_RTGR328N_3 0xbcc3
#define ID_RTGR328N_4 0xacc3
#define ID_RTGR328N_5 0x9cc3
#define ID_RTGR328N_6 0x8ce3 // RTGR328N_6&7 RFclock(date &time)&Temp&Hygro sensor like THGR328N
#define ID_RTGR328N_7 0x8ae3
struct WSProtocolDecoderOregon2 {
SubGhzProtocolDecoderBase base;
@ -101,9 +135,12 @@ static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration
}
// From sensor id code return amount of bits in variable section
// https://temofeev.ru/info/articles/o-dekodirovanii-protokola-pogodnykh-datchikov-oregon-scientific
static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) {
if(sensor_id == 0xEC40) return 16;
if(sensor_id == 0x1D20) return 24;
if(sensor_id == ID_THR228N) return 16;
if(sensor_id == ID_THGR122N) return 24;
return 0;
}
@ -134,15 +171,16 @@ static float ws_oregon2_decode_temp(uint32_t data) {
}
static void ws_oregon2_decode_var_data(WSBlockGeneric* ws_b, uint16_t sensor_id, uint32_t data) {
switch(sensor_id) {
case 0xEC40:
if(sensor_id == ID_THR228N) {
ws_b->temp = ws_oregon2_decode_temp(data);
ws_b->humidity = WS_NO_HUMIDITY;
break;
case 0x1D20:
return;
}
if(sensor_id == ID_THGR122N) {
ws_b->humidity = bcd_decode_short(data);
ws_b->temp = ws_oregon2_decode_temp(data >> 8);
break;
return;
}
}

View file

@ -1,11 +1,10 @@
#include "weather_station_receiver.h"
#include "../weather_station_app_i.h"
#include "weather_station_icons.h"
#include <weather_station_icons.h>
#include <math.h>
#include <input/input.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include <m-array.h>
#define FRAME_HEIGHT 12

View file

@ -4,6 +4,7 @@
#include <notification/notification_messages.h>
#include <gui/elements.h>
#include <assets_icons.h>
#define TAG "BtSrv"

View file

@ -1,5 +1,6 @@
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include "../desktop_i.h"
#include "desktop_view_lock_menu.h"

View file

@ -4,6 +4,7 @@
#include <gui/elements.h>
#include <gui/icon.h>
#include <gui/view.h>
#include <assets_icons.h>
#include <portmacro.h>
#include <desktop/desktop_settings.h>

View file

@ -2,6 +2,7 @@
#include <furi.h>
#include <gui/view.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include <stdint.h>
#include <portmacro.h>

View file

@ -1,6 +1,7 @@
#include "dialogs/dialogs_message.h"
#include "dialogs_i.h"
#include "dialogs_api_lock.h"
#include <assets_icons.h>
/****************** File browser ******************/

View file

@ -7,7 +7,7 @@
#include <stdint.h>
#include <gui/icon_animation.h>
#include <assets_icons.h>
#include <gui/icon.h>
#ifdef __cplusplus
extern "C" {

View file

@ -1,5 +1,6 @@
#include "gui/canvas.h"
#include "gui_i.h"
#include <assets_icons.h>
#define TAG "GuiSrv"

View file

@ -7,7 +7,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <assets_icons.h>
#include <gui/icon.h>
#ifdef __cplusplus
extern "C" {

View file

@ -5,6 +5,7 @@
#include <m-array.h>
#include <furi.h>
#include <stdint.h>
#include <assets_icons.h>
#define ITEM_FIRST_OFFSET 17
#define ITEM_NEXT_OFFSET 4

View file

@ -1,6 +1,7 @@
#include "byte_input.h"
#include <gui/elements.h>
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include "byte_input.h"
struct ByteInput {
View* view;

View file

@ -2,6 +2,7 @@
#include <m-array.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include <furi.h>
struct Menu {

View file

@ -1,5 +1,6 @@
#include "text_input.h"
#include <gui/elements.h>
#include <assets_icons.h>
#include <furi.h>
struct TextInput {

View file

@ -5,6 +5,7 @@
#include <stdint.h>
#include <gui/view_dispatcher.h>
#include <gui/gui.h>
#include <assets_icons.h>
#include <gui/modules/popup.h>
#include "views/power_off.h"

View file

@ -1,6 +1,7 @@
#include "power_off.h"
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
struct PowerOff {
View* view;

View file

@ -1,6 +1,7 @@
#include "power_unplug_usb.h"
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
struct PowerUnplugUsb {
View* view;

View file

@ -5,6 +5,7 @@
#include "storage/storage_glue.h"
#include "storages/storage_int.h"
#include "storages/storage_ext.h"
#include <assets_icons.h>
#define STORAGE_TICK 1000

View file

@ -3,6 +3,7 @@
#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/empty_screen.h>
#include <assets_icons.h>
#include <furi_hal_version.h>
#include <furi_hal_region.h>
#include <furi_hal_bt.h>

View file

@ -6,6 +6,7 @@
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <assets_icons.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/dialog_ex.h>

View file

@ -7,6 +7,7 @@
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include <dialogs/dialogs.h>
#include <assets_icons.h>
#include <desktop/desktop_settings.h>
#include <desktop/views/desktop_view_pin_input.h>

View file

@ -6,6 +6,7 @@
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <assets_icons.h>
#include "views/battery_info.h"
#include <gui/modules/submenu.h>

View file

@ -1,6 +1,7 @@
#include "battery_info.h"
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
struct BatteryInfo {
View* view;

View file

@ -4,6 +4,7 @@
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <assets_icons.h>
#include <notification/notification_messages.h>
#include <gui/modules/submenu.h>

View file

@ -2,6 +2,7 @@
#include <gui/view.h>
#include <gui/elements.h>
#include <gui/canvas.h>
#include <assets_icons.h>
#include <furi.h>
#include <input/input.h>

View file

@ -660,6 +660,24 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
return 1;
}
break;
case KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_2:
man = subghz_protocol_keeloq_common_magic_serial_type2_learning(
fix, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
return 1;
}
break;
case KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_3:
man = subghz_protocol_keeloq_common_magic_serial_type3_learning(
fix, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
return 1;
}
break;
case KEELOQ_LEARNING_UNKNOWN:
// Simple Learning
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);

View file

@ -109,6 +109,34 @@ inline uint64_t
inline uint64_t
subghz_protocol_keeloq_common_magic_serial_type1_learning(uint32_t data, uint64_t man) {
return man | ((uint64_t)data << 40) |
return (man & 0xFFFFFFFF) | ((uint64_t)data << 40) |
((uint64_t)(((data & 0xff) + ((data >> 8) & 0xFF)) & 0xFF) << 32);
}
/** Magic_serial_type2 Learning
* @param data - btn+serial number (32bit)
* @param man - magic man (64bit)
* @return manufacture for this serial number (64bit)
*/
inline uint64_t
subghz_protocol_keeloq_common_magic_serial_type2_learning(uint32_t data, uint64_t man) {
uint8_t* p = (uint8_t*)&data;
uint8_t* m = (uint8_t*)&man;
m[7] = p[0];
m[6] = p[1];
m[5] = p[2];
m[4] = p[3];
return man;
}
/** Magic_serial_type3 Learning
* @param data - serial number (24bit)
* @param man - magic man (64bit)
* @return manufacture for this serial number (64bit)
*/
inline uint64_t
subghz_protocol_keeloq_common_magic_serial_type3_learning(uint32_t data, uint64_t man) {
return (man & 0xFFFFFFFFFF000000) | (data & 0xFFFFFF);
}

View file

@ -23,6 +23,8 @@
#define KEELOQ_LEARNING_MAGIC_XOR_TYPE_1 4u
#define KEELOQ_LEARNING_FAAC 5u
#define KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_1 6u
#define KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_2 7u
#define KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_3 8u
/**
* Simple Learning Encrypt
@ -80,3 +82,19 @@ uint64_t subghz_protocol_keeloq_common_faac_learning(const uint32_t seed, const
*/
uint64_t subghz_protocol_keeloq_common_magic_serial_type1_learning(uint32_t data, uint64_t man);
/** Magic_serial_type2 Learning
* @param data - btn+serial number (32bit)
* @param man - magic man (64bit)
* @return manufacture for this serial number (64bit)
*/
uint64_t subghz_protocol_keeloq_common_magic_serial_type2_learning(uint32_t data, uint64_t man);
/** Magic_serial_type3 Learning
* @param data - btn+serial number (32bit)
* @param man - magic man (64bit)
* @return manufacture for this serial number (64bit)
*/
uint64_t subghz_protocol_keeloq_common_magic_serial_type3_learning(uint32_t data, uint64_t man);

View file

@ -340,6 +340,19 @@ class FlipperStorage:
else:
return True
def format_ext(self):
"""Create a directory on Flipper"""
self.send_and_wait_eol("storage format /ext\r")
self.send_and_wait_eol("y\r")
answer = self.read.until(self.CLI_EOL)
self.read.until(self.CLI_PROMPT)
if self.has_error(answer):
self.last_error = self.get_error(answer)
return False
else:
return True
def remove(self, path):
"""Remove file or directory on Flipper"""
self.send_and_wait_eol('storage remove "' + path + '"\r')

View file

@ -21,6 +21,11 @@ class Main(App):
self.parser_mkdir.add_argument("flipper_path", help="Flipper path")
self.parser_mkdir.set_defaults(func=self.mkdir)
self.parser_format = self.subparsers.add_parser(
"format_ext", help="Format flash card"
)
self.parser_format.set_defaults(func=self.format_ext)
self.parser_remove = self.subparsers.add_parser(
"remove", help="Remove file/directory"
)
@ -275,6 +280,17 @@ class Main(App):
storage.stop()
return 0
def format_ext(self):
if not (storage := self._get_storage()):
return 1
self.logger.debug("Formatting /ext SD card")
if not storage.format_ext():
self.logger.error(f"Error: {storage.last_error}")
storage.stop()
return 0
def stress(self):
self.logger.error("This test is wearing out flash memory.")
self.logger.error("Never use it with internal storage(/int)")

View file

@ -0,0 +1,48 @@
#!/usr/bin/env python3
import sys, os, time
def flp_serial_by_name(flp_name):
if sys.platform == "darwin": # MacOS
flp_serial = "/dev/cu.usbmodemflip_" + flp_name + "1"
elif sys.platform == "linux": # Linux
flp_serial = (
"/dev/serial/by-id/usb-Flipper_Devices_Inc._Flipper_"
+ flp_name
+ "_flip_"
+ flp_name
+ "-if00"
)
if os.path.exists(flp_serial):
return flp_serial
else:
if os.path.exists(flp_name):
return flp_name
else:
return ""
UPDATE_TIMEOUT = 30
def main():
flipper_name = sys.argv[1]
elapsed = 0
flipper = flp_serial_by_name(flipper_name)
while flipper == "" and elapsed < UPDATE_TIMEOUT:
elapsed += 1
time.sleep(1)
flipper = flp_serial_by_name(flipper_name)
if flipper == "":
print(f"Cannot find {flipper_name} flipper. Guess your flipper swam away")
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()

79
scripts/testing/units.py Normal file
View file

@ -0,0 +1,79 @@
#!/usr/bin/env python3
import sys, os
import serial
import re
from await_flipper import flp_serial_by_name
LEAK_THRESHOLD = 3000 # added until units are fixed
def main():
flp_serial = flp_serial_by_name(sys.argv[1])
if flp_serial == "":
print("Name or serial port is invalid")
sys.exit(1)
with serial.Serial(flp_serial, timeout=1) as flipper:
flipper.baudrate = 230400
flipper.flushOutput()
flipper.flushInput()
flipper.timeout = 300
flipper.read_until(b">: ").decode("utf-8")
flipper.write(b"unit_tests\r")
data = flipper.read_until(b">: ").decode("utf-8")
lines = data.split("\r\n")
tests_re = r"Failed tests: \d{0,}"
time_re = r"Consumed: \d{0,}"
leak_re = r"Leaked: \d{0,}"
status_re = r"Status: \w{3,}"
tests_pattern = re.compile(tests_re)
time_pattern = re.compile(time_re)
leak_pattern = re.compile(leak_re)
status_pattern = re.compile(status_re)
tests, time, leak, status = None, None, None, None
for line in lines:
print(line)
if not tests:
tests = re.match(tests_pattern, line)
if not time:
time = re.match(time_pattern, line)
if not leak:
leak = re.match(leak_pattern, line)
if not status:
status = re.match(status_pattern, line)
if leak is None or time is None or leak is None or status is None:
print("Failed to get data. Or output is corrupt")
sys.exit(1)
leak = int(re.findall(r"[- ]\d+", leak.group(0))[0])
status = re.findall(r"\w+", status.group(0))[1]
tests = int(re.findall(r"\d+", tests.group(0))[0])
time = int(re.findall(r"\d+", time.group(0))[0])
if tests > 0 or leak > LEAK_THRESHOLD or status != "PASSED":
print(f"Got {tests} failed tests.")
print(f"Leaked {leak} bytes.")
print(f"Status by flipper: {status}")
print(f"Time elapsed {time/1000} seconds.")
sys.exit(1)
print(
f"Tests ran successfully! Time elapsed {time/1000} seconds. Passed {tests} tests."
)
sys.exit(0)
if __name__ == "__main__":
main()