STM32单片机项目实例:基于TouchGFX的智能手表设计(8)底层驱动与UI进行关联

本文主要是介绍STM32单片机项目实例:基于TouchGFX的智能手表设计(8)底层驱动与UI进行关联,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32单片机项目实例:基于TouchGFX的智能手表设计(8)底层驱动与UI进行关联

一、概述与代码添加

  在TouchGFX中,从Model类执行与应用非UI部分(这里称为后端系统)的通信。后端系统是从UI接收事件和将事件输入UI的软件组件,例如采集传感器的新测量值。后端系统可作为单独的任务在同一MCU、单独的处理器、云模块或其他硬件上运行。从TouchGFX的角度来看,这并不十分重要,只要它是能够与之通信的组件。

  使用的特定通信协议不受TouchGFX管理。它只提供一个在每个TouchGFX嘀嗒时间调用一次的函数,可以在其中处理需要的通信。

图 1-1 Model-View-Presenter和外部通信

Model 类是一个永远存在的单类,它有两个用途:

  1. 保存UI的状态信息。 在切换屏幕时,View和Presenter的分配会被清除,因此它们不能用于存储在屏幕转换时应当保留的信息。 为此,使用Model保存信息。
  2. 作为面向后端系统的接口,向/从当前活动屏幕发送事件。

Model类是自动设置的,具有指向当前活动Presenter的指针。当Model中发生变化时,将变化通知当前活动Presenter。这是通过应用中ModelListener接口中的方法来完成的。TouchGFX Designer生成的新应用将自动拥有可直接供UI使用的Model类。

  采用STM32CubeMX配置TouchGFX后,需要打开TouchGFX 4.21.2 Designer软件重新生成以下代码,避免MDK编译报错。配置生成的代码中主要包含三个文件:Model.cpp、Model.hpp、ModelListener.hpp,在这个三个文件中添加与UI相关的数据交互接口。

Model.cpp文件:

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>Model::Model() : modelListener(0)
{
}void Model::tick()
{}

Model.hpp文件:

#ifndef MODEL_HPP
#define MODEL_HPPclass ModelListener;class Model
{
public:Model();void bind(ModelListener* listener){modelListener = listener;}void tick();
protected:ModelListener* modelListener;
};#endif // MODEL_HPP

ModelListener.hpp文件:

