firmware-base/docs/docs-rest.md

11 KiB

REST API Documentation

This document provides an overview of the RESTful API and WebSocket interface for interacting with the device.

Authentication

The API does not currently require authentication.

Base URL

All API endpoints are relative to the device's IP address. For example, if the device IP is 192.168.1.100, the full URL for /api/v1/system/info would be http://192.168.1.100/api/v1/system/info.


REST API Endpoints

System Endpoints

Get System Information

  • Endpoint: GET /api/v1/system/info
  • Description: Retrieves general system information like firmware version, uptime, and memory usage.
  • Response:
    {
      "version": "3ce112f",
      "board": "esp32dev",
      "uptime": 12345,
      "timestamp": 12345678,
      "freeHeapKb": 150.5,
      "maxFreeBlockKb": 100.2,
      "cpuTicks": 123456789,
      "loopDurationMs": 500,
      "cpuLoadPercent": null
    }
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/system/info
    
  • Node.js Example:
    const fetch = require('node-fetch');
    
    async function getSystemInfo() {
      try {
        const response = await fetch('http://<DEVICE_IP>/api/v1/system/info');
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error('Error fetching system info:', error);
      }
    }
    
    getSystemInfo();
    

Get System Logs

  • Endpoint: GET /api/v1/system/logs
  • Description: Retrieves the system logs.
  • Query Parameters:
    • level (optional): The minimum log level to retrieve. Can be one of none, error, warning, notice, trace, verbose. Defaults to verbose.
  • Response: An array of log strings.
    [
      "I: System initialized.",
      "W: Network connection weak."
    ]
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/system/logs?level=warning
    
  • Node.js Example:
    const fetch = require('node-fetch');
    
    async function getLogs() {
      try {
        const response = await fetch('http://<DEVICE_IP>/api/v1/system/logs?level=warning');
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error('Error fetching logs:', error);
      }
    }
    
    getLogs();
    

Get/Set Log Level

  • Endpoint:
    • GET /api/v1/system/log-level
    • GET /api/v1/system/log-level?level=<level>
  • Description:
    • GET without parameters retrieves the current log level.
    • GET with the level parameter sets a new log level.
  • Query Parameters:
    • level (for setting): The new log level. One of none, error, info, warning, notice, trace, verbose.
  • Response (Get):
    {
      "success": true,
      "level": "verbose"
    }
    
  • Response (Set):
    {
      "success": true,
      "level": "warning"
    }
    
  • cURL Example (Get):
    curl http://<DEVICE_IP>/api/v1/system/log-level
    
  • cURL Example (Set):
    curl http://<DEVICE_IP>/api/v1/system/log-level?level=warning
    
  • Node.js Example (Set):
    const fetch = require('node-fetch');
    
    async function setLogLevel(level) {
      try {
        const response = await fetch(`http://<DEVICE_IP>/api/v1/system/log-level?level=${level}`);
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error('Error setting log level:', error);
      }
    }
    
    setLogLevel('warning');
    

List Filesystem

  • Endpoint: GET /api/v1/fs/list
  • Description: Lists files and directories in the root of the device's filesystem (LittleFS).
  • Response:
    [
      {
        "name": "/index.html",
        "type": "file",
        "size": 1234
      },
      {
        "name": "/config",
        "type": "directory",
        "size": 0
      }
    ]
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/fs/list
    

Modbus Endpoints

These endpoints provide access to Modbus data (coils and registers).

Get All Coils

  • Endpoint: GET /api/v1/coils
  • Description: Retrieves the state of all mapped coils.
  • Response:
    {
      "coils": [
        {
          "address": 1,
          "value": 1,
          "name": "Motor_On",
          "component": "Motor",
          "id": 101,
          "type": 1,
          "flags": 0,
          "group": "Motors"
        }
      ]
    }
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/coils
    

Get Single Coil

  • Endpoint: GET /api/v1/coils?address=<address>
  • Description: Retrieves the state of a single coil by its address.
  • Query Parameters:
    • address: The address of the coil.
  • Response:
    {
      "address": 1,
      "value": true
    }
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/coils?address=1
    

Set Single Coil

  • Endpoint: POST /api/v1/coils/<address>?value=<value>
  • Description: Sets the state of a single coil.
  • URL Parameters:
    • address: The address of the coil.
  • Query Parameters:
    • value: The new state of the coil (1/true or 0/false).
  • Response:
    {
      "success": true,
      "address": 51,
      "value": true
    }
    
  • cURL Example:
    curl -X POST "http://<DEVICE_IP>/api/v1/coils/51?value=true"
    
  • Node.js Example:
    const fetch = require('node-fetch');
    
    async function setCoil(address, value) {
      try {
        const response = await fetch(`http://<DEVICE_IP>/api/v1/coils/${address}?value=${value}`, {
          method: 'POST'
        });
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error(`Error setting coil ${address}:`, error);
      }
    }
    
    setCoil(51, true);
    

