Skip to content

指令说明 ​

概述 ​

Node-MQ的指令(包括应答)采用JSON格式定义。例如,配置GPIO5为输入模式的指令:

json
{
  "action": "config",
  "input": [5]
}

读取GPIO5引脚电平数字量的指令:

json
{
  "action": "digital_read",
  "io_num": [5]
}

以及引脚电平数字量的应答信息:

json
{
  "type": "digital",
  "data": [
    {
      "io_num": 5,
       "value": 0
    }
  ]
}

指令JSON对象的形式如:

json
{
  "action": "action_name",
  "param_1": "value_1",
  "param_2": "value_2",
  ...
}

指令对象包含指令名称action属性,以及指令所需的参数。在具体指令章节中将对各自的参数作详细说明。

应答JSON对象的形式如:

json
{
  "type": "type_name",
  "data": "data",
  ...
}

应答对象包含应答数据类型type属性,以及具体的应答数据。应答数据同样在具体的指令章节中说明。

指令通道 ​

用于传输指令的通道称为指令通道。Node-MQ支持从MQTT、WebSocket或UART通道接收指令,并将对应指令的执行结果(应答)反馈至同一通道。所有的指令通道可以同时启用。

MQTT ​

当在设置页面启用了 MQTT Client 并配置了相应的MQTT参数后,Node-MQ启动后将自动连接MQTT Broker,并订阅配置的 Subscribe Topic 主题(默认为node/action)。由该主题接收的MQTT消息Payload将作为指令解析并执行。指令的执行结果(应答)以MQTT消息Payload发布到配置的 Publish Topic 主题(默认为node/post)。

作为指令发送方的MQTT客户端,应将指令发布到Node-MQ配置的 Subscribe Topic 主题,并订阅Node-MQ配置的 Publish Topic 主题,以便接收指令的执行结果以及Node-MQ发布的通知消息。

MQTT通道单次接收或发送的消息Payload最大允许 8 KB。

Node-MQ连接MQTT Broker后,将自动发布一条 type-online 消息,用以通知客户端该Node-MQ设备上线。消息Payload如下:

json
{
  "type": "online",
  "node_id": "node-5a25d4",
  "version": "1.0.0"
}
  • type - 数据类型online(在线消息)。
  • node_id - Node-MQ自动生成的硬件唯一标识。
  • version - Node-MQ固件版本号。

当在设置页面的MQTT参数中启用 Last Will 后,若Node-MQ设备异常断连,则客户端会收到由MQTT Broker以 Publish Topic 主题发布的遗嘱消息,消息Payload如下:

json
{
  "type": "offline",
  "node_id": "node-5a25d4"
}
  • type - 数据类型offline(断连消息)。
  • node_id - Node-MQ自动生成的硬件唯一标识。

可以在同一个MQTT网络中部署多个Node-MQ设备,此时应注意在MQTT参数中区分 Client ID(默认值为系统自动生成的硬件唯一标识)。多个Node-MQ设备可以通过配置不同的 Subscribe Topic 和 Publish Topic 进行分组控制,或独立控制。

WebSocket ​

WebSocket通道默认启用,连接地址为:

ws://<host>/ws

<host>为Node-MQ设备的IP地址。Node-MQ以SoftAP模式启动时,连接地址固定为ws://192.168.4.1/ws。

WebSocket通道单次接收或发送的数据包最大允许 8 KB。

当设置页面启用了 Access Control(访问控制)时,客户端在WebSocket连接建立后应首先发送 Access Code,若首帧数据非密码或密码验证失败,服务端将关闭连接。

WebSocket通道在同一时间只允许一个连接(独占),若已有客户端连接了WebSocket通道,则后续的连接请求将被忽略。

注意

Node-MQ的设置页面会自动连接WebSocket通道。因此,使用自定义的WebSocket客户端时,请关闭设置页面。

网页WebSocket客户端样例:

html
<!DOCTYPE html>
<html>

<head>
  <title>WebSocket Client</title>
</head>

<style>
  .main {
    display: flex;
    flex-flow: column;
    width: fit-content;
    gap: 8px;
  }

  .main textarea,
  .main button {
    padding: 5px;
  }
</style>

<body>
  <div class="main">
    Action
    <textarea id="action" rows="10" cols="40"></textarea>
    <button id="send">Send</button>
    Feedback
    <textarea id="feedback" rows="10" cols="40"></textarea>
    <span id="status"></span>
  </div>

  <script>
    // Replace with the actual IP address of Node-MQ.
    const IP_ADDRESS = '192.168.1.106';
    let ws;

    const action = document.getElementById('action');
    const feedback = document.getElementById('feedback');
    const send = document.getElementById('send');
    const status = document.getElementById('status');

    const connect = () => {
      status.textContent = 'Connecting';
      ws = new WebSocket(`ws://${IP_ADDRESS}/ws`);

      ws.onopen = () => {
        status.textContent = 'Connected';
        // If access control is enabled, send the Access Code.
        // ws.send('nodenode');
      };

      ws.onclose = (e) => {
        status.textContent = `Disconnected (code=${e.code})`;
        setTimeout(connect, 2000);
      };

      ws.onmessage = (e) => {
        feedback.value += e.data + '\n';
      };
    };

    send.onclick = () => {
      if (ws?.readyState === WebSocket.OPEN) {
        ws.send(action.value);
      }
      else {
        status.textContent = 'Not Connected';
      }
    };

    connect();
  </script>