#ifndef MODELLISTENER_HPP
#define MODELLISTENER_HPP#include <gui/model/Model.hpp>class ModelListener
{
public:ModelListener() : model(0) {}virtual ~ModelListener() {}void bind(Model* m){model = m;}
protected:Model* model;
};#endif // MODELLISTENER_HPP

  在Model.cpp中增加与底层驱动关联代码,Model.hpp与ModelListener.hpp用于函数的声明。下面是基于TouchGFX的智能手表设计的Model.cpp中的底层关联代码:

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>#if defined LINK_HARDWARE 	//TuchGFX仿真与实际硬件操作隔离//头文件包含extern "C"{#include "user_app.h"}//底层数据extern volatile SHT20_TemRH_Val gTemRH_Val;extern RTC_DateTypeDef gSystemDate;  //获取日期结构体extern RTC_TimeTypeDef gSystemTime;   //获取时间结构体extern gTask_BitDef gTaskStateBit;  //任务执行过程中使用到的标志位extern gTask_MarkEN gTaskEnMark;  //系统任务使能标识extern volatile StruAP3216C_Val gAP3216C_Val;	//AP3216数据结构extern volatile uint8_t gLastTimeSeconds;	//上一次的时间extern volatile float pitch,roll,yaw; //欧拉角extern unsigned long gSportStep;	//运动步数extern wifiRSSI ao_wifiRSSI;extern uint8_t gFiveKeyFunc;	//定义的五向按键值功能	extern volatile uint16_t gCurrentVal;	//资源扩展板电流,通道IN8   extern volatile uint16_t gVoltageVal;	//资源扩展板电压,通道IN9  extern volatile uint16_t gChipTempVal;//内部参考电压,通道IN12  extern volatile uint16_t gVrefVal;		//内部参考电压,通道IN13   	extern volatile uint16_t gVbatVal;		//RTC电池电压,通道IN14  extern int32_t n_heart_rate;   //heart rate value=n_heart_rate/4,采样率100sps,max30102设置4点求平均extern int32_t n_sp02; //SPO2 valueextern int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is validextern int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is validextern uint8_t gWiFiInfo[40];	//用于通知View界面的Text文本显示
//volatile uint8_t gSwitchSpace = 0x00;	//页面切换的时间间隙static int32_t gHeartRate = 0;  //表盘页面的心率数据
#else //Designer仿真#include <ctime>#ifndef _MSC_VER#include <sys/time.h>#endif /* _MSC_VER*///volatile uint8_t gBacklightVal = 50;	//背光值,默认50%
#endif
/**********************************TouchGFX与底层间的访问**********************************/
Model::Model() : modelListener(0)
{}
//
void Model::tick()
{static uint8_t tickCount = 0;	//减少数据上传的次数,优化界面刷新tickCount++;	#if defined LINK_HARDWARE//if(gSwitchSpace != 0) gSwitchSpace--;	/********************************硬件页面切换*********************************///表盘页面if(gTaskEnMark.UPDATE_DIAL_EN && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->DialPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//应用页面if(gTaskEnMark.UPDATE_APPPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace)){modelListener->AppPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//六轴页面if(gTaskEnMark.UPDATE_SIX_AXIS_EN && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace)){modelListener->SixAxisPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//无线页面if(gTaskEnMark.UPDATE_WIFIPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->WiFiPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//设置页面if(gTaskEnMark.UPDATE_SETTINGPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->SettingPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//控制页面if(gTaskEnMark.UPDATE_MOTORPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->MotorPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//信息页面,温度、湿度与光强度if(gTaskEnMark.UPDATE_INFOPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->InfoPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//健康页面if(gTaskEnMark.UPDATE_HEALTHPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->HealthPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//Chip页面if(gTaskEnMark.UPDATE_CHIPPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->ChipPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//Battery页面
if(gTaskEnMark.UPDATE_BATTERYPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->BatteryPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//Sport页面退出if(gTaskEnMark.UPDATE_SPORTPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->SportPageExit(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//Alipay页面退出if(gTaskEnMark.UPDATE_ALIPAYPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->AlipayPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//Sport页面进入if(!HAL_GPIO_ReadPin(USER_KEY_GPIO_Port,USER_KEY_Pin))	{modelListener->SportPageEnter(3);	}/********************************更新各类信息*********************************///更新时间信息,为使表盘页面滑动操作正常,在屏幕被点按时不更新数据if(gTaskEnMark.UPDATE_DIAL_EN && (gSystemTime.Seconds != gLastTimeSeconds)&&(gTaskStateBit.TouchPress == 0))	//每秒同步一次界面时间{modelListener->updateDate(gSystemDate.Year,gSystemDate.Month,gSystemDate.Date,gSystemDate.WeekDay);modelListener->updateTime(gSystemTime.Hours, gSystemTime.Minutes, gSystemTime.Seconds);//更新新值gLastTimeSeconds = gSystemTime.Seconds;	//更新温度/步数/心率modelListener->updateTempStepHeart(gTemRH_Val.Tem,gSportStep,gHeartRate);}//健康监测信息上传if(gTaskEnMark.UPDATE_HEALTHPAGE && (gTaskStateBit.TouchPress == 0))	{//send samples and calculation result to terminal program through UARTif(ch_hr_valid || ch_spo2_valid)
{modelListener->updateHeartRateInfo(n_heart_rate/4, n_sp02);gHeartRate = n_heart_rate/4;  //保存心率数据值表盘页面}//if(gTaskStateBit.Max30102)	//单次测量完成,清除标志{ch_hr_valid =0;ch_spo2_valid=0;gTaskStateBit.Max30102 = 0;}}//更新欧拉角if(gTaskEnMark.UPDATE_SIX_AXIS_EN)	//六轴界面活动时上传{modelListener->updateSixAxis(pitch, roll, yaw);}//获取WiFi模组的RSSI值if((gTaskEnMark.UPDATE_WIFI_RSSI_EN))	//只有在系统主页时,才进行WiFi的RSSI数据读取{modelListener->updateWiFiRSSI(gWiFiInfo, ao_wifiRSSI.gRSSI);}//更新温湿度信息if(gTaskEnMark.UPDATE_INFOPAGE)	//INFO面活动时上传{modelListener->updateInfo(gTemRH_Val.Hum, gTemRH_Val.Tem, gAP3216C_Val.ALS);}//更新芯片参数if(gTaskEnMark.UPDATE_CHIPPAGE && (!(tickCount % 5))){modelListener->updateChipInfor(gChipTempVal, gVrefVal, gVbatVal);	//更新芯片温度、参考电压、Vbat}	//更新电压与电流if(gTaskEnMark.UPDATE_BATTERYPAGE){modelListener->updateBatteryPageInfo(gCurrentVal, gVoltageVal);	//更新电压与电流}	
#else //Designer仿真timeval timenow;gettimeofday(&timenow, NULL);//仿真更新时间modelListener->updateTime((timenow.tv_sec / 60 / 60) % 24,(timenow.tv_sec
/ 60) % 60,timenow.tv_sec % 60);
#endif	
}
//风扇操作
void Model::turnFanStatus(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)HAL_GPIO_WritePin(EXT_FAN_GPIO_Port,EXT_FAN_Pin,GPIO_PIN_SET);	//风扇状态的设置else HAL_GPIO_WritePin(EXT_FAN_GPIO_Port,EXT_FAN_Pin,GPIO_PIN_RESET);	
#endif
}
//振动电机操作
void Model::setMotorStatus(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)HAL_GPIO_WritePin(EXT_MOTOR_GPIO_Port,EXT_MOTOR_Pin,GPIO_PIN_SET);	//振动电机状态的设置else HAL_GPIO_WritePin(EXT_MOTOR_GPIO_Port,EXT_MOTOR_Pin,GPIO_PIN_RESET);	
#endif
}
//排水操作
void Model::drainWaterStatus(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)HAL_GPIO_WritePin(EXT_MOTOR_GPIO_Port,EXT_MOTOR_Pin,GPIO_PIN_SET);	//振动电机设置else HAL_GPIO_WritePin(EXT_MOTOR_GPIO_Port,EXT_MOTOR_Pin,GPIO_PIN_RESET);	
#endif
}
//蜂鸣器操作
void Model::setBuzzerStatus(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)HAL_GPIO_WritePin(RUN_BEEP_GPIO_Port,RUN_BEEP_Pin,GPIO_PIN_SET);	//蜂鸣器状态的设置else  HAL_GPIO_WritePin(RUN_BEEP_GPIO_Port,RUN_BEEP_Pin,GPIO_PIN_RESET);	
#endif
}
/*********************gTaskEnMark赋值*************************/
//DialView的任务的状态
void Model::DialPageViewTask(bool enable)
{#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_DIAL_EN = 1;	//任务使能elsegTaskEnMark.UPDATE_DIAL_EN = 0;	//任务清除
#endif
}
//ApplicationPageView的任务的状态
void Model::ApplicationPageViewTask(bool enable)
{#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_APPPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_APPPAGE = 0;	//任务清除
#endif
}
//SixAxisPageView的任务的状态
void Model::SixAxisPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_SIX_AXIS_EN = 1;	//任务使能elsegTaskEnMark.UPDATE_SIX_AXIS_EN = 0;	//任务清除
#endif
}
//InfoPageView任务使能
void Model::InfoPageViewTask(bool newStatus)
{
#if defined LINK_HARDWAREif(newStatus == true)	gTaskEnMark.UPDATE_INFOPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_INFOPAGE = 0;	//任务清除
#endif
}
//ChipPageViewTask的任务的状态
void Model::ChipPageViewTask(bool enable)
{#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_CHIPPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_CHIPPAGE = 0;	//任务清除
#endif
}
//设置健康监测任务
void Model::HealthPageViewTask(bool newStatus)
{#if defined LINK_HARDWAREif(newStatus == true)	gTaskEnMark.UPDATE_HEALTHPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_HEALTHPAGE = 0;	//任务清除
#endif
}
//WiFi连接的任务状态
void Model::WiFiLinkTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_WIFI_RSSI_EN = 1;	//任务使能elsegTaskEnMark.UPDATE_WIFI_RSSI_EN = 0;	//任务清除
#endif
}
//WiFi界面的任务状态
void Model::WiFiPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_WIFIPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_WIFIPAGE = 0;	//任务清除
#endif
}
//Setting界面的任务状态
void Model::SettingPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_SETTINGPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_SETTINGPAGE = 0;	//任务清除
#endif
}
//Motor界面的任务状态
void Model::MotorPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_MOTORPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_MOTORPAGE = 0;	//任务清除
#endif
}
//Battery界面的任务状态
void Model::BatteryPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_BATTERYPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_BATTERYPAGE = 0;	//任务清除
#endif
}
//运动界面的任务状态
void Model::SportPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_SPORTPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_SPORTPAGE = 0;	//任务清除
#endif
}
//Aliplay界面任务状态
void Model::AlipayPageViewTask(bool enable)
{
#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_ALIPAYPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_ALIPAYPAGE = 0;	//任务清除
#endif
}

