You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Overview

The Scripting Reference provides comprehensive documentation for developing custom logic in FrameworX 10.1. With support for multiple programming languages including C#, VB.NET, Python, and JavaScript, you can implement complex calculations, automation logic, and integrations. This guide covers syntax, APIs, best practices, and practical examples for all scripting scenarios.


Supported Languages

Language Comparison

LanguageUse CasesPerformanceLearning CurveKey Features
C#Complex logic, performance-criticalExcellentModerateFull .NET access, strongly typed
VB.NETLegacy systems, simple logicExcellentEasyFamiliar syntax, .NET access
PythonData analysis, ML, scriptingGoodEasyLibraries, readable syntax
JavaScriptClient-side, expressions ,HTML5 (*1)GoodEasyWeb integration, JSON

(1) Use Portable pages instead of HTML

JavaScript is available only in HTML5-only, displays.  Prefer always to the Portable Pages, which allows the configuration on Desktop Rich Clients (.NET WPF) and Web/Mobile clients (WebAssembly).

Keep JavaScript and HTML5 only required for code compatibility  or use of external HTML5 controls.

Language Selection Guide

Decision Tree:
Need maximum performance? => C#
Need higher level of runtime security & Reliably => C#
Legacy VB code? => VB.NET Data science/ML? => Python Client-side logic? => C# & Python server classes
Simple expressions => any language. Platform expression editor can parse different languages.

Script Types

Tasks (Scheduled Scripts)

Tasks execute on schedules or triggers:

csharp

// C# Task Example

        // Read current values
        double production = @Tag.Production.Counter;
        DateTime shiftStart = @Tag.Shift.StartTime;
        
        // Calculate metrics
        double hours = (DateTime.Now - shiftStart).TotalHours;
double rate = c
ount / hours;
// Update tags @Tag.KPI.ProductionRate = rate; @Tag.KPI.LastUpdate = DateTime.Now; // Log to database @Script.Class.Util.LogToDatabase(rate);    

Classes (Reusable Libraries)

Classes provide reusable functions:

csharp

// C# Class Library: EngineeringCalcs

    // Flow calculation
    public static double CalculateFlow(double dp, double k)
    {
        return k * Math.Sqrt(dp);
    }
    
    // Temperature conversion
    public static double CelsiusToFahrenheit(double celsius)
    {
        return (celsius * 9.0 / 5.0) + 32;
    }
    
    // Pressure conversion
    public static double PSIToBar(double psi)
    {
        return psi * 0.0689476;
    }
    
    // Tank volume
    public static double CylindricalTankVolume(double diameter, double level)
    {
        double radius = diameter / 2;
        return Math.PI * radius * radius * level;
    }

Expressions (Inline Calculations)

Expressions are single-line calculations:

javascript

// JavaScript Expressions
// Conditional logic
@Tag.Pump.Status = @Tag.Pump.Running ? "Running" : "Stopped"

// Mathematical calculation
@Tag.Tank.Volume = Math.PI * Math.pow(@Tag.Tank.Radius, 2) * @Tag.Tank.Level

// String manipulation
@Tag.Display.Message = "Temperature: " + @Tag.Temp.Value.toFixed(1) + "°C"

// Date/time calculation
@Tag.Batch.Duration = (Date.now() - @Tag.Batch.StartTime) / 1000 / 60

Display Scripts (UI Event Handlers)

Scripts triggered by UI events:

csharp

// C# Display Script
public void OnButtonClick(object sender, EventArgs e)
{
    // Validate user input
    if (!ValidatePermissions())
    {
        ShowMessage("Access Denied");
        return;
    }
    
    // Execute command
    @Tag.Equipment.StartCommand = true;
    
    // Log action
    LogUserAction("Start button pressed");
    
    // Update display
    RefreshDisplay();
}

private bool ValidatePermissions()
{
    return @Tag.Security.UserLevel >= 2;
}

Tag Access

Reading and Writing Tags

C# Tag Access

csharp

// Reading tags
double temperature = @Tag.Process.Temperature;
bool motorRunning = @Tag.Motor1.Running;
string batchID = @Tag.Batch.ID;
DateTime timestamp = @Tag.System.CurrentTime;

// Writing tags
@Tag.Setpoint.Value = 75.5;
@Tag.Pump.Start = true;
@Tag.Message.Text = "Process started";

// Array access
double[] values = @Tag.Data.Array;
@Tag.Data.Array[0] = 100;

// Quality and timestamp
TagQuality quality = @Tag.Process.Temperature.Quality;
DateTime lastUpdate = @Tag.Process.Temperature.Timestamp;

Python Tag Access

python

