diff --git a/.gitignore b/.gitignore index 0dbf2f2..33f54f7 100644 --- a/.gitignore +++ b/.gitignore @@ -168,3 +168,4 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +.idea diff --git a/EXEC_INSTALL.bat b/EXEC_INSTALL.bat new file mode 100644 index 0000000..b01c084 --- /dev/null +++ b/EXEC_INSTALL.bat @@ -0,0 +1,12 @@ +@echo off +setlocal + +:: ---------- USER DEFINE -------------- +set "ymlPath=condaenv.yml" +:: ------------------------------------- + +:: Execute the Python script +conda env create -f "%ymlPath%" + +:: Pause at the end of the script +pause diff --git a/EXEC_PRESS_START.bat b/EXEC_PRESS_START.bat new file mode 100644 index 0000000..07b86ff --- /dev/null +++ b/EXEC_PRESS_START.bat @@ -0,0 +1,15 @@ +@echo off +setlocal + +:: ---------- USER DEFINE -------------- +set "venvName=opcua_com" +set "scriptPath=RUN_BTN.py" +set "arg=-n BTN_START" +:: ------------------------------------- + +:: Activate the Conda environment and execute the Python script +call conda activate %venvName% +python "%scriptPath%" %arg% + +:: Pause at the end of the script +pause diff --git a/EXEC_PRESS_STOP.bat b/EXEC_PRESS_STOP.bat new file mode 100644 index 0000000..42f742c --- /dev/null +++ b/EXEC_PRESS_STOP.bat @@ -0,0 +1,15 @@ +@echo off +setlocal + +:: ---------- USER DEFINE -------------- +set "venvName=opcua_com" +set "scriptPath=RUN_BTN.py" +set "arg=-n BTN_STOP" +:: ------------------------------------- + +:: Activate the Conda environment and execute the Python script +call conda activate %venvName% +python "%scriptPath%" %arg% + +:: Pause at the end of the script +pause diff --git a/README.md b/README.md index 47632c7..459b7c8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +v0.9 + # opcuaCOM_PY -Simuliertes Drücken von Tasten (START, STOP) über OPCUA \ No newline at end of file +Simuliertes Drücken von definierten Tasten (START, STOP...) über OPCUA \ No newline at end of file diff --git a/RUN_BTN.py b/RUN_BTN.py new file mode 100644 index 0000000..48bc58a --- /dev/null +++ b/RUN_BTN.py @@ -0,0 +1,63 @@ +import yaml +from opcua_connector import opcua_connector +import time +import argparse + + + +def check_opcua_server(OPCcon): + """State 0: Check if OPC UA server is reachable.""" + print("---- State 0 ----") + try: + OPCcon.opcuaclient.connect() # Connection happens here + print("OPC UA server is reachable.") + return 1 # Move to state 1 + except Exception as e: + print(f"Error connecting to OPC UA server: {e}") + +def establish_connection(OPCcon): + """State 1: Establish connection to OPC UA server.""" + print("---- State 1 ----") + try: + if OPCcon.opcuaclient.uaclient: + print("OPC UA connection established.") + return 2 # Move to state 2 + else: + print(f"Error establishing connection") + except Exception as e: + print(f"Error establishing connection: {e}") + +def push_btn(OPCcon, btn_name): + """State 2:""" + print("---- State 2 ----") + try: + OPCcon.press_btn(btn_name) + print("Data collection complete.") + return 99 # Return to state 2 + except Exception as e: + print(f"Error in data collection: {e}.") + + +if __name__ == '__main__': + # Argument parsing + parser = argparse.ArgumentParser(description='Run OPC UA button press script.') + parser.add_argument('-n', '--name', type=str, choices=['BTN_START', 'BTN_STOP'], required=True, help='Button name to press (BTN_START or BTN_STOP)') + args = parser.parse_args() + btn_name = args.name # Get button name from arguments + + # INIT + config = yaml.safe_load(open('./cfg.yaml')) + OPCcon = opcua_connector(config) + + # State machine loop + state = 0 + if state == 0: + state = check_opcua_server(OPCcon) + elif state == 1: + state = establish_connection(OPCcon) + elif state == 2: + state = push_btn(OPCcon, btn_name) + + # Close the InfluxDB connection when done + OPCcon.influxclient.close() + OPCcon.opcuaclient.disconnect() # Disconnect from OPC UA after state machine finishes \ No newline at end of file diff --git a/cfg.yaml b/cfg.yaml new file mode 100644 index 0000000..16d0819 --- /dev/null +++ b/cfg.yaml @@ -0,0 +1,17 @@ +--- + +data: + logging_folder: "./_logging/" + cfg_varlist: "cfg_varlist.csv" + +cred: + robot: + url: "opc.tcp://192.168.214.1:4840" + url_debug: "opc.tcp://192.168.214.250:4840" + username: "OpcUaClient" + password: "OPCUACLIENT" + influxdb: + url: "http://192.168.21.221:8086" + org: "mabi-robotic" + token: "uiD4vON8m90OBuVtERGgVZtUvJjDYVr34F3TVyRh_eRncBj0WcXI_6fVLdyAn3cvNWPQjd4CFaKHCr4RK8PgLQ==" + bucket: "max200_test" \ No newline at end of file diff --git a/cfg_varlist.csv b/cfg_varlist.csv new file mode 100644 index 0000000..c4581c4 --- /dev/null +++ b/cfg_varlist.csv @@ -0,0 +1,2 @@ +BTN_START ns=2;s=LBP_Chan1.A_NCStart +BTN_STOP ns=2;s=LBP_Chan1.A_NCStop \ No newline at end of file diff --git a/condaenv.yml b/condaenv.yml new file mode 100644 index 0000000..f77e6e7 --- /dev/null +++ b/condaenv.yml @@ -0,0 +1,13 @@ +name: opcua_com +channels: + - conda-forge + - defaults +dependencies: + - python=3.10 + - opcua + - numpy + - pyyaml + - cryptography + - matplotlib + - pandas + - influxdb-client \ No newline at end of file diff --git a/opcua_connector.py b/opcua_connector.py new file mode 100644 index 0000000..47d047e --- /dev/null +++ b/opcua_connector.py @@ -0,0 +1,77 @@ +# opcua_connector.py + +from opcua import Client, ua +from time import sleep, time +import datetime +import pandas as pd +from influxdb_client import InfluxDBClient, Point, WritePrecision +from influxdb_client.client.write_api import SYNCHRONOUS + + + + +class opcua_connector: + def __init__(self, config): + self.config = config + self.opcuaclient = Client(config['cred']["robot"]["url"]) + self.opcuaclient.set_user(config['cred']["robot"]["username"]) + self.opcuaclient.set_password(config['cred']["robot"]["password"]) + self.influxclient = InfluxDBClient(url=config['cred']["influxdb"]["url"], + token=config['cred']["influxdb"]["token"], + org=config['cred']["influxdb"]["org"]) + self.influx_bucket = config['cred']["influxdb"]["bucket"] + self.varlist_dict = self.read_varlist(config['data']["cfg_varlist"]) + + def press_btn(self, btn_name): + var = self.varlist_dict[btn_name] + print(var) + # _sent_opcua_data_impuls(self, var) + + def read_varlist(self, filename, DELIMITER='\t'): + df = pd.read_csv(filename, delimiter=DELIMITER, header=None) + return dict(zip(df.iloc[:, 0], df.iloc[:, 1])) + + + # def track_robot_position(self, SAMPLE_DELAY=0.07, TOTMANN_SEC=3, stop_trigger_node=None, stop_trigger_value=None): + # """Track robot position and check stop trigger from OPC UA client.""" + # try: + # start_time = time() + # write_api = self.influxclient.write_api(write_options=SYNCHRONOUS) + # living_point2 = 0 + # treshold_living = 1 + # + # def RECORDING(): + # fieldnames = self.var_list.values[:, 0].tolist() + # nodes = self.var_list.values[:, 1].tolist() + # val = self.__get_opcua_data(nodes) + # points = [Point("mvalues").field(field, value).time(datetime.datetime.utcnow(), WritePrecision.NS) + # for field, value in zip(fieldnames, val)] + # write_api.write(bucket=self.influx_bucket, org=self.config['cred']["influxdb"]["org"], record=points) + # return val[0] + # + # while TOTMANN_SEC == 0 or time() - start_time < TOTMANN_SEC: + # # Check stop trigger + # stop_trigger_value_current = self.opcuaclient.get_node(stop_trigger_node).get_value() + # if stop_trigger_value_current == stop_trigger_value: + # print("Stop trigger detected.") + # break # Exit the loop when stop trigger is detected + # living_point1 = living_point2 + # living_point2 = RECORDING() + # if abs(living_point1 - living_point2) >= treshold_living: + # start_time = time() # Reset start time to prolong session + # sleep(SAMPLE_DELAY) + # + # except Exception as e: + # print(f"Error during tracking: {e}") + + +def _get_opcua_data(self, var_list): + """ Retrieve OPC UA node values based on the list of variable nodes. """ + return [self.opcuaclient.get_node(var).get_value() for var in var_list] + + +def _sent_opcua_data_impuls(self, var): + node = self.opcuaclient.get_node(var) + node.set_value(1) # Set node to 1 + time.sleep(1) # Wait for 1 second + node.set_value(0) # Set node back to 0