Model.hpp中的函数声明:

#ifndef MODEL_HPP
#define MODEL_HPPclass ModelListener;class Model
{
public:Model();void bind(ModelListener* listener){modelListener = listener;}void tick();//SettingPageView的任务的状态void SettingPageViewTask(bool enable);//DialPageView的任务的状态void DialPageViewTask(bool enable);//FiveKeyPageView的任务的状态void FiveKeyPageViewTask(bool enable);//ApplicationPageView的任务的状态void ApplicationPageViewTask(bool enable);//SixAxisPageView的任务的状态void SixAxisPageViewTask(bool enable);	//InfoPageView的任务的状态void InfoPageViewTask(bool enable);	//ChipPageView的任务的状态void ChipPageViewTask(bool enable);//WiFiPageView的任务的状态void WiFiPageViewTask(bool enable);//MotorPageView的任务的状态void MotorPageViewTask(bool enable);//BatteryPageView的任务的状态void BatteryPageViewTask(bool enable);//SportPageView的任务的状态void SportPageViewTask(bool enable);//Aliplay界面任务状态void AlipayPageViewTask(bool enable);//控制事件void turnFanStatus(bool enable);void setMotorStatus(bool enable);void setBuzzerStatus(bool enable);void drainWaterStatus(bool enable);//HealthPageView的任务的状态void HealthPageViewTask(bool enable);
//无线连接任务void WiFiLinkTask(bool enable);
protected:ModelListener* modelListener;
};#endif // MODEL_HPP

