hacking 麦步手表之(3)制作一个英文表盘xzy-reborn

xiaoxiao2021-02-28  96

前不久,出了一件怪事,不知道是太阳风暴,还是恰逢农历闰六月的,

还是其他原因引起,

我的手表开始不断死机重启.

正想是不是联系售后寄回去时,

我发现了只要切换别的表盘就一切正常了,

再切换回"超清时钟"表盘有就立出现故障,

无奈只好忍痛割爱.

之后发现官方也把这个表盘下架了.

一时间再也找不到代替的时钟表盘.于是只好自己动手丰衣足食,自己做一个. 第一步:找素材

上官方淘宝评论找"高清时钟"的表盘图片,为了凑齐0~9的图片,可是费了九牛二虎之力

第二步,依葫芦画瓢

第三步:写代码

appinfo.json

{ "uuid": "e06ee4971ac29fd1b94f99cc9e8f93e5", "name": "reborn", "icon": "", "version": "1.0.9", "watchface": "true", "resources": [ { "type": "bmp", "name": "BMP_BG", "file": "bg.bmp" }, { "type": "bmp", "name": "BMP_0", "file": "0.bmp" }, { "type": "bmp", "name": "BMP_1", "file": "1.bmp" }, { "type": "bmp", "name": "BMP_2", "file": "2.bmp" }, { "type": "bmp", "name": "BMP_3", "file": "3.bmp" }, { "type": "bmp", "name": "BMP_4", "file": "4.bmp" }, { "type": "bmp", "name": "BMP_5", "file": "5.bmp" }, { "type": "bmp", "name": "BMP_6", "file": "6.bmp" }, { "type": "bmp", "name": "BMP_7", "file": "7.bmp" }, { "type": "bmp", "name": "BMP_8", "file": "8.bmp" }, { "type": "bmp", "name": "BMP_9", "file": "9.bmp" }, { "type": "bmp", "name": "BMP_COLON", "file": "COLON.bmp" } ] }

主程序xyz_reborn.c

