### Example Absolute Page Label Source: https://github.com/beremiz/beremiz/blob/python3/doc/svghmi/pages.md An example demonstrating how to specify an absolute page path. ```default HMI:Page:PumpControl@/PUMP0 ``` -------------------------------- ### Setup Python Virtual Environment and Install Packages Source: https://github.com/beremiz/beremiz/blob/python3/README.md Creates an isolated Python environment using virtualenv and installs the required Python packages listed in Beremiz's requirements.txt. This ensures dependency management. ```bash # setup isolated python environment virtualenv ~/Beremiz/venv # install required python packages ~/Beremiz/venv/bin/pip install -r ~/Beremiz/beremiz/requirements.txt ``` -------------------------------- ### Install System Packages (Ubuntu 22.04) Source: https://github.com/beremiz/beremiz/blob/python3/README.md Installs essential system packages required for building Beremiz on Ubuntu 22.04. Run these commands as root. ```bash sudo apt-get install \ build-essential automake flex bison \ libgtk-3-dev libgl1-mesa-dev libglu1-mesa-dev \ libpython3.10-dev libssl-dev \ python3.10 virtualenv cmake git ``` -------------------------------- ### Install Sphinx and Build Tools Source: https://github.com/beremiz/beremiz/blob/python3/README.md Install necessary packages on Ubuntu/Debian to build documentation using Sphinx. This includes essential build tools and the Sphinx library. ```bash sudo apt-get install build-essential python-sphynx ``` -------------------------------- ### Create and Start eRPC Server Source: https://context7.com/beremiz/beremiz/llms.txt Initializes and starts an eRPC server in a background thread. Ensure the server is ready before proceeding by using a lock. ```python server = eRPCServer( servicename="MyPLC", # Service name for discovery (None to disable) ip_addr="0.0.0.0", # Interface to bind ('' for all) port=3000 # Port number ) # Start server in background thread ready_lock = Lock() ready_lock.acquire() def start_server(): server.Loop(when_ready=ready_lock.release) server_thread = Thread(target=start_server, name="eRPCThread") server_thread.start() # Wait for server to be ready ready_lock.acquire() print("eRPC server is running") # Server provides these methods to connected clients: # - GetPLCstatus() -> (status, log_counts) # - StartPLC() -> success # - StopPLC() -> success # - NewPLC(md5, blob_id, extra_files) -> success # - MatchMD5(md5) -> matches # - GetLogMessage(level, msgid) -> (msg, tick, sec, nsec) # - SetTraceVariablesList(orders) -> success # - GetTraceVariables() -> (status, samples) # - SeedBlob(data) -> blob_id # - AppendChunkToBlob(data, blob_id) -> new_blob_id # - ResetLogCount() # - GetPLCID() -> (id, psk) # - ExtendedCall(method, args) -> result # Graceful shutdown server.Quit() server_thread.join() ``` -------------------------------- ### Python Extension Database Logging Example Source: https://context7.com/beremiz/beremiz/llms.txt An example of a Python extension that logs PLC data to an SQLite database. It demonstrates using OnStart for setup, Periodic for data insertion, and OnStop for cleanup. ```python # Example: Database logging import sqlite3 db_conn = None def OnStart(): global db_conn db_conn = sqlite3.connect('/var/log/plc_data.db') db_conn.execute(''' CREATE TABLE IF NOT EXISTS readings ( timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, temperature REAL, pressure REAL ) ''') def Periodic(): if db_conn: db_conn.execute( 'INSERT INTO readings (temperature, pressure) VALUES (?, ?)', (PLCGlobals.Temperature, PLCGlobals.Pressure) ) db_conn.commit() def OnStop(): if db_conn: db_conn.close() ``` -------------------------------- ### Beremiz Service Setup Source: https://context7.com/beremiz/beremiz/llms.txt Command to run the Beremiz service in production mode with specified parameters. ```APIDOC ## Beremiz Service Setup ### Description This command initiates the Beremiz service for production use, configuring network interfaces, ports, and working directories. ### Command ```bash python Beremiz_service.py -n "ProductionPLC" -i 0.0.0.0 -p 3000 -a 1 -x 0 -w 8009 -v /var/lib/beremiz/workdir ``` ### Parameters - **-n** (string) - Service name (e.g., "ProductionPLC") - **-i** (string) - IP address to bind to (e.g., "0.0.0.0") - **-p** (integer) - Port number for the service (e.g., 3000) - **-a** (integer) - Argument for the service (e.g., 1) - **-x** (integer) - Another argument for the service (e.g., 0) - **-w** (integer) - Workspace port (e.g., 8009) - **-v** - Verbose mode - **[WORKDIR]** (string) - Path to the working directory (e.g., "/var/lib/beremiz/workdir") ``` -------------------------------- ### Example Relative Jump Label Source: https://github.com/beremiz/beremiz/blob/python3/doc/svghmi/pages.md An example of using HMI:Jump with a relative path. ```default HMI:Jump:PumpControl@/PUMP7 ``` -------------------------------- ### Start Standalone Beremiz Service Source: https://github.com/beremiz/beremiz/blob/python3/README.md Use this command to start the Beremiz service in standalone mode. Ensure you create a working directory first. The service listens on the specified port. ```bash mkdir ~/beremiz_runtime_workdir ~/Beremiz/venv/bin/python ~/Beremiz/beremiz/Beremiz_service.py -p 61194 -i localhost -x 0 -a 1 ~/beremiz_runtime_workdir ``` -------------------------------- ### Build CanFestival (Optional) Source: https://github.com/beremiz/beremiz/blob/python3/README.md Builds the CanFestival library, which is required for CANopen support. This example configures it with a virtual CAN interface. Refer to the CanFestival manual for other interface options. ```bash cd ~/Beremiz git clone https://github.com/beremiz/canfestival cd ~/Beremiz/canfestival ./configure --can=virtual make ``` -------------------------------- ### Install LaTeX Packages for PDF Build Source: https://github.com/beremiz/beremiz/blob/python3/README.md Install additional LaTeX packages required for building PDF documentation on Ubuntu/Debian. These packages provide the necessary LaTeX components. ```bash sudo apt-get install textlive-latex-base texlive-latex-recommended \ texlive-fonts-recommended texlive-latex-extra ``` -------------------------------- ### Run Beremiz Service in Production Source: https://context7.com/beremiz/beremiz/llms.txt Command to start the Beremiz service in a production environment with specified parameters and working directory. ```bash python Beremiz_service.py \ -n "ProductionPLC" \ -i 0.0.0.0 \ -p 3000 \ -a 1 \ -x 0 \ -w 8009 \ -v \ /var/lib/beremiz/workdir ``` -------------------------------- ### Launch Beremiz IDE Source: https://github.com/beremiz/beremiz/blob/python3/README.md Starts the Beremiz Integrated Development Environment using the Python runtime from the virtual environment. This command should be executed after all build steps are completed. ```bash ~/Beremiz/venv/bin/python ~/Beremiz/beremiz/Beremiz.py ``` -------------------------------- ### Start Beremiz PLC Runtime Service Source: https://context7.com/beremiz/beremiz/llms.txt Starts the Beremiz runtime service for executing PLC programs. Supports configuration of network interfaces, ports, service discovery, autostart, headless mode, web interface, WAMP client, security, extensions, and event commands. ```bash python Beremiz_service.py ~/plc_workdir ``` ```bash python Beremiz_service.py -i 192.168.1.100 -p 61194 ~/plc_workdir ``` ```bash python Beremiz_service.py -n "MyPLCRuntime" -i 192.168.1.100 -p 61194 ~/plc_workdir ``` ```bash python Beremiz_service.py -a 1 ~/plc_workdir ``` ```bash python Beremiz_service.py -x 0 ~/plc_workdir ``` ```bash python Beremiz_service.py -w 8080 ~/plc_workdir ``` ```bash python Beremiz_service.py -w off ~/plc_workdir ``` ```bash python Beremiz_service.py -c /path/to/wampconf.json ~/plc_workdir ``` ```bash python Beremiz_service.py -s /path/to/psk_secrets ~/plc_workdir ``` ```bash python Beremiz_service.py -e /path/to/extension.py ~/plc_workdir ``` ```bash python Beremiz_service.py --on-plc-start "notify-send 'PLC Started'" \ --on-plc-stop "notify-send 'PLC Stopped'" ~/plc_workdir ``` ```bash python Beremiz_service.py --status-change "logger 'PLC status: {}'" ~/plc_workdir ``` -------------------------------- ### Get Source Code (Git) Source: https://github.com/beremiz/beremiz/blob/python3/README.md Clones the Beremiz and MatIEC repositories from GitHub into the prepared build directory. This fetches the necessary source files for compilation. ```bash cd ~/Beremiz git clone https://github.com/beremiz/beremiz git clone https://github.com/beremiz/matiec ``` -------------------------------- ### List Available PSK Ciphers (Server) Source: https://github.com/beremiz/beremiz/blob/python3/doc/programming/connect.md Lists the PSK ciphers available in the server's OpenSSL installation for TLSv1.2. This helps in verifying compatibility with the client. ```bash openssl ciphers -s -psk -tls1_2 ``` -------------------------------- ### C Extension Example for Beremiz Source: https://context7.com/beremiz/beremiz/llms.txt This C code defines functions for initializing, cleaning up, retrieving data, publishing data, and performing custom calculations within a Beremiz PLC environment. It demonstrates how to interact with IEC variables and external hardware. ```c /* c_ext C extension file */ /* C extensions execute synchronously within the PLC scan cycle */ #include "iec_std_lib.h" /* Declare external variables (mapped to IEC locations) */ extern __IEC_INT_t *__IX0_0; /* Input at %IX0.0 */ extern __IEC_INT_t *__QX0_0; /* Output at %QX0.0 */ extern __IEC_DINT_t *__MD100; /* Memory at %MD100 */ /* Initialize function - called once at PLC start */ void __init_my_extension(void) { /* Hardware initialization code */ printf("C Extension initialized\n"); } /* Cleanup function - called at PLC stop */ void __cleanup_my_extension(void) { /* Cleanup code */ printf("C Extension cleanup\n"); } /* Periodic function - called every scan cycle */ void __retrieve_my_extension(void) { /* Read inputs from hardware */ /* Example: Read GPIO state */ // *__IX0_0 = read_gpio(0); } void __publish_my_extension(void) { /* Write outputs to hardware */ /* Example: Write GPIO state */ // write_gpio(0, *__QX0_0); } /* Custom function callable from IEC code */ DINT custom_calculation(DINT input1, DINT input2) { /* Perform hardware-accelerated or optimized calculation */ return input1 * input2 + 42; } ``` -------------------------------- ### SVGHMI Widget Example Source: https://context7.com/beremiz/beremiz/llms.txt This SVG file demonstrates various SVGHMI widgets for creating interactive web-based HMIs. Widgets are defined using specific 'inkscape:label' attributes. ```xml 0.00 Enter value START Overview ``` -------------------------------- ### Build HTML Documentation Source: https://github.com/beremiz/beremiz/blob/python3/README.md Navigate to the documentation directory and run 'make all' to build the HTML version of the documentation. The output will be in the 'doc/_build/dirhtml*' directories. ```bash cd ~/Beremiz/doc make all ``` -------------------------------- ### Initialize and Build PLC Project with ProjectController Source: https://context7.com/beremiz/beremiz/llms.txt Demonstrates initializing ProjectController, loading projects, configuring target platforms, and performing build, connect, transfer, and run operations. ```python from ProjectController import ProjectController import wx # Initialize with wxPython app context app = wx.App() frame = wx.Frame(None) # Create project controller project = ProjectController() # Load a project error_msg, error = project.LoadProject("/path/to/project") if not error: print("Project loaded successfully") else: print(f"Error: {error_msg}") # Get project name and path print(f"Project: {project.GetProjectName()}") print(f"Path: {project.ProjectPath}") # Configure target platform # Available targets: Linux, Win32, Xenomai, Generic project.SetParamsAttribute("BeremizRoot.TargetType", "Linux") # Set URI for runtime connection project.SetParamsAttribute("BeremizRoot.URI_location", "ERPC://192.168.1.100:3000") # Build the project # Returns True on success, False on failure success = project._Build() if success: print("Build completed successfully") # Connect to runtime connected = project._Connect() if connected: # Transfer program to PLC transferred = project._Transfer() if transferred: # Start PLC execution project._Run() # Get PLC status status = project.GetPLCstatus() print(f"PLC Status: {status}") # Stop PLC project._Stop() # Disconnect from runtime project._Disconnect() # Clean build artifacts project._Clean() # Get available configuration tree nodes children_types = project.CTNChildrenTypes for name, importer, display_name in children_types: print(f"Extension: {display_name} ({name})") # Add extension node (e.g., Modbus support) modbus_node = project.CTNAddChild("modbus_0", "modbus") # Get all configuration nodes def print_tree(node, indent=0): print(" " * indent + node.CTNName()) for child in node.IECSortedChildren(): print_tree(child, indent + 2) print_tree(project) ``` -------------------------------- ### Initialize and Manage PLC Project with PLCControler Source: https://context7.com/beremiz/beremiz/llms.txt Demonstrates initializing PLCControler, creating, saving, and loading PLC projects. Includes POU management and variable addition. ```python from PLCControler import PLCControler # Initialize controller controller = PLCControler() # Create a new project with properties project_properties = { "projectName": "MyAutomationProject", "companyName": "MyCompany", "productName": "ProductLine1", "productVersion": "1.0", "authorName": "Engineer" } controller.CreateNewProject(project_properties) # Check if project is opened if controller.HasOpenedProject(): print("Project is ready") # Get the current project object project = controller.GetProject() # Save project to file controller.SaveXMLFile("/path/to/project/plc.xml") # Load existing project result = controller.OpenXMLFile("/path/to/project/plc.xml") if result is None: print("Project loaded successfully") # Get list of POUs (Program Organization Units) pou_list = controller.GetProjectPouList() for pou_name, pou_type in pou_list: print(f"POU: {pou_name}, Type: {pou_type}") # Add a new Program POU controller.ProjectAddPou("MainProgram", "program", "ST") # Add a Function Block controller.ProjectAddPou("MotorControl", "functionBlock", "FBD") # Add a Function controller.ProjectAddPou("CalculateSpeed", "function", "ST") # Get POU body content pou_body = controller.GetEditedElementText("MainProgram", debug=False) # Set POU body content (Structured Text) st_code = """ (* Main control loop *) IF StartButton AND NOT Emergency THEN MotorRunning := TRUE; Speed := CalculateSpeed(SetPoint, Feedback); END_IF; IF StopButton OR Emergency THEN MotorRunning := FALSE; Speed := 0; END_IF; """ controller.SetEditedElementText("MainProgram", st_code) # Add variables to a POU variables = [ {"Name": "StartButton", "Type": "BOOL", "Class": "Input"}, {"Name": "StopButton", "Type": "BOOL", "Class": "Input"}, {"Name": "Emergency", "Type": "BOOL", "Class": "Input"}, {"Name": "MotorRunning", "Type": "BOOL", "Class": "Output"}, {"Name": "Speed", "Type": "REAL", "Class": "Output"}, {"Name": "SetPoint", "Type": "REAL", "Class": "Local"}, {"Name": "Feedback", "Type": "REAL", "Class": "Local"} ] for var in variables: controller.AddEditedElementPouVar( "MainProgram", var["Type"], var["Name"], location="", description="" ) # Get qualifier types for action blocks qualifiers = controller.GetQualifierTypes() # Returns: OrderedDict([('N', False), ('R', False), ('S', False), ...]) # Undo/Redo operations controller.LoadPrevious() # Undo controller.LoadNext() # Redo ``` -------------------------------- ### Prepare Build Directory Source: https://github.com/beremiz/beremiz/blob/python3/README.md Creates and navigates to the directory where Beremiz source code and build artifacts will be stored. This sets up the workspace for subsequent commands. ```bash mkdir ~/Beremiz cd ~/Beremiz ``` -------------------------------- ### Build PDF Documentation Source: https://github.com/beremiz/beremiz/blob/python3/README.md Navigate to the documentation directory and run 'make latexpdf' to build the PDF version of the documentation. The output file will be 'doc/_build/latex/Beremiz.pdf'. ```bash cd ~/Beremiz/doc make latexpdf ``` -------------------------------- ### Initialize eRPC Server Source: https://context7.com/beremiz/beremiz/llms.txt Sets up the eRPC server for runtime communication. Ensure the PLC object is initialized first. ```python from runtime.eRPCServer import eRPCServer from runtime import CreatePLCObjectSingleton from threading import Thread, Lock # Initialize PLC object first CreatePLCObjectSingleton( WorkingDir="/var/lib/beremiz", argv=[], statuschange=[], evaluator=lambda f, *a, **k: (f(*a, **k), None), pyruntimevars={} ) ``` -------------------------------- ### Display SVG Image via HTTP GET Path Source: https://github.com/beremiz/beremiz/blob/python3/doc/svghmi/widgets.md Use HMI:Image:variable where 'variable' is the HTTP GET path to the image. This widget displays an SVG image dynamically. ```text HMI:Image:variable ``` -------------------------------- ### Launch Stunnel Server Source: https://github.com/beremiz/beremiz/blob/python3/doc/programming/connect.md Command to launch the Stunnel service with the specified configuration file. This command should be run on the server (runtime) side. ```bash stunnel ./stunnel.conf ``` -------------------------------- ### Modbus Data Access in Structured Text Source: https://context7.com/beremiz/beremiz/llms.txt Example of accessing Modbus data (registers and coils) and controlling Modbus requests within IEC 61131-3 Structured Text. ```iecst (* Modbus variable mapping example *) (* %QW = Output Word, %IW = Input Word *) (* Location format: %[I/Q][X/B/W/D].node.request.channel *) VAR (* Read from Modbus slave holding registers *) Temperature AT %IW1.0.0 : INT; (* Channel 0 *) Pressure AT %IW1.0.1 : INT; (* Channel 1 *) FlowRate AT %IW1.0.2 : INT; (* Channel 2 *) (* Write to Modbus slave registers *) SetPoint AT %QW1.1.0 : INT; (* Channel 0 *) ControlMode AT %QW1.1.1 : INT; (* Channel 1 *) (* Read coil status *) SensorActive AT %IX1.2.0 : BOOL; (* Coil 0 *) AlarmStatus AT %IX1.2.1 : BOOL; (* Coil 1 *) (* Modbus request control *) ExecuteRead AT %QX1.0.0.0 : BOOL; (* Trigger read request *) RequestStatus AT %IB1.0.0.1 : BYTE; (* 0=OK, 1=Error, 3=Timeout *) END_VAR (* Control logic *) IF ExecuteRead THEN (* Process received data *) IF RequestStatus = 0 THEN CurrentTemp := Temperature; CurrentPressure := Pressure; END_IF; END_IF; SetPoint := DesiredTemperature * 10; (* Scale for transmission *) ``` -------------------------------- ### Launch Beremiz IDE Source: https://context7.com/beremiz/beremiz/llms.txt Launches the Beremiz IDE with various options for project management, development mode, SDK selection, updates, extensions, and logging. ```bash python Beremiz.py ``` ```bash python Beremiz.py /path/to/project ``` ```bash python Beremiz.py /path/to/project /path/to/builddir ``` ```bash python Beremiz.py --devmode ``` ```bash python Beremiz.py --plcsdkselector ``` ```bash python Beremiz.py --sdkpath /path/to/sdk ``` ```bash python Beremiz.py --updatecheck https://updates.example.com/version.json ``` ```bash python Beremiz.py --extend /path/to/extension.py ``` ```bash python Beremiz.py --log /path/to/logfile.txt ``` -------------------------------- ### Pulse Timer Functionality Source: https://github.com/beremiz/beremiz/blob/python3/doc/programming/stdlib/index.md Generates an output pulse of a specified duration when a rising edge is detected on the input. The timer is not re-triggerable once started. The ET output shows the elapsed time. ```text ( BOOL:IN, TIME:PT ) => ( BOOL:Q, TIME:ET ) ``` -------------------------------- ### Mercurial Pre-commit Hooks for Code Linting Source: https://github.com/beremiz/beremiz/blob/python3/CONTRIBUTING.md Configure Mercurial hooks in .hg/hgrc to automatically run code checks before committing. This example uses a local script to check only changed Python files. ```ini [hooks] pre-shelve.linter = touch .hg/skiphook post-shelve.linter = rm .hg/skiphook pretxncommit.linter = ./tests/tools/check_source.sh --only-changes ``` -------------------------------- ### Configure OPC-UA Client in Beremiz Source: https://context7.com/beremiz/beremiz/llms.txt Sets up an OPC-UA client connection, specifying the server URI, security settings, authentication, and nodes to subscribe to. Adjust security modes and policies based on server requirements. ```python # OPC-UA Client Configuration from opc_ua import OPCUAClient # Configuration structure opcua_config = { "Server_URI": "opc.tcp://192.168.1.100:4840", "Security_Mode": "SignAndEncrypt", # None, Sign, SignAndEncrypt "Security_Policy": "Basic256Sha256", # Authentication "Auth_Type": "UserPassword", # Anonymous, UserPassword, Certificate "User": "opcua_user", "Password": "secret", # Node subscriptions "Subscriptions": [ { "NodeID": "ns=2;s=Temperature", "Direction": "input", "IEC_Type": "REAL", "Location": 0 }, { "NodeID": "ns=2;s=Pressure", "Direction": "input", "IEC_Type": "REAL", "Location": 1 }, { "NodeID": "ns=2;s=Setpoint", "Direction": "output", "IEC_Type": "REAL", "Location": 0 } ], "Publish_Interval_ms": 100 } ``` -------------------------------- ### Mercurial Pre-commit Hooks with Docker for Code Linting Source: https://github.com/beremiz/beremiz/blob/python3/CONTRIBUTING.md Configure Mercurial hooks using a Docker container to ensure checks are consistent with Bitbucket pipeline environments. This example checks changed Python files using a specified Docker image. ```ini [hooks] pre-shelve.linter = touch .hg/skiphook post-shelve.linter = rm .hg/skiphook pretxncommit.linter = hg status -m -n -a -n -I '**.py' --change $HG_NODE > files.lst && docker run --volume=$PWD:/beremiz --workdir="/beremiz" --volume=$PWD/../CanFestival-3:/CanFestival-3 --memory=1g --entrypoint=/beremiz/tests/tools/check_source.sh skvorl/beremiz-requirements --files-to-check files.lst ``` -------------------------------- ### Configure MQTT Client in Beremiz Source: https://context7.com/beremiz/beremiz/llms.txt Defines the configuration for an MQTT client, including broker URI, client ID, authentication, and input/output topics. Ensure correct topic names and data types are specified for seamless integration. ```python mqtt_config = { "Broker_URI": "mqtt://broker.example.com:1883", "Client_ID": "BeremizPLC01", # Authentication options "Auth_Type": "UserPassword", # or "x509" "User": "plc_user", "Password": "secret", # For x509 authentication # "KeyStore": "/path/to/client.pem", # "TrustStore": "/path/to/ca.pem", # Input topics (subscribe) "inputs": [ {"Topic": "sensors/temperature", "QoS": 1, "Type": "REAL", "Location": 0}, {"Topic": "sensors/humidity", "QoS": 1, "Type": "REAL", "Location": 1}, {"Topic": "commands/setpoint", "QoS": 2, "Type": "INT", "Location": 2}, ], # Output topics (publish) "outputs": [ {"Topic": "status/pump", "QoS": 1, "Retained": True, "Type": "BOOL", "Location": 0}, {"Topic": "status/temperature", "QoS": 1, "Retained": True, "Type": "REAL", "Location": 1}, {"Topic": "alarms/high_temp", "QoS": 2, "Retained": False, "Type": "BOOL", "Location": 2}, ] } ``` -------------------------------- ### eRPC Server Configuration Source: https://context7.com/beremiz/beremiz/llms.txt Configure the eRPC server for runtime communication. ```APIDOC ## eRPC Server Configuration ### Description The eRPC server provides the runtime communication endpoint for IDE/CLI connections. ### Methods - `eRPCServer`: Class for configuring and running the eRPC server. - `CreatePLCObjectSingleton(...)`: Must be called to initialize the PLC object before starting the eRPC server. ### Request Example (Python) ```python from runtime.eRPCServer import eRPCServer from runtime import CreatePLCObjectSingleton from threading import Thread, Lock # Initialize PLC object first CreatePLCObjectSingleton( WorkingDir="/var/lib/beremiz", argv=[], statuschange=[], evaluator=lambda f, *a, **k: (f(*a, **k), None), pyruntimevars={} ) # Example of starting the eRPC server (details depend on specific implementation) # erpc_server = eRPCServer(port=3000) # server_thread = Thread(target=erpc_server.run) # server_thread.start() ``` ``` -------------------------------- ### Connect IDE to Beremiz Runtime Source: https://github.com/beremiz/beremiz/blob/python3/README.md Configure your Beremiz IDE project settings with this URI to connect to a running Beremiz service. This URI specifies the IP address and port of the service. ```text ERPC://127.0.0.1:61194 ``` -------------------------------- ### Connector Factory for Runtime Communication Source: https://context7.com/beremiz/beremiz/llms.txt Establishes connections to PLC runtimes using various schemes like LOCAL, ERPC, ERPCS, and WAMP. Requires a project controller instance. ```python from connectors import ConnectorFactory, ConnectorSchemes # Get available connection schemes schemes = ConnectorSchemes() print(f"Available schemes: {schemes}") # Output: ['ERPC', 'ERPCS', 'WAMP', 'WAMPS', 'LOCAL', 'FLASH'] # Connect to local runtime (auto-started) # LOCAL:// starts a local runtime on demand connector = ConnectorFactory("LOCAL://", project_controller) # Connect to remote runtime via ERPC (unencrypted) connector = ConnectorFactory("ERPC://192.168.1.100:3000", project_controller) # Connect to remote runtime via ERPC with PSK encryption connector = ConnectorFactory("ERPCS://192.168.1.100:4000#MyPLCID", project_controller) # Connect via WAMP (Web Application Messaging Protocol) connector = ConnectorFactory("WAMP://wamp.server.com:8080#realm1", project_controller) # Using the connector if connector is not None: # Get PLC status status, log_counts = connector.GetPLCstatus() print(f"Status: {status}, Logs: {log_counts}") # Start/Stop PLC connector.StartPLC() connector.StopPLC() # Transfer program connector.NewPLC(md5sum, plc_blob_id, extra_files) # Get log messages for level in range(4): count = log_counts[level] for msg_id in range(count): msg, tick, sec, nsec = connector.GetLogMessage(level, msg_id) print(f"[{level}] {msg}") # Debug trace operations connector.SetTraceVariablesList([(0, None), (1, None)]) status, traces = connector.GetTraceVariables() ``` -------------------------------- ### Create and Manage PLCObject Singleton Source: https://context7.com/beremiz/beremiz/llms.txt Initializes the PLCObject singleton for managing PLC execution and communication. Use GetPLCObjectSingleton to retrieve the instance. ```python from runtime import CreatePLCObjectSingleton, GetPLCObjectSingleton from runtime import PlcStatus # Create PLC object singleton (done once at runtime startup) working_dir = "/var/lib/beremiz/workdir" argv = [] status_callbacks = [] evaluator = lambda tocall, *args, **kwargs: (tocall(*args, **kwargs), None) runtime_vars = {} CreatePLCObjectSingleton( working_dir, argv, status_callbacks, evaluator, runtime_vars ) # Get the singleton instance plc = GetPLCObjectSingleton() # Auto-load last transferred PLC (with optional autostart) plc.AutoLoad(autostart=True) # Manual PLC control plc.StartPLC() # Start execution plc.StopPLC() # Stop execution # Check PLC status # Returns: PlcStatus.Empty, PlcStatus.Stopped, PlcStatus.Started, PlcStatus.Broken status = plc.PLCStatus print(f"Current status: {status}") # Log messages from PLC plc.LogMessage(0, "Info: PLC operation started") plc.LogMessage(1, "Warning: Sensor value out of range") plc.LogMessage(2, "Error: Communication failure") # Get log messages level = 0 # 0=Info, 1=Warning, 2=Error msg_count = plc.GetLogCount(level) for msg_id in range(msg_count): message, tick, tv_sec, tv_nsec = plc.GetLogMessage(level, msg_id) print(f"[{tick}] {message}") # Reset log count plc.ResetLogCount() # Transfer new PLC program (via blob mechanism) import hashlib # Step 1: Calculate MD5 of new program with open("new_plc.so", "rb") as f: plc_data = f.read() md5sum = hashlib.md5(plc_data).hexdigest() # Step 2: Create blob and append chunks blob_id = plc.SeedBlob(plc_data[:1024]) for i in range(1024, len(plc_data), 1024): chunk = plc_data[i:i+1024] blob_id = plc.AppendChunkToBlob(chunk, blob_id) # Step 3: Install new PLC with extra files extra_files = [ ("config.xml", config_blob_id), ("hmi.svg", hmi_blob_id) ] success = plc.NewPLC(md5sum, blob_id, extra_files) # Verify MD5 match matches = plc.MatchMD5(md5sum) print(f"MD5 verified: {matches}") # Debug tracing trace_orders = [ (0, None), # Variable index 0, no forced value (1, None), # Variable index 1, no forced value (2, b'\x01'), # Variable index 2, forced to 1 (BOOL) ] plc.SetTraceVariablesList(trace_orders) # Get trace data status, samples = plc.GetTraceVariables() for tick, trace_buffer in samples: print(f"Tick {tick}: {trace_buffer.hex()}") # Extended call for custom runtime extensions result = plc.ExtendedCall("GetVersions", b"") print(f"Runtime versions: {result.decode()}") # Get PLC identification plc_id, psk = plc.GetPLCID() print(f"PLC ID: {plc_id}") ``` -------------------------------- ### Build BACnet (Optional) Source: https://github.com/beremiz/beremiz/blob/python3/README.md Compiles the BACnet stack, required for BACnet communication support. This command checks out the source from SVN and builds the library with specific defines for enhanced functionality. ```bash cd ~/Beremiz svn checkout https://svn.code.sf.net/p/bacnet/code/trunk/bacnet-stack/ BACnet cd BACnet make MAKE_DEFINE='-fPIC' MY_BACNET_DEFINES='-DPRINT_ENABLED=1 -DBACAPP_ALL -DBACFILE -DINTRINSIC_REPORTING -DBACNET_TIME_MASTER -DBACNET_PROPERTY_LISTS=1 -DBACNET_PROTOCOL_REVISION=16' library ``` -------------------------------- ### ProjectController API Source: https://context7.com/beremiz/beremiz/llms.txt Extends PLCControler with build toolchain integration, runtime connection, and project configuration. ```APIDOC ## ProjectController API ### Description ProjectController builds upon PLCControler by adding capabilities for configuring target platforms, connecting to runtime environments, building, transferring, and managing PLC projects. ### Initialization Requires a wxPython application context. ```python import wx from ProjectController import ProjectController app = wx.App() frame = wx.Frame(None) project = ProjectController() ``` ### Project Loading and Information - **LoadProject(filePath)**: Loads a project from the specified file path. - **filePath** (string) - Path to the project file. - Returns a tuple `(error_msg, error)` where `error` is a boolean indicating failure. - **GetProjectName()**: Returns the name of the loaded project. - **ProjectPath**: Property that returns the path of the loaded project. ### Configuration - **SetParamsAttribute(attribute, value)**: Sets a project parameter. - **attribute** (string) - The name of the parameter (e.g., "BeremizRoot.TargetType", "BeremizRoot.URI_location"). - **value** (string) - The value to set for the parameter. ### Build and Runtime Operations - **_Build()**: Builds the project. Returns `True` on success, `False` on failure. - **_Connect()**: Connects to the PLC runtime. Returns `True` if connected, `False` otherwise. - **_Transfer()**: Transfers the built program to the PLC. Returns `True` if successful, `False` otherwise. - **_Run()**: Starts the PLC execution. - **GetPLCstatus()**: Retrieves the current status of the PLC. - **_Stop()**: Stops the PLC execution. - **_Disconnect()**: Disconnects from the PLC runtime. - **_Clean()**: Cleans build artifacts. ### Extension Management - **CTNChildrenTypes**: Property returning a list of available extension node types, each as a tuple `(name, importer, display_name)`. - **CTNAddChild(name, type)**: Adds a new extension node to the project configuration tree. - **name** (string) - The name for the new node. - **type** (string) - The type of the extension (e.g., "modbus"). ### Configuration Tree Traversal - **CTNName()**: Method on a node object returning its name. - **IECSortedChildren()**: Method on a node object returning its children in sorted order. ### Example Usage ```python import wx from ProjectController import ProjectController app = wx.App() frame = wx.Frame(None) project = ProjectController() error_msg, error = project.LoadProject("/path/to/project") if not error: print("Project loaded successfully") print(f"Project: {project.GetProjectName()}") print(f"Path: {project.ProjectPath}") project.SetParamsAttribute("BeremizRoot.TargetType", "Linux") project.SetParamsAttribute("BeremizRoot.URI_location", "ERPC://192.168.1.100:3000") success = project._Build() if success: print("Build completed successfully") connected = project._Connect() if connected: transferred = project._Transfer() if transferred: project._Run() status = project.GetPLCstatus() print(f"PLC Status: {status}") project._Stop() project._Disconnect() project._Clean() children_types = project.CTNChildrenTypes for name, importer, display_name in children_types: print(f"Extension: {display_name} ({name})") modbus_node = project.CTNAddChild("modbus_0", "modbus") def print_tree(node, indent=0): print(" " * indent + node.CTNName()) for child in node.IECSortedChildren(): print_tree(child, indent + 2) print_tree(project) ``` ``` -------------------------------- ### Beremiz CLI Build and Control Operations Source: https://context7.com/beremiz/beremiz/llms.txt Provides scriptable project building, PLC control, and deployment using the Beremiz CLI. Supports various operations like build, clean, transfer, run, stop, and configuration overrides. ```bash python -m Beremiz_cli --project-home ./my_plc_project build ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project build --target Linux ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project clean ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --uri ERPC://192.168.1.100:3000 \ build transfer ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --uri ERPC://192.168.1.100:3000 \ run ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --uri ERPC://192.168.1.100:3000 \ stop ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --uri ERPC://192.168.1.100:3000 \ build transfer run ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --keep build transfer run ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --config TargetType.Board.EnableFeature boolean true \ --config TargetType.Board.MaxConnections integer 10 \ build ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --buildpath /tmp/plc_build \ --verbose \ build ``` ```bash python -m Beremiz_cli --project-home ./my_plc_project \ --uri ERPC://192.168.1.100:3000 \ connect flush ``` -------------------------------- ### Connector Factory and Runtime Communication Source: https://context7.com/beremiz/beremiz/llms.txt Establish connections to PLC runtimes using various protocols. ```APIDOC ## Connector Factory and Runtime Communication ### Description Connectors provide the communication layer between IDE/CLI and PLC runtimes using various protocols. ### Methods - `ConnectorSchemes()`: Returns a list of available connection schemes. - `ConnectorFactory(scheme_uri, project_controller)`: Creates a connector instance based on the provided scheme URI. - `scheme_uri`: The URI specifying the connection protocol and endpoint (e.g., "LOCAL://", "ERPC://host:port", "ERPCS://host:port#PLCID", "WAMP://host:port#realm"). - `project_controller`: Controller object for the project. - `connector.GetPLCstatus()`: Gets the PLC status and log counts. - `connector.StartPLC()`: Starts the PLC. - `connector.StopPLC()`: Stops the PLC. - `connector.NewPLC(md5sum, plc_blob_id, extra_files)`: Transfers a new PLC program. - `connector.GetLogMessage(level, msg_id)`: Retrieves a log message. - `connector.SetTraceVariablesList(trace_orders)`: Sets variables for debug tracing. - `connector.GetTraceVariables()`: Retrieves trace data. ### Request Example (Python) ```python from connectors import ConnectorFactory, ConnectorSchemes # Get available connection schemes schemes = ConnectorSchemes() print(f"Available schemes: {schemes}") # Connect to local runtime connector = ConnectorFactory("LOCAL://", project_controller) # Connect to remote runtime via ERPC connector = ConnectorFactory("ERPC://192.168.1.100:3000", project_controller) # Connect to remote runtime via ERPC with PSK encryption connector = ConnectorFactory("ERPCS://192.168.1.100:4000#MyPLCID", project_controller) # Connect via WAMP connector = ConnectorFactory("WAMP://wamp.server.com:8080#realm1", project_controller) # Using the connector if connector is not None: status, log_counts = connector.GetPLCstatus() print(f"Status: {status}, Logs: {log_counts}") connector.StartPLC() connector.StopPLC() # Assuming md5sum, plc_blob_id, and extra_files are defined # connector.NewPLC(md5sum, plc_blob_id, extra_files) for level in range(4): count = log_counts[level] for msg_id in range(count): msg, tick, sec, nsec = connector.GetLogMessage(level, msg_id) print(f"[{level}] {msg}") connector.SetTraceVariablesList([(0, None), (1, None)]) status, traces = connector.GetTraceVariables() ``` ``` -------------------------------- ### eRPC Server Configuration (Stunnel) Source: https://github.com/beremiz/beremiz/blob/python3/doc/programming/connect.md Configuration for Stunnel to wrap an unencrypted eRPC server into a TLS-PSK SSL socket. Ensure 'psk.txt' contains the shared secret. ```ini [ERPCPSK] accept = 4000 connect = 127.0.0.1:3000 ciphers = PSK sslVersion = TLSv1.2 PSKsecrets = psk.txt ```