</body>

</html>

保存样例为.html文件,并根据Node-MQ设备的实际IP地址修改对应变量后,使用浏览器打开即可测试样例。

UART ​

ESP32-S3 模块提供3个UART控制器(UART0~UART2),均可用作指令通道,并可同时启用。UART通道需要由config指令启用,参考 UART配置。

UART通道单次接收或发送的数据包最大允许 4 KB。使用UART通道发送的指令必须一次性连续发送(字符中断间隔小于20毫秒),一次完整指令不可分段发送。

通用规则 ​

  • 单条指令或应答均以JSON对象形式定义。

  • 多条指令可以组合为JSON对象数组,一次性提交。Node-MQ将按照数组中的顺序逐一执行。例如:

    json
    [
      {
        "action": "config",
        "input": [5]
      },
      {
        "action": "digital_read",
        "io_num": [5]
      }
    ]
  • 指令JSON对象固定包含action属性,标识指令名称。例如{"action": "config"}表示资源配置指令。

  • 应答JSON对象固定包含type属性,标识应答数据类型。 例如{"type": "digital"}表示引脚电平数字量。

  • 指令和应答JSON对象中的属性名称和预定义值(字符型)使用小写英文加下划线分隔形式(snake_case)。

  • 根据应答行为的不同,指令可以分为两种类型:

    1. 需要明确应答的指令。此类指令的意图即获取应答数据,例如读取引脚电平数字量指令。
    2. 非必须应答的指令,如设置引脚电平数字量指令。对于此类指令,Node-MQ采用静默原则,即除非捕获到错误,否则不应答。在具体指令说明中提到“该指令无应答”的,均属于此类指令。
  • 当Node-MQ在解析或执行指令过程中捕获到错误时,将反馈type-error错误信息,例如:

    json
    {
      "type": "error",
      "tag": "config",
      "msg": "ERR_INVALID_IO"
    }
    • type - 数据类型error(错误消息)。
    • tag - 标识错误源或指令名称。
    • msg - 错误的可读名称或描述。
  • Node-MQ的指令通道均为异步传输通道,即指令的发送方在发出指令后不会同步等待应答,而是以指令已发出的状态立即返回。指令执行结果则以异步消息的形式通知指令发送方。为使发送方在收到应答消息后能识别其所对应的指令,所有指令均支持可选的id属性,类型为无符号整数(uint32)。当指令JSON对象中包含该属性时,其应答JSON对象也将包含相同值的id属性。指令的发送方可以为指令设置id标识,并在收到应答后根据相同的id关联对应的指令。带有id属性的指令如:

    json
    {
      "id": 33,
      "action": "digital_read",
      "io_num": [5]
    }
  • Node-MQ在解析指令JSON时,支持单元素数组简写。即对于数组类型的属性,当仅有一个元素时,可以直接将该元素作为属性值。例如,整型数组:

    json
    {
      "action": "digital_read",
      "io_num": [5]
    }

    可简写为:

    json
    {
      "action": "digital_read",
      "io_num": 5
    }

    或对象数组:

    json
    {
      "action": "config",
      "uart": [
        {
          "uart_num": 0
        }
      ]
    }

    可简写为:

    json
    {
      "action": "config",
      "uart": {
        "uart_num": 0
      }
    }

文档约定 ​

  1. 本文档统一使用以下格式描述JSON指令对象的属性定义:

    属性名称 [值类型] (可选标识) 属性说明。

    • 值类型:

      • string - UTF-8字符串,如{"action": "config"}。
      • int - 整数值,如{"value": 10}。
      • float - 浮点值,如{"value": 4.5}。
      • bool - 布尔值,如{"value": true}。
      • object - JSON对象,如{"data": {"name": "Kyle"}}。
      • array - 数组,如{"input": [1, 2, 3]}。
    • 可选标识:

      • (!) - 表示该属性必须存在。
      • (?) - 表示该属性可选,可以不存在。

    样例:

    • action [string] (!) 指令名称。

      字符串类型的必选属性 action。

    • input [array] (?) 设置为输入模式的GPIO序号数组。

      数组类型的可选属性 input。

  2. 在文档中使用以下简写形式指代具体的指令或应答:

    • 指令如{"action": "config"}简写为action-config。
    • 应答如{"type": "digital"}简写为type-digital。