【电子量产工具】6. 业务系统

简介: 【电子量产工具】6. 业务系统

前言

最近看了 电子量产工具 这个项目,本专栏是对该项目的一个总结。


一、业务系统分析

前面实现了各个子系统:显示、输入、文字、UI、页面,它们只是提供基础能力,跟业务逻辑没有关系。这样的架构很容易扩展,可以在这上面实现各种业务,对于不同的产品,我们只需要写出自己页面函数。

那么对于我们的带电子量产工具,是怎么设置 的主页面呢?

首先 观赏 最终实验效果:

可以看到在这个主界面上有很多按键,按键上有各自的名字。初始时,按键是红色,当点击按键时,变成绿色。只有一些按键可以通过点击改变颜色,有的可以通过网络输入改变颜色,甚至可以显示进度蓝色。

可以创建一个配置文件 来描述各个按键的特点:

我们编写 主页面代码时,需要先从配置文件中解析 出数据,再根据数据生成按钮。

当有事件发生时,就可以找到对应按钮,再 根据配置文案金的数据 执行相应的 点击函数。

二、处理配置文件

  1. 对于配置文件的每一行,都创建一个ItemCfg 结构体。(每一个按钮)
typedef struct ItemCfg {
  int index;
  char name[100];
  int bCanBeTouched;        // 是否可以被点击
  char command[100];        // 状态发生变化时 调用的命令
}ItemCfg, *PItemCfg;
  1. 解析配置文件。
int ParseConfigFile(void)
{
  FILE *fp;
  char buf[100];
  char *p = buf;
  /* 1. open config file */
  fp = fopen(CFG_FILE, "r");
  if (!fp)
  {
    printf("can not open cfg file %s\n", CFG_FILE);
    return -1;
  }
  while (fgets(buf, 100, fp))
  {
    /* 2.1 read each line */
    buf[99] = '\0';   
    /* 2.2 吃掉开头的空格或TAB */
    p = buf;
    while (*p == ' ' || *p =='\t')
      p++;
    /* 2.3 忽略注释 */
    if (*p == '#')
      continue;
    /* 2.4 处理 */
    g_tItemCfgs[g_iItemCfgCount].command[0] = '\0';
    g_tItemCfgs[g_iItemCfgCount].index = g_iItemCfgCount;
    sscanf(p, "%s %d %s", g_tItemCfgs[g_iItemCfgCount].name, &g_tItemCfgs[g_iItemCfgCount].bCanBeTouched, \
                          g_tItemCfgs[g_iItemCfgCount].command);
    g_iItemCfgCount++;    
  }
  return 0;
}
  1. 获取配置文件按键的数目。
int GetItemCfgCount(void)
{
  return g_iItemCfgCount;
}
  1. 根据 系数 和 名字 获取配置文件。
PItemCfg GetItemCfgByIndex(int index)
{
  if (index < g_iItemCfgCount)
    return &g_tItemCfgs[index];
  else
    return NULL;
}
PItemCfg GetItemCfgByName(char *name)
{
  int i;
  for (i = 0; i < g_iItemCfgCount; i++)
  {
    if (strcmp(name, g_tItemCfgs[i].name) == 0)
      return &g_tItemCfgs[i];
  }
  return NULL;
}

三、生成界面

  1. 之前 在 页面系统 中写的是 默认的按下函数
    对于按钮,我们要提供自己的OnPressed函数,不适用UI系统默认的函数,这里编写 main_page 按下函数。
