def __init__(self): CodeFile.__init__(self) filepath = self.PythonFileName() if os.path.isfile(filepath): PythonParser = GenerateParserFromXSD( paths.AbsNeighbourFile(__file__, "py_ext_xsd.xsd")) xmlfile = open(filepath, 'r') pythonfile_xml = xmlfile.read() xmlfile.close() pythonfile_xml = pythonfile_xml.replace( 'xmlns="http://www.w3.org/2001/XMLSchema"', 'xmlns:xhtml="http://www.w3.org/1999/xhtml"') for cre, repl in [(re.compile(r"(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["), (re.compile(r"(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]: pythonfile_xml = cre.sub(repl, pythonfile_xml) try: python_code, error = PythonParser.LoadXMLString(pythonfile_xml) if error is None: self.CodeFile.globals.setanyText(python_code.getanyText()) os.remove(filepath) self.CreateCodeFileBuffer(False) self.OnCTNSave() except Exception as exc: error = str(exc) if error is not None: self.GetCTRoot().logger.write_error( _("Couldn't import old %s file.") % self.CTNName())
def Generate_C(self, buildpath, varlist, IECCFLAGS): plc_python_filepath = paths.AbsNeighbourFile(__file__, "plc_python.c") plc_python_file = open(plc_python_filepath, 'r') plc_python_code = plc_python_file.read() plc_python_file.close() python_eval_fb_list = [] for v in varlist: if v["vartype"] == "FB" and v["type"] in [ "PYTHON_EVAL", "PYTHON_POLL" ]: python_eval_fb_list.append(v) python_eval_fb_count = max(1, len(python_eval_fb_list)) # prepare python code plc_python_code = plc_python_code % { "python_eval_fb_count": python_eval_fb_count } Gen_Pythonfile_path = os.path.join(buildpath, "py_ext.c") pythonfile = open(Gen_Pythonfile_path, 'w') pythonfile.write(plc_python_code) pythonfile.close() return (["py_ext"], [(Gen_Pythonfile_path, IECCFLAGS)], True), ""
def GetCode(name): filename = paths.AbsNeighbourFile(__file__, name) return open(filename).read()
def GetHeader(): filename = paths.AbsNeighbourFile(__file__, "beremiz.h") return open(filename).read()
def GetLibraryPath(self): return paths.AbsNeighbourFile(__file__, "pous.xml")
def CTNGenerate_C(self, buildpath, locations): # Determine the current location in Beremiz's project configuration # tree current_location = self.GetCurrentLocation() # The current location of this plugin in Beremiz's configuration tree, separated by underscores # NOTE: Since BACnet plugin currently does not use sub-branches in the tree (in other words, this # _BacnetSlavePlug class was actually renamed as the RootClass), the current_location_dots # will actually be a single number (e.g.: 0 or 3 or 6, corresponding to the location # in which the plugin was inserted in the Beremiz configuration tree on Beremiz's left panel). locstr = "_".join(map(str, current_location)) # First check whether all the current parameters (inserted by user in # the GUI) are valid... if self.HasDuplicateObjectNames(): self.GetCTRoot().logger.write_warning( _("Error: BACnet server '{a1}.x:{a2}' contains objects with duplicate object names.\n" ).format(a1=locstr, a2=self.CTNName())) raise Exception(False) # TODO: return an error code instead of raising an exception # (currently unsupported by Beremiz) if self.HasDuplicateObjectIDs(): self.GetCTRoot().logger.write_warning( _("Error: BACnet server '{a1}.x: {a2}' contains objects with duplicate object identifiers.\n" ).format(a1=locstr, a2=self.CTNName())) raise Exception(False) # TODO: return an error code instead of raising an exception # (currently unsupported by Beremiz) # ------------------------------------------------------------------------------- # Create and populate the loc_dict dictionary with all parameters needed to configure # the generated source code (.c and .h files) # ---------------------------------------------------------------------- # 1) Create the dictionary (loc_dict = {}) loc_dict = {} loc_dict["locstr"] = locstr # The BACnetServerNode attribute is added dynamically by ConfigTreeNode._AddParamsMembers() # It will be an XML parser object created by # GenerateParserFromXSDstring(self.XSD).CreateRoot() # # Note: Override_Parameters_Saved_on_PLC is converted to an integer by int() # The above flag is not currently in use. It requires further thinking on how the # user will interpret and interact with this user interface... # loc_dict["Override_Parameters_Saved_on_PLC"] = int(self.BACnetServerNode.getOverride_Parameters_Saved_on_PLC()) loc_dict[ "network_interface"] = self.BACnetServerNode.getNetwork_Interface( ) loc_dict["port_number"] = self.BACnetServerNode.getUDP_Port_Number() loc_dict[ "BACnet_Device_ID"] = self.BACnetServerNode.getBACnet_Device_ID() loc_dict[ "BACnet_Device_Name"] = self.BACnetServerNode.getBACnet_Device_Name( ) loc_dict[ "BACnet_Comm_Control_Password"] = self.BACnetServerNode.getBACnet_Communication_Control_Password( ) loc_dict[ "BACnet_Device_Location"] = self.BACnetServerNode.getBACnet_Device_Location( ) loc_dict[ "BACnet_Device_Description"] = self.BACnetServerNode.getBACnet_Device_Description( ) loc_dict[ "BACnet_Device_AppSoft_Version"] = self.BACnetServerNode.getBACnet_Device_Application_Software_Version( ) loc_dict["BACnet_Vendor_ID"] = BACNET_VENDOR_ID loc_dict["BACnet_Vendor_Name"] = BACNET_VENDOR_NAME loc_dict["BACnet_Model_Name"] = BACNET_DEVICE_MODEL_NAME loc_dict["BACnet_Param_String_Size"] = BACNET_PARAM_STRING_SIZE # 2) Add the data specific to each BACnet object type # For each BACnet object type, start off by creating some intermediate helpful lists # a) parameters_list containing the strings that will # be included in the C source code, and which will initialize the struct with the # object (Analog Value, Binary Value, or Multi State Value) parameters # b) locatedvar_list containing the strings that will # declare the memory to store the located variables, as well as the # pointers (required by matiec) that point to that memory. # format for delaring IEC 61131-3 variable (and pointer) onto which # BACnet object is mapped locvar_format = '%(Ctype)s ___%(loc)s_%(Object Identifier)s; ' + \ '%(Ctype)s *__%(loc)s_%(Object Identifier)s = &___%(loc)s_%(Object Identifier)s;' # format for initializing a ANALOG_VALUE_DESCR struct in C code # also valid for ANALOG_INPUT and ANALOG_OUTPUT AX_params_format = '{&___%(loc)s_%(Object Identifier)s, ' + \ '%(Object Identifier)s, "%(Object Name)s", "%(Description)s", %(Unit ID)d}' # format for initializing a BINARY_VALUE_DESCR struct in C code # also valid for BINARY_INPUT and BINARY_OUTPUT BX_params_format = '{&___%(loc)s_%(Object Identifier)s, ' + \ '%(Object Identifier)s, "%(Object Name)s", "%(Description)s"}' # format for initializing a MULTISTATE_VALUE_DESCR struct in C code # also valid for MULTISTATE_INPUT and MULTISTATE_OUTPUT MSX_params_format = '{&___%(loc)s_%(Object Identifier)s, ' + \ '%(Object Identifier)s, "%(Object Name)s", "%(Description)s", %(Number of States)s}' # see the comment in GetVariableLocationTree() AV_locstr = 'MD' + locstr + '_2' AO_locstr = 'QD' + locstr + '_1' AI_locstr = 'ID' + locstr + '_0' BV_locstr = 'MX' + locstr + '_5' BO_locstr = 'QX' + locstr + '_4' BI_locstr = 'IX' + locstr + '_3' MSV_locstr = 'MB' + locstr + '_19' MSO_locstr = 'QB' + locstr + '_14' MSI_locstr = 'IB' + locstr + '_13' for ObjType, ObjLocStr, params_format in [ ("AV", AV_locstr, AX_params_format), ("AO", AO_locstr, AX_params_format), ("AI", AI_locstr, AX_params_format), ("BV", BV_locstr, BX_params_format), ("BO", BO_locstr, BX_params_format), ("BI", BI_locstr, BX_params_format), ("MSV", MSV_locstr, MSX_params_format), ("MSO", MSO_locstr, MSX_params_format), ("MSI", MSI_locstr, MSX_params_format) ]: parameters_list = [] locatedvar_list = [] self.ObjTables[ObjType + "_Obj"].UpdateAllVirtualProperties() for ObjProp in self.ObjTablesData[ObjType + "_Obj"]: ObjProp["loc"] = ObjLocStr parameters_list.append(params_format % ObjProp) locatedvar_list.append(locvar_format % ObjProp) loc_dict[ObjType + "_count"] = len(parameters_list) loc_dict[ObjType + "_param"] = ",\n".join(parameters_list) loc_dict[ObjType + "_lvars"] = "\n".join(locatedvar_list) # ---------------------------------------------------------------------- # Create the C source files that implement the BACnet server # ---------------------------------------------------------------------- # Names of the .c files that will be generated, based on a template file with same name # (names without '.c' --> this will be added later) # main server.c file is handled separately Generated_BACnet_c_mainfile = "server" Generated_BACnet_c_files = [ "ai", "ao", "av", "bi", "bo", "bv", "msi", "mso", "msv", "device" ] # Names of the .h files that will be generated, based on a template file with same name # (names without '.h' --> this will be added later) Generated_BACnet_h_files = [ "server", "device", "config_bacnet_for_beremiz", "ai", "ao", "av", "bi", "bo", "bv", "msi", "mso", "msv" ] # Generate the files with the source code postfix = "_".join(map(str, current_location)) template_file_dir = os.path.join(os.path.split(__file__)[0], "runtime") def generate_file(file_name, extension): generate_file_name = os.path.join( buildpath, "%s_%s.%s" % (file_name, postfix, extension)) template_file_name = os.path.join(template_file_dir, "%s.%s" % (file_name, extension)) generate_file_content = open(template_file_name).read() % loc_dict generate_file_handle = open(generate_file_name, 'w', encoding='utf-8') generate_file_handle.write(generate_file_content) generate_file_handle.close() for file_name in Generated_BACnet_c_files: generate_file(file_name, "c") for file_name in Generated_BACnet_h_files: generate_file(file_name, "h") generate_file(Generated_BACnet_c_mainfile, "c") Generated_BACnet_c_mainfile_name = \ os.path.join(buildpath, "%s_%s.%s" % (Generated_BACnet_c_mainfile, postfix, "c")) # ---------------------------------------------------------------------- # Finally, define the compilation and linking commands and flags # ---------------------------------------------------------------------- LDFLAGS = [] # when using dynamically linked library... # LDFLAGS.append(' -lbacnet') # LDFLAGS.append(' -L"'+BacnetLibraryPath+'"') # LDFLAGS.append(' "-Wl,-rpath,' + BacnetLibraryPath + '"') # when using static library: LDFLAGS.append(' "' + os.path.join(BacnetLibraryPath, "libbacnet.a") + '"') CFLAGS = ' -I"' + BacnetIncludePath + '"' CFLAGS += ' -I"' + BacnetIncludePortPath + '"' # ---------------------------------------------------------------------- # Create a file containing the default configuration paramters. # Beremiz will then transfer this file to the PLC, where the web server # will read it to obtain the default configuration parameters. # ---------------------------------------------------------------------- # NOTE: This is no loner needed! The web interface will read these # parameters directly from the compiled C code (.so file) # ### extra_file_name = os.path.join(buildpath, "%s_%s.%s" % ('bacnet_extrafile', postfix, 'txt')) ### extra_file_handle = open(extra_file_name, 'w') ### ### proplist = ["network_interface", "port_number", "BACnet_Device_ID", "BACnet_Device_Name", ### "BACnet_Comm_Control_Password", "BACnet_Device_Location", ### "BACnet_Device_Description", "BACnet_Device_AppSoft_Version"] ### for propname in proplist: ### extra_file_handle.write("%s:%s\n" % (propname, loc_dict[propname])) ### ### extra_file_handle.close() ### extra_file_handle = open(extra_file_name, 'r') # Format of data to return: # [(Cfiles, CFLAGS), ...], LDFLAGS, DoCalls, extra_files # LDFLAGS = ['flag1', 'flag2', ...] # DoCalls = true or false # extra_files = (fname,fobject), ... # fobject = file object, already open'ed for read() !! # # extra_files -> files that will be downloaded to the PLC! websettingfile = open( paths.AbsNeighbourFile(__file__, "web_settings.py"), 'r') websettingcode = websettingfile.read() websettingfile.close() location_str = "_".join(map(str, self.GetCurrentLocation())) websettingcode = websettingcode % locals() runtimefile_path = os.path.join(buildpath, "runtime_bacnet_websettings.py") runtimefile = open(runtimefile_path, 'w') runtimefile.write(websettingcode) runtimefile.close() return ( [(Generated_BACnet_c_mainfile_name, CFLAGS)], LDFLAGS, True, ['bacnet'], ("runtime_bacnet_websettings_%s.py" % location_str, open(runtimefile_path, "r", encoding='utf-8')), )
def CTNGenerate_C(self, buildpath, locations): # print "#############" # print self.__class__ # print type(self) # print "self.CTNType >>>" # print self.CTNType # print "type(self.CTNType) >>>" # print type(self.CTNType) # print "#############" loc_dict = {"locstr": "_".join(map(str, self.GetCurrentLocation()))} # Determine the number of (modbus library) nodes ALL instances of the modbus plugin will need # total_node_count: (tcp nodes, rtu nodes, ascii nodes) # # Also get a list with tuples of (location, IP address, port number) used by all the Modbus/IP server nodes # This list is later used to search for duplicates in port numbers! # IPServer_port_numbers = [(location, IP address, port number), ...] # location : tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x" # IPserver_port_number: a number (i.e. port number used by the Modbus/IP server) # IP address : IP address of the network interface on which the server will be listening # ("", "*", or "#ANY#" => listening on all interfaces!) # # Also get a list with tuples of (location, Configuration_Name) used by all the Modbus nodes # This list is later used to search for duplicates in Configuration Names! # Node_Configuration_Names = [(location, Configuration_Name), ...] # location : tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x" # Configuration_Name: the "Configuration_Name" string total_node_count = (0, 0, 0) IPServer_port_numbers = [] Node_Configuration_Names = [] for CTNInstance in self.GetCTRoot().IterChildren(): if CTNInstance.CTNType == "modbus": # ask each modbus plugin instance how many nodes it needs, and add them all up. total_node_count = tuple(x1 + x2 for x1, x2 in zip( total_node_count, CTNInstance.GetNodeCount())) IPServer_port_numbers.extend( CTNInstance.GetIPServerPortNumbers()) Node_Configuration_Names.extend(CTNInstance.GetConfigNames()) # Search for use of duplicate Configuration_Names by Modbus nodes # Configuration Names are used by the web server running on the PLC # (more precisely, run by Beremiz_service.py) to identify and allow # changing the Modbus parameters after the program has been downloaded # to the PLC (but before it is started) # With clashes in the configuration names, the Modbus nodes will not be # distinguasheble on the web interface! for i in range(0, len(Node_Configuration_Names) - 1): for j in range(i + 1, len(Node_Configuration_Names)): if Node_Configuration_Names[i][1] == Node_Configuration_Names[ j][1]: error_message = _( "Error: Modbus plugin nodes %{a1}.x and %{a2}.x use the same Configuration_Name \"{a3}\".\n" ).format(a1=_lt_to_str(Node_Configuration_Names[i][0]), a2=_lt_to_str(Node_Configuration_Names[j][0]), a3=Node_Configuration_Names[j][1]) self.FatalError(error_message) # Search for use of duplicate port numbers by Modbus/IP servers # Note: We only consider duplicate port numbers if using the same network interface! i = 0 for loc1, addr1, port1 in IPServer_port_numbers[:-1]: i = i + 1 for loc2, addr2, port2 in IPServer_port_numbers[i:]: if (port1 == port2) and ( (addr1 == addr2) # on the same network interface or (addr1 == "") or (addr1 == "*") or (addr1 == "#ANY#") # or one (or both) of the servers or (addr2 == "") or (addr2 == "*") or (addr2 == "#ANY#") # use all available network interfaces ): error_message = _( "Error: Modbus plugin nodes %{a1}.x and %{a2}.x use same port number \"{a3}\" " + "on the same (or overlapping) network interfaces \"{a4}\" and \"{a5}\".\n" ).format(a1=_lt_to_str(loc1), a2=_lt_to_str(loc2), a3=port1, a4=addr1, a5=addr2) self.FatalError(error_message) # Determine the current location in Beremiz's project configuration # tree current_location = self.GetCurrentLocation() # define a unique name for the generated C and h files prefix = "_".join(map(str, current_location)) Gen_MB_c_path = os.path.join(buildpath, "MB_%s.c" % prefix) Gen_MB_h_path = os.path.join(buildpath, "MB_%s.h" % prefix) c_filename = os.path.join(os.path.split(__file__)[0], "mb_runtime.c") h_filename = os.path.join(os.path.split(__file__)[0], "mb_runtime.h") tcpclient_reqs_count = 0 rtuclient_reqs_count = 0 ascclient_reqs_count = 0 tcpclient_node_count = 0 rtuclient_node_count = 0 ascclient_node_count = 0 tcpserver_node_count = 0 rtuserver_node_count = 0 ascserver_node_count = 0 nodeid = 0 client_nodeid = 0 client_requestid = 0 server_id = 0 server_node_list = [] client_node_list = [] client_request_list = [] server_memarea_list = [] loc_vars = [] loc_vars_list = [] # list of variables already declared in C code! for child in self.IECSortedChildren(): # print "<<<<<<<<<<<<<" # print "child (self.IECSortedChildren())----->" # print child.__class__ # print ">>>>>>>>>>>>>" # if child.PlugType == "ModbusTCPserver": tcpserver_node_count += 1 new_node = GetTCPServerNodePrinted(self, child) if new_node is None: return [], "", False server_node_list.append(new_node) # for subchild in child.IECSortedChildren(): new_memarea = GetTCPServerMemAreaPrinted( self, subchild, nodeid) if new_memarea is None: return [], "", False server_memarea_list.append(new_memarea) function = subchild.GetParamsAttributes( )[0]["children"][0]["value"] # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words' memarea = modbus_memtype_dict[function][1] for iecvar in subchild.GetLocations(): # print repr(iecvar) absloute_address = iecvar["LOC"][3] start_address = int(GetCTVal(subchild, 2)) relative_addr = absloute_address - start_address # test if relative address in request specified range if relative_addr in xrange(int(GetCTVal(subchild, 1))): if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address)) loc_vars_list.append(str(iecvar["NAME"])) server_id += 1 # if child.PlugType == "ModbusRTUslave": rtuserver_node_count += 1 new_node = GetRTUSlaveNodePrinted(self, child) if new_node is None: return [], "", False server_node_list.append(new_node) # for subchild in child.IECSortedChildren(): new_memarea = GetTCPServerMemAreaPrinted( self, subchild, nodeid) if new_memarea is None: return [], "", False server_memarea_list.append(new_memarea) function = subchild.GetParamsAttributes( )[0]["children"][0]["value"] # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words' memarea = modbus_memtype_dict[function][1] for iecvar in subchild.GetLocations(): # print repr(iecvar) absloute_address = iecvar["LOC"][3] start_address = int(GetCTVal(subchild, 2)) relative_addr = absloute_address - start_address # test if relative address in request specified range if relative_addr in xrange(int(GetCTVal(subchild, 1))): if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address)) loc_vars_list.append(str(iecvar["NAME"])) server_id += 1 # if child.PlugType == "ModbusTCPclient": tcpclient_reqs_count += len(child.IECSortedChildren()) new_node = GetTCPClientNodePrinted(self, child) if new_node is None: return [], "", False client_node_list.append(new_node) for subchild in child.IECSortedChildren(): new_req = GetClientRequestPrinted(self, subchild, client_nodeid) if new_req is None: return [], "", False client_request_list.append(new_req) for iecvar in subchild.GetLocations(): # absloute address - start address relative_addr = iecvar["LOC"][3] - int( GetCTVal(subchild, 3)) # test if the located variable # (a) has relative address in request specified range # AND is NOT # (b) is a control flag added by this modbus plugin # to control its execution at runtime. # Currently, we only add the "Execution Control Flag" # to each client request (one flag per request) # to control when to execute the request (if not executed periodically) # While all Modbus registers/coils are mapped onto a location # with 4 numbers (e.g. %QX0.1.2.55), this control flag is mapped # onto a location with 4 numbers (e.g. %QX0.1.2.0.0), where the last # two numbers are always '0.0', and the first two identify the request. # In the following if, we check for this condition by checking # if their are at least 4 or more number in the location's address. if (relative_addr in xrange(int(GetCTVal( subchild, 2))) # condition (a) explained above and len(iecvar["LOC"]) < 5): # condition (b) explained above if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) loc_vars_list.append(str(iecvar["NAME"])) # Now add the located variable in case it is a flag (condition (b) above if len(iecvar["LOC"] ) >= 5: # condition (b) explained above if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].flag_exec_req;" % (client_requestid)) loc_vars_list.append(str(iecvar["NAME"])) client_requestid += 1 tcpclient_node_count += 1 client_nodeid += 1 # if child.PlugType == "ModbusRTUclient": rtuclient_reqs_count += len(child.IECSortedChildren()) new_node = GetRTUClientNodePrinted(self, child) if new_node is None: return [], "", False client_node_list.append(new_node) for subchild in child.IECSortedChildren(): new_req = GetClientRequestPrinted(self, subchild, client_nodeid) if new_req is None: return [], "", False client_request_list.append(new_req) for iecvar in subchild.GetLocations(): # absloute address - start address relative_addr = iecvar["LOC"][3] - int( GetCTVal(subchild, 3)) # test if the located variable # (a) has relative address in request specified range # AND is NOT # (b) is a control flag added by this modbus plugin # to control its execution at runtime. # Currently, we only add the "Execution Control Flag" # to each client request (one flag per request) # to control when to execute the request (if not executed periodically) # While all Modbus registers/coils are mapped onto a location # with 4 numbers (e.g. %QX0.1.2.55), this control flag is mapped # onto a location with 4 numbers (e.g. %QX0.1.2.0.0), where the last # two numbers are always '0.0', and the first two identify the request. # In the following if, we check for this condition by checking # if their are at least 4 or more number in the location's address. if (relative_addr in xrange(int(GetCTVal( subchild, 2))) # condition (a) explained above and len(iecvar["LOC"]) < 5): # condition (b) explained above if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) loc_vars_list.append(str(iecvar["NAME"])) # Now add the located variable in case it is a flag (condition (b) above if len(iecvar["LOC"] ) >= 5: # condition (b) explained above if str(iecvar["NAME"]) not in loc_vars_list: loc_vars.append( "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].flag_exec_req;" % (client_requestid)) loc_vars_list.append(str(iecvar["NAME"])) client_requestid += 1 rtuclient_node_count += 1 client_nodeid += 1 nodeid += 1 loc_dict["loc_vars"] = "\n".join(loc_vars) loc_dict["server_nodes_params"] = ",\n\n".join(server_node_list) loc_dict["client_nodes_params"] = ",\n\n".join(client_node_list) loc_dict["client_req_params"] = ",\n\n".join(client_request_list) loc_dict["tcpclient_reqs_count"] = str(tcpclient_reqs_count) loc_dict["tcpclient_node_count"] = str(tcpclient_node_count) loc_dict["tcpserver_node_count"] = str(tcpserver_node_count) loc_dict["rtuclient_reqs_count"] = str(rtuclient_reqs_count) loc_dict["rtuclient_node_count"] = str(rtuclient_node_count) loc_dict["rtuserver_node_count"] = str(rtuserver_node_count) loc_dict["ascclient_reqs_count"] = str(ascclient_reqs_count) loc_dict["ascclient_node_count"] = str(ascclient_node_count) loc_dict["ascserver_node_count"] = str(ascserver_node_count) loc_dict["total_tcpnode_count"] = str(total_node_count[0]) loc_dict["total_rtunode_count"] = str(total_node_count[1]) loc_dict["total_ascnode_count"] = str(total_node_count[2]) loc_dict["max_remote_tcpclient"] = int( self.GetParamsAttributes()[0]["children"][0]["value"]) # get template file content into a string, format it with dict # and write it to proper .h file mb_main = open(h_filename).read() % loc_dict f = open(Gen_MB_h_path, 'w') f.write(mb_main) f.close() # same thing as above, but now to .c file mb_main = open(c_filename).read() % loc_dict f = open(Gen_MB_c_path, 'w') f.write(mb_main) f.close() LDFLAGS = [] LDFLAGS.append(" \"-L" + ModbusPath + "\"") LDFLAGS.append(" \"" + os.path.join(ModbusPath, "libmb.a") + "\"") LDFLAGS.append(" \"-Wl,-rpath," + ModbusPath + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave_and_master.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_master.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_tcp.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_rtu.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_ascii.o") + "\"") # LDFLAGS.append("\"" + os.path.join(ModbusPath, "sin_util.o") + "\"") # Target is ARM with linux and not win on x86 so winsock2 (ws2_32) library is useless !!! # if os.name == 'nt': # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos' # LDFLAGS.append(" -lws2_32 ") # on windows we need to load winsock # library! websettingfile = open( paths.AbsNeighbourFile(__file__, "web_settings.py"), 'r') websettingcode = websettingfile.read() websettingfile.close() location_str = "_".join(map(str, self.GetCurrentLocation())) websettingcode = websettingcode % locals() runtimefile_path = os.path.join(buildpath, "runtime_modbus_websettings.py") runtimefile = open(runtimefile_path, 'w') runtimefile.write(websettingcode) runtimefile.close() return ( [(Gen_MB_c_path, ' -I"' + ModbusPath + '"')], LDFLAGS, True, ("runtime_modbus_websettings_%s.py" % location_str, open(runtimefile_path, "rb")), )
def CTNGenerate_C(self, buildpath, locations): can_driver = self.GetCanDriver() if can_driver is not None: can_drivers = local_canfestival_config.DLL_LIST if can_driver not in can_drivers: can_driver = can_drivers[0] can_drv_ext = self.GetCTRoot().GetBuilder().extension can_drv_prefix = self.GetCTRoot().GetBuilder().dlopen_prefix can_driver_name = can_drv_prefix + "libcanfestival_" + can_driver + can_drv_ext else: can_driver_name = "" format_dict = { "locstr": "_".join(map(str, self.GetCurrentLocation())), "candriver": can_driver_name, "nodes_includes": "", "board_decls": "", "nodes_init": "", "nodes_open": "", "nodes_stop": "", "nodes_close": "", "nodes_send_sync": "", "nodes_proceed_sync": "", "slavebootups": "", "slavebootup_register": "", "post_sync": "", "post_sync_register": "", "pre_op": "", "pre_op_register": "", } for child in self.IECSortedChildren(): childlocstr = "_".join(map(str, child.GetCurrentLocation())) nodename = "OD_%s" % childlocstr # Try to get Slave Node child_data = getattr(child, "CanFestivalSlaveNode", None) if child_data is None: # Not a slave -> master child_data = getattr(child, "CanFestivalNode") # Apply sync setting format_dict[ "nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n ' % ( nodename, child_data.getNodeId()) if child_data.getSync_TPDOs(): format_dict[ "nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n ' % ( nodename) format_dict[ "nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n ' % ( nodename) # initialize and declare node boot status variables for post_SlaveBootup lookup SlaveIDs = child.GetSlaveIDs() if len(SlaveIDs) == 0: # define post_SlaveBootup lookup functions format_dict["slavebootups"] += ( "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n" % (nodename)) else: format_dict["slavebootups"] += ( "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n" % (nodename) + " check_and_start_node(d, nodeId);\n" + "}\n") # register previously declared func as post_SlaveBootup callback for that node format_dict["slavebootup_register"] += ( "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n" % (nodename, nodename)) format_dict["pre_op"] += ( "static void %s_preOperational(CO_Data* d){\n " % (nodename) + "".join([ " masterSendNMTstateChange(d, %d, NMT_Reset_Comunication);\n" % NdId for NdId in SlaveIDs ]) + "}\n") format_dict["pre_op_register"] += ( "%s_Data.preOperational = %s_preOperational;\n" % (nodename, nodename)) else: # Slave node align = child_data.getSync_Align() align_ratio = child_data.getSync_Align_Ratio() if align > 0: format_dict["post_sync"] += ( "static int %s_CalCount = 0;\n" % (nodename) + "static void %s_post_sync(CO_Data* d){\n" % (nodename) + " if(%s_CalCount < %d){\n" % (nodename, align) + " %s_CalCount++;\n" % (nodename) + " align_tick(-1);\n" + " }else{\n" + " align_tick(%d);\n" % (align_ratio) + " }\n" + "}\n") format_dict["post_sync_register"] += ( "%s_Data.post_sync = %s_post_sync;\n" % (nodename, nodename)) format_dict[ "nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n ' % ( nodename, child_data.getNodeId()) # Include generated OD headers format_dict["nodes_includes"] += '#include "%s.h"\n' % (nodename) # Declare CAN channels according user filled config format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n' % ( nodename, child.GetCanDevice(), child_data.getCAN_Baudrate()) format_dict["nodes_open"] += 'NODE_OPEN(%s)\n ' % (nodename) format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n ' % (nodename) format_dict["nodes_stop"] += 'NODE_STOP(%s)\n ' % (nodename) filename = paths.AbsNeighbourFile(__file__, "cf_runtime.c") cf_main = open(filename).read() % format_dict cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c" % format_dict) f = open(cf_main_path, 'w') f.write(cf_main) f.close() res = [ (cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath)) ], local_canfestival_config.getLDFLAGS(CanFestivalPath), True if can_driver is not None: can_driver_path = os.path.join(CanFestivalPath, "drivers", can_driver, can_driver_name) if os.path.exists(can_driver_path): res += ((can_driver_name, file(can_driver_path, "rb")), ) return res
def _getSVGUIserverpath(self): return paths.AbsNeighbourFile(__file__, "svgui_server.py")
def __init__(self, plcState=False, *a, **kw): super(WebInterface, self).__init__(*a, **kw) self.jsModules.mapping[u'WebInterface'] = paths.AbsNeighbourFile(__file__), 'webinterface.js') self.plcState = plcState self.MainPage.setPLCState(plcState)
def GetLibraryPath(self): return paths.AbsNeighbourFile(__file__, "NativeLib.xml")
class SettingsPage(rend.Page): # We deserve a slash addSlash = True # This makes webform_css url answer some default CSS child_webform_css = webform.defaultCSS child_webinterface_css = File( paths.AbsNeighbourFile(__file__, 'webinterface.css'), 'text/css') implements(ISettings) def __getattr__(self, name): global extensions_settings_od if name.startswith('configurable_'): token = name[13:] def configurable_something(ctx): settings, _display = extensions_settings_od[token] return settings return configurable_something raise AttributeError def extensions_settings(self, context, data): """ Project extensions settings Extensions added to Configuration Tree in IDE have their setting rendered here """ global extensions_settings_od res = [] for token in extensions_settings_od: _settings, display = extensions_settings_od[token] res += [tags.h2[display], webform.renderForms(token)] return res docFactory = loaders.stan([ tags.html[ tags.head[tags.title[_("Beremiz Runtime Settings")], tags.link(rel='stylesheet', type='text/css', href=url.here.child("webform_css")), tags.link(rel='stylesheet', type='text/css', href=url.here.child("webinterface_css"))], tags.body[tags.a(href='/')['Back'], tags.h1["Runtime settings:"], webform.renderForms('staticSettings'), tags.h1["Extensions settings:"], webform.renderForms('dynamicSettings'), extensions_settings]] ]) def configurable_staticSettings(self, ctx): return configurable.TypedInterfaceConfigurable(self) def configurable_dynamicSettings(self, ctx): """ Runtime Extensions settings Extensions loaded through Beremiz_service -e or optional runtime features render setting forms here """ return ConfigurableSettings def sendLogMessage(self, level, message, **kwargs): level = LogLevelsDict[level] if _PySrv.plcobj is not None: _PySrv.plcobj.LogMessage(level, "Web form log message: " + message) def locateChild(self, ctx, segments): if segments[0] in customSettingsURLs: return customSettingsURLs[segments[0]](ctx, segments) return super(SettingsPage, self).locateChild(ctx, segments)
# -*- coding: utf-8 -*- # This file is part of Beremiz, a Integrated Development Environment for # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. # # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD # Copyright (C) 2017: Andrey Skvortsov # # See COPYING file for copyrights details. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from __future__ import absolute_import import util.paths as paths from POULibrary import SimplePOULibraryFactory NativeLibrary = SimplePOULibraryFactory( paths.AbsNeighbourFile(__file__, "NativeLib.xml"))