Skip to content

Commit

Permalink
Support none ascii characters sent from Gadgetbridge. Fixes #83
Browse files Browse the repository at this point in the history
Added new font of size 16 that contains most UTF letters between 0x0 and 0xFF.
Use this font in notifications.

Disable ZDS app by default to fit new font with more UTF characters.
  • Loading branch information
jakkra committed Nov 1, 2023
1 parent d36209f commit 987170d
Show file tree
Hide file tree
Showing 8 changed files with 3,110 additions and 7 deletions.
2 changes: 1 addition & 1 deletion app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ menu "ZSWatch"
config APPLICATIONS_USE_ZDS
bool
prompt "Activate the application 'ZDS'"
default y
default n
select APPLICATIONS_USE_ACCELEROMETER

config APPLICATIONS_USE_IAQ
Expand Down
2 changes: 1 addition & 1 deletion app/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,4 @@ CONFIG_INPUT_CST816S=n
CONFIG_INPUT_MODIFIED_CST816S=y

# APDS9306
CONFIG_APDS9306_IS_APDS9306_065=y
CONFIG_APDS9306_IS_APDS9306_065=y
3 changes: 3 additions & 0 deletions app/src/applications/notification/notification_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,19 @@ static void build_notification_entry(lv_obj_t *parent, zsw_not_mngr_notification
lv_group_add_obj(input_group, cont);
lv_obj_add_flag(cont, LV_OBJ_FLAG_SCROLL_ON_FOCUS);

LV_FONT_DECLARE(lv_font_montserrat_14_full)
title = lv_label_create(cont);
lv_label_set_text(title, not->title);
lv_obj_set_size(title, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_center(title);
lv_obj_add_flag(title, LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_style_text_font(title, &lv_font_montserrat_14_full, 0);

title = lv_label_create(cont);
lv_label_set_text(title, not->body);
lv_obj_set_size(title, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_add_flag(title, LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_style_text_font(title, &lv_font_montserrat_14_full, 0);
}

static void not_button_pressed(lv_event_t *e)
Expand Down
4 changes: 2 additions & 2 deletions app/src/applications/zds/zds_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ static application_t app = {
static void zds_app_start(lv_obj_t *root, lv_group_t *group)
{
zds_ui_show(root);
zbus_obs_set_enable(&zds_app_accel_lis, true);
zbus_chan_add_obs(&accel_data_chan, &zds_app_accel_lis, K_MSEC(100));
}

static void zds_app_stop(void)
{
zbus_obs_set_enable(&zds_app_accel_lis, false);
zbus_chan_rm_obs(&accel_data_chan, &zds_app_accel_lis, K_MSEC(100));
zds_ui_remove();
}

Expand Down
179 changes: 179 additions & 0 deletions app/src/ble/ble_comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,180 @@ static int32_t extract_value_int32(char *key, char *data)
return id;
}


static void convert_to_encoded_text(char *data, int len, char *out_data, int out_buf_len)
{
int i = 0, j = 0;
// https://www.utf8-chartable.de/
uint8_t basic_latin_utf16_to_utf8_table[0x80][3] = {
// utf-16 => 2 byte utf-8
{0x80, 0xc2, 0x80},
{0x81, 0xc2, 0x81},
{0x82, 0xc2, 0x82},
{0x83, 0xc2, 0x83},
{0x84, 0xc2, 0x84},
{0x85, 0xc2, 0x85},
{0x86, 0xc2, 0x86},
{0x87, 0xc2, 0x87},
{0x88, 0xc2, 0x88},
{0x89, 0xc2, 0x89},
{0x8A, 0xc2, 0x8a},
{0x8B, 0xc2, 0x8b},
{0x8C, 0xc2, 0x8c},
{0x8D, 0xc2, 0x8d},
{0x8E, 0xc2, 0x8e},
{0x8F, 0xc2, 0x8f},
{0x90, 0xc2, 0x90},
{0x91, 0xc2, 0x91},
{0x92, 0xc2, 0x92},
{0x93, 0xc2, 0x93},
{0x94, 0xc2, 0x94},
{0x95, 0xc2, 0x95},
{0x96, 0xc2, 0x96},
{0x97, 0xc2, 0x97},
{0x98, 0xc2, 0x98},
{0x99, 0xc2, 0x99},
{0x9A, 0xc2, 0x9a},
{0x9B, 0xc2, 0x9b},
{0x9C, 0xc2, 0x9c},
{0x9D, 0xc2, 0x9d},
{0x9E, 0xc2, 0x9e},
{0x9F, 0xc2, 0x9f},
{0xA0, 0xc2, 0xa0},
{0xA1, 0xc2, 0xa1},
{0xA2, 0xc2, 0xa2},
{0xA3, 0xc2, 0xa3},
{0xA4, 0xc2, 0xa4},
{0xA5, 0xc2, 0xa5},
{0xA6, 0xc2, 0xa6},
{0xA7, 0xc2, 0xa7},
{0xA8, 0xc2, 0xa8},
{0xA9, 0xc2, 0xa9},
{0xAA, 0xc2, 0xaa},
{0xAB, 0xc2, 0xab},
{0xAC, 0xc2, 0xac},
{0xAD, 0xc2, 0xad},
{0xAE, 0xc2, 0xae},
{0xAF, 0xc2, 0xaf},
{0xB0, 0xc2, 0xb0},
{0xB1, 0xc2, 0xb1},
{0xB2, 0xc2, 0xb2},
{0xB3, 0xc2, 0xb3},
{0xB4, 0xc2, 0xb4},
{0xB5, 0xc2, 0xb5},
{0xB6, 0xc2, 0xb6},
{0xB7, 0xc2, 0xb7},
{0xB8, 0xc2, 0xb8},
{0xB9, 0xc2, 0xb9},
{0xBA, 0xc2, 0xba},
{0xBB, 0xc2, 0xbb},
{0xBC, 0xc2, 0xbc},
{0xBD, 0xc2, 0xbd},
{0xBE, 0xc2, 0xbe},
{0xBF, 0xc2, 0xbf},
{0xC0, 0xc3, 0x80},
{0xC1, 0xc3, 0x81},
{0xC2, 0xc3, 0x82},
{0xC3, 0xc3, 0x83},
{0xC4, 0xc3, 0x84},
{0xC5, 0xc3, 0x85},
{0xC6, 0xc3, 0x86},
{0xC7, 0xc3, 0x87},
{0xC8, 0xc3, 0x88},
{0xC9, 0xc3, 0x89},
{0xCA, 0xc3, 0x8a},
{0xCB, 0xc3, 0x8b},
{0xCC, 0xc3, 0x8c},
{0xCD, 0xc3, 0x8d},
{0xCE, 0xc3, 0x8e},
{0xCF, 0xc3, 0x8f},
{0xD0, 0xc3, 0x90},
{0xD1, 0xc3, 0x91},
{0xD2, 0xc3, 0x92},
{0xD3, 0xc3, 0x93},
{0xD4, 0xc3, 0x94},
{0xD5, 0xc3, 0x95},
{0xD6, 0xc3, 0x96},
{0xD7, 0xc3, 0x97},
{0xD8, 0xc3, 0x98},
{0xD9, 0xc3, 0x99},
{0xDA, 0xc3, 0x9a},
{0xDB, 0xc3, 0x9b},
{0xDC, 0xc3, 0x9c},
{0xDD, 0xc3, 0x9d},
{0xDE, 0xc3, 0x9e},
{0xDF, 0xc3, 0x9f},
{0xE0, 0xc3, 0xa0},
{0xE1, 0xc3, 0xa1},
{0xE2, 0xc3, 0xa2},
{0xE3, 0xc3, 0xa3},
{0xE4, 0xc3, 0xa4},
{0xE5, 0xc3, 0xa5},
{0xE6, 0xc3, 0xa6},
{0xE7, 0xc3, 0xa7},
{0xE8, 0xc3, 0xa8},
{0xE9, 0xc3, 0xa9},
{0xEA, 0xc3, 0xaa},
{0xEB, 0xc3, 0xab},
{0xEC, 0xc3, 0xac},
{0xED, 0xc3, 0xad},
{0xEE, 0xc3, 0xae},
{0xEF, 0xc3, 0xaf},
{0xF0, 0xc3, 0xb0},
{0xF1, 0xc3, 0xb1},
{0xF2, 0xc3, 0xb2},
{0xF3, 0xc3, 0xb3},
{0xF4, 0xc3, 0xb4},
{0xF5, 0xc3, 0xb5},
{0xF6, 0xc3, 0xb6},
{0xF7, 0xc3, 0xb7},
{0xF8, 0xc3, 0xb8},
{0xF9, 0xc3, 0xb9},
{0xFA, 0xc3, 0xba},
{0xFB, 0xc3, 0xbb},
{0xFC, 0xc3, 0xbc},
{0xFD, 0xc3, 0xbd},
{0xFE, 0xc3, 0xbe},
{0xFF, 0xc3, 0xbf},
};

// For none ascii characters Gadgetbridge encodes them in a strange utf-16 way.
// For example Gadgetbridge sends ö as just 0xF6 byte, but then it sends ä as "\xe4" (4 bytes) string.
// Which is very strange.
// LVGL works with ascii, and properly formatted utf-8.
while (data[i] != '\0' && i < len - 3 && j < out_buf_len - 3) {
if (data[i] == '\\' && data[i + 1] == 'x') {
// Parse string "\xe4" as 0xe4
char hex[3] = {data[i + 2], data[i + 3], '\0'};
int value = strtol(hex, NULL, 16);
if (value < 0x80) {
// Character encoded in a string, but it's an normal ascii, just copy it.
out_data[j] = value;
} else {
// Character encoded as "\xe4" (4 bytes)
out_data[j] = basic_latin_utf16_to_utf8_table[value - 0x80][1];
j++;
out_data[j] = basic_latin_utf16_to_utf8_table[value - 0x80][2];
j++;
}
i += 4;
} else if (data[i] >= 0x80) {
// Character encoded as utf-16, but in a single byte and the value is not ascii.
out_data[j] = basic_latin_utf16_to_utf8_table[data[i] - 0x80][1];
j++;
out_data[j] = basic_latin_utf16_to_utf8_table[data[i] - 0x80][2];
j++;
i++;
} else {
// Ascii character, just copy it.
out_data[j] = data[i];
i++;
j++;
}
}
out_data[j] = '\0';
}

static int parse_notify(char *data, int len)
{
ble_comm_cb_data_t cb;
Expand Down Expand Up @@ -645,6 +819,11 @@ static int parse_data(char *data, int len)
{
int type_len;
char *type;
uint8_t input_data_utf8[MAX_GB_PACKET_LENGTH];

// Convert data from Gadgetbridge into properly encoded text.
convert_to_encoded_text(data, len, input_data_utf8, sizeof(input_data_utf8));
data = input_data_utf8;

type = extract_value_str("\"t\":", data, &type_len);
if (type == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion app/src/events/accel_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ZBUS_CHAN_DEFINE(accel_data_chan,
NULL,
NULL,
#ifdef CONFIG_APPLICATIONS_USE_ACCELEROMETER
ZBUS_OBSERVERS(watchface_accel_lis, power_manager_accel_lis, zds_app_accel_lis),
ZBUS_OBSERVERS(watchface_accel_lis, power_manager_accel_lis),
#else
ZBUS_OBSERVERS(watchface_accel_lis, power_manager_accel_lis),
#endif
Expand Down
Loading

0 comments on commit 987170d

Please sign in to comment.