Compare commits
10 Commits
master
...
microkerne
| Author | SHA1 | Date |
|---|---|---|
|
|
fe67a5aa16 | |
|
|
4076b90792 | |
|
|
45e344984d | |
|
|
d60c045794 | |
|
|
32e50913b4 | |
|
|
98bd60356a | |
|
|
1bca808abf | |
|
|
5e87814024 | |
|
|
59c5ab7a02 | |
|
|
553f4c457e |
|
|
@ -1,11 +0,0 @@
|
|||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
IndentAccessModifiers: false
|
||||
AccessModifierOffset: -4
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
SortIncludes: CaseSensitive
|
||||
IndentPPDirectives: BeforeHash
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
|
@ -2,12 +2,5 @@
|
|||
*.o
|
||||
*libmusl.a
|
||||
*liblwip.a
|
||||
*/build/*
|
||||
.DS_Store
|
||||
|
||||
.cache/
|
||||
compile_commands.json
|
||||
.clangd
|
||||
Ubiquitous/XiZi_AIoT/services/app/bin/*
|
||||
Ubiquitous/XiZi_AIoT/build/*
|
||||
Ubiquitous/XiZi_AIoT/services/app/fs.img
|
||||
Ubiquitous/XiZi_AIoT/services/tools/mkfs/mkfs
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
[submodule "Ubiquitous/RT-Thread_Fusion_XiUOS/aiit_board/xidatong-riscv64/kendryte-sdk/kendryte-sdk-source"]
|
||||
path = Ubiquitous/RT-Thread_Fusion_XiUOS/aiit_board/xidatong-riscv64/kendryte-sdk/kendryte-sdk-source
|
||||
url = https://www.gitlink.org.cn/chunyexixiaoyu/kendryte-sdk-source.git
|
||||
[submodule "APP_Framework/lib/lorawan/lora_radio_driver"]
|
||||
path = APP_Framework/lib/lorawan/lora_radio_driver
|
||||
url = https://gitlink.org.cn/xuos/lora_radio_driver
|
||||
[submodule "APP_Framework/lib/lorawan/lorawan_devicenode"]
|
||||
path = APP_Framework/lib/lorawan/lorawan_devicenode
|
||||
url = https://gitlink.org.cn/xuos/lorawan_devicenode.git
|
||||
|
|
|
|||
|
|
@ -20,5 +20,4 @@ menu "Applications"
|
|||
source "$APP_DIR/Applications/sensor_app/Kconfig"
|
||||
source "$APP_DIR/Applications/embedded_database_app/Kconfig"
|
||||
source "$APP_DIR/Applications/webnet/Kconfig"
|
||||
source "$APP_DIR/Applications/webserver/Kconfig"
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -39,10 +39,6 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
ifeq ($(CONFIG_APP_USING_WEBNET),y)
|
||||
SRC_DIR += webnet
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_WEBSERVER),y)
|
||||
SRC_DIR += webserver
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
|
|
@ -281,7 +281,6 @@ menu "test app"
|
|||
menuconfig USER_TEST_MQTTCLIENT
|
||||
bool "Config test mqtt client"
|
||||
default n
|
||||
select LIB_USING_CJSON
|
||||
|
||||
menuconfig USER_TEST_FTPCLIENT
|
||||
bool "Config test ftp client"
|
||||
|
|
|
|||
|
|
@ -150,9 +150,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_FTPCLIENT_RISCV),y)
|
||||
ifeq ($(CONFIG_BSP_USING_W5500),y)
|
||||
SRC_FILES += test_ftpclient_riscv/test_ftpclient_riscv.c
|
||||
endif
|
||||
SRC_FILES += test_ftpclient_riscv/test_ftpclient_riscv.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_LORA_P2P),y)
|
||||
|
|
|
|||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_4g_ec200a.c
|
||||
* @brief Implement the connection 4G function, using QUECTEL EC200A device
|
||||
* @version 1.1
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.10.15
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
||||
char *trans_data = "{\"saleid\": \"52330000MJ87322565\", \"gateid\": \"10100001011\", \"type\": \"report\", \"time\": \"2023-06-15 17:22:00\", \"sequence\": \"268\", \"source\": \"da\", \"meter\": [{\"id\": \"T100106\", \"status\": \"1\", \"name\": \"T100106\", \"values\": {}}]}\r\n";
|
||||
// const char chk_buad[] = {"AT+IPR?\r\n"};
|
||||
const char set_mode[] = {"AT+QMTCFG=\"recv/mode\",0,0,1\r\n"};
|
||||
// const char set_cfg[] = {"AT+QMTCFG=\"aliauth\",0,\"k0celEMx5DK\",\"test_device\",\"411aa14c0dc671f7ee869adced442d13\"\r\n"};
|
||||
const char set_server[] = {"AT+QMTOPEN=0,\"xyheqmx.e3.luyouxia.net\",13333\r\n"};
|
||||
// const char set_server[] = {"AT+QMTOPEN=0,\"iot-060a7p7c.mqtt.iothub.aliyuncs.com\",1883\r\n"};
|
||||
const char set_conn[] = {"AT+QMTCONN=0,\"quectel\",\"test\",\"test123456\"\r\n"};
|
||||
// const char set_conn[] = {"AT+QMTCONN=0,\"sysoul\"\r\n"};
|
||||
// const char set_get[] = {"AT+QMTSUB=0,1,\"/get\",0\r\n"};
|
||||
// const char set_reply[] = {"AT+QMTPUBEX=0,0,0,0,\"/reply\",1000\r\n"};
|
||||
char recv_buf[100] = {0};
|
||||
int buf_len = 0;
|
||||
|
||||
|
||||
void Test4G(void)
|
||||
{
|
||||
int quectel_fd = PrivOpen(ADAPTER_QUECTEL_DRIVER, O_RDWR);
|
||||
if (quectel_fd < 0) {
|
||||
printf("open quectel fd error:%d\n", quectel_fd);
|
||||
return;
|
||||
}
|
||||
printf("quectel fopen success\n");
|
||||
|
||||
struct SerialDataCfg quectel_cfg;
|
||||
memset(&quectel_cfg, 0, sizeof(struct SerialDataCfg));
|
||||
quectel_cfg.serial_baud_rate = BAUD_RATE_115200;
|
||||
quectel_cfg.serial_data_bits = DATA_BITS_8;
|
||||
quectel_cfg.serial_stop_bits = STOP_BITS_1;
|
||||
quectel_cfg.serial_parity_mode = PARITY_NONE;
|
||||
quectel_cfg.serial_bit_order = BIT_ORDER_LSB;
|
||||
quectel_cfg.serial_invert_mode = NRZ_NORMAL;
|
||||
// quectel_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
quectel_cfg.serial_buffer_size = 1024;
|
||||
quectel_cfg.serial_timeout = 1000;
|
||||
quectel_cfg.is_ext_uart = 0;
|
||||
// quectel_cfg.ext_uart_no = ADAPTER_QUECTEL_DRIVER_EXT_PORT;
|
||||
// quectel_cfg.port_configure = PORT_CFG_INIT;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = &quectel_cfg;
|
||||
if (0 != PrivIoctl(quectel_fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("ioctl quectel fd error %d\n", quectel_fd);
|
||||
PrivClose(quectel_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("4G module set\n");
|
||||
|
||||
// memset(recv_buf, 0, sizeof(recv_buf));
|
||||
// printf("chk_buad: %s\n", chk_buad);
|
||||
// printf("chk_buad_len: %d\n", strlen(chk_buad));
|
||||
// PrivWrite(quectel_fd, chk_buad, strlen(chk_buad));
|
||||
// PrivTaskDelay(30);
|
||||
// buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
// printf("buf_len: %d\n", buf_len);
|
||||
// printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
// PrivTaskDelay(1000);
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
printf("set_mode: %s\n", set_mode);
|
||||
printf("set_mode_len: %d\n", strlen(set_mode));
|
||||
PrivWrite(quectel_fd, set_mode, strlen(set_mode));
|
||||
PrivTaskDelay(30);
|
||||
buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
printf("buf_len: %d\n", buf_len);
|
||||
printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
PrivTaskDelay(1000);
|
||||
|
||||
// memset(recv_buf, 0, sizeof(recv_buf));
|
||||
// printf("set_cfg: %s\n", set_cfg);
|
||||
// printf("set_cfg_len: %d\n", strlen(set_cfg));
|
||||
// PrivWrite(quectel_fd, set_cfg, strlen(set_cfg));
|
||||
// PrivTaskDelay(30);
|
||||
// buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
// printf("buf_len: %d\n", buf_len);
|
||||
// printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
// PrivTaskDelay(1000);
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
printf("set_server: %s\n", set_server);
|
||||
printf("set_server_len: %d\n", strlen(set_server));
|
||||
PrivWrite(quectel_fd, set_server, strlen(set_server));
|
||||
PrivTaskDelay(30);
|
||||
buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
printf("buf_len: %d\n", buf_len);
|
||||
printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
PrivTaskDelay(1000);
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
printf("set_conn: %s\n", set_conn);
|
||||
printf("set_conn_len: %d\n", strlen(set_conn));
|
||||
PrivWrite(quectel_fd, set_conn, strlen(set_conn));
|
||||
PrivTaskDelay(30);
|
||||
buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
printf("buf_len: %d\n", buf_len);
|
||||
printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
PrivTaskDelay(1000);
|
||||
|
||||
while (1) {
|
||||
printf("start send\n");
|
||||
char set_reply[50] = {"AT+QMTPUBEX=0,0,0,0,\"/reply\","};
|
||||
char data_len_str[20];
|
||||
sprintf(data_len_str, "%d", strlen(trans_data));
|
||||
printf("data_len_str: %s\n", data_len_str);
|
||||
strcat(set_reply, data_len_str);
|
||||
strcat(set_reply, "\r\n");
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
printf("set_reply: %s\n", set_reply);
|
||||
printf("set_reply_len: %d\n", strlen(set_reply));
|
||||
PrivWrite(quectel_fd, set_reply, strlen(set_reply));
|
||||
PrivTaskDelay(30);
|
||||
buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
printf("buf_len: %d\n", buf_len);
|
||||
printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
PrivTaskDelay(500);
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
printf("send_data: %s\n", trans_data);
|
||||
printf("send_data_len: %d\n", strlen(trans_data));
|
||||
PrivWrite(quectel_fd, trans_data, strlen(trans_data));
|
||||
PrivTaskDelay(30);
|
||||
buf_len = PrivRead(quectel_fd, recv_buf, sizeof(recv_buf));
|
||||
printf("buf_len: %d\n", buf_len);
|
||||
printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf);
|
||||
PrivTaskDelay(5000);
|
||||
}
|
||||
|
||||
PrivClose(quectel_fd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(Test4G, a quectel test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
#endif
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
* @date: 2023/2/17
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
|
@ -55,34 +54,28 @@ void TestCAN(void)
|
|||
}
|
||||
printf("CAN configure successful!\n");
|
||||
|
||||
uint8_t data_buff[64u] = "12344321";
|
||||
uint8_t data_buff[64u] = {1,2,3,4,4,3,2,1};
|
||||
struct CanSendConfigure frame_send;
|
||||
frame_send.ide=0;
|
||||
frame_send.stdid = 0x55;
|
||||
frame_send.rtr=0;
|
||||
frame_send.data_lenth=8;
|
||||
frame_send.data = data_buff;
|
||||
|
||||
struct CanSendConfigure frame_recv;
|
||||
uint8_t recv_buff[64u] = {};
|
||||
uint8_t recv_buff[65U] = {0};
|
||||
frame_recv.data = recv_buff;
|
||||
|
||||
// CAN write
|
||||
while (1)
|
||||
{
|
||||
// PrivTaskDelay(500);
|
||||
// PrivWrite(can_fd, &frame_send, NONE);
|
||||
// PrivTaskDelay(500);
|
||||
PrivTaskDelay(500);
|
||||
PrivWrite(can_fd, &frame_send, NONE);
|
||||
PrivTaskDelay(500);
|
||||
PrivRead(can_fd, &frame_recv, NONE);
|
||||
// if any data has received,Then printf message
|
||||
if(frame_recv.data_lenth > 0){
|
||||
printf("ID %08x : \n",frame_recv.exdid);
|
||||
for(int i = 0; i < frame_recv.data_lenth; i ++) {
|
||||
printf("0x%x ", frame_recv.data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
frame_send.data = recv_buff;
|
||||
PrivWrite(can_fd, &frame_send, NONE);
|
||||
printf("ID %08x:%s\n",frame_recv.exdid,frame_recv.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <transform.h>
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
||||
#ifdef BSP_USING_W5500
|
||||
#include <socket.h>
|
||||
|
||||
#define BUFF_SIZE 128
|
||||
|
|
@ -190,6 +189,6 @@ PRIV_SHELL_CMD_FUNCTION(TestSocketAsClient, a w5500 client-ip-port-msg test samp
|
|||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
#include <transform.h>
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
||||
#define BSP_LED_PIN 134
|
||||
#define BSP_LED_PIN 29
|
||||
#define NULL_PARAMETER 0
|
||||
|
||||
static uint16_t pin_fd=0;
|
||||
|
|
@ -30,7 +30,6 @@ static struct PinStat pin_led;
|
|||
|
||||
void LedFlip(void *parameter)
|
||||
{
|
||||
printf("%s val %d time %d\n", __func__, pin_led.val, PrivGetTickTime());
|
||||
pin_led.pin = BSP_LED_PIN;
|
||||
pin_led.val = !pin_led.val;
|
||||
PrivWrite(pin_fd, &pin_led, NULL_PARAMETER);
|
||||
|
|
@ -38,7 +37,7 @@ void LedFlip(void *parameter)
|
|||
|
||||
void TestHwTimer(void)
|
||||
{
|
||||
uint32_t period_ms = 500;
|
||||
x_ticks_t period = 1;
|
||||
|
||||
pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR);
|
||||
if(pin_fd<0) {
|
||||
|
|
@ -76,7 +75,7 @@ void TestHwTimer(void)
|
|||
return;
|
||||
}
|
||||
|
||||
ioctl_cfg.args = (void *)&period_ms;
|
||||
ioctl_cfg.args = (void *).
|
||||
if (0 != PrivIoctl(timer_fd, OPE_CFG, &ioctl_cfg)) {
|
||||
printf("timer pin fd error %d\n", pin_fd);
|
||||
PrivClose(pin_fd);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ void TestLora(int argc, char *argv[])
|
|||
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
uart_cfg.serial_timeout = 1000;
|
||||
uart_cfg.is_ext_uart = 0;
|
||||
uart_cfg.dev_recv_callback = NULL;
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&uart_cfg;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ static struct SerialDataCfg serial_cfg =
|
|||
.serial_buffer_size = SERIAL_RB_BUFSZ,
|
||||
.serial_timeout = E220_DAFAULT_SERIAL_TIMEOUT, // 串口超时配置
|
||||
.is_ext_uart = 0,
|
||||
.dev_recv_callback = NULL,
|
||||
};
|
||||
|
||||
enum LoraMode current_mode = -1; // 当前模块处于什么模式
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* XiUOS includes */
|
||||
#ifdef CONFIG_ADD_XIZI_FEATURES
|
||||
#include <xizi.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADD_NUTTX_FEATURES
|
||||
#include <nuttx/config.h>
|
||||
#endif
|
||||
|
||||
/* PikaPython includes */
|
||||
#include "pika_port.h"
|
||||
|
||||
/* External PikaPython application functions */
|
||||
extern int pika_app_init(void);
|
||||
extern int pika_app_run(void);
|
||||
extern int pika_app_deinit(void);
|
||||
extern int pika_app_is_initialized(void);
|
||||
extern int pika_app_load_script(const char* filename);
|
||||
|
||||
/* Test function for PikaPython */
|
||||
int test_pikapython(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("\n=== PikaPython Test for XiUOS ===\n");
|
||||
|
||||
/* Initialize PikaPython runtime */
|
||||
printf("Initializing PikaPython...\n");
|
||||
ret = pika_app_init();
|
||||
if (ret != 0) {
|
||||
printf("Failed to initialize PikaPython: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if runtime is initialized */
|
||||
if (!pika_app_is_initialized()) {
|
||||
printf("PikaPython runtime not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("PikaPython runtime initialized successfully\n");
|
||||
|
||||
/* Run embedded Python script */
|
||||
printf("Running embedded Python script...\n");
|
||||
ret = pika_app_run();
|
||||
if (ret != 0) {
|
||||
printf("Failed to run Python script: %d\n", ret);
|
||||
pika_app_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Test loading script from file (if file system is enabled) */
|
||||
#ifdef CONFIG_PIKAPYTHON_ENABLE_FILE_SYSTEM
|
||||
printf("Testing file system script loading...\n");
|
||||
ret = pika_app_load_script("/app/main.py");
|
||||
if (ret == 0) {
|
||||
printf("Script loaded from file successfully\n");
|
||||
ret = pika_app_run();
|
||||
if (ret != 0) {
|
||||
printf("Failed to run loaded script: %d\n", ret);
|
||||
}
|
||||
} else {
|
||||
printf("File system script loading not available or failed\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Deinitialize PikaPython runtime */
|
||||
printf("Deinitializing PikaPython...\n");
|
||||
ret = pika_app_deinit();
|
||||
if (ret != 0) {
|
||||
printf("Failed to deinitialize PikaPython: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("PikaPython test completed successfully!\n");
|
||||
printf("=== End of PikaPython Test ===\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main function for standalone test */
|
||||
#ifdef CONFIG_PIKAPYTHON_STANDALONE_TEST
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("PikaPython Standalone Test\n");
|
||||
return test_pikapython();
|
||||
}
|
||||
#endif
|
||||
|
|
@ -138,7 +138,6 @@ void Test485(void)
|
|||
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
uart_cfg.serial_timeout = -1;
|
||||
uart_cfg.is_ext_uart = 0;
|
||||
uart_cfg.dev_recv_callback = NULL;
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&uart_cfg;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ void Test485(void)
|
|||
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
uart_cfg.serial_timeout = 1000;
|
||||
uart_cfg.is_ext_uart = 0;
|
||||
uart_cfg.dev_recv_callback = NULL;
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&uart_cfg;
|
||||
|
|
|
|||
|
|
@ -76,12 +76,10 @@ struct IperfParam {
|
|||
static void* TestIperfServer(void* param)
|
||||
{
|
||||
struct IperfParam* iperf_param = (struct IperfParam*)param;
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 6);
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
printf("[%s] Err: Can't create socker.\n", __func__);
|
||||
return NULL;
|
||||
} else {
|
||||
printf("[%s] Info Create server socket %d\n", __func__, sock);
|
||||
}
|
||||
|
||||
uint8_t* recv_data = (uint8_t*)malloc(IPERF_BUFSZ);
|
||||
|
|
@ -123,9 +121,8 @@ static void* TestIperfServer(void* param)
|
|||
socklen_t sin_size = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in client_addr;
|
||||
int connection = accept(sock, (struct sockaddr*)&client_addr, &sin_size);
|
||||
printf("[%s] Info: New client connected from (%s, %d), connect: %d\n", __func__,
|
||||
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port),
|
||||
connection);
|
||||
printf("[%s] Info: New client connected from (%s, %d)\n", __func__,
|
||||
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||
|
||||
int flag = 1;
|
||||
setsockopt(connection,
|
||||
|
|
@ -144,8 +141,8 @@ static void* TestIperfServer(void* param)
|
|||
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||
break;
|
||||
} else if (bytes_received < 0) {
|
||||
KPrintf("recv error: %d, client: (%s, %d)\n",
|
||||
bytes_received, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||
KPrintf("recv error, client: (%s, %d)\n",
|
||||
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -261,6 +258,8 @@ enum IperfParamEnum {
|
|||
|
||||
void TestSocket(int argc, char* argv[])
|
||||
{
|
||||
lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
|
||||
static char usage_info[] = "Run either a iperf server or iperf client.";
|
||||
static char program_info[] = "Lwip socket test task, a simple iperf.";
|
||||
static const char* const usages[] = {
|
||||
|
|
|
|||
|
|
@ -23,13 +23,12 @@
|
|||
void TimerFunction(union sigval sig_val)
|
||||
{
|
||||
static int cnt = 0;
|
||||
printf("%s cnt %d ms %d\n", __func__, cnt++, PrivGetTickTime());
|
||||
printf("%s cnt %d\n", __func__, cnt++);
|
||||
}
|
||||
|
||||
void TestTimer(void)
|
||||
{
|
||||
int ret = 0;
|
||||
static int count = 0;
|
||||
int timer_flags;
|
||||
timer_t timer_id;
|
||||
struct sigevent evp;
|
||||
|
|
@ -41,9 +40,7 @@ void TestTimer(void)
|
|||
evp.sigev_notify_function = TimerFunction;
|
||||
evp.sigev_notify_attributes = &timer_flags;
|
||||
|
||||
count++;
|
||||
|
||||
ret = PrivTimerCreate(count, &evp, &timer_id);
|
||||
ret = timer_create(CLOCK_REALTIME, &evp, &timer_id);
|
||||
if (ret < 0) {
|
||||
printf("%s create timer failed ret %d\n", __func__, ret);
|
||||
return;
|
||||
|
|
@ -51,14 +48,14 @@ void TestTimer(void)
|
|||
|
||||
struct itimerspec value;
|
||||
//active time interval
|
||||
value.it_interval.tv_sec = 0;
|
||||
value.it_interval.tv_nsec = 1000000 * 10;
|
||||
value.it_interval.tv_sec = 2;
|
||||
value.it_interval.tv_nsec = 0;
|
||||
|
||||
//first timer set time
|
||||
value.it_value.tv_sec = 2;
|
||||
value.it_value.tv_nsec = 0;
|
||||
|
||||
ret = PrivTimerModify(timer_id, 1, &value, NULL);
|
||||
ret = timer_settime(timer_id, 1, &value, NULL);
|
||||
if (ret < 0) {
|
||||
printf("%s set timer time failed ret %d\n", __func__, ret);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ void TestUart(int argc, char* argv[])
|
|||
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
uart_cfg.serial_timeout = -1;
|
||||
uart_cfg.is_ext_uart = 0;
|
||||
uart_cfg.dev_recv_callback = NULL;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,3 @@
|
|||
SRC_FILES := 4g_app.c
|
||||
|
||||
ifeq ($(CONFIG_DEVICE_ADL400),y)
|
||||
SRC_FILES += ch32v208_adl400.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEVICE_DTZ178),y)
|
||||
SRC_FILES += ch32v208_dtz178.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEVICE_DTSD342),y)
|
||||
SRC_FILES += ch32v208_dtsd342.c
|
||||
endif
|
||||
SRC_FILES := 4g_app.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
|||
|
|
@ -1,673 +0,0 @@
|
|||
/**
|
||||
* @file ch32v208_adl400.c
|
||||
* @brief ch32v208 board gets data from Acrel-ADL400 electricity meter with rs485 bus,
|
||||
* and then sends it to the server with 4G.
|
||||
* @author Huo Yujia (huoyujia081@126.com)
|
||||
* @version 1.0
|
||||
* @date 2024-07-10
|
||||
*/
|
||||
|
||||
#include <ModuleConfig.h>
|
||||
#include <adapter.h>
|
||||
#include <transform.h>
|
||||
#define MAX_FRAME_SIZE 256 // 最大帧大小
|
||||
#define MAX_BUFFER_SIZE 1024 * 2 // 最大缓冲区大小
|
||||
#define RECEIVE_DATA_INTERVAL_MS 1000 * 60 * 2 // ADL400数据采集间隔时间,单位为毫秒
|
||||
#define RESEND_COUNT 3 // 最大帧重发次数
|
||||
#define RECONNECT_COUNT 5 // 最大连接次数
|
||||
#define WATING_RESPONSE_MS 5000 // 等待响应时间,单位为毫秒
|
||||
|
||||
/**
|
||||
* @brief 生成Modbus RTU请求帧中的CRC循环冗余码
|
||||
* @param CRC_Ptr
|
||||
* @param LEN 需要生成CRC冗余码的数据长度
|
||||
* @return uint16_t 以小端顺序返回CRC循环冗余码
|
||||
*/
|
||||
static uint16_t generateCRC(uint8_t *CRC_Ptr, uint8_t LEN) {
|
||||
uint16_t CRC_Value = 0;
|
||||
uint8_t i = 0;
|
||||
uint8_t j = 0;
|
||||
|
||||
CRC_Value = 0xffff;
|
||||
for (i = 0; i < LEN; i++) // LEN为数组长度
|
||||
{
|
||||
CRC_Value ^= *(CRC_Ptr + i);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (CRC_Value & 0x00001)
|
||||
CRC_Value = (CRC_Value >> 1) ^ 0xA001;
|
||||
else
|
||||
CRC_Value = (CRC_Value >> 1);
|
||||
}
|
||||
}
|
||||
CRC_Value = ((CRC_Value >> 8) + (CRC_Value << 8)); // 交换高低字节
|
||||
|
||||
return CRC_Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 生成Modbus RTU请求帧,用于获取指定寄存器的值
|
||||
* @param address 请求的Modbus地址
|
||||
* @param functionCode 功能码
|
||||
* @param startAddress 数据起始地址
|
||||
* @param quantity 数据读取个数
|
||||
* @param modbusRtuRequestFrame 生成的ModBus RTU请求帧数组
|
||||
* @param requestFrameArrLength 生成的ModBus RTU请求帧数组长度,固定为8
|
||||
* @return int 0表示生成成功,其他结果表示生成失败
|
||||
* @note Modbus
|
||||
* RTU请求帧格式:地址(1字节)+功能码(1字节)+数据起始地址(2字节)+数据读取个数(2字节)+校验码(2字节)
|
||||
*/
|
||||
static int generateRequestFrame(unsigned char address, unsigned char functionCode, unsigned short startAddress, unsigned short quantity,
|
||||
unsigned char modbusRtuRequestFrame[], int requestFrameArrLength) {
|
||||
if (requestFrameArrLength != 8) {
|
||||
printf("the length of request frame array is not 8\n");
|
||||
return -1;
|
||||
}
|
||||
modbusRtuRequestFrame[0] = address;
|
||||
modbusRtuRequestFrame[1] = functionCode;
|
||||
modbusRtuRequestFrame[2] = (startAddress >> 8) & 0xff;
|
||||
modbusRtuRequestFrame[3] = startAddress & 0xff;
|
||||
modbusRtuRequestFrame[4] = (quantity >> 8) & 0xff;
|
||||
modbusRtuRequestFrame[5] = quantity & 0xff;
|
||||
modbusRtuRequestFrame[6] = (generateCRC(modbusRtuRequestFrame, 6) >> 8) & 0xff;
|
||||
modbusRtuRequestFrame[7] = generateCRC(modbusRtuRequestFrame, 6) & 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将要上传服务器的数据帧
|
||||
*/
|
||||
struct DataFrame {
|
||||
unsigned char id[13]; // 用响应的时间戳作为数据帧的id
|
||||
unsigned char data[MAX_FRAME_SIZE]; // 上传服务器的数据帧字符串,前12字节表示数据帧id。字符串格式:数据帧id,数据1,数据2,数据3...
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modbus RTU响应数据帧的缓存,使用循环队列作为数据结构
|
||||
*/
|
||||
struct QueueBuffer {
|
||||
struct DataFrame *buffer[MAX_BUFFER_SIZE / sizeof(struct DataFrame)]; // 循环队列存储空间,使用数组存储
|
||||
int front; // 循环队列队头
|
||||
int rear; // 循环队列队尾
|
||||
pthread_mutex_t mutex; // 互斥访问循环队列信号量
|
||||
sem_t full; // 循环队列中有效成员个数的信号量
|
||||
};
|
||||
|
||||
#define BUFFER_ELEM_COUNT (MAX_BUFFER_SIZE / sizeof(struct DataFrame)) // 循环队列中可以容纳的最大成员个数
|
||||
|
||||
/**
|
||||
* @brief 初始化循环队列
|
||||
* @param pQueueBuffer 循环队列指针
|
||||
* @return * int 0表示初始化成功,其他表示初始化失败
|
||||
*/
|
||||
static int initBuffer(struct QueueBuffer *pQueueBuffer) {
|
||||
pQueueBuffer->front = 0;
|
||||
pQueueBuffer->rear = 0;
|
||||
if (PrivMutexCreate(&pQueueBuffer->mutex, 0) < 0) {
|
||||
printf("buffer mutex create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (PrivSemaphoreCreate(&pQueueBuffer->full, 0, 0) < 0) {
|
||||
printf("buffer full semaphore create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列入队,如果循环队列已满,则将最旧的成员出队后,新成员再入队
|
||||
* @param pQueueBuffer 循环队列指针
|
||||
* @param pDataFrame ADL400响应数据帧
|
||||
* @return int 0表示入队成功,其他表示入队失败
|
||||
*/
|
||||
static int offerBuffer(struct QueueBuffer *pQueueBuffer, struct DataFrame *pDataFrame) {
|
||||
/* 循环队列已满,将最旧的成员出队 */
|
||||
if ((pQueueBuffer->rear + 1) % BUFFER_ELEM_COUNT == pQueueBuffer->front) {
|
||||
struct DataFrame *frontDataFrame = pQueueBuffer->buffer[pQueueBuffer->front];
|
||||
PrivFree(frontDataFrame);
|
||||
pQueueBuffer->front = (pQueueBuffer->front + 1) % BUFFER_ELEM_COUNT;
|
||||
}
|
||||
/* 新成员入队 */
|
||||
pQueueBuffer->buffer[pQueueBuffer->rear] = pDataFrame;
|
||||
pQueueBuffer->rear = (pQueueBuffer->rear + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", pQueueBuffer->front);
|
||||
printf("rear: %d\n", pQueueBuffer->rear);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列出队,如果队列为空则返回NULL
|
||||
* @param pQueueBuffer 循环队列指针
|
||||
* @return struct DataFrame* 出队成员,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *pollBuffer(struct QueueBuffer *pQueueBuffer) {
|
||||
/* 队列为空,返回NULL */
|
||||
if (pQueueBuffer->front == pQueueBuffer->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 最旧的成员出队 */
|
||||
struct DataFrame *pFrontDataFrame = pQueueBuffer->buffer[pQueueBuffer->front];
|
||||
pQueueBuffer->buffer[pQueueBuffer->front] = NULL;
|
||||
pQueueBuffer->front = (pQueueBuffer->front + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", pQueueBuffer->front);
|
||||
printf("rear: %d\n", pQueueBuffer->rear);
|
||||
return pFrontDataFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查看队头元素,如果队列为空则返回NULL
|
||||
* @param pQueueBuffer 循环队列指针
|
||||
* @return struct DataFrame* 队头元素,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *peekBuffer(struct QueueBuffer *pQueueBuffer) {
|
||||
/* 如果队列为空,返回NULL */
|
||||
if (pQueueBuffer->front == pQueueBuffer->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 返回队头元素,但不出队 */
|
||||
return pQueueBuffer->buffer[pQueueBuffer->front];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 改写PrivRead函数,原有函数只会读取接收缓冲区的当前已有字节,新函数会读取指定字节数再返回
|
||||
* @param fd 文件描述符
|
||||
* @param buf 数据读取到的位置
|
||||
* @param len 读取的指定字节数
|
||||
* @return int 如果读取到指定字节数返回0;如果到达WATING_RESPONSE_MS仍未读取到指定字节数,或者读数据错误,返回-1
|
||||
*/
|
||||
static int privReadEnoughData(int fd, void *buf, size_t len) {
|
||||
char *buffer = (char *)buf; // 将接收的存储空间指针强制转型
|
||||
int gottenBytes = 0; // 已经读取到的字节数
|
||||
int remainTime = WATING_RESPONSE_MS; // 剩余的时间
|
||||
|
||||
/* 只有接收的字节数不够,并且还有剩余时间,才可以继续读取 */
|
||||
while (gottenBytes < len && remainTime > 0) {
|
||||
int bytes = PrivRead(fd, buffer + gottenBytes, len - gottenBytes); // 从设备读取
|
||||
if (bytes > 0) {
|
||||
gottenBytes += bytes; // 读取到字节
|
||||
} else if (bytes < 0) {
|
||||
printf("Error reading from serial port\n");
|
||||
return -1; // 读取错误
|
||||
}
|
||||
PrivTaskDelay(100); // 每100ms读取一次
|
||||
remainTime -= 100; // 剩余时间减去100ms
|
||||
}
|
||||
/* 若没有剩余时间,表示还没有读取到指定的字节数,返回-1;若有剩余时间,表示已经读取了指定的字节数,返回0 */
|
||||
return remainTime < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析ADL400响应的Modbus RTU数据帧
|
||||
* @param modbusRtuResponseFrame0 请求数据后ADL400的响应帧
|
||||
* @param modbusRtuResponseFrame1 请求时间戳后ADL400的响应帧
|
||||
* @param modbusRtuResponseFrame2 请求电流电压比后ADL400的响应帧
|
||||
* @param pDataFrame 将要上传给服务器的数据帧,包括id和数据
|
||||
*/
|
||||
static void parseModBusRtuResponseFrame(unsigned char *modbusRtuResponseFrame0, unsigned char *modbusRtuResponseFrame1,
|
||||
unsigned char *modbusRtuResponseFrame2, struct DataFrame *pDataFrame) {
|
||||
/* 从frame2中获取电压变比pt和电流变比ct */
|
||||
unsigned char *p = modbusRtuResponseFrame2;
|
||||
int pt = (unsigned short)modbusRtuResponseFrame2[3] << 8 | (unsigned short)modbusRtuResponseFrame2[4];
|
||||
int ct = (unsigned short)modbusRtuResponseFrame2[5] << 8 | (unsigned short)modbusRtuResponseFrame2[6];
|
||||
|
||||
/* 从frame1中获取时间戳,即数据帧的id */
|
||||
for (int i = 8; i >= 3; i--) {
|
||||
sprintf(pDataFrame->id, "%s%02x", pDataFrame->id, modbusRtuResponseFrame1[i]);
|
||||
sprintf(pDataFrame->data, "%s%02x", pDataFrame->data, modbusRtuResponseFrame1[i]);
|
||||
}
|
||||
|
||||
/* 从frame0中获取要上传到服务器的ADL400的数据 */
|
||||
for (int i = 3; i < modbusRtuResponseFrame0[2] + 3; i += 4) {
|
||||
int originalData = (unsigned int)modbusRtuResponseFrame0[i] << 24 | (unsigned int)modbusRtuResponseFrame0[i + 1] << 16 |
|
||||
(unsigned int)modbusRtuResponseFrame0[i + 2] << 8 | (unsigned int)modbusRtuResponseFrame0[i + 3];
|
||||
sprintf(pDataFrame->data, "%s,%d", pDataFrame->data, originalData); // 将数据拼接到字符串
|
||||
}
|
||||
|
||||
strcat(pDataFrame->data, "\n"); // 字符串末尾添加换行符,表示数据帧结束
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从ADL400接收数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *receiveDataFromADL400Task(void *arg) {
|
||||
struct QueueBuffer *pQueueBuffer = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
int fd = PrivOpen("/dev/rs485_dev1", O_RDWR); // 打开设备文件
|
||||
if (fd < 0) { // 打开设备文件失败,打印错误信息
|
||||
printf("open rs485 fd error: %d\n", fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct SerialDataCfg rs485Configuration;
|
||||
memset(&rs485Configuration, 0, sizeof(struct SerialDataCfg));
|
||||
/* 读取RS485配置信息 */
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
int baudRatesOption = CFG->baudRate_Rs485;
|
||||
int dataBitsOption = CFG->dataBits_Rs485;
|
||||
int stopBitsOption = CFG->stopBits_Rs485;
|
||||
int parityOption = CFG->parity_Rs485;
|
||||
PrivMutexAbandon(&romConfigurationMutex); // 释放互斥锁
|
||||
switch (baudRatesOption) {
|
||||
case 1:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_2400;
|
||||
break;
|
||||
case 2:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_4800;
|
||||
break;
|
||||
case 3:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_9600;
|
||||
break;
|
||||
case 4:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_19200;
|
||||
break;
|
||||
case 5:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_38400;
|
||||
break;
|
||||
case 6:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_57600;
|
||||
break;
|
||||
case 7:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_115200;
|
||||
break;
|
||||
case 8:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_230400;
|
||||
break;
|
||||
default:
|
||||
rs485Configuration.serial_baud_rate = BAUD_RATE_9600;
|
||||
break;
|
||||
}
|
||||
switch (dataBitsOption) {
|
||||
case 1:
|
||||
rs485Configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
case 2:
|
||||
rs485Configuration.serial_data_bits = DATA_BITS_9;
|
||||
break;
|
||||
default:
|
||||
rs485Configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
}
|
||||
switch (stopBitsOption) {
|
||||
case 1:
|
||||
rs485Configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
case 2:
|
||||
rs485Configuration.serial_stop_bits = STOP_BITS_2;
|
||||
break;
|
||||
default:
|
||||
rs485Configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
}
|
||||
switch (parityOption) {
|
||||
case 1:
|
||||
rs485Configuration.serial_parity_mode = PARITY_NONE;
|
||||
break;
|
||||
case 2:
|
||||
rs485Configuration.serial_parity_mode = PARITY_ODD;
|
||||
break;
|
||||
case 3:
|
||||
rs485Configuration.serial_parity_mode = PARITY_EVEN;
|
||||
break;
|
||||
}
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&rs485Configuration;
|
||||
if (0 != PrivIoctl(fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("ioctl uart fd error %d\n", fd);
|
||||
PrivClose(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char modbusRtuRequestFrame[8]; // 定义Modbus RTU请求帧
|
||||
unsigned char modBusRtuResponseFrame0[256]; // 定义Modbus RTU响应帧0
|
||||
unsigned char modBusRtuResponseFrame1[256]; // 定义Modbus RTU响应帧1
|
||||
unsigned char modBusRtuResponseFrame2[32]; // 定义Modbus RTU响应帧2
|
||||
while (1) {
|
||||
/* 生成Modbus RTU请求帧0,用于请求ADL400数据 */
|
||||
if (generateRequestFrame(0x93, 0x03, 0x0000, 0x003C, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)) < 0) {
|
||||
break; // 生成请求帧失败,退出循环
|
||||
}
|
||||
PrivWrite(fd, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)); // 发送Modbus RTU请求帧
|
||||
/* 读取Modbus RTU响应帧0数据 */
|
||||
if (privReadEnoughData(fd, modBusRtuResponseFrame0, 5 + (0x003C << 1)) < 0) {
|
||||
printf("read data from adl400 time out\n"); // 读取超时,打印错误信息
|
||||
break; // 读取失败,退出循环
|
||||
}
|
||||
|
||||
/* 生成Modbus RTU请求帧1,用于请求时间戳 */
|
||||
if (generateRequestFrame(0x93, 0x03, 0x003C, 0x0003, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)) < 0) {
|
||||
break; // 生成请求帧失败,退出循环
|
||||
}
|
||||
PrivWrite(fd, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)); // 发送Modbus RTU请求帧
|
||||
/* 读取Modbus RTU响应帧1数据 */
|
||||
if (privReadEnoughData(fd, modBusRtuResponseFrame1, 5 + (0x0003 << 1)) < 0) {
|
||||
printf("read data from adl400 time out\n"); // 读取超时,打印错误信息
|
||||
break; // 读取失败,退出循环
|
||||
}
|
||||
|
||||
/* 生成Modbus RTU请求帧2,用于请求电压电流变比 */
|
||||
if (generateRequestFrame(0x93, 0x03, 0x008D, 0x0002, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)) < 0) {
|
||||
break; // 生成请求帧失败,退出循环
|
||||
}
|
||||
PrivWrite(fd, modbusRtuRequestFrame, sizeof(modbusRtuRequestFrame)); // 发送Modbus RTU请求帧
|
||||
/* 读取Modbus RTU响应帧2 */
|
||||
if (privReadEnoughData(fd, modBusRtuResponseFrame2, 5 + (0x0002 << 1)) < 0) {
|
||||
printf("read data from adl400 time out\n"); // 读取超时,打印错误信息
|
||||
break; // 读取失败,退出循环
|
||||
}
|
||||
|
||||
/* 解析Modbus RTU响应帧 */
|
||||
struct DataFrame *pDataFrame = (struct DataFrame *)PrivMalloc(sizeof(struct DataFrame));
|
||||
memset(pDataFrame, 0, sizeof(struct DataFrame));
|
||||
parseModBusRtuResponseFrame(modBusRtuResponseFrame0, modBusRtuResponseFrame1, modBusRtuResponseFrame2, pDataFrame);
|
||||
|
||||
/* 将解析后的数据帧放入循环队列 */
|
||||
PrivMutexObtain(&pQueueBuffer->mutex); // 获取互斥锁
|
||||
offerBuffer(pQueueBuffer, pDataFrame); // 将数据帧放入队列
|
||||
printf("receive data from ADL400, id: %s\n", pDataFrame->id); // 打印接收到的数据帧ID
|
||||
PrivMutexAbandon(&pQueueBuffer->mutex); // 释放互斥锁
|
||||
PrivSemaphoreAbandon(&pQueueBuffer->full); // 释放信号量,即告知发送数据线程,队列中有新的数据帧
|
||||
|
||||
PrivTaskDelay(RECEIVE_DATA_INTERVAL_MS); // 延迟一段时间再读取下一帧数据
|
||||
}
|
||||
|
||||
PrivClose(fd); // 关闭设备文件
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过4G向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *sendDataToServerTask_4G(void *arg) {
|
||||
uint8_t serverIpAddress[16] = {}; // 目的IP地址
|
||||
uint8_t serverPort[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *pQueueBuffer = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receiveBuffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_4G_NAME); // 查找4G模块适配器
|
||||
|
||||
AdapterDeviceOpen(adapter); // 打开适配器对应的设备(实际打开串口中断)
|
||||
int baud_rate = BAUD_RATE_115200; // 波特率,用于设置4G模块串口
|
||||
AdapterDeviceControl(adapter, OPE_INT, &baud_rate); // 对适配器对应设备进行配置(实际配置波特率)
|
||||
|
||||
struct DataFrame *pDataFrame = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&pQueueBuffer->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 如果启用了BLE配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(serverIpAddress, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(serverPort, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("serverIpAddress:\t%s\n", serverIpAddress);
|
||||
printf("serverPort:\t\t%s\n", serverPort);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
if (CFG->mqttSwitch_4G == 1) { // 如果使能MQTT
|
||||
AdapterDeviceMqttConnect(adapter, serverIpAddress, serverPort, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else { // 如果禁用MQTT
|
||||
AdapterDeviceConnect(adapter, CLIENT, serverIpAddress, serverPort, IPV4);
|
||||
}
|
||||
|
||||
AdapterDeviceNetstat(adapter); // 读取网络连接状态
|
||||
/* 若连接失败,则等待10s再次尝试连接 */
|
||||
if (CFG->mqttSwitch_4G == 0 && !adapter->network_info.is_connected ||
|
||||
CFG->mqttSwitch_4G == 1 && !adapter->network_info.mqttIsConnected) {
|
||||
PrivSemaphoreAbandon(&pQueueBuffer->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else // 如果没有启用BLE配置功能
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(serverIpAddress, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(serverPort, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("serverIpAddress:\t%s\n", serverIpAddress);
|
||||
printf("serverPort:\t\t%s\n", serverPort);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnectCount = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnectCount > 0) {
|
||||
int res;
|
||||
if (CFG->mqttSwitch_4G == 1) {
|
||||
res = AdapterDeviceMqttConnect(adapter, mqttServerIp, mqttServerPort, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else {
|
||||
res = AdapterDeviceConnect(adapter, CLIENT, serverIpAddress, serverPort, IPV4);
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
reconnectCount--;
|
||||
}
|
||||
if (reconnectCount <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&pQueueBuffer->full); // 释放信号量
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&pQueueBuffer->mutex); // 获取互斥锁
|
||||
pDataFrame = pollBuffer(pQueueBuffer); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&pQueueBuffer->mutex); // 释放互斥锁
|
||||
|
||||
int resendCount = RESEND_COUNT; // 定义数据帧重发次数
|
||||
while (pDataFrame != NULL && resendCount > 0) { // 只有数据帧非空并且还有剩余重发次数,才进行发送
|
||||
/* 向服务器发送数据 */
|
||||
printf("pDataFrame->data: %s", pDataFrame->data);
|
||||
printf("send data to server, id: %s\n", pDataFrame->id);
|
||||
if (CFG->mqttSwitch_4G == 1) { // MQTT模式下,无需服务器响应数据
|
||||
AdapterDeviceMqttSend(adapter, CFG->mqttTopic_4G, pDataFrame->data,
|
||||
strlen(pDataFrame->data)); // 发送数据,注意当前最多发送256字节
|
||||
break;
|
||||
} else {
|
||||
AdapterDeviceSend(adapter, pDataFrame->data,
|
||||
strlen(pDataFrame->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
/* 多读取2字节,是为了防止前面还有命令模式返回的剩余的\r\n影响判断 */
|
||||
memset(receiveBuffer, 0, sizeof(receiveBuffer));
|
||||
int receiveLength = AdapterDeviceRecv(adapter, receiveBuffer, strlen(pDataFrame->id) + 2);
|
||||
if (receiveLength == strlen(pDataFrame->id) + 2 || receiveLength == strlen(pDataFrame->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receiveLength: %d\n", receiveLength);
|
||||
printf("receiveBuffer: ");
|
||||
for (int i = 0; i < receiveLength; i++) {
|
||||
printf("%c", receiveBuffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(receiveBuffer, pDataFrame->id) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
} else {
|
||||
printf("receiveLength: %d\n", receiveLength);
|
||||
printf("receiveBuffer: ");
|
||||
for (int i = 0; i < receiveLength; i++) {
|
||||
printf("%d ", receiveBuffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
resendCount--;
|
||||
}
|
||||
if (pDataFrame != NULL) {
|
||||
PrivFree(pDataFrame); // 释放数据帧内存
|
||||
pDataFrame = NULL; // 避免野指针
|
||||
}
|
||||
// AdapterDeviceDisconnect(adapter, NULL); // 关闭适配器对应的设备
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resendCount <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过以太网向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *sendDataToServerTask_Ethernet(void *arg) {
|
||||
uint8_t serverIpAddress[16] = {}; // 目的IP地址
|
||||
uint8_t serverPort[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *pQueueBuffer = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receiveBuffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_ETHERNET_NAME); // 查找以太网模块适配器
|
||||
|
||||
#ifndef BSP_BLE_CONFIG // 如果没有使能蓝牙配置功能
|
||||
AdapterDeviceSetUp(adapter); // 启动以太网主任务线程
|
||||
AdapterDeviceSetDhcp(adapter, CFG->dhcpSwitch_Ethernet); // 启用或禁用DHCP
|
||||
#endif
|
||||
|
||||
struct DataFrame *pDataFrame = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&pQueueBuffer->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 使能蓝牙配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待;
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(serverIpAddress, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(serverPort, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("serverIpAddress:\t%s\n", serverIpAddress);
|
||||
printf("serverPort:\t\t%s\n", serverPort);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, serverIpAddress, serverPort, IPV4);
|
||||
|
||||
/* 连接失败,则等待10s再次尝试连接 */
|
||||
if (res != 0 && res != 0x1D) {
|
||||
PrivSemaphoreAbandon(&pQueueBuffer->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(serverIpAddress, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(serverPort, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("serverIpAddress:\t%s\n", serverIpAddress);
|
||||
printf("serverPort:\t\t%s\n", serverPort);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnectCount = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnectCount > 0) {
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, serverIpAddress, serverPort, IPV4); // 尝试连接服务器
|
||||
if (res == 0 || res == 0x1D) {
|
||||
break;
|
||||
}
|
||||
reconnectCount--;
|
||||
}
|
||||
if (reconnectCount <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&pQueueBuffer->full); // 释放信号量
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&pQueueBuffer->mutex); // 获取互斥锁
|
||||
pDataFrame = pollBuffer(pQueueBuffer); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&pQueueBuffer->mutex); // 释放互斥锁
|
||||
|
||||
int resendCount = RESEND_COUNT; // 定义数据帧重发次数
|
||||
|
||||
/* 只有数据帧非空并且还有剩余重发次数,才进行发送 */
|
||||
while (pDataFrame != NULL && resendCount > 0) {
|
||||
/* 向服务器发送数据 */
|
||||
printf("send data to server, id: %s\n", pDataFrame->id);
|
||||
printf("pDataFrame->data: %s", pDataFrame->data);
|
||||
AdapterDeviceSend(adapter, pDataFrame->data,
|
||||
strlen(pDataFrame->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
memset(receiveBuffer, 0, sizeof(receiveBuffer));
|
||||
PrivTaskDelay(6000);
|
||||
if (AdapterDeviceRecv(adapter, receiveBuffer, strlen(pDataFrame->id)) == strlen(pDataFrame->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receiveBuffer: ");
|
||||
for (int i = 0; i < strlen(receiveBuffer); i++) {
|
||||
printf("%c", receiveBuffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(pDataFrame->id, receiveBuffer) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
}
|
||||
resendCount--;
|
||||
}
|
||||
if (pDataFrame != NULL) {
|
||||
PrivFree(pDataFrame); // 释放数据帧内存
|
||||
pDataFrame = NULL; // 避免野指针
|
||||
}
|
||||
AdapterDeviceDisconnect(adapter, NULL);
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resendCount <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开启从ADL400接收数据的线程以及上传数据到服务器的线程,此方法在main方法中被调用,开机或复位启动
|
||||
*/
|
||||
void startUpTransformDataTask(void) {
|
||||
/* 分配循环队列空间 */
|
||||
struct QueueBuffer *pQueueBuffer = (struct QueueBuffer *)PrivCalloc(1, sizeof(struct QueueBuffer));
|
||||
if (initBuffer(pQueueBuffer) < 0) {
|
||||
PrivFree(pQueueBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 启动从ADL400接收数据的线程 */
|
||||
pthread_attr_t receiveDataFromADL400TaskAttr;
|
||||
pthread_args_t receiveDataFromADL400TaskArgs;
|
||||
receiveDataFromADL400TaskAttr.schedparam.sched_priority = 16; // 线程优先级
|
||||
receiveDataFromADL400TaskAttr.stacksize = 2048; // 线程栈大小
|
||||
receiveDataFromADL400TaskArgs.pthread_name = "receiveDataFromADL400Task"; // 线程名字
|
||||
receiveDataFromADL400TaskArgs.arg = pQueueBuffer; // 线程参数
|
||||
pthread_t receiveDataThread; // 线程ID
|
||||
PrivTaskCreate(&receiveDataThread, &receiveDataFromADL400TaskAttr, receiveDataFromADL400Task, &receiveDataFromADL400TaskArgs);
|
||||
PrivTaskStartup(&receiveDataThread);
|
||||
|
||||
/* 启动上传数据到服务器的线程 */
|
||||
pthread_attr_t sendDataToServerTaskAttr;
|
||||
pthread_args_t sendDataToServerTaskArgs;
|
||||
sendDataToServerTaskAttr.schedparam.sched_priority = 16; // 线程优先级
|
||||
sendDataToServerTaskAttr.stacksize = 2200; // 线程栈大小
|
||||
sendDataToServerTaskArgs.pthread_name = "sendDataToServerTask"; // 线程名字
|
||||
sendDataToServerTaskArgs.arg = pQueueBuffer; // 线程参数
|
||||
pthread_t sendDataThread; // 线程ID
|
||||
void *(*start_routine)(void *) = sendDataToServerTask_4G; // 通过4G模块上传到服务器
|
||||
// void *(*start_routine)(void *) = sendDataToServerTask_Ethernet; // 通过以太网模块上传到服务器
|
||||
PrivTaskCreate(&sendDataThread, &sendDataToServerTaskAttr, start_routine, &sendDataToServerTaskArgs); // 通过4G模块上传到服务器
|
||||
PrivTaskStartup(&sendDataThread);
|
||||
}
|
||||
|
|
@ -1,807 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file .c
|
||||
* @brief Support reading data from WASION DTSD342 using the Modbus-RTU protocol
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2025.4.21
|
||||
*/
|
||||
|
||||
#include <ModuleConfig.h>
|
||||
#include <adapter.h>
|
||||
#include <transform.h>
|
||||
#include <math.h>
|
||||
#include <cJSON.h>
|
||||
|
||||
#define MAX_FRAME_SIZE 256 // 最大帧大小
|
||||
#define MAX_DATA_SIZE 1024 // 最大数据大小
|
||||
#define MAX_BUFFER_SIZE 1024 * 2 // 最大缓冲区大小
|
||||
#define RECEIVE_DATA_INTERVAL_MS 1000 * 60 * 2 // DTSD342数据采集间隔时间,单位为毫秒
|
||||
#define SAMPLE_DATA_INTERVAL_MS 350 // 稳定连续采集的间隔时间,单位为毫秒
|
||||
#define SEND_FRAME_LEN 8 // 发送帧长度
|
||||
#define RECEIVE_FRAME_LEN 5 // 返回帧长度(不包含各项数据长度)
|
||||
#define RESEND_COUNT 3 // 最大帧重发次数
|
||||
#define RECONNECT_COUNT 5 // 最大连接次数
|
||||
#define WATING_RESPONSE_MS 5000 // 等待响应时间,单位为毫秒
|
||||
#define DATA_COUNT (sizeof(data_start_address_map) / sizeof(data_start_address_map[0])) // 数据项数量
|
||||
#define READ_COMMAND 0x03 /* 读取数据 */
|
||||
#define ADDRESS 0x01
|
||||
#define FRAME_ID "DTSD342"
|
||||
|
||||
#ifndef DATA_ITEMS_DEF_H
|
||||
#define DATA_ITEMS_DEF_H
|
||||
|
||||
#define DATA_ITEMS_XMACRO \
|
||||
X(FORWARD_ACTIVE_ENERGY, 0x2006, 4, 1) /* 正向有功电能,4字节,1位小数,单位Wh */ \
|
||||
X(FORWARD_REACTIVE_ENERGY, 0x200E, 4, 1) /* 正向无功电能,4字节,1位小数,单位varh */ \
|
||||
X(REVERSE_ACTIVE_ENERGY, 0x2106, 4, 1) /* 反向有功电能,4字节,1位小数,单位Wh */ \
|
||||
X(REVERSE_REACTIVE_ENERGY, 0x210E, 4, 1) /* 反向无功电能,4字节,1位小数,单位varh */ \
|
||||
X(VOLTAGE_A, 0x1800, 4, 3) /* A相电压,4字节,3位小数,单位V */ \
|
||||
X(VOLTAGE_B, 0x1802, 4, 3) /* B相电压,4字节,3位小数,单位V */ \
|
||||
X(VOLTAGE_C, 0x1804, 4, 3) /* C相电压,4字节,3位小数,单位V */ \
|
||||
X(CURRENT_A, 0x1810, 4, 4) /* A相电流,4字节,4位小数,单位A */ \
|
||||
X(CURRENT_B, 0x1812, 4, 4) /* B相电流,4字节,4位小数,单位A */ \
|
||||
X(CURRENT_C, 0x1814, 4, 4) /* C相电流,4字节,4位小数,单位A */ \
|
||||
X(ACTIVE_POWER_A, 0x181A, 4, 1) /* A有功功率,4字节,1位小数,单位W */ \
|
||||
X(ACTIVE_POWER_B, 0x181C, 4, 1) /* B有功功率,4字节,1位小数,单位W */ \
|
||||
X(ACTIVE_POWER_C, 0x181E, 4, 1) /* C有功功率,4字节,1位小数,单位W */ \
|
||||
X(ACTIVE_POWER_TOTAL, 0x1820, 4, 1) /* 总有功功率,4字节,1位小数,单位W */ \
|
||||
X(REACTIVE_POWER_A, 0x1822, 4, 1) /* A无功功率,4字节,1位小数,单位var */ \
|
||||
X(REACTIVE_POWER_B, 0x1824, 4, 1) /* B无功功率,4字节,1位小数,单位var */ \
|
||||
X(REACTIVE_POWER_C, 0x1826, 4, 1) /* C无功功率,4字节,1位小数,单位var */ \
|
||||
X(REACTIVE_POWER_TOTAL, 0x1828, 4, 1) /* 总无功功率,4字节,1位小数,单位var */ \
|
||||
X(APPARENT_POWER_A, 0x182A, 4, 1) /* A视在功率,4字节,1位小数,单位VA */ \
|
||||
X(APPARENT_POWER_B, 0x182C, 4, 1) /* B视在功率,4字节,1位小数,单位VA */ \
|
||||
X(APPARENT_POWER_C, 0x182E, 4, 1) /* C视在功率,4字节,1位小数,单位VA */ \
|
||||
X(APPARENT_POWER_TOTAL, 0x1830, 4, 1) /* 总视在功率,4字节,1位小数,单位VA */ \
|
||||
X(POWER_FACTOR_A, 0x1019, 2, 3) /* A功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_B, 0x101A, 2, 3) /* B功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_C, 0x101B, 2, 3) /* C功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_TOTAL, 0x101C, 2, 3) /* 总功率因数,2字节,3位小数,单位无 */ \
|
||||
X(FREQUENCY, 0x101D, 2, 2) /* 电网频率,2字节,2位小数,单位Hz */ \
|
||||
X(INTERNAL_TEMPERATURE, 0x0135, 2, 0) /* 内部温度,2字节,0位小数,单位℃ */
|
||||
|
||||
#endif // DATA_ITEMS_DEF_H
|
||||
|
||||
#ifndef DATA_ITEMS_H
|
||||
#define DATA_ITEMS_H
|
||||
|
||||
typedef enum {
|
||||
#define X(name, start_address, size, dec) name,
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
} DataIdIndex;
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte_size;
|
||||
uint8_t decimal_places;
|
||||
} DataInfo;
|
||||
|
||||
static const uint16_t data_start_address_map[] = {
|
||||
#define X(name, start_address, size, dec) start_address,
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const DataInfo data_info_map[] = {
|
||||
#define X(name, start_address, size, dec) {size, dec},
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const char *data_id_names[] = {
|
||||
#define X(name, start_address, size, dec) #name,
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
#endif // DATA_ITEMS_H
|
||||
|
||||
/**
|
||||
* @brief 生成Modbus RTU请求帧中的CRC循环冗余码
|
||||
* @param data 需要生成CRC冗余码的数据指针
|
||||
* @param len 需要生成CRC冗余码的数据长度
|
||||
* @return uint16_t
|
||||
*/
|
||||
static uint16_t GenerateCRC(uint8_t *data, uint8_t len) {
|
||||
uint16_t crc = 0xFFFF;
|
||||
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (crc & 0x0001)
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return crc; // 返回原始值,高字节在高位
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 生成Modbus RTU请求帧,用于获取指定寄存器的值
|
||||
* @param address 请求的Modbus地址
|
||||
* @param function_code 功能码
|
||||
* @param start_address 数据起始地址
|
||||
* @param quantity 数据读取个数
|
||||
* @param request_frame 生成的ModBus RTU请求帧数组
|
||||
* @return int 0表示生成成功,其他结果表示生成失败
|
||||
* @note Modbus
|
||||
* RTU请求帧格式:地址(1字节)+功能码(1字节)+数据起始地址(2字节)+数据读取个数(2字节)+校验码(2字节)
|
||||
*/
|
||||
static int GenerateRequestFrame(unsigned char address, unsigned char function_code, unsigned short start_address, unsigned short quantity, unsigned char request_frame[]) {
|
||||
request_frame[0] = address;
|
||||
request_frame[1] = function_code;
|
||||
request_frame[2] = (start_address >> 8) & 0xff;
|
||||
request_frame[3] = start_address & 0xff;
|
||||
request_frame[4] = (quantity >> 8) & 0xff;
|
||||
request_frame[5] = quantity & 0xff;
|
||||
|
||||
uint16_t crc = GenerateCRC(request_frame, 6);
|
||||
|
||||
request_frame[6] = crc & 0xff;
|
||||
request_frame[7] = (crc >> 8) & 0xff;
|
||||
|
||||
// printf("GenerateRequestFrame: ");
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// printf("%02X ", request_frame[i]);
|
||||
// printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将要上传服务器的数据帧
|
||||
*/
|
||||
struct DataFrame {
|
||||
unsigned char id[8]; // 电表型号标识
|
||||
unsigned char data[MAX_DATA_SIZE]; // 上传服务器的数据帧字符串,用JSON封装
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modbus RTU响应数据帧的缓存,使用循环队列作为数据结构
|
||||
*/
|
||||
struct QueueBuffer {
|
||||
struct DataFrame *buffer[MAX_BUFFER_SIZE / sizeof(struct DataFrame)]; // 循环队列存储空间,使用数组存储
|
||||
int front; // 循环队列队头
|
||||
int rear; // 循环队列队尾
|
||||
pthread_mutex_t mutex; // 互斥访问循环队列信号量
|
||||
sem_t full; // 循环队列中有效成员个数的信号量
|
||||
};
|
||||
|
||||
#define BUFFER_ELEM_COUNT (MAX_BUFFER_SIZE / sizeof(struct DataFrame)) // 循环队列中可以容纳的最大成员个数
|
||||
|
||||
/**
|
||||
* @brief 初始化循环队列
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return * int 0表示初始化成功,其他表示初始化失败
|
||||
*/
|
||||
static int InitBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
queue_buffer_ptr->front = 0;
|
||||
queue_buffer_ptr->rear = 0;
|
||||
if (PrivMutexCreate(&queue_buffer_ptr->mutex, 0) < 0) {
|
||||
printf("buffer mutex create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (PrivSemaphoreCreate(&queue_buffer_ptr->full, 0, 0) < 0) {
|
||||
printf("buffer full semaphore create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列入队,如果循环队列已满,则将最旧的成员出队后,新成员再入队
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @param data_frame_ptr DTSD342响应数据帧
|
||||
* @return int 0表示入队成功,其他表示入队失败
|
||||
*/
|
||||
static int OfferBuffer(struct QueueBuffer *queue_buffer_ptr, struct DataFrame *data_frame_ptr) {
|
||||
/* 循环队列已满,将最旧的成员出队 */
|
||||
if ((queue_buffer_ptr->rear + 1) % BUFFER_ELEM_COUNT == queue_buffer_ptr->front) {
|
||||
struct DataFrame *front_data_frame_ptr = queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
PrivFree(front_data_frame_ptr);
|
||||
queue_buffer_ptr->front = (queue_buffer_ptr->front + 1) % BUFFER_ELEM_COUNT;
|
||||
}
|
||||
/* 新成员入队 */
|
||||
queue_buffer_ptr->buffer[queue_buffer_ptr->rear] = data_frame_ptr;
|
||||
queue_buffer_ptr->rear = (queue_buffer_ptr->rear + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", queue_buffer_ptr->front);
|
||||
printf("rear: %d\n", queue_buffer_ptr->rear);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列出队,如果队列为空则返回NULL
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return struct DataFrame* 出队成员,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *PollBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
/* 队列为空,返回NULL */
|
||||
if (queue_buffer_ptr->front == queue_buffer_ptr->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 最旧的成员出队 */
|
||||
struct DataFrame *front_data_frame_ptr = queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
queue_buffer_ptr->buffer[queue_buffer_ptr->front] = NULL;
|
||||
queue_buffer_ptr->front = (queue_buffer_ptr->front + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", queue_buffer_ptr->front);
|
||||
printf("rear: %d\n", queue_buffer_ptr->rear);
|
||||
return front_data_frame_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查看队头元素,如果队列为空则返回NULL
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return struct DataFrame* 队头元素,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *PeekBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
/* 如果队列为空,返回NULL */
|
||||
if (queue_buffer_ptr->front == queue_buffer_ptr->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 返回队头元素,但不出队 */
|
||||
return queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 改写PrivRead函数,原有函数只会读取接收缓冲区的当前已有字节,新函数会读取指定字节数再返回
|
||||
* @param fd 文件描述符
|
||||
* @param buf 数据读取到的位置
|
||||
* @param len 读取的指定字节数
|
||||
* @return int 如果读取到指定字节数返回0;如果到达WATING_RESPONSE_MS仍未读取到指定字节数,或者读数据错误,返回-1
|
||||
*/
|
||||
static int PrivReadEnoughData(int fd, void *buf, size_t len) {
|
||||
char *buffer = (char *)buf; // 将接收的存储空间指针强制转型
|
||||
int gotten_bytes = 0; // 已经读取到的字节数
|
||||
int remain_time = WATING_RESPONSE_MS; // 剩余的时间
|
||||
|
||||
/* 只有接收的字节数不够,并且还有剩余时间,才可以继续读取 */
|
||||
while (gotten_bytes < len && remain_time > 0) {
|
||||
int bytes = PrivRead(fd, buffer + gotten_bytes, len - gotten_bytes); // 从设备读取
|
||||
// printf("gotten_bytes: %d\n", bytes);
|
||||
gotten_bytes += bytes;
|
||||
PrivTaskDelay(100); // 每100ms读取一次
|
||||
remain_time -= 100; // 剩余时间减去100ms
|
||||
}
|
||||
/* 若没有剩余时间,表示还没有读取到指定的字节数,返回-1;若有剩余时间,表示已经读取了指定的字节数,返回0 */
|
||||
return remain_time < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析DTSD342响应的Modbus RTU数据帧
|
||||
* @param response_frame 返回的数据帧
|
||||
* @param data_info_ptr 数据项的字节数和小数位数信息
|
||||
* @param item_id 数据项ID
|
||||
* @param root 根节点
|
||||
*/
|
||||
static void ParseResponseFrame(unsigned char *response_frame, const DataInfo *data_info_ptr, int item_id, cJSON *root) {
|
||||
if (!response_frame || !data_info_ptr || !root) {
|
||||
printf("Invalid input to ParseResponseFrame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t data_len = response_frame[2]; // 数据域长度
|
||||
if (data_len != data_info_ptr->byte_size) {
|
||||
printf("Invalid data length in frame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *data_value = &response_frame[3]; // 数据内容起始位置
|
||||
|
||||
// for (int i = 0; i < data_info_ptr->byte_size; i++)
|
||||
// printf("%02x ", data_value[i]);
|
||||
|
||||
uint32_t raw_value = 0;
|
||||
for (int i = 0; i < data_len; i++) {
|
||||
raw_value = (raw_value << 8) | data_value[i]; // 高字节在前
|
||||
}
|
||||
|
||||
double scaled_value = raw_value / pow(10, data_info_ptr->decimal_places);
|
||||
// printf("Parsed value: %.*f\n", data_info_ptr->decimal_places, scaled_value);
|
||||
|
||||
char format[10];
|
||||
snprintf(format, sizeof(format), "%%.%df", data_info_ptr->decimal_places);
|
||||
|
||||
char scaled_value_str[20];
|
||||
snprintf(scaled_value_str, sizeof(scaled_value_str), format, scaled_value);
|
||||
|
||||
cJSON_AddStringToObject(root, data_id_names[item_id], scaled_value_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从DTSD342接收数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *ReceiveDataFromDTSD342Task(void *arg) {
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
int fd = PrivOpen("/dev/rs485_dev1", O_RDWR); // 打开设备文件
|
||||
if (fd < 0) { // 打开设备文件失败,打印错误信息
|
||||
printf("open rs485 fd error: %d\n", fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct SerialDataCfg rs485_configuration;
|
||||
memset(&rs485_configuration, 0, sizeof(struct SerialDataCfg));
|
||||
/* 读取RS485配置信息 */
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
int baud_rates_option = CFG->baudRate_Rs485;
|
||||
int data_bits_option = CFG->dataBits_Rs485;
|
||||
int stop_bits_option = CFG->stopBits_Rs485;
|
||||
int parity_option = CFG->parity_Rs485;
|
||||
PrivMutexAbandon(&romConfigurationMutex); // 释放互斥锁
|
||||
switch (baud_rates_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_2400;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_4800;
|
||||
break;
|
||||
case 3:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_9600; // 默认波特率9600
|
||||
break;
|
||||
case 4:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_19200;
|
||||
break;
|
||||
case 5:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_38400;
|
||||
break;
|
||||
case 6:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_57600;
|
||||
break;
|
||||
case 7:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_115200;
|
||||
break;
|
||||
case 8:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_230400;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_9600;
|
||||
break;
|
||||
}
|
||||
switch (data_bits_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_9;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
}
|
||||
switch (stop_bits_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_2;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
}
|
||||
switch (parity_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_parity_mode = PARITY_NONE; // 默认无奇偶校验
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_parity_mode = PARITY_ODD;
|
||||
break;
|
||||
case 3:
|
||||
rs485_configuration.serial_parity_mode = PARITY_EVEN;
|
||||
break;
|
||||
}
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&rs485_configuration;
|
||||
if (0 != PrivIoctl(fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("ioctl uart fd error %d\n", fd);
|
||||
PrivClose(fd);
|
||||
return NULL;
|
||||
}
|
||||
printf("open rs485 fd success %d\n", fd);
|
||||
|
||||
unsigned char request_frame[MAX_FRAME_SIZE]; // 定义请求帧
|
||||
unsigned char response_frame[MAX_FRAME_SIZE]; // 定义回复帧
|
||||
while (1) {
|
||||
printf("enter cycle\n");
|
||||
struct DataFrame *data_frame_ptr = (struct DataFrame *)PrivMalloc(sizeof(struct DataFrame));
|
||||
memset(data_frame_ptr, 0, sizeof(struct DataFrame));
|
||||
|
||||
// 创建一个空的JSON对象
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
int is_success = 1;
|
||||
|
||||
for (int i = 0; i < DATA_COUNT; i++) {
|
||||
const uint16_t start_address = data_start_address_map[i];
|
||||
const DataInfo *data_info = &data_info_map[i];
|
||||
|
||||
memset(request_frame, 0, sizeof(request_frame));
|
||||
if (GenerateRequestFrame(ADDRESS, READ_COMMAND, start_address, data_info->byte_size / 2, request_frame) < 0) {
|
||||
printf("Generate frame failed for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
PrivWrite(fd, request_frame, SEND_FRAME_LEN); // 发送Modbus RTU请求帧
|
||||
|
||||
/* 读取响应帧数据 */
|
||||
memset(response_frame, 0, sizeof(response_frame));
|
||||
if (PrivReadEnoughData(fd, response_frame, RECEIVE_FRAME_LEN + data_info->byte_size) < 0) {
|
||||
printf("Timeout reading response for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("Response frame for index %d: ", i);
|
||||
// for (int j = 0; j < RECEIVE_FRAME_LEN + data_info->byte_size; j++)
|
||||
// printf("%02X ", response_frame[j]);
|
||||
// printf("\n");
|
||||
|
||||
// 校验帧头、帧尾
|
||||
if (response_frame[0] != ADDRESS || response_frame[1] != READ_COMMAND) {
|
||||
printf("Invalid frame format for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// 校验和
|
||||
uint16_t calc_crc16 = GenerateCRC(response_frame, RECEIVE_FRAME_LEN + data_info->byte_size - 2);
|
||||
uint16_t recv_crc16 = (response_frame[RECEIVE_FRAME_LEN + data_info->byte_size - 1] << 8) | response_frame[RECEIVE_FRAME_LEN + data_info->byte_size - 2];
|
||||
if (calc_crc16 != recv_crc16) {
|
||||
printf("Modbus CRC16 error at index %d: calc %04X, recv %04X\n", i, calc_crc16, recv_crc16);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ParseResponseFrame(response_frame, data_info, i, root);
|
||||
|
||||
PrivTaskDelay(SAMPLE_DATA_INTERVAL_MS);
|
||||
}
|
||||
|
||||
if (!is_success) {
|
||||
printf("read all data failed\n");
|
||||
PrivFree(data_frame_ptr);
|
||||
cJSON_Delete(root);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data_frame_ptr->id, FRAME_ID, strlen(FRAME_ID));
|
||||
printf("data_frame_ptr->id: %s\n", data_frame_ptr->id);
|
||||
|
||||
char *json_str = cJSON_Print(root);
|
||||
strncpy((char *)data_frame_ptr->data, json_str, MAX_DATA_SIZE - 1);
|
||||
data_frame_ptr->data[MAX_DATA_SIZE - 1] = '\0'; // 确保结尾是 \0
|
||||
printf("data_frame_ptr->data: %s\n", data_frame_ptr->data);
|
||||
|
||||
// 删除字符串空间
|
||||
free(json_str);
|
||||
// 删除 cJSON 对象
|
||||
cJSON_Delete(root);
|
||||
|
||||
/* 将解析后的数据帧放入循环队列 */
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
OfferBuffer(queue_buffer_ptr, data_frame_ptr); // 将数据帧放入队列
|
||||
printf("receive data from DTSD342, id: %s\n", data_frame_ptr->id); // 打印接收到的数据帧ID
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量,即告知发送数据线程,队列中有新的数据帧
|
||||
|
||||
PrivTaskDelay(RECEIVE_DATA_INTERVAL_MS); // 延迟一段时间再读取下一帧数据
|
||||
|
||||
printf("end cycle\n");
|
||||
}
|
||||
|
||||
PrivClose(fd); // 关闭设备文件
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过4G向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *SendDataToServerTask_4G(void *arg) {
|
||||
uint8_t server_ip_address[16] = {}; // 目的IP地址
|
||||
uint8_t server_port[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receive_buffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_4G_NAME); // 查找4G模块适配器
|
||||
|
||||
AdapterDeviceOpen(adapter); // 打开适配器对应的设备(实际打开串口中断)
|
||||
int baud_rate = BAUD_RATE_115200; // 波特率,用于设置4G模块串口
|
||||
AdapterDeviceControl(adapter, OPE_INT, &baud_rate); // 对适配器对应设备进行配置(实际配置波特率)
|
||||
|
||||
struct DataFrame *data_frame_ptr = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&queue_buffer_ptr->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 如果启用了BLE配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
if (CFG->mqttSwitch_4G == 1) { // 如果使能MQTT
|
||||
AdapterDeviceMqttConnect(adapter, server_ip_address, server_port, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else { // 如果禁用MQTT
|
||||
AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
}
|
||||
|
||||
AdapterDeviceNetstat(adapter); // 读取网络连接状态
|
||||
/* 若连接失败,则等待10s再次尝试连接 */
|
||||
if (CFG->mqttSwitch_4G == 0 && !adapter->network_info.is_connected ||
|
||||
CFG->mqttSwitch_4G == 1 && !adapter->network_info.mqttIsConnected) {
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else // 如果没有启用BLE配置功能
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnect_count = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnect_count > 0) {
|
||||
int res;
|
||||
if (CFG->mqttSwitch_4G == 1) {
|
||||
res = AdapterDeviceMqttConnect(adapter, mqttServerIp, mqttServerPort, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else {
|
||||
res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
reconnect_count--;
|
||||
}
|
||||
if (reconnect_count <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
data_frame_ptr = PollBuffer(queue_buffer_ptr); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
|
||||
int resend_count = RESEND_COUNT; // 定义数据帧重发次数
|
||||
while (data_frame_ptr != NULL && resend_count > 0) { // 只有数据帧非空并且还有剩余重发次数,才进行发送
|
||||
/* 向服务器发送数据 */
|
||||
printf("data_frame_ptr->data: %s", data_frame_ptr->data);
|
||||
printf("send data to server, id: %s\n", data_frame_ptr->id);
|
||||
if (CFG->mqttSwitch_4G == 1) { // MQTT模式下,无需服务器响应数据
|
||||
AdapterDeviceMqttSend(adapter, CFG->mqttTopic_4G, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
break;
|
||||
} else {
|
||||
AdapterDeviceSend(adapter, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
/* 多读取2字节,是为了防止前面还有命令模式返回的剩余的\r\n影响判断 */
|
||||
memset(receive_buffer, 0, sizeof(receive_buffer));
|
||||
int receive_length = AdapterDeviceRecv(adapter, receive_buffer, strlen(data_frame_ptr->id) + 2);
|
||||
if (receive_length == strlen(data_frame_ptr->id) + 2 || receive_length == strlen(data_frame_ptr->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receive_length: %d\n", receive_length);
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < receive_length; i++) {
|
||||
printf("%c", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(receive_buffer, data_frame_ptr->id) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
} else {
|
||||
printf("receive_length: %d\n", receive_length);
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < receive_length; i++) {
|
||||
printf("%d ", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
resend_count--;
|
||||
}
|
||||
if (data_frame_ptr != NULL) {
|
||||
PrivFree(data_frame_ptr); // 释放数据帧内存
|
||||
data_frame_ptr = NULL; // 避免野指针
|
||||
}
|
||||
// AdapterDeviceDisconnect(adapter, NULL); // 关闭适配器对应的设备
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resend_count <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过以太网向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *SendDataToServerTask_Ethernet(void *arg) {
|
||||
uint8_t server_ip_address[16] = {}; // 目的IP地址
|
||||
uint8_t server_port[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receive_buffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_ETHERNET_NAME); // 查找以太网模块适配器
|
||||
|
||||
#ifndef BSP_BLE_CONFIG // 如果没有使能蓝牙配置功能
|
||||
AdapterDeviceSetUp(adapter); // 启动以太网主任务线程
|
||||
AdapterDeviceSetDhcp(adapter, CFG->dhcpSwitch_Ethernet); // 启用或禁用DHCP
|
||||
#endif
|
||||
|
||||
struct DataFrame *data_frame_ptr = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&queue_buffer_ptr->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 使能蓝牙配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待;
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
|
||||
/* 连接失败,则等待10s再次尝试连接 */
|
||||
if (res != 0 && res != 0x1D) {
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnect_count = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnect_count > 0) {
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4); // 尝试连接服务器
|
||||
if (res == 0 || res == 0x1D) {
|
||||
break;
|
||||
}
|
||||
reconnect_count--;
|
||||
}
|
||||
if (reconnect_count <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
data_frame_ptr = PollBuffer(queue_buffer_ptr); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
|
||||
int resend_count = RESEND_COUNT; // 定义数据帧重发次数
|
||||
|
||||
/* 只有数据帧非空并且还有剩余重发次数,才进行发送 */
|
||||
while (data_frame_ptr != NULL && resend_count > 0) {
|
||||
/* 向服务器发送数据 */
|
||||
printf("send data to server, id: %s\n", data_frame_ptr->id);
|
||||
printf("data_frame_ptr->data: %s", data_frame_ptr->data);
|
||||
AdapterDeviceSend(adapter, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
memset(receive_buffer, 0, sizeof(receive_buffer));
|
||||
PrivTaskDelay(6000);
|
||||
if (AdapterDeviceRecv(adapter, receive_buffer, strlen(data_frame_ptr->id)) == strlen(data_frame_ptr->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < strlen(receive_buffer); i++) {
|
||||
printf("%c", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(data_frame_ptr->id, receive_buffer) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
}
|
||||
resend_count--;
|
||||
}
|
||||
if (data_frame_ptr != NULL) {
|
||||
PrivFree(data_frame_ptr); // 释放数据帧内存
|
||||
data_frame_ptr = NULL; // 避免野指针
|
||||
}
|
||||
AdapterDeviceDisconnect(adapter, NULL);
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resend_count <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开启从DTSD342接收数据的线程以及上传数据到服务器的线程,此方法在main方法中被调用,开机或复位启动
|
||||
*/
|
||||
void StartUpTransformDataTask(void) {
|
||||
/* 分配循环队列空间 */
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)PrivCalloc(1, sizeof(struct QueueBuffer));
|
||||
if (InitBuffer(queue_buffer_ptr) < 0) {
|
||||
PrivFree(queue_buffer_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 启动从DTSD342接收数据的线程 */
|
||||
pthread_attr_t receive_data_from_dtsd342_task_attr;
|
||||
pthread_args_t receive_data_from_dtsd342_task_args;
|
||||
receive_data_from_dtsd342_task_attr.schedparam.sched_priority = 16; // 线程优先级
|
||||
receive_data_from_dtsd342_task_attr.stacksize = 2048; // 线程栈大小
|
||||
receive_data_from_dtsd342_task_args.pthread_name = "ReceiveDataFromDTSD342Task"; // 线程名字
|
||||
receive_data_from_dtsd342_task_args.arg = queue_buffer_ptr; // 线程参数
|
||||
pthread_t receive_data_thread; // 线程ID
|
||||
PrivTaskCreate(&receive_data_thread, &receive_data_from_dtsd342_task_attr, ReceiveDataFromDTSD342Task, &receive_data_from_dtsd342_task_args);
|
||||
PrivTaskStartup(&receive_data_thread);
|
||||
|
||||
/* 启动上传数据到服务器的线程 */
|
||||
pthread_attr_t send_data_to_server_task_attr;
|
||||
pthread_args_t send_data_to_server_task_args;
|
||||
send_data_to_server_task_attr.schedparam.sched_priority = 16; // 线程优先级
|
||||
send_data_to_server_task_attr.stacksize = 2200; // 线程栈大小
|
||||
send_data_to_server_task_args.pthread_name = "SendDataToServerTask"; // 线程名字
|
||||
send_data_to_server_task_args.arg = queue_buffer_ptr; // 线程参数
|
||||
pthread_t send_data_thread; // 线程ID
|
||||
void *(*start_routine)(void *) = SendDataToServerTask_4G; // 通过4G模块上传到服务器
|
||||
// void *(*start_routine)(void *) = SendDataToServerTask_Ethernet; // 通过以太网模块上传到服务器
|
||||
PrivTaskCreate(&send_data_thread, &send_data_to_server_task_attr, start_routine, &send_data_to_server_task_args); // 通过4G模块上传到服务器
|
||||
PrivTaskStartup(&send_data_thread);
|
||||
}
|
||||
|
|
@ -1,862 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file .c
|
||||
* @brief Support reading data from WISDOM DTZ178 using the DL/T645-2007 protocol
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2025.4.14
|
||||
*/
|
||||
|
||||
#include <ModuleConfig.h>
|
||||
#include <adapter.h>
|
||||
#include <transform.h>
|
||||
#include <math.h>
|
||||
#include <cJSON.h>
|
||||
|
||||
#define MAX_FRAME_SIZE 256 // 最大帧大小
|
||||
#define MAX_DATA_SIZE 1024 // 最大数据大小
|
||||
#define MAX_BUFFER_SIZE 1024 * 2 // 最大缓冲区大小
|
||||
#define RECEIVE_DATA_INTERVAL_MS 1000 * 60 * 2 // DTZ178数据采集间隔时间,单位为毫秒
|
||||
#define SAMPLE_DATA_INTERVAL_MS 300 // 稳定连续采集的间隔时间,单位为毫秒
|
||||
#define SEND_FRAME_LEN 16 // 发送帧长度
|
||||
#define BASE_RECEIVE_FRAME_LEN 16 // 基础返回帧长度(不包含各项数据长度)
|
||||
#define TOTAL_RECEIVE_FRAME_LEN 20 // 总返回帧长度(不包含各项数据长度),包含4个前置0xFE字节
|
||||
#define RESEND_COUNT 3 // 最大帧重发次数
|
||||
#define RECONNECT_COUNT 5 // 最大连接次数
|
||||
#define WATING_RESPONSE_MS 5000 // 等待响应时间,单位为毫秒
|
||||
#define DATA_COUNT (sizeof(data_id_map) / sizeof(data_id_map[0])) // 数据项数量
|
||||
#define READ_COMMAND 0x11 // 读取数据指令
|
||||
|
||||
static const uint8_t addr_meter[6] = {0x01, 0x22, 0x00, 0x03, 0x61, 0x74};
|
||||
static uint8_t parsed_date[11] = {0};
|
||||
static uint8_t parsed_time[9] = {0};
|
||||
|
||||
#ifndef DATA_ITEMS_DEF_H
|
||||
#define DATA_ITEMS_DEF_H
|
||||
|
||||
#define DATA_ITEMS_XMACRO \
|
||||
X(ENERGY_TOTAL, 0x00, 0x00, 0x00, 0x00, 4, 2) /* 总电能,4字节,2位小数,单位kWh */ \
|
||||
X(ENERGY_ACTIVE, 0x00, 0x01, 0x00, 0x00, 4, 2) /* 有功电能,4字节,2位小数,单位kWh */ \
|
||||
X(ENERGY_REACTIVE, 0x00, 0x02, 0x00, 0x00, 4, 2) /* 无功电能,4字节,2位小数,单位kWh */ \
|
||||
X(VOLTAGE_A, 0x02, 0x01, 0x01, 0x00, 2, 1) /* A相电压,2字节,1位小数,单位V */ \
|
||||
X(VOLTAGE_B, 0x02, 0x01, 0x02, 0x00, 2, 1) /* B相电压,2字节,1位小数,单位V */ \
|
||||
X(VOLTAGE_C, 0x02, 0x01, 0x03, 0x00, 2, 1) /* C相电压,2字节,1位小数,单位V */ \
|
||||
X(CURRENT_A, 0x02, 0x02, 0x01, 0x00, 3, 3) /* A相电流,3字节,3位小数,单位A */ \
|
||||
X(CURRENT_B, 0x02, 0x02, 0x02, 0x00, 3, 3) /* B相电流,3字节,3位小数,单位A */ \
|
||||
X(CURRENT_C, 0x02, 0x02, 0x03, 0x00, 3, 3) /* C相电流,3字节,3位小数,单位A */ \
|
||||
X(ACTIVE_POWER_TOTAL, 0x02, 0x03, 0x00, 0x00, 3, 4) /* 总有功功率,3字节,4位小数,单位kW */ \
|
||||
X(ACTIVE_POWER_A, 0x02, 0x03, 0x01, 0x00, 3, 4) /* A有功功率,3字节,4位小数,单位kW */ \
|
||||
X(ACTIVE_POWER_B, 0x02, 0x03, 0x02, 0x00, 3, 4) /* B有功功率,3字节,4位小数,单位kW */ \
|
||||
X(ACTIVE_POWER_C, 0x02, 0x03, 0x03, 0x00, 3, 4) /* C有功功率,3字节,4位小数,单位kW */ \
|
||||
X(REACTIVE_POWER_TOTAL, 0x02, 0x04, 0x00, 0x00, 3, 4) /* 总无功功率,3字节,4位小数,单位kvar */ \
|
||||
X(REACTIVE_POWER_A, 0x02, 0x04, 0x01, 0x00, 3, 4) /* A无功功率,3字节,4位小数,单位kvar */ \
|
||||
X(REACTIVE_POWER_B, 0x02, 0x04, 0x02, 0x00, 3, 4) /* B无功功率,3字节,4位小数,单位kvar */ \
|
||||
X(REACTIVE_POWER_C, 0x02, 0x04, 0x03, 0x00, 3, 4) /* C无功功率,3字节,4位小数,单位kvar */ \
|
||||
X(APPARENT_POWER_TOTAL, 0x02, 0x05, 0x00, 0x00, 3, 4) /* 总视在功率,3字节,4位小数,单位kVA */ \
|
||||
X(APPARENT_POWER_A, 0x02, 0x05, 0x01, 0x00, 3, 4) /* A视在功率,3字节,4位小数,单位kVA */ \
|
||||
X(APPARENT_POWER_B, 0x02, 0x05, 0x02, 0x00, 3, 4) /* B视在功率,3字节,4位小数,单位kVA */ \
|
||||
X(APPARENT_POWER_C, 0x02, 0x05, 0x03, 0x00, 3, 4) /* C视在功率,3字节,4位小数,单位kVA */ \
|
||||
X(POWER_FACTOR_TOTAL, 0x02, 0x06, 0x00, 0x00, 2, 3) /* 总功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_A, 0x02, 0x06, 0x01, 0x00, 2, 3) /* A功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_B, 0x02, 0x06, 0x02, 0x00, 2, 3) /* B功率因数,2字节,3位小数,单位无 */ \
|
||||
X(POWER_FACTOR_C, 0x02, 0x06, 0x03, 0x00, 2, 3) /* C功率因数,2字节,3位小数,单位无 */ \
|
||||
X(FREQUENCY, 0x02, 0x80, 0x00, 0x02, 2, 2) /* 电网频率,2字节,2位小数,单位Hz */ \
|
||||
X(INTERNAL_TEMPERATURE, 0x02, 0x80, 0x00, 0x07, 2, 1) /* 内部温度,2字节,1位小数,单位℃ */ \
|
||||
X(DATE_YMD, 0x04, 0x00, 0x01, 0x01, 4, 0) /* 年月日星期,4字节,0位小数,单位无*/ \
|
||||
X(TIME_HMS, 0x04, 0x00, 0x01, 0x02, 3, 0) /* 时分秒,3字节,0位小数,单位无 */
|
||||
|
||||
|
||||
#endif // DATA_ITEMS_DEF_H
|
||||
|
||||
#ifndef DATA_ITEMS_H
|
||||
#define DATA_ITEMS_H
|
||||
|
||||
typedef enum {
|
||||
#define X(name, id3, id2, id1, id0, size, dec) name,
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
} DataIdIndex;
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte_size;
|
||||
uint8_t decimal_places;
|
||||
} DataInfo;
|
||||
|
||||
static const uint8_t data_id_map[][4] = {
|
||||
#define X(name, id3, id2, id1, id0, size, dec) {id3, id2, id1, id0},
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const DataInfo data_info_map[] = {
|
||||
#define X(name, id3, id2, id1, id0, size, dec) {size, dec},
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const char *data_id_names[] = {
|
||||
#define X(name, id3, id2, id1, id0, size, dec) #name,
|
||||
DATA_ITEMS_XMACRO
|
||||
#undef X
|
||||
};
|
||||
|
||||
#endif // DATA_ITEMS_H
|
||||
|
||||
/**
|
||||
* @brief 计算DL/T645-2007数据帧的校验和
|
||||
* @param data 数据帧指针
|
||||
* @param len 校验的长度(从第一个 0x68 开始,到CS前一位)
|
||||
* @return uint8_t 校验和
|
||||
*/
|
||||
static uint8_t CheckSum(const uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint16_t sum = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
return (uint8_t)(sum & 0xFF); // 返回低8位
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 构造DL/T645-2007协议数据帧
|
||||
* @param addr 6字节地址(低位在前)
|
||||
* @param ctrl_code 控制码,如0x11表示读数据
|
||||
* @param data_id 4字节数据标识(低位在前)
|
||||
* @param data 数据域内容(可为空)
|
||||
* @param data_len 数据域长度(读数据时<=200,写数据时<=50)
|
||||
* @param request_frame 输出构造好的完整帧
|
||||
* @return int 0成功,-1失败
|
||||
*/
|
||||
static int GenerateRequestFrame(const uint8_t addr[6], uint8_t ctrl_code, const uint8_t data_id[4], const uint8_t *data, uint8_t data_len, uint8_t *request_frame)
|
||||
{
|
||||
if (!addr || !data_id || !request_frame)
|
||||
return -1;
|
||||
|
||||
uint8_t idx = 0;
|
||||
request_frame[idx++] = 0x68;
|
||||
|
||||
// 地址 6 字节(低位在前)
|
||||
for (int i = 5; i >= 0; i--)
|
||||
request_frame[idx++] = addr[i];
|
||||
|
||||
request_frame[idx++] = 0x68;
|
||||
request_frame[idx++] = ctrl_code;
|
||||
|
||||
uint8_t total_data_len = 4 + data_len;
|
||||
request_frame[idx++] = total_data_len;
|
||||
|
||||
// 数据标识 + 数据内容,低位在前,+0x33加密
|
||||
for (int i = 3; i >= 0; i--)
|
||||
request_frame[idx++] = data_id[i] + 0x33;
|
||||
|
||||
for (int i = 0; i < data_len; i++)
|
||||
request_frame[idx++] = data[i] + 0x33;
|
||||
|
||||
// 校验和
|
||||
uint8_t cs = CheckSum(request_frame, idx);
|
||||
request_frame[idx++] = cs;
|
||||
|
||||
// 结束码
|
||||
request_frame[idx++] = 0x16;
|
||||
|
||||
// printf("GenerateRequestFrame: ");
|
||||
// for (int i = 0; i < idx; i++) {
|
||||
// printf("%02X ", request_frame[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将要上传服务器的数据帧
|
||||
*/
|
||||
struct DataFrame {
|
||||
unsigned char id[20]; // 用响应的时间戳作为数据帧的id
|
||||
unsigned char data[MAX_DATA_SIZE]; // 上传服务器的数据帧字符串,用JSON封装
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modbus RTU响应数据帧的缓存,使用循环队列作为数据结构
|
||||
*/
|
||||
struct QueueBuffer {
|
||||
struct DataFrame *buffer[MAX_BUFFER_SIZE / sizeof(struct DataFrame)]; // 循环队列存储空间,使用数组存储
|
||||
int front; // 循环队列队头
|
||||
int rear; // 循环队列队尾
|
||||
pthread_mutex_t mutex; // 互斥访问循环队列信号量
|
||||
sem_t full; // 循环队列中有效成员个数的信号量
|
||||
};
|
||||
|
||||
#define BUFFER_ELEM_COUNT (MAX_BUFFER_SIZE / sizeof(struct DataFrame)) // 循环队列中可以容纳的最大成员个数
|
||||
|
||||
/**
|
||||
* @brief 初始化循环队列
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return * int 0表示初始化成功,其他表示初始化失败
|
||||
*/
|
||||
static int InitBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
queue_buffer_ptr->front = 0;
|
||||
queue_buffer_ptr->rear = 0;
|
||||
if (PrivMutexCreate(&queue_buffer_ptr->mutex, 0) < 0) {
|
||||
printf("buffer mutex create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (PrivSemaphoreCreate(&queue_buffer_ptr->full, 0, 0) < 0) {
|
||||
printf("buffer full semaphore create failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列入队,如果循环队列已满,则将最旧的成员出队后,新成员再入队
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @param data_frame_ptr DTZ178响应数据帧
|
||||
* @return int 0表示入队成功,其他表示入队失败
|
||||
*/
|
||||
static int OfferBuffer(struct QueueBuffer *queue_buffer_ptr, struct DataFrame *data_frame_ptr) {
|
||||
/* 循环队列已满,将最旧的成员出队 */
|
||||
if ((queue_buffer_ptr->rear + 1) % BUFFER_ELEM_COUNT == queue_buffer_ptr->front) {
|
||||
struct DataFrame *front_data_frame_ptr = queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
PrivFree(front_data_frame_ptr);
|
||||
queue_buffer_ptr->front = (queue_buffer_ptr->front + 1) % BUFFER_ELEM_COUNT;
|
||||
}
|
||||
/* 新成员入队 */
|
||||
queue_buffer_ptr->buffer[queue_buffer_ptr->rear] = data_frame_ptr;
|
||||
queue_buffer_ptr->rear = (queue_buffer_ptr->rear + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", queue_buffer_ptr->front);
|
||||
printf("rear: %d\n", queue_buffer_ptr->rear);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 循环队列出队,如果队列为空则返回NULL
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return struct DataFrame* 出队成员,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *PollBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
/* 队列为空,返回NULL */
|
||||
if (queue_buffer_ptr->front == queue_buffer_ptr->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 最旧的成员出队 */
|
||||
struct DataFrame *front_data_frame_ptr = queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
queue_buffer_ptr->buffer[queue_buffer_ptr->front] = NULL;
|
||||
queue_buffer_ptr->front = (queue_buffer_ptr->front + 1) % BUFFER_ELEM_COUNT;
|
||||
printf("front: %d\n", queue_buffer_ptr->front);
|
||||
printf("rear: %d\n", queue_buffer_ptr->rear);
|
||||
return front_data_frame_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查看队头元素,如果队列为空则返回NULL
|
||||
* @param queue_buffer_ptr 循环队列指针
|
||||
* @return struct DataFrame* 队头元素,如果队列为空则返回NULL
|
||||
*/
|
||||
static struct DataFrame *PeekBuffer(struct QueueBuffer *queue_buffer_ptr) {
|
||||
/* 如果队列为空,返回NULL */
|
||||
if (queue_buffer_ptr->front == queue_buffer_ptr->rear) {
|
||||
return NULL;
|
||||
}
|
||||
/* 返回队头元素,但不出队 */
|
||||
return queue_buffer_ptr->buffer[queue_buffer_ptr->front];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 改写PrivRead函数,原有函数只会读取接收缓冲区的当前已有字节,新函数会读取指定字节数再返回
|
||||
* @param fd 文件描述符
|
||||
* @param buf 数据读取到的位置
|
||||
* @param len 读取的指定字节数
|
||||
* @return int 如果读取到指定字节数返回0;如果到达WATING_RESPONSE_MS仍未读取到指定字节数,或者读数据错误,返回-1
|
||||
*/
|
||||
static int PrivReadEnoughData(int fd, void *buf, size_t len) {
|
||||
char *buffer = (char *)buf; // 将接收的存储空间指针强制转型
|
||||
int gotten_bytes = 0; // 已经读取到的字节数
|
||||
int remain_time = WATING_RESPONSE_MS; // 剩余的时间
|
||||
|
||||
/* 只有接收的字节数不够,并且还有剩余时间,才可以继续读取 */
|
||||
while (gotten_bytes < len && remain_time > 0) {
|
||||
int bytes = PrivRead(fd, buffer + gotten_bytes, len - gotten_bytes); // 从设备读取
|
||||
gotten_bytes += bytes;
|
||||
PrivTaskDelay(100); // 每100ms读取一次
|
||||
remain_time -= 100; // 剩余时间减去100ms
|
||||
}
|
||||
/* 若没有剩余时间,表示还没有读取到指定的字节数,返回-1;若有剩余时间,表示已经读取了指定的字节数,返回0 */
|
||||
return remain_time < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将BCD格式的多字节数值转换为十进制整数
|
||||
* @param bcd BCD格式的原始数值(低字节在低位)
|
||||
* @param bytes BCD所占用的字节数
|
||||
* @return 转换后的十进制整数结果
|
||||
* @note 每个字节的高4位和低4位分别代表1位十进制数字,即每个字节表示两位十进制数。
|
||||
* 最低位字节代表最低的两位十进制数,依此类推。例如 0x12 0x34 表示1234。
|
||||
*/
|
||||
static uint32_t BcdToDecimal(uint32_t bcd, uint8_t bytes)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
uint8_t byte = (bcd >> (i * 8)) & 0xFF;
|
||||
uint8_t high = (byte >> 4) & 0x0F; // 高4位
|
||||
uint8_t low = byte & 0x0F; // 低4位
|
||||
result += (high * 10 + low) * pow(100, i); // 每个字节是2位十进制
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析DTZ178响应的Modbus RTU数据帧
|
||||
* @param response_frame 返回的数据帧
|
||||
* @param data_info_ptr 数据项的字节数和小数位数信息
|
||||
* @param item_id 数据项ID
|
||||
* @param root 根节点
|
||||
*/
|
||||
static void ParseResponseFrame(unsigned char *response_frame, const DataInfo *data_info_ptr, int item_id, cJSON *root) {
|
||||
if (!response_frame || !data_info_ptr || !root) {
|
||||
printf("Invalid input to ParseResponseFrame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t data_len_total = response_frame[13]; // 数据域长度,包括数据标识(4字节) + 数据内容
|
||||
if (data_len_total < 4 || data_len_total - 4 != data_info_ptr->byte_size) {
|
||||
printf("Invalid data length in frame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *data_field = &response_frame[14]; // 数据域开始位置(含数据标识 + 数据内容)
|
||||
const uint8_t *data_value = &data_field[4]; // 数据内容起始位置
|
||||
|
||||
// for (int i = 0; i < data_info_ptr->byte_size; i++)
|
||||
// printf("%02x ", data_value[i]);
|
||||
|
||||
// 判断是否是日期或时间
|
||||
if (item_id == DATE_YMD) {
|
||||
snprintf(parsed_date, sizeof(parsed_date), "20%02x-%02x-%02x", data_value[3] - 0x33, data_value[2] - 0x33, data_value[1] - 0x33);
|
||||
// printf("Parsed date: %s\n", parsed_date);
|
||||
return;
|
||||
} else if (item_id == TIME_HMS) {
|
||||
snprintf(parsed_time, sizeof(parsed_time), "%02x:%02x:%02x", data_value[2] - 0x33, data_value[1] - 0x33, data_value[0] - 0x33);
|
||||
// printf("Parsed time: %s\n", parsed_time);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t bcd = 0;
|
||||
|
||||
for (int i = data_info_ptr->byte_size - 1; i >= 0; i--) {
|
||||
// 解密(减去0x33),反向拼接(低位在前 → 高位在前)
|
||||
bcd |= ((uint32_t)(data_value[i] - 0x33)) << (8 * i);
|
||||
}
|
||||
|
||||
uint32_t value = 0;
|
||||
value = BcdToDecimal(bcd, data_info_ptr->byte_size);
|
||||
|
||||
// 除以10的倍数来处理小数点
|
||||
double final_value = value / pow(10, data_info_ptr->decimal_places);
|
||||
|
||||
// printf("Parsed value: %.*f\n", data_info_ptr->decimal_places, final_value);
|
||||
|
||||
char format[10];
|
||||
snprintf(format, sizeof(format), "%%.%df", data_info_ptr->decimal_places);
|
||||
|
||||
char final_value_str[20];
|
||||
snprintf(final_value_str, sizeof(final_value_str), format, final_value);
|
||||
|
||||
cJSON_AddStringToObject(root, data_id_names[item_id], final_value_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从DTZ178接收数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *ReceiveDataFromDTZ178Task(void *arg) {
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
int fd = PrivOpen("/dev/rs485_dev1", O_RDWR); // 打开设备文件
|
||||
if (fd < 0) { // 打开设备文件失败,打印错误信息
|
||||
printf("open rs485 fd error: %d\n", fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct SerialDataCfg rs485_configuration;
|
||||
memset(&rs485_configuration, 0, sizeof(struct SerialDataCfg));
|
||||
/* 读取RS485配置信息 */
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
int baud_rates_option = CFG->baudRate_Rs485;
|
||||
int data_bits_option = CFG->dataBits_Rs485;
|
||||
int stop_bits_option = CFG->stopBits_Rs485;
|
||||
int parity_option = CFG->parity_Rs485;
|
||||
PrivMutexAbandon(&romConfigurationMutex); // 释放互斥锁
|
||||
switch (baud_rates_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_2400; // 默认波特率为2400
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_4800;
|
||||
break;
|
||||
case 3:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_9600;
|
||||
break;
|
||||
case 4:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_19200;
|
||||
break;
|
||||
case 5:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_38400;
|
||||
break;
|
||||
case 6:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_57600;
|
||||
break;
|
||||
case 7:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_115200;
|
||||
break;
|
||||
case 8:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_230400;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_baud_rate = BAUD_RATE_9600;
|
||||
break;
|
||||
}
|
||||
switch (data_bits_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_9;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_data_bits = DATA_BITS_8;
|
||||
break;
|
||||
}
|
||||
switch (stop_bits_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_2;
|
||||
break;
|
||||
default:
|
||||
rs485_configuration.serial_stop_bits = STOP_BITS_1;
|
||||
break;
|
||||
}
|
||||
switch (parity_option) {
|
||||
case 1:
|
||||
rs485_configuration.serial_parity_mode = PARITY_NONE;
|
||||
break;
|
||||
case 2:
|
||||
rs485_configuration.serial_parity_mode = PARITY_ODD;
|
||||
break;
|
||||
case 3:
|
||||
rs485_configuration.serial_parity_mode = PARITY_EVEN; // 默认校验方式为偶校验
|
||||
break;
|
||||
}
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&rs485_configuration;
|
||||
if (0 != PrivIoctl(fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("ioctl uart fd error %d\n", fd);
|
||||
PrivClose(fd);
|
||||
return NULL;
|
||||
}
|
||||
printf("open rs485 fd success %d\n", fd);
|
||||
|
||||
unsigned char request_frame[MAX_FRAME_SIZE]; // 定义请求帧
|
||||
unsigned char response_frame[MAX_FRAME_SIZE]; // 定义回复帧
|
||||
while (1) {
|
||||
printf("enter cycle\n");
|
||||
struct DataFrame *data_frame_ptr = (struct DataFrame *)PrivMalloc(sizeof(struct DataFrame));
|
||||
memset(data_frame_ptr, 0, sizeof(struct DataFrame));
|
||||
|
||||
// 创建一个空的JSON对象
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
int is_success = 1;
|
||||
|
||||
for (int i = 0; i < DATA_COUNT; i++) {
|
||||
const uint8_t *data_id = data_id_map[i];
|
||||
const DataInfo *data_info = &data_info_map[i];
|
||||
|
||||
memset(request_frame, 0, sizeof(request_frame));
|
||||
if (GenerateRequestFrame(addr_meter, READ_COMMAND, data_id, NULL, 0, request_frame) < 0) {
|
||||
printf("Generate frame failed for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
PrivWrite(fd, request_frame, SEND_FRAME_LEN); // 发送Modbus RTU请求帧
|
||||
|
||||
/* 读取响应帧数据 */
|
||||
memset(response_frame, 0, sizeof(response_frame));
|
||||
if (PrivReadEnoughData(fd, response_frame, TOTAL_RECEIVE_FRAME_LEN + data_info->byte_size) < 0) {
|
||||
printf("Timeout reading response for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("Response frame for index %d: ", i);
|
||||
// for (int j = 0; j < TOTAL_RECEIVE_FRAME_LEN + data_info->byte_size; j++)
|
||||
// printf("%02X ", response_frame[j]);
|
||||
// printf("\n");
|
||||
|
||||
// 校验帧头、帧尾
|
||||
if (response_frame[4] != 0x68 || response_frame[11] != 0x68 || response_frame[TOTAL_RECEIVE_FRAME_LEN + data_info->byte_size - 1] != 0x16) {
|
||||
printf("Invalid frame format for index %d\n", i);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// 校验和
|
||||
uint8_t calc_cs = CheckSum(response_frame + 4, BASE_RECEIVE_FRAME_LEN + data_info->byte_size - 2);
|
||||
uint8_t recv_cs = response_frame[TOTAL_RECEIVE_FRAME_LEN + data_info->byte_size - 2];
|
||||
if (calc_cs != recv_cs) {
|
||||
printf("CheckSum error at index %d: calc %02X, recv %02X\n", i, calc_cs, recv_cs);
|
||||
is_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ParseResponseFrame(response_frame, data_info, i, root);
|
||||
|
||||
PrivTaskDelay(SAMPLE_DATA_INTERVAL_MS);
|
||||
}
|
||||
|
||||
if (!is_success) {
|
||||
printf("read all data failed\n");
|
||||
PrivFree(data_frame_ptr);
|
||||
cJSON_Delete(root);
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf((char *)data_frame_ptr->id, sizeof(data_frame_ptr->id), "%s %s", parsed_date, parsed_time);
|
||||
printf("data_frame_ptr->id: %s\n", data_frame_ptr->id);
|
||||
|
||||
char *json_str = cJSON_Print(root);
|
||||
strncpy((char *)data_frame_ptr->data, json_str, MAX_DATA_SIZE - 1);
|
||||
data_frame_ptr->data[MAX_DATA_SIZE - 1] = '\0'; // 确保结尾是 \0
|
||||
printf("data_frame_ptr->data: %s\n", data_frame_ptr->data);
|
||||
|
||||
// 删除字符串空间
|
||||
free(json_str);
|
||||
// 删除 cJSON 对象
|
||||
cJSON_Delete(root);
|
||||
|
||||
/* 将解析后的数据帧放入循环队列 */
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
OfferBuffer(queue_buffer_ptr, data_frame_ptr); // 将数据帧放入队列
|
||||
printf("receive data from DTZ178, id: %s\n", data_frame_ptr->id); // 打印接收到的数据帧ID
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量,即告知发送数据线程,队列中有新的数据帧
|
||||
|
||||
PrivTaskDelay(RECEIVE_DATA_INTERVAL_MS); // 延迟一段时间再读取下一帧数据
|
||||
|
||||
printf("end cycle\n");
|
||||
}
|
||||
|
||||
PrivClose(fd); // 关闭设备文件
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过4G向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *SendDataToServerTask_4G(void *arg) {
|
||||
uint8_t server_ip_address[16] = {}; // 目的IP地址
|
||||
uint8_t server_port[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receive_buffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_4G_NAME); // 查找4G模块适配器
|
||||
|
||||
AdapterDeviceOpen(adapter); // 打开适配器对应的设备(实际打开串口中断)
|
||||
int baud_rate = BAUD_RATE_115200; // 波特率,用于设置4G模块串口
|
||||
AdapterDeviceControl(adapter, OPE_INT, &baud_rate); // 对适配器对应设备进行配置(实际配置波特率)
|
||||
|
||||
struct DataFrame *data_frame_ptr = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&queue_buffer_ptr->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 如果启用了BLE配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
if (CFG->mqttSwitch_4G == 1) { // 如果使能MQTT
|
||||
AdapterDeviceMqttConnect(adapter, server_ip_address, server_port, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else { // 如果禁用MQTT
|
||||
AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
}
|
||||
|
||||
AdapterDeviceNetstat(adapter); // 读取网络连接状态
|
||||
/* 若连接失败,则等待10s再次尝试连接 */
|
||||
if (CFG->mqttSwitch_4G == 0 && !adapter->network_info.is_connected ||
|
||||
CFG->mqttSwitch_4G == 1 && !adapter->network_info.mqttIsConnected) {
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else // 如果没有启用BLE配置功能
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_4G[0], CFG->destinationIpAddress_4G[1],
|
||||
CFG->destinationIpAddress_4G[2], CFG->destinationIpAddress_4G[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_4G[0] | CFG->destinationPort_4G[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_4G*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnect_count = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnect_count > 0) {
|
||||
int res;
|
||||
if (CFG->mqttSwitch_4G == 1) {
|
||||
res = AdapterDeviceMqttConnect(adapter, mqttServerIp, mqttServerPort, CFG->mqttClientId_4G, CFG->mqttUsername_4G,
|
||||
CFG->mqttPassword_4G);
|
||||
} else {
|
||||
res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
reconnect_count--;
|
||||
}
|
||||
if (reconnect_count <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
printf("4G connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
data_frame_ptr = PollBuffer(queue_buffer_ptr); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
|
||||
int resend_count = RESEND_COUNT; // 定义数据帧重发次数
|
||||
while (data_frame_ptr != NULL && resend_count > 0) { // 只有数据帧非空并且还有剩余重发次数,才进行发送
|
||||
/* 向服务器发送数据 */
|
||||
printf("data_frame_ptr->data: %s", data_frame_ptr->data);
|
||||
printf("send data to server, id: %s\n", data_frame_ptr->id);
|
||||
if (CFG->mqttSwitch_4G == 1) { // MQTT模式下,无需服务器响应数据
|
||||
AdapterDeviceMqttSend(adapter, CFG->mqttTopic_4G, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
break;
|
||||
} else {
|
||||
AdapterDeviceSend(adapter, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
/* 多读取2字节,是为了防止前面还有命令模式返回的剩余的\r\n影响判断 */
|
||||
memset(receive_buffer, 0, sizeof(receive_buffer));
|
||||
int receive_length = AdapterDeviceRecv(adapter, receive_buffer, strlen(data_frame_ptr->id) + 2);
|
||||
if (receive_length == strlen(data_frame_ptr->id) + 2 || receive_length == strlen(data_frame_ptr->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receive_length: %d\n", receive_length);
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < receive_length; i++) {
|
||||
printf("%c", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(receive_buffer, data_frame_ptr->id) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
} else {
|
||||
printf("receive_length: %d\n", receive_length);
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < receive_length; i++) {
|
||||
printf("%d ", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
resend_count--;
|
||||
}
|
||||
if (data_frame_ptr != NULL) {
|
||||
PrivFree(data_frame_ptr); // 释放数据帧内存
|
||||
data_frame_ptr = NULL; // 避免野指针
|
||||
}
|
||||
// AdapterDeviceDisconnect(adapter, NULL); // 关闭适配器对应的设备
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resend_count <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过以太网向服务器发送数据的线程
|
||||
* @param arg 循环队列指针
|
||||
* @return void* 目前返回值无意义
|
||||
*/
|
||||
static void *SendDataToServerTask_Ethernet(void *arg) {
|
||||
uint8_t server_ip_address[16] = {}; // 目的IP地址
|
||||
uint8_t server_port[6] = {}; // 目的端口号
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)arg; // 循环队列指针
|
||||
unsigned char receive_buffer[256]; // 从服务器接收每帧响应的存储空间
|
||||
|
||||
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_ETHERNET_NAME); // 查找以太网模块适配器
|
||||
|
||||
#ifndef BSP_BLE_CONFIG // 如果没有使能蓝牙配置功能
|
||||
AdapterDeviceSetUp(adapter); // 启动以太网主任务线程
|
||||
AdapterDeviceSetDhcp(adapter, CFG->dhcpSwitch_Ethernet); // 启用或禁用DHCP
|
||||
#endif
|
||||
|
||||
struct DataFrame *data_frame_ptr = NULL; // 数据帧定义
|
||||
while (1) {
|
||||
PrivSemaphoreObtainWait(&queue_buffer_ptr->full, NULL); // 尝试获取循环队列队头元素,如果获取信号量失败,则等待信号量
|
||||
#ifdef BSP_BLE_CONFIG // 使能蓝牙配置功能
|
||||
/* 获取互斥锁 */
|
||||
PrivMutexObtain(&adapter->lock); // 若其他线程正在使用adapter,则阻塞等待
|
||||
PrivMutexObtain(&romConfigurationMutex); // 若其他线程正在读取或者写入CFG,则阻塞等待;
|
||||
|
||||
/* 尝试连接服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4);
|
||||
|
||||
/* 连接失败,则等待10s再次尝试连接 */
|
||||
if (res != 0 && res != 0x1D) {
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* 尝试连接到服务器 */
|
||||
sprintf(server_ip_address, "%u.%u.%u.%u", CFG->destinationIpAddress_Ethernet[0], CFG->destinationIpAddress_Ethernet[1],
|
||||
CFG->destinationIpAddress_Ethernet[2], CFG->destinationIpAddress_Ethernet[3]);
|
||||
sprintf(server_port, "%u", (unsigned short)CFG->destinationPort_Ethernet[0] | CFG->destinationPort_Ethernet[1] << 8);
|
||||
printf("-*-*-*-*sendDataToServerTask_Ethernet*-*-*-*\n");
|
||||
printf("server_ip_address:\t%s\n", server_ip_address);
|
||||
printf("server_port:\t\t%s\n", server_port);
|
||||
printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
|
||||
int reconnect_count = RECONNECT_COUNT; // 尝试重新连接服务器最多RECONNECT_COUNT次
|
||||
while (reconnect_count > 0) {
|
||||
int res = AdapterDeviceConnect(adapter, CLIENT, server_ip_address, server_port, IPV4); // 尝试连接服务器
|
||||
if (res == 0 || res == 0x1D) {
|
||||
break;
|
||||
}
|
||||
reconnect_count--;
|
||||
}
|
||||
if (reconnect_count <= 0) { // 若RECONNECT_COUNT次都连接失败,则等待10s再次尝试连接
|
||||
PrivSemaphoreAbandon(&queue_buffer_ptr->full); // 释放信号量
|
||||
printf("Ethernet connect to server failed\n"); // 连接失败,打印错误信息
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PrivMutexObtain(&queue_buffer_ptr->mutex); // 获取互斥锁
|
||||
data_frame_ptr = PollBuffer(queue_buffer_ptr); // 从队列中获取数据帧
|
||||
PrivMutexAbandon(&queue_buffer_ptr->mutex); // 释放互斥锁
|
||||
|
||||
int resend_count = RESEND_COUNT; // 定义数据帧重发次数
|
||||
|
||||
/* 只有数据帧非空并且还有剩余重发次数,才进行发送 */
|
||||
while (data_frame_ptr != NULL && resend_count > 0) {
|
||||
/* 向服务器发送数据 */
|
||||
printf("send data to server, id: %s\n", data_frame_ptr->id);
|
||||
printf("data_frame_ptr->data: %s", data_frame_ptr->data);
|
||||
AdapterDeviceSend(adapter, data_frame_ptr->data,
|
||||
strlen(data_frame_ptr->data)); // 发送数据,注意当前最多发送256字节
|
||||
|
||||
/* 从服务器接收响应,约定服务器接收完数据帧后,返回数据帧中的前12个字节,即数据帧id */
|
||||
memset(receive_buffer, 0, sizeof(receive_buffer));
|
||||
PrivTaskDelay(6000);
|
||||
if (AdapterDeviceRecv(adapter, receive_buffer, strlen(data_frame_ptr->id)) == strlen(data_frame_ptr->id)) {
|
||||
/* 打印服务器响应 */
|
||||
printf("receive_buffer: ");
|
||||
for (int i = 0; i < strlen(receive_buffer); i++) {
|
||||
printf("%c", receive_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
/* 比较服务器响应的内容与发送的数据帧id是否一致 */
|
||||
if (strstr(data_frame_ptr->id, receive_buffer) != NULL) {
|
||||
break; // 接收成功,退出循环
|
||||
}
|
||||
}
|
||||
resend_count--;
|
||||
}
|
||||
if (data_frame_ptr != NULL) {
|
||||
PrivFree(data_frame_ptr); // 释放数据帧内存
|
||||
data_frame_ptr = NULL; // 避免野指针
|
||||
}
|
||||
AdapterDeviceDisconnect(adapter, NULL);
|
||||
#ifdef BSP_BLE_CONFIG
|
||||
/* 释放互斥锁 */
|
||||
PrivMutexAbandon(&romConfigurationMutex);
|
||||
PrivMutexAbandon(&adapter->lock);
|
||||
#endif
|
||||
if (resend_count <= 0) { // 如果数据帧重发次数超过上限,表示发送失败,丢弃该帧
|
||||
PrivTaskDelay(1000 * 10); // 延迟10秒,避免网络拥塞
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开启从DTZ178接收数据的线程以及上传数据到服务器的线程,此方法在main方法中被调用,开机或复位启动
|
||||
*/
|
||||
void StartUpTransformDataTask(void) {
|
||||
/* 分配循环队列空间 */
|
||||
struct QueueBuffer *queue_buffer_ptr = (struct QueueBuffer *)PrivCalloc(1, sizeof(struct QueueBuffer));
|
||||
if (InitBuffer(queue_buffer_ptr) < 0) {
|
||||
PrivFree(queue_buffer_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 启动从DTZ178接收数据的线程 */
|
||||
pthread_attr_t receive_data_from_dtz178_task_attr;
|
||||
pthread_args_t receive_data_from_dtz178_task_args;
|
||||
receive_data_from_dtz178_task_attr.schedparam.sched_priority = 16; // 线程优先级
|
||||
receive_data_from_dtz178_task_attr.stacksize = 2048; // 线程栈大小
|
||||
receive_data_from_dtz178_task_args.pthread_name = "ReceiveDataFromDTZ178Task"; // 线程名字
|
||||
receive_data_from_dtz178_task_args.arg = queue_buffer_ptr; // 线程参数
|
||||
pthread_t receive_data_thread; // 线程ID
|
||||
PrivTaskCreate(&receive_data_thread, &receive_data_from_dtz178_task_attr, ReceiveDataFromDTZ178Task, &receive_data_from_dtz178_task_args);
|
||||
PrivTaskStartup(&receive_data_thread);
|
||||
|
||||
/* 启动上传数据到服务器的线程 */
|
||||
pthread_attr_t send_data_to_server_task_attr;
|
||||
pthread_args_t send_data_to_server_task_args;
|
||||
send_data_to_server_task_attr.schedparam.sched_priority = 16; // 线程优先级
|
||||
send_data_to_server_task_attr.stacksize = 2200; // 线程栈大小
|
||||
send_data_to_server_task_args.pthread_name = "SendDataToServerTask"; // 线程名字
|
||||
send_data_to_server_task_args.arg = queue_buffer_ptr; // 线程参数
|
||||
pthread_t send_data_thread; // 线程ID
|
||||
void *(*start_routine)(void *) = SendDataToServerTask_4G; // 通过4G模块上传到服务器
|
||||
// void *(*start_routine)(void *) = SendDataToServerTask_Ethernet; // 通过以太网模块上传到服务器
|
||||
PrivTaskCreate(&send_data_thread, &send_data_to_server_task_attr, start_routine, &send_data_to_server_task_args); // 通过4G模块上传到服务器
|
||||
PrivTaskStartup(&send_data_thread);
|
||||
}
|
||||
|
|
@ -8,20 +8,6 @@ menu "connection app"
|
|||
menuconfig SOCKET_DEMO
|
||||
bool "Config test socket demo"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Select Ammeter Device Type"
|
||||
default DEVICE_ADL400
|
||||
|
||||
config DEVICE_ADL400
|
||||
bool "CH32V208_ADL400"
|
||||
|
||||
config DEVICE_DTZ178
|
||||
bool "CH32V208_DTZ178"
|
||||
|
||||
config DEVICE_DTSD342
|
||||
bool "CH32V208_DTSD342"
|
||||
endchoice
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -15,10 +15,6 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
SRC_DIR += socket_demo
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CONNECTION_ADAPTER_FREEMODBUSTCP),y)
|
||||
SRC_DIR += freemodbus_tcp_slave
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := tcpserver_sample.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
/*
|
||||
* FreeModbus Libary: Win32 Demo Application
|
||||
* Copyright (C) 2006 Christian Walter <wolti@sil.at>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* File: $Id$
|
||||
*/
|
||||
|
||||
/**********************************************************
|
||||
* Linux TCP support.
|
||||
* Based on Walter's project.
|
||||
* Modified by Steven Guo <gotop167@163.com>
|
||||
***********************************************************/
|
||||
|
||||
/* ----------------------- Standard C Libs includes --------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <transform.h>
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
/* ----------------------- Modbus includes ----------------------------------*/
|
||||
#include "mb.h"
|
||||
#include "mbport.h"
|
||||
|
||||
/* ----------------------- Defines ------------------------------------------*/
|
||||
#define PROG "freemodbus"
|
||||
|
||||
#define REG_INPUT_START 1000
|
||||
#define REG_INPUT_NREGS 4
|
||||
#define REG_HOLDING_START 2000
|
||||
#define REG_HOLDING_NREGS 10
|
||||
|
||||
/* ----------------------- Static variables ---------------------------------*/
|
||||
static USHORT usRegInputStart = REG_INPUT_START;
|
||||
static USHORT usRegInputBuf[REG_INPUT_NREGS];
|
||||
static USHORT usRegHoldingStart = REG_HOLDING_START;
|
||||
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
|
||||
static pthread_mutex_t xLock;
|
||||
static enum ThreadState
|
||||
{
|
||||
STOPPED,
|
||||
RUNNING,
|
||||
SHUTDOWN
|
||||
} ePollThreadState;
|
||||
|
||||
/* ----------------------- Static functions ---------------------------------*/
|
||||
static BOOL bCreatePollingThread( void );
|
||||
static enum ThreadState eGetPollingThreadState( void );
|
||||
static void eSetPollingThreadState( enum ThreadState eNewState );
|
||||
static void* pvPollingThread( void *pvParameter );
|
||||
int LWIPConnectSocket(uint16_t port);
|
||||
|
||||
/* ----------------------- Start implementation -----------------------------*/
|
||||
int MBSlave()
|
||||
{
|
||||
int iExitCode;
|
||||
CHAR cCh;
|
||||
BOOL bDoExit;
|
||||
usRegHoldingBuf[5] = 123;
|
||||
usRegHoldingBuf[7] = 234;
|
||||
|
||||
printf("%s ip %d.%d.%d.%d mask %d.%d.%d.%d gw %d.%d.%d.%d\n", __func__,
|
||||
192, 168, 250, 233,
|
||||
255, 255, 255, 255,
|
||||
192, 168, 250, 1);
|
||||
uint8_t local_ip[4] = {192,168,250,233};
|
||||
uint8_t gateway[4] = {192,168,250,1};
|
||||
uint8_t netmask[4] = {255,255,255,0};
|
||||
lwip_config_tcp(0, local_ip, netmask, gateway);
|
||||
printf("%s LWIPInit done\n", __func__);
|
||||
|
||||
if( eMBTCPInit( MB_TCP_PORT_USE_DEFAULT ) != MB_ENOERR )
|
||||
{
|
||||
fprintf( stderr, "%s: can't initialize modbus stack!\r\n", PROG );
|
||||
iExitCode = EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
eSetPollingThreadState( STOPPED );
|
||||
/* CLI interface. */
|
||||
if( bCreatePollingThread( ) != TRUE )
|
||||
{
|
||||
printf( "Can't start protocol stack! Already running?\r\n" );
|
||||
}
|
||||
}
|
||||
printf("%d %d %s\n",sizeof(usRegHoldingBuf),__LINE__,__func__);
|
||||
|
||||
while(1)
|
||||
{
|
||||
for(int i =0; i<sizeof(usRegHoldingBuf)/2;i++)
|
||||
{
|
||||
printf("poll recv is %3d\n", usRegHoldingBuf[i]);
|
||||
MdelayKTask(100);
|
||||
}
|
||||
}
|
||||
return iExitCode;
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(MBSlave, a Mtcp server Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
BOOL bCreatePollingThread( void )
|
||||
{
|
||||
BOOL bResult;
|
||||
pthread_t xThread;
|
||||
if( eGetPollingThreadState( ) == STOPPED )
|
||||
{
|
||||
if( pthread_create( &xThread, NULL, pvPollingThread, NULL ) != 0 )
|
||||
{
|
||||
/* Can't create the polling thread. */
|
||||
bResult = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bResult = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bResult = FALSE;
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
void* pvPollingThread( void *pvParameter )
|
||||
{
|
||||
eSetPollingThreadState( RUNNING );
|
||||
|
||||
if( eMBEnable( ) == MB_ENOERR )
|
||||
{
|
||||
do
|
||||
{
|
||||
if( eMBPoll( ) != MB_ENOERR )
|
||||
break;
|
||||
}
|
||||
while( eGetPollingThreadState( ) != SHUTDOWN );
|
||||
}
|
||||
|
||||
( void )eMBDisable( );
|
||||
|
||||
eSetPollingThreadState( STOPPED );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum ThreadState eGetPollingThreadState( )
|
||||
{
|
||||
enum ThreadState eCurState;
|
||||
|
||||
( void )pthread_mutex_lock( &xLock );
|
||||
eCurState = ePollThreadState;
|
||||
( void )pthread_mutex_unlock( &xLock );
|
||||
|
||||
return eCurState;
|
||||
}
|
||||
|
||||
void eSetPollingThreadState( enum ThreadState eNewState )
|
||||
{
|
||||
( void )pthread_mutex_lock( &xLock );
|
||||
ePollThreadState = eNewState;
|
||||
( void )pthread_mutex_unlock( &xLock );
|
||||
}
|
||||
|
||||
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
||||
{
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
int iRegIndex;
|
||||
|
||||
if( ( usAddress >= REG_INPUT_START )
|
||||
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
|
||||
{
|
||||
iRegIndex = ( int )( usAddress - usRegInputStart );
|
||||
while( usNRegs > 0 )
|
||||
{
|
||||
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
|
||||
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
|
||||
iRegIndex++;
|
||||
usNRegs--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eStatus = MB_ENOREG;
|
||||
}
|
||||
|
||||
return eStatus;
|
||||
}
|
||||
|
||||
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
|
||||
{
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
int iRegIndex;
|
||||
|
||||
if( ( usAddress >= REG_HOLDING_START ) &&
|
||||
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
|
||||
{
|
||||
iRegIndex = ( int )( usAddress - usRegHoldingStart );
|
||||
switch ( eMode )
|
||||
{
|
||||
/* Pass current register values to the protocol stack. */
|
||||
case MB_REG_READ:
|
||||
while( usNRegs > 0 )
|
||||
{
|
||||
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 );
|
||||
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF );
|
||||
iRegIndex++;
|
||||
usNRegs--;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Update current register values with new values from the
|
||||
* protocol stack. */
|
||||
case MB_REG_WRITE:
|
||||
while( usNRegs > 0 )
|
||||
{
|
||||
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
|
||||
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
|
||||
iRegIndex++;
|
||||
usNRegs--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eStatus = MB_ENOREG;
|
||||
}
|
||||
return eStatus;
|
||||
}
|
||||
|
||||
|
||||
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
|
||||
{
|
||||
return MB_ENOREG;
|
||||
}
|
||||
|
||||
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
||||
{
|
||||
return MB_ENOREG;
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence panasonic fatek ab abb koyo
|
||||
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := ab_l30erm.c ab_micro850.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
# AB_850通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 通信接线及参数设置
|
||||
|
||||
* 网口
|
||||
|
||||
*Mosbus TCP协议,IP:192.168.250.56,Port:502
|
||||
|
||||
## 存储区
|
||||
|
||||
- 存储区D区
|
||||
|
||||
## JSON配方设计
|
||||
|
||||
* AB_850类型PLC需要配置控制器映射
|
||||
|
||||

|
||||
|
||||
* 共测试Word和real共2种类型数据,real型数据有2个Word组成,以下为JSON文件解释。
|
||||
|
||||
- ```json
|
||||
{
|
||||
"device_id": 1, //设备ID默认是1,此参数无效
|
||||
"device_name": "AB_850", //设备名称,自定义
|
||||
"communication_type": 0, //通讯协议类型 0是以太网,1是串口
|
||||
"socket_config": { //以太网配置
|
||||
"plc_ip": "192.168.250.56", //PLC的IP地址
|
||||
"local_ip": "192.168.250.233", //矽达通IP地址设定
|
||||
"gateway": "192.168.250.1", //矽达通的网关地址设定
|
||||
"netmask": "255.255.255.0", //矽达通子网掩码设定
|
||||
"port":502 //端口号设定
|
||||
},
|
||||
"protocol_type": 2, //通讯协议,2代表modbus-tcp协议
|
||||
"read_period": 100, //交互周期ms
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "CON_DATA[0]", //变量名称,自定义
|
||||
"value_type": 1, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 1, //功能码。1是读线圈
|
||||
"start_address": 0, //起始地址
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "CON_DATA[1]", //变量名称,自定义
|
||||
"value_type": 1, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 1, //功能码。1是读
|
||||
"start_address": 1, //起始地址偏移1位106*8+1=849
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "CON_INT", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 2, //起始地址偏移2位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "CON_ARRAY[0]_1", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 3, //起始地址偏移3位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "CON_ARRAY[0]_2", //变量名称,自定义,CON_ARRAY[0]_1和CON_ARRAY[0]_2组成real型数据
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 4, //起始地址偏移4位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 通信测试
|
||||
|
||||
(1) 新增1个通信demo,命名为ab_micro850.c;
|
||||
|
||||
(2) 复制modbus_tcp样例代码程序到ab_micro850.c文件中;
|
||||
|
||||
(3) void **ControlAB850Test**(void) 更改函数名;
|
||||
|
||||
(4) PRIV_SHELL_CMD_FUNCTION(**ControlAB850Test**, AB Plc micro850 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||
|
||||
(5) 剪裁配置完成后,用过烧写器下载至矽数通中,重启后完成测试。
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# AB_L30ERM通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 通信接线及参数设置
|
||||
|
||||
* 网口
|
||||
|
||||
*Ethernet/ip协议,IP:192.168.250.57,Port:44818
|
||||
|
||||
## 存储区
|
||||
|
||||
- Ethernet/ip协议是根据变量名称搜索寄存器地址
|
||||
|
||||
## JSON配方设计
|
||||
|
||||
* 本实例共测试Word和real共2种类型数据,以下为JSON文件解释。
|
||||
|
||||
- ```json
|
||||
{
|
||||
"device_id": “ab_l30”, //
|
||||
"device_name": "robot", //设备名称,自定义
|
||||
"communication_type": 0, //通讯协议类型 0是以太网,1是串口
|
||||
"socket_config": { //以太网配置
|
||||
"plc_ip": "192.168.250.37", //PLC的IP地址
|
||||
"local_ip": "192.168.250.123", //矽达通IP地址设定
|
||||
"gateway": "192.168.250.1", //矽达通的网关地址设定
|
||||
"netmask": "255.255.255.0", //矽达通子网掩码设定
|
||||
"port":502 //端口号设定
|
||||
},
|
||||
"protocol_type": 12, //通讯协议,12代表ethernet/ip协议
|
||||
"read_period": 100, //交互周期ms
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "L30_SPEED", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"wordlen": "WORD", //以WORD方式传输
|
||||
"amount": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "L30_TORQUE", //变量名称,自定义
|
||||
"value_type": 9, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"wordlen": 2, //以WORD方式传输
|
||||
"amount": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "D", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"wordlen": 3, //以WORD方式传输
|
||||
"amount": 1 //默认是1,代表读取1个数据类型长度
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 通信测试
|
||||
|
||||
(1) 新增1个通信demo,命名为ab_l30erm.c;
|
||||
|
||||
(2) 复制modbus_tcp样例代码程序到ab_l30erm.c文件中;
|
||||
|
||||
(3) void **ControlABL30Test**(void) 更改函数名;
|
||||
|
||||
(4) PRIV_SHELL_CMD_FUNCTION(**ControlABL30Test**, AB Plc l30ermDemo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||
|
||||
(5) 剪裁配置完成后,用过烧写器下载至矽数通中,重启后完成测试。
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ab_l30.c
|
||||
* @brief PLC ABB L30 app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.8.27
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlABL30Test(void)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t read_data_length = 0;
|
||||
uint8_t read_data[1024] = {0};
|
||||
ControlProtocolType CIP_protocol = ControlProtocolFind();
|
||||
if (NULL == CIP_protocol) {
|
||||
printf("%s get CIP protocol %p failed\n", __func__, CIP_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get CIP protocol %p successfull\n", __func__, CIP_protocol);
|
||||
if (CONTROL_REGISTERED == CIP_protocol->protocol_status) {
|
||||
ControlProtocolOpen(CIP_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(CIP_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] CIP data %d using receipe file\n", __func__, i, read_data_length);
|
||||
i++;
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(CIP_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlABL30Test, Ab Plc CIP Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ab_micro850.c
|
||||
* @brief PLC AB MICRO850 app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.10.5
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlAB850Test(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
//ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlAB850Test, AB Plc MICRO850 Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 2.6 MiB |
|
Before Width: | Height: | Size: 14 KiB |
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"device_id": "ab_l30",
|
||||
"device_name": "robot",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.57",
|
||||
"local_ip": "192.168.250.123",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"port": 44818
|
||||
},
|
||||
"protocol_type": 12,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "L30_SPEED",
|
||||
"value_type": 3,
|
||||
"wordlen": "WORD",
|
||||
"amount": 1
|
||||
},
|
||||
{
|
||||
"value_name": "L30_TORQUE",
|
||||
"value_type": 9,
|
||||
"wordlen": "WORD",
|
||||
"amount": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D",
|
||||
"value_type": 3,
|
||||
"wordlen": "WORD",
|
||||
"amount": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "AB_850",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.32",
|
||||
"local_ip": "192.168.250.56",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "D106.0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 848,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D106.1",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":849,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D100",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 100,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D102",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 102,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D103",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 103,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := abb_pm5630.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
# ABB通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 通信接线及参数设置
|
||||
|
||||
* 网口
|
||||
|
||||
*Mosbus TCP协议,IP:192.168.250.58,Port:502
|
||||
|
||||
## 存储区
|
||||
|
||||
- 存储区MW区
|
||||
|
||||
## JSON配方设计
|
||||
|
||||
* 共测试Word和real共2种类型数据,real型数据有2个Word组成,以下为JSON文件解释。
|
||||
|
||||
- ```json
|
||||
{
|
||||
"device_id": 1, //设备ID默认是1,此参数无效
|
||||
"device_name": "ABB_PM5630", //设备名称,自定义
|
||||
"communication_type": 0, //通讯协议类型 0是以太网,1是串口
|
||||
"socket_config": { //以太网配置
|
||||
"plc_ip": "192.168.250.58", //PLC的IP地址
|
||||
"local_ip": "192.168.250.233", //矽达通IP地址设定
|
||||
"gateway": "192.168.250.1", //矽达通的网关地址设定
|
||||
"netmask": "255.255.255.0", //矽达通子网掩码设定
|
||||
"port":502 //端口号设定
|
||||
},
|
||||
"protocol_type": 2, //通讯协议,2代表modbus-tcp协议
|
||||
"read_period": 100, //交互周期ms
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "MW0", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 0, //起始地址
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "MW1", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 1, //起始地址偏移1位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "MW10", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 10, //起始地址偏移10位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "MD20_1", //变量名称,自定义
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 20, //起始地址偏移20位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
},
|
||||
{
|
||||
"value_name": "MD20_2", //变量名称,自定义,MD20_1和MD20_2组成real型数据
|
||||
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||
"function_code": 3, //功能码。3是读
|
||||
"start_address": 21, //起始地址偏移21位
|
||||
"data_length": 1 //默认是1,代表读取1个数据类型长度
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 通信测试
|
||||
|
||||
(1) 新增1个通信demo,命名为abb_pm5630.c;
|
||||
|
||||
(2) 复制modbus_tcp样例代码程序到abb_pm5630.c文件中;
|
||||
|
||||
(3) void **ControlABBPM5630Test**(void) 更改函数名;
|
||||
|
||||
(4) PRIV_SHELL_CMD_FUNCTION(**ControlABBPM5630Test**, ABB Plc PM5630 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||
|
||||
(5) 剪裁配置完成后,用过烧写器下载至矽数通中,重启后完成测试。
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file abb_pm5630.c
|
||||
* @brief PLC ABB pm5630 app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.10.20
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlABBPM5630Test(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
//ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlABBPM5630Test, ABB Plc PM5630 Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
Before Width: | Height: | Size: 2.7 MiB |
|
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "ABB_PM5630",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.32",
|
||||
"local_ip": "192.168.250.58",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "MW0",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "MW1",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address":1,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "MW10",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 10,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "MD20_1",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address":20,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "MD20_2",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address":21,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.0 MiB |
|
|
@ -1,48 +1,22 @@
|
|||
# 台达 PLC与矽达通ARM通信测试
|
||||
# 台达 DVP通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 台达DVP与矽达通ARM通信处测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
## 通信接线及参数设置
|
||||
|
||||
* 网口
|
||||
* 通过自带 RJ45 网口连接
|
||||
* 网口参数:IP:192.168.250.27 Port:502
|
||||
* 测试的协议:Modbus TCP
|
||||
|
||||
### 存储区
|
||||
## 存储区
|
||||
|
||||
- 含M,D,X,Y。台达PLC中 各存储区地址和Modbus地址有明确的对应表,详见台达DVP协议解析测试文档。
|
||||
|
||||
### 通信测试
|
||||
## 通信测试
|
||||
|
||||
- 共测试BOOL,INT16,INT32,FLOAT 共四种类型数据。
|
||||
- 测试D区,M区和Y区。
|
||||
|
||||
|
||||
|
||||
## 台达AS332T与矽达通ARM通信处测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
|
||||
* 网口
|
||||
* 通过自带 RJ45 网口连接
|
||||
* 网口参数:IP:192.168.250.5 Port:502
|
||||
* 测试的协议:Modbus TCP
|
||||
|
||||
### 存储区
|
||||
|
||||
- 含M,D,X,Y。台达PLC中 各存储区地址和Modbus地址有明确的对应表,详见台达AS332T协议解析测试文档。
|
||||
|
||||
### 通信测试结果
|
||||
|
||||
- 共测试BOOL,INT16,INT32,FLOAT 共四种类型数据。
|
||||
- 测试D区,M区和Y区。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
|
|
@ -17,53 +15,9 @@
|
|||
* @brief PLC DELTA AS332T app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.10.10
|
||||
* @date 2022.9.27
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlDeltaas332tTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlDeltaas332tTest, Delta as332t Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
|
@ -1,79 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "DELTA_AS332T_TCP",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.5",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 1000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M16",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 16,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M17",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 17,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M18",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 30,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D300",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 300,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D301",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 302,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D302",
|
||||
"value_type": 4,
|
||||
"function_code": 3,
|
||||
"start_address": 302,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D304",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 304,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "Y1.0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 40976,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "Y10",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 40970,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := fatek_fbs_24mc_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# 永宏通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 永宏FBs-24MCT2-AC通信测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
|
||||
* 网口和串口
|
||||
* FBS-24MCT2自带圆口232,用于程序的下载。
|
||||
* 可本体拓展FBs-CBES用于Modbus TCP,永宏私有协议永宏协议等通信。板卡默认IP:192.168.2.3.端口号500,永宏协议
|
||||
* 通过本体拓展FBs-CM22通信模板,可用于Modbus RTU及永宏协议通信。串口接线:+接485A;-接485B。
|
||||
* 串口模块MODBUS RTU通信参数配置:通信速率:9600;数据位:8bit;停止位:1bit;校验:偶校验
|
||||
* 串口模块永宏协议通信参数配置:通信速率:9600;数据位:8bit;停止位:1bit;校验:偶校验
|
||||
* 终端与PLC通信测试,PC编程软件与PLC不能处于联机状态。
|
||||
|
||||
|
||||
### 存储区
|
||||
|
||||
- 存储区 X,Y,R,D区等。
|
||||
|
||||
### 通信测试
|
||||
|
||||
- 共测试BOOL,INT16等类型数据。
|
||||
|
||||
|
||||
- 测试Y区,R区及D区数据。
|
||||
|
||||
|
||||
- 测试截图:
|
||||
|
||||
测试PLC环境搭建:
|
||||
|
||||

|
||||
|
||||
解析完成的配方为:
|
||||
|
||||

|
||||
|
||||
测试结果:
|
||||
|
||||

|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fatek_fbs_24mc_uart.c
|
||||
* @brief PLC fatek fbs app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.11.28
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlFatekFBsUartTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType modbus_rtu_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_rtu_protocol) {
|
||||
printf("%s get modbus rtu protocol %p failed\n", __func__, modbus_rtu_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get modbus rtu protocol %p successfull\n", __func__, modbus_rtu_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_rtu_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_rtu_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_rtu_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus rtu data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(modbus_rtu_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlFatekFBsUartTest, fatek fbs uart Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 172 KiB |
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "FATEK_FBSMC24T_RTU",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 9600,
|
||||
"data_bits": 8,
|
||||
"stop_bits": 1,
|
||||
"check_mode":3
|
||||
},
|
||||
"protocol_type": 3,
|
||||
"read_period": 2000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "Y0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D0",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 6000,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R10",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 10,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 3.1 MiB |
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c inovance_am401_cpu1608tn_uart.c inovance_H3U_cpu3232MT_ethernet.c
|
||||
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c inovance_am401_cpu1608tn_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
Before Width: | Height: | Size: 200 KiB |
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file inovance_H3U_cpu3232MT_ethernet.c
|
||||
* @brief PLC Inovance H3U-3232MT app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024.08.06
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlInovanceH3UCPU3232MTTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
// ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlInovanceH3UCPU3232MTTest, Inovance PLC N3UCPU3232MT Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "Ino_H3U3232MT",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.55",
|
||||
"local_ip": "192.168.250.147",
|
||||
"gateway": "192.168.250.252",
|
||||
"netmask": "255.255.255.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 300,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M8000",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8000,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D120",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 120,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := koyo_nk1cpu40.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
Before Width: | Height: | Size: 1.7 MiB |
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file koyo_nk1cpu40.c
|
||||
* @brief PLC AB MICRO850 app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024.07.03
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlKoyoNK1CPU40Test(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
// ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlKoyoNK1CPU40Test, Koyo Plc NK1CPU40 Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := mitsubishi_fx3u.c mitsubishi_fx5u.c mitsubishi_fx2n.c mitsubishi_q02u.c mitsubishi_q06h.c mitsubishi_q03udv.c
|
||||
SRC_FILES := mitsubishi_fx3u.c mitsubishi_fx5u.c mitsubishi_fx2n.c mitsubishi_q02u.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
|||
|
|
@ -1,88 +1,24 @@
|
|||
# 三菱通信测试
|
||||
# 三菱 FX2N通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 三菱FX2N通信测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
## 通信接线及参数设置
|
||||
|
||||
* 串口
|
||||
* FX2N自带8针圆口422,用于程序的下载。全系列不支持网口,且需购买串口拓展模块FX2N-485-BD用于通信测试。
|
||||
* 接线:RDA和SDA短接,引出A;RDB与SDB短接,引出B。
|
||||
* 串口模块支持MC-1C协议,通信速率:9600;数据位:7bit;停止位:1bit;校验:偶校验
|
||||
|
||||
### 存储区
|
||||
## 存储区
|
||||
|
||||
- 存储区 I,Q,M,D区。
|
||||
|
||||
### 通信测试
|
||||
## 通信测试
|
||||
|
||||
- 共测试BOOL,INT16,FLOAT共三种类型数据。
|
||||
|
||||
|
||||
- 测试M区及D区数据。
|
||||
|
||||
## 三菱Q06H通信测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
|
||||
* 接口
|
||||
* 首次连接时,可通过CPU自带的串口(打印机方口线)进行程序的下载。
|
||||
* 本次测试通过Q06H拓展的模块QJ71E71_100模块的网口模块进行MC—3E通信测试。
|
||||
* PLC网口模块IP:192.168.250.21 端口号:4000
|
||||
|
||||
### 存储区
|
||||
|
||||
- 存储区 I,Q,M,D区。
|
||||
|
||||
### 通信测试
|
||||
|
||||
- 共测试BOOL,INT16,FLOAT共三种类型数据。
|
||||
|
||||
|
||||
- 测试M区及D区数据。
|
||||
|
||||
- 测试截图:
|
||||
|
||||
解析完成的配方为
|
||||
|
||||

|
||||
|
||||
测试结果:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 三菱Q03UDV通信测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
|
||||
* 接口
|
||||
* 本次测试通过Q03UDV拓展的模块QJ71E71_100模块的网口模块进行MC—3E通信测试。网口模块IP:192.168.250.21 端口号:4000
|
||||
* 本次测试还可通过Q03UDV自身网口进行MC—3E通信测试。网口模块IP:192.168.250.22 端口号:6000
|
||||
|
||||
### 存储区
|
||||
|
||||
- 存储区 I,Q,M,D区。
|
||||
|
||||
### 通信测试
|
||||
|
||||
- 共测试BOOL,INT16,FLOAT共三种类型数据。
|
||||
|
||||
|
||||
- 测试M区及D区数据。
|
||||
|
||||
- 测试截图:
|
||||
|
||||
扩展模块解析完成的配方为
|
||||
|
||||

|
||||
|
||||
CPU自带网口解析完成的配方为
|
||||
|
||||

|
||||
|
||||
测试结果:
|
||||
|
||||

|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.8 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
|
@ -1,368 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "FX3U_MC_1E",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.25",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 2000
|
||||
},
|
||||
"protocol_type": 6,
|
||||
"read_period": 2000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "使能",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "回零",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "急停",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "正限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "负限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "6",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动运行中",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "20",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "故障",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "21",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "待机",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "22",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "手动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "23",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "24",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "运行方向",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "25",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "复位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "26",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "备用1",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "27",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "产量",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型1",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型2",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型3",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型4",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型5",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型6",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "50",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型7",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "51",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型8",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "52",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型9",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "53",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "200",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "加速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "202",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "减速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "204",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "起始位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "206",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "终点位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "208",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "张力值",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "300",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型1",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "302",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型2",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "304",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型3",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "306",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型4",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "308",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y001",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y002",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y010",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "10",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "D400",
|
||||
"value_type": 4,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "400",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
{
|
||||
"device_id": 769,
|
||||
"device_name": "Q02UCPU",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 0,
|
||||
"baud_rate": 19200,
|
||||
"data_bits": 7,
|
||||
"stop_bits": 1,
|
||||
"check_mode": 3
|
||||
},
|
||||
"protocol_type": 10,
|
||||
"read_period": 1000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "使能",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "回零",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "急停",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "正限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "负限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "6",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动运行中",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "20",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "故障",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "21",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "待机",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "22",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "手动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "23",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "24",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "运行方向",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "25",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "复位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "26",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "备用1",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "27",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "产量",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型1",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型2",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型3",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型4",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型5",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型6",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "50",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型7",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "51",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型8",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "52",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型9",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "53",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "200",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "加速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "202",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "减速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "204",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "起始位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "206",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "终点位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "208",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "张力值",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "300",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型1",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "302",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型2",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "304",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型3",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "306",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型4",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "308",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,494 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "Q02UCPU_MC_3E",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.21",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 4000
|
||||
},
|
||||
"protocol_type": 7,
|
||||
"read_period": 2000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "使能",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "回零",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "急停",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "正限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "负限位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "6",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动运行中",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "20",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "故障",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "21",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "待机",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "22",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "手动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "23",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "自动模式",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "24",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "运行方向",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "25",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "复位",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "26",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "备用1",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "27",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "产量",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型1",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型2",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型3",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "3",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型4",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型5",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "5",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型6",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "50",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型7",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "51",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型8",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "52",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "整型9",
|
||||
"value_type": 3,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "53",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "200",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "加速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "202",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "减速度",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "204",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "起始位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "206",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "终点位置",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "208",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "张力值",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "300",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型1",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "302",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型2",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "304",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型3",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "306",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "浮点型4",
|
||||
"value_type": 9,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "308",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y001",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y002",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "Y010",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "10",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "D400",
|
||||
"value_type": 4,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "400",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "D402",
|
||||
"value_type": 8,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "402",
|
||||
"device_points_count": 4,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "D406",
|
||||
"value_type": 8,
|
||||
"device_code": "D",
|
||||
"head_device_number_string": "406",
|
||||
"device_points_count": 4,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "B1",
|
||||
"value_type": 1,
|
||||
"device_code": "B",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "B10",
|
||||
"value_type": 1,
|
||||
"device_code": "B",
|
||||
"head_device_number_string": "10",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "B20",
|
||||
"value_type": 1,
|
||||
"device_code": "B",
|
||||
"head_device_number_string": "20",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "W1",
|
||||
"value_type": 3,
|
||||
"device_code": "W",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "W2",
|
||||
"value_type": 4,
|
||||
"device_code": "W",
|
||||
"head_device_number_string": "2",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "W4",
|
||||
"value_type": 9,
|
||||
"device_code": "W",
|
||||
"head_device_number_string": "4",
|
||||
"device_points_count": 2,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "W6",
|
||||
"value_type": 8,
|
||||
"device_code": "W",
|
||||
"head_device_number_string": "6",
|
||||
"device_points_count": 4,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "W22",
|
||||
"value_type": 3,
|
||||
"device_code": "W",
|
||||
"head_device_number_string": "22",
|
||||
"device_points_count": 1,
|
||||
"command_type": 1,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "B44",
|
||||
"value_type": 1,
|
||||
"device_code": "B",
|
||||
"head_device_number_string": "44",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 500
|
||||
},
|
||||
{
|
||||
"value_name": "B200",
|
||||
"value_type": 1,
|
||||
"device_code": "B",
|
||||
"head_device_number_string": "200",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 500
|
||||
},
|
||||
{
|
||||
"value_name": "Y100",
|
||||
"value_type": 1,
|
||||
"device_code": "Y",
|
||||
"head_device_number_string": "100",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 500
|
||||
},
|
||||
{
|
||||
"value_name": "X150",
|
||||
"value_type": 1,
|
||||
"device_code": "X",
|
||||
"head_device_number_string": "150",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 500
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mitsubishi_q03udv.c
|
||||
* @brief PLC MITSUBISHI Q03udv app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.10.30
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlQ03udvTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType melsec_3e_protocol = ControlProtocolFind();
|
||||
if (NULL == melsec_3e_protocol) {
|
||||
printf("%s get melsec 3e protocol %p failed\n", __func__, melsec_3e_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get melsec 3e protocol %p successfull\n", __func__, melsec_3e_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == melsec_3e_protocol->protocol_status) {
|
||||
ControlProtocolOpen(melsec_3e_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(melsec_3e_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] melsec 3c data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(melsec_3c_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlQ03udvTest, Mitsubishi Q03udv Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mitsubishi_q06h.c
|
||||
* @brief PLC MITSUBISHI Q06H app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.10.30
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlQ06hTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType melsec_3e_protocol = ControlProtocolFind();
|
||||
if (NULL == melsec_3e_protocol) {
|
||||
printf("%s get melsec 3e protocol %p failed\n", __func__, melsec_3e_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get melsec 3e protocol %p successfull\n", __func__, melsec_3e_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == melsec_3e_protocol->protocol_status) {
|
||||
ControlProtocolOpen(melsec_3e_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(melsec_3e_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] melsec 3c data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(melsec_3c_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlQ06hTest, Mitsubishi Q06H Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "NJ501",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.22",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"port": 9600
|
||||
},
|
||||
"protocol_type": 5,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
|
||||
{
|
||||
"value_name": "整型1",
|
||||
"value_type": 3,
|
||||
"area_char": "D",
|
||||
"data_type": 1,
|
||||
"start_address": 100,
|
||||
"bit_address": 0,
|
||||
"data_length": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -18,34 +18,6 @@
|
|||
* @date 2022.9.27
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void ControlNj501Test(void)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t read_data_length = 0;
|
||||
uint8_t read_data[1024] = {0};
|
||||
ControlProtocolType fins_protocol = ControlProtocolFind();
|
||||
if (NULL == fins_protocol) {
|
||||
printf("%s get fins protocol %p failed\n", __func__, fins_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get fins protocol %p successfull\n", __func__, fins_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == fins_protocol->protocol_status) {
|
||||
ControlProtocolOpen(fins_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(fins_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] fins data %d using receipe file\n", __func__, i, read_data_length);
|
||||
i++;
|
||||
PrivTaskDelay(100000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(fins_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlNj501Test, Omron Plc FINS Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := panasonic_fpxh_tcp.c panasonic_fpxh_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# 松下通信测试
|
||||
|
||||
[TOC]
|
||||
|
||||
## 松下FPXHC40ET通信测试
|
||||
|
||||
### 通信接线及参数设置
|
||||
|
||||
* 网口和串口
|
||||
* FPXHC40ET自带miniUSB,用于程序的下载。本体自带的串口为RS232。
|
||||
* 本体自带的网口可用于Modbus TCP,Ethernet/IP等通信。目前用于Modbus TCP通信测试,网口IP:192.168.250.51 Port:502
|
||||
* 通过本体拓展FPXH-COM3通信模板,可用于Modbus RTU通信。串口接线:S+接485A;S-接485B。
|
||||
* 串口模块通信参数配置:通信速率:115200;数据位:8bit;停止位:1bit;校验:偶校验
|
||||
|
||||
### 存储区
|
||||
|
||||
- 存储区 X,Y,R,D,L区等。
|
||||
|
||||
### 通信测试
|
||||
|
||||
- 共测试BOOL,INT16等类型数据。
|
||||
|
||||
|
||||
- 测试Y区,R区及DT区数据。
|
||||
|
||||
|
||||
- 测试截图:
|
||||
|
||||
测试PLC环境搭建:
|
||||
|
||||

|
||||
|
||||
解析完成的配方为:
|
||||
|
||||

|
||||
|
||||
测试结果:
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "PANASONIC_FPXH_TCP",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.51",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 1000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "Y0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":2048,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R100",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 2208,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R101",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 2209,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT0",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT1",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 1,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT200",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 200,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "PANASONIC_FPXH_RTU",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 9600,
|
||||
"data_bits": 8,
|
||||
"stop_bits": 1,
|
||||
"check_mode":3
|
||||
},
|
||||
"protocol_type": 3,
|
||||
"read_period": 2000,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "Y0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":2048,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R100",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 2208,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "R101",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 2209,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT0",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 0,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT1",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 1,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "DT200",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 200,
|
||||
"quantity": 1
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||