-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmodbus-ping.c
184 lines (165 loc) · 4.47 KB
/
modbus-ping.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <error.h>
#include <modbus/modbus.h>
#include <modbus/modbus-rtu.h>
#include "modbustools.h"
void usage(char* self, int e) {
fprintf(stderr, "Usage: %s [-d /dev/ttyX] [-r baudrate] [-b databits] [-p (N|E|O)] [-s stopbits] [-n retries] [-v] <bus_address>\n", self);
fprintf(stderr, "Options description:\n\
-d: UART device (default %s)\n\
-r: UART baud rate: 9600, 19200, 57600, 115200 etc (default %d)\n\
-b: UART data bits: 5-8 (default %d)\n\
-p: UART parity check: None, Even, Odd (default %c)\n\
-b: UART stop bits: 1-2 (default %d)\n\
-n: retry count (default %d)\n\
-v: verbose debug on stderr\n", MODBUSTOOLS_DEFAULT_UART, MODBUSTOOLS_DEFAULT_BAUDRATE, MODBUSTOOLS_DEFAULT_DATABITS, MODBUSTOOLS_DEFAULT_PARITY, MODBUSTOOLS_DEFAULT_STOPBITS, MODBUSTOOLS_DEFAULT_RETRIES);
exit(e);
}
int main( int argc, char** argv ) {
// Configuration variables and defaults
char* uart = MODBUSTOOLS_DEFAULT_UART;
int uart_baudrate = MODBUSTOOLS_DEFAULT_BAUDRATE;
int uart_databits = MODBUSTOOLS_DEFAULT_DATABITS;
char uart_parity = MODBUSTOOLS_DEFAULT_PARITY;
int uart_stopbits = MODBUSTOOLS_DEFAULT_STOPBITS;
int retry = MODBUSTOOLS_DEFAULT_RETRIES;
int debug=0;
long tmp;
// Parse commandline options
int c;
while ((c = getopt (argc, argv, "hd:r:b:p:s:t:n:v")) != -1) {
switch (c) {
case 'h':
usage(argv[0], 0);
case 'd':
uart=optarg;
break;
case 'r':
tmp=strtol(optarg, NULL, 0);
uart_baudrate=(int)tmp;
break;
case 'b':
tmp=strtol(optarg, NULL, 0);
if(tmp>=5 && tmp<=8) {
uart_databits=(int)tmp;
} else {
fprintf(stderr, "%s: invalid UART data bits setting -- %d\n", argv[0], tmp);
exit(1);
}
break;
case 'p':
switch(*optarg) {
case 'N':
case 'E':
case 'O':
uart_parity=*optarg;
break;
default:
fprintf(stderr, "%s: invalid UART parity setting -- '%s'\n", argv[0], optarg);
exit(1);
}
break;
case 's':
tmp=strtol(optarg, NULL, 0);
if(tmp==1 || tmp==2) {
uart_stopbits=(int)tmp;
} else {
fprintf(stderr, "%s: invalid UART stop bits setting -- %d\n", argv[0], tmp);
exit(1);
}
break;
case 'n':
tmp=strtol(optarg, NULL, 0);
if(tmp>0) {
retry=tmp;
} else {
fprintf(stderr, "%s: invalid retry count -- %d\n", argv[0], tmp);
exit(1);
}
break;
case 'v':
debug=1;
break;
}
}
// Determine bus address
uint8_t addr;
if((argc-optind)>0) {
long addrl=strtol(argv[optind], NULL, 0);
if( (addrl>=0) && (addrl<=247) ) {
addr=(uint8_t)addrl;
} else {
fprintf(stderr, "%s: invalid bus address -- %d, MODBUS allows from 1 to 247 and 0 for broadcast\n", argv[0], addrl);
exit(1);
}
} else {
fprintf(stderr, "%s: not enough arguments\n", argv[0]);
usage(argv[0], 1);
}
// Check UART settings
struct stat info;
if(stat(uart, &info)==0) {
if(!S_ISCHR(info.st_mode)) {
fprintf(stderr, "%s: given UART device is not a character device -- '%s'\n", argv[0], uart);
exit(1);
}
} else {
error(1, errno, "cannot stat UART device '%s'", uart);
}
// Debug output
if(debug) {
fprintf(stderr, "Device: %s %d %d/%c/%d\n", uart, uart_baudrate, uart_databits, uart_parity, uart_stopbits);
fprintf(stderr, "Bus address: %d\n", addr);
}
// Connect
modbus_t* modbus=modbus_new_rtu(uart, uart_baudrate, uart_parity, uart_databits, uart_stopbits);
if (modbus == NULL) {
fprintf(stderr, "%s: unable to create the libmodbus context\n", argv[0]);
exit(2);
}
modbus_rtu_set_serial_mode(modbus, MODBUS_RTU_RS485); // Make configurable!
if (modbus_connect(modbus) == -1) {
fprintf(stderr, "%s: MODBUS connection failed: %s\n", argv[0], modbus_strerror(errno));
modbus_free(modbus);
exit(2);
}
// Prepare buffers
uint8_t ping_rq[] = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 };
// ^addr ^ping func & sub ^payload
uint8_t rsp[MODBUS_RTU_MAX_ADU_LENGTH];
ping_rq[0]=addr;
int result;
// Interact with modbus
for(; retry>0; retry--) {
modbus_send_raw_request(modbus, ping_rq, 6*sizeof(uint8_t));
if( modbus_receive_confirmation(modbus, rsp) == -1 ) {
result=2;
// usleep(100000);
} else {
result=0;
break;
}
}
// Debug output
if(debug) {
fprintf(stderr, "Retries left: %d\n", retry);
}
switch(result) {
case 0:
printf("OK\n");
break;
case 2:
printf("No response\n");
break;
}
// Clean up
modbus_close(modbus);
modbus_free(modbus);
// Exit with result
exit(result);
}