From 7ad63c0bc1d2f2b8c3f1cabb5d4afc77a0d3dbf9 Mon Sep 17 00:00:00 2001 From: lyon Date: Mon, 19 Sep 2022 14:49:11 +0800 Subject: [PATCH 1/2] add_files --- package/modbus/LICENSE | 201 ---- package/modbus/_modbus.c | 194 ---- package/modbus/_modbus.pyi | 32 - package/modbus/agile_modbus.c | 1519 ----------------------------- package/modbus/agile_modbus.h | 359 ------- package/modbus/agile_modbus_rtu.c | 291 ------ package/modbus/agile_modbus_rtu.h | 79 -- package/modbus/agile_modbus_tcp.c | 226 ----- package/modbus/agile_modbus_tcp.h | 83 -- package/modbus/modbus.py | 99 -- 10 files changed, 3083 deletions(-) delete mode 100644 package/modbus/LICENSE delete mode 100644 package/modbus/_modbus.c delete mode 100644 package/modbus/_modbus.pyi delete mode 100644 package/modbus/agile_modbus.c delete mode 100644 package/modbus/agile_modbus.h delete mode 100644 package/modbus/agile_modbus_rtu.c delete mode 100644 package/modbus/agile_modbus_rtu.h delete mode 100644 package/modbus/agile_modbus_tcp.c delete mode 100644 package/modbus/agile_modbus_tcp.h delete mode 100644 package/modbus/modbus.py diff --git a/package/modbus/LICENSE b/package/modbus/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/package/modbus/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/package/modbus/_modbus.c b/package/modbus/_modbus.c deleted file mode 100644 index 897ef8c00..000000000 --- a/package/modbus/_modbus.c +++ /dev/null @@ -1,194 +0,0 @@ -#include "_modbus__ModBus.h" -#include "agile_modbus.h" - -void _modbus__ModBus___init__rtu(PikaObj* self, - int sendBUffSize, - int readBuffSize) { - agile_modbus_rtu_t ctx_rtu = {0}; - obj_setBytes(self, "sendBuff", NULL, sendBUffSize); - obj_setBytes(self, "readBuff", NULL, readBuffSize); - agile_modbus_rtu_init(&ctx_rtu, obj_getBytes(self, "sendBuff"), - sendBUffSize, obj_getBytes(self, "readBuff"), - readBuffSize); - obj_setStruct(self, "ctx_rtu", ctx_rtu); - agile_modbus_rtu_t* ctx_rtu_heap = obj_getStruct(self, "ctx_rtu"); - obj_setPtr(self, "ctx", &ctx_rtu_heap->_ctx); -} - -void _modbus__ModBus_setSlave(PikaObj* self, int slave) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - agile_modbus_set_slave(ctx, slave); -} - -void _modbus__ModBus___init__tcp(PikaObj* self, - int sendBuffSize, - int readBuffSize) { - agile_modbus_tcp_t ctx_tcp = {0}; - obj_setBytes(self, "sendBuff", NULL, sendBuffSize); - obj_setBytes(self, "readBuff", NULL, readBuffSize); - agile_modbus_tcp_init(&ctx_tcp, obj_getBytes(self, "sendBuff"), - sendBuffSize, obj_getBytes(self, "readBuff"), - readBuffSize); - obj_setStruct(self, "ctx_tcp", ctx_tcp); - agile_modbus_tcp_t* ctx_tcp_heap = obj_getStruct(self, "ctx_tcp"); - obj_setPtr(self, "ctx", &ctx_tcp_heap->_ctx); -} - -int _modbus__ModBus_deserializeMaskWriteRegister(PikaObj* self, int msgLength) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_deserialize_mask_write_register(ctx, msgLength); -} - -Arg* _modbus__ModBus_deserializeReadRegisters(PikaObj* self, int msgLength) { - uint16_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_read_registers(ctx, msgLength, - (uint16_t*)buff); - return arg_newBytes((uint8_t*)buff, len * 2); -} - -Arg* _modbus__ModBus_deserializeReadBits(PikaObj* self, int msgLength) { - uint8_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_read_bits(ctx, msgLength, buff); - return arg_newBytes(buff, len); -} - -Arg* _modbus__ModBus_deserializeReadInputBits(PikaObj* self, int msgLength) { - uint8_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_read_input_bits(ctx, msgLength, buff); - return arg_newBytes(buff, len); -} - -Arg* _modbus__ModBus_deserializeReadInputRegisters(PikaObj* self, - int msgLength) { - uint16_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_read_input_registers(ctx, msgLength, - (uint16_t*)buff); - return arg_newBytes((uint8_t*)buff, len * 2); -} - -Arg* _modbus__ModBus_deserializeReportSlaveId(PikaObj* self, - int msgLength, - int maxDest) { - uint8_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_report_slave_id(ctx, msgLength, maxDest, - (uint8_t*)buff); - return arg_newBytes(buff, len); -} - -Arg* _modbus__ModBus_deserializeWriteAndReadRegisters(PikaObj* self, - int msgLength) { - uint16_t buff[128] = {0}; - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - int len = agile_modbus_deserialize_write_and_read_registers( - ctx, msgLength, (uint16_t*)buff); - return arg_newBytes((uint8_t*)buff, len * 2); -} - -int _modbus__ModBus_deserializeWriteBit(PikaObj* self, int msgLength) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_deserialize_write_bit(ctx, msgLength); -} - -int _modbus__ModBus_deserializeWriteBits(PikaObj* self, int msgLength) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_deserialize_write_bits(ctx, msgLength); -} - -int _modbus__ModBus_deserializeWriteRegister(PikaObj* self, int msgLength) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_deserialize_write_register(ctx, msgLength); -} - -int _modbus__ModBus_deserializeWriteRegisters(PikaObj* self, int msgLength) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_deserialize_write_registers(ctx, msgLength); -} - -int _modbus__ModBus_serializeMaskWriteRegister(PikaObj* self, - int addr, - int andMask, - int orMask) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_mask_write_register(ctx, addr, andMask, - orMask); -} - -int _modbus__ModBus_serializeReadBits(PikaObj* self, int addr, int nb) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_read_bits(ctx, addr, nb); -} - -int _modbus__ModBus_serializeReadInputBits(PikaObj* self, int addr, int nb) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_read_input_bits(ctx, addr, nb); -} - -int _modbus__ModBus_serializeReadInputRegisters(PikaObj* self, - int addr, - int nb) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_read_input_registers(ctx, addr, nb); -} - -int _modbus__ModBus_serializeReadRegisters(PikaObj* self, int addr, int nb) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_read_registers(ctx, addr, nb); -} - -int _modbus__ModBus_serializeReportSlaveId(PikaObj* self) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_report_slave_id(ctx); -} - -int _modbus__ModBus_serializeWriteAndReadRegisters(PikaObj* self, - int writeAddr, - int writeNb, - uint8_t* src, - int readAddr, - int readNb) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_write_and_read_registers( - ctx, writeAddr, writeNb, (uint16_t*)src, readAddr, readNb); -} - -int _modbus__ModBus_serializeWriteBit(PikaObj* self, int addr, int status) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_write_bit(ctx, addr, status); -} - -int _modbus__ModBus_serializeWriteBits(PikaObj* self, - int addr, - int nb, - uint8_t* src) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_write_bits(ctx, addr, nb, src); -} - -int _modbus__ModBus_serializeWriteRegister(PikaObj* self, int addr, int value) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_write_register(ctx, addr, value); -} - -int _modbus__ModBus_serializeWriteRegisters(PikaObj* self, - int addr, - int nb, - uint8_t* src) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return agile_modbus_serialize_write_registers(ctx, addr, nb, - (uint16_t*)src); -} - -Arg* _modbus__ModBus_getSendBuff(PikaObj* self) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return arg_newBytes(ctx->send_buf, ctx->send_bufsz); -} - -Arg* _modbus__ModBus_getReadBuff(PikaObj* self) { - agile_modbus_t* ctx = obj_getPtr(self, "ctx"); - return arg_newBytes(ctx->read_buf, ctx->read_bufsz); -} diff --git a/package/modbus/_modbus.pyi b/package/modbus/_modbus.pyi deleted file mode 100644 index dbac725eb..000000000 --- a/package/modbus/_modbus.pyi +++ /dev/null @@ -1,32 +0,0 @@ -class _ModBus: - def setSlave(self, slave: int): ... - - def serializeReadBits(self, addr: int, nb: int) -> int: ... - def serializeReadInputBits(self, addr: int, nb: int) -> int: ... - def serializeReadRegisters(self, addr: int, nb: int) -> int: ... - def serializeReadInputRegisters(self, addr: int, nb: int) -> int: ... - def serializeWriteBit(self, addr: int, status: int) -> int: ... - def serializeWriteRegister(self, addr: int, value: int) -> int: ... - def serializeMaskWriteRegister(self, addr: int, andMask: int, orMask: int) -> int: ... - def serializeReportSlaveId(self) -> int: ... - - def serializeWriteAndReadRegisters(self, writeAddr: int, writeNb: int, src: bytes, readAddr: int, readNb: int) -> int: ... - def serializeWriteBits(self, addr: int, nb: int, src: bytes) -> int: ... - def serializeWriteRegisters(self, addr: int, nb: int, src: bytes) -> int: ... - - def deserializeWriteBit(self, msgLength: int) -> int: ... - def deserializeWriteRegister(self, msgLength: int) -> int: ... - def deserializeWriteBits(self, msgLength: int) -> int: ... - def deserializeWriteRegisters(self, msgLength: int) -> int: ... - def deserializeMaskWriteRegister(self, msgLength: int) -> int: ... - def deserializeReadBits(self, msgLength: int) -> bytes: ... - def deserializeReadInputBits(self, msgLength: int) -> bytes: ... - def deserializeReadRegisters(self, msgLength: int) -> bytes: ... - def deserializeReadInputRegisters(self, msgLength: int) -> bytes: ... - def deserializeWriteAndReadRegisters(self, msgLength: int) -> bytes: ... - def deserializeReportSlaveId(self, msgLength: int, maxDest: int) -> bytes: ... - - def getSendBuff(self) -> bytes: ... - def getReadBuff(self) -> bytes: ... - def __init__rtu(self, sendBuffSize: int, readBuffSize: int): ... - def __init__tcp(self, sendBuffSize: int, readBuffSize: int): ... diff --git a/package/modbus/agile_modbus.c b/package/modbus/agile_modbus.c deleted file mode 100644 index 81ff40424..000000000 --- a/package/modbus/agile_modbus.c +++ /dev/null @@ -1,1519 +0,0 @@ -/** - * @file agile_modbus.c - * @brief Agile Modbus 软件包通用源文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2022-07-28 - * - @verbatim - 使用: - 用户需要实现硬件接口的 `发送数据` 、 `等待数据接收结束` 、 `清空接收缓存` 函数 - - - 主机: - 1. `agile_modbus_rtu_init` / `agile_modbus_tcp_init` 初始化 `RTU/TCP` 环境 - 2. `agile_modbus_set_slave` 设置从机地址 - 3. `清空接收缓存` - 4. `agile_modbus_serialize_xxx` 打包请求数据 - 5. `发送数据` - 6. `等待数据接收结束` - 7. `agile_modbus_deserialize_xxx` 解析响应数据 - 8. 用户处理得到的数据 - - - 从机: - 1. 实现 `agile_modbus_slave_callback_t` 类型回调函数 - 2. `agile_modbus_rtu_init` / `agile_modbus_tcp_init` 初始化 `RTU/TCP` 环境 - 3. `agile_modbus_set_slave` 设置从机地址 - 4. `等待数据接收结束` - 5. `agile_modbus_slave_handle` 处理请求数据 - 6. `清空接收缓存` (可选) - 7. `发送数据` - - @endverbatim - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#include "agile_modbus.h" -#include - -/** @defgroup COMMON Common - * @{ - */ - -/** @defgroup COMMON_Private_Constants Common Private Constants - * @{ - */ -#define AGILE_MODBUS_MSG_LENGTH_UNDEFINED -1 /**< 对应功能码数据长度未定义 */ -/** - * @} - */ - -/** @defgroup COMMON_Private_Functions Common Private Functions - * @{ - */ - -/** - * @brief 计算功能码后要接收的数据元长度 - @verbatim - ---------- Request Indication ---------- - | Client | ---------------------->| Server | - ---------- Confirmation Response ---------- - - 以 03 功能码请求报文举例 - - ---------- ------ --------------- --------- - | header | | 03 | | 00 00 00 01 | | CRC16 | - ---------- ------ --------------- --------- - - ---------- - | header | - ---------- - RTU: 设备地址 - TCP: | 事务处理标识 协议标识 长度 单元标识符 | - - --------------- - | 00 00 00 01 | - --------------- - 数据元: 与功能码相关的数据,如 03 功能码数据元中包含寄存器起始地址和寄存器长度 - - @endverbatim - * @param ctx modbus 句柄 - * @param function 功能码 - * @param msg_type 消息类型 - * @return 数据元长度 - */ -static uint8_t agile_modbus_compute_meta_length_after_function(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type) -{ - int length; - - if (msg_type == AGILE_MODBUS_MSG_INDICATION) { - if (function <= AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER) { - length = 4; - } else if (function == AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS || - function == AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS) { - length = 5; - } else if (function == AGILE_MODBUS_FC_MASK_WRITE_REGISTER) { - length = 6; - } else if (function == AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS) { - length = 9; - } else { - /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ - length = 0; - if (ctx->compute_meta_length_after_function) - length = ctx->compute_meta_length_after_function(ctx, function, msg_type); - } - } else { - /* MSG_CONFIRMATION */ - switch (function) { - case AGILE_MODBUS_FC_READ_COILS: - case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: - case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS: - case AGILE_MODBUS_FC_READ_INPUT_REGISTERS: - case AGILE_MODBUS_FC_REPORT_SLAVE_ID: - case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS: - length = 1; - break; - - case AGILE_MODBUS_FC_WRITE_SINGLE_COIL: - case AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS: - length = 4; - break; - - case AGILE_MODBUS_FC_MASK_WRITE_REGISTER: - length = 6; - break; - - default: - length = 1; - if (ctx->compute_meta_length_after_function) - length = ctx->compute_meta_length_after_function(ctx, function, msg_type); - } - } - - return length; -} - -/** - * @brief 计算数据元之后要接收的数据长度 - @verbatim - ---------- Request Indication ---------- - | Client | ---------------------->| Server | - ---------- Confirmation Response ---------- - - 以 03 功能码响应报文举例 - - ---------- ------ ------ --------- --------- - | header | | 03 | | 02 | | 00 00 | | CRC16 | - ---------- ------ ------ --------- --------- - - ---------- - | header | - ---------- - RTU: 设备地址 - TCP: | 事务处理标识 协议标识 长度 单元标识符 | - - ------ - | 02 | - ------ - 数据元: 两个字节数据 - - --------- - | 00 00 | - --------- - 数据 - - @endverbatim - * @param ctx modbus 句柄 - * @param msg 消息指针 - * @param msg_length 消息长度 - * @param msg_type 消息类型 - * @return 数据长度 - */ -static int agile_modbus_compute_data_length_after_meta(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type) -{ - int function = msg[ctx->backend->header_length]; - int length; - - if (msg_type == AGILE_MODBUS_MSG_INDICATION) { - switch (function) { - case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS: - length = msg[ctx->backend->header_length + 5]; - break; - - case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS: - length = msg[ctx->backend->header_length + 9]; - break; - - default: - length = 0; - if (ctx->compute_data_length_after_meta) - length = ctx->compute_data_length_after_meta(ctx, msg, msg_length, msg_type); - } - } else { - /* MSG_CONFIRMATION */ - if (function <= AGILE_MODBUS_FC_READ_INPUT_REGISTERS || - function == AGILE_MODBUS_FC_REPORT_SLAVE_ID || - function == AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS) { - length = msg[ctx->backend->header_length + 1]; - } else { - length = 0; - if (ctx->compute_data_length_after_meta) - length = ctx->compute_data_length_after_meta(ctx, msg, msg_length, msg_type); - } - } - - length += ctx->backend->checksum_length; - - return length; -} - -/** - * @brief 检验接收数据正确性 - * @param ctx modbus 句柄 - * @param msg 消息指针 - * @param msg_length 消息长度 - * @param msg_type 消息类型 - * @return >0:正确,modbus 数据帧长度; 其他:异常 - */ -static int agile_modbus_receive_msg_judge(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type) -{ - int remain_len = msg_length; - - remain_len -= (ctx->backend->header_length + 1); - if (remain_len < 0) - return -1; - remain_len -= agile_modbus_compute_meta_length_after_function(ctx, msg[ctx->backend->header_length], msg_type); - if (remain_len < 0) - return -1; - remain_len -= agile_modbus_compute_data_length_after_meta(ctx, msg, msg_length, msg_type); - if (remain_len < 0) - return -1; - - return ctx->backend->check_integrity(ctx, msg, msg_length - remain_len); -} - -/** - * @} - */ - -/** @defgroup COMMON_Exported_Functions Common Exported Functions - * @{ - */ - -/** - * @brief 初始化 modbus 句柄 - * @param ctx modbus 句柄 - * @param send_buf 发送缓冲区 - * @param send_bufsz 发送缓冲区大小 - * @param read_buf 接收缓冲区 - * @param read_bufsz 接收缓冲区大小 - */ -void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz) -{ - memset(ctx, 0, sizeof(agile_modbus_t)); - ctx->slave = -1; - ctx->send_buf = send_buf; - ctx->send_bufsz = send_bufsz; - ctx->read_buf = read_buf; - ctx->read_bufsz = read_bufsz; -} - -/** - * @brief 设置地址 - * @param ctx modbus 句柄 - * @param slave 地址 - * @return 0:成功 - */ -int agile_modbus_set_slave(agile_modbus_t *ctx, int slave) -{ - return ctx->backend->set_slave(ctx, slave); -} - -/** - * @brief 设置 modbus 对象的计算功能码后要接收的数据元长度回调函数 - * @param ctx modbus 句柄 - * @param cb 计算功能码后要接收的数据元长度回调函数 - * @see agile_modbus_compute_meta_length_after_function - */ -void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx, - uint8_t (*cb)(agile_modbus_t *ctx, int function, - agile_modbus_msg_type_t msg_type)) -{ - ctx->compute_meta_length_after_function = cb; -} - -/** - * @brief 设置 modbus 对象的计算数据元之后要接收的数据长度回调函数 - * @param ctx modbus 句柄 - * @param cb 计算数据元之后要接收的数据长度回调函数 - * @see agile_modbus_compute_data_length_after_meta - */ -void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx, - int (*cb)(agile_modbus_t *ctx, uint8_t *msg, - int msg_length, agile_modbus_msg_type_t msg_type)) -{ - ctx->compute_data_length_after_meta = cb; -} - -/** - * @brief 校验接收数据正确性 - * @note 该 API 返回的是 modbus 数据帧长度,比如 8 个字节的 modbus 数据帧 + 2 个字节的脏数据,返回 8 - * @param ctx modbus 句柄 - * @param msg_length 接收数据长度 - * @param msg_type 消息类型 - * @return >0:正确,modbus 数据帧长度; 其他:异常 - */ -int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type) -{ - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, msg_type); - - return rc; -} - -/** - * @} - */ - -/** @defgroup Modbus_Master Modbus Master - * @{ - */ - -/** @defgroup Master_Private_Functions Master Private Functions - * @{ - */ - -/** - * @brief 计算预期响应数据长度 - * @note 如果是特殊的功能码,返回 AGILE_MODBUS_MSG_LENGTH_UNDEFINED ,但这不代表异常。 - * agile_modbus_check_confirmation 调用该 API 处理时认为 AGILE_MODBUS_MSG_LENGTH_UNDEFINED 返回值也是有效的。 - * @param ctx modbus 句柄 - * @param req 请求数据指针 - * @return 预期响应数据长度 - */ -static int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req) -{ - int length; - const int offset = ctx->backend->header_length; - - switch (req[offset]) { - case AGILE_MODBUS_FC_READ_COILS: - case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: { - /* Header + nb values (code from write_bits) */ - int nb = (req[offset + 3] << 8) | req[offset + 4]; - length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0); - } break; - - case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS: - case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS: - case AGILE_MODBUS_FC_READ_INPUT_REGISTERS: - /* Header + 2 * nb values */ - length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]); - break; - - case AGILE_MODBUS_FC_WRITE_SINGLE_COIL: - case AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS: - length = 5; - break; - - case AGILE_MODBUS_FC_MASK_WRITE_REGISTER: - length = 7; - break; - - default: - /* The response is device specific (the header provides the - length) */ - return AGILE_MODBUS_MSG_LENGTH_UNDEFINED; - } - - return offset + length + ctx->backend->checksum_length; -} - -/** - * @brief 检查确认从机响应的数据 - * @param ctx modbus 句柄 - * @param req 请求数据指针 - * @param rsp 响应数据指针 - * @param rsp_length 响应数据长度 - * @return >=0:对应功能码响应对象的长度(如 03 功能码,值代表寄存器个数); - * 其他:异常 (-1:报文错误;其他:可根据 `-128 - $返回值` 得到异常码) - */ -static int agile_modbus_check_confirmation(agile_modbus_t *ctx, uint8_t *req, - uint8_t *rsp, int rsp_length) -{ - int rc; - int rsp_length_computed; - const int offset = ctx->backend->header_length; - const int function = rsp[offset]; - - if (ctx->backend->pre_check_confirmation) { - rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length); - if (rc < 0) - return -1; - } - - rsp_length_computed = agile_modbus_compute_response_length_from_request(ctx, req); - - /* Exception code */ - if (function >= 0x80) { - if (rsp_length == (offset + 2 + (int)ctx->backend->checksum_length) && req[offset] == (rsp[offset] - 0x80)) - return (-128 - rsp[offset + 1]); - else - return -1; - } - - /* Check length */ - if ((rsp_length == rsp_length_computed || rsp_length_computed == AGILE_MODBUS_MSG_LENGTH_UNDEFINED) && function < 0x80) { - int req_nb_value; - int rsp_nb_value; - - /* Check function code */ - if (function != req[offset]) - return -1; - - /* Check the number of values is corresponding to the request */ - switch (function) { - case AGILE_MODBUS_FC_READ_COILS: - case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: - /* Read functions, 8 values in a byte (nb - * of values in the request and byte count in - * the response. */ - req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; - req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0); - rsp_nb_value = rsp[offset + 1]; - break; - - case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS: - case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS: - case AGILE_MODBUS_FC_READ_INPUT_REGISTERS: - /* Read functions 1 value = 2 bytes */ - req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; - rsp_nb_value = (rsp[offset + 1] / 2); - break; - - case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS: - case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS: - /* N Write functions */ - req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; - rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4]; - break; - - case AGILE_MODBUS_FC_REPORT_SLAVE_ID: - /* Report slave ID (bytes received) */ - req_nb_value = rsp_nb_value = rsp[offset + 1]; - break; - - default: - /* 1 Write functions & others */ - req_nb_value = rsp_nb_value = 1; - } - - if (req_nb_value == rsp_nb_value) - rc = rsp_nb_value; - else - rc = -1; - } else - rc = -1; - - return rc; -} - -/** - * @} - */ - -/** @defgroup Master_Common_Operation_Functions Master Common Operation Functions - * @brief 常用 modbus 主机操作函数 - @verbatim - API 形式如下: - - agile_modbus_serialize_xxx 打包请求数据 - 返回值: - >0:请求数据长度 - 其他:异常 - - - agile_modbus_deserialize_xxx 解析响应数据 - 返回值: - >=0:对应功能码响应对象的长度(如 03 功能码,值代表寄存器个数) - 其他:异常 (-1:报文错误;其他:可根据 `-128 - $返回值` 得到异常码) - - @endverbatim - * @{ - */ - -int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_READ_BITS) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_COILS, addr, nb, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int i, temp, bit; - int pos = 0; - int offset; - int offset_end; - int nb; - - offset = ctx->backend->header_length + 2; - offset_end = offset + rc; - nb = (ctx->send_buf[ctx->backend->header_length + 3] << 8) + ctx->send_buf[ctx->backend->header_length + 4]; - - for (i = offset; i < offset_end; i++) { - /* Shift reg hi_byte to temp */ - temp = ctx->read_buf[i]; - - for (bit = 0x01; (bit & 0xff) && (pos < nb);) { - dest[pos++] = (temp & bit) ? 1 : 0; - bit = bit << 1; - } - } - - return nb; -} - -int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_READ_BITS) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int i, temp, bit; - int pos = 0; - int offset; - int offset_end; - int nb; - - offset = ctx->backend->header_length + 2; - offset_end = offset + rc; - nb = (ctx->send_buf[ctx->backend->header_length + 3] << 8) + ctx->send_buf[ctx->backend->header_length + 4]; - - for (i = offset; i < offset_end; i++) { - /* Shift reg hi_byte to temp */ - temp = ctx->read_buf[i]; - - for (bit = 0x01; (bit & 0xff) && (pos < nb);) { - dest[pos++] = (temp & bit) ? 1 : 0; - bit = bit << 1; - } - } - - return nb; -} - -int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_READ_REGISTERS) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_HOLDING_REGISTERS, addr, nb, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int offset; - int i; - - offset = ctx->backend->header_length; - for (i = 0; i < rc; i++) { - /* shift reg hi_byte to temp OR with lo_byte */ - dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)]; - } - - return rc; -} - -int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_READ_REGISTERS) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_INPUT_REGISTERS, addr, nb, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int offset; - int i; - - offset = ctx->backend->header_length; - for (i = 0; i < rc; i++) { - /* shift reg hi_byte to temp OR with lo_byte */ - dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)]; - } - - return rc; -} - -int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER, addr, (int)value, ctx->send_buf); - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_WRITE_BITS) - return -1; - - int i; - int byte_count; - int req_length; - int bit_check = 0; - int pos = 0; - - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS, addr, nb, ctx->send_buf); - byte_count = (nb / 8) + ((nb % 8) ? 1 : 0); - - min_req_length += (1 + byte_count); - if (ctx->send_bufsz < min_req_length) - return -1; - - ctx->send_buf[req_length++] = byte_count; - for (i = 0; i < byte_count; i++) { - int bit; - - bit = 0x01; - ctx->send_buf[req_length] = 0; - - while ((bit & 0xFF) && (bit_check++ < nb)) { - if (src[pos++]) - ctx->send_buf[req_length] |= bit; - else - ctx->send_buf[req_length] &= ~bit; - - bit = bit << 1; - } - req_length++; - } - - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (nb > AGILE_MODBUS_MAX_WRITE_REGISTERS) - return -1; - - int i; - int req_length; - int byte_count; - - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS, addr, nb, ctx->send_buf); - byte_count = nb * 2; - - min_req_length += (1 + byte_count); - if (ctx->send_bufsz < min_req_length) - return -1; - - ctx->send_buf[req_length++] = byte_count; - for (i = 0; i < nb; i++) { - ctx->send_buf[req_length++] = src[i] >> 8; - ctx->send_buf[req_length++] = src[i] & 0x00FF; - } - - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length + 2; - if (ctx->send_bufsz < min_req_length) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_MASK_WRITE_REGISTER, addr, 0, ctx->send_buf); - - /* HACKISH, count is not used */ - req_length -= 2; - - ctx->send_buf[req_length++] = and_mask >> 8; - ctx->send_buf[req_length++] = and_mask & 0x00ff; - ctx->send_buf[req_length++] = or_mask >> 8; - ctx->send_buf[req_length++] = or_mask & 0x00ff; - - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx, - int write_addr, int write_nb, - const uint16_t *src, - int read_addr, int read_nb) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - if (write_nb > AGILE_MODBUS_MAX_WR_WRITE_REGISTERS) - return -1; - - if (read_nb > AGILE_MODBUS_MAX_WR_READ_REGISTERS) - return -1; - - int req_length; - int i; - int byte_count; - - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS, read_addr, read_nb, ctx->send_buf); - byte_count = write_nb * 2; - - min_req_length += (5 + byte_count); - if (ctx->send_bufsz < min_req_length) - return -1; - - ctx->send_buf[req_length++] = write_addr >> 8; - ctx->send_buf[req_length++] = write_addr & 0x00ff; - ctx->send_buf[req_length++] = write_nb >> 8; - ctx->send_buf[req_length++] = write_nb & 0x00ff; - ctx->send_buf[req_length++] = byte_count; - for (i = 0; i < write_nb; i++) { - ctx->send_buf[req_length++] = src[i] >> 8; - ctx->send_buf[req_length++] = src[i] & 0x00FF; - } - - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int offset; - int i; - - offset = ctx->backend->header_length; - for (i = 0; i < rc; i++) { - /* shift reg hi_byte to temp OR with lo_byte */ - dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)]; - } - - return rc; -} - -int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - - int req_length = 0; - req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_REPORT_SLAVE_ID, 0, 0, ctx->send_buf); - /* HACKISH, addr and count are not used */ - req_length -= 4; - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - if (max_dest <= 0) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - if (rc < 0) - return rc; - - int i; - int offset; - - offset = ctx->backend->header_length + 2; - - /* Byte count, slave id, run indicator status and - additional data. Truncate copy to max_dest. */ - for (i = 0; i < rc && i < max_dest; i++) { - dest[i] = ctx->read_buf[offset + i]; - } - - return rc; -} - -/** - * @} - */ - -/** @defgroup Master_Raw_Operation_Functions Master Raw Operation Functions - * @{ - */ - -/** - * @brief 将原始数据打包成请求报文 - * @param ctx modbus 句柄 - * @param raw_req 原始报文(PDU + Slave address) - * @param raw_req_length 原始报文长度 - * @return >0:请求数据长度; 其他:异常 - */ -int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length) -{ - if (raw_req_length < 2) { - /* The raw request must contain function and slave at least and - must not be longer than the maximum pdu length plus the slave - address. */ - - return -1; - } - - int min_req_length = ctx->backend->header_length + 1 + ctx->backend->checksum_length + raw_req_length - 2; - if (ctx->send_bufsz < min_req_length) - return -1; - - agile_modbus_sft_t sft; - int req_length; - - sft.slave = raw_req[0]; - sft.function = raw_req[1]; - /* The t_id is left to zero */ - sft.t_id = 0; - /* This response function only set the header so it's convenient here */ - req_length = ctx->backend->build_response_basis(&sft, ctx->send_buf); - - if (raw_req_length > 2) { - /* Copy data after function code */ - memcpy(ctx->send_buf + req_length, raw_req + 2, raw_req_length - 2); - req_length += raw_req_length - 2; - } - - req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length); - - return req_length; -} - -/** - * @brief 解析响应原始数据 - * @param ctx modbus 句柄 - * @param msg_length 接收数据长度 - * @return >=0:对应功能码响应对象的长度(如 03 功能码,值代表寄存器个数); - * 其他:异常 (-1:报文错误;其他:可根据 `-128 - $返回值` 得到异常码) - */ -int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length) -{ - int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_req_length) - return -1; - if ((msg_length <= 0) || (msg_length > ctx->read_bufsz)) - return -1; - - int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, AGILE_MODBUS_MSG_CONFIRMATION); - if (rc < 0) - return -1; - - rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc); - - return rc; -} - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup Modbus_Slave Modbus Slave - * @{ - */ - -/** @defgroup Slave_Private_Functions Slave Private Functions - * @{ - */ - -/** - * @brief 打包异常响应数据 - * @param ctx modbus 句柄 - * @param sft modbus 信息头 - * @param exception_code 异常码 - * @return 响应数据长度 - */ -static int agile_modbus_serialize_response_exception(agile_modbus_t *ctx, agile_modbus_sft_t *sft, int exception_code) -{ - int rsp_length; - - /* Build exception response */ - sft->function = sft->function + 0x80; - rsp_length = ctx->backend->build_response_basis(sft, ctx->send_buf); - ctx->send_buf[rsp_length++] = exception_code; - - return rsp_length; -} - -/** - * @} - */ - -/** @defgroup Slave_Operation_Functions Slave Operation Functions - * @{ - */ - -/** - * @brief 从机 IO 设置 - * @param buf 存放 IO 数据区 - * @param index IO 索引(第几个 IO) - * @param status IO 状态 - */ -void agile_modbus_slave_io_set(uint8_t *buf, int index, int status) -{ - int offset = index / 8; - int shift = index % 8; - - if (status) - buf[offset] |= (0x01 << shift); - else - buf[offset] &= ~(0x01 << shift); -} - -/** - * @brief 读取从机 IO 状态 - * @param buf IO 数据区域 - * @param index IO 索引(第几个 IO) - * @return IO 状态(1/0) - */ -uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index) -{ - int offset = index / 8; - int shift = index % 8; - - uint8_t status = (buf[offset] & (0x01 << shift)) ? 1 : 0; - - return status; -} - -/** - * @brief 从机寄存器设置 - * @param buf 存放数据区 - * @param index 寄存器索引(第几个寄存器) - * @param data 寄存器数据 - */ -void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data) -{ - buf[index * 2] = data >> 8; - buf[index * 2 + 1] = data & 0xFF; -} - -/** - * @brief 读取从机寄存器数据 - * @param buf 寄存器数据区域 - * @param index 寄存器索引(第几个寄存器) - * @return 寄存器数据 - */ -uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index) -{ - uint16_t data = (buf[index * 2] << 8) + buf[index * 2 + 1]; - - return data; -} - -/** - * @brief 从机数据处理 - * @param ctx modbus 句柄 - * @param msg_length 接收数据长度 - * @param slave_strict 从机地址严格检查标志 - * @arg 0: 不比对从机地址 - * @arg 1: 比对从机地址 - * @param slave_cb 从机回调函数 - * @param slave_data 从机回调函数私有数据 - * @param frame_length 存放 modbus 数据帧长度 - * @return >=0:要响应的数据长度; 其他:异常 - */ -int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, - agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length) -{ - int min_rsp_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length; - if (ctx->send_bufsz < min_rsp_length) - return -1; - - int req_length = agile_modbus_receive_judge(ctx, msg_length, AGILE_MODBUS_MSG_INDICATION); - if (req_length < 0) - return -1; - if (frame_length) - *frame_length = req_length; - - int offset; - int slave; - int function; - uint16_t address; - int rsp_length = 0; - int exception_code = 0; - agile_modbus_sft_t sft; - uint8_t *req = ctx->read_buf; - uint8_t *rsp = ctx->send_buf; - - memset(rsp, 0, ctx->send_bufsz); - offset = ctx->backend->header_length; - slave = req[offset - 1]; - function = req[offset]; - address = (req[offset + 1] << 8) + req[offset + 2]; - - sft.slave = slave; - sft.function = function; - sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); - - struct agile_modbus_slave_info slave_info = {0}; - slave_info.sft = &sft; - slave_info.rsp_length = &rsp_length; - slave_info.address = address; - - if (slave_strict) { - if ((slave != ctx->slave) && (slave != AGILE_MODBUS_BROADCAST_ADDRESS)) - return 0; - } - - switch (function) { - case AGILE_MODBUS_FC_READ_COILS: - case AGILE_MODBUS_FC_READ_DISCRETE_INPUTS: { - int nb = (req[offset + 3] << 8) + req[offset + 4]; - if (nb < 1 || AGILE_MODBUS_MAX_READ_BITS < nb) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - int end_address = (int)address + nb - 1; - if (end_address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - slave_info.nb = (nb / 8) + ((nb % 8) ? 1 : 0); - rsp[rsp_length++] = slave_info.nb; - slave_info.send_index = rsp_length; - rsp_length += slave_info.nb; - slave_info.nb = nb; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - } break; - - case AGILE_MODBUS_FC_READ_HOLDING_REGISTERS: - case AGILE_MODBUS_FC_READ_INPUT_REGISTERS: { - int nb = (req[offset + 3] << 8) + req[offset + 4]; - if (nb < 1 || AGILE_MODBUS_MAX_READ_REGISTERS < nb) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - int end_address = (int)address + nb - 1; - if (end_address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - slave_info.nb = nb << 1; - rsp[rsp_length++] = slave_info.nb; - slave_info.send_index = rsp_length; - rsp_length += slave_info.nb; - slave_info.nb = nb; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - } break; - - case AGILE_MODBUS_FC_WRITE_SINGLE_COIL: { - //! warning: comparison is always false due to limited range of data type [-Wtype-limits] - #if 0 - if (address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - #endif - - int data = (req[offset + 3] << 8) + req[offset + 4]; - if (data == 0xFF00 || data == 0x0) - data = data ? 1 : 0; - else { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - slave_info.buf = (uint8_t *)&data; - rsp_length = req_length; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - memcpy(rsp, req, req_length); - } break; - - case AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER: { - //! warning: comparison is always false due to limited range of data type [-Wtype-limits] - #if 0 - if (address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - #endif - - int data = (req[offset + 3] << 8) + req[offset + 4]; - - slave_info.buf = (uint8_t *)&data; - rsp_length = req_length; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - memcpy(rsp, req, req_length); - } break; - - case AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS: { - int nb = (req[offset + 3] << 8) + req[offset + 4]; - int nb_bits = req[offset + 5]; - if (nb < 1 || AGILE_MODBUS_MAX_WRITE_BITS < nb || nb_bits * 8 < nb) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - int end_address = (int)address + nb - 1; - if (end_address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - slave_info.nb = nb; - slave_info.buf = &req[offset + 6]; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + 4)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - /* 4 to copy the bit address (2) and the quantity of bits */ - memcpy(rsp + rsp_length, req + rsp_length, 4); - rsp_length += 4; - } break; - - case AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS: { - int nb = (req[offset + 3] << 8) + req[offset + 4]; - int nb_bytes = req[offset + 5]; - if (nb < 1 || AGILE_MODBUS_MAX_WRITE_REGISTERS < nb || nb_bytes != nb * 2) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - int end_address = (int)address + nb - 1; - if (end_address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - slave_info.nb = nb; - slave_info.buf = &req[offset + 6]; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + 4)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - /* 4 to copy the address (2) and the no. of registers */ - memcpy(rsp + rsp_length, req + rsp_length, 4); - rsp_length += 4; - - } break; - - case AGILE_MODBUS_FC_REPORT_SLAVE_ID: { - int str_len; - int byte_count_pos; - - slave_cb = NULL; - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - /* Skip byte count for now */ - byte_count_pos = rsp_length++; - rsp[rsp_length++] = ctx->slave; - /* Run indicator status to ON */ - rsp[rsp_length++] = 0xFF; - - str_len = strlen(AGILE_MODBUS_VERSION_STRING); - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + str_len)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - memcpy(rsp + rsp_length, AGILE_MODBUS_VERSION_STRING, str_len); - rsp_length += str_len; - rsp[byte_count_pos] = rsp_length - byte_count_pos - 1; - } break; - - case AGILE_MODBUS_FC_READ_EXCEPTION_STATUS: - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION; - break; - - case AGILE_MODBUS_FC_MASK_WRITE_REGISTER: { - //! warning: comparison is always false due to limited range of data type [-Wtype-limits] - #if 0 - if (address > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - #endif - - slave_info.buf = &req[offset + 3]; - rsp_length = req_length; - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - memcpy(rsp, req, req_length); - } break; - - case AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS: { - int nb = (req[offset + 3] << 8) + req[offset + 4]; - uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6]; - int nb_write = (req[offset + 7] << 8) + req[offset + 8]; - int nb_write_bytes = req[offset + 9]; - if (nb_write < 1 || AGILE_MODBUS_MAX_WR_WRITE_REGISTERS < nb_write || - nb < 1 || AGILE_MODBUS_MAX_WR_READ_REGISTERS < nb || - nb_write_bytes != nb_write * 2) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; - break; - } - - int end_address = (int)address + nb - 1; - int end_address_write = (int)address_write + nb_write - 1; - if (end_address > 0xFFFF || end_address_write > 0xFFFF) { - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; - break; - } - - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - rsp[rsp_length++] = nb << 1; - slave_info.buf = &req[offset + 3]; - slave_info.send_index = rsp_length; - rsp_length += (nb << 1); - if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) { - exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE; - break; - } - } break; - - default: { - if (slave_cb == NULL) - exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION; - else { - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - slave_info.send_index = rsp_length; - slave_info.buf = &req[offset + 1]; - slave_info.nb = req_length - offset - 1; - } - } break; - } - - if (exception_code) - rsp_length = agile_modbus_serialize_response_exception(ctx, &sft, exception_code); - else { - if (slave_cb) { - int ret = slave_cb(ctx, &slave_info, slave_data); - - if (ret < 0) { - if (ret == -AGILE_MODBUS_EXCEPTION_UNKNOW) - rsp_length = 0; - else - rsp_length = agile_modbus_serialize_response_exception(ctx, &sft, -ret); - } - } - } - - if (rsp_length) { - if ((ctx->backend->backend_type == AGILE_MODBUS_BACKEND_TYPE_RTU) && (slave == AGILE_MODBUS_BROADCAST_ADDRESS)) - return 0; - - rsp_length = ctx->backend->send_msg_pre(rsp, rsp_length); - } - - return rsp_length; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/package/modbus/agile_modbus.h b/package/modbus/agile_modbus.h deleted file mode 100644 index 4be7429b5..000000000 --- a/package/modbus/agile_modbus.h +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @file agile_modbus.h - * @brief Agile Modbus 软件包通用头文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2022-07-28 - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#ifndef __PKG_AGILE_MODBUS_H -#define __PKG_AGILE_MODBUS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** @addtogroup COMMON - * @{ - */ - -/** @defgroup COMMON_Exported_Constants Common Exported Constants - * @{ - */ - -/** @defgroup Modbus_Function_Codes Modbus Function Codes - * @{ - */ -#define AGILE_MODBUS_FC_READ_COILS 0x01 -#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS 0x02 -#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS 0x03 -#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS 0x04 -#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL 0x05 -#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 -#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS 0x07 -#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F -#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 -#define AGILE_MODBUS_FC_REPORT_SLAVE_ID 0x11 -#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER 0x16 -#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 -/** - * @} - */ - -/** @defgroup Modbus_Constants Modbus Constants - * @{ - */ -#define AGILE_MODBUS_VERSION_STRING "AMB_1.1.0" /**< Agile Modbus 版本号 */ - -#define AGILE_MODBUS_BROADCAST_ADDRESS 0 /**< Modbus 广播地址 */ - -/** @name Quantity limit of Coils - @verbatim - Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) - Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0) - (chapter 6 section 11 page 29) - Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0) - - @endverbatim - * @{ - */ -#define AGILE_MODBUS_MAX_READ_BITS 2000 -#define AGILE_MODBUS_MAX_WRITE_BITS 1968 -/** - * @} - */ - -/** @name Quantity limit of Registers - @verbatim - Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15) - Quantity of Registers to read (2 bytes): 1 to 125 (0x7D) - (chapter 6 section 12 page 31) - Quantity of Registers to write (2 bytes) 1 to 123 (0x7B) - (chapter 6 section 17 page 38) - Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79) - - @endverbatim - * @{ - */ -#define AGILE_MODBUS_MAX_READ_REGISTERS 125 -#define AGILE_MODBUS_MAX_WRITE_REGISTERS 123 -#define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS 121 -#define AGILE_MODBUS_MAX_WR_READ_REGISTERS 125 -/** - * @} - */ - -/** - @verbatim - The size of the MODBUS PDU is limited by the size constraint inherited from - the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 - bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server - address (1 byte) - CRC (2 bytes) = 253 bytes. - - @endverbatim - */ -#define AGILE_MODBUS_MAX_PDU_LENGTH 253 - -/** - @verbatim - Consequently: - - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256 - bytes. - - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes. - so the maximum of both backend in 260 bytes. This size can used to allocate - an array of bytes to store responses and it will be compatible with the two - backends. - - @endverbatim - */ -#define AGILE_MODBUS_MAX_ADU_LENGTH 260 -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup COMMON_Exported_Types Common Exported Types - * @{ - */ - -/** - * @brief Modbus 异常码 - */ -enum { - AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01, - AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, - AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, - AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE, - AGILE_MODBUS_EXCEPTION_ACKNOWLEDGE, - AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY, - AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE, - AGILE_MODBUS_EXCEPTION_MEMORY_PARITY, - AGILE_MODBUS_EXCEPTION_NOT_DEFINED, - AGILE_MODBUS_EXCEPTION_GATEWAY_PATH, - AGILE_MODBUS_EXCEPTION_GATEWAY_TARGET, - AGILE_MODBUS_EXCEPTION_UNKNOW = 0xff -}; - -/** - * @brief Modbus 后端类型 - */ -typedef enum { - AGILE_MODBUS_BACKEND_TYPE_RTU = 0, /**< RTU */ - AGILE_MODBUS_BACKEND_TYPE_TCP /**< TCP */ -} agile_modbus_backend_type_t; - -/** - * @brief Modbus 收到消息类型 - * - @verbatim - ---------- Request Indication ---------- - | Client | ---------------------->| Server | - ---------- Confirmation Response ---------- - - @endverbatim - */ -typedef enum { - AGILE_MODBUS_MSG_INDICATION, /**< 主机端的请求消息 */ - AGILE_MODBUS_MSG_CONFIRMATION /**< 服务器端的请求消息 */ -} agile_modbus_msg_type_t; - -/** - * @brief 包含 modbus 头部参数结构体 - */ -typedef struct agile_modbus_sft { - int slave; /**< 从机地址 */ - int function; /**< 功能码 */ - int t_id; /**< 事务标识符 */ -} agile_modbus_sft_t; - -typedef struct agile_modbus agile_modbus_t; /**< Agile Modbus 结构体 */ - -/** - * @brief Agile Modbus 后端接口结构体 - */ -typedef struct agile_modbus_backend { - uint32_t backend_type; /**< 后端类型 */ - uint32_t header_length; /**< 头部长度,不包含功能码 */ - uint32_t checksum_length; /**< 校验数据长度 */ - uint32_t max_adu_length; /**< 后端 ADU 长度 */ - int (*set_slave)(agile_modbus_t *ctx, int slave); /**< 设置地址接口 */ - int (*build_request_basis)(agile_modbus_t *ctx, int function, int addr, - int nb, uint8_t *req); /**< 构建基础请求报文接口 */ - int (*build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp); /**< 构建基础响应报文接口 */ - int (*prepare_response_tid)(const uint8_t *req, int *req_length); /**< 准备响应接口 */ - int (*send_msg_pre)(uint8_t *req, int req_length); /**< 预发送数据接口 */ - int (*check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length); /**< 检查接收数据完整性接口 */ - int (*pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req, - const uint8_t *rsp, int rsp_length); /**< 预检查确认接口 */ -} agile_modbus_backend_t; - -/** - * @brief Agile Modbus 结构体 - */ -struct agile_modbus { - int slave; /**< 从机地址 */ - uint8_t *send_buf; /**< 发送缓冲区 */ - int send_bufsz; /**< 发送缓冲区大小 */ - uint8_t *read_buf; /**< 接收缓冲区 */ - int read_bufsz; /**< 接收缓冲区大小 */ - uint8_t (*compute_meta_length_after_function)(agile_modbus_t *ctx, int function, - agile_modbus_msg_type_t msg_type); /**< 自定义计算数据元长度接口 */ - int (*compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg, - int msg_length, agile_modbus_msg_type_t msg_type); /**< 自定义计算数据长度接口 */ - const agile_modbus_backend_t *backend; /**< 后端接口 */ - void *backend_data; /**< 后端数据,指向 RTU 或 TCP 结构体 */ -}; - -/** - * @} - */ - -/** @addtogroup Modbus_Slave - * @{ - */ - -/** @defgroup Slave_Exported_Types Slave Exported Types - * @{ - */ - -/** - * @brief Agile Modbus 从机信息结构体 - */ -struct agile_modbus_slave_info { - agile_modbus_sft_t *sft; /**< sft 结构体指针 */ - int *rsp_length; /**< 响应数据长度指针 */ - int address; /**< 寄存器地址 */ - int nb; /**< 数目 */ - uint8_t *buf; /**< 不同功能码需要使用的数据域 */ - int send_index; /**< 发送缓冲区当前索引 */ -}; - -/** - * @brief 从机回调函数 - * @param ctx modbus 句柄 - * @param slave_info 从机信息体 - * @param data 私有数据 - * @return =0:正常; - * <0:异常 - * (-AGILE_MODBUS_EXCEPTION_UNKNOW(-255): 未知异常,从机不会打包响应数据) - * (其他负数异常码: 从机会打包异常响应数据) - */ -typedef int (*agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data); - -/** - * @} - */ - -/** - * @} - */ - -/** @addtogroup COMMON_Exported_Functions - * @{ - */ -void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz); -int agile_modbus_set_slave(agile_modbus_t *ctx, int slave); -void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx, - uint8_t (*cb)(agile_modbus_t *ctx, int function, - agile_modbus_msg_type_t msg_type)); -void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx, - int (*cb)(agile_modbus_t *ctx, uint8_t *msg, - int msg_length, agile_modbus_msg_type_t msg_type)); -int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type); -/** - * @} - */ - -/** @addtogroup Modbus_Master - * @{ - */ - -/** @addtogroup Master_Common_Operation_Functions - * @{ - */ -int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb); -int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest); -int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb); -int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest); -int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb); -int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest); -int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb); -int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest); -int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status); -int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length); -int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value); -int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length); -int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src); -int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length); -int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src); -int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length); -int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); -int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length); -int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx, - int write_addr, int write_nb, - const uint16_t *src, - int read_addr, int read_nb); -int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest); -int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx); -int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest); -/** - * @} - */ - -/** @addtogroup Master_Raw_Operation_Functions - * @{ - */ -int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length); -int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length); -/** - * @} - */ - -/** - * @} - */ - -/** @addtogroup Modbus_Slave - * @{ - */ - -/** @addtogroup Slave_Operation_Functions - * @{ - */ -int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, - agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length); -void agile_modbus_slave_io_set(uint8_t *buf, int index, int status); -uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index); -void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data); -uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index); -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/* Include RTU and TCP module */ -#include "agile_modbus_rtu.h" -#include "agile_modbus_tcp.h" - -#ifdef __cplusplus -} -#endif - -#endif /* __PKG_AGILE_MODBUS_H */ diff --git a/package/modbus/agile_modbus_rtu.c b/package/modbus/agile_modbus_rtu.c deleted file mode 100644 index 95b24cf0a..000000000 --- a/package/modbus/agile_modbus_rtu.c +++ /dev/null @@ -1,291 +0,0 @@ -/** - * @file agile_modbus_rtu.c - * @brief Agile Modbus 软件包 RTU 源文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2021-12-02 - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#include "agile_modbus.h" -#include "agile_modbus_rtu.h" - -/** @defgroup RTU RTU - * @{ - */ - -/** @defgroup RTU_Private_Constants RTU Private Constants - * @{ - */ -/** Table of CRC values for high-order byte */ -static const uint8_t _table_crc_hi[] = - { - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40}; - -/** Table of CRC values for low-order byte */ -static const uint8_t _table_crc_lo[] = - { - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, - 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, - 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, - 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, - 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, - 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, - 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, - 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, - 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, - 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, - 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, - 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, - 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, - 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, - 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, - 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, - 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, - 0x43, 0x83, 0x41, 0x81, 0x80, 0x40}; -/** - * @} - */ - -/** @defgroup RTU_Private_Functions RTU Private Functions - * @{ - */ - -/** - * @brief RTU CRC16 计算 - * @param buffer 数据指针 - * @param buffer_length 数据长度 - * @return CRC16 值 - */ -static uint16_t agile_modbus_rtu_crc16(uint8_t *buffer, uint16_t buffer_length) -{ - uint8_t crc_hi = 0xFF; /* high CRC byte initialized */ - uint8_t crc_lo = 0xFF; /* low CRC byte initialized */ - unsigned int i; /* will index into CRC lookup */ - - /* pass through message buffer */ - while (buffer_length--) { - i = crc_hi ^ *buffer++; /* calculate the CRC */ - crc_hi = crc_lo ^ _table_crc_hi[i]; - crc_lo = _table_crc_lo[i]; - } - - return (crc_hi << 8 | crc_lo); -} - -/** - * @brief RTU 设置地址接口 - * @param ctx modbus 句柄 - * @param slave 从机地址 - * @return 0:成功 - */ -static int agile_modbus_rtu_set_slave(agile_modbus_t *ctx, int slave) -{ - ctx->slave = slave; - return 0; -} - -/** - * @brief RTU 构建基础请求报文接口(头部报文) - * @param ctx modbus 句柄 - * @param function 功能码 - * @param addr 寄存器地址 - * @param nb 寄存器数目 - * @param req 数据存放指针 - * @return 数据长度 - */ -static int agile_modbus_rtu_build_request_basis(agile_modbus_t *ctx, int function, - int addr, int nb, - uint8_t *req) -{ - req[0] = ctx->slave; - req[1] = function; - req[2] = addr >> 8; - req[3] = addr & 0x00ff; - req[4] = nb >> 8; - req[5] = nb & 0x00ff; - - return AGILE_MODBUS_RTU_PRESET_REQ_LENGTH; -} - -/** - * @brief RTU 构建基础响应报文接口(头部报文) - * @param sft modbus 头部参数结构体指针 - * @param rsp 数据存放指针 - * @return 数据长度 - */ -static int agile_modbus_rtu_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp) -{ - rsp[0] = sft->slave; - rsp[1] = sft->function; - - return AGILE_MODBUS_RTU_PRESET_RSP_LENGTH; -} - -/** - * @brief RTU 准备响应接口 - * @note 该 API 会将 req_length 自动减去 AGILE_MODBUS_RTU_CHECKSUM_LENGTH 长度 - * @param req 请求数据指针 - * @param req_length 请求数据长度 - * @return 0 (RTU 没有事务标识符) - */ -static int agile_modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length) -{ - (*req_length) -= AGILE_MODBUS_RTU_CHECKSUM_LENGTH; - /* No TID */ - return 0; -} - -/** - * @brief RTU 预发送数据接口 - * @note 该 API 会计算 CRC16 并自动填入尾部 - * @param req 数据存放指针 - * @param req_length 已有数据长度 - * @return 数据长度 - */ -static int agile_modbus_rtu_send_msg_pre(uint8_t *req, int req_length) -{ - uint16_t crc = agile_modbus_rtu_crc16(req, req_length); - req[req_length++] = crc >> 8; - req[req_length++] = crc & 0x00FF; - - return req_length; -} - -/** - * @brief RTU 检查接收数据完整性接口(CRC16 对比) - * @param ctx modbus 句柄 - * @param msg 接收数据指针 - * @param msg_length 有效数据长度 - * @return >0:有效数据长度; 其他:异常 - */ -static int agile_modbus_rtu_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length) -{ - uint16_t crc_calculated; - uint16_t crc_received; - - crc_calculated = agile_modbus_rtu_crc16(msg, msg_length - 2); - crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; - - /* Check CRC of msg */ - if (crc_calculated == crc_received) - return msg_length; - - return -1; -} - -/** - * @brief RTU 预检查确认接口(请求响应地址对比) - * @note 如果请求地址是广播地址0,返回成功 - * @param ctx modbus 句柄 - * @param req 请求数据指针 - * @param rsp 响应数据指针 - * @param rsp_length 响应数据长度 - * @return 0:成功; 其他:异常 - */ -static int agile_modbus_rtu_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req, - const uint8_t *rsp, int rsp_length) -{ - /* Check responding slave is the slave we requested (except for broacast - * request) */ - if (req[0] != rsp[0] && req[0] != AGILE_MODBUS_BROADCAST_ADDRESS) - return -1; - - return 0; -} - -/** - * @} - */ - -/** @addtogroup RTU_Private_Constants - * @{ - */ - -/** - * @brief RTU 后端接口 - */ -static const agile_modbus_backend_t agile_modbus_rtu_backend = - { - AGILE_MODBUS_BACKEND_TYPE_RTU, - AGILE_MODBUS_RTU_HEADER_LENGTH, - AGILE_MODBUS_RTU_CHECKSUM_LENGTH, - AGILE_MODBUS_RTU_MAX_ADU_LENGTH, - agile_modbus_rtu_set_slave, - agile_modbus_rtu_build_request_basis, - agile_modbus_rtu_build_response_basis, - agile_modbus_rtu_prepare_response_tid, - agile_modbus_rtu_send_msg_pre, - agile_modbus_rtu_check_integrity, - agile_modbus_rtu_pre_check_confirmation}; - -/** - * @} - */ - -/** @defgroup RTU_Exported_Functions RTU Exported Functions - * @{ - */ - -/** - * @brief RTU 初始化 - * @param ctx RTU 句柄 - * @param send_buf 发送缓冲区 - * @param send_bufsz 发送缓冲区大小 - * @param read_buf 接收缓冲区 - * @param read_bufsz 接收缓冲区大小 - * @return 0:成功 - */ -int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz) -{ - agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz); - ctx->_ctx.backend = &agile_modbus_rtu_backend; - ctx->_ctx.backend_data = ctx; - - return 0; -} - -/** - * @} - */ - -/** - * @} - */ diff --git a/package/modbus/agile_modbus_rtu.h b/package/modbus/agile_modbus_rtu.h deleted file mode 100644 index 062aa84a6..000000000 --- a/package/modbus/agile_modbus_rtu.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file agile_modbus_rtu.h - * @brief Agile Modbus 软件包 RTU 头文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2021-12-02 - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#ifndef __PKG_AGILE_MODBUS_RTU_H -#define __PKG_AGILE_MODBUS_RTU_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** @addtogroup RTU - * @{ - */ - -/** @defgroup RTU_Exported_Constants RTU Exported Constants - * @{ - */ -#define AGILE_MODBUS_RTU_HEADER_LENGTH 1 -#define AGILE_MODBUS_RTU_PRESET_REQ_LENGTH 6 -#define AGILE_MODBUS_RTU_PRESET_RSP_LENGTH 2 - -#define AGILE_MODBUS_RTU_CHECKSUM_LENGTH 2 - -/** - @verbatim - Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 - RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes - - @endverbatim - */ -#define AGILE_MODBUS_RTU_MAX_ADU_LENGTH 256 -/** - * @} - */ - -/** @defgroup RTU_Exported_Types RTU Exported Types - * @{ - */ - -/** - * @brief RTU 结构体 - */ -typedef struct agile_modbus_rtu { - agile_modbus_t _ctx; /**< modbus 句柄 */ -} agile_modbus_rtu_t; - -/** - * @} - */ - -/** @addtogroup RTU_Exported_Functions - * @{ - */ -int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz); -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __PKG_AGILE_MODBUS_RTU_H */ diff --git a/package/modbus/agile_modbus_tcp.c b/package/modbus/agile_modbus_tcp.c deleted file mode 100644 index 478045994..000000000 --- a/package/modbus/agile_modbus_tcp.c +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file agile_modbus_tcp.c - * @brief Agile Modbus 软件包 TCP 源文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2021-12-02 - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#include "agile_modbus.h" -#include "agile_modbus_tcp.h" - -/** @defgroup TCP TCP - * @{ - */ - -/** @defgroup TCP_Private_Functions TCP Private Functions - * @{ - */ - -/** - * @brief TCP 设置地址接口 - * @param ctx modbus 句柄 - * @param slave 从机地址 - * @return 0:成功 - */ -static int agile_modbus_tcp_set_slave(agile_modbus_t *ctx, int slave) -{ - ctx->slave = slave; - return 0; -} - -/** - * @brief TCP 构建基础请求报文接口(头部报文) - * @param ctx modbus 句柄 - * @param function 功能码 - * @param addr 寄存器地址 - * @param nb 寄存器数目 - * @param req 数据存放指针 - * @return 数据长度 - */ -static int agile_modbus_tcp_build_request_basis(agile_modbus_t *ctx, int function, - int addr, int nb, - uint8_t *req) -{ - agile_modbus_tcp_t *ctx_tcp = ctx->backend_data; - - /* Increase transaction ID */ - if (ctx_tcp->t_id < UINT16_MAX) - ctx_tcp->t_id++; - else - ctx_tcp->t_id = 0; - req[0] = ctx_tcp->t_id >> 8; - req[1] = ctx_tcp->t_id & 0x00ff; - - /* Protocol Modbus */ - req[2] = 0; - req[3] = 0; - - /* Length will be defined later by set_req_length_tcp at offsets 4 - and 5 */ - - req[6] = ctx->slave; - req[7] = function; - req[8] = addr >> 8; - req[9] = addr & 0x00ff; - req[10] = nb >> 8; - req[11] = nb & 0x00ff; - - return AGILE_MODBUS_TCP_PRESET_REQ_LENGTH; -} - -/** - * @brief TCP 构建基础响应报文接口(头部报文) - * @param sft modbus 头部参数结构体指针 - * @param rsp 数据存放指针 - * @return 数据长度 - */ -static int agile_modbus_tcp_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp) -{ - /* Extract from MODBUS Messaging on TCP/IP Implementation - Guide V1.0b (page 23/46): - The transaction identifier is used to associate the future - response with the request. */ - rsp[0] = sft->t_id >> 8; - rsp[1] = sft->t_id & 0x00ff; - - /* Protocol Modbus */ - rsp[2] = 0; - rsp[3] = 0; - - /* Length will be set later by send_msg (4 and 5) */ - - /* The slave ID is copied from the indication */ - rsp[6] = sft->slave; - rsp[7] = sft->function; - - return AGILE_MODBUS_TCP_PRESET_RSP_LENGTH; -} - -/** - * @brief TCP 准备响应接口 - * @param req 请求数据指针 - * @param req_length 请求数据长度 - * @return 事务标识符 - */ -static int agile_modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length) -{ - return (req[0] << 8) + req[1]; -} - -/** - * @brief TCP 预发送数据接口(计算长度字段的值并存入) - * @param req 数据存放指针 - * @param req_length 已有数据长度 - * @return 数据长度 - */ -static int agile_modbus_tcp_send_msg_pre(uint8_t *req, int req_length) -{ - /* Substract the header length to the message length */ - int mbap_length = req_length - 6; - - req[4] = mbap_length >> 8; - req[5] = mbap_length & 0x00FF; - - return req_length; -} - -/** - * @brief TCP 检查接收数据完整性接口 - * @param ctx modbus 句柄 - * @param msg 接收数据指针 - * @param msg_length 有效数据长度 - * @return 有效数据长度 - */ -static int agile_modbus_tcp_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length) -{ - return msg_length; -} - -/** - * @brief TCP 预检查确认接口(对比事务标识符和协议标识符) - * @param ctx modbus 句柄 - * @param req 请求数据指针 - * @param rsp 响应数据指针 - * @param rsp_length 响应数据长度 - * @return 0:成功; 其他:异常 - */ -static int agile_modbus_tcp_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req, - const uint8_t *rsp, int rsp_length) -{ - /* Check transaction ID */ - if (req[0] != rsp[0] || req[1] != rsp[1]) - return -1; - - /* Check protocol ID */ - if (rsp[2] != 0x0 && rsp[3] != 0x0) - return -1; - - return 0; -} - -/** - * @} - */ - -/** @defgroup TCP_Private_Constants TCP Private Constants - * @{ - */ - -/** - * @brief TCP 后端接口 - */ -static const agile_modbus_backend_t agile_modbus_tcp_backend = - { - AGILE_MODBUS_BACKEND_TYPE_TCP, - AGILE_MODBUS_TCP_HEADER_LENGTH, - AGILE_MODBUS_TCP_CHECKSUM_LENGTH, - AGILE_MODBUS_TCP_MAX_ADU_LENGTH, - agile_modbus_tcp_set_slave, - agile_modbus_tcp_build_request_basis, - agile_modbus_tcp_build_response_basis, - agile_modbus_tcp_prepare_response_tid, - agile_modbus_tcp_send_msg_pre, - agile_modbus_tcp_check_integrity, - agile_modbus_tcp_pre_check_confirmation}; - -/** - * @} - */ - -/** @defgroup TCP_Exported_Functions TCP Exported Functions - * @{ - */ - -/** - * @brief TCP 初始化 - * @param ctx TCP 句柄 - * @param send_buf 发送缓冲区 - * @param send_bufsz 发送缓冲区大小 - * @param read_buf 接收缓冲区 - * @param read_bufsz 接收缓冲区大小 - * @return 0:成功 - */ -int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz) -{ - agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz); - ctx->_ctx.backend = &agile_modbus_tcp_backend; - ctx->_ctx.backend_data = ctx; - - ctx->t_id = 0; - - return 0; -} - -/** - * @} - */ - -/** - * @} - */ diff --git a/package/modbus/agile_modbus_tcp.h b/package/modbus/agile_modbus_tcp.h deleted file mode 100644 index 50475e073..000000000 --- a/package/modbus/agile_modbus_tcp.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file agile_modbus_tcp.h - * @brief Agile Modbus 软件包 TCP 头文件 - * @author 马龙伟 (2544047213@qq.com) - * @date 2021-12-02 - * - * @attention - * - *

