The machine IP must be reachable from your PC.
1. Introduction
# Retrieve machining results results = cnc.read(200, 100) # 200 is the address where the results are stored, 100 is the length of the data
Using these libraries, you can programmatically "ask" the CNC for nearly any internal status: www.robustel.store pyfanuc · PyPI fanuc focas python
You can go beyond reading data and actually manage programs, such as reading the file list using CNC_RDPDF_ALLDIR or CNC_RDPDF_SUBDIRN . This is useful for automated backup systems or push-programming scenarios. Overcoming Challenges
Connecting to a single machine is just the beginning. The real power of using Python with FOCAS is unlocked when you integrate it into a broader Industrial IoT (IIoT) ecosystem.
import ctypes import os # Define path to the FOCAS DLL dll_path = os.path.join(os.getcwd(), "Fwlib32.dll") # Load the library using ctypes try: focas = ctypes.WinDLL(dll_path) except OSError as e: print(f"Error loading FOCAS DLL: e. Check 32-bit/64-bit compatibility.") exit(1) # Configuration parameters CNC_IP = b"111.22.33.44" # Must be a byte string CNC_PORT = 8193 TIMEOUT = 10 # Seconds # Variable to hold the machine handle handle = ctypes.c_ushort(0) # 1. Connect to the CNC Machine # Function signature: cnc_allclibhndl3(ip, port, timeout, pointer_to_handle) ret = focas.cnc_allclibhndl3(CNC_IP, CNC_PORT, TIMEOUT, ctypes.byref(handle)) if ret == 0: print(f"Successfully connected! Handle ID: handle.value") # 2. Read Machine Status (Example) # Define the structure to hold statinfo data based on FANUC documentation class ODBST(ctypes.Structure): _fields_ = [ ("hdg_gno", ctypes.c_short), ("g_line", ctypes.c_short), ("g_No", ctypes.c_short), ("run", ctypes.c_short), # Status: 0=STOP, 1=HOLD, 2=START, 3=MDI, etc. ("motion", ctypes.c_short), # Motion status ("mstb", ctypes.c_short), # M, S, T, B status ("emergency", ctypes.c_short),# Emergency stop status ("alarm", ctypes.c_short), # Alarm status ("edit", ctypes.c_short) # Edit status ] status_data = ODBST() stat_ret = focas.cnc_statinfo(handle, ctypes.byref(status_data)) if stat_ret == 0: print(f"Machine Run Status: status_data.run") print(f"Emergency Stop Active: status_data.emergency") print(f"Alarm Active: status_data.alarm") else: print(f"Failed to read status info. Error code: stat_ret") # 3. Free the Machine Handle (Disconnect) focas.cnc_freelibhndl(handle) print("Disconnected from CNC.") else: print(f"Connection failed. FOCAS Return Error Code: ret") Use code with caution. Essential FOCAS Error Codes The machine IP must be reachable from your PC
class POSITION_DATA(ctypes.Structure): _fields_ = [ ("name", ctypes.c_char), ("type", ctypes.c_char), ("value", ctypes.c_long) # Value is usually returned as an integer multiplied by 1000 or 10000 ] class ODBPOS(ctypes.Structure): _fields_ = [ ("dat", POSITION_DATA * 4) # Assuming up to 4 axes (X, Y, Z, A) ] def read_axis_positions(handle): pos_structure = ODBPOS() data_type = 0 # 0 reads absolute position, 1 reads machine position num_axes = ctypes.c_short(4) # Number of axes to read result = focas.cnc_rdposition(handle, data_type, ctypes.byref(num_axes), ctypes.byref(pos_structure)) if result == 0: for i in range(num_axes.value): axis_name = pos_structure.dat[i].name.decode('utf-8') # Convert raw integer value to actual decimal mm/inch actual_value = pos_structure.dat[i].value / 10000.0 print(f"Axis axis_name: actual_value") else: print(f"Failed to read positions. Error: result") Use code with caution. Advanced Use Cases: Moving Beyond Basics
# Wait for the next collection interval time.sleep(monitoring_interval_seconds)
Python's vast ecosystem makes it easy to turn raw FOCAS data into business value. Data Logging and IoT Pipelines This is useful for automated backup systems or
import ctypes from ctypes import ByRef, Structure, c_short, c_long, c_float # 1. Load the FOCAS Library # Ensure Fwlib64.dll and its dependent dependencies (e.g., fwlibe64.dll) are in your script directory focas = ctypes.WinDLL("./Fwlib64.dll") # 2. Define FOCAS C-Structures in Python class ODBAXIS(Structure): _fields_ = [ ("dummy", c_short), ("type", c_short), ("data", c_long * 4) # Array for up to 4 axes ] # 3. Establish Connection cnc_ip = b"1192.168.1.100" # Must be a byte string cnc_port = 8193 timeout = 10 lib_handle = c_short(0) # Call cnc_allclibhndl3 to get a handle ret = focas.cnc_allclibhndl3(cnc_ip, cnc_port, timeout, ByRef(lib_handle)) if ret == 0: print(f"Successfully connected! Handle ID: lib_handle.value") # 4. Read Absolute Position Data axis_num = -1 # -1 reads all axes data_length = 4 + 4 * 4 # Size calculation based on FOCAS documentation position_data = ODBAXIS() pos_ret = focas.cnc_absolute(lib_handle, axis_num, data_length, ByRef(position_data)) if pos_ret == 0: # FANUC integers often omit the decimal point. # Divide by 1000 or 10000 depending on machine metric/inch settings. x_pos = position_data.data[0] / 1000.0 y_pos = position_data.data[1] / 1000.0 z_pos = position_data.data[2] / 1000.0 print(f"X Axis Position: x_pos") print(f"Y Axis Position: y_pos") print(f"Z Axis Position: z_pos") else: print(f"Failed to read position data. Error code: pos_ret") # 5. Free the Library Handle focas.cnc_freelibhndl(lib_handle) print("Disconnected from CNC.") else: print(f"Connection failed. FOCAS Error Code: ret") Use code with caution. Open-Source Python Wrappers
Using cnc_rdpmcrng and cnc_wtpmcrng , Python can read and write to the CNC's internal programmable machine control (PMC) addresses. This allows your Python application to trigger physical stack lights, interlock doors, or communicate directly with external robotic loading cells without modifying the core NC program logic. Best Practices and Performance Optimization
Integrating Python with FANUC FOCAS unlocks advanced capabilities that standard CNC software cannot easily match: 1. IIoT and MQTT Data Streaming
Send data to databases (SQL), cloud platforms (AWS/Azure), or create MQTT/OPC-UA protocols.