# HG changeset patch # User Mario de Sousa # Date 1591017082 -3600 # Node ID d2b2ee04bfa18fd76afbef1900564eec746fdb53 # Parent 7575050a80c5427f748b0c510425ea0d013bf3bc Add web extension: configure Modbus Server plugin parameters diff -r 7575050a80c5 -r d2b2ee04bfa1 modbus/mb_runtime.c --- a/modbus/mb_runtime.c Mon Jun 01 08:54:26 2020 +0100 +++ b/modbus/mb_runtime.c Mon Jun 01 14:11:22 2020 +0100 @@ -513,6 +513,16 @@ // -1 --> modbus node created!; no thread created // >=0 --> modbus node created!; thread created! server_nodes[index].mb_nd = -2; + /* see comment in mb_runtime.h to understad why we need to initialize these entries */ + switch (server_nodes[index].node_address.naf) { + case naf_tcp: + server_nodes[index].node_address.addr.tcp.host = server_nodes[index].str1; + server_nodes[index].node_address.addr.tcp.service = server_nodes[index].str2; + break; + case naf_rtu: + server_nodes[index].node_address.addr.rtu.device = server_nodes[index].str1; + break; + } } /* modbus library init */ @@ -919,12 +929,13 @@ const char * __modbus_get_ClientNode_addr_type (int nodeid) {return addr_type_str[client_nodes[nodeid].node_address.naf];} const char * __modbus_get_ServerNode_config_name(int nodeid) {return server_nodes[nodeid].config_name; } -const char * __modbus_get_ServerNode_host (int nodeid) {return server_nodes[nodeid].node_address.addr.tcp.host; } -const char * __modbus_get_ServerNode_port (int nodeid) {return server_nodes[nodeid].node_address.addr.tcp.service; } -const char * __modbus_get_ServerNode_device (int nodeid) {return server_nodes[nodeid].node_address.addr.rtu.device; } +const char * __modbus_get_ServerNode_host (int nodeid) {return server_nodes[nodeid].str1; } +const char * __modbus_get_ServerNode_port (int nodeid) {return server_nodes[nodeid].str2; } +const char * __modbus_get_ServerNode_device (int nodeid) {return server_nodes[nodeid].str1; } int __modbus_get_ServerNode_baud (int nodeid) {return server_nodes[nodeid].node_address.addr.rtu.baud; } int __modbus_get_ServerNode_parity (int nodeid) {return server_nodes[nodeid].node_address.addr.rtu.parity; } int __modbus_get_ServerNode_stop_bits (int nodeid) {return server_nodes[nodeid].node_address.addr.rtu.stop_bits;} +u8 __modbus_get_ServerNode_slave_id (int nodeid) {return server_nodes[nodeid].slave_id; } const char * __modbus_get_ServerNode_addr_type (int nodeid) {return addr_type_str[server_nodes[nodeid].node_address.naf];} @@ -937,4 +948,11 @@ void __modbus_set_ClientNode_comm_period(int nodeid, u64 value) {client_nodes[nodeid].comm_period = value;} - +void __modbus_set_ServerNode_host (int nodeid, const char * value) {__safe_strcnpy(server_nodes[nodeid].str1, value, MODBUS_PARAM_STRING_SIZE);} +void __modbus_set_ServerNode_port (int nodeid, const char * value) {__safe_strcnpy(server_nodes[nodeid].str2, value, MODBUS_PARAM_STRING_SIZE);} +void __modbus_set_ServerNode_device (int nodeid, const char * value) {__safe_strcnpy(server_nodes[nodeid].str1, value, MODBUS_PARAM_STRING_SIZE);} +void __modbus_set_ServerNode_baud (int nodeid, int value) {server_nodes[nodeid].node_address.addr.rtu.baud = value;} +void __modbus_set_ServerNode_parity (int nodeid, int value) {server_nodes[nodeid].node_address.addr.rtu.parity = value;} +void __modbus_set_ServerNode_stop_bits (int nodeid, int value) {server_nodes[nodeid].node_address.addr.rtu.stop_bits = value;} +void __modbus_set_ServerNode_slave_id (int nodeid, u8 value) {server_nodes[nodeid].slave_id = value;} + diff -r 7575050a80c5 -r d2b2ee04bfa1 modbus/mb_runtime.h --- a/modbus/mb_runtime.h Mon Jun 01 08:54:26 2020 +0100 +++ b/modbus/mb_runtime.h Mon Jun 01 14:11:22 2020 +0100 @@ -83,6 +83,8 @@ typedef struct{ const char *location; const char *config_name; + char str1[MODBUS_PARAM_STRING_SIZE]; + char str2[MODBUS_PARAM_STRING_SIZE]; u8 slave_id; node_addr_t node_address; int mb_nd; // modbus library node used for this server diff -r 7575050a80c5 -r d2b2ee04bfa1 modbus/mb_utils.py --- a/modbus/mb_utils.py Mon Jun 01 08:54:26 2020 +0100 +++ b/modbus/mb_utils.py Mon Jun 01 14:11:22 2020 +0100 @@ -57,14 +57,12 @@ params: child - the correspondent subplugin in Beremiz """ node_init_template = '''/*node %(locnodestr)s*/ -{"%(locnodestr)s", "%(config_name)s", %(slaveid)s, {naf_tcp, {.tcp = {%(host)s, "%(port)s", DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */}''' +{"%(locnodestr)s", "%(config_name)s", "%(host)s", "%(port)s", %(slaveid)s, {naf_tcp, {.tcp = {NULL, NULL, DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */}''' location = ".".join(map(str, child.GetCurrentLocation())) config_name, host, port, slaveid = GetCTVals(child, range(4)) if host == "#ANY#": - host = 'INADDR_ANY' - else: - host = '"' + host + '"' + host = '' # slaveid = GetCTVal(child, 2) # if int(slaveid) not in xrange(256): # self.GetCTRoot().logger.write_error("Error: Wrong slave ID in %s server node\nModbus Plugin C code returns empty\n"%location) @@ -121,7 +119,7 @@ params: child - the correspondent subplugin in Beremiz """ node_init_template = '''/*node %(locnodestr)s*/ -{"%(locnodestr)s", "%(config_name)s", %(slaveid)s, {naf_rtu, {.rtu = {"%(device)s", %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */}''' +{"%(locnodestr)s", "%(config_name)s", "%(device)s", "",%(slaveid)s, {naf_rtu, {.rtu = {NULL, %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */}''' location = ".".join(map(str, child.GetCurrentLocation())) config_name, device, baud, parity, stopbits, slaveid = GetCTVals(child, range(6)) diff -r 7575050a80c5 -r d2b2ee04bfa1 runtime/Modbus_config.py --- a/runtime/Modbus_config.py Mon Jun 01 08:54:26 2020 +0100 +++ b/runtime/Modbus_config.py Mon Jun 01 14:11:22 2020 +0100 @@ -61,21 +61,21 @@ # Should be a directory that does not get wiped on reboot! _ModbusConfFiledir = "/tmp" -# Will contain references to the C functions -# (implemented in beremiz/modbus/mb_runtime.c) -# used to get/set the Modbus specific configuration paramters -GetParamFuncs = {} -SetParamFuncs = {} - - -# List of all TCP clients configured in the loaded PLC (i.e. the .so file loaded into memory) -# Each entry will be a dictionary. See _Add_TCP_Client() for the data structure details... -_TCPclient_list = [] - - - - -# Paramters we will need to get from the C code, but that will not be shown +# List of all Web Extension Setting nodes we are handling. +# One WebNode each for: +# - Modbus TCP client +# - Modbus TCP server +# - Modbus RTU client +# - Modbus RTU slave +# configured in the loaded PLC (i.e. the .so file loaded into memory) +# Each entry will be a dictionary. See _AddWebNode() for the details +# of the data structure in each entry. +_WebNodeList = [] + + + + +# Parameters we will need to get from the C code, but that will not be shown # on the web interface. Common to all modbus entry types (client/server, tcp/rtu/ascii) General_parameters = [ # param. name label ctype type annotate type @@ -108,15 +108,43 @@ ("comm_period" , _("Invocation Rate (ms)") , ctypes.c_ulonglong, annotate.Integer) ] - +TCPserver_parameters = [ + # param. name label ctype type annotate type + # (C code var name) (used on web interface) (C data type) (web data type) + # (annotate.String, + # annotate.Integer, ...) + ("host" , _("Local IP Address") , ctypes.c_char_p, annotate.String), + ("port" , _("Local Port Number") , ctypes.c_char_p, annotate.String), + ("slave_id" , _("Slave ID") , ctypes.c_ubyte, annotate.Integer) + ] + +RTUslave_parameters = [ + # param. name label ctype type annotate type + # (C code var name) (used on web interface) (C data type) (web data type) + # (annotate.String, + # annotate.Integer, ...) + ("device" , _("Serial Port") , ctypes.c_char_p, annotate.String), + ("baud" , _("Baud Rate") , ctypes.c_int, annotate.Integer), + ("parity" , _("Parity") , ctypes.c_int, annotate.Integer), + ("stop_bits" , _("Stop Bits") , ctypes.c_int, annotate.Integer), + ("slave_id" , _("Slave ID") , ctypes.c_ulonglong, annotate.Integer) + ] + + +# Dictionary containing List of Web viewable parameters # Note: the dictionary key must be the same as the string returned by the # __modbus_get_ClientNode_addr_type() # __modbus_get_ServerNode_addr_type() # functions implemented in C (see modbus/mb_runtime.c) -_client_parameters = {} -_client_parameters["tcp" ] = TCPclient_parameters -_client_parameters["rtu" ] = RTUclient_parameters -_client_parameters["ascii"] = [] # (Note: ascii not yet implemented in Beremiz modbus plugin) +_client_WebParamListDict = {} +_client_WebParamListDict["tcp" ] = TCPclient_parameters +_client_WebParamListDict["rtu" ] = RTUclient_parameters +_client_WebParamListDict["ascii"] = [] # (Note: ascii not yet implemented in Beremiz modbus plugin) + +_server_WebParamListDict = {} +_server_WebParamListDict["tcp" ] = TCPserver_parameters +_server_WebParamListDict["rtu" ] = RTUslave_parameters +_server_WebParamListDict["ascii"] = [] # (Note: ascii not yet implemented in Beremiz modbus plugin) #def _CheckPortnumber(port_number): @@ -164,22 +192,22 @@ -def _SetSavedConfiguration(node_id, newConfig): +def _SetSavedConfiguration(WebNode_id, newConfig): """ Stores a dictionary in a persistant file containing the Modbus parameter configuration """ - filename = _TCPclient_list[node_id]["filename"] + filename = _WebNodeList[WebNode_id]["filename"] with open(os.path.realpath(filename), 'w') as f: json.dump(newConfig, f, sort_keys=True, indent=4) - _TCPclient_list[node_id]["SavedConfiguration"] = newConfig - - - - -def _DelSavedConfiguration(node_id): + _WebNodeList[WebNode_id]["SavedConfiguration"] = newConfig + + + + +def _DelSavedConfiguration(WebNode_id): """ Deletes the file cotaining the persistent Modbus configuration """ - filename = _TCPclient_list[node_id]["filename"] + filename = _WebNodeList[WebNode_id]["filename"] if os.path.exists(filename): os.remove(filename) @@ -187,12 +215,12 @@ -def _GetSavedConfiguration(node_id): +def _GetSavedConfiguration(WebNode_id): """ Returns a dictionary containing the Modbus parameter configuration that was last saved to file. If no file exists, then return None """ - filename = _TCPclient_list[node_id]["filename"] + filename = _WebNodeList[WebNode_id]["filename"] try: #if os.path.isfile(filename): saved_config = json.load(open(filename)) @@ -208,16 +236,18 @@ -def _GetPLCConfiguration(node_id): +def _GetPLCConfiguration(WebNode_id): """ Returns a dictionary containing the current Modbus parameter configuration stored in the C variables in the loaded PLC (.so file) """ current_config = {} - addr_type = _TCPclient_list[node_id]["addr_type"] - - for par_name, x1, x2, x3 in _client_parameters[addr_type]: - value = GetParamFuncs[par_name](node_id) + C_node_id = _WebNodeList[WebNode_id]["C_node_id"] + WebParamList = _WebNodeList[WebNode_id]["WebParamList"] + GetParamFuncs = _WebNodeList[WebNode_id]["GetParamFuncs"] + + for par_name, x1, x2, x3 in WebParamList: + value = GetParamFuncs[par_name](C_node_id) if value is not None: current_config[par_name] = value @@ -225,53 +255,54 @@ -def _SetPLCConfiguration(node_id, newconfig): +def _SetPLCConfiguration(WebNode_id, newconfig): """ Stores the Modbus parameter configuration into the the C variables in the loaded PLC (.so file) """ - addr_type = _TCPclient_list[node_id]["addr_type"] - + C_node_id = _WebNodeList[WebNode_id]["C_node_id"] + SetParamFuncs = _WebNodeList[WebNode_id]["SetParamFuncs"] + for par_name in newconfig: value = newconfig[par_name] if value is not None: - SetParamFuncs[par_name](node_id, value) + SetParamFuncs[par_name](C_node_id, value) -def _GetWebviewConfigurationValue(ctx, node_id, argument): +def _GetWebviewConfigurationValue(ctx, WebNode_id, argument): """ Callback function, called by the web interface (NevowServer.py) to fill in the default value of each parameter of the web form Note that the real callback function is a dynamically created function that - will simply call this function to do the work. It will also pass the node_id + will simply call this function to do the work. It will also pass the WebNode_id as a parameter. - """ + """ try: - return _TCPclient_list[node_id]["WebviewConfiguration"][argument.name] + return _WebNodeList[WebNode_id]["WebviewConfiguration"][argument.name] except Exception: return "" -def _updateWebInterface(node_id): +def _updateWebInterface(WebNode_id): """ Add/Remove buttons to/from the web interface depending on the current state - If there is a saved state => add a delete saved state button """ - config_hash = _TCPclient_list[node_id]["config_hash"] - config_name = _TCPclient_list[node_id]["config_name"] + config_hash = _WebNodeList[WebNode_id]["config_hash"] + config_name = _WebNodeList[WebNode_id]["config_name"] # Add a "Delete Saved Configuration" button if there is a saved configuration! - if _TCPclient_list[node_id]["SavedConfiguration"] is None: + if _WebNodeList[WebNode_id]["SavedConfiguration"] is None: _NS.ConfigurableSettings.delSettings("ModbusConfigDelSaved" + config_hash) else: def __OnButtonDel(**kwargs): - return OnButtonDel(node_id = node_id, **kwargs) + return OnButtonDel(WebNode_id = WebNode_id, **kwargs) _NS.ConfigurableSettings.addSettings( "ModbusConfigDelSaved" + config_hash, # name (internal, may not contain spaces, ...) @@ -291,21 +322,21 @@ Note that this function does not get called directly. The real callback function is the dynamic __OnButtonSave() function, which will add the - "node_id" argument, and call this function to do the work. + "WebNode_id" argument, and call this function to do the work. """ #_plcobj.LogMessage("Modbus web server extension::OnButtonSave() Called") - newConfig = {} - node_id = kwargs.get("node_id", None) - addr_type = _TCPclient_list[node_id]["addr_type"] - - for par_name, x1, x2, x3 in _client_parameters[addr_type]: + newConfig = {} + WebNode_id = kwargs.get("WebNode_id", None) + WebParamList = _WebNodeList[WebNode_id]["WebParamList"] + + for par_name, x1, x2, x3 in WebParamList: value = kwargs.get(par_name, None) if value is not None: newConfig[par_name] = value - _TCPclient_list[node_id]["WebviewConfiguration"] = newConfig + _WebNodeList[WebNode_id]["WebviewConfiguration"] = newConfig # First check if configuration is OK. ## TODO... @@ -315,13 +346,13 @@ # store to file the new configuration so that # we can recoup the configuration the next time the PLC # has a cold start (i.e. when Beremiz_service.py is retarted) - _SetSavedConfiguration(node_id, newConfig) + _SetSavedConfiguration(WebNode_id, newConfig) # Configure PLC with the current Modbus parameters - _SetPLCConfiguration(node_id, newConfig) + _SetPLCConfiguration(WebNode_id, newConfig) # File has just been created => Delete button must be shown on web interface! - _updateWebInterface(node_id) + _updateWebInterface(WebNode_id) @@ -333,23 +364,23 @@ Modbus configution """ - node_id = kwargs.get("node_id", None) + WebNode_id = kwargs.get("WebNode_id", None) # Delete the file - _DelSavedConfiguration(node_id) + _DelSavedConfiguration(WebNode_id) # Set the current configuration to the default (hardcoded in C) - new_config = _TCPclient_list[node_id]["DefaultConfiguration"] - _SetPLCConfiguration(node_id, new_config) + new_config = _WebNodeList[WebNode_id]["DefaultConfiguration"] + _SetPLCConfiguration(WebNode_id, new_config) #Update the webviewconfiguration - _TCPclient_list[node_id]["WebviewConfiguration"] = new_config + _WebNodeList[WebNode_id]["WebviewConfiguration"] = new_config # Reset SavedConfiguration - _TCPclient_list[node_id]["SavedConfiguration"] = None + _WebNodeList[WebNode_id]["SavedConfiguration"] = None # File has just been deleted => Delete button on web interface no longer needed! - _updateWebInterface(node_id) + _updateWebInterface(WebNode_id) @@ -361,40 +392,53 @@ Note that this function does not get called directly. The real callback function is the dynamic __OnButtonShowCur() function, which will add the - "node_id" argument, and call this function to do the work. - """ - node_id = kwargs.get("node_id", None) - - _TCPclient_list[node_id]["WebviewConfiguration"] = _GetPLCConfiguration(node_id) - - - - -def _Load_TCP_Client(node_id): - TCPclient_entry = {} - - config_name = GetParamFuncs["config_name"](node_id) + "WebNode_id" argument, and call this function to do the work. + """ + WebNode_id = kwargs.get("WebNode_id", None) + + _WebNodeList[WebNode_id]["WebviewConfiguration"] = _GetPLCConfiguration(WebNode_id) + + + + +def _AddWebNode(C_node_id, WebParamListDict, GetParamFuncs, SetParamFuncs): + """ + Load from the compiled code (.so file, aloready loaded into memmory) + the configuration parameters of a specific Modbus plugin node. + This function works with both client and server nodes, depending on the + Get/SetParamFunc dictionaries passed to it (either the client or the server + node versions of the Get/Set functions) + """ + WebNode_entry = {} + + config_name = GetParamFuncs["config_name"](C_node_id) # addr_type will be one of "tcp", "rtu" or "ascii" - addr_type = GetParamFuncs["addr_type" ](node_id) + addr_type = GetParamFuncs["addr_type" ](C_node_id) # For some operations we cannot use the config name (e.g. filename to store config) # because the user may be using characters that are invalid for that purpose ('/' for # example), so we create a hash of the config_name, and use that instead. config_hash = hashlib.md5(config_name).hexdigest() - _plcobj.LogMessage("Modbus web server extension::_Load_TCP_Client("+str(node_id)+") config_name="+config_name) + #_plcobj.LogMessage("Modbus web server extension::_AddWebNode("+str(C_node_id)+") config_name="+config_name) # Add the new entry to the global list - # Note: it is OK, and actually necessary, to do this _before_ seting all the parameters in TCPclient_entry - # TCPclient_entry will be stored as a reference, so we can insert parameters at will. - global _TCPclient_list - _TCPclient_list.append(TCPclient_entry) - - # store all node_id relevant data for future reference - TCPclient_entry["node_id" ] = node_id - TCPclient_entry["config_name" ] = config_name - TCPclient_entry["addr_type" ] = addr_type - TCPclient_entry["config_hash" ] = config_hash - TCPclient_entry["filename" ] = os.path.join(_ModbusConfFiledir, "Modbus_config_" + config_hash + ".json") + # Note: it is OK, and actually necessary, to do this _before_ seting all the parameters in WebNode_entry + # WebNode_entry will be stored as a reference, so we can later insert parameters at will. + global _WebNodeList + _WebNodeList.append(WebNode_entry) + WebNode_id = len(_WebNodeList) - 1 + + # store all WebNode relevant data for future reference + # + # Note that "WebParamList" will reference one of: + # - TCPclient_parameters, TCPserver_parameters, RTUclient_parameters, RTUslave_parameters + WebNode_entry["C_node_id" ] = C_node_id + WebNode_entry["config_name" ] = config_name + WebNode_entry["config_hash" ] = config_hash + WebNode_entry["filename" ] = os.path.join(_ModbusConfFiledir, "Modbus_config_" + config_hash + ".json") + WebNode_entry["GetParamFuncs"] = GetParamFuncs + WebNode_entry["SetParamFuncs"] = SetParamFuncs + WebNode_entry["WebParamList" ] = WebParamListDict[addr_type] # Dictionary that contains the Modbus configuration currently being shown # on the web interface @@ -404,35 +448,35 @@ # The configuration viewed on the web will only be different to the current # configuration when the user edits the configuration, and when # the user asks to save an edited configuration that contains an error. - TCPclient_entry["WebviewConfiguration"] = None + WebNode_entry["WebviewConfiguration"] = None # Upon PLC load, this Dictionary is initialised with the Modbus configuration # hardcoded in the C file # (i.e. the configuration inserted in Beremiz IDE when project was compiled) - TCPclient_entry["DefaultConfiguration"] = _GetPLCConfiguration(node_id) - TCPclient_entry["WebviewConfiguration"] = TCPclient_entry["DefaultConfiguration"] + WebNode_entry["DefaultConfiguration"] = _GetPLCConfiguration(WebNode_id) + WebNode_entry["WebviewConfiguration"] = WebNode_entry["DefaultConfiguration"] # Dictionary that stores the Modbus configuration currently stored in a file # Currently only used to decide whether or not to show the "Delete" button on the - # web interface (only shown if _SavedConfiguration is not None) - SavedConfig = _GetSavedConfiguration(node_id) - TCPclient_entry["SavedConfiguration"] = SavedConfig + # web interface (only shown if "SavedConfiguration" is not None) + SavedConfig = _GetSavedConfiguration(WebNode_id) + WebNode_entry["SavedConfiguration"] = SavedConfig if SavedConfig is not None: - _SetPLCConfiguration(node_id, SavedConfig) - TCPclient_entry["WebviewConfiguration"] = SavedConfig + _SetPLCConfiguration(WebNode_id, SavedConfig) + WebNode_entry["WebviewConfiguration"] = SavedConfig # Define the format for the web form used to show/change the current parameters # We first declare a dynamic function to work as callback to obtain the default values for each parameter def __GetWebviewConfigurationValue(ctx, argument): - return _GetWebviewConfigurationValue(ctx, node_id, argument) + return _GetWebviewConfigurationValue(ctx, WebNode_id, argument) webFormInterface = [(name, web_dtype (label=web_label, default=__GetWebviewConfigurationValue)) - for name, web_label, c_dtype, web_dtype in _client_parameters[addr_type]] + for name, web_label, c_dtype, web_dtype in WebParamListDict[addr_type]] # Configure the web interface to include the Modbus config parameters def __OnButtonSave(**kwargs): - OnButtonSave(node_id=node_id, **kwargs) + OnButtonSave(WebNode_id=WebNode_id, **kwargs) _NS.ConfigurableSettings.addSettings( "ModbusConfigParm" + config_hash, # name (internal, may not contain spaces, ...) @@ -443,7 +487,7 @@ # Add a "View Current Configuration" button def __OnButtonShowCur(**kwargs): - OnButtonShowCur(node_id=node_id, **kwargs) + OnButtonShowCur(WebNode_id=WebNode_id, **kwargs) _NS.ConfigurableSettings.addSettings( "ModbusConfigViewCur" + config_hash, # name (internal, may not contain spaces, ...) @@ -453,7 +497,8 @@ __OnButtonShowCur) # callback # Add the Delete button to the web interface, if required - _updateWebInterface(node_id) + _updateWebInterface(WebNode_id) + @@ -495,21 +540,41 @@ return # Map the get/set functions (written in C code) we will be using to get/set the configuration parameters + # Will contain references to the C functions (implemented in beremiz/modbus/mb_runtime.c) + GetClientParamFuncs = {} + SetClientParamFuncs = {} + GetServerParamFuncs = {} + SetServerParamFuncs = {} + for name, web_label, c_dtype, web_dtype in TCPclient_parameters + RTUclient_parameters + General_parameters: - GetParamFuncName = "__modbus_get_ClientNode_" + name - GetParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, GetParamFuncName) - GetParamFuncs[name].restype = c_dtype - GetParamFuncs[name].argtypes = [ctypes.c_int] + ParamFuncName = "__modbus_get_ClientNode_" + name + GetClientParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, ParamFuncName) + GetClientParamFuncs[name].restype = c_dtype + GetClientParamFuncs[name].argtypes = [ctypes.c_int] for name, web_label, c_dtype, web_dtype in TCPclient_parameters + RTUclient_parameters: - SetParamFuncName = "__modbus_set_ClientNode_" + name - SetParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, SetParamFuncName) - SetParamFuncs[name].restype = None - SetParamFuncs[name].argtypes = [ctypes.c_int, c_dtype] + ParamFuncName = "__modbus_set_ClientNode_" + name + SetClientParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, ParamFuncName) + SetClientParamFuncs[name].restype = None + SetClientParamFuncs[name].argtypes = [ctypes.c_int, c_dtype] + + for name, web_label, c_dtype, web_dtype in TCPserver_parameters + RTUslave_parameters + General_parameters: + ParamFuncName = "__modbus_get_ServerNode_" + name + GetServerParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, ParamFuncName) + GetServerParamFuncs[name].restype = c_dtype + GetServerParamFuncs[name].argtypes = [ctypes.c_int] + + for name, web_label, c_dtype, web_dtype in TCPserver_parameters + RTUslave_parameters: + ParamFuncName = "__modbus_set_ServerNode_" + name + SetServerParamFuncs[name] = getattr(_plcobj.PLClibraryHandle, ParamFuncName) + SetServerParamFuncs[name].restype = None + SetServerParamFuncs[name].argtypes = [ctypes.c_int, c_dtype] for node_id in range(client_count): - _Load_TCP_Client(node_id) - + _AddWebNode(node_id, _client_WebParamListDict ,GetClientParamFuncs, SetClientParamFuncs) + + for node_id in range(server_count): + _AddWebNode(node_id, _server_WebParamListDict, GetServerParamFuncs, SetServerParamFuncs) @@ -517,22 +582,22 @@ def OnUnLoadPLC(): """ - # Callback function, called (by PLCObject.py) when a PLC program is unloaded from memory + Callback function, called (by PLCObject.py) when a PLC program is unloaded from memory """ #_plcobj.LogMessage("Modbus web server extension::OnUnLoadPLC() Called...") # Delete the Modbus specific web interface extensions # (Safe to ask to delete, even if it has not been added!) - global _TCPclient_list - for TCPclient_entry in _TCPclient_list: - config_hash = TCPclient_entry["config_hash"] + global _WebNodeList + for WebNode_entry in _WebNodeList: + config_hash = WebNode_entry["config_hash"] _NS.ConfigurableSettings.delSettings("ModbusConfigParm" + config_hash) _NS.ConfigurableSettings.delSettings("ModbusConfigViewCur" + config_hash) _NS.ConfigurableSettings.delSettings("ModbusConfigDelSaved" + config_hash) # Dele all entries... - _TCPclient_list = [] + _WebNodeList = []