diff --git a/Keil_5/ble_app_peripheral.uvprojx b/Keil_5/ble_app_peripheral.uvprojx index 08f4490..917ae15 100644 --- a/Keil_5/ble_app_peripheral.uvprojx +++ b/Keil_5/ble_app_peripheral.uvprojx @@ -16,8 +16,8 @@ ARMCM0 ARM - ARM.CMSIS.5.6.0 - http://www.keil.com/pack/ + ARM.Cortex_DFP.1.1.0 + https://www.keil.com/pack/ IROM(0x0,0x0) IRAM(0x0,0x0) CPUTYPE("Cortex-M0") CLOCK(12000000) ESEL ELITTLE @@ -185,6 +185,8 @@ 0 0 0 + 0 + 0 0 0 0 @@ -351,7 +353,7 @@ 0 0 0 - 0 + 4 @@ -481,7 +483,7 @@ 2 2 2 - 2 + 0 @@ -580,7 +582,7 @@ 2 2 2 - 2 + 0 @@ -1319,7 +1321,7 @@ 2 2 2 - 2 + 0 @@ -1403,7 +1405,7 @@ 2 2 2 - 2 + 0 @@ -1548,8 +1550,8 @@ ARMCM0 ARM - ARM.CMSIS.5.6.0 - http://www.keil.com/pack/ + ARM.Cortex_DFP.1.1.0 + https://www.keil.com/pack/ IROM(0x0,0x0) IRAM(0x0,0x0) CPUTYPE("Cortex-M0") CLOCK(12000000) ESEL ELITTLE @@ -1717,6 +1719,8 @@ 0 0 0 + 0 + 0 0 0 0 @@ -1883,7 +1887,7 @@ 0 0 0 - 0 + 4 @@ -2013,7 +2017,7 @@ 2 2 2 - 2 + 0 @@ -2112,7 +2116,7 @@ 2 2 2 - 2 + 0 @@ -2851,7 +2855,7 @@ 2 2 2 - 2 + 0 @@ -2935,7 +2939,7 @@ 2 2 2 - 2 + 0 @@ -3080,8 +3084,8 @@ ARMCM0P ARM - ARM.CMSIS.5.6.0 - http://www.keil.com/pack/ + ARM.Cortex_DFP.1.1.0 + https://www.keil.com/pack/ IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ESEL ELITTLE @@ -3249,6 +3253,8 @@ 0 0 0 + 0 + 0 0 0 8 @@ -3415,7 +3421,7 @@ 0 0 0 - 0 + 4 @@ -3535,7 +3541,7 @@ 2 2 2 - 2 + 0 @@ -3644,7 +3650,7 @@ 2 2 2 - 2 + 0 @@ -4317,7 +4323,7 @@ 2 2 2 - 2 + 0 @@ -4416,7 +4422,7 @@ 2 2 2 - 2 + 0 @@ -4561,8 +4567,8 @@ ARMCM0P ARM - ARM.CMSIS.5.6.0 - http://www.keil.com/pack/ + ARM.Cortex_DFP.1.1.0 + https://www.keil.com/pack/ IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ESEL ELITTLE @@ -4730,6 +4736,8 @@ 0 0 0 + 0 + 0 0 0 8 @@ -4896,7 +4904,7 @@ 0 0 0 - 0 + 4 @@ -5016,7 +5024,7 @@ 2 2 2 - 2 + 0 @@ -5125,7 +5133,7 @@ 2 2 2 - 2 + 0 @@ -5798,7 +5806,7 @@ 2 2 2 - 2 + 0 @@ -5897,7 +5905,7 @@ 2 2 2 - 2 + 0 @@ -6042,8 +6050,8 @@ ARMCM0P ARM - ARM.CMSIS.5.6.0 - http://www.keil.com/pack/ + ARM.Cortex_DFP.1.1.0 + https://www.keil.com/pack/ IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ESEL ELITTLE @@ -6211,6 +6219,8 @@ 0 0 0 + 0 + 0 0 0 8 @@ -6377,7 +6387,7 @@ 0 0 0 - 0 + 4 @@ -6497,7 +6507,7 @@ 2 2 2 - 2 + 0 @@ -6596,7 +6606,7 @@ 2 2 2 - 2 + 0 @@ -7279,7 +7289,7 @@ 2 2 2 - 2 + 0 @@ -7363,7 +7373,7 @@ 2 2 2 - 2 + 0 diff --git a/src/epd/PC2U2_sfont.py b/src/epd/PC2U2_sfont.py new file mode 100644 index 0000000..e759730 --- /dev/null +++ b/src/epd/PC2U2_sfont.py @@ -0,0 +1,97 @@ +import re +import struct + +# 读取 font.txt 中的全部内容 +with open("font.txt", "r", encoding="gbk", errors="ignore") as f: + lines = f.readlines() + +# 用于存储字体数据 +font_chars = [] + +# 临时缓存 bitmap 和字符信息 +current_bitmap = [] +current_char = "" +width = height = 0 + +# 正则匹配 +bitmap_line_re = re.compile(r'\{([0-9xA-Fa-f, ]+)\}') +char_comment_re = re.compile(r'/\*\s*"(.+?)",\s*(\d+)\s*\*/') +size_comment_re = re.compile(r'/\*\s*\(\s*(\d+)\s*X\s*(\d+)\s*,.*\*/') + +for line in lines: + # 如果是bitmap行 + bitmap_match = bitmap_line_re.search(line) + if bitmap_match: + hex_str = bitmap_match.group(1) + bytes_list = [int(x, 16) for x in hex_str.split(',')] + current_bitmap.extend(bytes_list) + + # 如果是字符注释行 + char_match = char_comment_re.search(line) + if char_match: + current_char = char_match.group(1) + + # 如果是尺寸注释行 + size_match = size_comment_re.search(line) + if size_match: + width = int(size_match.group(1)) + height = int(size_match.group(2)) + + # 生成 FontChar 结构 + ucs = ord(current_char) + ft_adv = width + ft_bw = width + ft_bh = height + ft_bx = 0 + ft_by = 0 + + header = [ft_adv, ft_bw, ft_bh, ft_bx, ft_by] + + font_chars.append({ + "char": current_char, + "ucs": ucs, + "header": header, + "bitmap": current_bitmap.copy() + }) + + # 清空临时变量 + current_bitmap.clear() + current_char = "" + width = height = 0 + +# 构造 sfont[] 数据 +font_count = len(font_chars) +offset = 2 + font_count * 4 # 2 字节总数 + 每个字符 4 字节索引 +index_entries = [] +data_blocks = [] + +for fc in font_chars: + # UCS + 偏移 + index_entries.append(struct.pack('>7; + // 校准ADC偏移,使用单端输入模式 + adc_offset_calibrate(ADC_INPUT_MODE_SINGLE_ENDED); + // 获取电池电压采样值 + adcval = adc_get_vbat_sample(false); + // 将ADC值转换为实际电压值 (单位: mV) + int volt = (adcval*225)>>7; - struct custs1_val_set_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_SET_REQ, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_set_req, DEF_SVC1_ADC_VAL_1_CHAR_LEN); - req->conidx = app_env->conidx; - req->handle = SVC1_IDX_ADC_VAL_1_VAL; - req->length = DEF_SVC1_ADC_VAL_1_CHAR_LEN; - req->value[0] = volt&0xff; - req->value[1] = volt>>8; - KE_MSG_SEND(req); - - return volt; + // 分配内存并构造BLE消息 + struct custs1_val_set_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_SET_REQ, + prf_get_task_from_id(TASK_ID_CUSTS1), + TASK_APP, + custs1_val_set_req, + DEF_SVC1_ADC_VAL_1_CHAR_LEN); + // 设置连接索引 + req->conidx = app_env->conidx; + // 设置特征值句柄 + req->handle = SVC1_IDX_ADC_VAL_1_VAL; + // 设置数据长度 + req->length = DEF_SVC1_ADC_VAL_1_CHAR_LEN; + // 设置电压值(16位,低字节在前) + req->value[0] = volt&0xff; + req->value[1] = volt>>8; + // 发送BLE消息 + KE_MSG_SEND(req); + + return volt; } /****************************************************************************************/ +/** + * 农历年份数据表(2020-2051年) + * 每个16位数据包含以下信息: + * - 高4位(bit 15-12): 闰月月份,0表示当年无闰月 + * - 低12位(bit 11-0): 每个月的大小月标记,1表示大月(30天),0表示小月(29天) + * 例如:0x07954 + * - 0: 无闰月 + * - 7954: 从正月到十二月的大小月情况 + */ static const uint16_t lunar_year_info[32] = { - 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029 - 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x0d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039 - 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x0b255, 0x06d20, 0x0ada0, //2040-2049 - 0x04b63, 0x09370, //2050-2051 + 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029 + 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x0d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039 + 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x0b255, 0x06d20, 0x0ada0, //2040-2049 + 0x04b63, 0x09370, //2050-2051 }; + +// 额外的农历年份信息,用于标记特殊年份的闰月情况 static const uint32_t lunar_year_info2 = 0x48010000; -// 每个节气相对于"小寒"的秒数 +/** + * 24节气时间数据表 + * 存储了一年中24个节气相对于"小寒"的时间间隔(以秒为单位) + * + * 节气顺序: + * 1-6月:小寒、大寒、立春、雨水、惊蛰、春分 + * 7-12月:清明、谷雨、立夏、小满、芒种、夏至 + * 13-18月:小暑、大暑、立秋、处暑、白露、秋分 + * 19-24月:寒露、霜降、立冬、小雪、大雪、冬至 + */ static int jieqi_info[] = { - 0, 1272283, 2547462, 3828568, 5117483, 6416376, - 7726093, 9047327, 10379235, 11721860, 13072410, 14428379, - 15787551, 17145937, 18501082, 19850188, 21190911, 22520708, - 23839844, 25146961, 26443845, 27730671, 29010666, 30284551, + 0, 1272283, 2547462, 3828568, 5117483, 6416376, // 小寒到春分 + 7726093, 9047327, 10379235, 11721860, 13072410, 14428379, // 清明到夏至 + 15787551, 17145937, 18501082, 19850188, 21190911, 22520708, // 小暑到秋分 + 23839844, 25146961, 26443845, 27730671, 29010666, 30284551, // 寒露到冬至 }; -// 已知2020年"小寒"相对于1月1日的秒数 +/** + * 2020年"小寒"节气的基准时间 + * 相对于2020年1月1日的秒数 + * 用于计算其他年份的节气时间 + */ #define xiaohan_2020 451804 +/** + * 全局时间变量定义 + * 公历日期相关变量: + * year: 年份,如2025 + * month: 月份,0-11表示1-12月 + * date: 日期,0-30表示1-31日 + * wday: 星期,0-6表示星期日到星期六 + * + * 农历日期相关变量: + * l_year: 农历年在lunar_year_info数组中的索引,如4表示2024年 + * l_month: 农历月份,0-11表示正月到腊月,最高位1表示闰月 + * l_date: 农历日期,0-29表示初一到三十 + * + * 时间相关变量: + * hour: 小时,0-23 + * minute: 分钟,0-59 + * second: 秒,0-59 + */ int year=2025, month=0, date=0, wday=3; int l_year=4, l_month=11, l_date=1; int hour=0, minute=0, second=0; +/** + * 获取农历月份的天数 + * + * @param mon 月份编号,最高位为1表示闰月 + * @param yinfo_out 输出参数,用于返回年份信息 + * @return 返回该月的天数(29或30) + */ static int get_lunar_mdays(int mon, int *yinfo_out) { - int lflag = mon&0x80; - mon &= 0x7f; + // 获取闰月标志(最高位) + int lflag = mon&0x80; + // 获取实际月份(去除闰月标志) + mon &= 0x7f; // 取得当年的信息 int yinfo = lunar_year_info[l_year]; @@ -327,44 +409,71 @@ static int epd_wait_state; static timer_hnd epd_wait_hnd; typedef struct { - char *name; - uint8_t mon; - uint8_t day; + char *name; + uint8_t mon; + uint8_t day; }HOLIDAY_INFO; HOLIDAY_INFO hday_info[] = { - {"除夕", 0xc0|12, 30}, - {"春节", 0x80| 1, 1}, - {"元宵节", 0x80| 1, 15}, - {"龙抬头", 0x80| 2, 2}, - {"端午节", 0x80| 5, 5}, - {"七夕节", 0x80| 7, 7}, - {"中秋节", 0x80| 8, 15}, - {"重阳节", 0x80| 9, 9}, - {"腊八节", 0x80|12, 8}, + // 农历传统节日(0x80 表示农历日期,0xc0 表示月末) + {"腊八", 0x80|12, 8}, // 农历腊月初八 + {"小年", 0x80|12, 23}, // 农历腊月廿三 + {"除夕", 0xc0|12, 30}, // 农历腊月最后一天 + {"春节", 0x80| 1, 1}, // 农历正月初一 + {"元宵节", 0x80| 1, 15}, // 农历正月十五 + {"龙抬头", 0x80| 2, 2}, // 农历二月初二 + {"寒食节", 0x80| 3, 3}, // 农历三月初三 + {"端午节", 0x80| 5, 5}, // 农历五月初五 + {"七夕节", 0x80| 7, 7}, // 农历七月初七 + {"中元节", 0x80| 7, 15}, // 农历七月十五 + {"中秋节", 0x80| 8, 15}, // 农历八月十五 + {"重阳节", 0x80| 9, 9}, // 农历九月初九 + {"下元节", 0x80|10, 15}, // 农历十月十五 - {"元旦节", 1, 1}, - {"情人节", 2, 14}, - {"妇女节", 3, 8}, - {"植树节", 3, 12}, - {"愚人节", 4, 1}, - {"劳动节", 5, 1}, - {"青年节", 5, 4}, - {"母亲节", 5, 0x97}, // 5月第二个周日 - {"儿童节", 6, 1}, - {"父亲节", 6, 0xa7}, // 6月第三个周日 - {"教师节", 9, 10}, - {"国庆节", 10, 1}, - {"程序员节", 10, 24}, - {"万圣节", 11, 1}, - {"光棍节", 11, 11}, - {"平安夜", 12, 24}, + // 阳历法定节假日和纪念日 + {"元旦", 1, 1}, + {"湿地日", 2, 2}, + {"情人节", 2, 14}, + {"妇女节", 3, 8}, + {"植树节", 3, 12}, + {"权益日", 3, 15}, + {"愚人节", 4, 1}, + {"读书日", 4, 23}, + {"阅读日", 4, 23}, + {"航天日", 4, 24}, + {"劳动节", 5, 1}, + {"青年节", 5, 4}, + {"护士节", 5, 12}, + {"儿童节", 6, 1}, + {"环境日", 6, 5}, + {"遗产日", 6, 8}, + {"建党节", 7, 1}, + {"建军节", 8, 1}, + {"抗战日", 9, 3}, + {"教师节", 9, 10}, + {"安全日", 9, 15}, + {"烈士日", 9, 30}, + {"国庆节", 10, 1}, + {"万圣节", 10, 31}, + {"消防日", 11, 9}, + {"记者节", 11, 8}, + {"宪法日", 12, 4}, + {"志愿日", 12, 5}, + {"公祭日", 12, 13}, {"圣诞节", 12, 25}, - {"", 0, 0}, + + + // 特殊周期性节日 + {"母亲节", 5, 0x97}, // 5月第二个周日 + {"父亲节", 6, 0xa7}, // 6月第三个周日 + {"感恩节", 11, 0xa4}, // 11月第四个周四 + + {"", 0, 0} // 结束标记 }; + static char *jieqi_str = "小寒"; -static char *holiday_str = "元旦节"; +static char *holiday_str = "元旦"; static void ldate_str(char *buf) { @@ -470,49 +579,113 @@ static uint8_t batt_cal(uint16_t adc_sample) return batt_lvl; } +/** + * 绘制电池电量图标 + * + * @param x 图标左上角的x坐标 + * @param y 图标中心的y坐标 + * + * 图标说明: + * - 外框大小:16x8像素 + * - 电量显示:根据实际电量百分比填充内部 + * - 电池正极:2x2像素 + */ static void draw_batt(int x, int y) { - int p = batt_cal(adcval); - p /= 10; + // 获取电池电量百分比并转换为显示段数(0-10) + int p = batt_cal(adcval); + p /= 10; - draw_rect(x, y-4, x+14, y+4, BLACK); - draw_box(x-2, y-1, x-1, y+1, BLACK); + // 绘制电池外框 + draw_rect(x, y-4, x+14, y+4, BLACK); + // 绘制电池正极 + draw_box(x-2, y-1, x-1, y+1, BLACK); - draw_box(x+12-p, y-2, x+12, y+2, BLACK); + // 绘制电量填充部分 + draw_box(x+12-p, y-2, x+12, y+2, BLACK); } +/** + * 绘制蓝牙图标 + * + * @param x 图标中心的x坐标 + * @param y 图标中心的y坐标 + * + * 图标说明: + * - 总体大小:7x9像素 + * - 由一条垂直线和两个对称的三角形组成 + */ static void draw_bt(int x, int y) { - int i; + int i; - draw_vline(x, y-4, y+4, BLACK); - - for(i=0; i<5; i++){ - draw_pixel(x-2+i, y-2+i, BLACK); - draw_pixel(x-2+i, y+2-i, BLACK); - } - draw_pixel(x+1, y-3, BLACK); - draw_pixel(x+1, y+3, BLACK); + // 绘制中心竖线 + draw_vline(x, y-4, y+4, BLACK); + + // 绘制两个对称的三角形 + for(i=0; i<5; i++){ + // 绘制上三角形的边 + draw_pixel(x-2+i, y-2+i, BLACK); + // 绘制下三角形的边 + draw_pixel(x-2+i, y+2-i, BLACK); + } + // 绘制三角形的补充点 + draw_pixel(x+1, y-3, BLACK); + draw_pixel(x+1, y+3, BLACK); } +/** + * 电子墨水屏更新等待定时器 + * + * 功能说明: + * - 检查电子墨水屏是否处于忙状态 + * - 如果忙,则40ms后再次检查 + * - 如果空闲,则完成更新流程并进入省电模式 + * + * 电子墨水屏更新完成后的处理: + * 1. 发送深度睡眠命令(0x10, 0x01) + * 2. 关闭电源 + * 3. 关闭硬件接口 + * 4. 设置系统进入扩展睡眠模式 + */ static void epd_wait_timer(void) { - if(epd_busy()){ - epd_wait_hnd = app_easy_timer(40, epd_wait_timer); - }else{ - epd_wait_hnd = EASY_TIMER_INVALID_TIMER; - epd_cmd1(0x10, 0x01); - epd_power(0); - epd_hw_close(); - arch_set_sleep_mode(ARCH_EXT_SLEEP_ON); - } + if(epd_busy()){ + // 屏幕仍在忙,40ms后再次检查 + epd_wait_hnd = app_easy_timer(40, epd_wait_timer); + }else{ + // 屏幕更新完成 + epd_wait_hnd = EASY_TIMER_INVALID_TIMER; + // 发送深度睡眠命令 + epd_cmd1(0x10, 0x01); + // 关闭电源 + epd_power(0); + // 关闭硬件接口 + epd_hw_close(); + // 设置系统进入扩展睡眠模式 + arch_set_sleep_mode(ARCH_EXT_SLEEP_ON); + } } - +/** + * 绘制时钟界面 + * + * @param flags 显示控制标志 + * bit0-1: 更新模式(快速/正常) + * bit2: 是否显示蓝牙图标 + * + * 显示内容包括: + * - 电池电量图标 + * - 蓝牙连接状态图标(可选) + * - 大字号时间显示 + * - 公历日期和星期 + * - 农历日期 + * - 节气和节日信息 + */ void clock_draw(int flags) { - char tbuf[64]; + char tbuf[64]; if(ota_state){ return; @@ -533,12 +706,38 @@ void clock_draw(int flags) } // 使用大字显示时间 - select_font(1); - sprintf(tbuf, "%02d:%02d", hour, minute); - draw_text(12, 25, tbuf, BLACK); + + if(h24_format){ + // 24小时制 + select_font(0); + sprintf(tbuf, "%02d:%02d", hour, minute); + draw_text(5, 25, " ", BLACK); + draw_text(5, 38, " ", BLACK); + select_font(1); + draw_text(12, 25, tbuf, BLACK); + }else{ + // 12小时制 + int h = hour; + char *ampm = "A"; + if(h>=12){ + if(h>12) h -= 12; + ampm = "P"; + }else if(h==0){ + h = 12; // 0点显示为12点 + } + sprintf(tbuf, "%02d:%02d", h, minute); + select_font(1); + draw_text(12, 25, tbuf, BLACK); + select_font(0); + // 显示AM/PM + draw_text(5, 25, ampm, BLACK); + draw_text(5, 38, "M", BLACK); + } + + // 显示公历日期 - sprintf(tbuf, "%4d年%2d月%2d日 星期%s", year, month+1, date+1, wday_str[wday]); + sprintf(tbuf, "%4d年%2d月%2d日 星期%s", year, month+1, date+1, wday_str[wday]); select_font(0); draw_text(15, 8, tbuf, BLACK); @@ -567,33 +766,94 @@ void clock_draw(int flags) /****************************************************************************************/ -void user_svc1_ctrl_wr_ind_handler(ke_msg_id_t const msgid, struct custs1_val_write_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) +/** + * 控制点写入指示处理函数 + * + * @param msgid 消息ID + * @param param 写入参数 + * @param dest_id 目标任务ID + * @param src_id 源任务ID + * + * 处理通过BLE接收到的控制命令 + */ +void user_svc1_ctrl_wr_ind_handler(ke_msg_id_t const msgid, + struct custs1_val_write_ind const *param, + ke_task_id_t const dest_id, + ke_task_id_t const src_id) { - printk("Control Point: %02x\n", param->value[0]); - + // 打印接收到的控制命令 + printk("Control Point: %02x\n", param->value[0]); } -void user_svc1_long_val_wr_ind_handler(ke_msg_id_t const msgid, struct custs1_val_write_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) +/** + * 长值特征写入指示处理函数 + * + * @param msgid 消息ID + * @param param 写入参数 + * @param dest_id 目标任务ID + * @param src_id 源任务ID + * + * 处理命令: + * - 0x91: 时钟设置命令 + * - 0xA0及以上: OTA升级相关命令 + */ +void user_svc1_long_val_wr_ind_handler(ke_msg_id_t const msgid, + struct custs1_val_write_ind const *param, + ke_task_id_t const dest_id, + ke_task_id_t const src_id) { - //printk("Long value: %d\n", param->length); - if(param->value[0]==0x91){ - clock_set((uint8_t*)param->value); + if(param->value[0]==0x91){ + // 设置时钟 + clock_set((uint8_t*)param->value); + // 更新显示(带蓝牙图标,快速更新模式) + clock_draw(DRAW_BT|UPDATE_FAST); + // 打印当前时间信息 + clock_print(); + } + else if(param->value[0]==0x90) + { + //修改24-12小时制 + h24_format = !h24_format; clock_draw(DRAW_BT|UPDATE_FAST); - clock_print(); - }else if(param->value[0]>=0xa0){ - ota_handle((u8*)param->value); } + else if(param->value[0]>=0xa0) + { + // 处理OTA升级命令 + ota_handle((u8*)param->value); + } + } - -void user_svc1_long_val_att_info_req_handler(ke_msg_id_t const msgid, struct custs1_att_info_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) +/** + * 长值特征属性信息请求处理函数 + * + * @param msgid 消息ID + * @param param 请求参数 + * @param dest_id 目标任务ID + * @param src_id 源任务ID + * + * 响应BLE客户端的属性信息请求 + */ +void user_svc1_long_val_att_info_req_handler(ke_msg_id_t const msgid, + struct custs1_att_info_req const *param, + ke_task_id_t const dest_id, + ke_task_id_t const src_id) { - struct custs1_att_info_rsp *rsp = KE_MSG_ALLOC(CUSTS1_ATT_INFO_RSP, src_id, dest_id, custs1_att_info_rsp); + // 分配响应消息内存 + struct custs1_att_info_rsp *rsp = KE_MSG_ALLOC(CUSTS1_ATT_INFO_RSP, + src_id, + dest_id, + custs1_att_info_rsp); + // 设置连接索引 rsp->conidx = app_env[param->conidx].conidx; + // 设置属性索引 rsp->att_idx = param->att_idx; + // 设置长度为0 rsp->length = 0; + // 设置状态为无错误 rsp->status = ATT_ERR_NO_ERROR; + // 发送响应消息 KE_MSG_SEND(rsp); } diff --git a/weble/log.js b/weble/log.js deleted file mode 100644 index 658e7f6..0000000 --- a/weble/log.js +++ /dev/null @@ -1,64 +0,0 @@ -// 创建日志容器与清除按钮 -const logDiv = document.createElement("div"); -logDiv.id = "fixed-log-window"; -document.body.appendChild(logDiv); - -// 添加清除按钮 -const clearBtn = document.createElement("button"); -clearBtn.textContent = "清空日志"; -clearBtn.className = "clear-log-btn"; -logDiv.appendChild(clearBtn); - -// 按钮点击事件 -clearBtn.onclick = () => { - logDiv.querySelectorAll(".log-entry").forEach(entry => entry.remove()); -}; - -// 覆盖 console.log(保持原有功能) -const originalLog = console.log; -console.log = function(...args) { - originalLog(...args); - const logLine = document.createElement("div"); - logLine.className = "log-entry"; - logLine.textContent = args.join(" "); - logDiv.appendChild(logLine); - logDiv.scrollTop = logDiv.scrollHeight; // 自动滚动 -}; - -// 样式增强 -const style = document.createElement("style"); -style.textContent = ` -#fixed-log-window { - /* 原有样式保持不变 */ - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 200px; - background: rgba(0, 0, 0, 0.85); - color: #fff; - overflow-y: auto; - padding: 40px 10px 10px; /* 顶部留出按钮空间 */ - font-family: monospace; -} -.clear-log-btn { - position: fixed; - right: 20px; - bottom: 215px; - padding: 4px 12px; - background: #ff4444; - border: none; - color: white; - cursor: pointer; - border-radius: 3px; -} -.clear-log-btn:hover { - background: #cc0000; -} -.log-entry { - padding: 4px 0; - border-bottom: 1px solid rgba(255,255,255,0.1); -} -`; -document.head.appendChild(style); - diff --git a/weble/webApp.html b/weble/webApp.html new file mode 100644 index 0000000..14b9e70 --- /dev/null +++ b/weble/webApp.html @@ -0,0 +1,609 @@ + + + + + + HM CLOCK + + + + + + + + + + + + + +
+ +
+

HM CLOCK 控制中心

+
+ + +
+ +
+ + + + +
+ + +
+
+
+ +
+
+

设备名称

+

未连接

+
+
+ +
+
+ +
+
+

当前电压

+

--.- V

+
+
+ +
+
+ +
+
+

设备时间

+

--:--:--

+
+
+ +
+
+ +
+
+

系统时间

+

加载中...

+
+
+
+ + + + + +
+
+

+ 设备日志 +

+ +
+ +
+
终端已启动,等待设备连接...
+
+
+
+ + +
+

HM CLOCK蓝牙控制工具 © https://github.com/tpunix/HMCLOCK

+
+
+ + + + + + \ No newline at end of file diff --git a/weble/weble.html b/weble/weble.html deleted file mode 100644 index 377ae75..0000000 --- a/weble/weble.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - Web Bluetooth Example - - - - - -
-
-
-
-
- - - - - - - - -