模拟服务 : 串口

串口模拟服务,用于模拟串口通信,支持串口发送和接收, 并通过匹配规则自动进行响应。 或当没有规则被匹配时,可转发到其他通讯连接来完成通讯。

串口模拟服务

开始

如何使用 Bittly 实现串口模拟自动响应与数据发送

连接配置

  • 路径 : 串口设备路径,例如 COM1/dev/ttyS0
  • 波特率 : 串口波特率,例如 9600
  • 数据位 : 串口数据位,例如 8
  • 停止位 : 串口停止位,例如 1
  • 校验位 : 串口校验位,例如 None
  • 流控 : 串口流控,例如 None
  • 内容模式 : 串口内容模式,例如 文本HEX
  • 字符集 : 当内容模式为文本模式时,可指定数据内容字符集,当字符集为 默认 时, 则使用当前项目指定的字符集。

变量

在服务运行时, 对于需要临时存储的数据, 可以通过变量来进行存储。 变量的值可以在服务运行时进行修改, 但在服务启动时,将会使用默认值进行初始化。

变量可以在脚本或者模板中使用,

例如在模板中使用变量:

{{ $var("变量名") }}

在脚本中使用变量:

// 获取变量
let value = $this.variableGet("变量名");

// 设置变量
$this.variableSet("变量名", "变量值");

分帧

当收到数据后,可能收到的数据不是一个完整的数据包,或者存在多余的数据,这时需要对数据进行分帧处理。

收到数据后直接提交给后续步骤处理,不做任何处理。

超时

配置项

  • 时间 : 超时时间,单位毫秒。

当收到数据后,如果在超时时间内没有收到更多数据,则标识该数据为一个完整的数据包,提交给后续步骤处理。 如果在超时时间内收到更多数据,则继续等待。

换行

配置项

  • 换行符 : 换行符。支持\r, \n\r\n

当收到数据后,如果收到换行符,则标识该数据为一个完整的数据包,提交给后续步骤处理。 如果没有收到换行符,则继续等待。

假设换行符为 \n, 收到数据如下:

hello\nworld\n123

则收到的数据帧为:

hello\n

world\n

数据末尾的 123 会被保留,等待下一次数据到来。

固定长度

配置项

  • 长度 : 固定长度,单位字节。

当收到数据后,如果收到的数据长度等于固定长度,则标识该数据为一个完整的数据包,提交给后续步骤处理。 如果收到的数据长度小于固定长度,则继续等待。

假设收到数据长度为 13,固定长度为 5,收到的数据如下:

hello12345!!!

则收到的数据帧为:

hello

12345

数据末尾的 !!! 会被保留,等待下一次数据到来。

匹配头尾

配置项

  • 帧头 : 帧头标识,可选。
  • 帧尾 : 帧尾标识,可选。
  • 超时 : 超时时间,单位毫秒。

当配置了帧头和帧尾时,则当收到数据后,如果收到的数据包含帧头和帧尾,则标识该数据为一个完整的数据包,提交给后续步骤处理。 如果在帧头之前存在数据,则会被忽略, 即仅仅被帧头帧尾包括的内容会被提交给后续步骤处理。

假设帧头为 hello,帧尾为 world,收到的数据如下:

hello12345world

则收到的数据帧为:

12345

如果配置了帧头而未配置帧尾,接收到的数据将按以下规则处理:若能识别出下一帧的帧头,则将当前帧头至下一帧帧头之前的数据视为完整数据包, 并提交给后续处理。如果未检测到下一帧帧头,则系统将根据设置的超时时间等待,超时后将已接收的数据作为完整数据包处理。

若仅配置了帧尾而未配置帧头,当接收的数据包含帧尾时,将帧尾之前的所有数据视为一个完整的数据包,并提交给后续处理步骤。

当内容模式为文本时, 帧头和帧尾可以配置为文本,例如 helloworld。 如果内容模式为HEX时,帧头和帧尾可以配置为十六进制,例如 AA BBEE FF

正则表达式

配置项

  • 表达式 : 正则表达式。
  • 忽略大小写 : 是否忽略大小写。

当配置分帧模式为正则表达式时,收到数据后则会进行正则表达式匹配,并将匹配的数据内容作为一个完整的数据包提交给后续步骤处理。

例如,配置正则表达式为 hello.*world,收到的数据如下:

hello12345world

则收到的数据帧为:

12345

JSON

当收到数据后,检查数据是否为一个完整的JSON数据包,如果是则提交给后续步骤处理。

例如,收到的数据如下:

