25 MelsecSerialClient client;
26 std::array<std::uint16_t, 2> out_words {};
27 std::array<std::byte, mcprotocol::serial::kMaxResponseFrameBytes> rx_chunk {};
28 std::size_t rx_chunk_size = 0;
29 bool tx_started =
false;
30 bool tx_completed =
false;
31 bool rx_ready =
false;
32 bool request_done =
false;
33 Status completion_status {};
36ProtocolConfig make_protocol() {
37 ProtocolConfig config;
38 config.frame_kind = FrameKind::C4;
39 config.code_mode = CodeMode::Ascii;
40 config.ascii_format = AsciiFormat::Format4;
41 config.target_series = PlcSeries::Q_L;
42 config.sum_check_enabled =
false;
43 config.route = RouteConfig {
44 .kind = RouteKind::HostStation,
48 .request_destination_module_io_no = 0x03FF,
49 .request_destination_module_station_no = 0x00,
50 .self_station_enabled =
false,
51 .self_station_no = 0x00,
56void on_request_complete(
void* user, Status status) {
57 auto* app =
static_cast<ExampleApp*
>(user);
58 app->request_done =
true;
59 app->completion_status = status;
64 app.tx_started =
true;
67void simulate_plc_response(ExampleApp& app,
const ProtocolConfig& config) {
68 const std::array<std::uint8_t, 8> response_data {
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8'};
69 std::array<std::uint8_t, mcprotocol::serial::kMaxResponseFrameBytes> response_frame {};
70 std::size_t response_frame_size = 0;
71 const Status status = FrameCodec::encode_success_response(
77 app.request_done =
true;
78 app.completion_status = status;
82 std::memcpy(app.rx_chunk.data(), response_frame.data(), response_frame_size);
83 app.rx_chunk_size = response_frame_size;
91 const ProtocolConfig config = make_protocol();
93 Status status = app.client.configure(config);
95 std::fprintf(stderr,
"configure failed: %s\n", status.message);
99 status = app.client.async_batch_read_words(
101 BatchReadWordsRequest {
103 .points =
static_cast<std::uint16_t
>(app.out_words.size()),
109 std::fprintf(stderr,
"request start failed: %s\n", status.message);
113 uart_start_tx_async(app, app.client.pending_tx_frame());
115 for (std::uint32_t tick = 1; tick <= 4 && !app.request_done; ++tick) {
116 if (app.tx_started && !app.tx_completed) {
117 status = app.client.notify_tx_complete(tick);
119 std::fprintf(stderr,
"notify_tx_complete failed: %s\n", status.message);
122 app.tx_completed =
true;
123 simulate_plc_response(app, config);
127 app.client.on_rx_bytes(
130 app.rx_ready =
false;
133 app.client.poll(tick);
136 if (!app.request_done || !app.completion_status.ok()) {
137 std::fprintf(stderr,
"request did not complete successfully\n");
141 if (app.out_words[0] != 0x1234U || app.out_words[1] != 0x5678U) {
142 std::fprintf(stderr,
"unexpected read data: %04X %04X\n", app.out_words[0], app.out_words[1]);
146 std::printf(
"example read ok: D100=0x%04X D101=0x%04X\n", app.out_words[0], app.out_words[1]);
Frame-level encode/decode helper for complete serial MC frames.
Asynchronous MC protocol client for UART / serial integrations.
Asynchronous request-execution state machine for serial MC protocol traffic.
RouteKind
Route layout inside the request header.
FrameKind
MC protocol frame family used on the serial link.
CodeMode
Request/response payload encoding.
AsciiFormat
ASCII formatting variant for C4 / C3 / C2 serial frames.
PlcSeries
PLC family selection used for subcommand and device-layout differences.
Top-level protocol configuration shared by codecs and client requests.
Route header fields for serial MC requests.
Result object returned by most public APIs.