需求分件
配置文件如下:

我们现在让要程序能执行command列中的命令,即当某个按钮的状态发生变化时,它能去执行command中的脚本命令。
具体来说,这里当第一个名为led的按钮的状态发生变化时,它能去执行脚本led.sh
脚本文件led.sh
脚本文件led.sh的分析
#!/bin/sh
status=$1
if [ "$status" = "ok" ]
then
echo "led has been tested, it is ok"
fi
if [ "$status" = "err" ]
then
echo "led has been tested, it is fail"
fi
以下是对这个脚本文件的分析。
第一行代码#!/bin/sh
第一行 #!/bin/sh 称为 Shebang(或Sha-bang),它的作用是指明该脚本文件应该使用哪种解释器来执行。
具体解释:
-
#和!组成的标记:#!是特殊的标记,表示这是一个脚本文件的开头。
-
/bin/sh:- 指定了用
/bin/sh作为解释器来运行该脚本。 /bin/sh通常是指向 Bourne Shell 或其兼容版本(如 Dash)的符号链接。在多数现代 Linux 系统中,/bin/sh通常较轻量,用于运行简单脚本。
- 指定了用
-
作用:
- 当你运行这个脚本(例如通过
./led.sh ok),系统会根据#!/bin/sh找到/bin/sh程序,然后使用它来解释和执行脚本的内容。 - 如果没有这个 Shebang 标记,脚本可能无法正确执行,或需要明确指定解释器(例如
sh led.sh ok)。
- 当你运行这个脚本(例如通过
简而言之:#!/bin/sh 指定了该脚本应由 /bin/sh 解释器运行,是 Linux 脚本的标准开头,确保脚本能正确被系统识别和执行。
第二行代码status=$1【理解整个脚本文件功能的关键】
第二行代码 status=$1 的作用是将脚本运行时传递的第一个命令行参数赋值给变量 status。
详细说明:
-
$1:- 表示脚本运行时传递的第一个参数。
- 在 Shell 脚本中,
$1是一个 位置参数,代表命令行中的第一个参数。 - 其他位置参数包括
$2(第二个参数),$3(第三个参数),以此类推。
-
status=$1:- 将
$1的值赋给变量status。 status是一个普通的 Shell 变量,用于保存传递的参数值。
- 将
-
用法示例:
如果脚本led.sh是这样运行的:./led.sh ok$1的值为ok。- 变量
status被赋值为ok,后续脚本中的status都会使用这个值。
示例分析:
以脚本内容为例,运行:
./led.sh ok
status的值是ok,因此脚本会执行以下分支:if [ "$status" = "ok" ] then echo "led has been tested, it is ok" fi
如果运行:
./led.sh err
status的值是err,脚本会执行另一分支:if [ "$status" = "err" ] then echo "led has been tested, it is fail" fi
脚本文件上板运行
我们要想咱们的程序能执行这个脚本文件,先要测试下这个脚本文件自身是否能够运行…
将脚本文件放于NFS文件的目录support_command中
然后开发板上执行下面的运令:
cd /mnt/support_command
chmod +x led.sh
./led.sh ok
结果报下面的错:
-bash: /mnt/support_command/led.sh: /bin/sh^M: bad interpreter: No such file or directory
这是由于Linux和Windows下的换行格式不同造成的,具体的原因和转换方法见:https://blog.youkuaiyun.com/wenhao_ir/article/details/144856144
执行下面的命令进行转换:
dos2unix led.sh
然后再执行:
./led.sh ok

再执行
./led.sh err

这样就表示脚本文件led.sh没有问题了。
程序改进
其实就是对输入事件的处理,所以去修改page\main_page.c中的MainPageOnPressed()函数。
修改后的代码如下:
static int MainPageOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
unsigned int dwColor = BUTTON_DEFAULT_COLOR;
char name[100];
char status[100];
char *strButton;
char *command_status[3] = {"err", "ok", "percent"};
int command_status_index = 0;
char command[1000];
PItemCfg ptItemCfg;
strButton = ptButton->name;
/* 1. 对于触摸屏事件 */
if (ptInputEvent->iType == INPUT_TYPE_TOUCH && ptInputEvent->iPressure != 0)
{
/* 1.1 分辨能否被点击 */
if (GetItemCfgByName(ptButton->name)->bCanBeTouched == 0)
return -1;
/* 1.2 修改颜色 */
ptButton->status = !ptButton->status;
if (ptButton->status)
{
dwColor = BUTTON_PRESSED_COLOR;
command_status_index = 1;
}
}
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)
{
command_status_index = 1;
dwColor = BUTTON_PRESSED_COLOR;
}
else if (strcmp(status, "err") == 0)
{
command_status_index = 0;
dwColor = BUTTON_DEFAULT_COLOR;
}
else if (status[0] >= '0' && status[0] <= '9')
{
command_status_index = 2;
dwColor = BUTTON_PERCENT_COLOR;
strButton = status;
}
else
return -1;
}
else
{
return -1;
}
/* 绘制底色 */
DrawRegion(&ptButton->tRegion, dwColor);
/* 居中写文字 */
DrawTextInRegionCentral(strButton, &ptButton->tRegion, BUTTON_TEXT_COLOR);
/* flush to lcd/web */
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
/* 执行command */
ptItemCfg = GetItemCfgByName(ptButton->name);
if (ptItemCfg->command[0] != '\0')
{
sprintf(command, "%s %s", ptItemCfg->command, command_status[command_status_index]);
system(command);
}
return 0;
}
支持能运行command项中的脚本文件的相关流程如下:
首先定义一个字符串指针数组command_status:
char *command_status[3] = {"err", "ok", "percent"};
这里面存储的就是按钮的三种状态…当然前两个也可作为脚本文件led.sh的第1个参数。
然后对于触摸屏输入事件,当某个按钮的状态值为1时,则进行下面的操作:
if (ptButton->status)
{
dwColor = BUTTON_PRESSED_COLOR;
command_status_index = 1;
}
也就是说令command_status_index的值为1,即指向数组command_status中的"ok"
对于网络输入事件,区分三种情况,相关代码如下:
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)
{
command_status_index = 1;
dwColor = BUTTON_PRESSED_COLOR;
}
else if (strcmp(status, "err") == 0)
{
command_status_index = 0;
dwColor = BUTTON_DEFAULT_COLOR;
}
else if (status[0] >= '0' && status[0] <= '9')
{
command_status_index = 2;
dwColor = BUTTON_PERCENT_COLOR;
strButton = status;
}
else
return -1;
}
通过上面就确定了启动脚本时添加的参数是什么了。
然后就是把解析配置文件得到的命令行提取出来,并加上参数构造成一个完整的命令:
/* 执行command */
ptItemCfg = GetItemCfgByName(ptButton->name);
if (ptItemCfg->command[0] != '\0')
{
sprintf(command, "%s %s", ptItemCfg->command, command_status[command_status_index]);
system(command);
}
在这段代码中:
ptItemCfg = GetItemCfgByName(ptButton->name);
根据按钮名字将配置项取出。
然后利用函数sprintf构造出完整的命令行。
最后调用函数system运行构造出的命令行。
其实很简单…
交叉编译
源码复制进Ubuntu时,然后交叉编译
cd /home/book/mycode/C0016_improve_command
make
将生成的test文件重命名为 support_cmd_test
上板测试
准备好需要的文件和目录

:
先把配置文件复制到etc目录
【复制前请把用Notepad++转换成UNIX文件换行格式】
cp -ri /mnt/support_command/etc/* /etc/
如果没有事先用Notepad++转换成UNIX换行格式,可以用下面的命令操作:
dos2unix /mnt/support_command/etc/test_gui/gui.conf
进入有可执行程序的目录:
cd /mnt/support_command/
首先把自带的QT的GUI界面关掉【这次就必须关掉了,事实证明不关掉的话会影响后面的测试】:
/etc/init.d/S99myirhmi2 stop
然后把屏幕刷黑
./draw_lcd_black
然后运行咱们的业务系统的可执行程序【后台运行】
./support_cmd_test ./simsun.ttc &
当点击led按钮后,效果如下:

再点击一次,效果如下:

1593

被折叠的 条评论
为什么被折叠?



