mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 15:18:35 -07:00
Merge remote-tracking branch 'upstream/dev' into emv-fixes
This commit is contained in:
@@ -30,7 +30,7 @@ static void locale_test_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
}
|
}
|
||||||
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
|
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
furi_hal_rtc_get_datetime(&datetime);
|
furi_hal_rtc_get_datetime(&datetime);
|
||||||
|
|
||||||
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
|
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
|
||||||
|
|||||||
175
applications/debug/unit_tests/datetimelib/datetimelib_test.c
Normal file
175
applications/debug/unit_tests/datetimelib/datetimelib_test.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
#include <datetime/datetime.h>
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_correct_min) {
|
||||||
|
DateTime correct_min = {0, 0, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&correct_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_correct_max) {
|
||||||
|
DateTime correct_max = {23, 59, 59, 31, 12, 2099, 7};
|
||||||
|
bool result = datetime_validate_datetime(&correct_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_second) {
|
||||||
|
DateTime incorrect_sec = {0, 0, 60, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_sec);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_minute) {
|
||||||
|
DateTime incorrect_min = {0, 60, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_hour) {
|
||||||
|
DateTime incorrect_hour = {24, 0, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_hour);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_day_min) {
|
||||||
|
DateTime incorrect_day_min = {0, 0, 0, 0, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_day_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_day_max) {
|
||||||
|
DateTime incorrect_day_max = {0, 0, 0, 32, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_day_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_month_min) {
|
||||||
|
DateTime incorrect_month_min = {0, 0, 0, 1, 0, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_month_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_month_max) {
|
||||||
|
DateTime incorrect_month_max = {0, 0, 0, 1, 13, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_month_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_year_min) {
|
||||||
|
DateTime incorrect_year_min = {0, 0, 0, 1, 1, 1999, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_year_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_year_max) {
|
||||||
|
DateTime incorrect_year_max = {0, 0, 0, 1, 1, 2100, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_year_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_min) {
|
||||||
|
DateTime incorrect_weekday_min = {0, 0, 0, 1, 1, 2000, 0};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_weekday_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_max) {
|
||||||
|
DateTime incorrect_weekday_max = {0, 0, 0, 1, 1, 2000, 8};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_weekday_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_validate_datetime) {
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_correct_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_correct_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_second);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_minute);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_hour);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_min) {
|
||||||
|
uint32_t test_value = 0;
|
||||||
|
DateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 0};
|
||||||
|
|
||||||
|
DateTime result = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &result);
|
||||||
|
|
||||||
|
mu_assert_mem_eq(&min_datetime_expected, &result, sizeof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_max) {
|
||||||
|
uint32_t test_value = UINT32_MAX;
|
||||||
|
DateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 0};
|
||||||
|
|
||||||
|
DateTime result = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &result);
|
||||||
|
|
||||||
|
mu_assert_mem_eq(&max_datetime_expected, &result, sizeof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_to_timestamp) {
|
||||||
|
uint32_t test_value = random();
|
||||||
|
|
||||||
|
DateTime datetime = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &datetime);
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&datetime);
|
||||||
|
|
||||||
|
mu_assert_int_eq(test_value, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_timestamp_to_datetime_suite) {
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_min);
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_max);
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_to_timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_datetime_to_timestamp_min) {
|
||||||
|
DateTime min_datetime = {0, 0, 0, 1, 1, 1970, 0};
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&min_datetime);
|
||||||
|
mu_assert_int_eq(0, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_datetime_to_timestamp_max) {
|
||||||
|
DateTime max_datetime = {6, 28, 15, 7, 2, 2106, 0};
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&max_datetime);
|
||||||
|
mu_assert_int_eq(UINT32_MAX, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_datetime_to_timestamp_suite) {
|
||||||
|
MU_RUN_TEST(test_datetime_datetime_to_timestamp_min);
|
||||||
|
MU_RUN_TEST(test_datetime_datetime_to_timestamp_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_minunit_test_datetime() {
|
||||||
|
MU_RUN_SUITE(test_datetime_timestamp_to_datetime_suite);
|
||||||
|
MU_RUN_SUITE(test_datetime_datetime_to_timestamp_suite);
|
||||||
|
MU_RUN_SUITE(test_datetime_validate_datetime);
|
||||||
|
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
@@ -214,37 +214,6 @@ MU_TEST(furi_hal_i2c_ext_eeprom) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(furi_hal_rtc_timestamp2datetime_min) {
|
|
||||||
uint32_t test_value = 0;
|
|
||||||
FuriHalRtcDateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 0};
|
|
||||||
|
|
||||||
FuriHalRtcDateTime result = {0};
|
|
||||||
furi_hal_rtc_timestamp_to_datetime(test_value, &result);
|
|
||||||
|
|
||||||
mu_assert_mem_eq(&min_datetime_expected, &result, sizeof(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(furi_hal_rtc_timestamp2datetime_max) {
|
|
||||||
uint32_t test_value = UINT32_MAX;
|
|
||||||
FuriHalRtcDateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 0};
|
|
||||||
|
|
||||||
FuriHalRtcDateTime result = {0};
|
|
||||||
furi_hal_rtc_timestamp_to_datetime(test_value, &result);
|
|
||||||
|
|
||||||
mu_assert_mem_eq(&max_datetime_expected, &result, sizeof(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(furi_hal_rtc_timestamp2datetime2timestamp) {
|
|
||||||
uint32_t test_value = random();
|
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime = {0};
|
|
||||||
furi_hal_rtc_timestamp_to_datetime(test_value, &datetime);
|
|
||||||
|
|
||||||
uint32_t result = furi_hal_rtc_datetime_to_timestamp(&datetime);
|
|
||||||
|
|
||||||
mu_assert_int_eq(test_value, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
||||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
||||||
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
||||||
@@ -258,15 +227,8 @@ MU_TEST_SUITE(furi_hal_i2c_ext_suite) {
|
|||||||
MU_RUN_TEST(furi_hal_i2c_ext_eeprom);
|
MU_RUN_TEST(furi_hal_i2c_ext_eeprom);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(furi_hal_rtc_datetime_suite) {
|
|
||||||
MU_RUN_TEST(furi_hal_rtc_timestamp2datetime_min);
|
|
||||||
MU_RUN_TEST(furi_hal_rtc_timestamp2datetime_max);
|
|
||||||
MU_RUN_TEST(furi_hal_rtc_timestamp2datetime2timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int run_minunit_test_furi_hal() {
|
int run_minunit_test_furi_hal() {
|
||||||
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
||||||
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
||||||
MU_RUN_SUITE(furi_hal_rtc_datetime_suite);
|
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ int run_minunit_test_protocol_dict();
|
|||||||
int run_minunit_test_lfrfid_protocols();
|
int run_minunit_test_lfrfid_protocols();
|
||||||
int run_minunit_test_nfc();
|
int run_minunit_test_nfc();
|
||||||
int run_minunit_test_bit_lib();
|
int run_minunit_test_bit_lib();
|
||||||
|
int run_minunit_test_datetime();
|
||||||
int run_minunit_test_float_tools();
|
int run_minunit_test_float_tools();
|
||||||
int run_minunit_test_bt();
|
int run_minunit_test_bt();
|
||||||
int run_minunit_test_dialogs_file_browser_options();
|
int run_minunit_test_dialogs_file_browser_options();
|
||||||
@@ -57,6 +58,7 @@ const UnitTest unit_tests[] = {
|
|||||||
{.name = "protocol_dict", .entry = run_minunit_test_protocol_dict},
|
{.name = "protocol_dict", .entry = run_minunit_test_protocol_dict},
|
||||||
{.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols},
|
{.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols},
|
||||||
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
||||||
|
{.name = "datetime", .entry = run_minunit_test_datetime},
|
||||||
{.name = "float_tools", .entry = run_minunit_test_float_tools},
|
{.name = "float_tools", .entry = run_minunit_test_float_tools},
|
||||||
{.name = "bt", .entry = run_minunit_test_bt},
|
{.name = "bt", .entry = run_minunit_test_bt},
|
||||||
{.name = "dialogs_file_browser_options",
|
{.name = "dialogs_file_browser_options",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static const char* known_ext[] = {
|
|||||||
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
||||||
[ArchiveFileTypeFolder] = "?",
|
[ArchiveFileTypeFolder] = "?",
|
||||||
[ArchiveFileTypeUnknown] = "*",
|
[ArchiveFileTypeUnknown] = "*",
|
||||||
|
[ArchiveFileTypeAppOrJs] = ".fap|.js",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ArchiveFileTypeEnum known_type[] = {
|
static const ArchiveFileTypeEnum known_type[] = {
|
||||||
@@ -48,7 +49,7 @@ static const ArchiveFileTypeEnum known_type[] = {
|
|||||||
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
||||||
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
||||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||||
[ArchiveTabApplications] = ArchiveFileTypeApplication,
|
[ArchiveTabApplications] = ArchiveFileTypeAppOrJs,
|
||||||
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
||||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ typedef enum {
|
|||||||
ArchiveFileTypeJS,
|
ArchiveFileTypeJS,
|
||||||
ArchiveFileTypeFolder,
|
ArchiveFileTypeFolder,
|
||||||
ArchiveFileTypeUnknown,
|
ArchiveFileTypeUnknown,
|
||||||
|
ArchiveFileTypeAppOrJs,
|
||||||
ArchiveFileTypeLoading,
|
ArchiveFileTypeLoading,
|
||||||
} ArchiveFileTypeEnum;
|
} ArchiveFileTypeEnum;
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ static const Icon* ArchiveItemIcons[] = {
|
|||||||
[ArchiveFileTypeUnknown] = &I_unknown_10px,
|
[ArchiveFileTypeUnknown] = &I_unknown_10px,
|
||||||
[ArchiveFileTypeLoading] = &I_loading_10px,
|
[ArchiveFileTypeLoading] = &I_loading_10px,
|
||||||
[ArchiveFileTypeJS] = &I_js_script_10px,
|
[ArchiveFileTypeJS] = &I_js_script_10px,
|
||||||
|
[ArchiveFileTypeAppOrJs] = &I_unknown_10px,
|
||||||
};
|
};
|
||||||
|
|
||||||
void archive_browser_set_callback(
|
void archive_browser_set_callback(
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalRtcDateTime curr_dt;
|
DateTime curr_dt;
|
||||||
furi_hal_rtc_get_datetime(&curr_dt);
|
furi_hal_rtc_get_datetime(&curr_dt);
|
||||||
uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
|
uint32_t curr_ts = datetime_datetime_to_timestamp(&curr_dt);
|
||||||
|
|
||||||
char time_string[TIME_LEN];
|
char time_string[TIME_LEN];
|
||||||
char date_string[DATE_LEN];
|
char date_string[DATE_LEN];
|
||||||
@@ -191,9 +191,9 @@ int32_t clock_app(void* p) {
|
|||||||
case InputKeyOk:;
|
case InputKeyOk:;
|
||||||
// START/STOP TIMER
|
// START/STOP TIMER
|
||||||
|
|
||||||
FuriHalRtcDateTime curr_dt;
|
DateTime curr_dt;
|
||||||
furi_hal_rtc_get_datetime(&curr_dt);
|
furi_hal_rtc_get_datetime(&curr_dt);
|
||||||
uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
|
uint32_t curr_ts = datetime_datetime_to_timestamp(&curr_dt);
|
||||||
|
|
||||||
if(plugin_state->timer_running) {
|
if(plugin_state->timer_running) {
|
||||||
// Update stopped seconds
|
// Update stopped seconds
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
LocaleDateFormat date_format;
|
LocaleDateFormat date_format;
|
||||||
LocaleTimeFormat time_format;
|
LocaleTimeFormat time_format;
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
FuriMutex* mutex;
|
FuriMutex* mutex;
|
||||||
FuriMessageQueue* event_queue;
|
FuriMessageQueue* event_queue;
|
||||||
uint32_t timer_start_timestamp;
|
uint32_t timer_start_timestamp;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <applications/services/locale/locale.h>
|
#include <applications/services/locale/locale.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -173,7 +173,7 @@ static void furi_string_cat_timestamp(
|
|||||||
const char* date_hdr,
|
const char* date_hdr,
|
||||||
const char* time_hdr,
|
const char* time_hdr,
|
||||||
uint32_t tmst_1900);
|
uint32_t tmst_1900);
|
||||||
static void epoch_1900_datetime_to_furi(uint32_t seconds, FuriHalRtcDateTime* out);
|
static void epoch_1900_datetime_to_furi(uint32_t seconds, DateTime* out);
|
||||||
static bool get_file_contents(
|
static bool get_file_contents(
|
||||||
const MfDesfireApplication* app,
|
const MfDesfireApplication* app,
|
||||||
const MfDesfireFileId* id,
|
const MfDesfireFileId* id,
|
||||||
@@ -528,7 +528,7 @@ static void furi_string_cat_timestamp(
|
|||||||
const char* date_hdr,
|
const char* date_hdr,
|
||||||
const char* time_hdr,
|
const char* time_hdr,
|
||||||
uint32_t tmst_1900) {
|
uint32_t tmst_1900) {
|
||||||
FuriHalRtcDateTime tm;
|
DateTime tm;
|
||||||
|
|
||||||
epoch_1900_datetime_to_furi(tmst_1900, &tm);
|
epoch_1900_datetime_to_furi(tmst_1900, &tm);
|
||||||
|
|
||||||
@@ -551,7 +551,7 @@ static void furi_string_cat_timestamp(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert a "1900"-based timestamp to Furi time, assuming a UTC/GMT timezone.
|
// Convert a "1900"-based timestamp to Furi time, assuming a UTC/GMT timezone.
|
||||||
static void epoch_1900_datetime_to_furi(uint32_t seconds, FuriHalRtcDateTime* out) {
|
static void epoch_1900_datetime_to_furi(uint32_t seconds, DateTime* out) {
|
||||||
uint16_t year, month, day, hour, minute, second;
|
uint16_t year, month, day, hour, minute, second;
|
||||||
|
|
||||||
// Calculate absolute number of days elapsed since the 1900 epoch
|
// Calculate absolute number of days elapsed since the 1900 epoch
|
||||||
@@ -569,17 +569,17 @@ static void epoch_1900_datetime_to_furi(uint32_t seconds, FuriHalRtcDateTime* ou
|
|||||||
//
|
//
|
||||||
|
|
||||||
for(year = 1900;; year++) {
|
for(year = 1900;; year++) {
|
||||||
uint16_t year_days = furi_hal_rtc_get_days_per_year(year);
|
uint16_t year_days = datetime_get_days_per_year(year);
|
||||||
if(absolute_days >= year_days)
|
if(absolute_days >= year_days)
|
||||||
absolute_days -= year_days;
|
absolute_days -= year_days;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_leap = furi_hal_rtc_is_leap_year(year);
|
bool is_leap = datetime_is_leap_year(year);
|
||||||
|
|
||||||
for(month = 1;; month++) {
|
for(month = 1;; month++) {
|
||||||
uint8_t days_in_month = furi_hal_rtc_get_days_per_month(is_leap, month);
|
uint8_t days_in_month = datetime_get_days_per_month(is_leap, month);
|
||||||
if(absolute_days >= days_in_month)
|
if(absolute_days >= days_in_month)
|
||||||
absolute_days -= days_in_month;
|
absolute_days -= days_in_month;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -23,8 +23,6 @@
|
|||||||
#include "protocols/emv/emv.h"
|
#include "protocols/emv/emv.h"
|
||||||
#include "helpers/nfc_emv_parser.h"
|
#include "helpers/nfc_emv_parser.h"
|
||||||
|
|
||||||
#include <furi_hal_rtc.h>
|
|
||||||
|
|
||||||
#define TAG "EMV"
|
#define TAG "EMV"
|
||||||
|
|
||||||
bool emv_get_currency_name(uint16_t cur_code, FuriString* currency_name) {
|
bool emv_get_currency_name(uint16_t cur_code, FuriString* currency_name) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||||
|
|
||||||
#include <applications/services/locale/locale.h>
|
#include <applications/services/locale/locale.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
static const MfDesfireApplicationId itso_app_id = {.data = {0x16, 0x02, 0xa0}};
|
static const MfDesfireApplicationId itso_app_id = {.data = {0x16, 0x02, 0xa0}};
|
||||||
static const MfDesfireFileId itso_file_id = 0x0f;
|
static const MfDesfireFileId itso_file_id = 0x0f;
|
||||||
@@ -87,8 +87,8 @@ static bool itso_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
furi_string_push_back(parsed_data, ' ');
|
furi_string_push_back(parsed_data, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalRtcDateTime timestamp = {0};
|
DateTime timestamp = {0};
|
||||||
furi_hal_rtc_timestamp_to_datetime(unixTimestamp, ×tamp);
|
datetime_timestamp_to_datetime(unixTimestamp, ×tamp);
|
||||||
FuriString* timestamp_str = furi_string_alloc();
|
FuriString* timestamp_str = furi_string_alloc();
|
||||||
locale_format_date(timestamp_str, ×tamp, locale_get_date_format(), "-");
|
locale_format_date(timestamp_str, ×tamp, locale_get_date_format(), "-");
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
#define TAG "Kazan"
|
#define TAG "Kazan"
|
||||||
|
|
||||||
@@ -282,12 +282,12 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
enum SubscriptionType subscription_type =
|
enum SubscriptionType subscription_type =
|
||||||
get_subscription_type(block_start_ptr[0], tariff_name);
|
get_subscription_type(block_start_ptr[0], tariff_name);
|
||||||
|
|
||||||
FuriHalRtcDateTime valid_from;
|
DateTime valid_from;
|
||||||
valid_from.year = 2000 + block_start_ptr[1];
|
valid_from.year = 2000 + block_start_ptr[1];
|
||||||
valid_from.month = block_start_ptr[2];
|
valid_from.month = block_start_ptr[2];
|
||||||
valid_from.day = block_start_ptr[3];
|
valid_from.day = block_start_ptr[3];
|
||||||
|
|
||||||
FuriHalRtcDateTime valid_to;
|
DateTime valid_to;
|
||||||
valid_to.year = 2000 + block_start_ptr[4];
|
valid_to.year = 2000 + block_start_ptr[4];
|
||||||
valid_to.month = block_start_ptr[5];
|
valid_to.month = block_start_ptr[5];
|
||||||
valid_to.day = block_start_ptr[6];
|
valid_to.day = block_start_ptr[6];
|
||||||
@@ -295,7 +295,7 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
const uint8_t last_trip_block_number = 2;
|
const uint8_t last_trip_block_number = 2;
|
||||||
block_start_ptr = &data->block[start_block_num + last_trip_block_number].data[1];
|
block_start_ptr = &data->block[start_block_num + last_trip_block_number].data[1];
|
||||||
|
|
||||||
FuriHalRtcDateTime last_trip;
|
DateTime last_trip;
|
||||||
last_trip.year = 2000 + block_start_ptr[0];
|
last_trip.year = 2000 + block_start_ptr[0];
|
||||||
last_trip.month = block_start_ptr[1];
|
last_trip.month = block_start_ptr[1];
|
||||||
last_trip.day = block_start_ptr[2];
|
last_trip.day = block_start_ptr[2];
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#include "nfc_supported_card_plugin.h"
|
#include "nfc_supported_card_plugin.h"
|
||||||
#include <flipper_application.h>
|
#include <flipper_application.h>
|
||||||
|
|
||||||
#include <machine/endian.h>
|
|
||||||
#include <nfc/protocols/st25tb/st25tb.h>
|
#include <nfc/protocols/st25tb/st25tb.h>
|
||||||
|
|
||||||
|
#include <machine/endian.h>
|
||||||
|
|
||||||
#define TAG "MyKey"
|
#define TAG "MyKey"
|
||||||
|
|
||||||
const uint32_t blankBlock18 = 0x480FCD8F, blankBlock19 = 0x070082C0;
|
const uint32_t blankBlock18 = 0x480FCD8F, blankBlock19 = 0x070082C0;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||||
|
|
||||||
#include <applications/services/locale/locale.h>
|
#include <applications/services/locale/locale.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
static const MfDesfireApplicationId opal_app_id = {.data = {0x31, 0x45, 0x53}};
|
static const MfDesfireApplicationId opal_app_id = {.data = {0x31, 0x45, 0x53}};
|
||||||
|
|
||||||
@@ -78,11 +78,11 @@ typedef struct __attribute__((__packed__)) {
|
|||||||
|
|
||||||
static_assert(sizeof(OpalFile) == 16, "OpalFile");
|
static_assert(sizeof(OpalFile) == 16, "OpalFile");
|
||||||
|
|
||||||
// Converts an Opal timestamp to FuriHalRtcDateTime.
|
// Converts an Opal timestamp to DateTime.
|
||||||
//
|
//
|
||||||
// Opal measures days since 1980-01-01 and minutes since midnight, and presumes
|
// Opal measures days since 1980-01-01 and minutes since midnight, and presumes
|
||||||
// all days are 1440 minutes.
|
// all days are 1440 minutes.
|
||||||
static void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDateTime* out) {
|
static void opal_date_time_to_furi(uint16_t days, uint16_t minutes, DateTime* out) {
|
||||||
out->year = 1980;
|
out->year = 1980;
|
||||||
out->month = 1;
|
out->month = 1;
|
||||||
// 1980-01-01 is a Tuesday
|
// 1980-01-01 is a Tuesday
|
||||||
@@ -93,7 +93,7 @@ static void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDa
|
|||||||
|
|
||||||
// What year is it?
|
// What year is it?
|
||||||
for(;;) {
|
for(;;) {
|
||||||
const uint16_t num_days_in_year = furi_hal_rtc_get_days_per_year(out->year);
|
const uint16_t num_days_in_year = datetime_get_days_per_year(out->year);
|
||||||
if(days < num_days_in_year) break;
|
if(days < num_days_in_year) break;
|
||||||
days -= num_days_in_year;
|
days -= num_days_in_year;
|
||||||
out->year++;
|
out->year++;
|
||||||
@@ -104,8 +104,8 @@ static void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDa
|
|||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// What month is it?
|
// What month is it?
|
||||||
const bool is_leap = furi_hal_rtc_is_leap_year(out->year);
|
const bool is_leap = datetime_is_leap_year(out->year);
|
||||||
const uint8_t num_days_in_month = furi_hal_rtc_get_days_per_month(is_leap, out->month);
|
const uint8_t num_days_in_month = datetime_get_days_per_month(is_leap, out->month);
|
||||||
if(days <= num_days_in_month) break;
|
if(days <= num_days_in_month) break;
|
||||||
days -= num_days_in_month;
|
days -= num_days_in_month;
|
||||||
out->month++;
|
out->month++;
|
||||||
@@ -154,7 +154,7 @@ static bool opal_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
const uint8_t balance_cents = balance % 100;
|
const uint8_t balance_cents = balance % 100;
|
||||||
const int32_t balance_dollars = balance / 100;
|
const int32_t balance_dollars = balance / 100;
|
||||||
|
|
||||||
FuriHalRtcDateTime timestamp;
|
DateTime timestamp;
|
||||||
opal_date_time_to_furi(opal_file->days, opal_file->minutes, ×tamp);
|
opal_date_time_to_furi(opal_file->days, opal_file->minutes, ×tamp);
|
||||||
|
|
||||||
// Usages 4..6 associated with the Manly Ferry, which correspond to
|
// Usages 4..6 associated with the Manly Ferry, which correspond to
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
#define TAG "Social_Moscow"
|
#define TAG "Social_Moscow"
|
||||||
|
|
||||||
@@ -61,24 +61,24 @@ static const MfClassicKeyPair social_moscow_4k_keys[] = {
|
|||||||
|
|
||||||
#define TOPBIT(X) (1 << ((X)-1))
|
#define TOPBIT(X) (1 << ((X)-1))
|
||||||
|
|
||||||
void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
void from_days_to_datetime(uint16_t days, DateTime* datetime, uint16_t start_year) {
|
||||||
uint32_t timestamp = days * 24 * 60 * 60;
|
uint32_t timestamp = days * 24 * 60 * 60;
|
||||||
FuriHalRtcDateTime start_datetime = {0};
|
DateTime start_datetime = {0};
|
||||||
start_datetime.year = start_year - 1;
|
start_datetime.year = start_year - 1;
|
||||||
start_datetime.month = 12;
|
start_datetime.month = 12;
|
||||||
start_datetime.day = 31;
|
start_datetime.day = 31;
|
||||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
timestamp += datetime_datetime_to_timestamp(&start_datetime);
|
||||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
datetime_timestamp_to_datetime(timestamp, datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
void from_minutes_to_datetime(uint32_t minutes, DateTime* datetime, uint16_t start_year) {
|
||||||
uint32_t timestamp = minutes * 60;
|
uint32_t timestamp = minutes * 60;
|
||||||
FuriHalRtcDateTime start_datetime = {0};
|
DateTime start_datetime = {0};
|
||||||
start_datetime.year = start_year - 1;
|
start_datetime.year = start_year - 1;
|
||||||
start_datetime.month = 12;
|
start_datetime.month = 12;
|
||||||
start_datetime.day = 31;
|
start_datetime.day = 31;
|
||||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
timestamp += datetime_datetime_to_timestamp(&start_datetime);
|
||||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
datetime_timestamp_to_datetime(timestamp, datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||||
@@ -221,10 +221,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_extended,
|
card_extended,
|
||||||
card_crc16_2);
|
card_crc16_2);
|
||||||
card_validator = card_validator1 * 1024 + card_validator2;
|
card_validator = card_validator1 * 1024 + card_validator2;
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -283,7 +283,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_hash,
|
card_hash,
|
||||||
card_valid_from_date,
|
card_valid_from_date,
|
||||||
card_rfu3);
|
card_rfu3);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -336,10 +336,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type3,
|
card_transport_type3,
|
||||||
card_transport_type4,
|
card_transport_type4,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
card_start_trip_minutes - (2 * 24 * 60), &card_start_trip_minutes_s, 2016);
|
card_start_trip_minutes - (2 * 24 * 60), &card_start_trip_minutes_s, 2016);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -397,9 +397,9 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type,
|
card_transport_type,
|
||||||
card_rfu3,
|
card_rfu3,
|
||||||
card_transfer_in_metro);
|
card_transfer_in_metro);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date - 1) * 24 * 60 + card_start_trip_time,
|
(card_start_trip_date - 1) * 24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -478,9 +478,9 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type2,
|
card_transport_type2,
|
||||||
card_rfu5,
|
card_rfu5,
|
||||||
card_transfer_in_metro);
|
card_transfer_in_metro);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date - 1) * 24 * 60 + card_start_trip_time,
|
(card_start_trip_date - 1) * 24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -548,10 +548,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_zoo,
|
card_zoo,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
card_start_trip_minutes - (2 * 24 * 60), &card_start_trip_minutes_s, 1992);
|
card_start_trip_minutes - (2 * 24 * 60), &card_start_trip_minutes_s, 1992);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -618,10 +618,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_extended,
|
card_extended,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_valid_to_date - 1) * 24 * 60 + card_valid_for_minutes -
|
(card_valid_to_date - 1) * 24 * 60 + card_valid_for_minutes -
|
||||||
card_start_trip_neg_minutes,
|
card_start_trip_neg_minutes,
|
||||||
@@ -684,10 +684,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type3,
|
card_transport_type3,
|
||||||
card_transport_type4,
|
card_transport_type4,
|
||||||
card_blocked);
|
card_blocked);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
result,
|
result,
|
||||||
@@ -760,10 +760,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_extended,
|
card_extended,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_use_before_date + 1) * 24 * 60 + card_valid_for_minutes -
|
(card_use_before_date + 1) * 24 * 60 + card_valid_for_minutes -
|
||||||
card_start_trip_neg_minutes,
|
card_start_trip_neg_minutes,
|
||||||
@@ -825,11 +825,11 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_route,
|
card_route,
|
||||||
card_passages_ground_transport,
|
card_passages_ground_transport,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
|
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
card_start_trip_minutes - (24 * 60), &card_start_trip_minutes_s, 2019);
|
card_start_trip_minutes - (24 * 60), &card_start_trip_minutes_s, 2019);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -893,10 +893,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_extended,
|
card_extended,
|
||||||
card_route,
|
card_route,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2019);
|
from_days_to_datetime(card_use_before_date - 1, &card_use_before_date_s, 2019);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
card_valid_from_date + card_valid_for_minutes - card_start_trip_neg_minutes - 24 * 60,
|
card_valid_from_date + card_valid_for_minutes - card_start_trip_neg_minutes - 24 * 60,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -959,7 +959,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_app_code4,
|
card_app_code4,
|
||||||
card_type4,
|
card_type4,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date - 1, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date - 1, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -995,7 +995,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_valid_to_minutes,
|
card_valid_to_minutes,
|
||||||
card_valid_by_date,
|
card_valid_by_date,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date - 1, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date - 1, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
#define TAG "Troika"
|
#define TAG "Troika"
|
||||||
|
|
||||||
@@ -62,24 +62,24 @@ static const MfClassicKeyPair troika_4k_keys[] = {
|
|||||||
|
|
||||||
#define TOPBIT(X) (1 << ((X)-1))
|
#define TOPBIT(X) (1 << ((X)-1))
|
||||||
|
|
||||||
void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
void from_days_to_datetime(uint16_t days, DateTime* datetime, uint16_t start_year) {
|
||||||
uint32_t timestamp = days * 24 * 60 * 60;
|
uint32_t timestamp = days * 24 * 60 * 60;
|
||||||
FuriHalRtcDateTime start_datetime = {0};
|
DateTime start_datetime = {0};
|
||||||
start_datetime.year = start_year - 1;
|
start_datetime.year = start_year - 1;
|
||||||
start_datetime.month = 12;
|
start_datetime.month = 12;
|
||||||
start_datetime.day = 31;
|
start_datetime.day = 31;
|
||||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
timestamp += datetime_datetime_to_timestamp(&start_datetime);
|
||||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
datetime_timestamp_to_datetime(timestamp, datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
void from_minutes_to_datetime(uint32_t minutes, DateTime* datetime, uint16_t start_year) {
|
||||||
uint32_t timestamp = minutes * 60;
|
uint32_t timestamp = minutes * 60;
|
||||||
FuriHalRtcDateTime start_datetime = {0};
|
DateTime start_datetime = {0};
|
||||||
start_datetime.year = start_year - 1;
|
start_datetime.year = start_year - 1;
|
||||||
start_datetime.month = 12;
|
start_datetime.month = 12;
|
||||||
start_datetime.day = 31;
|
start_datetime.day = 31;
|
||||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
timestamp += datetime_datetime_to_timestamp(&start_datetime);
|
||||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
datetime_timestamp_to_datetime(timestamp, datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||||
@@ -170,10 +170,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
if(card_valid_by_date == 0) {
|
if(card_valid_by_date == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -247,10 +247,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_extended,
|
card_extended,
|
||||||
card_crc16_2);
|
card_crc16_2);
|
||||||
card_validator = card_validator1 * 1024 + card_validator2;
|
card_validator = card_validator1 * 1024 + card_validator2;
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -309,7 +309,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_hash,
|
card_hash,
|
||||||
card_valid_from_date,
|
card_valid_from_date,
|
||||||
card_rfu3);
|
card_rfu3);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -362,10 +362,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type3,
|
card_transport_type3,
|
||||||
card_transport_type4,
|
card_transport_type4,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
result,
|
result,
|
||||||
@@ -422,9 +422,9 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type,
|
card_transport_type,
|
||||||
card_rfu3,
|
card_rfu3,
|
||||||
card_transfer_in_metro);
|
card_transfer_in_metro);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -503,9 +503,9 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type2,
|
card_transport_type2,
|
||||||
card_rfu5,
|
card_rfu5,
|
||||||
card_transfer_in_metro);
|
card_transfer_in_metro);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -573,10 +573,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_zoo,
|
card_zoo,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 1992);
|
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 1992);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
result,
|
result,
|
||||||
@@ -642,10 +642,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_extended,
|
card_extended,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_valid_to_date)*24 * 60 + card_valid_for_minutes - card_start_trip_neg_minutes,
|
(card_valid_to_date)*24 * 60 + card_valid_for_minutes - card_start_trip_neg_minutes,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -707,10 +707,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_transport_type3,
|
card_transport_type3,
|
||||||
card_transport_type4,
|
card_transport_type4,
|
||||||
card_blocked);
|
card_blocked);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2016);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
result,
|
result,
|
||||||
@@ -783,10 +783,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_blocked,
|
card_blocked,
|
||||||
card_extended,
|
card_extended,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2016);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
(card_use_before_date + 1) * 24 * 60 + card_valid_for_minutes -
|
(card_use_before_date + 1) * 24 * 60 + card_valid_for_minutes -
|
||||||
card_start_trip_neg_minutes,
|
card_start_trip_neg_minutes,
|
||||||
@@ -848,11 +848,11 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_route,
|
card_route,
|
||||||
card_passages_ground_transport,
|
card_passages_ground_transport,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
|
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2019);
|
from_minutes_to_datetime(card_start_trip_minutes, &card_start_trip_minutes_s, 2019);
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
result,
|
result,
|
||||||
@@ -915,10 +915,10 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_extended,
|
card_extended,
|
||||||
card_route,
|
card_route,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 2019);
|
||||||
|
|
||||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
DateTime card_start_trip_minutes_s = {0};
|
||||||
from_minutes_to_datetime(
|
from_minutes_to_datetime(
|
||||||
card_valid_from_date + card_valid_for_minutes - card_start_trip_neg_minutes,
|
card_valid_from_date + card_valid_for_minutes - card_start_trip_neg_minutes,
|
||||||
&card_start_trip_minutes_s,
|
&card_start_trip_minutes_s,
|
||||||
@@ -981,7 +981,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_app_code4,
|
card_app_code4,
|
||||||
card_type4,
|
card_type4,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
@@ -1017,7 +1017,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
|||||||
card_valid_to_minutes,
|
card_valid_to_minutes,
|
||||||
card_valid_by_date,
|
card_valid_by_date,
|
||||||
card_hash);
|
card_hash);
|
||||||
FuriHalRtcDateTime card_use_before_date_s = {0};
|
DateTime card_use_before_date_s = {0};
|
||||||
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
from_days_to_datetime(card_valid_by_date, &card_use_before_date_s, 1992);
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#include "nfc_supported_card_plugin.h"
|
#include "nfc_supported_card_plugin.h"
|
||||||
|
|
||||||
#include <flipper_application/flipper_application.h>
|
#include <flipper_application/flipper_application.h>
|
||||||
|
|
||||||
#include <nfc/nfc_device.h>
|
|
||||||
#include <bit_lib.h>
|
|
||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||||
|
|
||||||
|
#include <bit_lib.h>
|
||||||
|
|
||||||
#define TAG "TwoCities"
|
#define TAG "TwoCities"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
#include "protocols/mf_classic/mf_classic.h"
|
#include "protocols/mf_classic/mf_classic.h"
|
||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <furi_hal_rtc.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
#define TAG "Umarsh"
|
#define TAG "Umarsh"
|
||||||
|
|
||||||
bool parse_datetime(uint16_t date, FuriHalRtcDateTime* result) {
|
bool parse_datetime(uint16_t date, DateTime* result) {
|
||||||
result->year = 2000 + (date >> 9);
|
result->year = 2000 + (date >> 9);
|
||||||
result->month = date >> 5 & 0x0F;
|
result->month = date >> 5 & 0x0F;
|
||||||
result->day = date & 0x1F;
|
result->day = date & 0x1F;
|
||||||
@@ -81,13 +81,13 @@ static bool umarsh_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
const uint16_t balance_rub = (bit_lib_bytes_to_num_be(block_start_ptr + 8, 2)) & 0x7FFF;
|
const uint16_t balance_rub = (bit_lib_bytes_to_num_be(block_start_ptr + 8, 2)) & 0x7FFF;
|
||||||
const uint8_t balance_kop = bit_lib_bytes_to_num_be(block_start_ptr + 10, 1) & 0x7F;
|
const uint8_t balance_kop = bit_lib_bytes_to_num_be(block_start_ptr + 10, 1) & 0x7F;
|
||||||
|
|
||||||
FuriHalRtcDateTime expiry_datetime;
|
DateTime expiry_datetime;
|
||||||
bool is_expiry_datetime_valid = parse_datetime(expiry_date, &expiry_datetime);
|
bool is_expiry_datetime_valid = parse_datetime(expiry_date, &expiry_datetime);
|
||||||
|
|
||||||
FuriHalRtcDateTime valid_to_datetime;
|
DateTime valid_to_datetime;
|
||||||
bool is_valid_to_datetime_valid = parse_datetime(valid_to, &valid_to_datetime);
|
bool is_valid_to_datetime_valid = parse_datetime(valid_to, &valid_to_datetime);
|
||||||
|
|
||||||
FuriHalRtcDateTime last_refill_datetime;
|
DateTime last_refill_datetime;
|
||||||
bool is_last_refill_datetime_valid =
|
bool is_last_refill_datetime_valid =
|
||||||
parse_datetime(last_refill_date, &last_refill_datetime);
|
parse_datetime(last_refill_date, &last_refill_datetime);
|
||||||
|
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_da
|
|||||||
const uint8_t last_refill_amount_kop = last_refill_amount % 100;
|
const uint8_t last_refill_amount_kop = last_refill_amount % 100;
|
||||||
const uint16_t refill_counter = bit_lib_bytes_to_num_le(block_start_ptr + 10, 2);
|
const uint16_t refill_counter = bit_lib_bytes_to_num_le(block_start_ptr + 10, 2);
|
||||||
|
|
||||||
FuriHalRtcDateTime last_refill_datetime = {0};
|
DateTime last_refill_datetime = {0};
|
||||||
furi_hal_rtc_timestamp_to_datetime(last_refill_timestamp, &last_refill_datetime);
|
datetime_timestamp_to_datetime(last_refill_timestamp, &last_refill_datetime);
|
||||||
|
|
||||||
// block 2: trip block
|
// block 2: trip block
|
||||||
block_start_ptr = &data->block[start_trip_block_number + 2].data[0];
|
block_start_ptr = &data->block[start_trip_block_number + 2].data[0];
|
||||||
@@ -110,8 +110,8 @@ static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_da
|
|||||||
const uint32_t prev_balance_rub = prev_balance / 100;
|
const uint32_t prev_balance_rub = prev_balance / 100;
|
||||||
const uint8_t prev_balance_kop = prev_balance % 100;
|
const uint8_t prev_balance_kop = prev_balance % 100;
|
||||||
|
|
||||||
FuriHalRtcDateTime last_trip_datetime = {0};
|
DateTime last_trip_datetime = {0};
|
||||||
furi_hal_rtc_timestamp_to_datetime(last_trip_timestamp, &last_trip_datetime);
|
datetime_timestamp_to_datetime(last_trip_timestamp, &last_trip_datetime);
|
||||||
|
|
||||||
// PARSE DATA FROM PURSE SECTOR
|
// PARSE DATA FROM PURSE SECTOR
|
||||||
const uint8_t start_purse_block_number =
|
const uint8_t start_purse_block_number =
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "protocols/mf_classic/mf_classic.h"
|
#include "protocols/mf_classic/mf_classic.h"
|
||||||
|
|
||||||
#include <bit_lib.h>
|
#include <bit_lib.h>
|
||||||
#include <furi_hal_rtc.h>
|
|
||||||
|
|
||||||
#define TAG "Zolotaya Korona Online"
|
#define TAG "Zolotaya Korona Online"
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void subghz_scene_save_name_on_enter(void* context) {
|
|||||||
FuriString* dir_name = furi_string_alloc();
|
FuriString* dir_name = furi_string_alloc();
|
||||||
|
|
||||||
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
|
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
|
||||||
FuriHalRtcDateTime* datetime = subghz->save_datetime_set ? &subghz->save_datetime : NULL;
|
DateTime* datetime = subghz->save_datetime_set ? &subghz->save_datetime : NULL;
|
||||||
subghz->save_datetime_set = false;
|
subghz->save_datetime_set = false;
|
||||||
if(!subghz_path_is_file(subghz->file_path)) {
|
if(!subghz_path_is_file(subghz->file_path)) {
|
||||||
SubGhzProtocolDecoderBase* decoder_result = subghz_txrx_get_decoder(subghz->txrx);
|
SubGhzProtocolDecoderBase* decoder_result = subghz_txrx_get_decoder(subghz->txrx);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ typedef struct {
|
|||||||
FlipperFormat* flipper_string;
|
FlipperFormat* flipper_string;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
SubGhzRadioPreset* preset;
|
SubGhzRadioPreset* preset;
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
} SubGhzHistoryItem;
|
} SubGhzHistoryItem;
|
||||||
|
|
||||||
ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
|
ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
|
||||||
@@ -131,13 +131,13 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i
|
|||||||
return furi_string_get_cstr(instance->tmp_string);
|
return furi_string_get_cstr(instance->tmp_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalRtcDateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx) {
|
DateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
||||||
if(item) {
|
if(item) {
|
||||||
return item->datetime;
|
return item->datetime;
|
||||||
} else {
|
} else {
|
||||||
return (FuriHalRtcDateTime){};
|
return (DateTime){};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* outp
|
|||||||
|
|
||||||
void subghz_history_get_time_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) {
|
void subghz_history_get_time_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) {
|
||||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
||||||
FuriHalRtcDateTime* t = &item->datetime;
|
DateTime* t = &item->datetime;
|
||||||
furi_string_printf(output, "%.2d:%.2d:%.2d ", t->hour, t->minute, t->second);
|
furi_string_printf(output, "%.2d:%.2d:%.2d ", t->hour, t->minute, t->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i
|
|||||||
*
|
*
|
||||||
* @param instance - SubGhzHistory instance
|
* @param instance - SubGhzHistory instance
|
||||||
* @param idx - record index
|
* @param idx - record index
|
||||||
* @return datetime - FuriHalRtcDateTime received timestamp
|
* @return datetime - DateTime received timestamp
|
||||||
*/
|
*/
|
||||||
FuriHalRtcDateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx);
|
DateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx);
|
||||||
|
|
||||||
/** Get string item menu to history[idx]
|
/** Get string item menu to history[idx]
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ struct SubGhz {
|
|||||||
bool raw_send_only;
|
bool raw_send_only;
|
||||||
|
|
||||||
bool save_datetime_set;
|
bool save_datetime_set;
|
||||||
FuriHalRtcDateTime save_datetime;
|
DateTime save_datetime;
|
||||||
|
|
||||||
SubGhzLastSettings* last_settings;
|
SubGhzLastSettings* last_settings;
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void cli_command_date(Cli* cli, FuriString* args, void* context) {
|
|||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime = {0};
|
DateTime datetime = {0};
|
||||||
|
|
||||||
if(furi_string_size(args) > 0) {
|
if(furi_string_size(args) > 0) {
|
||||||
uint16_t hours, minutes, seconds, month, day, year, weekday;
|
uint16_t hours, minutes, seconds, month, day, year, weekday;
|
||||||
@@ -135,7 +135,7 @@ void cli_command_date(Cli* cli, FuriString* args, void* context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!furi_hal_rtc_validate_datetime(&datetime)) {
|
if(!datetime_validate_datetime(&datetime)) {
|
||||||
printf("Invalid datetime data");
|
printf("Invalid datetime data");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context)
|
|||||||
static void desktop_clock_update(Desktop* desktop) {
|
static void desktop_clock_update(Desktop* desktop) {
|
||||||
furi_assert(desktop);
|
furi_assert(desktop);
|
||||||
|
|
||||||
FuriHalRtcDateTime curr_dt;
|
DateTime curr_dt;
|
||||||
furi_hal_rtc_get_datetime(&curr_dt);
|
furi_hal_rtc_get_datetime(&curr_dt);
|
||||||
bool time_format_12 = locale_get_time_format() == LocaleTimeFormat12h;
|
bool time_format_12 = locale_get_time_format() == LocaleTimeFormat12h;
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin) {
|
|||||||
uint32_t timer_expires_at = furi_timer_get_expire_time(dolphin->clear_limits_timer);
|
uint32_t timer_expires_at = furi_timer_get_expire_time(dolphin->clear_limits_timer);
|
||||||
|
|
||||||
if((timer_expires_at - now_ticks) > HOURS_IN_TICKS(0.1)) {
|
if((timer_expires_at - now_ticks) > HOURS_IN_TICKS(0.1)) {
|
||||||
FuriHalRtcDateTime date;
|
DateTime date;
|
||||||
furi_hal_rtc_get_datetime(&date);
|
furi_hal_rtc_get_datetime(&date);
|
||||||
uint32_t now_time_in_ms = ((date.hour * 60 + date.minute) * 60 + date.second) * 1000;
|
uint32_t now_time_in_ms = ((date.hour * 60 + date.minute) * 60 + date.second) * 1000;
|
||||||
uint32_t time_to_clear_limits = 0;
|
uint32_t time_to_clear_limits = 0;
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ bool dolphin_state_load(DolphinState* dolphin_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t dolphin_state_timestamp() {
|
uint64_t dolphin_state_timestamp() {
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
furi_hal_rtc_get_datetime(&datetime);
|
furi_hal_rtc_get_datetime(&datetime);
|
||||||
return furi_hal_rtc_datetime_to_timestamp(&datetime);
|
return datetime_datetime_to_timestamp(&datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dolphin_state_is_levelup(uint32_t icounter) {
|
bool dolphin_state_is_levelup(uint32_t icounter) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ float locale_celsius_to_fahrenheit(float temp_c) {
|
|||||||
|
|
||||||
void locale_format_time(
|
void locale_format_time(
|
||||||
FuriString* out_str,
|
FuriString* out_str,
|
||||||
const FuriHalRtcDateTime* datetime,
|
const DateTime* datetime,
|
||||||
const LocaleTimeFormat format,
|
const LocaleTimeFormat format,
|
||||||
const bool show_seconds) {
|
const bool show_seconds) {
|
||||||
furi_assert(out_str);
|
furi_assert(out_str);
|
||||||
@@ -69,7 +69,7 @@ void locale_format_time(
|
|||||||
|
|
||||||
void locale_format_date(
|
void locale_format_date(
|
||||||
FuriString* out_str,
|
FuriString* out_str,
|
||||||
const FuriHalRtcDateTime* datetime,
|
const DateTime* datetime,
|
||||||
const LocaleDateFormat format,
|
const LocaleDateFormat format,
|
||||||
const char* separator) {
|
const char* separator) {
|
||||||
furi_assert(out_str);
|
furi_assert(out_str);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void locale_set_time_format(LocaleTimeFormat format);
|
|||||||
*/
|
*/
|
||||||
void locale_format_time(
|
void locale_format_time(
|
||||||
FuriString* out_str,
|
FuriString* out_str,
|
||||||
const FuriHalRtcDateTime* datetime,
|
const DateTime* datetime,
|
||||||
const LocaleTimeFormat format,
|
const LocaleTimeFormat format,
|
||||||
const bool show_seconds);
|
const bool show_seconds);
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ void locale_set_date_format(LocaleDateFormat format);
|
|||||||
*/
|
*/
|
||||||
void locale_format_date(
|
void locale_format_date(
|
||||||
FuriString* out_str,
|
FuriString* out_str,
|
||||||
const FuriHalRtcDateTime* datetime,
|
const DateTime* datetime,
|
||||||
const LocaleDateFormat format,
|
const LocaleDateFormat format,
|
||||||
const char* separator);
|
const char* separator);
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ static void rpc_system_system_get_datetime_process(const PB_Main* request, void*
|
|||||||
RpcSession* session = (RpcSession*)context;
|
RpcSession* session = (RpcSession*)context;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
furi_hal_rtc_get_datetime(&datetime);
|
furi_hal_rtc_get_datetime(&datetime);
|
||||||
|
|
||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
PB_Main* response = malloc(sizeof(PB_Main));
|
||||||
@@ -157,7 +157,7 @@ static void rpc_system_system_set_datetime_process(const PB_Main* request, void*
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
datetime.hour = request->content.system_set_datetime_request.datetime.hour;
|
datetime.hour = request->content.system_set_datetime_request.datetime.hour;
|
||||||
datetime.minute = request->content.system_set_datetime_request.datetime.minute;
|
datetime.minute = request->content.system_set_datetime_request.datetime.minute;
|
||||||
datetime.second = request->content.system_set_datetime_request.datetime.second;
|
datetime.second = request->content.system_set_datetime_request.datetime.second;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ libs = env.BuildModules(
|
|||||||
"update_util",
|
"update_util",
|
||||||
"heatshrink",
|
"heatshrink",
|
||||||
"bit_lib",
|
"bit_lib",
|
||||||
|
"datetime",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
22
lib/datetime/SConscript
Normal file
22
lib/datetime/SConscript
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Import("env")
|
||||||
|
|
||||||
|
env.Append(
|
||||||
|
LINT_SOURCES=[
|
||||||
|
Dir("."),
|
||||||
|
],
|
||||||
|
CPPPATH=[
|
||||||
|
"#/lib/datetime",
|
||||||
|
],
|
||||||
|
SDK_HEADERS=[
|
||||||
|
File("datetime.h"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
libenv = env.Clone(FW_LIB_NAME="datetime")
|
||||||
|
libenv.ApplyLibFlags()
|
||||||
|
|
||||||
|
sources = libenv.GlobRecursive("*.c*")
|
||||||
|
|
||||||
|
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||||
|
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||||
|
Return("lib")
|
||||||
104
lib/datetime/datetime.c
Normal file
104
lib/datetime/datetime.c
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include "datetime.h"
|
||||||
|
|
||||||
|
#define TAG "DateTime"
|
||||||
|
|
||||||
|
#define SECONDS_PER_MINUTE 60
|
||||||
|
#define SECONDS_PER_HOUR (SECONDS_PER_MINUTE * 60)
|
||||||
|
#define SECONDS_PER_DAY (SECONDS_PER_HOUR * 24)
|
||||||
|
#define MONTHS_COUNT 12
|
||||||
|
#define EPOCH_START_YEAR 1970
|
||||||
|
|
||||||
|
static const uint8_t datetime_days_per_month[2][MONTHS_COUNT] = {
|
||||||
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||||
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||||
|
|
||||||
|
static const uint16_t datetime_days_per_year[] = {365, 366};
|
||||||
|
|
||||||
|
bool datetime_validate_datetime(DateTime* datetime) {
|
||||||
|
bool invalid = false;
|
||||||
|
|
||||||
|
invalid |= (datetime->second > 59);
|
||||||
|
invalid |= (datetime->minute > 59);
|
||||||
|
invalid |= (datetime->hour > 23);
|
||||||
|
|
||||||
|
invalid |= (datetime->year < 2000);
|
||||||
|
invalid |= (datetime->year > 2099);
|
||||||
|
|
||||||
|
invalid |= (datetime->month == 0);
|
||||||
|
invalid |= (datetime->month > 12);
|
||||||
|
|
||||||
|
invalid |= (datetime->day == 0);
|
||||||
|
invalid |= (datetime->day > 31);
|
||||||
|
|
||||||
|
invalid |= (datetime->weekday == 0);
|
||||||
|
invalid |= (datetime->weekday > 7);
|
||||||
|
|
||||||
|
return !invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t datetime_datetime_to_timestamp(DateTime* datetime) {
|
||||||
|
uint32_t timestamp = 0;
|
||||||
|
uint8_t years = 0;
|
||||||
|
uint8_t leap_years = 0;
|
||||||
|
|
||||||
|
for(uint16_t y = EPOCH_START_YEAR; y < datetime->year; y++) {
|
||||||
|
if(datetime_is_leap_year(y)) {
|
||||||
|
leap_years++;
|
||||||
|
} else {
|
||||||
|
years++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp += ((years * datetime_days_per_year[0]) + (leap_years * datetime_days_per_year[1])) *
|
||||||
|
SECONDS_PER_DAY;
|
||||||
|
|
||||||
|
bool leap_year = datetime_is_leap_year(datetime->year);
|
||||||
|
|
||||||
|
for(uint8_t m = 1; m < datetime->month; m++) {
|
||||||
|
timestamp += datetime_get_days_per_month(leap_year, m) * SECONDS_PER_DAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp += (datetime->day - 1) * SECONDS_PER_DAY;
|
||||||
|
timestamp += datetime->hour * SECONDS_PER_HOUR;
|
||||||
|
timestamp += datetime->minute * SECONDS_PER_MINUTE;
|
||||||
|
timestamp += datetime->second;
|
||||||
|
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime) {
|
||||||
|
uint32_t days = timestamp / SECONDS_PER_DAY;
|
||||||
|
uint32_t seconds_in_day = timestamp % SECONDS_PER_DAY;
|
||||||
|
|
||||||
|
datetime->year = EPOCH_START_YEAR;
|
||||||
|
|
||||||
|
while(days >= datetime_get_days_per_year(datetime->year)) {
|
||||||
|
days -= datetime_get_days_per_year(datetime->year);
|
||||||
|
(datetime->year)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime->month = 1;
|
||||||
|
while(days >=
|
||||||
|
datetime_get_days_per_month(datetime_is_leap_year(datetime->year), datetime->month)) {
|
||||||
|
days -=
|
||||||
|
datetime_get_days_per_month(datetime_is_leap_year(datetime->year), datetime->month);
|
||||||
|
(datetime->month)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime->day = days + 1;
|
||||||
|
datetime->hour = seconds_in_day / SECONDS_PER_HOUR;
|
||||||
|
datetime->minute = (seconds_in_day % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
|
||||||
|
datetime->second = seconds_in_day % SECONDS_PER_MINUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t datetime_get_days_per_year(uint16_t year) {
|
||||||
|
return datetime_days_per_year[datetime_is_leap_year(year) ? 1 : 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool datetime_is_leap_year(uint16_t year) {
|
||||||
|
return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t datetime_get_days_per_month(bool leap_year, uint8_t month) {
|
||||||
|
return datetime_days_per_month[leap_year ? 1 : 0][month - 1];
|
||||||
|
}
|
||||||
75
lib/datetime/datetime.h
Normal file
75
lib/datetime/datetime.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Time
|
||||||
|
uint8_t hour; /**< Hour in 24H format: 0-23 */
|
||||||
|
uint8_t minute; /**< Minute: 0-59 */
|
||||||
|
uint8_t second; /**< Second: 0-59 */
|
||||||
|
// Date
|
||||||
|
uint8_t day; /**< Current day: 1-31 */
|
||||||
|
uint8_t month; /**< Current month: 1-12 */
|
||||||
|
uint16_t year; /**< Current year: 2000-2099 */
|
||||||
|
uint8_t weekday; /**< Current weekday: 1-7 */
|
||||||
|
} DateTime;
|
||||||
|
|
||||||
|
/** Validate Date Time
|
||||||
|
*
|
||||||
|
* @param datetime The datetime to validate
|
||||||
|
*
|
||||||
|
* @return { description_of_the_return_value }
|
||||||
|
*/
|
||||||
|
bool datetime_validate_datetime(DateTime* datetime);
|
||||||
|
|
||||||
|
/** Convert DateTime to UNIX timestamp
|
||||||
|
*
|
||||||
|
* @warning Mind timezone when perform conversion
|
||||||
|
*
|
||||||
|
* @param datetime The datetime (UTC)
|
||||||
|
*
|
||||||
|
* @return UNIX Timestamp in seconds from UNIX epoch start
|
||||||
|
*/
|
||||||
|
uint32_t datetime_datetime_to_timestamp(DateTime* datetime);
|
||||||
|
|
||||||
|
/** Convert UNIX timestamp to DateTime
|
||||||
|
*
|
||||||
|
* @warning Mind timezone when perform conversion
|
||||||
|
*
|
||||||
|
* @param[in] timestamp UNIX Timestamp in seconds from UNIX epoch start
|
||||||
|
* @param[out] datetime The datetime (UTC)
|
||||||
|
*/
|
||||||
|
void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime);
|
||||||
|
|
||||||
|
/** Gets the number of days in the year according to the Gregorian calendar.
|
||||||
|
*
|
||||||
|
* @param year Input year.
|
||||||
|
*
|
||||||
|
* @return number of days in `year`.
|
||||||
|
*/
|
||||||
|
uint16_t datetime_get_days_per_year(uint16_t year);
|
||||||
|
|
||||||
|
/** Check if a year a leap year in the Gregorian calendar.
|
||||||
|
*
|
||||||
|
* @param year Input year.
|
||||||
|
*
|
||||||
|
* @return true if `year` is a leap year.
|
||||||
|
*/
|
||||||
|
bool datetime_is_leap_year(uint16_t year);
|
||||||
|
|
||||||
|
/** Get the number of days in the month.
|
||||||
|
*
|
||||||
|
* @param leap_year true to calculate based on leap years
|
||||||
|
* @param month month to check, where 1 = January
|
||||||
|
* @return the number of days in the month
|
||||||
|
*/
|
||||||
|
uint8_t datetime_get_days_per_month(bool leap_year, uint8_t month);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
const ProtocolBase* lfrfid_protocols[] = {
|
const ProtocolBase* lfrfid_protocols[] = {
|
||||||
[LFRFIDProtocolEM4100] = &protocol_em4100,
|
[LFRFIDProtocolEM4100] = &protocol_em4100,
|
||||||
[LFRFIDProtocolEM4100_32] = &protocol_em4100_32,
|
[LFRFIDProtocolEM4100_32] = &protocol_em4100_32,
|
||||||
|
[LFRFIDProtocolEM4100_16] = &protocol_em4100_16,
|
||||||
[LFRFIDProtocolH10301] = &protocol_h10301,
|
[LFRFIDProtocolH10301] = &protocol_h10301,
|
||||||
[LFRFIDProtocolIdteck] = &protocol_idteck,
|
[LFRFIDProtocolIdteck] = &protocol_idteck,
|
||||||
[LFRFIDProtocolIndala26] = &protocol_indala26,
|
[LFRFIDProtocolIndala26] = &protocol_indala26,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
LFRFIDProtocolEM4100,
|
LFRFIDProtocolEM4100,
|
||||||
LFRFIDProtocolEM4100_32,
|
LFRFIDProtocolEM4100_32,
|
||||||
|
LFRFIDProtocolEM4100_16,
|
||||||
LFRFIDProtocolH10301,
|
LFRFIDProtocolH10301,
|
||||||
LFRFIDProtocolIdteck,
|
LFRFIDProtocolIdteck,
|
||||||
LFRFIDProtocolIndala26,
|
LFRFIDProtocolIndala26,
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ uint16_t protocol_em4100_get_time_divisor(ProtocolEM4100* proto) {
|
|||||||
return 1;
|
return 1;
|
||||||
case 32:
|
case 32:
|
||||||
return 2;
|
return 2;
|
||||||
|
case 16:
|
||||||
|
return 4;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -56,6 +58,8 @@ uint32_t protocol_em4100_get_t5577_bitrate(ProtocolEM4100* proto) {
|
|||||||
return LFRFID_T5577_BITRATE_RF_64;
|
return LFRFID_T5577_BITRATE_RF_64;
|
||||||
case 32:
|
case 32:
|
||||||
return LFRFID_T5577_BITRATE_RF_32;
|
return LFRFID_T5577_BITRATE_RF_32;
|
||||||
|
case 16:
|
||||||
|
return LFRFID_T5577_BITRATE_RF_16;
|
||||||
default:
|
default:
|
||||||
return LFRFID_T5577_BITRATE_RF_64;
|
return LFRFID_T5577_BITRATE_RF_64;
|
||||||
}
|
}
|
||||||
@@ -87,6 +91,12 @@ ProtocolEM4100* protocol_em4100_alloc(void) {
|
|||||||
return (void*)proto;
|
return (void*)proto;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ProtocolEM4100* protocol_em4100_16_alloc(void) {
|
||||||
|
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
|
||||||
|
proto->clock_per_bit = 16;
|
||||||
|
return (void*)proto;
|
||||||
|
};
|
||||||
|
|
||||||
ProtocolEM4100* protocol_em4100_32_alloc(void) {
|
ProtocolEM4100* protocol_em4100_32_alloc(void) {
|
||||||
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
|
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
|
||||||
proto->clock_per_bit = 32;
|
proto->clock_per_bit = 32;
|
||||||
@@ -373,3 +383,27 @@ const ProtocolBase protocol_em4100_32 = {
|
|||||||
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
|
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
|
||||||
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
|
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ProtocolBase protocol_em4100_16 = {
|
||||||
|
.name = "EM4100/16",
|
||||||
|
.manufacturer = "EM-Micro",
|
||||||
|
.data_size = EM4100_DECODED_DATA_SIZE,
|
||||||
|
.features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
|
||||||
|
.validate_count = 3,
|
||||||
|
.alloc = (ProtocolAlloc)protocol_em4100_16_alloc,
|
||||||
|
.free = (ProtocolFree)protocol_em4100_free,
|
||||||
|
.get_data = (ProtocolGetData)protocol_em4100_get_data,
|
||||||
|
.decoder =
|
||||||
|
{
|
||||||
|
.start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
|
||||||
|
.feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
|
||||||
|
},
|
||||||
|
.encoder =
|
||||||
|
{
|
||||||
|
.start = (ProtocolEncoderStart)protocol_em4100_encoder_start,
|
||||||
|
.yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
|
||||||
|
},
|
||||||
|
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
|
||||||
|
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
|
||||||
|
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,3 +4,5 @@
|
|||||||
extern const ProtocolBase protocol_em4100;
|
extern const ProtocolBase protocol_em4100;
|
||||||
|
|
||||||
extern const ProtocolBase protocol_em4100_32;
|
extern const ProtocolBase protocol_em4100_32;
|
||||||
|
|
||||||
|
extern const ProtocolBase protocol_em4100_16;
|
||||||
|
|||||||
@@ -139,4 +139,4 @@ void t5577_write_with_mask(LFRFIDT5577* data, uint8_t page, bool with_pass, uint
|
|||||||
t5577_write_reset();
|
t5577_write_reset();
|
||||||
FURI_CRITICAL_EXIT();
|
FURI_CRITICAL_EXIT();
|
||||||
t5577_stop();
|
t5577_stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void name_generator_make_auto_datetime(
|
|||||||
char* name,
|
char* name,
|
||||||
size_t max_name_size,
|
size_t max_name_size,
|
||||||
const char* prefix,
|
const char* prefix,
|
||||||
FuriHalRtcDateTime* custom_time) {
|
DateTime* custom_time) {
|
||||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDetailedFilename)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDetailedFilename)) {
|
||||||
name_generator_make_detailed_datetime(name, max_name_size, prefix, custom_time);
|
name_generator_make_detailed_datetime(name, max_name_size, prefix, custom_time);
|
||||||
} else {
|
} else {
|
||||||
@@ -88,12 +88,12 @@ void name_generator_make_detailed_datetime(
|
|||||||
char* name,
|
char* name,
|
||||||
size_t max_name_size,
|
size_t max_name_size,
|
||||||
const char* prefix,
|
const char* prefix,
|
||||||
FuriHalRtcDateTime* custom_time) {
|
DateTime* custom_time) {
|
||||||
furi_assert(name);
|
furi_assert(name);
|
||||||
furi_assert(max_name_size);
|
furi_assert(max_name_size);
|
||||||
furi_assert(prefix);
|
furi_assert(prefix);
|
||||||
|
|
||||||
FuriHalRtcDateTime dateTime;
|
DateTime dateTime;
|
||||||
if(custom_time) {
|
if(custom_time) {
|
||||||
dateTime = *custom_time;
|
dateTime = *custom_time;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void name_generator_make_auto_datetime(
|
|||||||
char* name,
|
char* name,
|
||||||
size_t max_name_size,
|
size_t max_name_size,
|
||||||
const char* prefix,
|
const char* prefix,
|
||||||
FuriHalRtcDateTime* custom_time);
|
DateTime* custom_time);
|
||||||
|
|
||||||
/** Generates random name
|
/** Generates random name
|
||||||
*
|
*
|
||||||
@@ -41,7 +41,7 @@ void name_generator_make_detailed_datetime(
|
|||||||
char* name,
|
char* name,
|
||||||
size_t max_name_size,
|
size_t max_name_size,
|
||||||
const char* prefix,
|
const char* prefix,
|
||||||
FuriHalRtcDateTime* custom_time);
|
DateTime* custom_time);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,56.0,,
|
Version,+,57.0,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@@ -38,6 +38,7 @@ Header,+,applications/services/power/power_service/power.h,,
|
|||||||
Header,+,applications/services/rpc/rpc_app.h,,
|
Header,+,applications/services/rpc/rpc_app.h,,
|
||||||
Header,+,applications/services/storage/storage.h,,
|
Header,+,applications/services/storage/storage.h,,
|
||||||
Header,+,lib/bit_lib/bit_lib.h,,
|
Header,+,lib/bit_lib/bit_lib.h,,
|
||||||
|
Header,+,lib/datetime/datetime.h,,
|
||||||
Header,+,lib/digital_signal/digital_sequence.h,,
|
Header,+,lib/digital_signal/digital_sequence.h,,
|
||||||
Header,+,lib/digital_signal/digital_signal.h,,
|
Header,+,lib/digital_signal/digital_signal.h,,
|
||||||
Header,+,lib/drivers/cc1101_regs.h,,
|
Header,+,lib/drivers/cc1101_regs.h,,
|
||||||
@@ -742,6 +743,12 @@ Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t"
|
|||||||
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
|
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
|
||||||
Function,-,ctermid,char*,char*
|
Function,-,ctermid,char*,char*
|
||||||
Function,-,cuserid,char*,char*
|
Function,-,cuserid,char*,char*
|
||||||
|
Function,+,datetime_datetime_to_timestamp,uint32_t,DateTime*
|
||||||
|
Function,+,datetime_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
||||||
|
Function,+,datetime_get_days_per_year,uint16_t,uint16_t
|
||||||
|
Function,+,datetime_is_leap_year,_Bool,uint16_t
|
||||||
|
Function,+,datetime_timestamp_to_datetime,void,"uint32_t, DateTime*"
|
||||||
|
Function,+,datetime_validate_datetime,_Bool,DateTime*
|
||||||
Function,+,dialog_ex_alloc,DialogEx*,
|
Function,+,dialog_ex_alloc,DialogEx*,
|
||||||
Function,+,dialog_ex_disable_extended_events,void,DialogEx*
|
Function,+,dialog_ex_disable_extended_events,void,DialogEx*
|
||||||
Function,+,dialog_ex_enable_extended_events,void,DialogEx*
|
Function,+,dialog_ex_enable_extended_events,void,DialogEx*
|
||||||
@@ -1288,12 +1295,9 @@ Function,-,furi_hal_resources_deinit_early,void,
|
|||||||
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
|
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
|
||||||
Function,-,furi_hal_resources_init,void,
|
Function,-,furi_hal_resources_init,void,
|
||||||
Function,-,furi_hal_resources_init_early,void,
|
Function,-,furi_hal_resources_init_early,void,
|
||||||
Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
|
|
||||||
Function,-,furi_hal_rtc_deinit_early,void,
|
Function,-,furi_hal_rtc_deinit_early,void,
|
||||||
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
||||||
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
|
Function,+,furi_hal_rtc_get_datetime,void,DateTime*
|
||||||
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
|
||||||
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
|
|
||||||
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
||||||
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||||
@@ -1308,11 +1312,10 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
|
|||||||
Function,-,furi_hal_rtc_init,void,
|
Function,-,furi_hal_rtc_init,void,
|
||||||
Function,-,furi_hal_rtc_init_early,void,
|
Function,-,furi_hal_rtc_init_early,void,
|
||||||
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
|
|
||||||
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_reset_registers,void,
|
Function,+,furi_hal_rtc_reset_registers,void,
|
||||||
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
||||||
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
|
Function,+,furi_hal_rtc_set_datetime,void,DateTime*
|
||||||
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
|
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
|
||||||
Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
||||||
@@ -1325,8 +1328,6 @@ Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
|||||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||||
Function,+,furi_hal_rtc_sync_shadow,void,
|
Function,+,furi_hal_rtc_sync_shadow,void,
|
||||||
Function,+,furi_hal_rtc_timestamp_to_datetime,void,"uint32_t, FuriHalRtcDateTime*"
|
|
||||||
Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime*
|
|
||||||
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
||||||
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
||||||
Function,+,furi_hal_sd_init,FuriStatus,_Bool
|
Function,+,furi_hal_sd_init,FuriStatus,_Bool
|
||||||
@@ -1728,8 +1729,8 @@ Function,+,loading_free,void,Loading*
|
|||||||
Function,+,loading_get_view,View*,Loading*
|
Function,+,loading_get_view,View*,Loading*
|
||||||
Function,+,locale_celsius_to_fahrenheit,float,float
|
Function,+,locale_celsius_to_fahrenheit,float,float
|
||||||
Function,+,locale_fahrenheit_to_celsius,float,float
|
Function,+,locale_fahrenheit_to_celsius,float,float
|
||||||
Function,+,locale_format_date,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleDateFormat, const char*"
|
Function,+,locale_format_date,void,"FuriString*, const DateTime*, const LocaleDateFormat, const char*"
|
||||||
Function,+,locale_format_time,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleTimeFormat, const _Bool"
|
Function,+,locale_format_time,void,"FuriString*, const DateTime*, const LocaleTimeFormat, const _Bool"
|
||||||
Function,+,locale_get_date_format,LocaleDateFormat,
|
Function,+,locale_get_date_format,LocaleDateFormat,
|
||||||
Function,+,locale_get_measurement_unit,LocaleMeasurementUnits,
|
Function,+,locale_get_measurement_unit,LocaleMeasurementUnits,
|
||||||
Function,+,locale_get_time_format,LocaleTimeFormat,
|
Function,+,locale_get_time_format,LocaleTimeFormat,
|
||||||
|
|||||||
|
@@ -37,7 +37,8 @@
|
|||||||
"heatshrink",
|
"heatshrink",
|
||||||
"flipperformat",
|
"flipperformat",
|
||||||
"flipper18",
|
"flipper18",
|
||||||
"bit_lib"
|
"bit_lib",
|
||||||
|
"datetime"
|
||||||
],
|
],
|
||||||
"excluded_sources": [
|
"excluded_sources": [
|
||||||
"furi_hal_infrared.c",
|
"furi_hal_infrared.c",
|
||||||
@@ -67,4 +68,4 @@
|
|||||||
"ibutton",
|
"ibutton",
|
||||||
"infrared"
|
"infrared"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,56.0,,
|
Version,+,57.0,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@@ -39,6 +39,7 @@ Header,+,applications/services/power/power_service/power.h,,
|
|||||||
Header,+,applications/services/rpc/rpc_app.h,,
|
Header,+,applications/services/rpc/rpc_app.h,,
|
||||||
Header,+,applications/services/storage/storage.h,,
|
Header,+,applications/services/storage/storage.h,,
|
||||||
Header,+,lib/bit_lib/bit_lib.h,,
|
Header,+,lib/bit_lib/bit_lib.h,,
|
||||||
|
Header,+,lib/datetime/datetime.h,,
|
||||||
Header,+,lib/digital_signal/digital_sequence.h,,
|
Header,+,lib/digital_signal/digital_sequence.h,,
|
||||||
Header,+,lib/digital_signal/digital_signal.h,,
|
Header,+,lib/digital_signal/digital_signal.h,,
|
||||||
Header,+,lib/drivers/cc1101_regs.h,,
|
Header,+,lib/drivers/cc1101_regs.h,,
|
||||||
@@ -814,6 +815,12 @@ Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t"
|
|||||||
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
|
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
|
||||||
Function,-,ctermid,char*,char*
|
Function,-,ctermid,char*,char*
|
||||||
Function,-,cuserid,char*,char*
|
Function,-,cuserid,char*,char*
|
||||||
|
Function,+,datetime_datetime_to_timestamp,uint32_t,DateTime*
|
||||||
|
Function,+,datetime_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
||||||
|
Function,+,datetime_get_days_per_year,uint16_t,uint16_t
|
||||||
|
Function,+,datetime_is_leap_year,_Bool,uint16_t
|
||||||
|
Function,+,datetime_timestamp_to_datetime,void,"uint32_t, DateTime*"
|
||||||
|
Function,+,datetime_validate_datetime,_Bool,DateTime*
|
||||||
Function,+,dialog_ex_alloc,DialogEx*,
|
Function,+,dialog_ex_alloc,DialogEx*,
|
||||||
Function,+,dialog_ex_disable_extended_events,void,DialogEx*
|
Function,+,dialog_ex_disable_extended_events,void,DialogEx*
|
||||||
Function,+,dialog_ex_enable_extended_events,void,DialogEx*
|
Function,+,dialog_ex_enable_extended_events,void,DialogEx*
|
||||||
@@ -1459,12 +1466,9 @@ Function,+,furi_hal_rfid_tim_read_continue,void,
|
|||||||
Function,+,furi_hal_rfid_tim_read_pause,void,
|
Function,+,furi_hal_rfid_tim_read_pause,void,
|
||||||
Function,+,furi_hal_rfid_tim_read_start,void,"float, float"
|
Function,+,furi_hal_rfid_tim_read_start,void,"float, float"
|
||||||
Function,+,furi_hal_rfid_tim_read_stop,void,
|
Function,+,furi_hal_rfid_tim_read_stop,void,
|
||||||
Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
|
|
||||||
Function,-,furi_hal_rtc_deinit_early,void,
|
Function,-,furi_hal_rtc_deinit_early,void,
|
||||||
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
||||||
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
|
Function,+,furi_hal_rtc_get_datetime,void,DateTime*
|
||||||
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
|
||||||
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
|
|
||||||
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
||||||
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||||
@@ -1479,11 +1483,10 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
|
|||||||
Function,-,furi_hal_rtc_init,void,
|
Function,-,furi_hal_rtc_init,void,
|
||||||
Function,-,furi_hal_rtc_init_early,void,
|
Function,-,furi_hal_rtc_init_early,void,
|
||||||
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
|
|
||||||
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_reset_registers,void,
|
Function,+,furi_hal_rtc_reset_registers,void,
|
||||||
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
||||||
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
|
Function,+,furi_hal_rtc_set_datetime,void,DateTime*
|
||||||
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
|
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
|
||||||
Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag
|
Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag
|
||||||
Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
||||||
@@ -1496,8 +1499,6 @@ Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
|||||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||||
Function,+,furi_hal_rtc_sync_shadow,void,
|
Function,+,furi_hal_rtc_sync_shadow,void,
|
||||||
Function,+,furi_hal_rtc_timestamp_to_datetime,void,"uint32_t, FuriHalRtcDateTime*"
|
|
||||||
Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime*
|
|
||||||
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
||||||
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
||||||
Function,+,furi_hal_sd_init,FuriStatus,_Bool
|
Function,+,furi_hal_sd_init,FuriStatus,_Bool
|
||||||
@@ -2139,8 +2140,8 @@ Function,+,loading_free,void,Loading*
|
|||||||
Function,+,loading_get_view,View*,Loading*
|
Function,+,loading_get_view,View*,Loading*
|
||||||
Function,+,locale_celsius_to_fahrenheit,float,float
|
Function,+,locale_celsius_to_fahrenheit,float,float
|
||||||
Function,+,locale_fahrenheit_to_celsius,float,float
|
Function,+,locale_fahrenheit_to_celsius,float,float
|
||||||
Function,+,locale_format_date,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleDateFormat, const char*"
|
Function,+,locale_format_date,void,"FuriString*, const DateTime*, const LocaleDateFormat, const char*"
|
||||||
Function,+,locale_format_time,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleTimeFormat, const _Bool"
|
Function,+,locale_format_time,void,"FuriString*, const DateTime*, const LocaleTimeFormat, const _Bool"
|
||||||
Function,+,locale_get_date_format,LocaleDateFormat,
|
Function,+,locale_get_date_format,LocaleDateFormat,
|
||||||
Function,+,locale_get_measurement_unit,LocaleMeasurementUnits,
|
Function,+,locale_get_measurement_unit,LocaleMeasurementUnits,
|
||||||
Function,+,locale_get_time_format,LocaleTimeFormat,
|
Function,+,locale_get_time_format,LocaleTimeFormat,
|
||||||
@@ -2603,9 +2604,9 @@ Function,-,music_worker_set_volume,void,"MusicWorker*, float"
|
|||||||
Function,-,music_worker_start,void,MusicWorker*
|
Function,-,music_worker_start,void,MusicWorker*
|
||||||
Function,-,music_worker_stop,void,MusicWorker*
|
Function,-,music_worker_stop,void,MusicWorker*
|
||||||
Function,+,name_generator_make_auto,void,"char*, size_t, const char*"
|
Function,+,name_generator_make_auto,void,"char*, size_t, const char*"
|
||||||
Function,+,name_generator_make_auto_datetime,void,"char*, size_t, const char*, FuriHalRtcDateTime*"
|
Function,+,name_generator_make_auto_datetime,void,"char*, size_t, const char*, DateTime*"
|
||||||
Function,+,name_generator_make_detailed,void,"char*, size_t, const char*"
|
Function,+,name_generator_make_detailed,void,"char*, size_t, const char*"
|
||||||
Function,+,name_generator_make_detailed_datetime,void,"char*, size_t, const char*, FuriHalRtcDateTime*"
|
Function,+,name_generator_make_detailed_datetime,void,"char*, size_t, const char*, DateTime*"
|
||||||
Function,+,name_generator_make_random,void,"char*, size_t"
|
Function,+,name_generator_make_random,void,"char*, size_t"
|
||||||
Function,+,name_generator_make_random_prefixed,void,"char*, size_t, const char*"
|
Function,+,name_generator_make_random_prefixed,void,"char*, size_t, const char*"
|
||||||
Function,-,nan,double,const char*
|
Function,-,nan,double,const char*
|
||||||
|
|||||||
|
@@ -15,7 +15,7 @@ void fatfs_init(void) {
|
|||||||
* @return Time in DWORD (toasters per square washing machine)
|
* @return Time in DWORD (toasters per square washing machine)
|
||||||
*/
|
*/
|
||||||
DWORD get_fattime() {
|
DWORD get_fattime() {
|
||||||
FuriHalRtcDateTime furi_time;
|
DateTime furi_time;
|
||||||
furi_hal_rtc_get_datetime(&furi_time);
|
furi_hal_rtc_get_datetime(&furi_time);
|
||||||
|
|
||||||
return ((uint32_t)(furi_time.year - 1980) << 25) | furi_time.month << 21 |
|
return ((uint32_t)(furi_time.year - 1980) << 25) | furi_time.month << 21 |
|
||||||
|
|||||||
@@ -42,18 +42,6 @@ typedef struct {
|
|||||||
|
|
||||||
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
|
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
|
||||||
|
|
||||||
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
|
|
||||||
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
|
|
||||||
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
|
|
||||||
#define FURI_HAL_RTC_MONTHS_COUNT 12
|
|
||||||
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
|
|
||||||
|
|
||||||
static const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] = {
|
|
||||||
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
|
||||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
|
||||||
|
|
||||||
static const uint16_t furi_hal_rtc_days_per_year[] = {365, 366};
|
|
||||||
|
|
||||||
static const FuriHalSerialId furi_hal_rtc_log_devices[] = {
|
static const FuriHalSerialId furi_hal_rtc_log_devices[] = {
|
||||||
[FuriHalRtcLogDeviceUsart] = FuriHalSerialIdUsart,
|
[FuriHalRtcLogDeviceUsart] = FuriHalSerialIdUsart,
|
||||||
[FuriHalRtcLogDeviceLpuart] = FuriHalSerialIdLpuart,
|
[FuriHalRtcLogDeviceLpuart] = FuriHalSerialIdLpuart,
|
||||||
@@ -103,7 +91,7 @@ static bool furi_hal_rtc_start_clock_and_switch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void furi_hal_rtc_recover() {
|
static void furi_hal_rtc_recover() {
|
||||||
FuriHalRtcDateTime datetime = {0};
|
DateTime datetime = {0};
|
||||||
|
|
||||||
// Handle fixable LSE failure
|
// Handle fixable LSE failure
|
||||||
if(LL_RCC_LSE_IsCSSDetected()) {
|
if(LL_RCC_LSE_IsCSSDetected()) {
|
||||||
@@ -350,7 +338,7 @@ FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat() {
|
|||||||
return data->locale_dateformat;
|
return data->locale_dateformat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {
|
void furi_hal_rtc_set_datetime(DateTime* datetime) {
|
||||||
furi_check(!FURI_IS_IRQ_MODE());
|
furi_check(!FURI_IS_IRQ_MODE());
|
||||||
furi_assert(datetime);
|
furi_assert(datetime);
|
||||||
|
|
||||||
@@ -389,7 +377,7 @@ void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {
|
|||||||
FURI_CRITICAL_EXIT();
|
FURI_CRITICAL_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime) {
|
void furi_hal_rtc_get_datetime(DateTime* datetime) {
|
||||||
furi_check(!FURI_IS_IRQ_MODE());
|
furi_check(!FURI_IS_IRQ_MODE());
|
||||||
furi_assert(datetime);
|
furi_assert(datetime);
|
||||||
|
|
||||||
@@ -407,28 +395,6 @@ void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime) {
|
|||||||
datetime->weekday = __LL_RTC_CONVERT_BCD2BIN((date >> 24) & 0xFF);
|
datetime->weekday = __LL_RTC_CONVERT_BCD2BIN((date >> 24) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime) {
|
|
||||||
bool invalid = false;
|
|
||||||
|
|
||||||
invalid |= (datetime->second > 59);
|
|
||||||
invalid |= (datetime->minute > 59);
|
|
||||||
invalid |= (datetime->hour > 23);
|
|
||||||
|
|
||||||
invalid |= (datetime->year < 2000);
|
|
||||||
invalid |= (datetime->year > 2099);
|
|
||||||
|
|
||||||
invalid |= (datetime->month == 0);
|
|
||||||
invalid |= (datetime->month > 12);
|
|
||||||
|
|
||||||
invalid |= (datetime->day == 0);
|
|
||||||
invalid |= (datetime->day > 31);
|
|
||||||
|
|
||||||
invalid |= (datetime->weekday == 0);
|
|
||||||
invalid |= (datetime->weekday > 7);
|
|
||||||
|
|
||||||
return !invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_rtc_set_fault_data(uint32_t value) {
|
void furi_hal_rtc_set_fault_data(uint32_t value) {
|
||||||
furi_hal_rtc_set_register(FuriHalRtcRegisterFaultData, value);
|
furi_hal_rtc_set_register(FuriHalRtcRegisterFaultData, value);
|
||||||
}
|
}
|
||||||
@@ -446,76 +412,7 @@ uint32_t furi_hal_rtc_get_pin_fails() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t furi_hal_rtc_get_timestamp() {
|
uint32_t furi_hal_rtc_get_timestamp() {
|
||||||
FuriHalRtcDateTime datetime = {0};
|
DateTime datetime = {0};
|
||||||
furi_hal_rtc_get_datetime(&datetime);
|
furi_hal_rtc_get_datetime(&datetime);
|
||||||
return furi_hal_rtc_datetime_to_timestamp(&datetime);
|
return datetime_datetime_to_timestamp(&datetime);
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
uint8_t years = 0;
|
|
||||||
uint8_t leap_years = 0;
|
|
||||||
|
|
||||||
for(uint16_t y = FURI_HAL_RTC_EPOCH_START_YEAR; y < datetime->year; y++) {
|
|
||||||
if(furi_hal_rtc_is_leap_year(y)) {
|
|
||||||
leap_years++;
|
|
||||||
} else {
|
|
||||||
years++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp +=
|
|
||||||
((years * furi_hal_rtc_days_per_year[0]) + (leap_years * furi_hal_rtc_days_per_year[1])) *
|
|
||||||
FURI_HAL_RTC_SECONDS_PER_DAY;
|
|
||||||
|
|
||||||
bool leap_year = furi_hal_rtc_is_leap_year(datetime->year);
|
|
||||||
|
|
||||||
for(uint8_t m = 1; m < datetime->month; m++) {
|
|
||||||
timestamp += furi_hal_rtc_get_days_per_month(leap_year, m) * FURI_HAL_RTC_SECONDS_PER_DAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp += (datetime->day - 1) * FURI_HAL_RTC_SECONDS_PER_DAY;
|
|
||||||
timestamp += datetime->hour * FURI_HAL_RTC_SECONDS_PER_HOUR;
|
|
||||||
timestamp += datetime->minute * FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
|
||||||
timestamp += datetime->second;
|
|
||||||
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_rtc_timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) {
|
|
||||||
uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY;
|
|
||||||
uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY;
|
|
||||||
|
|
||||||
datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR;
|
|
||||||
|
|
||||||
while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) {
|
|
||||||
days -= furi_hal_rtc_get_days_per_year(datetime->year);
|
|
||||||
(datetime->year)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
datetime->month = 1;
|
|
||||||
while(days >= furi_hal_rtc_get_days_per_month(
|
|
||||||
furi_hal_rtc_is_leap_year(datetime->year), datetime->month)) {
|
|
||||||
days -= furi_hal_rtc_get_days_per_month(
|
|
||||||
furi_hal_rtc_is_leap_year(datetime->year), datetime->month);
|
|
||||||
(datetime->month)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
datetime->day = days + 1;
|
|
||||||
datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR;
|
|
||||||
datetime->minute =
|
|
||||||
(seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
|
||||||
datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year) {
|
|
||||||
return furi_hal_rtc_days_per_year[furi_hal_rtc_is_leap_year(year) ? 1 : 0];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool furi_hal_rtc_is_leap_year(uint16_t year) {
|
|
||||||
return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month) {
|
|
||||||
return furi_hal_rtc_days_per_month[leap_year ? 1 : 0][month - 1];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,22 +8,12 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <datetime/datetime.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
// Time
|
|
||||||
uint8_t hour; /**< Hour in 24H format: 0-23 */
|
|
||||||
uint8_t minute; /**< Minute: 0-59 */
|
|
||||||
uint8_t second; /**< Second: 0-59 */
|
|
||||||
// Date
|
|
||||||
uint8_t day; /**< Current day: 1-31 */
|
|
||||||
uint8_t month; /**< Current month: 1-12 */
|
|
||||||
uint16_t year; /**< Current year: 2000-2099 */
|
|
||||||
uint8_t weekday; /**< Current weekday: 1-7 */
|
|
||||||
} FuriHalRtcDateTime;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FuriHalRtcFlagDebug = (1 << 0),
|
FuriHalRtcFlagDebug = (1 << 0),
|
||||||
FuriHalRtcFlagStorageFormatInternal = (1 << 1),
|
FuriHalRtcFlagStorageFormatInternal = (1 << 1),
|
||||||
@@ -247,21 +237,13 @@ FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat(void);
|
|||||||
*
|
*
|
||||||
* @param datetime The date time to set
|
* @param datetime The date time to set
|
||||||
*/
|
*/
|
||||||
void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime);
|
void furi_hal_rtc_set_datetime(DateTime* datetime);
|
||||||
|
|
||||||
/** Get RTC Date Time
|
/** Get RTC Date Time
|
||||||
*
|
*
|
||||||
* @param datetime The datetime
|
* @param datetime The datetime
|
||||||
*/
|
*/
|
||||||
void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime);
|
void furi_hal_rtc_get_datetime(DateTime* datetime);
|
||||||
|
|
||||||
/** Validate Date Time
|
|
||||||
*
|
|
||||||
* @param datetime The datetime to validate
|
|
||||||
*
|
|
||||||
* @return { description_of_the_return_value }
|
|
||||||
*/
|
|
||||||
bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime);
|
|
||||||
|
|
||||||
/** Set RTC Fault Data
|
/** Set RTC Fault Data
|
||||||
*
|
*
|
||||||
@@ -293,49 +275,6 @@ uint32_t furi_hal_rtc_get_pin_fails(void);
|
|||||||
*/
|
*/
|
||||||
uint32_t furi_hal_rtc_get_timestamp(void);
|
uint32_t furi_hal_rtc_get_timestamp(void);
|
||||||
|
|
||||||
/** Convert DateTime to UNIX timestamp
|
|
||||||
*
|
|
||||||
* @warning Mind timezone when perform conversion
|
|
||||||
*
|
|
||||||
* @param datetime The datetime (UTC)
|
|
||||||
*
|
|
||||||
* @return UNIX Timestamp in seconds from UNIX epoch start
|
|
||||||
*/
|
|
||||||
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
|
|
||||||
|
|
||||||
/** Convert UNIX timestamp to DateTime
|
|
||||||
*
|
|
||||||
* @warning Mind timezone when perform conversion
|
|
||||||
*
|
|
||||||
* @param[in] timestamp UNIX Timestamp in seconds from UNIX epoch start
|
|
||||||
* @param[out] datetime The datetime (UTC)
|
|
||||||
*/
|
|
||||||
void furi_hal_rtc_timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime);
|
|
||||||
|
|
||||||
/** Gets the number of days in the year according to the Gregorian calendar.
|
|
||||||
*
|
|
||||||
* @param year Input year.
|
|
||||||
*
|
|
||||||
* @return number of days in `year`.
|
|
||||||
*/
|
|
||||||
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year);
|
|
||||||
|
|
||||||
/** Check if a year a leap year in the Gregorian calendar.
|
|
||||||
*
|
|
||||||
* @param year Input year.
|
|
||||||
*
|
|
||||||
* @return true if `year` is a leap year.
|
|
||||||
*/
|
|
||||||
bool furi_hal_rtc_is_leap_year(uint16_t year);
|
|
||||||
|
|
||||||
/** Get the number of days in the month.
|
|
||||||
*
|
|
||||||
* @param leap_year true to calculate based on leap years
|
|
||||||
* @param month month to check, where 1 = January
|
|
||||||
* @return the number of days in the month
|
|
||||||
*/
|
|
||||||
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
"heatshrink",
|
"heatshrink",
|
||||||
"flipperformat",
|
"flipperformat",
|
||||||
"flipper7",
|
"flipper7",
|
||||||
"bit_lib"
|
"bit_lib",
|
||||||
|
"datetime"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user