This commit is contained in:
Willy-JL
2023-07-14 17:06:16 +02:00
32 changed files with 794 additions and 302 deletions

View File

@@ -1,6 +1,6 @@
App(
appid="lightmeter",
name="[BH1750] Lightmeter",
name="Lightmeter",
apptype=FlipperAppType.EXTERNAL,
entry_point="lightmeter_app",
requires=[
@@ -8,6 +8,7 @@ App(
],
stack_size=1 * 1024,
order=90,
fap_version=(1, 1),
fap_icon="lightmeter.png",
fap_category="GPIO",
fap_private_libs=[
@@ -18,9 +19,16 @@ App(
"BH1750.c",
],
),
Lib(
name="MAX44009",
cincludes=["."],
sources=[
"MAX44009.c",
],
),
],
fap_description="Lightmeter app for photography",
fap_author="Oleksii Kutuzov",
fap_weburl="https://github.com/oleksiikutuzov/flipperzero-lightmeter",
fap_icon_assets="icons",
fap_author="@oleksiikutuzov",
fap_version="1.0",
fap_description="Lightmeter app for photography based on BH1750 sensor",
)

View File

@@ -51,12 +51,18 @@ static const char* lux_only[] = {
[LUX_ONLY_ON] = "On",
};
static const char* sensor_type[] = {
[SENSOR_BH1750] = "BH1750",
[SENSOR_MAX44009] = "MAX44009",
};
enum LightMeterSubmenuIndex {
LightMeterSubmenuIndexISO,
LightMeterSubmenuIndexND,
LightMeterSubmenuIndexDome,
LightMeterSubmenuIndexBacklight,
LightMeterSubmenuIndexLuxMeter,
LightMeterSubmenuIndexSensorType,
LightMeterSubmenuIndexHelp,
LightMeterSubmenuIndexAbout,
};
@@ -127,6 +133,17 @@ static void lux_only_cb(VariableItem* item) {
lightmeter_app_set_config(app, config);
}
static void sensor_type_cb(VariableItem* item) {
LightMeterApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, sensor_type[index]);
LightMeterConfig* config = app->config;
config->sensor_type = index;
lightmeter_app_set_config(app, config);
}
static void ok_cb(void* context, uint32_t index) {
LightMeterApp* app = context;
UNUSED(app);
@@ -173,6 +190,11 @@ void lightmeter_scene_config_on_enter(void* context) {
variable_item_set_current_value_index(item, config->lux_only);
variable_item_set_current_value_text(item, lux_only[config->lux_only]);
item = variable_item_list_add(
var_item_list, "Sensor", COUNT_OF(sensor_type), sensor_type_cb, app);
variable_item_set_current_value_index(item, config->sensor_type);
variable_item_set_current_value_text(item, sensor_type[config->sensor_type]);
item = variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL);
item = variable_item_list_add(var_item_list, "About", 0, NULL, NULL);

View File

@@ -6,7 +6,8 @@ void lightmeter_scene_help_on_enter(void* context) {
FuriString* temp_str;
temp_str = furi_string_alloc();
furi_string_printf(
temp_str, "App works with BH1750\nambient light sensor\nconnected via I2C interface\n\n");
temp_str,
"App works with BH1750 and MAX44409 ambient light sensor connected via I2C interface\n\n");
furi_string_cat(temp_str, "\e#Pinout:\r\n");
furi_string_cat(
temp_str,

View File

@@ -9,6 +9,7 @@ static void lightmeter_scene_main_on_left(void* context) {
void lightmeter_scene_main_on_enter(void* context) {
LightMeterApp* app = context;
lightmeter_app_i2c_init_sensor(context);
lightmeter_main_view_set_left_callback(app->main_view, lightmeter_scene_main_on_left, app);
view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewMainView);
}
@@ -39,5 +40,5 @@ bool lightmeter_scene_main_on_event(void* context, SceneManagerEvent event) {
}
void lightmeter_scene_main_on_exit(void* context) {
UNUSED(context);
lightmeter_app_i2c_deinit_sensor(context);
}

View File

@@ -0,0 +1,27 @@
#include <MAX44009.h>
#include <math.h>
#include <furi.h>
void max44009_init() {
furi_hal_i2c_acquire(I2C_BUS);
furi_hal_i2c_write_reg_8(I2C_BUS, MAX44009_ADDR,
MAX44009_REG_CONFIG, MAX44009_REG_CONFIG_CONT_MODE, I2C_TIMEOUT);
furi_hal_i2c_release(I2C_BUS);
}
int max44009_read_light(float* result) {
uint8_t data_one = 0;
uint8_t exp, mantissa;
int status;
furi_hal_i2c_acquire(I2C_BUS);
furi_hal_i2c_read_reg_8(I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_HI, &data_one, I2C_TIMEOUT);
exp = (data_one & MAX44009_REG_LUX_HI_EXP_MASK) >> 4;
mantissa = (data_one & MAX44009_REG_LUX_HI_MANT_HI_MASK) << 4;
status = furi_hal_i2c_read_reg_8(I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_LO, &data_one, I2C_TIMEOUT);
mantissa |= (data_one & MAX44009_REG_LUX_LO_MANT_LO_MASK);
furi_hal_i2c_release(I2C_BUS);
*result = (float)pow(2, exp) * mantissa * 0.045;
FURI_LOG_D("MAX44009", "exp %d, mant %d, lux %f", exp, mantissa, (double)*result);
return status;
}

View File

@@ -0,0 +1,26 @@
#include <furi.h>
#include <furi_hal.h>
#pragma once
// I2C BUS
#define I2C_BUS &furi_hal_i2c_handle_external
#define I2C_TIMEOUT 10
#define MAX44009_ADDR (0x4A << 1)
#define MAX44009_REG_INT_STATUS 0x00
#define MAX44009_REG_INT_EN 0x01
#define MAX44009_REG_CONFIG 0x02
#define MAX44009_REG_CONFIG_CONT_MODE (1 << 7)
#define MAX44009_REG_LUX_HI 0x03
#define MAX44009_REG_LUX_HI_EXP_MASK 0xF0
#define MAX44009_REG_LUX_HI_MANT_HI_MASK 0x0F
#define MAX44009_REG_LUX_LO 0x04
#define MAX44009_REG_LUX_LO_MANT_LO_MASK 0x0F
#define MAX44009_REG_THRESH_HI 0x05
#define MAX44009_REG_THRESH_LO 0x06
#define MAX44009_REG_INT_TIME 0x07
void max44009_init();
int max44009_read_light(float* result);

View File

@@ -27,11 +27,6 @@ static void lightmeter_tick_event_callback(void* context) {
LightMeterApp* lightmeter_app_alloc(uint32_t first_scene) {
LightMeterApp* app = malloc(sizeof(LightMeterApp));
// Sensor
bh1750_set_power_state(1);
bh1750_init();
bh1750_set_mode(ONETIME_HIGH_RES_MODE);
// Set default values to config
app->config = malloc(sizeof(LightMeterConfig));
app->config->iso = DEFAULT_ISO;
@@ -117,8 +112,6 @@ void lightmeter_app_free(LightMeterApp* app) {
}
furi_record_close(RECORD_NOTIFICATION);
bh1750_set_power_state(0);
free(app->config);
free(app);
}
@@ -138,6 +131,38 @@ void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config)
app->config = config;
}
void lightmeter_app_i2c_init_sensor(LightMeterApp* context) {
LightMeterApp* app = context;
switch(app->config->sensor_type) {
case SENSOR_BH1750:
bh1750_set_power_state(1);
bh1750_init();
bh1750_set_mode(ONETIME_HIGH_RES_MODE);
break;
case SENSOR_MAX44009:
max44009_init();
break;
default:
FURI_LOG_E(TAG, "Invalid sensor type %d", app->config->sensor_type);
return;
}
}
void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context) {
LightMeterApp* app = context;
switch(app->config->sensor_type) {
case SENSOR_BH1750:
bh1750_set_power_state(0);
break;
case SENSOR_MAX44009:
// nothing
break;
default:
FURI_LOG_E(TAG, "Invalid sensor type %d", app->config->sensor_type);
return;
}
}
void lightmeter_app_i2c_callback(LightMeterApp* context) {
LightMeterApp* app = context;
@@ -145,16 +170,18 @@ void lightmeter_app_i2c_callback(LightMeterApp* context) {
float lux = 0;
bool response = 0;
if(bh1750_trigger_manual_conversion() == BH1750_OK) response = 1;
if(response) {
bh1750_read_light(&lux);
if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT;
EV = lux2ev(lux);
if(app->config->sensor_type == SENSOR_BH1750) {
if(bh1750_trigger_manual_conversion() == BH1750_OK) {
bh1750_read_light(&lux);
response = 1;
}
} else if(app->config->sensor_type == SENSOR_MAX44009) {
if(max44009_read_light(&lux)) response = 1;
}
if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT;
EV = lux2ev(lux);
main_view_set_lux(app->main_view, lux);
main_view_set_EV(app->main_view, EV);
main_view_set_response(app->main_view, response);

View File

@@ -18,6 +18,7 @@
#include "lightmeter_config.h"
#include <BH1750.h>
#include <MAX44009.h>
typedef struct {
int iso;
@@ -26,6 +27,7 @@ typedef struct {
int dome;
int backlight;
int lux_only;
int sensor_type;
} LightMeterConfig;
typedef struct {
@@ -55,4 +57,6 @@ typedef enum {
void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config);
void lightmeter_app_i2c_init_sensor(LightMeterApp* context);
void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context);
void lightmeter_app_i2c_callback(LightMeterApp* context);

View File

@@ -1,6 +1,6 @@
#pragma once
#define LM_VERSION_APP "0.7"
#define LM_VERSION_APP "1.1"
#define LM_DEVELOPED "Oleksii Kutuzov"
#define LM_GITHUB "https://github.com/oleksiikutuzov/flipperzero-lightmeter"
@@ -105,4 +105,9 @@ typedef enum {
LUX_ONLY_ON,
} LightMeterLuxOnlyMode;
typedef enum {
SENSOR_BH1750,
SENSOR_MAX44009,
} LightMeterSensorType;
typedef enum { BACKLIGHT_AUTO, BACKLIGHT_ON } LightMeterBacklight;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -136,8 +136,8 @@ static const WIFI_TextInputKey symbol_keyboard_keys_row_3[] = {
{SWITCH_KEYBOARD_KEY, 1, 23},
{'.', 15, 32},
{',', 29, 32},
{';', 41, 32},
{'`', 53, 32},
{':', 41, 32},
{'/', 53, 32},
{'\'', 65, 32},
{ENTER_KEY, 74, 23},
{'7', 100, 32},
@@ -233,6 +233,12 @@ static bool char_is_lowercase(char letter) {
static char char_to_uppercase(const char letter) {
if(letter == '_') {
return 0x20;
} else if(letter == ':') {
return 0x3B;
} else if(letter == '/') {
return 0x5C;
} else if(letter == '\'') {
return 0x60;
} else if(char_is_lowercase(letter)) {
return (letter - 0x20);
} else {

View File

@@ -89,6 +89,14 @@ void cli_command_help(Cli* cli, FuriString* args, void* context) {
}
}
void cli_command_uptime(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
UNUSED(args);
UNUSED(context);
uint32_t uptime = furi_get_tick() / furi_kernel_get_tick_frequency();
printf("Uptime: %luh%lum%lus", uptime / 60 / 60, uptime / 60 % 60, uptime % 60);
}
void cli_command_date(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
UNUSED(context);
@@ -463,6 +471,7 @@ void cli_commands_init(Cli* cli) {
cli_add_command(cli, "?", CliCommandFlagParallelSafe, cli_command_help, NULL);
cli_add_command(cli, "help", CliCommandFlagParallelSafe, cli_command_help, NULL);
cli_add_command(cli, "uptime", CliCommandFlagDefault, cli_command_uptime, NULL);
cli_add_command(cli, "date", CliCommandFlagParallelSafe, cli_command_date, NULL);
cli_add_command(cli, "log", CliCommandFlagParallelSafe, cli_command_log, NULL);
cli_add_command(cli, "sysctl", CliCommandFlagDefault, cli_command_sysctl, NULL);

View File

@@ -14,8 +14,6 @@ void desktop_scene_debug_callback(DesktopEvent event, void* context) {
void desktop_scene_debug_on_enter(void* context) {
Desktop* desktop = (Desktop*)context;
desktop_debug_get_dolphin_data(desktop->debug_view);
desktop_debug_set_callback(desktop->debug_view, desktop_scene_debug_callback, desktop);
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdDebug);
}
@@ -32,24 +30,6 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) {
dolphin_flush(dolphin);
consumed = true;
break;
case DesktopDebugEventDeed:
dolphin_deed(DolphinDeedTestRight);
desktop_debug_get_dolphin_data(desktop->debug_view);
consumed = true;
break;
case DesktopDebugEventWrongDeed:
dolphin_deed(DolphinDeedTestLeft);
desktop_debug_get_dolphin_data(desktop->debug_view);
consumed = true;
break;
case DesktopDebugEventSaveState:
dolphin_flush(dolphin);
consumed = true;
break;
default:
break;
}
@@ -60,6 +40,5 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) {
}
void desktop_scene_debug_on_exit(void* context) {
Desktop* desktop = (Desktop*)context;
desktop_debug_reset_screen_idx(desktop->debug_view);
UNUSED(context);
}

View File

@@ -18,95 +18,70 @@ void desktop_debug_set_callback(
}
void desktop_debug_render(Canvas* canvas, void* model) {
UNUSED(model);
canvas_clear(canvas);
DesktopDebugViewModel* m = model;
const Version* ver;
char buffer[64];
static const char* headers[] = {"Device Info:", "Dolphin Info:"};
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(
canvas, 64, 1 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignTop, headers[m->screen]);
uint32_t uptime = furi_get_tick() / furi_kernel_get_tick_frequency();
snprintf(
buffer,
sizeof(buffer),
"Uptime: %luh%lum%lus",
uptime / 60 / 60,
uptime / 60 % 60,
uptime % 60);
canvas_draw_str_aligned(canvas, 64, 1 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignTop, buffer);
canvas_set_font(canvas, FontSecondary);
if(m->screen != DesktopViewStatsMeta) {
// Hardware version
const char* my_name = furi_hal_version_get_name_ptr();
snprintf(
buffer,
sizeof(buffer),
"%d.F%dB%dC%d %s %s",
furi_hal_version_get_hw_version(),
furi_hal_version_get_hw_target(),
furi_hal_version_get_hw_body(),
furi_hal_version_get_hw_connect(),
furi_hal_version_get_hw_region_name_otp(),
my_name ? my_name : "Unknown");
canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer);
// Hardware version
const char* my_name = furi_hal_version_get_name_ptr();
snprintf(
buffer,
sizeof(buffer),
"%d.F%dB%dC%d %s %s",
furi_hal_version_get_hw_version(),
furi_hal_version_get_hw_target(),
furi_hal_version_get_hw_body(),
furi_hal_version_get_hw_connect(),
furi_hal_version_get_hw_region_name_otp(),
my_name ? my_name : "Unknown");
canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer);
ver = furi_hal_version_get_firmware_version();
const BleGlueC2Info* c2_ver = NULL;
ver = furi_hal_version_get_firmware_version();
const BleGlueC2Info* c2_ver = NULL;
#ifdef SRV_BT
c2_ver = ble_glue_get_c2_info();
c2_ver = ble_glue_get_c2_info();
#endif
if(!ver) { //-V1051
canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info");
return;
}
snprintf(
buffer,
sizeof(buffer),
"%s [%s]",
version_get_version(ver),
version_get_builddate(ver));
canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer);
uint16_t api_major, api_minor;
furi_hal_info_get_api_version(&api_major, &api_minor);
snprintf(
buffer,
sizeof(buffer),
"%s%s [%d.%d] %s",
version_get_dirty_flag(ver) ? "[!] " : "",
version_get_githash(ver),
api_major,
api_minor,
c2_ver ? c2_ver->StackTypeString : "<none>");
canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer);
snprintf(
buffer, sizeof(buffer), "[%d] %s", version_get_target(ver), version_get_gitbranch(ver));
canvas_draw_str(canvas, 0, 50 + STATUS_BAR_Y_SHIFT, buffer);
} else {
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
DolphinStats stats = dolphin_stats(dolphin);
furi_record_close(RECORD_DOLPHIN);
uint32_t current_lvl = stats.level;
uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter);
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, sizeof(buffer), "Icounter: %lu Butthurt %lu", m->icounter, m->butthurt);
canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer);
snprintf(
buffer,
sizeof(buffer),
"Level: %lu To level up: %lu",
current_lvl,
(remaining == (uint32_t)(-1) ? remaining : 0));
canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, buffer);
// even if timestamp is uint64_t, it's safe to cast it to uint32_t, because furi_hal_rtc_datetime_to_timestamp only returns uint32_t
snprintf(buffer, sizeof(buffer), "%lu", (uint32_t)m->timestamp);
canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer);
canvas_draw_str(canvas, 0, 49 + STATUS_BAR_Y_SHIFT, "[< >] icounter value [ok] save");
if(!ver) { //-V1051
canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info");
return;
}
snprintf(
buffer, sizeof(buffer), "%s [%s]", version_get_version(ver), version_get_builddate(ver));
canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer);
uint16_t api_major, api_minor;
furi_hal_info_get_api_version(&api_major, &api_minor);
snprintf(
buffer,
sizeof(buffer),
"%s%s [%d.%d] %s",
version_get_dirty_flag(ver) ? "[!] " : "",
version_get_githash(ver),
api_major,
api_minor,
c2_ver ? c2_ver->StackTypeString : "<none>");
canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer);
snprintf(
buffer, sizeof(buffer), "[%d] %s", version_get_target(ver), version_get_gitbranch(ver));
canvas_draw_str(canvas, 0, 50 + STATUS_BAR_Y_SHIFT, buffer);
}
View* desktop_debug_get_view(DesktopDebugView* debug_view) {
@@ -114,61 +89,43 @@ View* desktop_debug_get_view(DesktopDebugView* debug_view) {
return debug_view->view;
}
bool desktop_debug_input(InputEvent* event, void* context) {
static bool desktop_debug_input(InputEvent* event, void* context) {
furi_assert(event);
furi_assert(context);
DesktopDebugView* debug_view = context;
if(event->type != InputTypeShort && event->type != InputTypeRepeat) {
return false;
}
DesktopViewStatsScreens current = 0;
with_view_model(
debug_view->view,
DesktopDebugViewModel * model,
{
#ifdef SRV_DOLPHIN_STATE_DEBUG
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
model->screen = !model->screen;
}
#endif
current = model->screen;
},
true);
size_t count = (event->type == InputTypeRepeat) ? 10 : 1;
if(current == DesktopViewStatsMeta) {
if(event->key == InputKeyLeft) {
while(count-- > 0) {
debug_view->callback(DesktopDebugEventWrongDeed, debug_view->context);
}
} else if(event->key == InputKeyRight) {
while(count-- > 0) {
debug_view->callback(DesktopDebugEventDeed, debug_view->context);
}
} else if(event->key == InputKeyOk) {
debug_view->callback(DesktopDebugEventSaveState, debug_view->context);
} else {
return false;
}
}
if(event->key == InputKeyBack) {
if(event->key == InputKeyBack && event->type == InputTypeShort) {
debug_view->callback(DesktopDebugEventExit, debug_view->context);
}
return true;
}
static void desktop_debug_enter(void* context) {
DesktopDebugView* debug_view = context;
furi_timer_start(debug_view->timer, furi_ms_to_ticks(1000));
}
static void desktop_debug_exit(void* context) {
DesktopDebugView* debug_view = context;
furi_timer_stop(debug_view->timer);
}
void desktop_debug_timer(void* context) {
DesktopDebugView* debug_view = context;
view_get_model(debug_view->view);
view_commit_model(debug_view->view, true);
}
DesktopDebugView* desktop_debug_alloc() {
DesktopDebugView* debug_view = malloc(sizeof(DesktopDebugView));
debug_view->view = view_alloc();
view_allocate_model(debug_view->view, ViewModelTypeLocking, sizeof(DesktopDebugViewModel));
debug_view->timer = furi_timer_alloc(desktop_debug_timer, FuriTimerTypePeriodic, debug_view);
view_set_context(debug_view->view, debug_view);
view_set_draw_callback(debug_view->view, (ViewDrawCallback)desktop_debug_render);
view_set_input_callback(debug_view->view, desktop_debug_input);
view_set_enter_callback(debug_view->view, desktop_debug_enter);
view_set_exit_callback(debug_view->view, desktop_debug_exit);
return debug_view;
}
@@ -176,27 +133,7 @@ DesktopDebugView* desktop_debug_alloc() {
void desktop_debug_free(DesktopDebugView* debug_view) {
furi_assert(debug_view);
furi_timer_free(debug_view->timer);
view_free(debug_view->view);
free(debug_view);
}
void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) {
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
DolphinStats stats = dolphin_stats(dolphin);
with_view_model(
debug_view->view,
DesktopDebugViewModel * model,
{
model->icounter = stats.icounter;
model->butthurt = stats.butthurt;
model->timestamp = stats.timestamp;
},
true);
furi_record_close(RECORD_DOLPHIN);
}
void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view) {
with_view_model(
debug_view->view, DesktopDebugViewModel * model, { model->screen = 0; }, true);
}

View File

@@ -8,26 +8,13 @@ typedef struct DesktopDebugView DesktopDebugView;
typedef void (*DesktopDebugViewCallback)(DesktopEvent event, void* context);
// Debug info
typedef enum {
DesktopViewStatsFw,
DesktopViewStatsMeta,
DesktopViewStatsTotalCount,
} DesktopViewStatsScreens;
struct DesktopDebugView {
View* view;
FuriTimer* timer;
DesktopDebugViewCallback callback;
void* context;
};
typedef struct {
uint32_t icounter;
uint32_t butthurt;
uint64_t timestamp;
DesktopViewStatsScreens screen;
} DesktopDebugViewModel;
void desktop_debug_set_callback(
DesktopDebugView* debug_view,
DesktopDebugViewCallback callback,
@@ -36,7 +23,5 @@ void desktop_debug_set_callback(
View* desktop_debug_get_view(DesktopDebugView* debug_view);
DesktopDebugView* desktop_debug_alloc();
void desktop_debug_free(DesktopDebugView* debug_view);
void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view);
void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view);
void desktop_debug_free(DesktopDebugView* debug_view);

View File

@@ -1,5 +1,4 @@
#include "submenu.h"
#include <gui/canvas_i.h>
#include <assets_icons.h>
#include <gui/elements.h>
@@ -66,23 +65,24 @@ typedef struct {
size_t position;
size_t window_position;
bool locked_message_visible;
bool is_vertical;
} SubmenuModel;
static void submenu_process_up(Submenu* submenu);
static void submenu_process_down(Submenu* submenu);
static void submenu_process_ok(Submenu* submenu);
static size_t submenu_items_on_screen(bool header, bool vertical) {
size_t res = (vertical) ? 8 : 4;
return (header) ? res - 1 : res;
}
static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
SubmenuModel* model = _model;
const uint8_t item_height = 16;
uint8_t item_width = canvas_width(canvas) - 5;
if(canvas->orientation == CanvasOrientationVertical ||
canvas->orientation == CanvasOrientationVerticalFlip) {
item_width = 60;
}
canvas_clear(canvas);
if(!furi_string_empty(model->header)) {
@@ -97,7 +97,8 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
SubmenuItemArray_next(it)) {
const size_t item_position = position - model->window_position;
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
uint8_t y_offset = furi_string_empty(model->header) ? 0 : 16;
if(item_position < items_on_screen) {
@@ -117,7 +118,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
if(SubmenuItemArray_cref(it)->locked) {
canvas_draw_icon(
canvas,
110,
item_width - 10,
y_offset + (item_position * item_height) + item_height - 12,
&I_Lock_7x8);
}
@@ -125,7 +126,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
FuriString* disp_str;
disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
elements_string_fit_width(
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 25 : 11));
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 21 : 11));
canvas_draw_str(
canvas,
@@ -142,20 +143,39 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
elements_scrollbar(canvas, model->position, SubmenuItemArray_size(model->items));
if(model->locked_message_visible) {
const uint8_t frame_x = 7;
const uint8_t frame_width = canvas_width(canvas) - frame_x * 2;
const uint8_t frame_y = 7;
const uint8_t frame_height = canvas_height(canvas) - frame_y * 2;
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, 8, 10, 110, 48);
canvas_draw_box(canvas, frame_x + 2, frame_y + 2, frame_width - 4, frame_height - 4);
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
elements_multiline_text_aligned(
canvas,
84,
32,
AlignCenter,
AlignCenter,
furi_string_get_cstr(
SubmenuItemArray_get(model->items, model->position)->locked_message));
canvas_draw_icon(
canvas, frame_x + 2, canvas_height(canvas) - frame_y - 2 - 42, &I_WarningDolphin_45x42);
canvas_draw_rframe(canvas, frame_x, frame_y, frame_width, frame_height, 3);
canvas_draw_rframe(canvas, frame_x + 1, frame_y + 1, frame_width - 2, frame_height - 2, 2);
if(model->is_vertical) {
elements_multiline_text_aligned(
canvas,
32,
42,
AlignCenter,
AlignCenter,
furi_string_get_cstr(
SubmenuItemArray_get(model->items, model->position)->locked_message));
} else {
elements_multiline_text_aligned(
canvas,
84,
32,
AlignCenter,
AlignCenter,
furi_string_get_cstr(
SubmenuItemArray_get(model->items, model->position)->locked_message));
}
}
}
@@ -303,6 +323,7 @@ void submenu_add_lockable_item(
void submenu_reset(Submenu* submenu) {
furi_assert(submenu);
view_set_orientation(submenu->view, ViewOrientationHorizontal);
with_view_model(
submenu->view,
@@ -311,6 +332,7 @@ void submenu_reset(Submenu* submenu) {
SubmenuItemArray_reset(model->items);
model->position = 0;
model->window_position = 0;
model->is_vertical = false;
furi_string_reset(model->header);
},
true);
@@ -344,7 +366,8 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
model->window_position -= 1;
}
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
if(items_size <= items_on_screen) {
model->window_position = 0;
@@ -363,7 +386,8 @@ void submenu_process_up(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position > 0) {
@@ -386,7 +410,8 @@ void submenu_process_down(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position < items_size - 1) {
@@ -441,3 +466,48 @@ void submenu_set_header(Submenu* submenu, const char* header) {
},
true);
}
void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation) {
furi_assert(submenu);
const bool is_vertical =
(orientation == ViewOrientationVertical || orientation == ViewOrientationVerticalFlip) ?
true :
false;
view_set_orientation(submenu->view, orientation);
with_view_model(
submenu->view,
SubmenuModel * model,
{
model->is_vertical = is_vertical;
// Recalculating the position
// Need if _set_orientation is called after _set_selected_item
size_t position = model->position;
const size_t items_size = SubmenuItemArray_size(model->items);
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
if(position >= items_size) {
position = 0;
}
model->position = position;
model->window_position = position;
if(model->window_position > 0) {
model->window_position -= 1;
}
if(items_size <= items_on_screen) {
model->window_position = 0;
} else {
const size_t pos = items_size - items_on_screen;
if(model->window_position > pos) {
model->window_position = pos;
}
}
},
true);
}

View File

@@ -93,6 +93,13 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index);
*/
void submenu_set_header(Submenu* submenu, const char* header);
/** Set Orientation
*
* @param submenu Submenu instance
* @param orientation either vertical or horizontal
*/
void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation);
#ifdef __cplusplus
}
#endif

