内容


为嵌入式设备创建可执行的命令序列

使用 OpenOffice Spreadsheet、XML、PHP 和 blob 编写命令

Comments

将电子表格转换为 XML 文档是 Microsoft® Office Excel® 和 OpenOffice.org Calc 的当前版本的内置功能,这个功能不是为了吸引眼球,它对嵌入式系统的开发和测试尤其有用。

嵌入式系统开发人员需要一种方法来生成一些测试场景,以便验证一个设计原型或者首次样品。但是,生成这些场景的成本应该保持到最小。同样的要求也适用于创建经济高效的开发环境,以便使用很小的内存 “足迹” 执行专业的固件生成。

这里讨论的方法使用 OpenOffice.org Calc、XML 和一个 PHP 脚本来创建一个免费的测试场景或固件开发环境。这种方法通过一个生成 Modbus 命令测试场景的示例来演示。

将电子表格转换为 XML 文档

与 Excel 一样,OpenOffice.org Calc 能够生成通过两种格式(任取其一)来表示电子表格的 XML 文档。Microsoft Office Excel 2003 XML 生成 XML (.xml) 文件,而 OpenOffice.org Calc flat XML 生成 FODS (.fods) 文件。作为一个示例,MovieSchedule.xls 这个电子表格用于显示本地电影院中的一个电影列表的安排。 图 1 展示了电子表格的内容(查看 图 1 的文本版本)。

图 1. 电影安排电子表格
vMovieSchedule 电子表格的屏幕截图,其中有两个电影标题、两个剧场以及放映时间
vMovieSchedule 电子表格的屏幕截图,其中有两个电影标题、两个剧场以及放映时间

接下来,一个包含测试场景规范的序列的电子表格将由一个通过 PHP CLI 执行的 PHP 脚本转换为对等的二进制格式。清单 1 展示了电子表格 XML 文档(Excel 2003 格式)的一部分,该部分用于描述电子表格内容。

清单 1. 电影安排 XML 文档
<ss:Worksheet ss:Name="Movies">
     <Table ss:StyleID="ta1">
          <Column ss:Width="127.8144"/>
          <Column ss:Width="127.0512"/>
          <Column ss:Width="191.34"/>
          <Row ss:Height="14.2848">
               <Cell>
                    <Data ss:Type="String">Title</Data>
               </Cell>
               <Cell>
                    <Data ss:Type="String">Theater</Data>
               </Cell>
               <Cell>
                    <Data ss:Type="String">Schedule</Data>
               </Cell>
          </Row>
          <Row ss:Height="14.2848">
               <Cell>
                    <Data ss:Type="String">Avatar</Data>
          </Cell>
               <Cell>
                    <Data ss:Type="String">Criterion</Data>
               </Cell>
               <Cell>
                    <Data ss:Type="String">3:00 PM, 7:00 PM,
                    10:30 PM</Data>
               </Cell>
          </Row>
          <Row ss:Height="14.2848">
               <Cell>
                    <Data ss:Type="String">Surrogates</Data>
               </Cell>
               <Cell>
                    <Data ss:Type="String">Palace</Data>
               </Cell>
               <Cell>
                    <Data ss:Type="String">5:00 PM, 8:00 PM,
                    11:00 PM</Data>
               </Cell>
          </Row>
     </Table>
     <x:WorksheetOptions/>
</ss:Worksheet>

使用 PHP 将 XML 文档转换为 blob

电子表格的 XML 文档如何变成二进制代码?那是一个 PHP 脚本的作用所在,该脚本使用一些类分别完成以下功能:

  1. 通过 PHP DOM 类遍历 XML 文档。
  2. 将被遍历的元素的内容转换为一组作为数组存储的中介表示。
  3. 通过使用一个转换数据库将中介表示转换为目标二进制表。
  4. 将生成的二进制代码存储为转换数据库中的一个 blob。

XML 文档遍历和 “内容到中介” 表示转换是特定于域的。也就是说,它们已针对所使用的电子表格的结构进行定制。例如,一个协议测试电子表格将拥有两个已针对特定的协议进行定制的类。转换数据库包含两个表:一个是转换引用表,用于将中介 “代码” 映射到一个对应的二进制序列;另一个是二进制序列表,用于存储与输入 XML 电子表格文档对应的二进制序列。

示例:构建一个 Modbus 测试场景序列

为了便于说明,需要创建一个电子表格,用于指定一个 Modbus 命令序列。这个命令序列用作一个测试场景,测试通过一个串行接口 —RS-232 或 RS485 — 与一个设备的串行通信。这个 OpenOffice.org Calc 电子表格的工作簿 — ModbusExample.ods — 包含两个工作表。Modbus 是一个 “主-从” 应用程序级协议,也就是说,它独立于支持一个主设备和一组从设备之间的通信的底层网络的类型。它通常用于串行通信网络,尽管也有一些设备在 TCP/IP 下运行。

