智能家居-顶层实现
一.顶层整体逻辑
顶层直接与中间层之间进行业务往来,主要的工作就2个。
1).获取温度,亮度等传感器数据
2).下发风扇和灯的控制命令
顶层的了逻辑很简单,根据获取的温度判断风扇的开发,然后下发控制命令。根据亮度下发灯的开关命令。
二.数据结构组织
1.首先我们需要获取温度和亮度等数据,所以我们新建一个数据采集的结构体
typedef struct
{
int temprature; //温度
int bright; //亮度
int reserved[4]; //其它扩展传感器数据
} busi_sample_stru;
2.然后我们需要把控制风扇和灯的指令存入一个结构体,以便中间层按照指令执行
typedef struct
{
int fan_status; //风扇状态控制
int light_status; //灯状态控制
int reserved[4]; //其它控制
} busi_switch_stru;
3.建立模块与模块之间通讯用的结构体
typedef struct
{
SemaphoreHandle_t sem_req; //上层模块向下层模块请求数据的信号量
SemaphoreHandle_t sem_ack; //下层模块向上层模块应答的信号量
void *p_shared_mem; //上下层模块共用的内存块,上面两个结构体就是
int shared_mem_nbyte; //共享内存块的字节长度
} mmc_ctl_stru;
在该项目中,顶层会定义两组结构体:
(1)
busi_sample_stru busi_sample_values; //存储传感器数据的结构体
busi_switch_stru busi_switch_values; //存储控制命令的结构体
(2)
mmc_ctl_stru busi_sample_mmc_ctl; //顶层和中间层之间通讯传感器信息的结构体
mmc_ctl_stru busi_switch_mmc_ctl; //顶层和中间层之间通讯控制信息的结构体
三.模块之间通讯
1.模块间通讯的结构体初始化
void mmc_ctl_init(char *mmc_name,mmc_ctl_stru *p_mmc,void *psm,int sm_len)
//结构体之间通讯结构体的初始化
{
p_mmc->p_shared_mem = psm; //共享内存的指针指向对应的结构体
p_mmc->shared_mem_nbyte = sm_len; //共享数据的长度等于指向的结构体的大小
p_mmc->sem_req = xSemaphoreCreateBinary();//新建一个顶层向中间层请求数据的信号量
p_mmc->sem_ack = xSemaphoreCreateBinary();//新建一个中间层向顶层应答的信号量
memset(p_mmc->p_shared_mem,p_mmc->shared_mem_nbyte,0);
log_d("sem req&ack is created,shared mem called %s is initialized",mmc_name);
log_d("sem req&ack value:%08X %08X",p_mmc->sem_req,p_mmc->sem_ack);
elog_hexdump("req&ack",8,psm,sm_len);
}
//采样的mmc结构体的共享内存指针指向busi_sample_values
mmc_ctl_init("busi_sample_values",&busi_sample_mmc_ctl,&busi_sample_values,sizeof(busi_sample_values));
//控制的mmc结构体的共享内存指针指向busi_switch_mmc_ctl
mmc_ctl_init("busi_switch_values",&busi_switch_mmc_ctl,&busi_switch_values,sizeof(busi_switch_values));
2.模块间通讯函数
int mmc_ctl_requre(mmc_ctl_stru *p_mmc_ctl,int waittime)
{
xSemaphoreGive(p_mmc_ctl->sem_req); //requst of datablock via sem req
log_d("sem req is gived");
log_d("start waiting for sem ack");
if(xSemaphoreTake(p_mmc_ctl->sem_ack,waittime) == pdTRUE) //wait for sem ack success
{
log_d("shared memory is ready");
elog_hexdump("shared memory content",16,&p_mmc_ctl->p_shared_mem,p_mmc_ctl->shared_mem_nbyte); //log for shared memory raw data
return pdPASS;
}
else return pdFAIL;
}
顶层和中间层通讯其实就两步,1顶层向中间层发送请求,2中间层向顶层应答(在应答前,中间层把信息装填到共享内存块中,顶层读取共享内存块获取需要的数据)。有了这个函数以后,顶层模块只要向中间层发送两次请求,第一次:请求获取温度和亮度等数据 第二次:根据获取到的传感器数据,请求下发控制命令。而中间层在每次收到顶层的请求以后,都会往顶层定义的共享内存块中填入信息,第一次是温度和亮度等数据,第二次是风扇和灯当前的状态
//请求获取传感器数据
if(pdPASS == mmc_ctl_requre(&busi_sample_mmc_ctl,MMC_DELAY_TIME)) //requre for sample values
{
log_d("sample requre SUCCESS!");
log_i("temprature : %d , bright : %d , rsvd0 : %d , rsvd1 : %d , rsvd2 : %d , rsvd3 : %d ", \
busi_sample_values.temprature, \
busi_sample_values.bright, \
busi_sample_values.reserved[0], \
busi_sample_values.reserved[1], \
busi_sample_values.reserved[2], \
busi_sample_values.reserved[3] \
);
if(busi_sample_values.bright < BUSI_BRIGHT_DOWN_THRESHOLD) //current bright level is lowwer than down threshold
{
busi_switch_values.light_status = CONTROL_LIGHT_OPEN_STATUS;
log_w("bright level is too low,OPEN THE LIGHT!");
}
if(busi_sample_values.temprature < BUSI_TEMPRATURE_DOWN_THRESHOLD) //current bright level is lowwer than down threshold
{
busi_switch_values.fan_status = CONTROL_FAN_CLOSE_STATUS;
log_w("temprature is too low,CLOSE THE FAN!");
}
if(busi_sample_values.temprature > BUSI_TEMPRATURE_UP_THRESHOLD) //current bright level is higher than up threshold
{
busi_switch_values.fan_status = CONTROL_FAN_OPEN_STATUS;
log_w("temprature is too high,OPEN THE FAN!");
}
//请求下发风扇、灯等设备的控制命令
if(pdPASS == mmc_ctl_requre(&busi_switch_mmc_ctl,MMC_DELAY_TIME)) //requre for switch action and return status
{
log_d("switch requre SUCCESS!");
log_i("fan_status : %d , light_status : %d , rsvd0 : %d , rsvd1 : %d , rsvd2 : %d , rsvd3 : %d ", \
busi_switch_values.fan_status, \
busi_switch_values.light_status,\
busi_switch_values.reserved[0], \
busi_switch_values.reserved[1], \
busi_switch_values.reserved[2], \
busi_switch_values.reserved[3] \
);
}
else log_e("switch requre FAIL!");
}
else log_e("sample values requre FAIL!");
vTaskDelay(1000);
}
到这里为止,顶层的业务逻辑已经结束。