View File

@@ -20,7 +20,7 @@ static int32_t loader_applications_thread(void* p);
LoaderApplications* loader_applications_alloc(void (*closed_cb)(void*), void* context) {
LoaderApplications* loader_applications = malloc(sizeof(LoaderApplications));
loader_applications->thread =
furi_thread_alloc_ex(TAG, 512, loader_applications_thread, (void*)loader_applications);
furi_thread_alloc_ex(TAG, 768, loader_applications_thread, (void*)loader_applications);
loader_applications->closed_cb = closed_cb;
loader_applications->context = context;
furi_thread_start(loader_applications->thread);

View File

@@ -19,7 +19,7 @@ static const char* update_task_stage_descr[] = {
[UpdateTaskStageRadioErase] = "Uninstalling radio FW",
[UpdateTaskStageRadioWrite] = "Writing radio FW",
[UpdateTaskStageRadioInstall] = "Installing radio FW",
[UpdateTaskStageRadioBusy] = "Radio is updating",
[UpdateTaskStageRadioBusy] = "Core 2 busy",
[UpdateTaskStageOBValidation] = "Validating opt. bytes",
[UpdateTaskStageLfsBackup] = "Backing up LFS",
[UpdateTaskStageLfsRestore] = "Restoring LFS",
@@ -30,6 +30,191 @@ static const char* update_task_stage_descr[] = {
[UpdateTaskStageOBError] = "OB, report",
};
static const struct {
UpdateTaskStage stage;
uint8_t percent_min, percent_max;
const char* descr;
} update_task_error_detail[] = {
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 0,
.percent_max = 13,
.descr = "Wrong Updater HW",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 14,
.percent_max = 20,
.descr = "Manifest pointer error",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 21,
.percent_max = 30,
.descr = "Manifest load error",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 31,
.percent_max = 40,
.descr = "Wrong package version",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 41,
.percent_max = 50,
.descr = "HW Target mismatch",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 51,
.percent_max = 60,
.descr = "No DFU file",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 61,
.percent_max = 80,
.descr = "No Radio file",
},
#ifndef FURI_RAM_EXEC
{
.stage = UpdateTaskStageLfsBackup,
.percent_min = 0,
.percent_max = 100,
.descr = "FS R/W error",
},
#else
{
.stage = UpdateTaskStageRadioImageValidate,
.percent_min = 0,
.percent_max = 98,
.descr = "FS Read error",
},
{
.stage = UpdateTaskStageRadioImageValidate,
.percent_min = 99,
.percent_max = 100,
.descr = "CRC mismatch",
},
{
.stage = UpdateTaskStageRadioErase,
.percent_min = 0,
.percent_max = 30,
.descr = "Stack remove: cmd error",
},
{
.stage = UpdateTaskStageRadioErase,
.percent_min = 31,
.percent_max = 100,
.descr = "Stack remove: wait failed",
},
{
.stage = UpdateTaskStageRadioWrite,
.percent_min = 0,
.percent_max = 100,
.descr = "Stack write: error",
},
{
.stage = UpdateTaskStageRadioInstall,
.percent_min = 0,
.percent_max = 10,
.descr = "Stack install: cmd error",
},
{
.stage = UpdateTaskStageRadioInstall,
.percent_min = 11,
.percent_max = 100,
.descr = "Stack install: wait failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 0,
.percent_max = 10,
.descr = "Failed to start C2",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 11,
.percent_max = 20,
.descr = "C2 FUS swich failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 21,
.percent_max = 30,
.descr = "FUS operation failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 31,
.percent_max = 100,
.descr = "C2 Stach switch failed",
},
{
.stage = UpdateTaskStageOBValidation,
.percent_min = 0,
.percent_max = 100,
.descr = "Uncorr. value mismatch",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 0,
.percent_max = 1,
.descr = "Failed to open DFU file",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 1,
.percent_max = 97,
.descr = "DFU file read error",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 98,
.percent_max = 100,
.descr = "DFU file CRC mismatch",
},
{
.stage = UpdateTaskStageFlashWrite,
.percent_min = 0,
.percent_max = 100,
.descr = "Flash write error",
},
{
.stage = UpdateTaskStageFlashValidate,
.percent_min = 0,
.percent_max = 100,
.descr = "Flash compare error",
},
#endif
#ifndef FURI_RAM_EXEC
{
.stage = UpdateTaskStageLfsRestore,
.percent_min = 0,
.percent_max = 100,
.descr = "LFS I/O error",
},
{
.stage = UpdateTaskStageResourcesUpdate,
.percent_min = 0,
.percent_max = 100,
.descr = "SD card I/O error",
},
#endif
};
static const char* update_task_get_error_message(UpdateTaskStage stage, uint8_t percent) {
for(size_t i = 0; i < COUNT_OF(update_task_error_detail); i++) {
if(update_task_error_detail[i].stage == stage &&
percent >= update_task_error_detail[i].percent_min &&
percent <= update_task_error_detail[i].percent_max) {
return update_task_error_detail[i].descr;
}
}
return "Unknown error";
}
typedef struct {
UpdateTaskStageGroup group;
uint8_t weight;
@@ -111,8 +296,9 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui
if(stage >= UpdateTaskStageError) {
furi_string_printf(
update_task->state.status,
"%s #[%d-%d]",
update_task_stage_descr[stage],
"%s\n#[%d-%d]",
update_task_get_error_message(
update_task->state.stage, update_task->state.stage_progress),
update_task->state.stage,
update_task->state.stage_progress);
} else {

View File

@@ -24,3 +24,8 @@ bool update_task_open_file(UpdateTask* update_task, FuriString* filename);
int32_t update_task_worker_flash_writer(void* context);
int32_t update_task_worker_backup_restore(void* context);
#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}

View File

@@ -17,11 +17,6 @@
#define TAG "UpdWorkerBackup"
#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}
static bool update_task_pre_update(UpdateTask* update_task) {
bool success = false;
FuriString* backup_file_path;

View File

@@ -13,11 +13,6 @@
#define TAG "UpdWorkerRAM"
#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}
#define STM_DFU_VENDOR_ID 0x0483
#define STM_DFU_PRODUCT_ID 0xDF11
/* Written into DFU file by build pipeline */
@@ -137,7 +132,7 @@ static bool update_task_write_stack_data(UpdateTask* update_task) {
}
static void update_task_wait_for_restart(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 70);
furi_delay_ms(C2_MODE_SWITCH_TIMEOUT);
furi_crash("C2 timeout");
}
@@ -153,12 +148,12 @@ static bool update_task_write_stack(UpdateTask* update_task) {
manifest->radio_crc);
CHECK_RESULT(update_task_write_stack_data(update_task));
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 0);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 10);
CHECK_RESULT(
ble_glue_fus_stack_install(manifest->radio_address, 0) != BleGlueCommandResultError);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 80);
update_task_set_progress(update_task, UpdateTaskStageProgress, 80);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 100);
update_task_set_progress(update_task, UpdateTaskStageProgress, 100);
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
} while(false);
@@ -170,9 +165,9 @@ static bool update_task_remove_stack(UpdateTask* update_task) {
FURI_LOG_W(TAG, "Removing stack");
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 30);
CHECK_RESULT(ble_glue_fus_stack_delete() != BleGlueCommandResultError);
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 80);
update_task_set_progress(update_task, UpdateTaskStageProgress, 80);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 100);
update_task_set_progress(update_task, UpdateTaskStageProgress, 100);
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
} while(false);
@@ -180,6 +175,7 @@ static bool update_task_remove_stack(UpdateTask* update_task) {
}
static bool update_task_manage_radiostack(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
bool success = false;
do {
CHECK_RESULT(ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT));
@@ -208,15 +204,17 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) {
/* Version or type mismatch. Let's boot to FUS and start updating. */
FURI_LOG_W(TAG, "Restarting to FUS");
furi_hal_rtc_set_flag(FuriHalRtcFlagC2Update);
update_task_set_progress(update_task, UpdateTaskStageProgress, 20);
CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeFUS));
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
}
} else if(c2_state->mode == BleGlueC2ModeFUS) {
/* OK, we're in FUS mode. */
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
FURI_LOG_W(TAG, "Waiting for FUS to settle");
ble_glue_fus_wait_operation();
update_task_set_progress(update_task, UpdateTaskStageProgress, 30);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
if(stack_version_match) {
/* We can't check StackType with FUS, but partial version matches */
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagC2Update)) {
@@ -230,7 +228,7 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) {
/* We might just had the stack installed.
* Let's start it up to check its version */
FURI_LOG_W(TAG, "Starting stack to check full version");
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 40);
update_task_set_progress(update_task, UpdateTaskStageProgress, 50);
CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeStack));
/* ...system will restart here. */
update_task_wait_for_restart(update_task);