# Reading tags
temperature = @Tag.Process.Temperature
motor_running = @Tag.Motor1.Running
batch_id = @Tag.Batch.ID

# Writing tags
@Tag.Setpoint.Value = 75.5
@Tag.Pump.Start = True
@Tag.Message.Text = "Process started"

# Array operations
import numpy as np
values = np.array(@Tag.Data.Array)
mean_value = np.mean(values)
@Tag.Statistics.Mean = mean_value

# Bulk operations
tags_to_read = ['Tag1', 'Tag2', 'Tag3']
values = @Tag.ReadMultiple(tags_to_read)

Tag Properties and Methods

csharp

// Tag properties
public class TagProperties
{
    // Basic properties
    string Name { get; }
    object Value { get; set; }
    TagQuality Quality { get; }
    DateTime Timestamp { get; }
    
    // Extended properties
    double Min { get; set; }
    double Max { get; set; }
    string Units { get; }
    string Description { get; }
    
    // Methods
    void ForceValue(object value);
    void Subscribe(Action<TagChangeEvent> handler);
    void Unsubscribe();
    bool WriteWithConfirm(object value, int timeout);
}

Database Operations

SQL Database Access

csharp

// C# Database Operations
public class DatabaseScript
{
    public void ReadFromDatabase()
    {
        // Simple query
        var result = @Dataset.Query("SELECT * FROM Production WHERE Date = TODAY");
        
        // Parameterized query
        var parameters = new Dictionary<string, object>
        {
            { "StartDate", DateTime.Today },
            { "EndDate", DateTime.Now }
        };
        
        var data = @Dataset.ExecuteQuery(
            "SELECT * FROM Production WHERE Timestamp BETWEEN @StartDate AND @EndDate",
            parameters
        );
        
        // Process results
        foreach (var row in data.Rows)
        {
            @Tag.Production.Count = row["Count"];
            @Tag.Production.Quality = row["Quality"];
        }
    }
    
    public void WriteToDatabase()
    {
        // Insert data
        @Dataset.Execute(
            "INSERT INTO BatchRecords (BatchID, StartTime, Product) VALUES (@ID, @Time, @Product)",
            new {
                ID = @Tag.Batch.ID,
                Time = DateTime.Now,
                Product = @Tag.Batch.Product
            }
        );
        
        // Update data
        @Dataset.Execute(
            "UPDATE Equipment SET RunHours = @Hours WHERE ID = @EquipID",
            new {
                Hours = @Tag.Motor.RunHours,
                EquipID = @Tag.Motor.ID
            }
        );
    }
}

Transaction Management

csharp

// Transaction example
public void ExecuteTransaction()
{
    using (var transaction = @Dataset.BeginTransaction())
    {
        try
        {
            // Multiple operations in transaction
            @Dataset.Execute("INSERT INTO Orders ...", transaction);
            @Dataset.Execute("UPDATE Inventory ...", transaction);
            @Dataset.Execute("INSERT INTO Audit ...", transaction);
            
            // Commit if all successful
            transaction.Commit();
        }
        catch (Exception ex)
        {
            // Rollback on error
            transaction.Rollback();
            @Tag.Error.Message = ex.Message;
        }
    }
}

File Operations

Reading and Writing Files

csharp

// C# File Operations
public class FileOperations
{
    public void ReadCSV()
    {
        string path = @"C:\Data\production.csv";
        
        if (File.Exists(path))
        {
            var lines = File.ReadAllLines(path);
            
            foreach (var line in lines.Skip(1)) // Skip header
            {
                var values = line.Split(',');
                ProcessCSVLine(values);
            }
        }
    }
    
    public void WriteReport()
    {
        var report = new StringBuilder();
        report.AppendLine($"Production Report - {DateTime.Now}");
        report.AppendLine($"Total: {@Tag.Production.Total}");
        report.AppendLine($"Good: {@Tag.Production.Good}");
        report.AppendLine($"Reject: {@Tag.Production.Reject}");
        
        File.WriteAllText(@"C:\Reports\daily.txt", report.ToString());
    }
    
    public void AppendLog()
    {
        string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{@Tag.Process.Value}\n";
        File.AppendAllText(@"C:\Logs\process.log", logEntry);
    }
}

Communication Functions

Web Services and APIs

csharp

// REST API Calls
public class APIIntegration
{
    private HttpClient client = new HttpClient();
    
    public async Task GetDataFromAPI()
    {
        try
        {
            // GET request
            var response = await client.GetAsync("https://api.example.com/data");
            
            if (response.IsSuccessStatusCode)
            {
                string json = await response.Content.ReadAsStringAsync();
                dynamic data = JsonConvert.DeserializeObject(json);
                
                @Tag.External.Value = data.value;
                @Tag.External.Status = data.status;
            }
        }
        catch (Exception ex)
        {
            @Tag.Error.API = ex.Message;
        }
    }
    