Get All Registers

  • Endpoint: GET /api/v1/registers
  • Description: Retrieves the value of all mapped registers.
  • Query Parameters (optional):
    • page: The page number to retrieve (0-indexed). Defaults to 0.
    • pageSize: The number of registers per page. Defaults to 20.
  • Response (with pagination):
    {
      "registers": [
        {
          "error": 0,
          "address": 100,
          "value": 1234,
          "name": "Temperature_Setpoint",
          "component": "Heater",
          "id": 201,
          "type": 3,
          "slaveId": 1,
          "flags": 0,
          "group": "Heating"
        }
      ],
      "meta": {
        "page": 0,
        "pageSize": 20,
        "totalRegisters": 256,
        "totalPages": 13
      }
    }
    
  • cURL Example (with pagination):
    curl http://<DEVICE_IP>/api/v1/registers?page=1&pageSize=50
    
    curl http://<DEVICE_IP>/api/v1/registers
    

Get Single Register

  • Endpoint: GET /api/v1/registers?address=<address>
  • Description: Retrieves the value of a single register by its address.
  • Query Parameters:
    • address: The address of the register.
  • Response:
    {
      "address": 100,
      "value": 1234
    }
    
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/registers?address=100
    

Set Single Register

  • Endpoint: POST /api/v1/registers/<address>?value=<value>
  • Description: Sets the value of a single holding register.
  • URL Parameters:
    • address: The address of the register.
  • Query Parameters:
    • value: The new integer value for the register (16-bit signed).
  • Response:
    {
      "success": true,
      "address": 20,
      "value": 42
    }
    
  • cURL Example:
    curl -X POST "http://<DEVICE_IP>/api/v1/registers/20?value=42"
    
  • Node.js Example:
    const fetch = require('node-fetch');
    
    async function setRegister(address, value) {
      try {
        const response = await fetch(`http://<DEVICE_IP>/api/v1/registers/${address}?value=${value}`, {
          method: 'POST'
        });
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error(`Error setting register ${address}:`, error);
      }
    }
    
    setRegister(20, 42);
    

Get Modbus Address Mappings

  • Endpoint: GET /api/v1/mappings
  • Description: Retrieves the list of all Modbus address mappings.
  • cURL Example:
    curl http://<DEVICE_IP>/api/v1/mappings
    

WebSocket API

For real-time data streaming and more complex interactions, a WebSocket interface is provided.

  • Endpoint: ws://<DEVICE_IP>/ws

Connection

A client can connect to the WebSocket endpoint to receive real-time updates and send commands.

Node.js Example:

const WebSocket = require('ws');

const ws = new WebSocket('ws://<DEVICE_IP>/ws');

ws.on('open', function open() {
  console.log('Connected to WebSocket');
  // Send a command to get system info
  ws.send(JSON.stringify({ command: 'get_sysinfo' }));
});

ws.on('message', function incoming(data) {
  console.log('Received:', JSON.parse(data));
});

ws.on('close', function close() {
  console.log('Disconnected from WebSocket');
});

ws.on('error', function error(err) {
  console.error('WebSocket error:', err);
});

Commands

Commands are sent as JSON strings.

  • get_sysinfo: Get system information.
  • get_logs: Get log history.
  • get_coils: Get all coil values.
  • get_registers: Get all register values. Supports paging.
  • write_register: Write to a register. Payload: { "command": "write_register", "address": 100, "value": 1234 }
  • write_coil: Write to a coil. Payload: { "command": "write_coil", "address": 50, "value": true }

Register Paging via WebSocket

When requesting all registers via the get_registers command, the response can be paginated to handle a large number of registers efficiently.

Request Payload:

{
  "command": "get_registers",
  "page": 0,
  "pageSize": 50
}
  • page (optional): The page number to retrieve (0-indexed). Defaults to 0.
  • pageSize (optional): The number of registers per page. Defaults to 20.

Response Payload:

The response is a JSON object containing the data for the requested page and metadata about the pagination.

{
  "type": "registers",
  "data": [
    {
      "error": 0,
      "address": 100,
      "value": 1234,
      "name": "Register_100",
      "component": "CompA",
      "id": 1,
      "type": 3,
      "slaveId": 1,
      "flags": 1,
      "group": "Group1"
    }
    // ... up to pageSize registers
  ],
  "meta": {
    "page": 0,
    "pageSize": 50,
    "totalRegisters": 256,
    "totalPages": 6
  }
}
  • type: The type of the message (registers).
  • data: An array of register objects for the current page.
  • meta: An object containing pagination details:
    • page: The current page number.
    • pageSize: The number of items per page.
    • totalRegisters: The total number of registers available.
    • totalPages: The total number of pages.