底层网络包的数据或消息区域封装了一个请求命令,它请求设备中包含设备信号数据的寄存器的内容。该请求命令的格式如下:

[Device address][Request command][Start register][End register]

[Device address] 是 Modbus 设备地址(1-255),长度为一个字节。[Request command] 的长度也是一个字节,它的值基于正被寻址的寄存器的类型设置。读取寄存器的值:

  • 1 = Coil(事件指示器:长度为一个位)
  • 2 = Status(事件指示器:长度为一个位)
  • 3 = Hold(内部设备信号值:4 字节浮点值或 2 字节整数值)
  • 4 = Input(设备输入信号值:4 字节浮点值或 2 字节整数值)

其他命令也能够写入寄存器,但 Read 访问命令的使用频率通常更高。[Start register][End register] 的长度都是两字节,用于提供其值被请求的寄存器地址的范围。要了解 Modbus 协议的更多细节,请参见 参考资料 中的 Modbus 标准链接。

图 2. 设备通信设置
带有设备通信设置的电子表格的屏幕截图
带有设备通信设置的电子表格的屏幕截图

返回到示例电子表格工作簿,第一个工作表 —图 2 中的 Comm— 使用以下参数提供用于访问测试设备的串行通信设置(查看 图 2 的文本版本)。

  • Address测试设备的 Modbus 网络地址。
  • type用于与测试设备通信的协议;仅用于文档目的。
  • Interface用于链接测试设备和主机的电缆连接器的物理类型。
  • Baud主机和测试设备之间的通信数据传输速度。
  • Data一个通信包中的数据位数。
  • Parity主机和测试设备之间的通信的奇偶校验设置。
  • Stop主机和测试设备之间的通信的停止位数。

第二个工作表 Scenario(见 图 3)指定:

  • Register type正被寻址的 Modbus 寄存器的类型(input、hold、coil、status)。
  • Start Register一个寄存器测试范围中的起始 Modbus 寄存器地址。
  • End Register一个寄存器测试范围中的结束 Modbus 寄存器地址。
  • type来自一个寄存器范围的预期响应值的数据类型。这些单元的内容将被转换为预期响应值的预期字节数。Int 被转换为 2 而 float 被转换为 4。位被转换为以下公式:
    Number of bytes =int((Number of bits + 1) / 8) + 1

    其中,int([arg])[arg] 的值的整数部分。

  • Min一个 Modbus 响应包中的任何寄存器值的最小有效值。
  • Max一个 Modbus 响应包中的任何寄存器值的最大有效值。

查看 图 3 的文本版本

图 3. Modbus 请求场景
Modbus 请求场景的屏幕截图
Modbus 请求场景的屏幕截图

PHP 脚本 ProtoConvert.php(参见 下载 获取一个副本)将电子表格 XML 文档转换为一个二进制命令序列。对于上述电子表格中的每一行,通过 Modbus 请求包检索请求的寄存器范围,并根据它们对应的有效值范围验证 Modbus 响应包中的寄存器值。这个脚本基于以下 5 个类:

  • SupportDB建立一个到支持数据库的连接,提供一些访问方法来查询和更新数据库。这个脚本中使用的数据库包是 MySQL,但是您可以使用其他数据库包,比如 IBM® DB2® 或 PostgreSQL。
  • XMLWorkbook提取电子表格 XML 文档文件的内容。
  • CommSheet从对应的 XML 文档提取电子表格的 Comm 工作表部分的内容。
  • ScenarioSheet从对应的 XML 文档提取电子表格的 Scenario 工作表部分的内容。
  • ModbusReqSet从 Comm 和 Scenario 工作表生成一个可执行命令序列。

