#![no_std] #![feature(trace_macros)] #![feature(concat_idents)] #![feature(proc_macro_hygiene)] #![feature(exclusive_range_pattern)]
pub use watchface;
use core::{
fmt::Write,
ptr,
};
use macros::strn;
use watchface::lvgl::mynewt::{
result::*,
Strn,
};
use watchface::lvgl::{
self,
core::obj,
themes::theme,
widgets::label,
};
use watchface::{
BluetoothState,
String,
WatchFace,
WatchFaceState,
WatchFaceTime,
new_string,
to_strn,
};
pub struct BarebonesWatchFace {
pub time_label: lvgl::Ptr,
pub date_label: lvgl::Ptr,
pub bluetooth_label: lvgl::Ptr,
pub power_label: lvgl::Ptr,
}
impl WatchFace for BarebonesWatchFace {
fn new() -> MynewtResult<Self> {
let screen = watchface::get_active_screen();
let title_font = theme::get_font_title() ? ;
let watch_face = Self {
time_label: {
let lbl = label::create(screen, ptr::null()) ? ; label::set_long_mode(lbl, label::LV_LABEL_LONG_BREAK) ? ;
label::set_text( lbl, strn!("00:00")) ? ; obj::set_width( lbl, 240) ? ;
obj::set_height( lbl, 200) ? ;
label::set_align( lbl, label::LV_LABEL_ALIGN_CENTER) ? ;
obj::align( lbl, screen, obj::LV_ALIGN_CENTER, 0, -30) ? ;
obj::set_style_local_text_font(lbl, label::LV_LABEL_PART_MAIN, obj::LV_STATE_DEFAULT, title_font) ? ; lbl },
date_label: {
let lbl = label::create(screen, ptr::null()) ? ;
label::set_long_mode(lbl, label::LV_LABEL_LONG_BREAK) ? ;
obj::set_width( lbl, 200) ? ;
obj::set_height( lbl, 200) ? ;
label::set_text( lbl, strn!("")) ? ; label::set_align( lbl, label::LV_LABEL_ALIGN_CENTER) ? ;
obj::align( lbl, screen, obj::LV_ALIGN_CENTER, 0, 40) ? ;
lbl },
bluetooth_label: {
let lbl = label::create(screen, ptr::null()) ? ;
obj::set_width( lbl, 50) ? ;
obj::set_height( lbl, 80) ? ;
label::set_text( lbl, strn!("")) ? ; label::set_recolor( lbl, true) ? ;
label::set_align( lbl, label::LV_LABEL_ALIGN_LEFT) ? ;
obj::align( lbl, screen, obj::LV_ALIGN_IN_TOP_LEFT, 0, 0) ? ;
lbl },
power_label: {
let lbl = label::create(screen, ptr::null()) ? ;
obj::set_width( lbl, 80) ? ;
obj::set_height( lbl, 20) ? ;
label::set_text( lbl, strn!("")) ? ; label::set_recolor(lbl, true) ? ;
label::set_align( lbl, label::LV_LABEL_ALIGN_RIGHT) ? ;
obj::align( lbl, screen, obj::LV_ALIGN_IN_TOP_RIGHT, 0, 0) ? ;
lbl },
};
Ok(watch_face)
}
fn update(&mut self, state: &WatchFaceState) -> MynewtResult<()> {
self.update_date_time(state) ? ;
self.update_bluetooth(state) ? ;
self.update_power(state) ? ;
Ok(())
}
}
impl BarebonesWatchFace {
fn update_date_time(&self, state: &WatchFaceState) -> MynewtResult<()> {
let mut buf = new_string();
write!(
&mut buf, "{:02}:{:02}\0", state.time.hour,
state.time.minute
).expect("time fail");
label::set_text( self.time_label,
&to_strn(&buf)
) ? ;
let day = get_day_name(&state.time);
let month = get_month_name(&state.time);
let mut buf = new_string();
write!(
&mut buf, "{} {} {} {}\n\0", day,
state.time.day,
month,
state.time.year
).expect("date fail");
label::set_text( self.date_label,
&to_strn(&buf)
) ? ;
Ok(())
}
fn update_bluetooth(&self, state: &WatchFaceState) -> MynewtResult<()> {
if state.bluetooth == BluetoothState::BLUETOOTH_STATE_DISCONNECTED {
label::set_text(
self.bluetooth_label,
strn!("")
) ? ;
} else {
let color =
match &state.bluetooth {
BluetoothState::BLUETOOTH_STATE_INACTIVE => "#000000", BluetoothState::BLUETOOTH_STATE_ADVERTISING => "#0000ff", BluetoothState::BLUETOOTH_STATE_DISCONNECTED => "#ff0000", BluetoothState::BLUETOOTH_STATE_CONNECTED => "#00ff00", };
let mut buf = new_string();
write!(
&mut buf, "{} \u{F293}#\0", color
).expect("bt fail");
label::set_text( self.bluetooth_label,
&to_strn(&buf)
) ? ;
}
Ok(())
}
fn update_power(&self, state: &WatchFaceState) -> MynewtResult<()> {
let screen = watchface::get_active_screen();
let percentage = convert_battery_voltage(state.millivolts);
let color = if percentage <= 20 { "#f2495c" } else if state.powered && !(state.charging) { "#73bf69" } else { "#fade2a" };
let symbol = if state.powered { "\u{F0E7}" } else { " " };
let mut buf = new_string();
write!(
&mut buf, "{} {}%{}#\nRUST ({}mV)\0", color,
percentage,
symbol,
state.millivolts
).expect("batt fail");
label::set_text(
self.power_label,
&to_strn(&buf)
) ? ;
obj::align(
self.power_label, screen,
obj::LV_ALIGN_IN_TOP_RIGHT, 0, 0
) ? ;
Ok(())
}
}
fn get_month_name(time: &WatchFaceTime) -> String {
String::from(
match time.month {
1 => "JAN",
2 => "FEB",
3 => "MAR",
4 => "APR",
5 => "MAY",
6 => "JUN",
7 => "JUL",
8 => "AUG",
9 => "SEP",
10 => "OCT",
11 => "NOV",
12 => "DEC",
_ => "???",
}
)
}
fn get_day_name(time: & WatchFaceTime) -> String {
String::from(
match time.day_of_week {
0 => "SUN",
1 => "MON",
2 => "TUE",
3 => "WED",
4 => "THU",
5 => "FRI",
6 => "SAT",
_ => "???",
}
)
}
fn convert_battery_voltage(_voltage: u32) -> i32 {
50 }