3
3
Modbus TCP server script for debugging
4
4
Author: Michael Oberdorf IT-Consulting
5
5
Datum: 2020-03-30
6
+ Last modified by: Hackergarden Meetup@Codecentric
7
+ Last modified at: 2023-11-07
6
8
*************************************************************************** """
7
9
import sys
8
10
import os
18
20
import json
19
21
20
22
# default configuration file path
21
- config_file = '/opt/modbus_server/etc /modbus_server.json'
22
- VERSION = '1.1.3 '
23
+ config_file = '/app /modbus_server.json'
24
+ VERSION = '1.1.4 '
23
25
"""
24
26
###############################################################################
25
27
# F U N C T I O N S
@@ -39,7 +41,7 @@ def get_ip_address():
39
41
pass
40
42
return (ipaddr )
41
43
42
- def run_server (listener_address = '0.0.0.0' , listener_port = 5020 , tls_cert = None , tls_key = None , zeroMode = False , discreteInputs = dict (), coils = dict (), holdingRegisters = dict (), inputRegisters = dict ()):
44
+ def run_server (listener_address : str = '0.0.0.0' , listener_port : int = 5020 , tls_cert : str = None , tls_key : str = None , zeroMode : bool = False , discreteInputs : dict = dict (), coils : dict = dict (), holdingRegisters : dict = dict (), inputRegisters : dict = dict ()):
43
45
"""
44
46
Run the modbus server(s)
45
47
@param listener_address: string, IP address to bind the listener (default: '0.0.0.0')
@@ -139,10 +141,11 @@ def run_server(listener_address='0.0.0.0', listener_port=5020, tls_cert=None, tl
139
141
# StartTcpServer(context, identity=identity, framer=ModbusRtuFramer, address=(listener_address, listener_port))
140
142
141
143
142
- def prepareRegister (register , initializeUndefinedRegisters = False ):
144
+ def prepareRegister (register : dict , initType : str , initializeUndefinedRegisters : bool = False ) -> dict :
143
145
"""
144
146
Function to prepare the register to have the correct data types
145
147
@param register: dict(), the register dictionary, loaded from json file
148
+ @param initType: str(), how to initialize the register values 'boolean' or 'word'
146
149
@param initializeUndefinedRegisters: boolean, fill undefined registers with 0x00 (default: False)
147
150
@return: dict(), register with correct data types
148
151
"""
@@ -160,17 +163,34 @@ def prepareRegister(register, initializeUndefinedRegisters=False):
160
163
161
164
val = register [key ]
162
165
valOut = val
163
- if isinstance (val , str ) and str (val )[0 :2 ] == '0x' :
166
+ if initType == 'word' and isinstance (val , str ) and str (val )[0 :2 ] == '0x' :
164
167
valOut = int (val , 16 )
165
168
log .debug (' Transform value for register: ' + str (keyOut ) + ' from: ' + str (val ) + ' (' + str (type (key )) + ') to: ' + str (valOut ) + ' (' + str (type (valOut )) + ')' )
169
+ elif initType == 'boolean' :
170
+ if isinstance (val , bool ):
171
+ valOut = val
172
+ log .debug (' Set register: ' + str (keyOut ) + ' to: ' + str (valOut ) + ' (' + str (type (valOut )) + ')' )
173
+ elif isinstance (val , int ):
174
+ if val == 0 :
175
+ valOut = False
176
+ else :
177
+ valOut = True
178
+ log .debug (' Transform value for register: ' + str (keyOut ) + ' from: ' + str (val ) + ' (' + str (type (key )) + ') to: ' + str (valOut ) + ' (' + str (type (valOut )) + ')' )
166
179
outRegister [keyOut ] = valOut
167
180
168
181
if initializeUndefinedRegisters :
169
- log .debug (' Fill undefined registers with 0x00' )
182
+ if initType == 'word' :
183
+ log .debug (' Fill undefined registers with 0x00' )
184
+ elif initType == 'boolean' :
185
+ log .debug (' Fill undefined registers with False' )
170
186
for r in range (0 , 65536 , 1 ):
171
187
if r not in outRegister :
188
+ if initType == 'word' :
172
189
#log.debug(' Initialize address: ' + str(r) + ' with 0')
173
190
outRegister [r ] = 0
191
+ elif initType == 'boolean' :
192
+ #log.debug(' Initialize address: ' + str(r) + ' with False')
193
+ outRegister [r ] = False
174
194
175
195
return (outRegister )
176
196
@@ -194,7 +214,8 @@ def prepareRegister(register, initializeUndefinedRegisters=False):
194
214
config_file = args .config_file
195
215
196
216
# read configuration file
197
- with open (config_file , encoding = 'utf-8' ) as f : CONFIG = json .load (f )
217
+ with open (config_file , encoding = 'utf-8' ) as f :
218
+ CONFIG = json .load (f )
198
219
199
220
200
221
# Initialize logger
@@ -209,15 +230,16 @@ def prepareRegister(register, initializeUndefinedRegisters=False):
209
230
else : log .setLevel (logging .INFO )
210
231
211
232
212
- # be sure the data types within the dictionaries are correct (json will only allow strings as keys)
213
- discreteInputs = prepareRegister (CONFIG ['registers' ]['discreteInput' ], CONFIG ['registers' ]['initializeUndefinedRegisters' ])
214
- coils = prepareRegister (CONFIG ['registers' ]['coils' ], CONFIG ['registers' ]['initializeUndefinedRegisters' ])
215
- holdingRegisters = prepareRegister (CONFIG ['registers' ]['holdingRegister' ], CONFIG ['registers' ]['initializeUndefinedRegisters' ])
216
- inputRegisters = prepareRegister (CONFIG ['registers' ]['inputRegister' ], CONFIG ['registers' ]['initializeUndefinedRegisters' ])
217
-
218
-
219
233
# start the server
220
234
log .info ('Starting Modbus TCP Server, v' + str (VERSION ))
235
+ log .debug ('Loaded successfully the configuration file: {}' .format (config_file ))
236
+
237
+ # be sure the data types within the dictionaries are correct (json will only allow strings as keys)
238
+ discreteInputs = prepareRegister (register = CONFIG ['registers' ]['discreteInput' ], initType = 'boolean' , initializeUndefinedRegisters = CONFIG ['registers' ]['initializeUndefinedRegisters' ])
239
+ coils = prepareRegister (register = CONFIG ['registers' ]['coils' ], initType = 'boolean' , initializeUndefinedRegisters = CONFIG ['registers' ]['initializeUndefinedRegisters' ])
240
+ holdingRegisters = prepareRegister (register = CONFIG ['registers' ]['holdingRegister' ], initType = 'word' , initializeUndefinedRegisters = CONFIG ['registers' ]['initializeUndefinedRegisters' ])
241
+ inputRegisters = prepareRegister (register = CONFIG ['registers' ]['inputRegister' ], initType = 'word' , initializeUndefinedRegisters = CONFIG ['registers' ]['initializeUndefinedRegisters' ])
242
+
221
243
# try to get the interface IP address
222
244
localIPAddr = get_ip_address ()
223
245
if localIPAddr != '' : log .info ('Outbund device IP address is: ' + localIPAddr )
0 commit comments