static int MainPageOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
  unsigned int dwColor = BUTTON_DEFAULT_COLOR;
  char name[100];
  char status[100];
  char *strButton;
  strButton = ptButton->name;
  /* 1. 对于触摸屏事件 */
  if (ptInputEvent->iType == INPUT_TYPE_TOUCH)
  {
    /* 1.1 分辨能否被点击 */
    if (GetItemCfgByName(ptButton->name)->bCanBeTouched == 0)
      return -1;
    /* 1.2 修改颜色 */
    ptButton->status = !ptButton->status;
    if (ptButton->status)
      dwColor = BUTTON_PRESSED_COLOR;
  }
  else if (ptInputEvent->iType == INPUT_TYPE_NET)
  {
    /* 2. 对于网络事件 */
    /* 根据传入的字符串修改颜色 : wifi ok, wifi err, burn 70 */
    sscanf(ptInputEvent->str, "%s %s", name, status);
    if (strcmp(status, "ok") == 0)
      dwColor = BUTTON_PRESSED_COLOR;
    else if (strcmp(status, "err") == 0)
      dwColor = BUTTON_DEFAULT_COLOR;
    else if (status[0] >= '0' && status[0] <= '9')
    {     
      dwColor = BUTTON_PERCENT_COLOR;
      strButton = status;     
    }
    else
      return -1;
  }
  else
  {
    return -1;
  }
  /* 绘制底色 */
  DrawRegion(&ptButton->tRegion, dwColor);
  /* 居中写文字 */
  DrawTextInRegionCentral(strButton, &ptButton->tRegion, BUTTON_TEXT_COLOR);
  /* 刷新界面到 lcd/web */
  FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
  return 0;
}
  1. 根据配置文件生成按钮、界面:
static void GenerateButtons(void)
{
  int width, height;
  int n_per_line;
  int row, rows;
  int col;
  int n;
  PDispBuff pDispBuff;
  int xres, yres;
  int start_x, start_y;
  int pre_start_x, pre_start_y;
  PButton pButton;
  int i = 0;
  /* 算出单个按钮的width/height */
  g_tButtonCnt = n = GetItemCfgCount();
  pDispBuff = GetDisplayBuffer();
  xres = pDispBuff->iXres;
  yres = pDispBuff->iYres;
  width = sqrt(1.0/0.618 *xres * yres / n);
  n_per_line = xres / width + 1;
  width  = xres / n_per_line;
  height = 0.618 * width; 
  /* 居中显示:  计算每个按钮的region  */
  start_x = (xres - width * n_per_line) / 2;
  rows    = n / n_per_line;
  if (rows * n_per_line < n)
    rows++;
  start_y = (yres - rows*height)/2;
  /* 计算每个按钮的region */
  for (row = 0; (row < rows) && (i < n); row++)
  {
    pre_start_y = start_y + row * height;
    pre_start_x = start_x - width;
    for (col = 0; (col < n_per_line) && (i < n); col++)
    {
      pButton = &g_tButtons[i];
      pButton->tRegion.iLeftUpX = pre_start_x + width;
      pButton->tRegion.iLeftUpY = pre_start_y;
      pButton->tRegion.iWidth   = width - X_GAP;
      pButton->tRegion.iHeigh   = height - Y_GAP;
      pre_start_x = pButton->tRegion.iLeftUpX;
      /* InitButton */
      InitButton(pButton, GetItemCfgByIndex(i)->name, NULL, NULL, MainPageOnPressed);
      i++;
    }
  }
  /* OnDraw */
  for (i = 0; i < n; i++)
    g_tButtons[i].OnDraw(&g_tButtons[i], pDispBuff);
}

四、根据输入事件找到按钮

对于触摸屏事件,根据iX、iY找到按钮.

对于网络数据,我们限定为这样的格式:“name ok”、“name err”、“name 70%”根据name找到按钮.

/*  判断点击的位置  */
static int isTouchPointInRegion(int iX, int iY, PRegion ptRegion)
{
  if (iX < ptRegion->iLeftUpX || iX >= ptRegion->iLeftUpX + ptRegion->iWidth)
    return 0;
  if (iY < ptRegion->iLeftUpY || iY >= ptRegion->iLeftUpY + ptRegion->iHeigh)
    return 0;
  return 1;
}
/*  根据输入事件找到按钮  */
static PButton GetButtonByInputEvent(PInputEvent ptInputEvent)
{
  int i;
  char name[100];
  if (ptInputEvent->iType == INPUT_TYPE_TOUCH)
  {
    for (i = 0; i < g_tButtonCnt; i++)
    {
      if (isTouchPointInRegion(ptInputEvent->iX, ptInputEvent->iY, &g_tButtons[i].tRegion))
        return &g_tButtons[i];
    }
  }
  else if (ptInputEvent->iType == INPUT_TYPE_NET)
  {
    sscanf(ptInputEvent->str, "%s", name);
    return GetButtonByName(name);
  }
  else
  {
    return NULL;
  }
  return NULL;
}
  1. 重写 main_page.c 的 Run 函数。
