TT12-MCU/applications/_main.c
2023-08-03 11:04:50 +08:00

483 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-06-01 murmur the first version
* 处理TT相关的初始化、状态切换等逻辑
*/
#include <rtthread.h>
#define LOG_TAG "main_scha"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#include <board.h>
#include <ttmsg/ttmsg.h>
//#include <cfg.h>
#include <usrcfg.h>
#include <ttTR.h>
//static struct rt_event sw_check; //软件条件
static struct rt_event chkSta; //发送条件含两部分1-超时或文件准备好2-TT满足通信条件
#define ALL_READY 1
static int maxTTWaitTime = 4;
static int maxTTRetryCnt = 3;
rt_sem_t TTReady= RT_NULL;//天通具备发送状态后 rt_sem_release(TTReady);
rt_sem_t cfgUpdate = RT_NULL;
rt_sem_t shuntDownTT = RT_NULL;
//void TTisReady(void)
//{
// rt_sem_release(TTReady);
//}
SYS_CFG scfg={
.sendInterval =60,
.maxTTWaitTime = 4,
.maxTTRetryCnt = 3,
.minTTPeriCnt=5,
.minTTsinal=5,
.timeout=5,
.maxSizePerFile=1024
};
/**
* 更新全局参数
*/
static void updatecfg(void)
{
//因为不知原因,采用事件集独立更新配置出错,无精力深查
//独立响应单个参数更新事件,程序上更复杂也没特别必要
//现采用事件通知、统一全部重新加载
while(1)
{
if(rt_sem_take(cfgUpdate, RT_WAITING_FOREVER) == RT_EOK)
{
scfg.maxTTWaitTime = get_cfg("maxTTWaitTime");
scfg.maxTTRetryCnt = get_cfg("maxTTRetryCnt");
scfg.minTTPeriCnt = get_cfg("minTTPeriCnt");
scfg.minTTsinal = get_cfg("minTTsinal");
scfg.timeout = get_cfg("timeout");
scfg.maxSizePerFile = get_cfg("maxSizePerFile");
}
LOG_D("cfg updated.");
}
}
void sysSemInit()
{
// TTReady = rt_sem_create("TTisReady", 0, RT_IPC_FLAG_PRIO);
cfgUpdate = rt_sem_create("cfgUpdate", 0, RT_IPC_FLAG_PRIO);
shuntDownTT = rt_sem_create("shuntDNTT", 0, RT_IPC_FLAG_PRIO);
rt_sem_release(cfgUpdate); //上电更新值
updatecfg();
// LOG_D("sysSemInit DONE.");
}
static void sysEventInit(void)
{
rt_err_t result = rt_event_init(&chkSta, "chkSta", RT_IPC_FLAG_PRIO);
if (result != RT_EOK)
{
LOG_E("init event failed.\n");
}
}
void sysInit(void)
{
sysSemInit();
sysEventInit();
}
//INIT_COMPONENT_EXPORT(sysInit);
void timerIsReady(void)
{
rt_event_send(&sysInit, TIMER_IS_OUT);
}
void fileIsReady(void)
{
rt_event_send(&sysInit, FILE_IS_OK);
}
void TTIsReady(void)
{
rt_event_send(&sysInit, TT_IS_OK);
}
void d_upSta()
{
TTIsReady();
}
//extern void ttinfoInit(void);
//extern void startTTinfo(void);
/**
* 监控TT状态。需求条件1TT连续5个周期为激活状态且信号强度不低于5。
*/
void checkTT()
{
repGetTT(); //持续更新
}
typedef struct
{
char fname[60];
uint8_t index;
}FILE_INFO;
static void upSendFile_thread_entry(void *parameter)
{
FILE_INFO *f = RT_NULL;
f = (FILE_INFO *) parameter;
static rt_uint8_t d[10][200] = { };
static rt_uint8_t s[10] = { };
LOG_D("%s---%d",f->fname,f->index);
rt_uint8_t len = pack_File(f->fname, 0, d, s);
if (len)
{
LOG_D("%d pack(s) to send", f->index ? 1 : len);
for (size_t var = 0; var < len; var++)
{
if (!f->index || (var+1) == f->index)
{ //index=0 全发或者仅发index
sendMsg(d[var], s[var]);
LOG_D("send pack[%d] done.",var+1);
}
}
LOG_I("Done.");
}
}
/**
* 发送文件
* @param f 待发文件,指完整路径名
* @param index 指定发送的切片索引为0时表示全部发送
*/
void upSendFile(const char *f, int index)
{
static FILE_INFO info;
memset(&info, 0, sizeof(FILE_INFO));
strcpy(info.fname, f);
info.index = index;
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("upSendFile", upSendFile_thread_entry, (void *) &info, 1024 * 12, 27, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
LOG_E("thread 'upSendFile' create failure.");
return;
}
}
void d_upSendFile(int argc, char **argv)
{
int index=0;
if (argc == 3) {
index = atoi(argv[2]);
}
upSendFile(argv[1], index);
}
/**
* 获取本地待发文件列表并倒序发送
*/
void getAndSendFile()
{
int index[MAX_KEY_LEN];
char f[30][MAX_KEY_LEN];
size_t cnt = getFilesToSend(f, index);
LOG_I("%d files to be send");
for (size_t i = cnt-1; i > 0; i--)
{
upSendFile(f[i],index[i]);
}
}
static void chkAndSendFile_thread_entry()
{
while (1)
{
// int e;
LOG_I("等待文件就绪(或定时%d分钟超时",scfg.sendInterval);
int rst = rt_event_recv(&chkSta, FILE_IS_OK | TIMER_IS_OUT, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, RT_NULL);
if (rst == RT_EOK) //条件1满足
{
LOG_I("等待TT就绪");
}
for (size_t var = 0; var < scfg.maxTTRetryCnt; var++) //轮询尝试
{
LOG_I("第%d/%d次尝试。", var + 1,scfg.maxTTRetryCnt);
rst = rt_event_recv(&chkSta, TT_IS_OK, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, rt_tick_from_millisecond(scfg.maxTTWaitTime*60*1000),
RT_NULL);
// rst = rt_sem_take(TTReady, rt_tick_from_millisecond(maxTTWaitTime * 60 * 1000));
if (rst == RT_EOK) //条件2满足
{
LOG_I("TT准备就绪");
getAndSendFile();
break;
}
else if (rst == -RT_ETIMEOUT)//超时则重试
{
LOG_W("第%d次尝试中TT准备失败。", var + 1);
// pwTT_thread_entry("0");
rt_thread_mdelay(1000);
// checkTT();
// continue;
}
}
//continue;
//发送数据
//可能有多个待发文件,每个文件打包后为一个二维数组
//如果先打包后发送,需要三维数组,和大内存占用
//故改为“打包-发送”轮询操作
// upSendFile();
// LOG_I("----------------------------");
}
}
/**
* 检查状态并发送文件
*/
void chkAndSendFile()
{
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("chk&send", chkAndSendFile_thread_entry, RT_NULL, 1024 * 5, 24, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
LOG_E("thread 'chk&send' create failure.");
return;
}
}
//INIT_COMPONENT_EXPORT(smsg);
static rt_timer_t tmrToPNTT=RT_NULL;
static int isInWindow=0;//winow 关闭时复位
/**
* 关闭超时定时器定时时间到后关闭TT
*/
void stopTM()
{
if (!tmrToPNTT) {
return;
}
rt_timer_stop(tmrToPNTT);
rt_timer_stop(tmrToPNTT);
}
/**
* 重启超时定时器定时时间到后关闭TT
*/
void resetTM()
{
// LOG_D("try to reset");
if (tmrToPNTT == RT_NULL) {
return;
}
if (isInWindow) {
stopTM();
return;
}
rt_tick_t t= rt_tick_from_millisecond(scfg.timeout*60*1000);
rt_timer_control(tmrToPNTT, RT_TIMER_CTRL_SET_TIME,(void*) &t);
rt_timer_stop(tmrToPNTT);
rt_timer_start(tmrToPNTT);
// LOG_D("timer reseted.");
}
void d_getRemain()
{
LOG_D("=%d=",rt_tick_from_millisecond(10*60*1000));
rt_tick_t *arg1,*arg2;
arg1=rt_timer_control(tmrToPNTT, RT_TIMER_CTRL_GET_TIME, (void*)arg1);
arg2=rt_timer_control(tmrToPNTT, RT_TIMER_CTRL_GET_REMAIN_TIME, (void*)arg2);
LOG_D("tm=%d-%d",&arg1,&arg2);
}
/* 定时器超时函数 */
static void timeoutFunc(void *parameter)
{
// rt_kprintf("periodic timer is timeout %d\n", cnt);
// rt_timer_stop(timer1);
LOG_W("3s to shunt down TT");
rt_thread_mdelay(1000);
LOG_W("2s to shunt down TT");
rt_thread_mdelay(1000);
LOG_W("1s to shunt down TT");
rt_thread_mdelay(1000);
deInitTT();//Function[rt_mutex_take] shall not be used in ISR
// rt_sem_release(shuntDownTT);
// toPN =1;
}
//RT_TICK_PER_SECOND
//tcp连接保活
//实际场景不存在中间断掉的可能
void initTT_thread_entry()
{
pwTT_thread_entry("1");
while (1)
{
if (!tmrToPNTT) {
tmrToPNTT = rt_timer_create("TTtimeout", timeoutFunc,
RT_NULL, rt_tick_from_millisecond(scfg.timeout*60*1000),
RT_TIMER_FLAG_ONE_SHOT);//|RT_TIMER_FLAG_SOFT_TIMER);
// rt_timer_start(tmrToPNTT);
}
if (!isTTon()) {
break;
}
if (!isEthUP())
{ //只初始化一次
LOG_D("init eth...");
if (rt_hw_stm32_eth_init() == RT_EOK)
{
LOG_D("eth inited DONE.");
}; //激活网口
}
else if (!isTCPok()) //判断TCP连接是否正常异常自动重连
{
// LOG_W("TT server is not ready,--%d",isTCPok());
tcpInit();
// rt_thread_mdelay(1000);
if (isTCPok())
{
LOG_D("TCP is ready.");
tcpRecMQ(); //开启tcp接收线程
recTT();
}
}
rt_thread_mdelay(3000); //chk with 3 second interval
}
}
void deInitTT_thread_entry()
{
if (rt_sem_take(shuntDownTT, RT_WAITING_FOREVER) == RT_EOK)
// if (toPN)
{
pwTT_thread_entry("0");
rt_hw_stm32_eth_deinit(); //qu激活网口
if (tmrToPNTT)
{
rt_timer_delete(tmrToPNTT); //关闭倒计时
tmrToPNTT = RT_NULL;
}
tcpClose();
LOG_W("shunt down TT DONE");
// break;
}
// rt_thread_mdelay(1000);
// }
}
//INIT_APP_EXPORT(deInitTT_thread_entry);
/**
* TT上电初始化TT相关的网络、TCP等并保活
*/
void initTT()
{
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("initTT", initTT_thread_entry, RT_NULL, 1024 * 1.5, 20, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
LOG_E("thread 'initTT' create failure.");
return;
}
/* 创建 serial 线程 */
thread = rt_thread_create("deInitTT", deInitTT_thread_entry, RT_NULL, 1024 * 2, 19, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
LOG_E("thread 'deInitTT' create failure.");
return;
}
}
/**
* TT上电初始化TT相关的网络、TCP等并保活
*/
void deInitTT()
{
// /* 创建 serial 线程 */
// rt_thread_t thread = rt_thread_create("deInitTT", deInitTT_thread_entry, RT_NULL, 1024 * 2, 30, 10);
// /* 创建成功则启动线程 */
// if (thread != RT_NULL)
// {
// rt_thread_startup(thread);
// }
// else
// {
// LOG_E("thread 'initTT' create failure.");
// return;
// }
rt_sem_release(shuntDownTT);
}
//INIT_APP_EXPORT(deInitTT);
#define FUNC_DEMO
#ifdef FUNC_DEMO //测试时导出命令到控制台
MSH_CMD_EXPORT(d_upSta,FILE_IS_OK);
MSH_CMD_EXPORT(chkAndSendFile, chkAndSendFile);
MSH_CMD_EXPORT(upSendFile, upSendFile);
MSH_CMD_EXPORT(initTT,TT);
MSH_CMD_EXPORT(deInitTT,TT);
MSH_CMD_EXPORT(d_getRemain,d_getRemain);
MSH_CMD_EXPORT(d_upSendFile,d_upSendFile);
#endif