/* * ===================================================================================== * WatchFaceName: xyz-reborn * Description: * Author: wisepragma * Created: August 4,2017 * HomePage:http://blog.csdn.net/wisepragma * ===================================================================================== */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "maibu_sdk.h" #include "maibu_res.h" int32_t app_window_stack_push(Window *window); int8_t maibu_get_battery_percent(int8_t *percent); Window * app_window_stack_get_window_by_id(int32_t id); void app_window_update(Window *window); static void fillGRect(GRect *grc,uint8_t x,uint8_t y,uint8_t h,uint8_t w) { grc->origin.x=x; grc->origin.y=y; grc->size.w=w; grc->size.h=h; } static const uint16_t N_MIN_HIDE_SEC=3; static const char ORGIN_X=0,ORGIN_Y=33;//大数字起始位置 static GSize WATCH_NUM_SIZE={0,0};//大数字的高与宽,从图片资源上获取 static uint32_t half_sec_cnt = 0; static struct date_time last_time; static struct TIME_NUM { uint8_t value; int8_t lyid; GRect rc; }T_num[4]; static P_Window p_win=NULL; //bugfixed: layer id equal 0,is legal,changed initial value 0 to -1 static int32_t win_id =-1; static int32_t timer_id =-1; static int8_t lyid_battery = -1; static int8_t lyid_engtime1 = -1; static int8_t lyid_engtime2 = -1; static int8_t lyid_weekday = -1; static int8_t lyid_mondayyear = -1; static int8_t lyid_sec = -1; static const uint16_t tnum_bmp[10] = {BMP_0, BMP_1, BMP_2, BMP_3, BMP_4, BMP_5, BMP_6, BMP_7, BMP_8, BMP_9}; static const char wday[7][10] ={ "Sunday","Monday","Tuesday","Wednesday","Thursday", "Friday", "Saturday" }; static const char month[12][10] ={"January","February","March","April","May","June","July","August","September","October","November","December"}; static const char s_num[][10] = { "twelve", "one","two","three","four","five","six","seven","eight","nine", "ten", "eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen", "twenty" }; static const char s_decade[][8] = { "","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety", }; static char *gen_min_str(uint8_t num,char *buf) { if(num<=20) sprintf(buf,"%s",s_num[num]); else { sprintf(buf,"%s",s_decade[num/10]); if((num)!=0) sprintf(buf,"%s-%s",s_decade[num/10],s_num[num]); else sprintf(buf,"%s",s_decade[num/10]); } return buf; } static char *gen_time_str(uint8_t hour,uint8_t min,char *recvbuf,char *recvbuf2)//recvbuf at least 32 { char min_str[32]; char *prefix,*stuffix,*past_to,*am_pm; if(hour>=24 || min>59 ) return 0; if(hour>=12) am_pm="p.m."; else am_pm="a.m."; if(min==0) { prefix=(char*)s_num[hour]; //变成12小时制 past_to="o'clock" ; // if(hour==-1) { stuffix=" a.m.";am_pm=",midnight";}//显示不了那么多字只好注释掉 // else if(hour==12) { stuffix="p.m.";am_pm=",noon";} // else stuffix=""; } else if(min==30){ prefix="half"; past_to="past" ;stuffix=(char*)s_num[hour];} else if(min==15){ prefix="a quarter"; past_to="past";stuffix=(char*)s_num[hour];} else if(min==45) { prefix="a quarter"; past_to="to";stuffix=(char*)s_num[(hour+1)];} else if(0<min && min<30) { prefix=gen_min_str(min,min_str); past_to="past"; stuffix=(char*)s_num[hour]; } else if(min>30) { prefix=gen_min_str(60-min,min_str); past_to="to"; stuffix=(char*)s_num[(hour+1)]; } sprintf(recvbuf,"%s ", prefix); sprintf(recvbuf2,"%s %s %s",past_to, stuffix,am_pm); recvbuf[0]-=('a'-'A');//首字母大写 return recvbuf; } static int8_t create_txt_layer(Window *pwin, char *txt,uint8_t font_type,int16_t x,int16_t y,uint8_t h,uint8_t w,enum GColor ecolor,enum GAlign align)//return layer id { GRect frame_hm; fillGRect( &frame_hm,x,y,h,w ); LayerText alt_hm = {txt, frame_hm, align, font_type, 0}; P_Layer layer = app_layer_create_text(&alt_hm); int8_t id=-1; if(layer != NULL) { app_layer_set_bg_color(layer, ecolor); id = app_window_add_layer(pwin, layer); } return id; } static int8_t create_bmp_layer(Window *pwin, uint32_t bmpID,int16_t x,int16_t y,uint8_t h,uint8_t w/*,enum GColor ecolor*/) { int8_t lyid=-1; GRect frame_bg; GBitmap bitmap_bg;//height,width res_get_user_bitmap(bmpID, &bitmap_bg); fillGRect( &frame_bg,x,y,h,w ); LayerBitmap lb_bg = {bitmap_bg, frame_bg, GAlignLeft}; P_Layer layer_bitmap_bg = app_layer_create_bitmap(&lb_bg); //app_layer_set_bg_color(layer_bitmap_bg, ecolor); if(layer_bitmap_bg != NULL) { lyid=app_window_add_layer(pwin, layer_bitmap_bg); } return lyid; } //==========English time ====================== static void update_english_layer(struct date_time *datetime) { char txt_buf[32],txt_buf2[32]; sprintf(txt_buf,"%s", gen_time_str(datetime->hour,datetime->min,txt_buf,txt_buf2)); if( lyid_engtime1==-1 || lyid_engtime2==-1) { lyid_engtime1= create_txt_layer(p_win, txt_buf,U_ASCII_ARIAL_16,0, 92, 16, 127,GColorBlack,GAlignTopLeft); lyid_engtime2= create_txt_layer(p_win, txt_buf2,U_ASCII_ARIAL_16,0, 110, 16, 127,GColorBlack,GAlignTopRight); } else { P_Layer p_layer= app_window_get_layer_by_id(p_win, lyid_engtime1); app_layer_set_text_text(p_layer, txt_buf); p_layer= app_window_get_layer_by_id(p_win, lyid_engtime2); app_layer_set_text_text(p_layer, txt_buf2); } } //================================ static void update_mondayyear_layer(struct date_time *datetime) { char txt_buf[40],*str_stuffix; //凡个位为1,2,3 除11,12,13区别对待 switch( datetime->mday )//取0~9数,0取0~99 { case 1: str_stuffix="st"; if(datetime->mday0==11) str_stuffix="th"; break; case 2: str_stuffix="nd"; if(datetime->mday0==12) str_stuffix="th"; break; case 3: str_stuffix="rd"; if(datetime->mday0==13) str_stuffix="th"; break; default: str_stuffix="th"; } sprintf(txt_buf,"%s %d%s,%d", month[datetime->mon-1], datetime->mday,str_stuffix,datetime->year); if( lyid_mondayyear ==-1) { lyid_mondayyear =create_txt_layer(p_win, txt_buf,U_ASCII_ARIAL_12,0, 0, 32, 127,GColorBlack,GAlignTopLeft); } else { P_Layer p_layer= app_window_get_layer_by_id(p_win, lyid_mondayyear); app_layer_set_text_text(p_layer, txt_buf); } } //=========hour min====================== static void update_hour_min_layer(struct date_time *datetime) { GBitmap bitmap; T_num[0].value= datetime->hour/10; T_num[1].value= datetime->hour; T_num[2].value= datetime->min/10; T_num[3].value= datetime->min; if(T_num[0].lyid==-1) { fillGRect( &T_num[0].rc, ORGIN_X, ORGIN_Y, WATCH_NUM_SIZE.h, WATCH_NUM_SIZE.w ); fillGRect( &T_num[1].rc, WATCH_NUM_SIZE.w, ORGIN_Y, WATCH_NUM_SIZE.h, WATCH_NUM_SIZE.w ); fillGRect( &T_num[2].rc, 16+2*WATCH_NUM_SIZE.w, ORGIN_Y, WATCH_NUM_SIZE.h, WATCH_NUM_SIZE.w ); fillGRect( &T_num[3].rc, 16+3*WATCH_NUM_SIZE.w, ORGIN_Y, WATCH_NUM_SIZE.h, WATCH_NUM_SIZE.w ); } for(int pos=0;pos<4;pos++) { if(T_num[pos].lyid==-1) { T_num[pos].lyid =create_bmp_layer( p_win, tnum_bmp[ T_num[pos].value], T_num[pos].rc.origin.x, T_num[pos].rc.origin.y,T_num[pos].rc.size.h, T_num[pos].rc.size.w ); } else { P_Layer p_layer = app_window_get_layer_by_id(p_win, T_num[pos].lyid); if (p_layer != NULL) { res_get_user_bitmap(tnum_bmp[ T_num[pos].value ], &bitmap); app_layer_set_bitmap_bitmap(p_layer, &bitmap); } } } } //=========weekday====================== static void update_wday_layer(struct date_time *datetime) { char txt_buf[32]; sprintf(txt_buf, "%s", wday[datetime->wday]); if(lyid_weekday==-1) { lyid_weekday = create_txt_layer(p_win, txt_buf,U_ASCII_ARIAL_16,0, 14, 32, 127,GColorBlack,GAlignTopLeft); } else { P_Layer p_layer= app_window_get_layer_by_id(p_win, lyid_weekday); app_layer_set_text_text(p_layer, txt_buf); } } //=========battery====================== static void update_battery_layer() { //电量 int8_t percent=0; char txt_buf[5]; maibu_get_battery_percent(&percent); sprintf(txt_buf, "%d%%", percent); if(lyid_battery==-1) { lyid_battery = create_txt_layer(p_win, txt_buf,U_ASCII_ARIAL_16, 127-41, 14, 32,41,GColorBlack,GAlignTopRight); } else { P_Layer p_layer= app_window_get_layer_by_id(p_win, lyid_battery); app_layer_set_text_text(p_layer, txt_buf); } } //========second======================== static void update_second_layer(uint8_t second) { char txt_buf[5]; if(half_sec_cnt!=0) sprintf(txt_buf, "d", second);//date_time_t是date_time的指针 else txt_buf[0]='\0'; if(lyid_sec==-1) { lyid_sec=create_txt_layer(p_win, txt_buf,U_ASCII_ARIAL_14, 2*WATCH_NUM_SIZE.w+1, ORGIN_Y+22, 30, 30,GColorWhite,GAlignTopLeft); } else { P_Layer p_layer= app_window_get_layer_by_id(p_win, lyid_sec); if (p_layer == NULL) return; app_layer_set_text_text(p_layer, txt_buf); } } //================================ static void sec_callback(date_time_t tick_time, uint32_t millis,void *context) { half_sec_cnt++; //500ms刷新一次,避免秒慢于分钟更新 if(half_sec_cnt>=N_MIN_HIDE_SEC*60*2)//几钟后停止显示秒 { app_service_timer_unsubscribe(timer_id); half_sec_cnt=0; } P_Window p_win =app_window_stack_get_window_by_id(win_id);//(P_Window)context; if (p_win == NULL) return; update_second_layer( tick_time->sec ); app_window_update(p_win); } static void on_back_key() { P_Window p_win = app_window_stack_get_window_by_id(win_id); if(p_win != NULL) { if(half_sec_cnt==0) { timer_id=app_window_timer_subscribe(p_win, 500, sec_callback, 0); }          else          {                app_service_timer_unsubscribe(timer_id);                half_sec_cnt=0;                                        struct date_time datetime;                app_service_get_datetime(&datetime);                update_second_layer( datetime.sec );                app_window_update(p_win);          } } } static void time_change_callback(enum SysEventType type, void *context) { if (type == SysEventTypeTimeChange) { P_Window p_win =(P_Window)app_window_stack_get_window_by_id(win_id); if (p_win == NULL) return; struct date_time datetime; app_service_get_datetime(&datetime); //时分 update_hour_min_layer( &datetime ); //English Time update_english_layer(&datetime); //电量 update_battery_layer(); if(datetime.year !=last_time.year || datetime.mon!=last_time.mon || datetime.mday!=last_time.mday) { //星期几 update_wday_layer( &datetime ); //月,日年 update_mondayyear_layer( &datetime ); last_time.year = datetime.year; last_time.mon = datetime.mon; last_time.mday = datetime.mday; } app_window_update(p_win); } } //---------------main----------------------------------------------------------------------- int main() { #ifdef USE_SIMULATOR simulator_init(); #endif //....................切换表盘时,资源已销毁,要重新创建layer,否则将不能正常显示............................................................. win_id =-1; half_sec_cnt =0;//bugfixed -1 timer_id =-1; lyid_battery =-1; lyid_engtime1 =-1; lyid_engtime2 =-1; lyid_weekday =-1; lyid_mondayyear =-1; lyid_sec =-1; memset(T_num,-1,sizeof(T_num)); //......................................................................................................................... p_win = app_window_create(); if (p_win == NULL) return 0; struct date_time datetime; app_service_get_datetime(&datetime); GBitmap bitmap; res_get_user_bitmap(*tnum_bmp, &bitmap);//BMP_ID中取得宽高信息 WATCH_NUM_SIZE.h=bitmap.height; WATCH_NUM_SIZE.w=bitmap.width; //背景.放最前面-once res_get_user_bitmap(BMP_BG,&bitmap); create_bmp_layer( p_win, BMP_BG,0, 0, bitmap.height, bitmap.width ); //冒号-once res_get_user_bitmap(BMP_COLON,&bitmap); GRect rc; fillGRect( &rc, 2*WATCH_NUM_SIZE.w, ORGIN_Y, bitmap.height, bitmap.width ); create_bmp_layer( p_win, BMP_COLON, rc.origin.x, rc.origin.y,rc.size.h,rc.size.w ); //秒 update_second_layer( datetime.sec ); //时,分 update_hour_min_layer( &datetime ); //月,日年 update_mondayyear_layer(&datetime); //星期几 update_wday_layer( &datetime ); //电量 update_battery_layer(); //English time update_english_layer( &datetime); //线-once Geometry *p_geo[1]; uint8_t num = 0; LayerGeometry layer_geometry; memset(p_geo, 0, sizeof(p_geo)); Line line[] = { {{0,13},{127,13}}, {{0,31},{127,31}}, {{0,32},{127,32}}, {{0,90},{127,90}}, {{0,91},{127,91}} }; LineSet ls = {sizeof(line)/sizeof(*line), line}; Geometry alg = {GeometryTypeLineSet, FillOutline, GColorWhite, (void*)&ls}; p_geo[num++] = &alg; layer_geometry.num = num; layer_geometry.p_g = p_geo; P_Layer layer = app_layer_create_geometry(&layer_geometry); app_window_add_layer(p_win, layer); //显示秒定时器 timer_id=app_window_timer_subscribe(p_win, 500, sec_callback, 0); maibu_service_sys_event_subscribe(time_change_callback); app_window_click_subscribe(p_win, ButtonIdBack, on_back_key); //ButtonIdDown ButtonIdUp ButtonIdBack,ButtonIdSelect app_window_update(p_win); if (p_win != NULL) win_id= app_window_stack_push(p_win); //................................................................................. #ifdef USE_SIMULATOR simulator_wait(); #endif return 0; }

// 有两种情况会产生一个implicit declaration of function 的警告 // 1 没有把函数所在的c文件生成.o目标文件 // 2 在函数所在的c文件中定义了,但是没有在与之相关联的.h文件中声明

第四步.编译生成,模拟效果图

重编译表盘版本,将生成OUT.MAI文件,

改名成OUT.MP3,通过蓝牙传到手机上,再改名回OUT. MAI,

用麦步手机APP打开此文件,点击依旧安装,片刻即可安装成功

备注:

表盘第一行显示英文 月份日期,年份

第二行显示英文星期几,电量

中间高对比度显示24小时制时间

第三第四行显示英文时间

表盘切换或按后退键可以显示3分钟的秒,3分钟后,或者再按后退键自动消失,省电

表盘MAI文件下载:http://pan.baidu.com/s/1jHPny0e

转载请注明原文地址: https://www.6miu.com/read-46147.html

最新回复(0)