plant_manage/plan_manage_main/src/app/plan_handle.c

714 lines
17 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.

/*
* plan_handle.c - 计划处理模块
*
* 计划处理,指的是根据内存中的计划数据和时间数据得出输出数据,输出数据包括继电
* 器信号、植物属性值。
* 关于植物属性值,包括已完成计划周期次数,等。
* 基本原则是,起始周期时间区间加上重复周期数可以得到一个区间集合,判断当前时间
* 是否属于这个时间区间集合中的一个区间中的一个时间点。由此得到继电器信号,并在
* 继电器信号被置为无效的时候将计划周期次数加一。
* 需要解决的问题有,如何访问计划数据与时间数据,以及如何写入输出数据。
* 计划数据在tft.c模块属于静态数据如果要访问的话有两种方式一是声明计划
* 数据的类型并返回其整体地址,一个整体地址可以访问到所有的对象属性,不过需要知
* 道这个地址上数据的分布情况,需要额外的数据。二是根据每个元素的名字通过查询得
* 到其单独的值。
*/
#include <stdint.h>
#include "gpio.h"
#include "include/tft_plan_internal.h"
#include "include/plan_handle.h"
#include "include/tft.h"
#include "include/config.h"
#include "include/pm_flash.h"
#include "include/orient.h"
#include "include/key.h"
/*
* 计划输出数据类型定义
* is_reach表示是否到达计划执行时间
* note是一个字符串可以用来存储一些提示性字符
*/
typedef struct plan_output_
{
uint8_t is_reach;
uint8_t note[10];
} plan_output;
typedef enum lg_state_
{
LIGHT = 1, NO_LIGHT = 0
} lg_state;
/*
* 静态函数声明
*/
static void indata_to_outdata(plan_input *ind, plan_output *outd);
static void plan_ctr_exe(uint8_t activity);
static void plan_inpu_to_tft(void);
static void plan_key_func(void);
static void manul_key_func(void);
static void manul_ctr(void);
static void plan_ctr(void);
/*
* 输出和输入变量定义初始化全部为0
*/
static plan_output plan_out[OBJ_NUM] = { 0 };
plan_input plan_in[OBJ_NUM] = { 0 };
/**
* plan_handle_init() - 对计划处理模块进行初始化
*
* 主要包括IO初始化和计划数据的上电恢复工作
*/
void plan_handle_init(void)
{
gpio_init(LGRED_PINX, 1, NO_LIGHT);
gpio_init(LGBLUE_PINX, 1, NO_LIGHT);
gpio_init(LGUVB_PINX, 1, NO_LIGHT);
gpio_init(WATER_PINX, 1, 0);
gpio_init(LG1_PINX, 1, 1);
gpio_init(LG2_PINX, 1, 1);
gpio_init(LG3_PINX, 1, 1);
/*
* 数据恢复数据从从flash到plan_handle模块再从plan_handle模块到tft模块
*/
flash_read((uint8_t *)&plan_in, sizeof(plan_in));
plan_inpu_to_tft();
return;
}
/**
* indata_to_outdata() - 将一个植物输入的计划数据转换为对应的输出数据
* @ind: 计划输入数据的地址
* @outd: 转换后的值得地址
*
* 主要的功能是根据输入的数据得到是否到达计划执行时间,以及完成计划的次数
*/
static void indata_to_outdata(plan_input *ind, plan_output *outd)
{
// 首先得到系统时间并转换为日历时间格式
calendar_info st = get_system_time();
uint32_t sys_sec = calendar_to_sec(&st);
/*
* 因为在周期时间输入的时候没有输入年、月、秒的地方,所以将其初始化为起始值
* 以方便计算周期时间
*/
ind->pd_t.year = START_YEAR;
ind->pd_t.month = 1;
ind->pd_t.sec = 0;
uint32_t pd_sec = calendar_to_sec(&ind->pd_t);
/*
* 将第一次开始的时间加上周期时长乘以已完成次数,得到当前的开始时间;
* 结束时间的计算同开始时间。
* 由这两个时间可以得到当前执行计划的区间。
*/
uint32_t ctr_bg_sec = calendar_to_sec(&ind->bg_t) + pd_sec * ind->cnt;
uint32_t ctr_ed_sec = calendar_to_sec(&ind->ed_t) + pd_sec * ind->cnt;
// 比较系统时间是否在执行计划的区间
if (ctr_bg_sec < sys_sec && ctr_ed_sec > sys_sec)
{
outd->is_reach = 1;
}
else
{
if (outd->is_reach == 1)
{
/*
* 如果没有在执行区间,并且上一次在执行区间的话,表明一次计划执行完
* 成,给计划完成次数加一。
*/
ind->cnt++;
}
outd->is_reach = 0;
}
return;
}
/**
* plan_ctr_exe() - 计划控制的输出执行
* @activity: 表示执行哪一个计划活动一个活动编号对应一个植物当activity大于
* 植物的编号时,表示没有计划任务需要执行。
*
* 主要包括IO输出控制以及云台预置位控制
*/
static void plan_ctr_exe(uint8_t activity)
{
/*
* isnt_first数组是为了标记每一个活动在一次计划区间内是不是第一次执行主要
* 是因为不能频繁的多次调用云台的预置位
*/
static uint8_t isnt_first[OBJ_NUM] = { 0 };
if (activity >= OBJ_NUM)
{
// activity大于植物的编号的话代表没有计划任务需要执行
for (uint8_t i = 0; i < OBJ_NUM; i++)
{
isnt_first[i] = 0;
}
gpio_set(LGRED_PINX, NO_LIGHT);
gpio_set(LGBLUE_PINX, NO_LIGHT);
gpio_set(LGUVB_PINX, NO_LIGHT);
gpio_set(WATER_PINX, NO_LIGHT);
}
else
{
// 当activity对应于一个植物编号并且是第一次执行的时候就执行计划
if (isnt_first[activity] == 0)
{
orient_presetop(0, PRESET_CALL, activity + 1);
orient_presetop(1, PRESET_CALL, activity + 1);
gpio_set(LGRED_PINX, plan_in[activity].lg_r == 1 ? LIGHT : NO_LIGHT);
gpio_set(LGBLUE_PINX, plan_in[activity].lg_b == 1 ? LIGHT : NO_LIGHT);
gpio_set(LGUVB_PINX, plan_in[activity].lg_uvb == 1 ? LIGHT : NO_LIGHT);
gpio_set(WATER_PINX, plan_in[activity].water == 1 ? LIGHT : NO_LIGHT);
isnt_first[activity] = 1;
}
}
return;
}
/**
* plan_ctr() - 计划控制
*
* 完成从计划数据到输出执行的功能。
*/
void plan_ctr(void)
{
// 首先初始化活动不为任意一个植物编号
uint8_t activity = OBJ_NUM;
// 依次遍历每一个植物,得到需要执行的活动号,即对应的植物编号
for (uint8_t i = 0; i < OBJ_NUM; i++)
{
indata_to_outdata(&plan_in[i], &plan_out[i]);
if (plan_in[i].sw == 1)
{
if (plan_out[i].is_reach == 1)
{
activity = i;
break;
}
}
}
plan_ctr_exe(activity);
return;
}
/**
* plan_handle() - 计划处理
*
* 完成计划模式的数据处理及输出功能,手动模式下因为简单不需要复杂的数据运算,
* 此处处理为空,直接在其输入部分执行
*/
void plan_handle(void)
{
if (gpio_get(AMS_KEY_PINX))
{
plan_ctr();
}
else
{
manul_ctr();
}
return;
}
/**
* key_func() - 完成手动和自动模式下的按键输入功能
*
* 在自动模式下只是数据的输入,在手动模式在包括数据的输入和对应的输出执行部分。
*/
void key_func(void)
{
if (gpio_get(AMS_KEY_PINX))
{
plan_key_func();
}
else
{
manul_key_func();
}
return;
}
/**
* manul_ctr() - 手动控制部分
*
* 为空函数
*/
void manul_ctr(void)
{
return;
}
/**
* tft_to_plan_input() - 将tft显示的数据提取到计划处理的输入数据结构中
* @objn: 提取的对象号0~7
*
* 这个函数应该在tft输入有改变是被调用。
*/
void tft_to_plan_input(uint8_t objn)
{
plan_in[objn].bg_t.year = *get_value_of_kvp("bg_y", objn);
plan_in[objn].bg_t.month = *get_value_of_kvp("bg_mo", objn);
plan_in[objn].bg_t.mday = *get_value_of_kvp("bg_d", objn);
plan_in[objn].bg_t.hour = *get_value_of_kvp("bg_h", objn);
plan_in[objn].bg_t.min = *get_value_of_kvp("bg_mi", objn);
plan_in[objn].bg_t.sec = 0;
/*
* 结束时间在tft条目没有年、月、日赋值为和开始时间相同
*/
plan_in[objn].ed_t.year = plan_in[objn].bg_t.year;
plan_in[objn].ed_t.month = plan_in[objn].bg_t.month;
plan_in[objn].ed_t.mday = plan_in[objn].bg_t.mday;
plan_in[objn].ed_t.hour = *get_value_of_kvp("ed_h", objn);
plan_in[objn].ed_t.min = *get_value_of_kvp("ed_mi", objn);
plan_in[objn].ed_t.sec = 0;
plan_in[objn].pd_t.mday = *get_value_of_kvp("pd_d", objn);
plan_in[objn].pd_t.hour = *get_value_of_kvp("pd_h", objn);
plan_in[objn].pd_t.min = *get_value_of_kvp("pd_mi", objn);
plan_in[objn].lg_r = *get_value_of_kvp("lg_r", objn);
plan_in[objn].lg_b = *get_value_of_kvp("lg_b", objn);
plan_in[objn].lg_uvb = *get_value_of_kvp("lg_uvb", objn);
plan_in[objn].water = *get_value_of_kvp("water", objn);
plan_in[objn].sw = *get_value_of_kvp("sw", objn);
plan_in[objn].cnt = *get_value_of_kvp("cnt", objn);
return;
}
/*
* plan_inpu_to_tft() - 计划数据到tft
*
* 这个函数是为了在初始化时将从flash中恢复的计划数据重新装入tft
*/
static void plan_inpu_to_tft(void)
{
for(uint8_t objn = 0; objn < 8; objn++)
{
*get_value_of_kvp("bg_y", objn) = plan_in[objn].bg_t.year;
*get_value_of_kvp("bg_mo", objn) = plan_in[objn].bg_t.month;
*get_value_of_kvp("bg_d", objn) = plan_in[objn].bg_t.mday;
*get_value_of_kvp("bg_h", objn) = plan_in[objn].bg_t.hour;
*get_value_of_kvp("bg_mi", objn) = plan_in[objn].bg_t.min;
/*
* 结束时间在tft条目没有年、月、日
* *get_value_of_kvp("ed_y", objn) = plan_in[objn].ed_t.year;
* *get_value_of_kvp("ed_mo", objn) = plan_in[objn].ed_t.month;
* *get_value_of_kvp("ed_d", objn) = plan_in[objn].ed_t.mday;
*/
*get_value_of_kvp("ed_h", objn) = plan_in[objn].ed_t.hour;
*get_value_of_kvp("ed_mi", objn) = plan_in[objn].ed_t.min;
*get_value_of_kvp("pd_d", objn) = plan_in[objn].pd_t.mday;
*get_value_of_kvp("pd_h", objn) = plan_in[objn].pd_t.hour;
*get_value_of_kvp("pd_mi", objn) = plan_in[objn].pd_t.min;
*get_value_of_kvp("lg_r", objn) = plan_in[objn].lg_r;
*get_value_of_kvp("lg_b", objn) = plan_in[objn].lg_b;
*get_value_of_kvp("lg_uvb", objn) = plan_in[objn].lg_uvb;
*get_value_of_kvp("water", objn) = plan_in[objn].water;
*get_value_of_kvp("sw", objn) = plan_in[objn].sw;
*get_value_of_kvp("cnt", objn) = plan_in[objn].cnt;
}
return;
}
/**
* plan_key_func() - 计划模式下按键的处理
*
* 主要和tft显示屏关
*/
static void plan_key_func(void)
{
/*
* 按键功能注册部分
*/
switch (get_key_mean(UP_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 单击\n");
#endif /* PM_DEBUG */
tft_left();
break;
case D_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 双击\n");
#endif /* PM_DEBUG */
tft_up();
break;
case L_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(DOWN_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 单击\n");
#endif /* PM_DEBUG */
tft_right();
break;
case D_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 双击\n");
#endif /* PM_DEBUG */
tft_down();
break;
case L_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(OK_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 单击\n");
tft_ok();
#endif /* PM_DEBUG */
break;
case D_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(RET_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 单击\n");
#endif /* PM_DEBUG */
tft_ret();
break;
case D_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MR_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 单击\n");
#endif /* PM_DEBUG */
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MB_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 单击\n");
#endif /* PM_DEBUG */
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MUVB_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 单击\n");
#endif /* PM_DEBUG */
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
return;
}
/**
* manul_key_func() - 手动模式下的按键功能
*
* 包括了按键的输入和对应的输出执行部分
*/
static void manul_key_func(void)
{
/*
* 按键功能注册部分
*/
static uint8_t mlgr, mlgb, mlguvb;
switch (get_key_mean(UP_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 单击\n");
#endif /* PM_DEBUG */
orient_setspeed(0, ORIENT_LEFT, 100);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 双击\n");
#endif /* PM_DEBUG */
orient_setspeed(0, ORIENT_RIGHT, 100);
break;
case L_KEY:
#ifdef PM_DEBUG
printf("UP_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(DOWN_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 单击\n");
#endif /* PM_DEBUG */
orient_setspeed(1, ORIENT_LEFT, 100);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 双击\n");
#endif /* PM_DEBUG */
orient_setspeed(1, ORIENT_RIGHT, 100);
break;
case L_KEY:
#ifdef PM_DEBUG
printf("DOWN_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(OK_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 单击\n");
#endif /* PM_DEBUG */
break;
case D_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("OK_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(RET_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 单击\n");
#endif /* PM_DEBUG */
orient_setmode(0, MODE_MANUL);
orient_setmode(1, MODE_MANUL);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("RET_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MR_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 单击\n");
#endif /* PM_DEBUG */
mlgr = !mlgr;
gpio_set(LGRED_PINX, mlgr == 1 ? LIGHT : NO_LIGHT);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MR_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MB_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 单击\n");
#endif /* PM_DEBUG */
mlgb = !mlgb;
gpio_set(LGBLUE_PINX, mlgb == 1 ? LIGHT : NO_LIGHT);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MB_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
switch (get_key_mean(MUVB_KEY))
{
case N_KEY:
//printf("无键\n");
break;
case S_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 单击\n");
#endif /* PM_DEBUG */
mlguvb = !mlguvb;
gpio_set(LGUVB_PINX, mlguvb == 1 ? LIGHT : NO_LIGHT);
break;
case D_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 双击\n");
#endif /* PM_DEBUG */
break;
case L_KEY:
#ifdef PM_DEBUG
printf("MUVB_KEY 长按\n");
#endif /* PM_DEBUG */
break;
default:
break;
}
return;
}