给麦步手表写一个获取比特币行情的表盘

我对手表有着深厚的感情,每当人生遇到坎坷时,或者愤怒不已的时候,我都会想象和安慰自己“我去年买了块表”。刚有taobao的时候,我买了一块卡西欧的太阳能手表,时至今日我还记得价格是 258元。十多年过去了,这块表的卖家已经消失,我从来没有给他更换过电池,这块手表依然行走完好。
image001

古人云“穷玩车,富玩表”。为了体验一下富人的感觉,最近入手了一块麦步智能手表。对于这块手表,最重要的是可以写程序。于是我就尝试给他编写程序,听上去又在重复“屌丝玩电脑”。

image002

首先通读API,了解这个手表的原理。简单的说,这块手表通过蓝牙连接,从而实现WIFI通讯。
image003

目标是编写一个获取当前比特币行情。huobi 网提供了行情API, http://api.huobi.com/staticmarket/ticker_btc_json.js 可以显示实时行情。例如:一次返回数据如下

{“time”:”1467817886″,”ticker”:{“open”:4479,”vol”:604962.2546,”symbol”:”btccny”,”last”:4522.79,”buy”:4522.79,”sell”:4523.03,”high”:4612,”low”:4467.64} }。 其中的 last 就是当前的价格。

配合麦步手表提供的显示股票行情的代码,编写自己的程序如下:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

#include "maibu_sdk.h"

#include "maibu_res.h"

 

 

/*Web通讯ID*/

static uint32_t g_comm_id_web = 0;

 

/*Web request地址*/

#define DATA_WEB     "http://api.huobi.com/staticmarket/ticker_btc_json.js"

 

/* 时间项 */

#define DATE_TEXT_POS_X                      2

#define DATE_TEXT_POS_Y                      6

#define DATE_TEXT_SIZE_W                     70

#define DATE_TEXT_SIZE_H                     14

 

#define TIME_TEXT_POS_X                      90

#define TIME_TEXT_POS_Y                      6

#define TIME_TEXT_SIZE_W                     36

#define TIME_TEXT_SIZE_H                     14

 

static const char weekday[7][11] =

{

    {"周日"},

    {"周一"},

    {"周二"},

    {"周三"},

    {"周四"},

    {"周五"},

    {"周六"}

};

 

 

/*窗口ID*/

static int32_t g_window_id = -1;

 

//数据提示

static int32_t g_layer_id_text = -1;

//数据内容

static int32_t g_layer_id_data = -1;

 

//时间的句柄

static int32_t g_layer_id_time   = -1;

//日期的句柄

static int32_t g_layer_id_date   = -1;

 

//整个窗体句柄

static P_Window h_window;

 

void data_request_web()

{

     /*拼接url请求地址, 注意url的缓存大小*/

     char url[200] = "";   

     sprintf(url, "%s", DATA_WEB);              

 

     /*

               拼接过滤参数,即只接受和过滤参数匹配的返回值

               个人感觉这里的过滤可能是让手机做的,就是这里通知手机:json中的数据除了我制定的其他都过滤掉

     */

 

     /*发送一次*/

     g_comm_id_web = maibu_comm_request_web(url, "last", 0);

}

 

void add_text_layer(P_Window p_window, int32_t *p_layer_id, char *p_str, GRect *p_frame, enum GAlign align, int8_t font, enum GColor color)

{

    LayerText text_cfg = {p_str, *p_frame, align, font, 0};

    P_Layer layer = app_layer_create_text(&text_cfg);

    app_layer_set_bg_color(layer, color);

 

    P_Layer old_layer = app_window_get_layer_by_id(p_window, *p_layer_id);

    if(old_layer)

    {

        *p_layer_id = app_window_replace_layer(p_window, old_layer, layer);

    }

    else

    {

        *p_layer_id = app_window_add_layer(p_window, layer);

    }

}

 

static void add_time_bar(P_Window p_window)

{

    /* 添加时间图层 */

    uint8_t text_buf[40];

    struct date_time t;

    app_service_get_datetime(&t);

 

    memset(text_buf, 0, sizeof(text_buf));

    sprintf((char *)text_buf, "%s", (char *)&weekday[t.wday][0]);

    sprintf(&text_buf[6], "%02d-%02d", t.mon, t.mday);

 

    GRect frame;

    frame.origin.x = DATE_TEXT_POS_X;

    frame.origin.y = DATE_TEXT_POS_Y;

    frame.size.h   = DATE_TEXT_SIZE_H;

    frame.size.w   = DATE_TEXT_SIZE_W;

 

    add_text_layer(p_window, &g_layer_id_date, (char*)text_buf, &frame, GAlignLeft, U_ASCII_ARIAL_14, GColorWhite);

 

    frame.origin.x = TIME_TEXT_POS_X;

    frame.origin.y = TIME_TEXT_POS_Y;

    frame.size.h   = TIME_TEXT_SIZE_H;

    frame.size.w   = TIME_TEXT_SIZE_W;

 

    memset(text_buf, 0, sizeof(text_buf));

    sprintf(text_buf, "%02d:%02d", t.hour, t.min);

 

    add_text_layer(p_window, &g_layer_id_time, (char*)text_buf, &frame, GAlignLeft, U_ASCII_ARIAL_14, GColorWhite);

}

 

P_Window init_btc_window()

