tcp2rtu.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <termios.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/epoll.h>
  9. #include <arpa/inet.h>
  10. #include <linux/serial.h>
  11. #define MAX_EVENTS 10
  12. #define QUEUE_SIZE 256
  13. typedef struct
  14. {
  15. unsigned short transaction_id;
  16. unsigned char unit_id;
  17. unsigned char function_code;
  18. unsigned short address;
  19. unsigned short quantity;
  20. } TransactionEntry;
  21. typedef struct
  22. {
  23. TransactionEntry entries[QUEUE_SIZE];
  24. int front;
  25. int rear;
  26. int count;
  27. } TransactionQueue;
  28. void initQueue(TransactionQueue* queue)
  29. {
  30. queue->front = 0;
  31. queue->rear = 0;
  32. queue->count = 0;
  33. }
  34. int isQueueEmpty(TransactionQueue* queue)
  35. {
  36. return queue->count == 0;
  37. }
  38. int isQueueFull(TransactionQueue* queue)
  39. {
  40. return queue->count == QUEUE_SIZE;
  41. }
  42. void enqueue(TransactionQueue* queue,TransactionEntry entry)
  43. {
  44. if(!isQueueFull(queue))
  45. {
  46. queue->entries[queue->rear] = entry;
  47. queue->rear = (queue->rear + 1) % QUEUE_SIZE;
  48. queue->count++;
  49. }
  50. else
  51. {
  52. fprintf(stderr,"Transaction queue is full!\n");
  53. }
  54. }
  55. TransactionEntry dequeue(TransactionQueue* queue,unsigned char unit_id,unsigned char function_code,unsigned short address,unsigned short quantity,int compare_address,int compare_quantity)
  56. {
  57. TransactionEntry entry = { 0, 0, 0, 0, 0 };
  58. if(!isQueueEmpty(queue))
  59. {
  60. for(int i = queue->front; i != queue->rear; i = (i + 1) % QUEUE_SIZE)
  61. {
  62. if(queue->entries[i].unit_id == unit_id &&
  63. queue->entries[i].function_code == function_code &&
  64. (!compare_address || (queue->entries[i].address == address)) &&
  65. (!compare_quantity || (queue->entries[i].quantity == quantity)))
  66. {
  67. entry = queue->entries[i];
  68. queue->front = (i + 1) % QUEUE_SIZE;
  69. queue->count--;
  70. break;
  71. }
  72. }
  73. }
  74. else
  75. {
  76. fprintf(stderr,"Transaction queue is empty!\n");
  77. }
  78. return entry;
  79. }
  80. unsigned short crc16(const unsigned char* buf,int len)
  81. {
  82. unsigned short crc = 0xFFFF;
  83. for(int pos = 0; pos < len; pos++)
  84. {
  85. crc ^= (unsigned short)buf[pos];
  86. for(int i = 8; i != 0; i--)
  87. {
  88. if((crc & 1) != 0)
  89. {
  90. crc >>= 1;
  91. crc ^= 0xA001;
  92. }
  93. else
  94. {
  95. crc >>= 1;
  96. }
  97. }
  98. }
  99. return crc;
  100. }
  101. void configure_serial_port(int fd,int baud_rate)
  102. {
  103. struct termios options;
  104. tcgetattr(fd,&options);
  105. cfsetispeed(&options,baud_rate);
  106. cfsetospeed(&options,baud_rate);
  107. options.c_cflag |= (CLOCAL | CREAD);
  108. options.c_cflag &= ~CSIZE;
  109. options.c_cflag |= CS8;
  110. options.c_cflag &= ~PARENB;
  111. options.c_cflag &= ~CSTOPB;
  112. options.c_cflag &= ~CRTSCTS;
  113. options.c_iflag &= ~(IXON | IXOFF | IXANY);
  114. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  115. options.c_oflag &= ~OPOST;
  116. tcsetattr(fd,TCSANOW,&options);
  117. }
  118. void configure_rs485_mode(int fd)
  119. {
  120. struct serial_rs485 rs485conf;
  121. memset(&rs485conf,0,sizeof(rs485conf));
  122. /* Enable RS485 mode: */
  123. rs485conf.flags |= SER_RS485_ENABLED;
  124. /* Set logical level for RTS pin equal to 1 when sending: */
  125. rs485conf.flags |= SER_RS485_RTS_ON_SEND;
  126. /* Set logical level for RTS pin equal to 0 after sending: */
  127. rs485conf.flags &= ~SER_RS485_RTS_AFTER_SEND;
  128. /* Set this flag if you want to receive data even whilst sending data */
  129. rs485conf.flags &= ~SER_RS485_RX_DURING_TX;
  130. /* Set rts delay before send, if needed: */
  131. rs485conf.delay_rts_before_send = 0; // in miliseconds
  132. /* Set rts delay after send, if needed: */
  133. rs485conf.delay_rts_after_send = 0; // in miliseconds
  134. if(ioctl(fd,TIOCSRS485,&rs485conf) < 0)
  135. {
  136. perror("ERROR setting RS-485 mode");
  137. exit(1);
  138. }
  139. }
  140. int get_baud_rate(int baud_rate)
  141. {
  142. switch(baud_rate)
  143. {
  144. case 1200: return B1200;
  145. case 2400: return B2400;
  146. case 4800: return B4800;
  147. case 9600: return B9600;
  148. case 19200: return B19200;
  149. case 38400: return B38400;
  150. case 57600: return B57600;
  151. case 115200: return B115200;
  152. default:
  153. fprintf(stderr,"Unsupported baud rate: %d\n",baud_rate);
  154. exit(1);
  155. }
  156. }
  157. void print_binary(const unsigned char* data,int length)
  158. {
  159. for(int i = 0; i < length; i++)
  160. {
  161. printf("%02X ",data[i]);
  162. }
  163. printf("\n");
  164. }
  165. void parse_and_enqueue_request(TransactionQueue* queue,const unsigned char* buffer,int length)
  166. {
  167. unsigned short transaction_id = (buffer[0] << 8) | buffer[1];
  168. unsigned char unit_id = buffer[6];
  169. unsigned char function_code = buffer[7];
  170. unsigned short address = (buffer[8] << 8) | buffer[9];
  171. unsigned short quantity = (buffer[10] << 8) | buffer[11];
  172. TransactionEntry entry = { transaction_id, unit_id, function_code, address, quantity };
  173. enqueue(queue,entry);
  174. }
  175. void parse_and_send_response(TransactionQueue* queue,const unsigned char* buffer,int length,int newsockfd,int verbose)
  176. {
  177. unsigned char unit_id = buffer[0];
  178. unsigned char function_code = buffer[1];
  179. unsigned short address = 0;
  180. unsigned short quantity = 0;
  181. int compare_address = 0;
  182. int compare_quantity = 0;
  183. if(newsockfd > 0)
  184. {
  185. if(write(newsockfd,buffer,length) < 0)
  186. {
  187. perror("ERROR writing to socket");
  188. }
  189. }
  190. return;
  191. if(verbose)
  192. {
  193. printf("Converted Modbus TCP frame: ");
  194. print_binary(buffer,length);
  195. }
  196. if(function_code == 0x05 || function_code == 0x06 || function_code == 0x0F || function_code == 0x10)
  197. {
  198. address = (buffer[2] << 8) | buffer[3];
  199. compare_address = 1;
  200. }
  201. else if(function_code == 0x01 || function_code == 0x02 || function_code == 0x03 || function_code == 0x04)
  202. {
  203. quantity = (buffer[2] / 2); // Modbus RTU 字节数除以2是 quantity
  204. compare_quantity = 1;
  205. }
  206. else
  207. {
  208. fprintf(stderr,"Unsupported function code: %d\n",function_code);
  209. }
  210. TransactionEntry entry = dequeue(queue,unit_id,function_code,address,quantity,compare_address,compare_quantity);
  211. if(entry.transaction_id == 0)
  212. {
  213. // No matching transaction entry found
  214. fprintf(stderr,"No matching transaction entry found\n");
  215. return;
  216. }
  217. unsigned char tcp_frame[256];
  218. int data_length;
  219. unsigned short protocol_id = 0;
  220. if(function_code == 0x01 || function_code == 0x02 || function_code == 0x03 || function_code == 0x04)
  221. {
  222. unsigned char byte_count = buffer[2];
  223. data_length = byte_count + 1; // 包含 1 字节的 byte_count
  224. length = data_length + 2; // 单元标识符和功能码
  225. tcp_frame[0] = (entry.transaction_id >> 8) & 0xFF;
  226. tcp_frame[1] = entry.transaction_id & 0xFF;
  227. tcp_frame[2] = (protocol_id >> 8) & 0xFF;
  228. tcp_frame[3] = protocol_id & 0xFF;
  229. tcp_frame[4] = (length >> 8) & 0xFF;
  230. tcp_frame[5] = length & 0xFF;
  231. tcp_frame[6] = unit_id;
  232. tcp_frame[7] = function_code;
  233. tcp_frame[8] = byte_count;
  234. memcpy(tcp_frame + 9,buffer + 3,byte_count);
  235. }
  236. else if(function_code == 0x05 || function_code == 0x06)
  237. {
  238. data_length = 4;
  239. length = data_length + 2; // 单元标识符和功能码
  240. tcp_frame[0] = (entry.transaction_id >> 8) & 0xFF;
  241. tcp_frame[1] = entry.transaction_id & 0xFF;
  242. tcp_frame[2] = (protocol_id >> 8) & 0xFF;
  243. tcp_frame[3] = protocol_id & 0xFF;
  244. tcp_frame[4] = (length >> 8) & 0xFF;
  245. tcp_frame[5] = length & 0xFF;
  246. tcp_frame[6] = unit_id;
  247. tcp_frame[7] = function_code;
  248. tcp_frame[8] = (address >> 8) & 0xFF;
  249. tcp_frame[9] = address & 0xFF;
  250. memcpy(&tcp_frame[10],buffer + 4,2);
  251. // tcp_frame[10] = (quantity >> 8) & 0xFF;
  252. // tcp_frame[11] = quantity & 0xFF;
  253. }
  254. else if(function_code == 0x0F || function_code == 0x10)
  255. {
  256. data_length = 4;
  257. length = data_length + 4; // 单元标识符和功能码
  258. tcp_frame[0] = (entry.transaction_id >> 8) & 0xFF;
  259. tcp_frame[1] = entry.transaction_id & 0xFF;
  260. tcp_frame[2] = (protocol_id >> 8) & 0xFF;
  261. tcp_frame[3] = protocol_id & 0xFF;
  262. tcp_frame[4] = (length >> 8) & 0xFF;
  263. tcp_frame[5] = length & 0xFF;
  264. tcp_frame[6] = unit_id;
  265. tcp_frame[7] = function_code;
  266. tcp_frame[8] = (address >> 8) & 0xFF;
  267. tcp_frame[9] = address & 0xFF;
  268. memcpy(&tcp_frame[10],buffer + 4,2);
  269. // tcp_frame[10] = (quantity >> 8) & 0xFF;
  270. // tcp_frame[11] = quantity & 0xFF;
  271. }
  272. }
  273. int main(int argc,char* argv[])
  274. {
  275. int verbose = 0;
  276. const char* serial_port;
  277. int baud_rate;
  278. int tcp_port;
  279. for(int i = 1; i < argc; i++)
  280. {
  281. if(strcmp(argv[i],"-v") == 0)
  282. {
  283. verbose = 1;
  284. }
  285. else if(i == argc - 3)
  286. {
  287. serial_port = argv[i];
  288. }
  289. else if(i == argc - 2)
  290. {
  291. baud_rate = atoi(argv[i]);
  292. }
  293. else if(i == argc - 1)
  294. {
  295. tcp_port = atoi(argv[i]);
  296. }
  297. }
  298. if(argc < 4 || (argc == 5 && !verbose))
  299. {
  300. fprintf(stderr,"Usage: %s [-v] <serial_port> <baud_rate> <tcp_port>\n",argv[0]);
  301. exit(1);
  302. }
  303. int baud_rate_flag = get_baud_rate(baud_rate);
  304. int serial_fd = open(serial_port,O_RDWR | O_NOCTTY | O_NDELAY);
  305. if(serial_fd == -1)
  306. {
  307. perror("ERROR opening serial port");
  308. exit(1);
  309. }
  310. configure_serial_port(serial_fd,baud_rate_flag);
  311. configure_rs485_mode(serial_fd);
  312. int sockfd,newsockfd = -1;
  313. struct sockaddr_in serv_addr,cli_addr;
  314. socklen_t clilen;
  315. char buffer[256];
  316. int n;
  317. sockfd = socket(AF_INET,SOCK_STREAM,0);
  318. if(sockfd < 0)
  319. {
  320. perror("ERROR opening socket");
  321. close(serial_fd);
  322. exit(1);
  323. }
  324. memset((char*)&serv_addr,0,sizeof(serv_addr));
  325. serv_addr.sin_family = AF_INET;
  326. serv_addr.sin_addr.s_addr = INADDR_ANY;
  327. serv_addr.sin_port = htons(tcp_port);
  328. if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
  329. {
  330. perror("ERROR on binding");
  331. close(sockfd);
  332. close(serial_fd);
  333. exit(1);
  334. }
  335. listen(sockfd,5);
  336. clilen = sizeof(cli_addr);
  337. int epoll_fd = epoll_create1(0);
  338. if(epoll_fd == -1)
  339. {
  340. perror("ERROR creating epoll");
  341. close(sockfd);
  342. close(serial_fd);
  343. exit(1);
  344. }
  345. struct epoll_event ev,events[MAX_EVENTS];
  346. ev.events = EPOLLIN;
  347. ev.data.fd = sockfd;
  348. if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sockfd,&ev) == -1)
  349. {
  350. perror("ERROR adding socket to epoll");
  351. close(sockfd);
  352. close(serial_fd);
  353. close(epoll_fd);
  354. exit(1);
  355. }
  356. ev.events = EPOLLIN;
  357. ev.data.fd = serial_fd;
  358. if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,serial_fd,&ev) == -1)
  359. {
  360. perror("ERROR adding serial port to epoll");
  361. close(sockfd);
  362. close(serial_fd);
  363. close(epoll_fd);
  364. exit(1);
  365. }
  366. TransactionQueue queue;
  367. initQueue(&queue);
  368. while(1)
  369. {
  370. int nfds = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);
  371. if(nfds == -1)
  372. {
  373. perror("ERROR in epoll_wait");
  374. close(sockfd);
  375. close(serial_fd);
  376. close(epoll_fd);
  377. exit(1);
  378. }
  379. for(int i = 0; i < nfds; i++)
  380. {
  381. if(events[i].data.fd == sockfd)
  382. {
  383. newsockfd = accept(sockfd,(struct sockaddr*)&cli_addr,&clilen);
  384. if(newsockfd == -1)
  385. {
  386. perror("ERROR on accept");
  387. continue;
  388. }
  389. ev.events = EPOLLIN | EPOLLET;
  390. ev.data.fd = newsockfd;
  391. if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,newsockfd,&ev) == -1)
  392. {
  393. perror("ERROR adding new socket to epoll");
  394. close(newsockfd);
  395. continue;
  396. }
  397. }
  398. else if(events[i].data.fd == serial_fd)
  399. {
  400. memset(buffer,0,256);
  401. n = read(serial_fd,buffer,255);
  402. if(n < 0)
  403. {
  404. perror("ERROR reading from serial port");
  405. continue;
  406. }
  407. if(verbose)
  408. {
  409. printf("Received Modbus RTU frame: ");
  410. print_binary((unsigned char*)buffer,n);
  411. }
  412. parse_and_send_response(&queue,buffer,n,newsockfd,verbose);
  413. }
  414. else
  415. {
  416. memset(buffer,0,256);
  417. n = read(events[i].data.fd,buffer,255);
  418. if(n < 0)
  419. {
  420. perror("ERROR reading from socket");
  421. close(events[i].data.fd);
  422. continue;
  423. }
  424. else if(n == 0)
  425. {
  426. close(events[i].data.fd);
  427. continue;
  428. }
  429. if(verbose)
  430. {
  431. printf("Received Modbus TCP frame: ");
  432. print_binary((unsigned char*)buffer,n);
  433. }
  434. // parse_and_enqueue_request(&queue,buffer,n);
  435. // unsigned char rtu_frame[256];
  436. // int rtu_length = n - 6;
  437. // memcpy(rtu_frame,buffer + 6,rtu_length);
  438. // unsigned short crc = crc16(rtu_frame,rtu_length);
  439. // rtu_frame[rtu_length] = crc & 0xFF; // CRC LSB
  440. // rtu_frame[rtu_length + 1] = (crc >> 8) & 0xFF; // CRC MSB
  441. // rtu_length += 2;
  442. if(verbose)
  443. {
  444. printf("Converted Modbus RTU frame: ");
  445. print_binary(buffer,n);
  446. }
  447. if(write(serial_fd,buffer,n) < 0)
  448. {
  449. perror("ERROR writing to serial port");
  450. }
  451. }
  452. }
  453. }
  454. close(sockfd);
  455. close(serial_fd);
  456. close(epoll_fd);
  457. return 0;
  458. }