    public async Task PostDataToAPI()
    {
        var payload = new
        {
            timestamp = DateTime.Now,
            value = @Tag.Process.Value,
            quality = @Tag.Process.Quality
        };
        
        var json = JsonConvert.SerializeObject(payload);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        
        var response = await client.PostAsync("https://api.example.com/data", content);
        @Tag.API.LastPost = response.StatusCode.ToString();
    }
}

Email Notifications

csharp

// Email Functions
public class EmailScript
{
    public void SendAlarmEmail()
    {
        var email = new EmailMessage
        {
            To = "operator@company.com",
            Subject = $"Alarm: {@Tag.Alarm.Description}",
            Body = $@"
                Alarm Active: {@Tag.Alarm.Description}
                Time: {DateTime.Now}
                Value: {@Tag.Alarm.Value}
                Priority: {@Tag.Alarm.Priority}
                
                Please acknowledge at HMI.
            ",
            IsHtml = false
        };
        
        @System.SendEmail(email);
    }
}

Error Handling

Exception Management

csharp

// Comprehensive Error Handling
public class ErrorHandling
{
    public void SafeOperation()
    {
        try
        {
            // Risky operation
            double result = Calculate();
            @Tag.Result.Value = result;
        }
        catch (DivideByZeroException ex)
        {
            // Specific exception handling
            @Tag.Error.Type = "Division Error";
            @Tag.Error.Message = "Cannot divide by zero";
            LogError(ex);
        }
        catch (Exception ex)
        {
            // General exception handling
            @Tag.Error.Type = "General Error";
            @Tag.Error.Message = ex.Message;
            LogError(ex);
        }
        finally
        {
            // Always execute
            @Tag.Process.Calculating = false;
        }
    }
    
    private void LogError(Exception ex)
    {
        var errorLog = new
        {
            Timestamp = DateTime.Now,
            Type = ex.GetType().Name,
            Message = ex.Message,
            StackTrace = ex.StackTrace,
            User = @Tag.System.CurrentUser
        };
        
        @Dataset.Execute(
            "INSERT INTO ErrorLog (Time, Type, Message, Stack, User) VALUES (@Time, @Type, @Msg, @Stack, @User)",
            errorLog
        );
    }
}

Performance Optimization

Best Practices for Script Performance

csharp

// Performance Optimized Script
public class OptimizedScript
{
    // Cache frequently used values
    private static Dictionary<string, double> cache = new Dictionary<string, double>();
    
    // Batch operations
    public void BatchUpdate()
    {
        // Bad: Individual writes
        // for (int i = 0; i < 100; i++)
        //     @Tag.Array[i] = Calculate(i);
        
        // Good: Batch write
        double[] values = new double[100];
        for (int i = 0; i < 100; i++)
            values[i] = Calculate(i);
        @Tag.Array = values;
    }
    
    // Efficient loops
    public void EfficientLoop()
    {
        // Pre-calculate invariants
        double factor = @Tag.Config.Factor;
        double offset = @Tag.Config.Offset;
        
        var values = @Tag.Raw.Array;
        var results = new double[values.Length];
        
        // Use for instead of foreach for arrays
        for (int i = 0; i < values.Length; i++)
        {
            results[i] = values[i] * factor + offset;
        }
        
        @Tag.Scaled.Array = results;
    }
    
    // Minimize tag access
    public void MinimizeTagAccess()
    {
        // Bad: Multiple tag reads
        // if (@Tag.Process.Mode == 1 && @Tag.Process.Mode != 2)
        
        // Good: Single read
        int mode = @Tag.Process.Mode;
        if (mode == 1 && mode != 2)
        {
            // Process
        }
    }
}

Debugging Scripts

Debug Techniques

csharp

// Debugging Methods
public class DebugScript
{
    public void DebugExample()
    {
        // Console output (appears in logs)
        Console.WriteLine($"Debug: Starting process at {DateTime.Now}");
        
        // Conditional debugging
        #if DEBUG
        Console.WriteLine("Debug mode - detailed logging enabled");
        var stopwatch = Stopwatch.StartNew();
        #endif
        
        // Debug tags
        @Tag.Debug.LastRun = DateTime.Now;
        @Tag.Debug.ExecutionTime = stopwatch.ElapsedMilliseconds;
        
        // Breakpoint (in Designer test mode)
        System.Diagnostics.Debugger.Break();
        
        // Trace information
        Trace.WriteLine("Trace: Process completed");
        Trace.Assert(@Tag.Value > 0, "Value should be positive");
    }
}