{
    "name": "hello",
    "age": 18
} 
{
    "name": "world",

则收到的数据帧为:

{
    "name": "hello",
    "age": 18
}

XML

当收到数据后,检查数据是否为一个完整的XML数据包,如果是则提交给后续步骤处理。

例如,收到的数据如下:

<name>hello</name>
<age>18

则收到的数据帧为:

<name>hello</name>

数据转发

转发配置

在默认情况下,MOCK服务在没有匹配到响应规则时, 不会进行任何数据响应操作。 但是,如果我们希望将部分数据转发到其他服务, 则可以通过 转发 功能来实现。

例如,起初我们设备没有实现任何功能, 则我们可以通过配置响应规则来响应所有请求数据。 当设备实现了部分功能时, 我们可以通过将原规则禁用掉, 从而将部分请求数据转发到真实设备, 其余数据继续由MOCK服务响应。

在配置了转发规则后, 当请求数据未匹配任何规则时, MOCK 服务则会将请求数据转发到指定的服务地址, 转发配置可配置不同类型的通讯方式, 例如可以将串口MOCK服务转发到TCP服务, 也可以将TCP服务转发到串口服务。 但是, 转发的要求是两种服务之间支持同一种数据类型,例如串口和TCP服务都支持文本以及二进制数据,所以可以进行转发。

转发目标通过通讯模块进行配置, 配置完成后可通过刷新按钮刷新转发目标列表, 选择需要转发的目标即可。 对于TCP获取UDP等支持多客户端的服务,仅有在未开启多客户端模式下才能进行转发。

匹配规则

当服务接收到数据后, 会依次匹配每个规则, 当规则匹配成功时, 会执行对应的响应操作,并且停止匹配。

任意

当规则为任意时, 会匹配任意数据。 所以可以将任意规则放在最后, 以确保能够匹配到所有未匹配的数据。

文本

当规则为文本时, 会以文本方式进行匹配, 如果收到的数据与规则内容相同, 则执行对应的响应操作。

通配符

当规则为 通配符 时, 会以通配符方式进行匹配, 如果收到的数据与规则匹配成功, 则执行对应的响应操作。

在通配符中,使用 * 表示任意字符,使用 ? 表示任意单个字符。 如果需要匹配 *? 字符, 需要使用 \ 进行转义。

例如, 规则 01*03 匹配 01020301?03 匹配 0103

HEX

当规则为HEX时, 会以HEX方式进行匹配, 如果收到的数据与规则内容相同, 则执行对应的响应操作。

正则表达式

当规则为正则表达式时, 会以正则表达式进行匹配, 如果接收到的数据与规则匹配成功, 则执行对应的响应操作。

如果正则表达式中存在分组, 则分组数据将会被作为上下文数据用于响应操作。

例如, 正则表达式(?<temp>\d+),(?<level>\d+)匹配123,456时, temp的值为123level的值为456

则在响应规则模板中可以使用 {{temp}}{{level}} 来引用上下文数据。

HEX匹配

当规则为HEX匹配时, 会以HEX方式进行匹配, 如果接收到的数据与规则匹配成功, 则执行对应的响应操作。

如果表达式中存在变量解析, 则变量将会被解析为上下文数据用于响应操作。

例如, 表达式01 02 @U8<num> 04匹配01 02 03 04时, num的值为数值3

则在响应规则模板中可以使用 {{num}} 来引用上下文数据。

JSON

当匹配规则为JSON时, 会将请求数据解析为JSON对象后进行匹配, 如果接收到的数据与规则匹配成功, 则执行对应的响应操作。 并且收到的数据会被解析为JSON对象, 以便于后续的响应操作。

例如, 规则 $request.name === 'test' 匹配 {"name":"test"} 时, 则执行对应的响应操作。

其中 $request 表示整个JSON对象, $request.name 表示JSON对象中的 name 属性。

当匹配成功时, 会将匹配到的JSON对象作为上下文数据用于响应操作, 例如在响应规则模板中可以使用 {{$request.name}} 来引用上下文数据。

表达式

当规则为表达式时, 会以表达式方式进行匹配, 如果接收到的数据与规则匹配成功, 则执行对应的响应操作。

其中,表达式可以调用 MOCK服务中脚本到处的函数, 例如在脚本中导出函数 test :

export function test(name) {
    return name === 'test';
}

则可以在匹配规则中使用 test('test') 进行匹配, 如果表达式返回 true, 则执行对应的响应操作。

片段

片段用于保存一些常用的传输内容,以便在需要时重复使用。 片段支持文本和HEX两种格式, 支持批量发送。

  • 启用 : 配置是否启用该片段, 当片段被禁用时, 批量发送时不会发送该片段。
  • 名称 : 片段名称, 用于标识片段。
  • 格式 : 配置片段的格式, 支持文本和HEX两种格式。
  • 内容 : 配置片段的内容, 根据不同的格式填写不同的内容。
  • 延时 : 配置片段发送的延时时间, 单位毫秒。

手动

手动内容发送用于发送自定义内容。 支持文本和HEX两种格式, 支持定时发送。

脚本

脚本

Bittly 的串口 Mock 服务支持通过脚本来改变执行流程以及自定义响应内容。 脚本采用 JavaScript 语法, 在服务执行时, Bittly 会将脚本编译为 Javascript Module 并在适当的实际执行对应的函数。

脚本函数可以分为两种类型, 一种是生命周期函数,例如 init 等, 另一种是由用户自定义的函数, 可用于在响应模板以及匹配条件中调用。

生命周期函数

init()

初始化函数, 用于初始化脚本环境, 仅在服务启动时执行一次, 如果该函数执行失败,则服务启动失败。

例如

export async function init() {
    $this.variableSet('counter', 0);
}

onData

当客户端发送数据时, 会调用该函数处理数据,例如追加自定义帧头,帧尾或者解析值到变量等,该函数必须返回处理后的数据。

例如

export async function onData( data ) {
    return data;
}

beforeWrite

在客户端发送数据前, 会调用该函数处理数据,例如追加自定义帧头,帧尾或者解析值到变量等,该函数必须返回处理后的数据。

例如

export async function beforeWrite( data ) {
    return data;
}

内置函数

$this.variableGet(name)

获取当前变量值, 例如 $this.variableGet('counter')。 当变量不存在时将会抛出异常。

请求参数

  • name : 变量名称。

返回值: 变量值

例如:

export async function init() {
    // 获取变量值
    let counter = $this.variableGet('counter');
    console.log('Counter:', counter);
}

$this.variableSet(name, value)

设置当前变量值, 当变量不存在时将会抛出异常。

请求参数

  • name : 变量名称。
  • value : 变量值。

返回值: 无

例如:

export async function init() {
    // 设置变量值
    $this.variableSet('counter', 1);
}
2024 © Bittly 沪ICP备2023006101号-2