© Copyright (c) 2021 Ma Longwei. - * All rights reserved.

- * - */ - -#ifndef __PKG_AGILE_MODBUS_TCP_H -#define __PKG_AGILE_MODBUS_TCP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** @addtogroup TCP - * @{ - */ - -/** @defgroup TCP_Exported_Constants TCP Exported Constants - * @{ - */ -#define AGILE_MODBUS_TCP_HEADER_LENGTH 7 -#define AGILE_MODBUS_TCP_PRESET_REQ_LENGTH 12 -#define AGILE_MODBUS_TCP_PRESET_RSP_LENGTH 8 - -#define AGILE_MODBUS_TCP_CHECKSUM_LENGTH 0 - -/** - @verbatim - Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes - - @endverbatim - */ -#define AGILE_MODBUS_TCP_MAX_ADU_LENGTH 260 -/** - * @} - */ - -/** @defgroup TCP_Exported_Types TCP Exported Types - * @{ - */ - -/** - * @brief TCP 结构体 - */ -typedef struct agile_modbus_tcp { - agile_modbus_t _ctx; /**< modbus 句柄 */ - uint16_t t_id; /**< Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b - (page 23/46): - The transaction identifier is used to associate the future response - with the request. This identifier is unique on each TCP connection. */ -} agile_modbus_tcp_t; - -/** - * @} - */ - -/** @addtogroup TCP_Exported_Functions - * @{ - */ -int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz); -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/package/modbus/modbus.py b/package/modbus/modbus.py deleted file mode 100644 index c0f020e7c..000000000 --- a/package/modbus/modbus.py +++ /dev/null @@ -1,99 +0,0 @@ -import _modbus - - -class ModBus(_modbus._ModBus): - - def serializeWriteBits(self, addr: int, src: list) -> bytes: - lenth = super().serializeWriteBits(addr, len(list), bytes(src)) - return self.sendBuff[0:lenth] - - def serializeWriteRegisters(self, addr: int, src: list) -> bytes: - _src = bytes(2 * len(src)) - for i in range(len(src)): - _src[2 * i] = src[i] % 256 - _src[2 * i + 1] = src[i] // 256 - lenth = super().serializeWriteRegisters(addr, len(src), _src) - return self.sendBuff[0:lenth] - - def serializeReadBits(self, addr: int, nb: int) -> bytes: - lenth = super().serializeReadBits(addr, nb) - return self.sendBuff[0:lenth] - - def serializeReadInputBits(self, addr: int, nb: int) -> bytes: - lenth = super().serializeReadInputBits(addr, nb) - return self.sendBuff[0:lenth] - - def serializeReadRegisters(self, addr: int, nb: int) -> bytes: - lenth = super().serializeReadRegisters(addr, nb) - return self.sendBuff[0:lenth] - - def serializeReadInputRegisters(self, addr: int, nb: int) -> bytes: - lenth = super().serializeReadInputRegisters(addr, nb) - return self.sendBuff[0:lenth] - - def serializeWriteBit(self, addr: int, status: int) -> bytes: - lenth = super().serializeWriteBit(addr, status) - return self.sendBuff[0:lenth] - - def serializeWriteRegister(self, addr: int, value: int) -> bytes: - lenth = super().serializeWriteRegister(addr, value) - return self.sendBuff[0:lenth] - - def serializeMaskWriteRegister(self, - addr: int, - andMask: int, - orMask: int) -> bytes: - lenth = super().serializeMaskWriteRegister(addr, andMask, orMask) - return self.sendBuff[0:lenth] - - def serializeReportSlaveId(self) -> int: - lenth = super().serializeReportSlaveId() - return self.sendBuff[0:lenth] - - def deserializeReadRegisters(self, msg: bytes) -> list: - self.readBuff = msg - dest = super().deserializeReadRegisters(len(msg)) - ret = [] - for i in range(0, len(dest), 2): - ret.append(int(dest[i]) + int(dest[i + 1]) * 256) - return ret - - def deserializeReadBits(self, msg: bytes) -> list: - self.readBuff = msg - length = len(msg) - dest = super().deserializeReadBits(length) - return list(dest) - - def deserializeReadInputBits(self, msg: bytes) -> list: - self.readBuff = msg - length = len(msg) - dest = super().deserializeReadInputBits(length) - return list(dest) - - def deserializeReadInputRegisters(self, msg: bytes) -> list: - self.readBuff = msg - length = len(msg) - dest = super().deserializeReadInputRegisters(length) - ret = [] - for i in range(0, len(dest), 2): - ret.append(int(dest[i]) + int(dest[i + 1]) * 256) - return ret - - def deserializeWriteAndReadRegisters(self, msg: bytes) -> list: - self.readBuff = msg - length = len(msg) - dest = super().deserializeWriteAndReadRegisters(length) - ret = [] - for i in range(0, len(dest), 2): - ret.append(int(dest[i]) + int(dest[i + 1]) * 256) - return ret - - -class ModBusRTU(ModBus): - def __init__(self, sendBuffSize: int, readBuffSize: int): - self.__init__rtu(sendBuffSize, readBuffSize) - - -class ModBusTCP(ModBus): - def __init__(self, sendBuffSize: int, readBuffSize: int): - self.__init__tcp(sendBuffSize, readBuffSize) -- Gitee From ab6bc9d27f5bea38e1597178d15c1125c79c41cc Mon Sep 17 00:00:00 2001 From: lyon Date: Mon, 19 Sep 2022 14:49:11 +0800 Subject: [PATCH 2/2] update_toml --- packages.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages.toml b/packages.toml index 9c0a11cd4..433fa3926 100644 --- a/packages.toml +++ b/packages.toml @@ -362,3 +362,7 @@ releases = [ "v0.0.1 9f9579c54ebddb12c66afc8da64a987767ff512f", "v0.1.0 faa9c6230149d09188114af7af822e5d34af6b55" ] + +[[packages]] +name = "modbus" +releases = [ "v0.1.0 7ad63c0bc1d2f2b8c3f1cabb5d4afc77a0d3dbf9" ] -- Gitee