恒温器模拟与NQBP构建系统详解
1. 目标板连接与功能模拟
目标板通过USB供电,同时该USB连接还为PC与目标板的通信提供了串行UART接口,此UART连接用于应用程序的命令行界面(CLI)。
要运行功能模拟器,只需构建模拟器并执行输出映像,应用程序的命令行界面通过标准输入输出(STDIO)运行。
2. 命令行界面(CLI)
对于在目标硬件上运行的恒温器示例或作为模拟器运行时,CLI的操作大多相同,仅存在一些特定于目标平台的CLI命令。例如,
threads
命令在不同目标平台上的行为不同。
2.1 CLI基本帮助
CLI有一个
help
命令,不带参数使用
help
会显示支持的命令的简短列表,输入
help *
或
help <cmd>
则提供详细的帮助信息。可以通过运行
thermostat - simulation.exe
程序进入CLI。以下是一些常见命令示例:
bye [app [<exitcode>]]
dm ls [<filter>]
dm write {<mp-json>}
dm read <mpname>
filter
filter clear|ack
filter set <numhours>
help [* | <cmd>]
house [<odt>]
house enable <odt>
house disable <idt>
log
log enable <fname>
log disable
state [usarlct]
threads
tprint [<text>]
trace [on|off]
trace section (on|off) <sect1> [<sect2>]...
trace threadfilters [<threadname1> [<threadname2>]]...
trace level (none|brief|info|verbose|max)
trace here|revert
user mode eOFF|eCOOLING|eHEATING|eAUTO|eID_HEATING
user fan eAUTO|eCONTINUOUS
user setpt <cool> <heat>
wb
wb enot enable|disable
wb acc true|false
2.2 CLI运行制冷模式
以下是运行恒温器制冷操作的命令序列:
| 步骤 | 命令 | 描述 |
| ---- | ---- | ---- |
| 1 | state | 显示恒温器的当前状态 |
| 2 | house enable 95 | 启用房屋模拟器,模拟室外温度为95°F(范围 -20°F 到 120°F) |
| 3 | user setpt 70 60 | 配置恒温器的制冷和制热设定点分别为70°F和60°F(制冷设定点范围55°F到95°F,制热设定点范围5°F到90°F,且制热设定点必须小于制冷设定点) |
| 4 | user mode eAUTO | 将恒温器的制热或制冷模式设置为自动 |
| 5 | user fan eAUTO | 将恒温器的风扇运行模式设置为自动 |
| 6 | state | 显示恒温器的更新状态 |
| 7 | 等待30秒 | 让PID算法确定是否需要主动制冷 |
| 8 | wb enot disable | 对于白盒测试,暂时禁用最小关闭时间,使设备立即开启 |
| 9 | state | 显示恒温器的更新状态,此时系统正在积极制冷 |
以下是一个示例会话:
--- Your friendly neighborhood TShell. ---
$$$ state
ThermostatMode=eAUTO, FanMode=eAUTO, CoolSetpt=70.00, HeatSetpt=60.00,
idt=75.00, odt=<n/a>
SystemOn=off, OpMode=eCOOLING, Idu=eFURNACE, Odu=eAC, IduStages=0,
OduStages=1, force=0
g=off, bk=0, w1=off, w2=off, w3=off, y1=off, y2=off, o=COOL
pv=90.00, error=5.00, sum=150.00, pvInhibit=no, freezeCnt=0, inhibitCnt=0
IdtSensorAlarm: pri=no, sec=no, priAck=no, secAck=no, critical=no
NoActiveConditioningAlarm: active=no, ack=no, critical=no
UserCfgModeAlarm: active=no, ack=no, critical=no
$$$ house enable 95
Cmd simulator ENABLED.
$$$ user setpt 70 60
CoolSetpt=70.00, HeatSetpt=60.00
$$$ user mode eAUTO
New thermostat mode = eAUTO
$$$ user fan eAUTO
New fan mode = eAUTO
$$$ state
ThermostatMode=eAUTO, FanMode=eAUTO, CoolSetpt=70.00, HeatSetpt=60.00,
idt=75.00, odt=95.00
SystemOn=off, OpMode=eCOOLING, Idu=eFURNACE, Odu=eAC, IduStages=0, OduStages=1,
force=0
g=off, bk=0, w1=off, w2=off, w3=off, y1=off, y2=off, o=COOL
pv=90.50, error=5.00, sum=155.00, pvInhibit=no, freezeCnt=0, inhibitCnt=0
IdtSensorAlarm: pri=no, sec=no, priAck=no, secAck=no, critical=no
NoActiveConditioningAlarm: active=no, ack=no, critical=no
UserCfgModeAlarm: active=no, ack=no, critical=no
AirFilterAlert: active=no, ack=no, critical=no
Cycle=eOFF, BeginOn=00:00:00.000, TimeOn=0, BeginOff=00:00:00.000, TimeOff=0
Outdoor: BeginOn=00:00:00.000, BeginOff=00:00:00.008
Indoor: BeginOn=00:00:00.000, BeginOff=00:00:00.008
System: BeginOn=00:00:00.000, BeginOff=00:00:00.008
00 00:01:00.095
$$$ wb enot disable
enot = DISABLED (Equip Min Off Time)
$$$ state
ThermostatMode=eAUTO, FanMode=eAUTO, CoolSetpt=70.00, HeatSetpt=60.00,
idt=70.10, odt=95.00
SystemOn=ON, OpMode=eCOOLING, Idu=eFURNACE, Odu=eAC, IduStages=0, OduStages=1,
force=0
g=ON, bk=100, w1=off, w2=off, w3=off, y1=ON, y2=off, o=COOL
pv=17.16, error=0.10, sum=156.30, pvInhibit=no, freezeCnt=0, inhibitCnt=0
IdtSensorAlarm: pri=no, sec=no, priAck=no, secAck=no, critical=no
NoActiveConditioningAlarm: active=no, ack=no, critical=no
UserCfgModeAlarm: active=no, ack=no, critical=no
AirFilterAlert: active=no, ack=no, critical=no
Cycle=eON_CYCLE, BeginOn=00:01:22.008, TimeOn=362, BeginOff=00:00:00.000,
TimeOff=0
Outdoor: BeginOn=00:01:22.008, BeginOff=00:00:00.008
Indoor: BeginOn=00:00:00.000, BeginOff=00:00:00.008
System: BeginOn=00:01:22.008, BeginOff=00:00:00.008
00 00:01:28.813
3. 文档资料
更多文档的起始点是PIM仓库中的
top/start_here.html
文件,这是一个TiddlyWiki文件,包含了各种详细信息,如需求、软件架构、软件开发计划等。
top/
目录中的
run_doxygen.py
脚本可用于对
src/
树中的所有源代码运行Doxygen,其输出将放置在顶级
docs/
目录下。运行该脚本的前提条件如下:
- Python 3.6+
- Doxygen,版本1.8.15或更高,其可执行文件的位置需包含在Windows命令路径中(参考:www.doxygen.nl/index.html)
- Graphviz,版本2.38.0或更高,其可执行文件的位置必须包含在Windows命令路径中(参考:https://graphviz.org/)
- Microsoft帮助编译器,其位置需包含在Windows命令路径中,
run_doxygen.py
脚本会从一组网页生成单个Microsoft帮助文件,该帮助文件除了是单个文件外,还支持在源代码注释中搜索文本(下载地址:www.microsoft.com/en - us/download/details.aspx?id=21138)
4. 关于NQBP
NQBP是一个基于Python的构建引擎,全称为Not Quite Benv–Python。其主要特点包括:
- 在现有目录中添加新文件无需额外努力。
- 向构建中添加新的源目录,只需将新目录的名称和路径作为单行条目添加到单个文件中。
- 支持Windows和Linux主机平台。
- 无需处理makefile。
更详细的特点如下:
- 用于C、C++和汇编构建的多主机构建引擎。
- 专门针对嵌入式开发。
- 速度快。
- 基于命令行。
- 支持多种编译器工具链。
- 源代码可重用,即NQBP假设代码将在多个项目中共享。
- 编译器工具链可重用,特定的编译器工具链创建或定义后,可在无限数量的项目中重用。
- 在中小型项目中非常有效。
NQBP不是基于make的构建引擎,它不进行依赖检查,对于超过100,000行代码的大型项目不是最佳选择。
5. 安装NQBP
NQBP在PIM仓库中基本已预安装,其底层Python脚本位于
xsrc/nqbp
目录树中。NQBP依赖于通过
env.bat
和
env.sh
脚本设置的特定环境变量,这些变量如下表所示:
| 变量 | 描述 |
| ---- | ---- |
| NQBP_BIN | NQBP包所在根目录的完整路径 |
| NQBP_PKG_ROOT | 正在积极处理的包的完整路径,对于恒温器示例,这是PC上PIM仓库的根目录 |
| NQBP_WORK_ROOT | 包含一个或多个正在开发的包的目录的完整路径,对于PIM仓库,这是NQBP_PKG_ROOT的父目录 |
| NQBP_XPKGS_ROOT | 包含外部或第三方源代码的根目录的完整路径,对于PIM仓库,这是NQBP_PKG_ROOT/xsrc目录 |
| NQBP_XPKG_MODEL | 构建脚本引用外部或第三方源代码的模式,对于PIM仓库,此变量的值为mixed。如果在项目中重用NQBP,通常不设置此变量或设置为legacy,该变量用于支持在Outcast开发模型下进行构建 |
6. NQBP的使用
NQBP将构建目录与源代码目录分开,并进一步将构建目录分为两个类别:单元测试(
tests/
目录)和应用程序(
projects/
目录)。NQBP构建脚本只有在这两个目录之一中执行才有效,是否同时拥有这两个目录可自行选择。以下是使用传统或混合外部包模型时的目录结构:
<NQBP_WORK_ROOT>
└───<NQBP_PKG_ROOT> ; Typically this is the root of your SCM repo
├───<abc>
├───projects ; Build applications/released images
├───<xyz>
├───src ; Source code directory
├───tests ; Build unit tests
└───<NQBP_XPKGS_ROOT> ; recommended name for this directory is 'xsrc'
7. NQBP构建模型
NQBP的默认构建行为是始终进行干净构建,即删除所有先前构建的文件,然后构建所有源代码。对于小型项目,这种全量构建范式实际上比使用makefile检查所有头文件依赖并仅构建有更改的部分更快,但随着项目规模的增加,这种情况将不再适用。不过,NQBP提供了许多命令行选项来进行选择性构建,例如仅构建单个文件、单个目录或一组目录等。建议如果只更改了
.c
、
.cpp
、
.s
或
.asm
文件,进行选择性构建;如果更改了头文件,直接构建所有内容会更简单。
8. NQBP目标文件与库
NQBP编译目录时,会将所有目标文件放入为每个构建目录创建的库文件中,但不会为构建目录(即运行
nqbp.py
脚本的目录)中的对象创建库文件。在链接阶段,它将可执行映像与构建目录中的目标文件以及编译阶段创建的各个库进行链接,这样的好处是只将应用程序使用的特定目录中的代码包含进来,而不是将整个目录的所有目标文件都包含到应用程序中。不过,构建目录中的所有目标文件始终会被链接到应用程序中。
例如,如果应用程序使用了
Cpl::Container::Dictionary
类,但不使用
Cpl::Container
命名空间中的其他类,编译时NQBP构建脚本会编译整个
Cpl/Container
目录,但链接时,应用程序只会从库中链接
Cpl::Container::Dictionary
的目标代码。
这种方法的一个缺点是,如果应用程序代码中没有对放置在库中的目标文件中的变量或函数的引用,那么该变量或函数将不会被链接。例如:
- C/C++运行时代码,如复位中断发生时执行的代码(微控制器的向量表),应用程序没有对向量表中条目的显式函数调用,向量表通常由链接器脚本放置在RAM的特定位置。
- 自注册(与容器一起)的C++模块,例如Catch2单元测试,每个Catch2测试用例都会向测试运行器自注册,运行时测试运行器会遍历测试列表来执行各个测试。
NQBP提供了
.firstobjs
和
.lastobjs
参数机制,可在链接目录库的基础上,显式强制链接任意一组目标文件。直接链接目标文件时,这些目标文件将无条件包含在最终映像中。示例可参考
tests/Storm/Component/_0test/linux/gcc/mytoolchain.py
文件。
9. NQBP构建变体
NQBP支持构建变体的概念,即相同的基本代码集可以针对不同目标进行编译和链接。例如,使用MinGW编译器对
Cpl::Dm
命名空间进行自动化单元测试时有三个构建变体:
- win32:使用原生Win32 API进行线程处理的32位应用程序构建。
- win64:使用原生Win32 API进行线程处理的64位应用程序构建。
- cpp11:使用C++11线程接口的64位应用程序构建。
每个构建变体可以独立构建,即构建变体A不会删除变体B的最终输出文件,但会删除中间的目标文件和库文件。NQBP不将调试构建视为构建变体,这意味着启用或禁用调试构建会覆盖先前构建变体的最终输出文件。
10. NQBP构建脚本
NQBP使用的一些Python脚本在项目间是通用的,而另一些则特定于单个项目。完整构建脚本的主要组件如下表所示:
| 组件 | 描述 |
| ---- | ---- |
|
.py | 该脚本包含使用特定编译器构建特定输出集所需的编译器和链接器脚本命令、选项、配置等。创建编译器工具链后,可在无限数量的项目中重用。这些脚本位于
nqbp/nqbplib/toolchains
目录下。如果使用NQBP当前不支持的编译器,需要创建编译器工具链脚本,具体方法可参考
nqbp/top/start_here.html
文件 |
| nqbp.py | 用于执行构建,每个构建目录必须放置一个该脚本的副本,其内容最少,主要调用
nqbp/nqbplib
目录中的脚本进行实际构建 |
| mytoolchain.py | 用于指定使用哪个编译器工具链,并为引用的编译器工具链提供特定于项目的自定义设置。每个构建目录都需要有一个
mytoolchain.py
文件 |
| libdirs.b | 用于指定要构建的目录,每个构建目录都需要有一个
libdirs.b
文件 |
| sources.b | 可选文件,使用时指定给定目录中要构建的
.c
、
.cpp
、
.asm
或
.s
文件。默认情况下,NQBP会构建
libdirs.b
文件指定的目录或构建目录本身中找到的所有
.c
、
.cpp
、
.asm
或
.s
文件 |
11. 使用NQBP选择构建内容
选择要构建的文件的主要机制是构建目录中的
libdirs.b
文件和源目录中可选的
sources.b
文件。
sources.b
文件仅包含文件名,每行一个;
libdirs.b
文件包含目录名,每行一个,用于指定要编译和链接的目录,其具有以下额外的语法和语义:
- 目录相对于
NQBP_PKG_ROOT
目录引用。
- 文件中的条目可以引用
projects/
或
tests/
目录树中的另一个
libdirs.b
文件,语法是在
libdirs.b
文件中使用相对目录路径限定符进行引用。
- 空行或以
#
开头的行将被忽略。
- 可以使用前后带
$
字符的环境引用变量来标识目录或部分目录路径。
- 以方括号
[ ]
括起来的
<build - variant>
开头的条目,只有在
<build - variant>
与调用NQBP时指定的构建变体匹配时才会被编译。
- 方括号内可以使用可选的管道符号
|
来包含多个变体,例如
[arm7|arm9]
。
- 未指定变体前缀的条目将为所有变体编译。
- 条目可以指定一个可选的尾随源文件列表,用于指定要从构建中排除的文件或仅包含在构建中的文件,小于号
<
用于指定仅构建的文件列表,大于号
>
用于指定排除的文件列表。
以下是
libdirs.b
文件中可以包含的一些行的示例:
# Build the src/foo directory in my package
src/foo
# Build the src/foo directory but do NOT build the hello.c
# and world.cpp files
src/foo > hello.c world.cpp
# Build the src/foo directory but ONLY build the hello.c
# and world.cpp files
src/foobar < hello.c world.cpp
# Build the third-party module Uncle under the xsrc/ directory
xsrc/Uncle/src
综上所述,通过对恒温器模拟的CLI操作以及NQBP构建系统的详细介绍,我们可以更高效地进行恒温器项目的开发和构建。无论是对恒温器功能的测试,还是利用NQBP进行代码的编译和链接,都能依据这些方法和规则顺利开展工作。同时,相关文档的获取和环境变量的设置也为项目的进一步拓展和维护提供了有力支持。
恒温器模拟与NQBP构建系统详解(续)
12. 恒温器模拟与NQBP构建的关联
恒温器模拟通过CLI进行各种操作,如设置模式、温度等,而NQBP构建系统则为恒温器模拟的代码提供了编译、链接等构建支持。两者紧密结合,使得恒温器项目的开发更加高效和有序。
例如,在进行恒温器制冷模式测试时,我们使用CLI输入一系列命令来模拟实际的制冷过程。而这些CLI命令背后的代码,需要通过NQBP构建系统进行编译和链接,生成可执行文件,才能在目标硬件或模拟器上运行。
13. 恒温器模拟的实际应用场景
恒温器模拟在实际应用中有很多场景,比如智能家居系统中,通过模拟不同的环境温度和用户设置,来测试恒温器的性能和稳定性。
在数据中心中,恒温器模拟可以帮助管理员提前规划和调整空调系统的运行,以确保服务器的稳定运行。通过CLI命令,我们可以方便地模拟不同的温度和模式,观察恒温器的响应和控制效果。
14. NQBP构建系统的优势总结
- 高效性 :对于中小型项目,NQBP的全量构建范式在速度上具有优势,而且提供了选择性构建的选项,让开发者可以根据实际情况灵活选择构建方式。
- 可重用性 :源代码和编译器工具链的可重用性,使得项目之间可以共享代码和工具链,减少了开发成本和时间。
- 跨平台支持 :支持Windows和Linux主机平台,方便不同操作系统的开发者使用。
- 目录结构清晰 :将构建目录与源代码目录分开,并且进一步细分单元测试和应用程序目录,使得项目结构更加清晰,易于管理。
15. 使用NQBP的最佳实践
-
合理设置环境变量
:在安装NQBP时,正确设置环境变量是确保构建系统正常运行的关键。根据项目的实际情况,合理配置
NQBP_BIN、NQBP_PKG_ROOT等变量。 -
灵活使用
libdirs.b和sources.b文件 :通过libdirs.b文件指定要构建的目录,使用sources.b文件选择要构建的文件,根据项目的需求进行灵活配置。 - 利用构建变体 :对于不同的目标平台和需求,使用NQBP的构建变体功能,分别进行编译和链接,提高代码的兼容性和可维护性。
16. 恒温器模拟与NQBP构建的未来发展趋势
随着智能家居和物联网技术的不断发展,恒温器模拟的功能将越来越强大,对构建系统的要求也会越来越高。NQBP构建系统可能会在以下方面进行改进和发展:
-
支持更多的编译器和平台
:随着新的编译器和平台的出现,NQBP可能会扩展其支持范围,以满足不同开发者的需求。
-
增强自动化构建功能
:进一步提高构建的自动化程度,减少开发者的手动操作,提高开发效率。
-
与其他开发工具的集成
:与更多的开发工具进行集成,如版本控制系统、调试工具等,形成一个更加完整的开发环境。
17. 总结
本文详细介绍了恒温器模拟的CLI操作和NQBP构建系统的相关知识。从目标板连接、功能模拟,到CLI基本帮助和制冷模式运行,我们了解了如何通过CLI对恒温器进行模拟测试。同时,对NQBP构建系统的特点、安装、使用、构建模型、目标文件与库、构建变体、构建脚本以及选择构建内容等方面进行了深入探讨。
恒温器模拟和NQBP构建系统相互配合,为恒温器项目的开发提供了有力的支持。开发者可以根据本文提供的信息和最佳实践,更加高效地进行恒温器项目的开发和维护。在未来,随着技术的不断发展,恒温器模拟和NQBP构建系统也将不断完善和发展,为智能家居和物联网领域的发展做出更大的贡献。
以下是一个简单的流程图,展示了恒温器模拟和NQBP构建的整体流程:
graph LR
A[开始] --> B[恒温器代码编写]
B --> C[NQBP构建]
C --> D[生成可执行文件]
D --> E[恒温器模拟(CLI操作)]
E --> F[测试结果评估]
F --> G{是否通过测试}
G -- 是 --> H[项目发布]
G -- 否 --> B
通过这个流程图,我们可以清晰地看到恒温器项目从代码编写到模拟测试,再到最终发布的整个过程。每个环节都紧密相连,任何一个环节出现问题都可能导致项目的失败。因此,在开发过程中,我们需要严格按照流程进行操作,确保每个环节都能顺利进行。
超级会员免费看

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



