DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
melsec.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file melsec.h
6 * @brief Mitsubishi MELSEC MC protocol (binary 3E frame) codec (DETWS_ENABLE_MELSEC) -
7 * zero-heap batch-read request builder + response parser for MELSEC PLCs over TCP/UDP.
8 *
9 * The QnA-compatible binary 3E request frame (all multi-octet fields LITTLE-endian, unlike
10 * the big-endian PLC protocols):
11 * @code
12 * 50 00 subheader (request)
13 * 00 network number
14 * FF PC (station) number
15 * FF 03 request destination module I/O number (0x03FF)
16 * 00 request destination multidrop station
17 * LL LL request data length (the octets from the monitoring timer on)
18 * TT TT monitoring timer
19 * 01 04 command (0x0401 batch read)
20 * 00 00 subcommand (0x0000 word units)
21 * dd dd dd head device number (3 octets)
22 * CC device code (D = 0xA8, M = 0x90, ...)
23 * pp pp number of device points
24 * @endcode
25 * The response subheader is `D0 00`, followed by the same routing, a 2-octet length, a
26 * 2-octet end code (0x0000 = success), then the read data (2 octets per word point).
27 *
28 * Frame layout + device codes verified against a third-party MC-protocol implementation.
29 * This is the codec; the TCP/UDP send is the application's.
30 *
31 * @author Douglas Quigg (dstroy0)
32 * @date 2026
33 */
34
35#ifndef DETERMINISTICESPASYNCWEBSERVER_MELSEC_H
36#define DETERMINISTICESPASYNCWEBSERVER_MELSEC_H
37
38#include "ServerConfig.h"
39
40#if DETWS_ENABLE_MELSEC
41
42#include <stddef.h>
43#include <stdint.h>
44
45#define MELSEC_3E_REQ_SUBHEADER0 0x50 ///< request subheader (sent 0x50 then 0x00)
46#define MELSEC_3E_REQ_SUBHEADER1 0x00
47#define MELSEC_3E_RES_SUBHEADER0 0xD0 ///< response subheader (0xD0 0x00)
48#define MELSEC_3E_RES_SUBHEADER1 0x00
49
50#define MELSEC_NETWORK_DEFAULT 0x00 ///< local network
51#define MELSEC_PC_DEFAULT 0xFF ///< host station
52#define MELSEC_DEST_IO_DEFAULT 0x03FF ///< own station CPU
53#define MELSEC_DEST_MULTIDROP_DEFAULT 0x00
54
55#define MELSEC_CMD_BATCH_READ 0x0401 ///< batch read
56#define MELSEC_CMD_BATCH_WRITE 0x1401 ///< batch write
57#define MELSEC_SUBCMD_WORD 0x0000 ///< word units
58#define MELSEC_SUBCMD_BIT 0x0001 ///< bit units
59
60// Device (area) codes for the binary 3E frame.
61#define MELSEC_DEV_D 0xA8 ///< data register (D)
62#define MELSEC_DEV_R 0xAF ///< file/extension register (R)
63#define MELSEC_DEV_M 0x90 ///< auxiliary relay (M)
64#define MELSEC_DEV_S 0x98 ///< state (S)
65#define MELSEC_DEV_X 0x9C ///< input (X)
66#define MELSEC_DEV_Y 0x9D ///< output (Y)
67#define MELSEC_DEV_TN 0xC2 ///< timer current value (TN)
68#define MELSEC_DEV_TS 0xC1 ///< timer contact (TS)
69#define MELSEC_DEV_CN 0xC5 ///< counter current value (CN)
70#define MELSEC_DEV_CS 0xC4 ///< counter contact (CS)
71
72#define MELSEC_ENDCODE_OK 0x0000 ///< response end code: success
73
74// Binary 3E frame geometry (octet offsets and fixed lengths).
75#define MELSEC_3E_READ_REQ_LEN 21 ///< total octets in a batch-read request frame
76#define MELSEC_3E_READ_REQ_DATA_LEN 12 ///< batch-read request data-length field: timer..points
77#define MELSEC_3E_RES_MIN_LEN 11 ///< shortest valid response: subheader through end code
78#define MELSEC_3E_RES_LEN_OFFSET 7 ///< offset of the response data-length field
79#define MELSEC_3E_RES_DATALEN_BASE 9 ///< offset where the data-length-counted region (end code) begins
80#define MELSEC_3E_RES_DATA_OFFSET 11 ///< offset of the response read data (after the end code)
81#define MELSEC_ENDCODE_LEN 2 ///< end-code octets (counted inside the data length)
82
83/**
84 * @brief Build a binary 3E batch-read (word units) request.
85 * @param device_code MELSEC_DEV_* (or a raw device code).
86 * @param head_device starting device number (24-bit).
87 * @param points number of word points to read.
88 * @param monitoring_timer the CPU monitoring timer (units of 250 ms; 0 = wait indefinitely).
89 * @return total octets written (21), or 0 on overflow / bad input.
90 */
91size_t melsec_build_read(uint8_t *buf, size_t cap, uint8_t device_code, uint32_t head_device, uint16_t points,
92 uint16_t monitoring_timer);
93
94/** @brief A parsed 3E response. @ref data points INTO the source buffer (LE word values). */
95struct MelsecResponse
96{
97 uint16_t end_code; ///< 0x0000 on success
98 const uint8_t *data; ///< response payload (empty on error)
99 size_t data_len;
100};
101
102/** @brief Parse + validate a binary 3E response (subheader 0xD0 0x00, length, end code, data). */
103bool melsec_parse_response(const uint8_t *buf, size_t len, MelsecResponse *out);
104
105#endif // DETWS_ENABLE_MELSEC
106
107#endif // DETERMINISTICESPASYNCWEBSERVER_MELSEC_H
User-facing configuration for DeterministicESPAsyncWebServer.