View File

@@ -81,16 +81,17 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) {
canvas_set_font(canvas, FontPrimary);
if(model->failed) {
canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!");
canvas_draw_icon(canvas, 2, 22, &I_Warning_30x23);
canvas_draw_str_aligned(canvas, 40, 9, AlignLeft, AlignTop, "Update Failed!");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23);
elements_multiline_text_aligned(
canvas, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_str_aligned(
canvas, 18, 51, AlignLeft, AlignTop, "to retry, hold to abort");
canvas_draw_icon(canvas, 7, 50, &I_Ok_btn_9x9);
canvas_draw_icon(canvas, 75, 51, &I_Pin_back_arrow_10x8);
canvas, 18, 55, AlignLeft, AlignTop, "to retry, hold to abort");
canvas_draw_icon(canvas, 7, 54, &I_Ok_btn_9x9);
canvas_draw_icon(canvas, 75, 55, &I_Pin_back_arrow_10x8);
} else {
canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING");
canvas_set_font(canvas, FontSecondary);

View File

@@ -0,0 +1,42 @@
REM Written by @dexv
DELAY 2000
GUI r
DELAY 500
STRING powershell
ENTER
DELAY 1000
STRING $url = "https://update.flipperzero.one/qFlipper/release/windows-amd64/portable"
ENTER
STRING $output = "$env:USERPROFILE\Documents\qFlipper.zip"
ENTER
STRING $destination = "$env:USERPROFILE\Documents\qFlipper"
ENTER
STRING $shortcutPath = "$env:USERPROFILE\Desktop\qFlipper.lnk"
ENTER
STRING $scriptPath = "$env:USERPROFILE\Documents\qFlipperInstall.ps1"
ENTER
STRING $driverPath = "$destination\STM32 Driver"
ENTER
STRING $installBat = "$driverPath\install.bat"
ENTER
STRING (New-Object System.Net.WebClient).DownloadFile($url, $output)
ENTER
STRING Expand-Archive -Path $output -DestinationPath $destination -Force
ENTER
STRING Set-Location -Path $destination
ENTER
STRING Start-Process -FilePath ".\qFlipper.exe"
ENTER
STRING Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "/c $installBat"
ENTER
STRING $shell = New-Object -ComObject WScript.Shell
ENTER
STRING $shortcut = $shell.CreateShortcut($shortcutPath)
ENTER
STRING $shortcut.TargetPath = "$destination\qFlipper.exe"
ENTER
STRING $shortcut.Save()
ENTER
DELAY 500
STRING "powershell -ExecutionPolicy Bypass -File $scriptPath"
ENTER

View File

@@ -1,5 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 13th Jul, 2023
# Last Checked 13th Jul, 2023
#
# Model: Electrolux EACM-16 HP/N3
name: Off
@@ -476,74 +478,75 @@ name: Off
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6058 7359 592 1635 591 1634 592 1634 592 1634 592 1634 592 1633 592 1634 591 1634 592 515 591 516 590 516 590 516 590 517 589 518 588 518 589 518 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 1638 588 1638 588 518 589 518 588 518 589 518 588 518 589 518 589 518 589 518 588 1637 589 1638 588 1638 588 1638 588 1638 588 1638 588 1638 588 1638 588 518 588 519 588 518 588 519 588 518 589 519 587 519 588 519 587 1638 588 1638 588 519 588 1638 588 519 587 519 588 1638 588 1638 588 519 588 519 587 1639 587 519 587 1638 588 1639 587 519 588 519 587 1639 587 1639 587 1639 587 1639 587 1639 587 520 587 1639 587 1639 587 519 587 520 586 520 586 520 587 520 587 1640 586 521 586 521 586 522 585 1664 562 544 562 1664 562 544 562 1664 562 544 562 544 563 1664 562 544 562 1664 562 545 562 1664 562 545 561 1664 562 1664 562 7386 562
#
data: 6060 7357 592 1633 593 1633 593 1633 593 1633 593 1633 593 1633 592 1634 592 1634 592 515 591 515 591 515 591 516 590 517 590 516 590 517 590 517 589 1636 590 1636 590 1636 590 1636 590 1636 590 1636 590 1636 590 1636 590 517 590 517 590 517 590 517 590 517 590 517 589 517 590 517 590 1636 590 1637 589 1637 589 1637 589 1636 615 1612 589 1637 589 1636 590 517 590 517 589 517 590 517 590 517 590 517 589 517 590 517 590 1637 589 1637 589 1637 589 517 589 517 589 517 590 1637 589 1637 589 517 590 517 590 517 589 1637 589 1637 589 1637 590 517 589 517 589 517 589 518 589 517 589 1637 589 1637 589 517 590 1637 589 1637 589 1637 589 1637 589 1637 590 517 589 517 589 1637 589 517 589 517 590 517 589 1638 589 517 590 1637 589 518 589 1637 589 518 588 518 589 1637 589 518 588 1637 589 518 588 1637 589 518 589 1637 589 1637 589 7359 589
#
name: Cool_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6033 7358 591 1634 593 1634 592 1634 592 1634 592 1634 592 1634 592 1634 591 1634 592 515 617 490 616 491 590 517 590 517 590 517 590 517 590 517 590 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 518 589 517 590 517 589 518 589 517 616 492 589 517 615 492 590 517 589 518 613 1613 589 1637 614 1612 589 1637 589 1637 589 1637 589 1637 589 1638 588 518 613 493 613 494 596 512 589 518 612 494 589 1637 614 492 589 518 588 1637 614 1612 614 492 615 1612 613 1613 613 493 590 1637 589 1637 589 518 614 492 614 1612 614 492 614 493 613 1613 613 1612 614 1612 614 1612 614 1612 614 492 614 1612 614 1612 614 493 614 493 614 493 614 493 614 492 614 1612 614 493 614 492 615 492 614 1612 614 492 614 1612 614 492 614 1612 614 493 613 493 614 1612 614 492 614 1612 614 493 614 1612 614 493 614 1612 614 1612 614 7334 614
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6090 7300 672 1579 646 1579 622 1604 622 1604 622 1605 620 1605 620 1606 619 1607 618 488 618 489 617 490 616 490 616 491 616 491 616 490 617 491 616 1610 616 1610 616 1610 616 1610 616 1610 616 1611 616 1610 616 1610 616 491 616 491 615 491 616 491 615 491 615 491 615 491 616 491 616 1611 615 491 616 1611 615 1611 615 1611 615 1611 615 1611 615 1611 615 491 615 1611 615 491 615 491 616 491 615 492 615 491 615 491 616 1611 615 491 615 492 614 1611 615 1611 615 492 615 1611 615 1611 615 492 614 1611 615 1611 615 492 615 492 615 1611 615 492 615 492 614 1611 615 492 614 492 615 493 615 1611 615 1611 615 1612 614 492 615 492 614 1611 615 1611 615 1612 614 492 615 492 614 492 614 1612 614 492 614 1612 614 492 615 1612 614 492 614 1612 614 492 614 492 615 1612 614 493 614 1612 614 493 614 1612 614 493 614 1612 614 1612 614 7334 614
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6091 7301 646 1604 647 1579 647 1579 622 1604 621 1605 620 1605 620 1606 619 1607 618 488 618 488 618 489 617 490 616 491 615 491 615 491 616 491 616 1610 616 1611 615 1611 615 1611 616 1611 615 1610 616 1611 615 1611 615 491 615 491 616 491 616 491 615 491 615 491 616 491 615 491 615 1611 615 491 615 1611 615 1611 615 1611 615 1611 615 1611 615 1611 615 491 615 1611 615 491 615 492 615 491 615 492 615 492 615 491 616 1611 615 492 614 492 615 1611 615 1611 615 492 614 1611 615 1611 615 492 615 1611 615 1612 614 492 614 492 615 1611 615 492 615 492 614 492 615 492 615 492 614 1611 615 1612 614 1612 614 1612 614 492 615 1612 614 1612 614 1612 614 492 615 492 615 492 614 493 614 1612 614 492 615 1612 614 492 614 1612 614 492 614 1612 614 492 615 492 614 1612 614 493 613 1612 614 493 613 1612 614 493 613 1612 614 1612 614 7334 614
#
data: 6032 7356 592 1633 593 1633 592 1633 592 1633 592 1633 592 1633 618 1608 593 1634 617 490 590 516 614 492 616 491 591 517 589 517 590 517 589 517 590 1636 590 1636 590 1636 590 1636 615 1612 589 1636 590 1636 590 1636 589 517 590 517 589 517 589 517 590 517 589 517 589 517 590 517 589 517 589 517 590 1636 590 1636 590 1636 589 1637 589 1637 589 1636 589 1637 589 1637 589 517 589 517 589 517 589 517 589 517 590 517 589 1637 589 517 590 1636 589 517 589 517 589 1637 589 1637 588 1637 589 517 589 1637 589 518 588 1637 588 1637 589 518 588 518 588 518 588 1637 589 1637 589 1637 589 1637 589 1637 589 518 588 1637 589 1637 589 518 588 518 588 518 589 518 588 518 589 1637 589 517 589 518 589 518 588 1637 589 518 588 1637 589 518 588 1637 589 518 588 518 589 1637 588 518 589 1637 588 518 588 1638 588 518 588 1637 589 1637 589 7358 588
#
name: Cool_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6114 7274 647 1604 621 1605 620 1604 622 1604 621 1604 621 1605 620 1605 619 1606 619 488 618 488 618 489 617 490 616 490 616 491 616 490 616 490 616 1610 616 1610 616 1610 615 1610 615 1610 616 1610 616 1610 616 1610 616 491 615 491 616 491 615 491 615 491 615 491 616 491 615 491 615 1610 616 491 615 1610 616 1610 616 1610 616 1610 616 1610 615 1610 616 491 615 1610 616 491 615 491 615 491 616 491 615 491 615 491 616 1610 616 491 615 491 615 1610 616 1610 615 491 615 1610 617 1611 615 491 616 1610 616 1610 616 491 615 491 616 1610 616 491 615 491 615 491 615 491 615 491 615 1611 615 1611 614 491 615 1611 615 1611 615 1611 615 1611 615 1611 614 492 614 492 614 1611 614 492 615 492 615 492 614 1611 615 492 615 1611 615 492 614 1611 616 492 615 492 614 1611 614 492 615 1611 615 492 614 1611 615 492 614 1611 615 1611 615 7332 614
#
data: 6057 7329 647 1604 621 1579 646 1604 621 1604 621 1605 620 1605 620 1606 619 1607 618 488 618 489 617 490 616 490 616 491 616 491 616 490 616 490 616 1610 616 1610 616 1610 616 1610 616 1609 616 1610 616 1610 616 1610 616 490 616 490 617 490 616 491 615 490 616 490 616 490 616 490 616 1610 616 491 616 1610 616 1610 616 1610 616 1610 616 1610 616 1610 615 490 616 1610 615 491 615 491 615 491 616 491 616 490 616 491 616 1610 616 490 616 1610 615 491 616 490 616 1610 616 1610 616 1610 616 491 615 1610 616 491 615 1610 615 1610 616 491 615 491 615 491 616 491 615 491 616 491 615 1610 615 1611 615 491 615 1610 615 1610 616 1610 616 1610 615 1611 615 491 615 491 616 1611 614 491 615 491 616 492 615 1611 614 492 615 1611 614 492 615 1611 614 491 615 492 615 1611 615 492 614 1611 614 492 615 1611 615 492 614 1611 614 1611 615 7332 614
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6034 7357 592 1633 593 1634 592 1633 593 1633 593 1633 593 1633 618 1608 618 1608 618 489 617 490 616 490 618 491 614 492 615 492 589 517 614 493 614 1611 590 1637 614 1611 590 1636 614 1612 590 1637 589 1637 589 1637 590 517 589 517 590 517 589 517 590 517 589 517 590 517 589 517 589 1636 590 517 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 517 590 1637 589 517 590 517 589 517 589 518 588 517 590 517 589 1637 589 517 589 1637 589 517 589 517 590 1637 589 1637 589 1637 589 518 589 1637 589 517 589 1637 589 1637 590 517 589 518 589 518 588 518 589 518 589 517 589 1637 589 1637 589 1637 589 1637 590 518 589 1637 589 1637 589 1637 589 518 588 518 589 518 588 518 588 1638 588 518 589 1637 589 518 588 1637 589 518 588 1638 588 518 589 518 589 1637 589 518 589 1637 589 518 589 1637 589 518 589 1638 588 1638 588 7360 588
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6034 7358 592 1634 592 1634 592 1634 592 1633 593 1633 593 1634 592 1634 592 1634 592 515 616 490 591 516 590 517 613 493 590 517 589 517 590 517 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 1637 590 517 589 517 590 517 589 517 590 517 589 517 590 517 589 517 590 1637 589 517 590 1637 589 1637 589 1637 589 1637 589 1637 589 1637 589 517 590 1637 589 517 590 517 590 517 589 517 590 517 590 517 589 1637 589 517 589 1637 589 518 588 518 589 1637 589 1637 589 1637 589 518 589 1637 589 517 589 1637 589 1637 589 518 589 517 589 517 590 1637 589 517 589 518 588 518 589 1637 589 1637 589 1637 589 518 588 518 589 1637 589 1637 589 1637 589 518 589 518 589 518 589 1637 589 518 588 1637 589 518 589 1637 589 518 588 1637 589 518 589 518 588 1637 589 518 588 1637 589 517 589 1637 589 518 589 1637 589 1637 589 7359 589
#
name: Dh
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 6089 7302 644 1582 644 1582 644 1583 643 1584 642 1586 640 1607 618 1608 617 1609 617 490 616 491 615 491 615 492 615 492 614 492 615 492 615 492 614 1612 614 1612 614 1611 615 1611 615 1612 614 1612 614 1611 615 1611 615 492 615 492 615 492 614 492 614 492 614 492 615 492 615 492 615 492 615 1612 614 1612 614 1612 614 1612 614 1612 614 1612 614 1612 614 1612 614 492 614 492 614 492 614 492 615 492 615 492 614 492 615 1612 614 493 614 492 615 1612 614 1612 614 492 614 493 614 1612 614 492 615 1612 614 1612 614 493 614 493 613 1612 614 1612 614 493 614 493 613 1612 614 1612 614 493 613 1612 614 1612 614 493 614 1612 614 1612 614 493 613 493 614 1612 614 493 613 493 614 1613 613 494 613 493 614 1613 613 493 613 1613 613 493 613 1613 613 493 613 493 614 1613 613 494 613 1613 613 493 613 1613 613 494 613 1613 613 1613 613 7335 613
data: 6059 7355 592 1633 592 1633 592 1633 592 1633 592 1633 592 1633 592 1633 618 1608 617 489 617 490 616 490 616 491 590 517 589 517 614 492 590 517 590 1636 589 1636 590 1636 590 1636 589 1636 590 1636 590 1636 590 1636 590 517 589 517 589 517 589 517 590 517 589 517 589 517 589 517 589 517 589 1636 614 492 590 1636 590 1636 590 1636 589 1636 590 1636 589 1637 589 517 589 1636 590 517 589 517 589 517 614 492 590 517 589 1636 590 517 589 1636 590 517 589 517 589 517 589 517 590 1636 590 517 589 1636 590 517 589 1636 589 1636 590 1636 590 1637 589 517 589 517 589 1637 588 1637 589 517 589 1637 589 1636 590 517 589 1636 590 1636 590 517 589 517 589 1637 589 517 589 517 589 1637 589 517 589 518 588 1637 589 518 588 1637 589 517 590 1637 588 518 588 518 588 1637 589 518 588 1637 589 518 588 1637 589 518 588 1637 589 1637 589 7357 589
#
# Model: Tosot T24H-ILF/I/T24H-ILU/O
# Compatible Brands: Gree
name: Off
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9067 4428 600 1590 599 481 597 481 598 482 596 484 595 487 592 511 568 511 568 511 568 1621 569 511 568 1622 568 511 568 511 568 511 569 511 568 511 569 511 568 511 568 511 568 511 568 1622 568 511 568 511 568 511 568 511 569 511 568 511 568 1622 568 511 568 1622 568 511 568 511 568 1622 568 511 648 20161 569 511 568 511 568 511 568 511 568 511 569 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 1622 568 511 568 511 568 511 568 511 568 511 568 511 569 511 568 511 568 511 569 511 568 512 568 511 568 511 568 511 568 1622 568 1622 568 1622 568 511 648 40402 9171 4434 594 1621 569 510 569 511 568 511 568 510 569 511 568 511 568 511 568 511 568 1621 569 511 568 1621 569 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 1622 568 511 568 511 568 511 569 511 568 511 568 511 568 1622 568 1622 568 1622 568 512 568 512 567 1622 568 512 673 20162 568 511 568 511 568 510 569 510 569 511 568 511 568 511 568 511 569 511 568 511 569 511 568 511 568 511 568 511 568 511 568 511 569 511 568 511 569 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 569 511 568 1622 568 511 568 1622 568 512 567
#
data: 9072 4445 602 1586 603 477 601 478 600 479 599 480 598 481 598 482 597 482 572 1617 597 1593 572 1617 597 483 572 507 572 507 572 507 572 507 572 507 597 482 597 482 572 507 597 482 572 1618 571 507 572 507 572 507 572 507 572 507 572 507 572 1618 571 507 572 1618 572 507 572 507 572 1618 572 507 652 20153 572 507 597 482 572 507 572 507 597 482 597 482 572 507 596 483 572 507 572 507 572 507 572 507 572 507 572 1618 596 483 572 507 596 483 595 484 572 507 597 482 595 484 597 482 597 482 572 507 572 507 597 482 572 507 597 482 572 507 597 483 571 1618 597 482 675 40391 9179 4421 599 1590 599 481 597 482 597 482 597 481 598 482 597 482 597 482 597 1592 597 1592 598 1592 597 482 597 482 597 482 597 482 597 482 597 482 597 482 597 482 597 482 572 507 597 1593 597 482 572 507 572 507 572 507 572 507 572 508 571 1618 597 1593 596 1593 572 507 572 507 572 1618 597 482 678 20152 597 483 596 482 597 482 597 482 597 482 597 482 572 507 597 482 597 482 597 482 572 507 597 482 597 482 597 482 597 482 597 482 572 507 597 482 597 482 572 507 597 482 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 1618 596 482 572 507 572
#
name: Cool_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9087 4428 598 1591 598 482 596 482 596 1594 595 1595 594 1596 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 1597 593 486 593 486 593 486 593 486 593 487 592 486 593 1597 592 487 592 1597 592 487 592 487 592 1597 593 487 671 20132 593 1596 593 486 593 486 593 486 593 1596 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 1597 592 487 592 486 593 486 593 486 593 487 592 486 593 486 593 487 592 487 592 487 592 487 592 487 592 487 592 486 593 487 592 1597 593 1597 592 487 672 40393 9168 4432 594 1596 593 486 593 486 593 1597 593 1596 593 1597 592 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 487 592 487 592 486 593 486 593 1597 592 487 592 486 593 487 592 487 592 487 592 487 592 1597 593 1597 593 1597 592 487 592 487 592 1597 592 487 698 20131 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 486 593 1597 593 486 593 1597 592 487 592 486 593 487 592 486 593 487 592 487 592 487 592 487 592 1597 592
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9065 4429 598 482 597 482 597 1593 596 1594 595 1596 594 1597 593 487 592 487 592 487 593 1598 592 1598 592 1598 592 488 592 487 592 488 591 511 568 487 592 488 591 511 568 511 568 488 591 1599 591 511 568 511 568 511 568 511 568 511 569 511 568 1622 568 511 568 1622 568 511 568 511 568 1622 568 511 648 20137 593 1598 592 487 593 487 592 488 591 1599 591 488 591 487 592 488 591 511 568 488 591 511 568 489 590 511 568 1599 591 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 569 511 568 511 568 511 569 511 568 511 568 1622 568 1622 568 1622 568 511 648 40403 9170 4434 594 486 593 487 592 1597 593 1598 592 1598 592 1597 593 487 592 487 592 487 593 1598 592 1598 592 1598 592 488 591 488 591 488 591 511 568 488 591 488 591 511 568 511 569 511 568 1622 568 511 568 511 568 511 568 511 569 511 568 511 568 1622 568 1622 568 1622 568 511 569 511 568 1622 568 511 674 20138 592 488 591 488 591 511 568 488 591 511 568 511 568 511 568 511 568 511 568 511 568 489 590 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 511 568 1622 568 511 568 1622 568 511 568 511 568 511 569 511 568 511 568 1622 568 511 569 511 568 1622 568
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9104 4416 604 474 604 475 603 1587 602 1588 601 1590 599 1590 599 480 600 481 598 1591 599 1591 599 1591 599 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 599 481 598 1592 598 481 598 481 599 481 598 481 598 481 598 481 598 1592 598 481 598 1592 598 481 598 481 598 1592 598 481 678 20131 599 1591 599 481 598 481 598 481 598 1591 599 481 599 481 598 481 598 481 599 481 598 481 598 481 598 481 598 1592 598 481 598 481 599 481 598 481 598 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 678 40398 9182 4421 599 479 600 480 599 1591 599 1591 599 1591 599 1591 599 480 599 481 598 1591 599 1591 599 1591 599 481 598 481 598 481 598 481 598 481 599 481 598 481 599 480 599 481 599 481 598 1592 598 481 598 481 598 481 599 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 481 598 1592 598 481 704 20131 599 481 598 481 598 481 599 480 599 481 598 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 1592 598 481 598 1592 598 481 599 481 598 481 598 481 598 481 598 481 598 1592 598 481 598 482 597
#
data: 9049 4446 575 1613 577 503 601 478 601 1590 599 480 598 482 572 507 572 507 572 508 571 507 572 507 572 507 572 508 571 508 571 507 573 507 572 508 571 508 572 507 572 508 571 507 572 1618 572 508 572 507 572 508 571 508 571 508 571 508 571 1618 572 508 571 1618 572 508 571 508 571 1619 571 508 651 20157 572 507 572 507 572 507 572 507 572 507 572 507 573 507 572 507 572 507 572 507 572 507 572 507 572 507 572 1618 572 507 572 507 572 507 572 507 573 507 572 508 571 507 572 508 571 507 572 507 573 507 572 507 572 507 572 508 571 1619 571 507 572 1618 572 508 651 40424 9180 4422 599 1591 598 482 597 483 572 1618 572 507 598 482 597 482 572 507 572 507 598 482 572 507 598 482 572 507 598 482 597 482 572 507 572 507 572 507 573 507 572 507 573 507 572 1618 572 507 598 482 572 507 572 507 597 483 596 483 597 1593 572 1618 572 1618 572 508 572 507 572 1618 572 508 678 20157 572 507 597 482 597 482 597 481 598 482 572 507 572 507 572 507 572 507 597 482 572 507 597 482 572 507 573 507 572 507 572 507 572 507 572 507 572 507 572 507 572 508 572 507 572 507 572 507 572 507 572 507 572 508 571 508 571 1619 571 1618 572 508 571 507 572
#
name: Cool_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9045 4446 576 1613 576 503 575 503 601 1589 575 1615 574 1617 572 506 573 507 572 1618 571 1618 572 1618 571 507 572 507 572 507 572 507 572 508 571 507 572 507 572 507 572 508 571 508 571 1618 571 508 571 508 571 508 571 508 571 508 571 508 571 1619 571 508 571 1618 571 508 571 508 571 1619 571 508 651 20153 571 1618 571 508 571 508 571 507 572 1618 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 1619 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 1619 571 508 571 1619 570 1619 650 40414 9150 4450 573 1617 572 507 572 508 571 1618 572 1618 571 1618 571 508 571 508 571 1619 570 1618 572 1618 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 509 570 508 571 1619 571 509 570 509 570 509 570 508 571 509 570 509 570 1619 570 1620 569 1620 570 509 570 509 570 1620 570 509 676 20154 570 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 509 570 508 571 508 571 508 571 508 571 509 570 509 570 509 570 509 570 1619 570 509 570 1620 569 509 570 509 570 509 570 509 570 509 570 1620 569 1621 569 1620 569 1620 570
#
data: 9075 4419 603 1586 603 476 602 478 600 1589 600 480 599 481 598 482 597 482 597 1593 597 1593 597 1593 597 482 597 482 572 507 572 507 596 483 573 507 572 507 573 507 598 482 572 507 573 1618 572 508 572 507 572 508 572 507 596 483 572 508 571 1618 596 484 572 1618 572 507 572 507 572 1618 572 508 651 20158 597 482 598 482 597 482 597 482 597 482 572 507 572 507 572 507 597 482 597 483 597 482 572 507 573 507 597 1594 572 507 597 482 572 507 597 482 598 482 572 508 571 508 571 508 572 507 572 507 597 482 597 483 572 508 571 508 571 508 596 483 597 1593 596 1593 652 40424 9181 4422 599 1591 598 481 598 482 572 1618 598 482 597 481 598 482 598 481 598 1593 597 1593 597 1592 598 482 598 482 597 482 597 482 598 482 597 482 597 482 598 482 597 482 597 482 598 1593 597 482 597 482 597 482 597 483 597 482 572 508 597 1593 596 1594 597 1593 597 483 571 508 571 1618 572 508 678 20157 572 507 572 507 573 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 573 507 572 507 573 507 572 507 573 507 572 507 572 507 572 507 572 508 571 507 572 508 571 508 571 508 571 508 572 1618 572 508 571 1618 572
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9048 4447 576 503 576 503 601 1589 600 1590 599 481 573 507 572 507 572 507 572 1618 572 1618 572 1618 572 507 572 507 573 507 572 508 572 507 572 507 572 507 572 507 572 507 572 507 572 1618 572 507 573 507 572 508 571 507 572 507 572 508 571 1618 572 507 572 1618 572 508 571 507 572 1618 572 508 651 20157 572 507 572 507 572 507 572 507 572 508 572 507 572 507 572 507 572 508 571 508 572 508 571 508 571 508 571 1619 571 507 572 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 509 570 509 570 1620 570 1620 570 1620 570 1620 649 40424 9153 4450 573 506 573 507 572 1619 571 1618 572 508 571 508 571 508 572 508 571 1619 571 1619 571 1619 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 508 571 509 570 509 571 1619 571 509 571 509 570 509 571 509 570 509 570 509 570 1620 570 1621 569 1644 546 509 570 509 570 1620 570 510 676 20158 571 508 572 507 572 508 571 508 571 508 571 508 571 508 571 508 572 508 571 508 571 508 571 508 572 508 571 508 571 508 571 508 571 509 570 509 570 509 571 509 570 509 570 534 545 511 568 533 546 534 546 533 546 534 545 534 545 1645 545 534 545 1645 545 1644 546
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9072 4445 602 476 602 476 602 1588 600 1589 600 480 599 481 597 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 482 597 482 597 1592 598 481 598 481 598 481 598 481 598 481 598 481 598 1592 598 481 598 1592 598 481 598 481 598 1592 598 481 678 20126 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 1592 597 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 482 597 481 598 481 598 1592 597 1592 597 481 677 40388 9180 4420 600 479 599 480 599 1591 599 1591 598 481 598 481 598 481 598 481 598 481 598 1591 598 1591 598 1591 599 480 599 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 1591 598 481 598 481 598 481 598 481 598 481 598 481 598 1591 598 1592 598 1591 598 481 598 481 598 1592 598 481 704 20126 598 480 599 480 599 480 599 481 598 480 599 480 599 480 599 481 598 480 599 480 599 480 599 481 598 481 598 480 599 481 598 480 599 481 598 480 599 480 599 481 598 481 598 481 598 480 599 481 598 481 598 481 598 481 598 481 598 481 598 481 598 1591 599 481 598
#
name: Dh
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9102 4396 624 476 602 1587 602 478 600 1590 600 1591 599 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 598 481 599 481 598 1592 598 481 598 481 598 481 599 481 599 481 598 481 599 1592 598 481 598 1592 598 482 597 481 598 1592 598 481 678 20131 599 1592 598 481 598 481 598 481 598 1592 598 481 598 481 598 481 599 481 598 481 598 481 598 481 599 481 598 1592 598 481 599 481 598 481 598 481 598 481 598 481 598 481 598 482 597 481 598 481 598 481 598 481 598 481 598 481 598 482 597 1592 598 1592 598 1592 677 40398 9182 4421 599 480 599 1591 599 481 599 1592 598 1592 598 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 481 598 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 1592 598 481 599 481 598 482 597 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 482 597 1592 598 482 703 20131 598 481 598 481 598 481 598 481 598 481 599 481 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 599 481 598 481 598 481 598 481 599 481 598 481 598 1592 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 481 598 1592 598 1592 598
data: 9076 4445 577 503 602 1587 603 477 601 1589 600 1590 599 481 573 507 572 507 572 1618 572 1618 572 1618 572 507 572 507 573 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 572 1618 572 507 573 507 572 507 572 507 573 507 572 507 572 1618 572 507 573 1618 572 507 572 507 572 1618 572 507 652 20157 597 482 573 507 597 483 572 507 572 507 573 507 572 507 572 507 596 483 597 482 572 507 572 507 572 507 597 1593 572 507 572 507 573 507 572 507 572 507 572 507 572 507 572 507 572 507 572 507 596 484 572 507 572 507 572 507 597 1593 596 483 572 1618 572 1618 652 40424 9181 4422 599 480 598 1591 599 481 598 1592 598 1592 598 481 598 481 598 481 598 1592 598 1592 598 1592 598 481 598 481 598 481 598 482 597 481 598 481 599 481 598 482 598 482 597 482 598 1592 598 482 597 482 597 482 597 482 597 482 598 482 597 1593 597 1593 597 1592 598 482 598 482 596 1593 597 482 703 20132 598 481 598 481 599 481 598 481 598 481 598 481 598 481 598 481 598 482 598 481 598 482 597 482 597 482 597 482 598 482 598 481 598 481 598 482 597 482 598 482 598 1592 598 482 597 482 597 482 598 482 597 482 597 482 572 507 572 507 598 482 597 1593 597 1593 572
#
# Model: LG Generic
name: Off
@@ -729,3 +732,40 @@ type: raw
frequency: 38000
duty_cycle: 0.330000
data: 30675 50953 3432 1606 490 1190 489 350 489 350 489 350 489 350 489 351 488 350 489 351 489 351 488 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 351 488 351 489 351 488 1191 489 1191 489 351 488 351 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 1191 489 1191 488 1191 488 1191 488 1191 488 1191 488 351 489 1191 488 1191 489 351 488 351 489 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 1191 488 1191 489 1191 488 1191 488 1191 489 1191 488 351 488 351 489 351 488 1191 488 351 489 351 488 351 488 351 489 1191 488 351 489 351 488 1191 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 1191 488 1191 488 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1192 488 1191 488 351 489 1191 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 488 351 488 351 488 1192 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 352 487 352 488 351 488 352 488 351 488 351 488 351 488 1192 488 1192 487 352 488 352 487 352 487 352 488 352 487 352 488 351 488 352 488 352 488 352 487 352 488 351 488 351 488 352 488 352 487 352 488 352 487 352 488 352 488 352 488 352 487 1192 487 352 487 352 488 352 488 352 488 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 1193 486 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 488 352 487 352 488 352 487 353 486 353 487 352 487 352 488 352 488 352 487 352 487 352 487 352 487 353 487 352 488 352 488 352 487 1193 486 1193 486 1193 486 1193 487 353 487 352 487 353 486
#
# Model: LG PC07SQR
name: Off
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3169 9836 535 1553 511 551 491 543 491 544 490 1586 490 532 510 530 511 543 491 1579 489 1577 490 543 490 543 491 543 491 544 490 544 489 544 490 543 491 544 490 550 492 544 490 543 491 1586 489 542 492 1583 492 552 490 532 510 537 512 1585 491
#
name: Dh
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3385 9888 512 1544 512 544 489 544 489 544 490 1586 489 545 489 544 489 545 489 531 511 541 508 533 508 542 507 544 489 546 487 544 490 1587 489 1573 510 543 490 543 491 1578 490 545 489 1574 509 545 488 1587 489 1573 510 1586 490 1579 489 1568 507
#
name: Cool_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3288 9816 598 1504 574 472 569 463 571 463 571 1515 568 472 569 461 573 471 571 459 590 462 571 463 571 447 594 462 572 462 571 464 570 459 590 463 570 464 570 1496 571 1497 570 463 571 1514 569 464 570 1504 572 1514 569 471 571 473 568 462 572
#
name: Cool_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3205 9865 616 1473 536 518 516 517 517 517 517 1575 517 527 568 464 515 517 571 463 570 462 572 462 572 469 573 461 573 463 570 462 572 469 573 1504 572 451 590 451 591 472 569 463 571 1494 573 461 573 1497 570 1505 570 1503 572 471 571 1491 592
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3363 9846 596 1495 514 518 515 517 517 515 518 1552 516 502 539 517 517 516 518 516 518 517 517 517 571 462 517 518 516 1554 568 461 589 462 572 1505 571 1507 568 1514 514 1568 570 461 573 1504 572 472 570 1507 592 1490 593 460 574 462 572 447 594
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3204 9889 537 1587 491 529 512 544 489 545 489 1573 510 530 511 543 491 552 490 538 511 543 491 543 491 532 509 543 491 1587 489 537 512 543 491 1577 490 543 491 543 491 544 489 543 491 1586 489 544 490 1587 489 539 510 543 491 543 491 1586 490

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 1st Jul, 2023
# Last Checked 1st Jul, 2023
# Last Updated 13th Jul, 2023
# Last Checked 13th Jul, 2023
#
name: Power
type: parsed
@@ -3680,3 +3680,51 @@ type: parsed
protocol: NEC
address: 80 00 00 00
command: 02 00 00 00
#
name: Power
type: parsed
protocol: RC5
address: 15 00 00 00
command: 0C 00 00 00
#
name: Mute
type: parsed
protocol: RC5
address: 15 00 00 00
command: 0D 00 00 00
#
name: Vol_up
type: parsed
protocol: RC5
address: 15 00 00 00
command: 10 00 00 00
#
name: Vol_dn
type: parsed
protocol: RC5
address: 15 00 00 00
command: 11 00 00 00
#
name: Prev
type: parsed
protocol: NEC
address: 00 00 00 00
command: 40 00 00 00
#
name: Next
type: parsed
protocol: NEC
address: 00 00 00 00
command: 43 00 00 00
#
name: Play
type: parsed
protocol: RC5
address: 15 00 00 00
command: 35 00 00 00
#
name: Pause
type: parsed
protocol: RC5
address: 15 00 00 00
command: 35 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 1st Jul, 2023
# Last Checked 1st Jul, 2023
# Last Updated 13th Jul, 2023
# Last Checked 13th Jul, 2023
#
name: Power
type: raw
@@ -1833,3 +1833,51 @@ type: raw
frequency: 38000
duty_cycle: 0.33
data: 1286 396 1287 396 444 1240 1286 396 1286 397 443 1239 444 1240 1285 396 444 1239 444 1240 443 1241 442 7977 1286 396 1286 396 500 1183 1287 396 1286 395 501 1183 501 1184 1286 395 500 1184 499 1183 500 1183 501 7922 1340 341 1341 341 499 1184 1342 341 1341 340 500 1184 499 1183 1343 340 500 1184 499 1183 500 1184 499 7922 1342 340 1342 340 500 1184 1342 340 1342 340 500 1185 498 1184 1342 340 500 1184 499 1184 499 1186 498 7922 1341 341 1341 341 499 1184 1342 341 1341 340 500 1183 500 1184 1342 341 499 1184 500 1184 499 1184 499
#
name: Power
type: parsed
protocol: NECext
address: 82 21 00 00
command: 1F E0 00 00
#
name: Power
type: parsed
protocol: NECext
address: 82 21 00 00
command: 1B E4 00 00
#
name: Power
type: raw
frequency: 38000
duty_cycle: 0.33
data: 1278 421 1279 422 508 1210 1250 422 1278 421 509 1182 509 1183 508 1183 508 1183 508 1182 509 1184 1276 7327 1278 421 1279 421 509 1184 1276 422 1277 422 508 1183 508 1183 508 1182 509 1184 507 1184 507 1182 1278 7329 1351 345 1355 346 508 1183 1353 346 1353 346 509 1182 509 1182 509 1184 507 1183 508 1182 508 1183 1353 7251 1354 345 1354 346 508 1184 1352 346 1353 346 508 1184 507 1182 509 1185 506 1182 509 1183 508 1186 1350 7253 1352 345 1354 346 508 1183 1353 346 1353 345 509 1184 507 1183 508 1211 479 1184 507 1183 508 1185 1351 7254 1351 347 1352 348 506 1183 1353 347 1352 346 508 1183 508 1184 507 1187 504 1183 508 1185 506 1184 1352
#
name: Rotate
type: raw
frequency: 38000
duty_cycle: 0.33
data: 1278 421 1279 421 509 1183 1277 421 1278 422 508 1183 508 1182 509 1182 509 1182 509 1184 1276 421 509 8086 1279 421 1278 421 509 1183 1277 422 1277 422 508 1182 509 1183 508 1182 509 1184 507 1183 1352 347 508 8088 1353 346 1353 346 508 1184 1351 346 1353 347 507 1184 507 1184 507 1183 508 1187 504 1183 1353 346 508 8088 1352 345 1354 346 508 1183 1353 347 1352 346 508 1184 507 1185 506 1185 506 1184 507 1183 1349 350 508 8092 1345 352 1348 351 506 1185 1347 351 1348 352 505 1185 505 1185 506 1187 503 1185 505 1185 1347 354 504 8094 1250 446 1253 447 497 1193 1253 447 1252 446 497 1194 496 1195 495 1193 497 1195 495 1196 1252 446 495
#
name: Timer
type: raw
frequency: 38000
duty_cycle: 0.33
data: 1253 446 1253 447 495 1194 1254 446 1253 447 422 1268 422 1268 1253 448 421 1270 421 1269 422 1269 422 8176 1251 448 1251 447 421 1269 1253 445 1254 447 421 1267 423 1269 1253 446 422 1270 421 1269 422 1269 422 8174 1253 447 1252 446 423 1269 1252 447 1252 445 424 1268 423 1269 1252 447 422 1268 422 1269 422 1268 423 8174 1252 446 1253 448 493 1195 1254 446 1253 447 495 1196 495 1195 1252 447 496 1193 497 1194 498 1194 496 8098 1253 445 1254 446 499 1194 1252 446 1253 446 498 1192 498 1191 1254 447 503 1187 504 1187 504 1186 505 8091 1346 352 1347 353 505 1186 1346 352 1347 352 505 1185 506 1187 1345 351 507 1185 505 1185 505 1184 506
#
name: Power
type: parsed
protocol: NEC
address: 30 00 00 00
command: 88 00 00 00
#
name: Speed_up
type: parsed
protocol: NEC
address: 30 00 00 00
command: 8C 00 00 00
#
name: Speed_dn
type: parsed
protocol: NEC
address: 30 00 00 00
command: 87 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 16th Jun, 2023
# Last Checked 1st Jul, 2023
# Last Checked 13th Jul, 2023
#
# ON
name: Power

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 1st Jul, 2023
# Last Checked 1st Jul, 2023
# Last Checked 13th Jul, 2023
#
name: Power
type: parsed

View File

@@ -2981,6 +2981,7 @@ Function,+,submenu_free,void,Submenu*
Function,+,submenu_get_view,View*,Submenu*
Function,+,submenu_reset,void,Submenu*
Function,+,submenu_set_header,void,"Submenu*, const char*"
Function,+,submenu_set_orientation,void,"Submenu*, ViewOrientation"
Function,+,submenu_set_selected_item,void,"Submenu*, uint32_t"
Function,-,system,int,const char*
Function,+,t5577_write,void,LFRFIDT5577*
1 entry status name type params
2981 Function + submenu_get_view View* Submenu*
2982 Function + submenu_reset void Submenu*
2983 Function + submenu_set_header void Submenu*, const char*
2984 Function + submenu_set_orientation void Submenu*, ViewOrientation
2985 Function + submenu_set_selected_item void Submenu*, uint32_t
2986 Function - system int const char*
2987 Function + t5577_write void LFRFIDT5577*

View File

@@ -20,7 +20,8 @@ static const char* update_prepare_result_descr[] = {
[UpdatePrepareResultManifestInvalid] = "Invalid manifest data",
[UpdatePrepareResultStageMissing] = "Missing Stage2 loader",
[UpdatePrepareResultStageIntegrityError] = "Corrupted Stage2 loader",
[UpdatePrepareResultManifestPointerError] = "Failed to create update pointer file",
[UpdatePrepareResultManifestPointerCreateError] = "Failed to create update pointer file",
[UpdatePrepareResultManifestPointerCheckError] = "Update pointer file error (corrupted FS?)",
[UpdatePrepareResultTargetMismatch] = "Hardware target mismatch",
[UpdatePrepareResultOutdatedManifestVersion] = "Update package is too old",
[UpdatePrepareResultIntFull] = "Need more free space in internal storage",
@@ -142,8 +143,8 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
File* file = storage_file_alloc(storage);
uint64_t free_int_space;
FuriString* stage_path;
stage_path = furi_string_alloc();
FuriString* stage_path = furi_string_alloc();
FuriString* manifest_path_check = furi_string_alloc();
do {
if((storage_common_fs_info(storage, STORAGE_INT_PATH_PREFIX, NULL, &free_int_space) !=
FSE_OK) ||
@@ -188,7 +189,18 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
}
if(!update_operation_persist_manifest_path(storage, manifest_file_path)) {
result = UpdatePrepareResultManifestPointerError;
result = UpdatePrepareResultManifestPointerCreateError;
break;
}
if(!update_operation_get_current_package_manifest_path(storage, manifest_path_check) ||
(furi_string_cmpi_str(manifest_path_check, manifest_file_path) != 0)) {
FURI_LOG_E(
"update",
"Manifest pointer check failed: '%s' != '%s'",
furi_string_get_cstr(manifest_path_check),
manifest_file_path);
result = UpdatePrepareResultManifestPointerCheckError;
break;
}
@@ -197,6 +209,7 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
} while(false);
furi_string_free(stage_path);
furi_string_free(manifest_path_check);
storage_file_free(file);
update_manifest_free(manifest);

View File

@@ -28,7 +28,8 @@ typedef enum {
UpdatePrepareResultManifestInvalid,
UpdatePrepareResultStageMissing,
UpdatePrepareResultStageIntegrityError,
UpdatePrepareResultManifestPointerError,
UpdatePrepareResultManifestPointerCreateError,
UpdatePrepareResultManifestPointerCheckError,
UpdatePrepareResultTargetMismatch,
UpdatePrepareResultOutdatedManifestVersion,
UpdatePrepareResultIntFull,