透明小时钟开发流程与总结
文章目录
- 功能实现:
- 时间更新
- 天气信息更新
- 菜单配置
- WiFi 配置UI
- Drop down list
- WiFi配置
- lvgl使用虚拟键盘
- WIFI问题
- 其他
- 主界面切换ui
- 逻辑问题
- LVGL
- 设置图片动画
- 主菜单逻辑
- 需要做的事情
- doing
- 城市名字打错之后会进入无限循环。
功能实现:
时间更新
时间功能需要在custom.h里面exten data、time
未知问题,字符串位置索引错误,把char network 分别给time和data会互相重叠。。
解决:使用srting 字符串格式,并且直接传给lvgl为字符串转换为char*的函数 string.(c_str())。
// home_data_str_temp=network_time;//日期暂存// home_time_str_temp=network_time;//时间暂存 这句话的问题。字符串会先赋值,然后后面的就多出来了。。 大意了。。。。
esp32 定时器一共三个,0-3号
定时器的开启要在函数初始化结束后。
定时器中不能对时间进行校准,不然就会错误。
arduino的头文件包含真是吐了!!!
时间更新——ticker定时,每秒定时,到60s的时候再刷新。
time_hour=atoi(home_data_str.substring(8,10).c_str());//时-数值型 memset(temp, 0, sizeof(temp)); sprintf(temp,"%d",time_minute);String weather_code_str=weatherdata.weather_code; weather_code_str.toInt()
String转整数型 使用 String.toInt() (优先)
字符串(char*)转整数型 使用 atoi() //遇到问题,不是函数转换的问题,是数值传递时出现问题,要使用int来接收而不是char
字符串(char*)剪裁 substring()
整形转字符串 sprintf()
字符串(char*)清空函数 memset()
sting转char* string.c_str()
存在偶尔的时间显示错误问题
{ 显示错误
测试时使用预编译命令
#define test 1 #if(test)//要测试的函数,测试时运行。 不加{} #else//正常的函数,测试时不运行。 #endif
- 遇到指针赋值的,一定要确定要赋值的指针是否为static!!!!!局部指针赋值给别人就是错误的!!!
时间更新函数,结束。
天气信息更新
联网才会更新天气和日期,离线模式下,只有时间有效(时钟计时推算,且长时间下有飘逸)
错误
void WIFIconnect::connect_server(String city)
{struct WetherData{char city[32];char code_city[32];char weather[64];char high[32];char low[32];char humi[32];};const char *host = "api.seniverse.com";const char *privateKey = "SNfnJoTWHKFu_rJrW";const char *language = "en";WiFiClient client;if (!client.connect(host, 80)){Serial.println("Connect server failed!"); //网络连接失败,无网络。return;}String getUrl = "/v3/weather/daily.json?key=";getUrl += privateKey;getUrl += "&location=";getUrl += city;getUrl += "&language=";getUrl += language;client.print(String("GET ") + getUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");Serial.println("");char endOfHeaders[] = "\r\n\r\n";bool ok = client.find(endOfHeaders);if (!ok){Serial.println("No response or invalid response!");}String line="";line += client.readStringUntil('\n'); DynamicJsonDocument doc(1400);DeserializationError error = deserializeJson(doc, line);if (error){Serial.println("deserialize json failed");return;}struct WetherData weatherdata = {0};strcpy(weatherdata.city, doc["results"][0]["location"]["name"].as<const char*>());strcpy(weatherdata.weather, doc["results"][0]["daily"][0]["text_day"].as<const char*>());strcpy(weatherdata.high, doc["results"][0]["daily"][0]["high"].as<const char*>());strcpy(weatherdata.low, doc["results"][0]["daily"][0]["low"].as<const char*>());strcpy(weatherdata.humi, doc["results"][0]["daily"][0]["humidity"].as<const char*>());Serial.print("City:");Serial.println(weatherdata.city);Serial.print("textDay:");Serial.println(weatherdata.weather);Serial.print("temp high:");Serial.println(weatherdata.high);Serial.print("temp low:");Serial.println(weatherdata.low);Serial.print("humi:");Serial.println(weatherdata.humi);client.stop();
}
已解决,天气信息json索引错误,有[ ]的要加[0]
strcpy(weatherdata.weather_text, doc["results"][0]["now"]["text"].as<const char*>());
天气图片信息,要注释掉设置尺寸的信息,适应自动调整图片。
lv_obj_set_size(ui->home_img_weather, 51, 51);
索引图片正常
天气暂无问题
菜单配置
回菜单配置,配置一个结构体,结构体里放置需要全局引用的变量。
struct Weather_Overall_Data//main.h中 {String lv_home_data;String lv_home_time; char time_hour;char time_minute;char time_sec; }; struct Weather_Overall_Data weather_overall_data//main.cpp中//指针赋值:把string直接传给string、把char*直接传给string,更加安全。。且不需要使用static修饰。weather_overall_data.lv_home_time=home_time_str_temp;//strcpy(wether_overall_data.lv_home_time,home_time_str_temp.c_str());//传出参数//这样做不需要再使用static修饰string//但这样会出现字符串叠加问题//需要home_data_str_temp为static// lv_home_data=(char*)home_data_str_temp.c_str();//传出参数// lv_home_time=(char*)home_time_str_temp.c_str();
如果需要在C中使用string,应该包含 string.h 。
问题1:没有定义的引用,但这个函数却是有定义的。有可能是在cpp文件里面引用了c文件里的函数,或者是在c文件里面引用了cpp文件里的函数。
C里面不能编译CPP文件。c里面不能编译cpp文件
c和c++混合编译
在C++里面编译C文件的函数 解决办法: 也可以使用在c里面编译C++文件的方法。
直接在c++文件里对头文件进行extern"C"{}
extern "C" { #include "a.h" };
在C里面编译C++文件里面的函数 解决办法:
在c++文件对应的.h 里在函数声明时使用 extern"C"{}
#ifdef __cplusplus extern "C"{#endif void function(void);#ifdef __cplusplus } #endif
通常一个函数为了兼容c和c++会被这样上面那样写。
其中__cplusplus就是c++的意思。也就是说,这个函数在c++文件中被编译时,是要包含extern“C”{} 的,代表这是一个c函数。
另外,需要注意的是!C里面不可以包含具有C++关键字的头文件(如string),如果需要调用这些数据(如string),必须在C++文件里对他封装为函数,再在头文件里对该函数使用extern“C”{}即可。即,使用的时候需要通过函数的形式间接调用数据。(从此处也可以看出来,#include 里面的代码只是替换的作用,并没有被编译,只有在.c或.cpp里面的文件才会被编译为.o)
至此,参数全部可以传出来了并且各函数间可以互相调用。
还需要主页间切换
把几个菜单都加入group。
按键按下后要释放。,但又不能立马释放。
问题 :进入菜单再回来就会出错。
- 原因:动画的问题,动画还没有结束,就对对象刷新或加入组。
- 解决:去掉动画的延迟。
问题:图片没有被选中动画(focused),只有点击动画(pressed)和被控动画(check)。
- 使用全屏固定位选中。
- 或者使用背景图片,前景是按键,这样按键就有被选择的框了。(优先)
- 先创建7个图像、再创建7个按键、然后按键按下后跳转到对应的功能。
- 已实现
问题:进入菜单后一分钟左右会出现错误,并且重启。
- 原因:定时器更新刷新时间,在没有对象的时候刷新对象。
- 解决:刷新对象的时候判断当前菜单在哪,在主界面的时候再刷新。
- 结构体内添加一个当前菜单位置,lv_home_data_refresh这个函数内部对菜单位置判断即可。
开机启动校准一次时间和天气。
时间校准时刷新时间和日期数据。
天气校准时刷新天气数据:图片、地区、温度。
WiFi 配置UI
- 设置ui
- lvgl 加入组(group)是由顺序的,先加入的为第一个组,编码值增加时会进入下一个组。但最后一个加入的组会被先预选中。所以,按照顺加入组即可,将最后一个需要先显示的组放到最后一个即可。(如果这个组时单独的一个的话,并且与其他组没有前后顺序)
- lvgl的switch居然是按键释放的时候动作,所以要在转切屏幕动画结束之前把按键释放了。
Drop down list
使用 Drop down list 官方代码
#include "../../../lv_examples.h"
#include <stdio.h>
#if LV_USE_DROPDOWNstatic void event_handler(lv_obj_t * obj, lv_event_t event)
{if(event == LV_EVENT_VALUE_CHANGED) {char buf[32];lv_dropdown_get_selected_str(obj, buf, sizeof(buf));printf("Option: %s\n", buf);}
}void lv_ex_dropdown_1(void)
{/*Create a normal drop down list*/lv_obj_t * ddlist = lv_dropdown_create(lv_scr_act(), NULL);lv_dropdown_set_options(ddlist, "Apple\n""Banana\n""Orange\n""Melon\n""Grape\n""Raspberry");lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);lv_obj_set_event_cb(ddlist, event_handler);
}#endif
list被改变时,调用这个函数:
void ddlist_value_changed(void)
{char buf[32];lv_dropdown_get_selected_str(guider_ui.wifi_config_ddlist_1, buf, sizeof(buf));printf("Option: %s\n", buf);
}
lv_dropdown_get_selected_str函数的使用:
/*** Get the current selected option as a string* @param ddlist pointer to ddlist object* @param buf pointer to an array to store the string* @param buf_size size of `buf` in bytes. 0: to ignore it.*/
void lv_dropdown_get_selected_str(const lv_obj_t * ddlist, char * buf, uint32_t buf_size)
list添加成员:
/*** Add an options to a drop down list from a string. Only works for dynamic options.* @param ddlist pointer to drop down list object* @param option a string without '\n'. E.g. "Four"* @param pos the insert position, indexed from 0, LV_DROPDOWN_POS_LAST = end of string*/ void lv_dropdown_add_option(lv_obj_t * ddlist, const char * option, uint32_t pos)
pos=0时,默认 后加入的会放在第一个位置
优先显示最后一个list。
list清空成员
/*** Clear any options in a drop down list. Static or dynamic.* @param ddlist pointer to drop down list object*/ void lv_dropdown_clear_options(lv_obj_t * ddlist)
WiFi配置
- 界面中的 取消,实际上读取spiffs文件系统中上次配置成功的WiFi信息。
- 界面中的 应用,实际上是将WiFi信息写入到spiffs文件系统中。
lvgl使用虚拟键盘
问题:wifi写入密码的时候无法聚焦到键盘上
解决: lv_group_focus_obj(kb);强制聚焦。
官方源码的解释:
static lv_obj_t * kb; static lv_obj_t * ta; static void kb_event_cb(lv_obj_t * keyboard, lv_event_t event) {lv_keyboard_def_event_cb(kb, event);//键盘回调函数if(event == LV_EVENT_APPLY || event == LV_EVENT_CANCEL) {//如果关闭或应用按键被单击lv_keyboard_set_textarea(kb, NULL); //取消为键盘分配的输入框lv_obj_del(kb);//删除键盘对象kb = NULL;//清除对象} }static void kb_create(void) {kb = lv_keyboard_create(lv_scr_act(), NULL);//创建一个键盘lv_keyboard_set_cursor_manage(kb, true);//设置启动键盘的文本提示光标lv_obj_set_event_cb(kb, kb_event_cb);//这是键盘的回调函数lv_keyboard_set_textarea(kb, ta);//为键盘分配一个文本区域 ,将单击的字符自动放在此处。}static void ta_event_cb(lv_obj_t * ta_local, lv_event_t event) {if(event == LV_EVENT_CLICKED && kb == NULL) { //如果输入框被按下,并且键盘对象没有被创建。LV_EVENT_PRESSEDkb_create();} }void lv_ex_keyboard_1(void) {/*Create a text area. The keyboard will write here*/ta = lv_textarea_create(lv_scr_act(), NULL);//创建到当前屏幕(容器)上lv_obj_align(ta, NULL, LV_ALIGN_IN_TOP_MID, 0, LV_DPI / 16);//对齐lv_obj_set_event_cb(ta, ta_event_cb);//输入框回调函数lv_textarea_set_text(ta, "");//设置输入框内容lv_coord_t max_h = LV_VER_RES / 2 - LV_DPI / 8;//获得坐标if(lv_obj_get_height(ta) > max_h) lv_obj_set_height(ta, max_h);//设置高输入框的高kb_create(); }
自己使用只需要把LV_EVENT_CLICKED换成 LV_EVENT_PRESSED就行了,然后添加自己的函数处理一下
void password_input(void) {lv_ex_keyboard_1();lv_group_add_obj(group, ta);lv_group_add_obj(group, kb);lv_group_focus_obj(kb); //已经被聚焦,点一下确认键就可以了。button_ent_click();//模拟点击确认。}
问题,输入退出后(删除对象),group会聚焦到“应用”上无法聚焦其他控件
尝试解决:在删除对象的时候强制聚焦到其他控件上
- 聚焦后无法再移动。
尝试解决:重新加入全部的组
- 无响应。
尝试解决:在删除对象前强制聚焦到其他控件上
- 正常
- 原因:焦点还focus在键盘上,但是键盘对象却被删除了,导致无法正常退出focus和obj,从而无法切换到group的其他obj。
编码长按要有加速
关联文本框。
把文本框的内容取出来,
链接选中的WiFi
存入spiffs
结束,但有小问题
已按照wifi强度顺序添加,并且修复无 法选择WIFI退出。
WIFI问题
E (16232) wifi:Set status to INIT 长时间连接WIFI但是不连接网络,就会出错。
尝试
void setup(void) {Serial.begin(115200);WiFi.begin(ssid, password);delay(1000);WiFi.disconnect();delay(1000);WiFi.begin(ssid, password);delay(1000); ... }
- 重启路由器可以解决,但是其他设备可以正常连接,说明其实并不是路由器的问题,还是ESP32的问题。
开机启动画面
wifi强度显示。
WiFi.RSSI()
- 返回int型,转换一下就可以
- WIFI强度:~ -80 弱、-81 -71一般、-70 -0 信号强、
- 已添加wifi强度图像显示
- 问题:WIFI显示未连接
- WIFI强度显示正常。
其他
ui已完成
主界面切换ui
- 添加对应的逻辑
- 应用键被按下后,要返回home。
- 添加逻辑函数
- location逻辑完成
逻辑问题
- 更改的WIFI连接上后没问题(能连接上,不判断能否上网,只验证密码是否正确)再保存。
- 更改的location连接问没问题后再保存
LVGL
设置图片动画
//Write animation: menu_img_wifimove in x directionlv_anim_t menu_img_wifi_x;lv_anim_init(&menu_img_wifi_x);lv_anim_set_var(&menu_img_wifi_x, ui->menu_img_wifi);lv_anim_set_time(&menu_img_wifi_x, 1000);lv_anim_set_exec_cb(&menu_img_wifi_x, (lv_anim_exec_xcb_t)lv_obj_set_x);lv_anim_set_values(&menu_img_wifi_x, lv_obj_get_x(ui->menu_img_wifi), 10);_lv_memcpy_small(&menu_img_wifi_x.path, &lv_anim_path_menu_img_wifi, sizeof(lv_anim_path_cb_t));lv_anim_start(&menu_img_wifi_x);
主菜单逻辑
- 开机显示开机画面(7张图片每张1s),并等待扫描和连接WIFI。
- 扫描WIFI并等待加入,70次错误后进入主页面
- WiFi错误界面:(账号、密码、地点错误)重试:重启 、 取消:进入主界面。
- 初始化正常,进入主页面,显示天气等数据。
- 在主页持续30秒将进入睡眠模式。
需要做的事情
- 进入主页需要验证是否联网,如果没有网络连接将刷新WIFI和天气图片
- 使用内部RTC进行时间刷新
- 写一个手动更新时间日期的函数和界面(联网自动更新)
- 电量显示
- 睡眠与睡眠唤醒
doing
修改默认启动界面
setup_scr_light_config(ui);lv_scr_load(ui->image_config);
城市名字打错之后会进入无限循环。
解决:先初始化 mpu,如果开机向下,就重置城市信息。
透明小时钟开发流程与总结相关推荐
- 微信小程序怎么在wxml中插入多个图片_兰州小程序开发流程费用推荐品牌_便企网...
兰州小程序开发流程费用推荐品牌,有人说既然开发文档这么详细那直接跟着开发文档来学习就可以轻松入门,你有这份自信是非常好的,也希望你有很强的学习能力,但对于很多的普通人新手来说(当然也包括我),做作品的 ...
- ui测试怎么做?依据文档有哪些_微信小程序开发流程有哪些?各个环节注意事项...
微信小程序开发流程有哪些?各个环节注意事项是什么?微信小程序开发有哪些注意事项,开发流程是怎样的?下面就一起来看看吧. 1.微信小程序开发之注册小程序 在开发小程序之前,首先就是要注册一个小程序.不过 ...
- 小程序 cover-view 字体_【企商云】2021年,要知道的9个小程序开发流程清单
从17年小程序上线后,格外受到市场青睐,从火爆春节的"跳一跳"到商界巨头头条.百度.支付宝等纷纷上线,而20年疫情期间更让小程序成为商家运营法宝,极力转型线上线下.如今距离2021 ...
- 武装你的小程序——开发流程指南
前端工程本质上是软件工程的一种.软件工程化关注的是性能.稳定性.可用性.可维护性等方面,注重基本的开发效率.运行效率的同时,思考维护效率.一切以这些为目标的工作都是"前端工程化". ...
- 微信小程序开发详细步骤(企业小程序开发流程)
今天珍奶bb给大家简单唠唠微信小程序开发详细步骤(企业小程序开发流程)? 微信小程序制作流程是什么?微信小程序制作模板套用怎么操作?今天珍奶bb给大家简单唠唠微信小程序制作流程是什么? 在唠微信小程序 ...
- 微信小程序开发流程的两种方法科普
现在微信小程序早已渗透我们日常生活的方方面面,很多商家看到了小程序带来的巨大流量,也想开发一个自己的小程序.所以今天就跟大家科普下微信小程序开发流程,你会发现这个开发过程其实非常简单. 1. 在微信公 ...
- 小程序发布上线流程_微信小程序开发流程的两种方法科普
现在微信小程序早已渗透到我们日常生活的方方面面,很多商家看到了小程序带来的巨大流量,也想开发一个自己的小程序.所以今天就跟大家科普下微信小程序开发流程,你会发现这个开发过程其实非常简单. 1. 在微信 ...
- 【小程序】微信小程序开发流程
文章目录 一.概述 二.整体开发架构 三.注册账号和安装开发工具 1)注册账号 1.注册方法 2.选择注册的帐号类型 3.填写邮箱和密码 4.激活邮箱 5.填写主体信息 6.登录后台补充信息 2)安装 ...
- 小程序开发流程:微信小程序开通步骤有哪些?
一个小程序开发的大致的流程步骤如下: 1.开发微信小程序需要去微信官网注册一个企业版的小程序账号: 2.开通微信小程序,每年需要交300元的认证费.如果是开通过微信企业订阅号或者服务号的,就可以复用订 ...
最新文章
- stable_partition
- python37.dll可能与您正在运行_win7系统提示模块可能与您正在运行的windows版本不兼容如何解决...
- Android复习15【动画:创建资源文件夹、创建动画资源文件、组合动画、属性动画、材料设计新特性】
- 高中计算机网络安全教案,浙教版高中信息技术教案信息安全
- 移动端适配的几种解决办法
- webservice 基本要点
- 免费直播| TDD如何颠覆了我对开发的认知?
- 《ArcGIS Runtime SDK for .NET开发笔记》--三维功能
- C# ToString() 参数大全
- 设备驱动简介 -- ldd3读书笔记
- JavaScript正则表达式19例(11)
- 网易易盾—推理拼图验证码的破解
- linux imx6 sdio wifi,关于ATWILC1000 wifi模块在imx6q上SDIO接口驱动调试
- wind 数据 python_从wind python接口获取数据并存储
- JNI便捷开发框架JNA框架之指针参数Pointer(二)
- 积分墙广告的七个真相(触控软文)
- C++ 16进制日志输出 每行右侧ASII输出
- 观远数据苏春园:五年AI+BI路,数智化破局中的变与不变|数据猿采访
- 考研OR工作----计算机操作系统简答题及疑难知识点总结(第一章 操作系统引论)
- 涂抹mysql笔记-数据导出导入