static void MainPageRun(void *pParams)
{
  int error;
  InputEvent tInputEvent;
  PButton ptButton;
  PDispBuff ptDispBuff = GetDisplayBuffer();
  /* 读取配置文件 */
  error = ParseConfigFile();
  if (error)
    return ;
  /* 根据配置文件生成按钮、界面 */
  GenerateButtons();
  while (1)
  {
    /* 读取输入事件 */
    error = GetInputEvent(&tInputEvent);
    if (error)
      continue;
    /* 根据输入事件找到按钮 */
    ptButton = GetButtonByInputEvent(&tInputEvent);
    if (!ptButton)
      continue;
    /* 调用按钮的OnPressed函数 */
    ptButton->OnPressed(ptButton, ptDispBuff, &tInputEvent);
  }
}

五、业务系统总流程测试

测试效果:


总结

这个电子量产工具的项目就到这里结束了,后面继续推出 面试笔试的 新专栏,帮助大家避开 笔试的坑。

相关文章
|
监控 小程序 算法
原生小程序电子班牌系统 智慧校园云平台源码
智慧校园云平台电子班牌系统,集学生管理、班级管理、校园管理于一身,融合学校教务管理、教师管理、学籍管理、考勤、信息发布、班级文明建设、校园风采、家校互通等一系列应用,为校园管理现代化、信息化提供有效解决工具
141 3
【电子量产工具】5.页面系统
【电子量产工具】5.页面系统
65 0
|
编解码 中间件 Linux
【电子量产工具】1.显示系统
【电子量产工具】1.显示系统
111 0
|
监控 供应链 新能源
万界星空科技/免费开源MES系统/免费自动排产管理
万界星空科技MES系统通过快速合理安排有限产能计划,计划更优化,实现最优生产计划排程,提高生产效率和设备利用率,达到对生产现场进行有效指导。
343 0
万界星空科技/免费开源MES系统/免费自动排产管理
|
vr&ar
【电子量产工具】4. UI系统
【电子量产工具】4. UI系统
92 0
|
存储 UED
【电子量产工具】2.输入系统
【电子量产工具】2.输入系统
79 0
MetaX窖管家产品介绍-数字孪生酒窖测温(硬件+软件)
针对酒窖窖池的实时测温硬件,以及配套软件。
|
存储 消息中间件 缓存
医院HIS系统云平台源码,SaaS服务,融合B/S版电子病历系统,支持电子病历四级
云HIS系统有效实现医疗数据共享与交换,解决数据重复采集及信息孤岛等问题。重构管理服务流程,重建统一的信息架构体系,重造病人服务环境,向不同类型的医疗机构提供SaaS化HIS服务解决方案
263 0
医院HIS系统云平台源码,SaaS服务,融合B/S版电子病历系统,支持电子病历四级
|
供应链 监控 API
一个优秀的电子购物平台,需要那些业务系统支撑?
根据我国商务部的统计数据,2021年度我国电子商务平台的销售额占社会消费品零售总额的比重为24.5%,可以说电子商务已经完全渗透进了我们的日常生活,甚至可以说,网络购物对全球生活方式带来了巨大的改革,那么,我们要想搭建一个合格的购物平台的时候,要有哪些业务系统在支撑呢?今天我们就来细数现在的大型电商平台跨境电商平台背后的业务系统。
|
数据中心
智慧校园平台电子班牌系统源码 SaaS服务模式,数据统一平台
智慧校园系统是通过信息化手段,实现对校园内各类资源的有效集成 整合和优化,实现资源的有效配置和充分利用,将校务管理过程的优化协调。为校园提供数字化教学、数字化学习、数字化科研和数字化管理。 致力于为家长和教师提供一个全方位、多层次、高效率的校园教学、生活空间,全面打造校园全场景信息化服务,提供更加便捷的师生服务。
394 0
智慧校园平台电子班牌系统源码 SaaS服务模式,数据统一平台