ModelListener.hpp中的函数声明:

#ifndef MODELLISTENER_HPP
#define MODELLISTENER_HPP#include <gui/model/Model.hpp>
extern "C" {
#include "stdint.h"
}
class ModelListener
{
public:ModelListener() : model(0) {}virtual ~ModelListener() {}void bind(Model* m){model = m;}//更新日期和时间virtual void updateDate(uint8_t Year, uint8_t Month, uint8_t Date, uint8_t WeekDay) {}virtual void updateTime(uint8_t Hours, uint8_t Minutes, uint8_t Seconds) {}//页面跳转virtual void SettingPageChange(uint8_t newFiveKeyFunc){}virtual void DialPageChange(uint8_t newFiveKeyFunc){}virtual void AppPageChange(uint8_t newFiveKeyFunc){}virtual void SixAxisPageChange(uint8_t newFiveKeyFunc){}virtual void ChipPageChange(uint8_t newFiveKeyFunc){}virtual void MotorPageChange(uint8_t newFiveKeyFunc){}virtual void InfoPageChange(uint8_t newFiveKeyFunc){}virtual void HealthPageChange(uint8_t newFiveKeyFunc){}virtual void WiFiPageChange(uint8_t newFiveKeyFunc){}virtual void BatteryPageChange(uint8_t newFiveKeyFunc){}virtual void SportPageEnter(uint8_t newKeyFunc){}virtual void SportPageExit(uint8_t newFiveKeyFunc){}virtual void AlipayPageChange(uint8_t newFiveKeyFunc){}//温度/步数/心率上传
virtual void updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate){}//更新姿态信息参数virtual void updateSixAxis(float pitchVal,float rollVal,float yawVal) {}//更新芯片内部参数virtual void updateChipInfor(uint16_t ChipTempVal, uint16_t VrefVal, uint16_t VbatVal) {}	//健康监测信息上传virtual void updateHeartRateInfo(uint32_t newHeartRate, uint32_t newSPO2) {}	//更新温湿度、光照度数据上传	virtual void updateInfo(float newHum, float newTem, uint16_t newALS) {}//获取WiFi模组的RSSI值virtual void updateWiFiRSSI(uint8_t (&pWiFiInfo)[40], uint16_t newRSSI) {}	virtual void updateWalkStep(unsigned long newStep){}//更新电压、电流virtual void updateBatteryPageInfo(uint16_t CurrentVal, uint16_t VoltageVal) {}
protected:Model* model;
};#endif // MODELLISTENER_HPP

 

这篇关于STM32单片机项目实例:基于TouchGFX的智能手表设计(8)底层驱动与UI进行关联的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/513011

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测