使用这些类背后的驱动逻辑基本上如下所示:

  1. 建立一个到支持数据库 ProtoTransDB 的连接,数据库的元数据如 清单 2 所示。
    清单 2. 转换数据库元数据
    # 
    #       Protocol test translation support database schema 
    # 
    # 
    
    DROP DATABASE IF EXISTS ProtoTransDB; 
    CREATE DATABASE ProtoTransDB; 
    USE ProtoTransDB; 
    
    # 
    #     Repository of translated protocol test sequences 
    # 
    #     NOTES - 
    # 
    #          (1) TestID = test sequence ID consisting of: 
    # 
    #               1. <TestSpec> = Name of the test sequence 
    #                         specification spreadsheet 
    #               2. <TestStored> = Time stamp when test sequence 
    #                         was translated 
    # 
    #               stored in the format <TestSpec>_<TestStored> 
    # 
    #          (2) TestSequence = executable test sequence 
    # 
    #          (3) The contents of TestSequence consists of 
    #               a sequence of commands as follows: 
    # 
    #               <set_comm> 
    #               <request_1> 
    #               <response_1_verify> 
    #               .................... 
    #               <request_N> 
    #               <response_N_verify> 
    # 
    #          where, 
    #               <set_comm> = communication port configuration 
    #                         consisting of the following: 
    # 
    #                    1. test sequence command (0x0A) 
    #                    2. interface type (0x01 = RS232, 
    #                                   0x02 = RS485 2 wire, 
    #                                   0x03 = RS485 4 wire) 
    #                    3. baud rate (2 bytes) 
    #                    4. number of data bytes (1 byte) 
    #                    5. parity (0x00 = none, 
    #                              0x01 = odd, 
    #                              0x02 = even) 
    #                    6. number of stop bits (1 byte) 
    # 
    #               <request_i> = register value request consisting of the following 
    # 
    #                    1. register requested command (0x0B) 
    #                    2. Modbus register request command (6 bytes): 
    #                         Device address (1 byte) 
    #                         Register read command (1 byte) 
    #                         Start register (2 bytes) 
    #                         End register (2 bytes) 
    # 
    #               <response_i_verify> = register value response verification rule 
    #                    for preceding request consisting of the following: 
    # 
    #                    1. verification rule command (0x0C) 
    #                    2. Bytes per value (Int = 0x02, Float = 0x04, Bit = 0x00) 
    #                    3. Total number of value bytes (2 bytes, 
    #                              Bytes per value * 
    #                              (End register - Start register + 1)) 
    #                    4. Valid minimum for each register value (2 bytes) 
    #                    5. Valid maximum for each register value (2 bytes) 
    #
    
    CREATE TABLE TestScenario 
    ( 
         TestID                         VARCHAR(50) NOT NULL, 
         TestSequence         BLOB,	 
         PRIMARY KEY (TestID ASC) 
    );
  2. 提取电子表格 XML 文档的内容。
  3. 提取 XML 文档的 Comm 工作表的内容。
  4. 提取 XML 文档的 Scenario 工作表的内容。
  5. 将 Comm 和 Scenario 工作表的内容转换为一个可执行命令序列,该命令序列针对一个通过 Modbus 协议通信的设备定义一个测试序列。

使用以下命令运行这个 PHP 脚本:

php ProtoConvert.php <database_access> <XML_doc>

其中,<database_access> 是包含数据库连接参数的文件的完整路径名,<XML_doc> 是包含表示 Modbus 测试序列电子表格的 XML 文档的文件的完整路径名。

如果步骤 14 中出现失败,那么后续步骤将不能执行。清单 2 还包含作为一个 blob 存储在数据库中的测试序列命令的说明。本例中的数据库只包含一个表来存储测试序列,因为转换引用信息被嵌入到 PHP 脚本中。

图 2图 3 中展示的 Modbus 电子表格的测试序列位于 清单 3 中。这个序列实际上是一个持续的字节流(16 进制值)。但是,为了强调它的组件,我们根据 清单 2 中的元数据注释描述的测试序列结构将其分解为它的一些组件,以 16 进制值显示。

清单 3. 测试命令的样例序列
0A 01 2580 08 00 01 

0B 02 04 0136 0136 
0C 02 0002 0000 0190 

0B 02 03 01C2 01C4 
0C 02 0006 0014 015E 

0B 02 03 0212 0217 
0C 02 000C 0000 0064 

0B 02 01 011D 0122 
0C 00 0001 0000 0001

0A 开头的命令指示了串行通信配置设置。以 0B0C 开头的后续命令对分别是请求和验证规则命令,用于提取和检查从测试设备上的 Modbus 寄存器提取的值。

运行时环境包含一个主计算机,它通过自身与一个测试设备之间的串行线缆连接到该测试设备。这个主机运行一个测试序列命令解释器,该解释器以如下方式执行每条命令:

  • 串口设置(0A)。将连接主机的串口设置为接受测试的设备。
  • 寄存器地址请求(0B)。通过标准的 Modbus 命令请求测试设备上的 Modbus 寄存器的内容。
  • 验证规则(0C)。针对有效值限制测试由前面的寄存器地址请求返回的值。

测试序列命令解释器还对每条命令的响应进行日志记录,以备后续分析所需。

结束语

通过使用 OpenOffice.org Calc 的 XML 文档生成功能、PHP 的 DOM 遍历功能以及一个 blob 表示数据库,可以将电子表格中的测试场景规范成功转换为一个测试命令序列。但这种技术的用途还不止这些。

在 ModbusExample.ods 电子表格示例中,您将一个规范有效地转换为一个命令序列。使用适当的电子表格结构,可以构建其他类似的 “规范到命令” 序列转换工具,比如:

  • 基于 “输入-输出” 规范的批生产控制序列生成器;
  • 从设备规范生成的自动测试设备程序生成;
  • 带有精简指令集的设备的固件生成。

下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=487699
ArticleTitle=为嵌入式设备创建可执行的命令序列
publish-date=05062010