-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmocli.py
More file actions
executable file
·164 lines (126 loc) · 5.51 KB
/
Copy pathmocli.py
File metadata and controls
executable file
·164 lines (126 loc) · 5.51 KB
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
#!/usr/bin/env python
import argparse
import functools
'''
Command Line Wrapper around pymodbus
Known Issues:
Writing Integer Values: if the first value in a --values input is a negative
value, the parser interprets it incorrectly as an option flag. This can be
avoided if the space is removed between the -v or --values flag and the
values that follow.
'''
def stringBool(val):
uval = val.upper()
if uval in ['1','T','TRUE']:
return True
elif uval in ['0','F','FALSE']:
return False
else:
return None
def arrayStringBools(valarr):
result = [stringBool(item) for item in valarr]
return result
# String to Int works as expected except for when value is out of signed or
# unsigned Modbus Word (2 Bytes) range. In this case it will return None. If a
# negative number is provided, it is converted to the equivalent unsigned Word
# value silently.
def stringToInt(val):
intval = int(val)
if intval < -0xFFFF or intval > 0xFFFF:
return None
elif intval < 0:
return 0x10000 + intval
else:
return intval
def arrayStringInts(valarr):
return [stringToInt(item) for item in valarr]
parser = argparse.ArgumentParser(prog='ReadHTcp')
parser.add_argument('method', choices=['tcp','udp','rtu','serial'], default='tcp')
parser.add_argument('-a','--address',type=int)
parser.add_argument('-c','--count',type=int,default=1)
parser.add_argument('-v','--values',type=lambda s: [item for item in list(map(lambda t: t.strip(),s.split(',')))])
parser.add_argument('-i','--ip',default='127.0.0.1')
parser.add_argument('-p','--port',default=502,type=int)
parser.add_argument('-u','--unit',type=int,default='0')
# Arguments for Serial Clients
# timeout is in seconds
parser.add_argument('-t', '-timeout',type=int,default=3)
parser.add_argument('--stopbits',choices=[0,1,2],default=1)
parser.add_argument('--bytesize',choices=[5,6,7,8],default=8)
parser.add_argument('--parity',choices=['N','E','O'])
parser.add_argument('--baudrate',type=int,default=9600)
# Datastore Arguments
parser.add_argument('--zeromode',action='store_true')
parser.add_argument('-r','--repeat',type=int,default=1)
parser.add_argument('-f','--function',choices=['rcs','wcs','wc','rds','rhs','whs','wh','ris','rwh','mwh','read-coils','write-coils','write_coil','read-discretes','read-holdings','write-holdings','write-holding','read-inputs','read-write-registers','mask-write-register'])
parser.add_argument('-d','--debug',action='store_true')
kargs, uargs = parser.parse_known_args()
duargs = {}
for s in uargs:
key,val = s.split('=')
duargs[key]=val
if kargs.debug:
print('dict',kargs.__dict__)
print('debug', kargs.debug)
print('Known: ', kargs)
print('Unknown: ',uargs)
print('Unknown Dict: ',duargs)
quit()
client = None
try:
if kargs.method == 'tcp':
from pymodbus.client.sync import ModbusTcpClient
client = ModbusTcpClient(kargs.ip,port=kargs.port,unit_id=kargs.unit)
elif kargs.method == 'rtu':
from pymodbus.client.sync import ModbusSeriaClient
client = ModbusRtuClient(kargs.method, port=kargs.port, stopbits=kargs.stopbits,bytesize=kargs.bytesize,parity=kargs.parity,baudrate=kargs.baudrate,timeout=kargs.timeout)
if client != None:
display_prefix = ''
function_result = None
write_result = None
for x in range(kargs.repeat):
if kargs.function in ['rcs','read-coils']:
read = client.read_coils(kargs.address,kargs.count,unit=kargs.unit)
function_result=read.bits
display_prefix = 'Read Coils'
elif kargs.function in ['rds','read-discretes']:
read = client.read_discrete_inputs(kargs.address,kargs.count,unit=kargs.unit)
function_result=read.bits
display_prefix = 'Read Discretes'
elif kargs.function in ['ris','read-inputs']:
read = client.read_input_registers(kargs.address,kargs.count,unit=kargs.unit)
function_result=read.registers
display_prefix = 'Read Input Registers'
elif kargs.function in ['rhs','read-holding']:
read = client.read_holding_registers(kargs.address,kargs.count,unit=kargs.unit)
function_result = read.registers
display_prefix = 'Read Holding'
elif kargs.function in ['wc','write-coil']:
result = client.write_coil(kargs.address,stringBool(kargs.values[0]),unit=kargs.unit)
write_result = result
display_prefix = 'Write Coil'
elif kargs.function in ['wcs','write-coils']:
coil_values = arrayStringBools(kargs.values)
result = client.write_coils(kargs.address,coil_values,unit=kargs.unit)
write_result = result
display_prefix = 'Write Coils'
elif kargs.function in ['wh','write-holding']:
result = client.write_register(kargs.address,stringToInt(kargs.values[0]),unit=kargs.unit)
write_result = result
display_prefix = 'Write Holding Register'
elif kargs.function in ['whs','write-holdings']:
# print('-------> Values: ' +str(arrayStringInts(kargs.values)))
result = client.write_registers(kargs.address,arrayStringInts(kargs.values),unit=kargs.unit)
write_result = result
display_prefix = 'Write Holding Registers'
else:
print('Function "%s" is not yet implemented in this wrapper. Exiting' % kargs.function)
quit()
# Display results
if function_result != None:
print(display_prefix + ' #%s' % x,functools.reduce(lambda x,y: str(x)+ ',' + str(y),function_result[:kargs.count]))
if write_result != None:
print(display_prefix + ' #%s' % x, write_result)
finally:
if client != None:
client.close()