Script Examples Library

Common Calculations

csharp

// Standard Industrial Calculations
public static class IndustrialCalcs
{
    // PID Controller
    public static double PID(double setpoint, double processValue, 
                            ref double integral, ref double lastError,
                            double kp, double ki, double kd, double dt)
    {
        double error = setpoint - processValue;
        integral += error * dt;
        double derivative = (error - lastError) / dt;
        lastError = error;
        
        return kp * error + ki * integral + kd * derivative;
    }
    
    // Moving Average
    public static double MovingAverage(Queue<double> window, double newValue, int windowSize)
    {
        window.Enqueue(newValue);
        if (window.Count > windowSize)
            window.Dequeue();
        
        return window.Average();
    }
    
    // Rate of Change
    public static double RateOfChange(double currentValue, double lastValue, double timeInterval)
    {
        return (currentValue - lastValue) / timeInterval;
    }
    
    // Totalization
    public static double Totalize(double flow, double timeInterval, ref double total)
    {
        total += flow * timeInterval;
        return total;
    }
}

Data Processing

python

# Python Data Analysis Script
import numpy as np
import statistics

def analyze_batch_data():
    # Get array data
    temperatures = @Tag.Batch.TemperatureArray
    pressures = @Tag.Batch.PressureArray
    
    # Statistical analysis
    @Tag.Stats.TempMean = np.mean(temperatures)
    @Tag.Stats.TempStdDev = np.std(temperatures)
    @Tag.Stats.TempMin = np.min(temperatures)
    @Tag.Stats.TempMax = np.max(temperatures)
    
    # Find outliers
    z_scores = np.abs((temperatures - np.mean(temperatures)) / np.std(temperatures))
    outliers = np.where(z_scores > 3)[0]
    @Tag.Stats.OutlierCount = len(outliers)
    
    # Correlation
    correlation = np.corrcoef(temperatures, pressures)[0, 1]
    @Tag.Stats.TempPressureCorrelation = correlation
    
    # Quality determination
    if @Tag.Stats.TempStdDev < 2.0 and len(outliers) == 0:
        @Tag.Batch.Quality = "Good"
    else:
        @Tag.Batch.Quality = "Review Required"

Script Security

Security Best Practices

csharp

// Secure Scripting Practices
public class SecureScript
{
    // Input validation
    public void ValidateInput(string userInput)
    {
        // Sanitize input
        userInput = userInput.Trim();
        
        // Validate format
        if (!Regex.IsMatch(userInput, @"^[a-zA-Z0-9_]+$"))
        {
            throw new ArgumentException("Invalid input format");
        }
        
        // Check length
        if (userInput.Length > 50)
        {
            throw new ArgumentException("Input too long");
        }
        
        // SQL injection prevention (use parameters)
        @Dataset.Execute(
            "SELECT * FROM Table WHERE Name = @Name",
            new { Name = userInput }
        );
    }
    
    // Permission checking
    public void SecureOperation()
    {
        // Check user permission
        if (@Tag.Security.UserLevel < 3)
        {
            @Tag.Error.Message = "Insufficient permissions";
            LogSecurityEvent("Unauthorized access attempt");
            return;
        }
        
        // Execute privileged operation
        ExecutePrivilegedOperation();
    }
    
    // Audit logging
    private void LogSecurityEvent(string action)
    {
        @Dataset.Execute(
            "INSERT INTO SecurityLog (Time, User, Action, Result) VALUES (@Time, @User, @Action, @Result)",
            new {
                Time = DateTime.Now,
                User = @Tag.System.CurrentUser,
                Action = action,
                Result = "Denied"
            }
        );
    }
}

Next Steps

Additional Resources


AI Assistant Data

<details> <summary>Structured Information for AI Tools</summary>

json

{
  "page": "Scripting Reference",
  "type": "Technical Reference",
  "purpose": "Comprehensive scripting documentation for FrameworX",
  "languages": ["C#", "VB.NET", "Python", "JavaScript"],
  "scriptTypes": {
    "tasks": "Scheduled or triggered execution",
    "classes": "Reusable libraries",
    "expressions": "Inline calculations",
    "display": "UI event handlers"
  },
  "keyTopics": [
    "Tag access and manipulation",
    "Database operations",
    "File I/O",
    "Web services",
    "Error handling",
    "Performance optimization",
    "Security"
  ],
  "commonUses": [
    "Calculations",
    "Data processing",
    "Integration",
    "Automation",
    "Reporting"
  ]
}

</detail

  • No labels