前阵子跟Arduino中文社区联合做了一个运营活动,是征集用麦步手表跟开源类硬件去结合做一些有意思的项目,募集到了一批大神,贡献了很多创意。
arduino.cn的 @Zoologist 拿到手表后先写了一个比特币行情的表盘来练手,以下是他的分享
我对手表有着深厚的感情,每当人生遇到坎坷时,或者愤怒不已的时候,我都会想象和安慰自己“我去年买了块表”。刚有taobao的时候,我买了一块卡西欧的太阳能手表,时至今日我还记得价格是 258元。十多年过去了,这块表的卖家已经消失,我从来没有给他更换过电池,这块手表依然行走完好。
古人云“穷玩车,富玩表”。为了体验一下富人的感觉,最近入手了一块麦步智能手表。对于这块手表,最重要的是可以写程序。于是我就尝试给他编写程序,听上去又在重复“屌丝玩电脑”。
首先通读API,了解这个手表的原理。简单的说,这块手表通过蓝牙连接,从而实现WIFI通讯。
因此,手机上也需要一直运行一个程序才能保持连接
目标是编写一个获取当前比特币行情。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;
- }
复制代码
编译之后上传到手表,可以在表面看到当前的价格(因为比特币波动非常快,所以会有一点点差别)
看起来工作正常,美中不足就是屏幕有点小,如果能像美国队长那块一样大就完美了。
这块手表的一大重要特性就是采用电纸屏幕,就是那种 Kindle 的屏幕材质,不改变内容无需耗电,这样待机可以很长时间(标称21天)。说道这里,我想起来一个很老的苏联笑话: 有一个人在机场等六点的飞机,可是他忘记了带手表,于是他想找 个人问问。这时,他看见一个人提着两个巨大的手提箱吃力的走过来,手腕上戴 着一块异常漂亮的一看就知道是高科技产品的手表。 “请问,几点了?”他问道。 “哪个国家的时间?”那人反问。 “哦?”他的好奇心来了,“你都知道哪些国家的时间呢?” “所有的国家,”那人回答道。 “哇!那可真是一块好手表呀!” “还不止这些呢,这块表还有GPS卫星系统,可以随时收发电子邮件、 传真,这个彩色的屏幕可以收看NTSC制式的电视节目!”那人给他 演示,果真如此! “哦!太棒了,我真想拥有一块这样的手表,您……您可以把它卖给我吗?” “说实话,我已经烦透了这块表了,这样吧,900美元,如何?” 他马上掏出支票簿,写了900美元给那人,“成交!” “好的,现在,它是你的了。”那人如释重负,把手表交给他,“这个是你 的手表”,然后指着地上的两个大箱子说,“这两个是电池!” 无数的科学家和工程师在不断的努力改造着我们的生活,让很多在过去看起来无法实现的事情变成现实,这是非常令人振奋和激动人心的。 特别感谢 龍坤楊 麦步手表开箱与精简Web request Demo 一文的帮助
比特币行情表盘在此:
本帖原文链接请见Arduino中文社区:链接在此 |