{

     static P_Window p_window;

    

     p_window = app_window_create();

     if (NULL == p_window)

     {

               return NULL;

     }

 

    /* 添加表盘背景 */

    GRect frame = {{0, 0}, {128, 128}};

    GBitmap bitmap;

 

    res_get_user_bitmap(BMP_STOCK_BG, &bitmap);

    LayerBitmap layer_bitmap = {bitmap, frame, GAlignCenter};

    P_Layer layer = app_layer_create_bitmap(&layer_bitmap);

    app_window_add_layer(p_window, layer);

 

    /* 添加时间栏 */

    add_time_bar(p_window);

 

     /*加入你的代码 begin*/     

 

     /*添加数据提示信息*/

     GRect frame_main = {{0, 30}, {16, 128}};

    add_text_layer(p_window, &g_layer_id_text, "BTC", &frame_main, GAlignCenter, U_ASCII_ARIAL_14, GColorWhite);

    

     /*添加数据*/

     GRect frame_data = {{0, 60}, {16, 128}};

    add_text_layer(p_window, &g_layer_id_data, "waiting", &frame_data, GAlignCenter, U_ASCII_ARIAL_14, GColorWhite);

    

     return p_window;

 

}

 

void data_comm_result_callback(enum ECommResult result, uint32_t comm_id, void *context)

{

 

     /*如果上一次请求WEB通讯失败,并且通讯ID相同,则重新发送*/

     if ((result == ECommResultFail) && (comm_id == g_comm_id_web))

     {

               data_request_web();

     }

    

}

 

static void web_recv_callback(const uint8_t *buff, uint16_t size)

{

    char stock_gid[10];

     char i;

 

    maibu_get_json_str(buff, "last", stock_gid, 10);

 

     for (i=0;i<10;i++)

     {

     if (stock_gid[i]=='}')

               {

                         stock_gid[i]=0;

               }

     }

 

     /*添加数据*/

     GRect frame_data = {{0, 60}, {16, 128}};

    add_text_layer(h_window, &g_layer_id_data, stock_gid, &frame_data, GAlignCenter, U_ASCII_ARIAL_14, GColorWhite);

    

     app_window_update(h_window);

}

 

static void watch_time_change_callback(enum SysEventType type, void *context)

{

    /*时间更改,分变化*/

    if (type == SysEventTypeTimeChange)

    {

        uint8_t text_buf[40];

        struct date_time t;

        app_service_get_datetime(&t);

 

        memset(text_buf, 0, sizeof(text_buf));

        sprintf((char *)text_buf, "%s", (char *)&weekday[t.wday][0]);

        sprintf(&text_buf[6], "%02d-%02d", t.mon, t.mday);

 

        GRect frame;

        frame.origin.x = DATE_TEXT_POS_X;

        frame.origin.y = DATE_TEXT_POS_Y;

        frame.size.h   = DATE_TEXT_SIZE_H;

        frame.size.w   = DATE_TEXT_SIZE_W;

 

        add_text_layer(h_window, &g_layer_id_date, (char*)text_buf, &frame, GAlignLeft, U_ASCII_ARIAL_14, GColorWhite);

 

        frame.origin.x = TIME_TEXT_POS_X;

        frame.origin.y = TIME_TEXT_POS_Y;

        frame.size.h   = TIME_TEXT_SIZE_H;

        frame.size.w   = TIME_TEXT_SIZE_W;

 

        memset(text_buf, 0, sizeof(text_buf));

        sprintf(text_buf, "%02d:%02d", t.hour, t.min);

 

        add_text_layer(h_window, &g_layer_id_time, (char*)text_buf, &frame, GAlignLeft, U_ASCII_ARIAL_14, GColorWhite);

 

        app_window_update(h_window);

    }

}

 

static void data_timer_callback(date_time_t tick_time, uint32_t millis, void *context)

{

    data_request_web();

}

 

int main()

{

 

     /*创建消息列表窗口*/

     h_window = init_btc_window();

 

     //订阅时间改变事件

    maibu_service_sys_event_subscribe(watch_time_change_callback);

    

     /*放入窗口栈显示*/

     g_window_id = app_window_stack_push(h_window);

 

     data_request_web();

 

     /*注册通讯结果回调*/

     maibu_comm_register_result_callback(data_comm_result_callback);

 

     //注册网络请求回调函数

    maibu_comm_register_web_callback(web_recv_callback);

 

    //聚合数据源每隔10s更新数据

    app_window_timer_subscribe(h_window, 10000, data_timer_callback, (void *)h_window);

    

     return 0;

}

 

编译之后上传到手表上就OK了。

看起来工作正常,美中不足就是屏幕有点小,如果能像美国队长那块一样大就完美了。

image004

这块手表的一大重要特性就是采用电纸屏幕,就是那种 Kindle 的屏幕材质,不改变内容无需耗电,这样待机可以很长时间(标称21天)。说道这里,我想起来一个很老的苏联笑话:

有一个人在机场等六点的飞机,可是他忘记了带手表,于是他想找

个人问问。这时,他看见一个人提着两个巨大的手提箱吃力的走过来,手腕上戴

着一块异常漂亮的一看就知道是高科技产品的手表。

  “请问,几点了?”他问道。

  “哪个国家的时间?”那人反问。

  “哦?”他的好奇心来了,“你都知道哪些国家的时间呢?”

  “所有的国家,”那人回答道。

  “哇!那可真是一块好手表呀!”

  “还不止这些呢,这块表还有GPS卫星系统,可以随时收发电子邮件、

传真,这个彩色的屏幕可以收看NTSC制式的电视节目!”那人给他

演示,果真如此!

“哦!太棒了,我真想拥有一块这样的手表,您……您可以把它卖给我吗?”

“说实话,我已经烦透了这块表了,这样吧,900美元,如何?”

  他马上掏出支票簿,写了900美元给那人,“成交!”

 “好的,现在,它是你的了。”那人如释重负,把手表交给他,“这个是你

的手表”,然后指着地上的两个大箱子说,“这两个是电池!”

无数的科学家和工程师在不断的努力改造着我们的生活。

发表评论

电子邮件地址不会被公开。 必填项已用*标注