<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SCADA Archives | DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/tag/scada/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Fri, 04 Sep 2026 15:32:24 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>SCADA Archives | DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Triggering Gateway File Syncs for Ignition 8.3 Using Git Hooks</title>
		<link>https://static.dmcinfo.com/blog/44721/ignition-8-3-gateway-file-sync-git/</link>
		
		<dc:creator><![CDATA[Wenjing Deng]]></dc:creator>
		<pubDate>Wed, 03 Jun 2026 23:00:00 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Ignition]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[GIT]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[Workflows]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=44721</guid>

					<description><![CDATA[<p>Ignition 8.3’s file-based project structure makes it much easier to use standard Git workflows with SCADA projects. Project resources can now be version-controlled directly as files, which makes branch switching, pull requests, and external editing more practical. This also enables patterns&#160;such as&#160;using symbolic links to share project resources across environments. One issue that arises with [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/44721/ignition-8-3-gateway-file-sync-git/">Triggering Gateway File Syncs for Ignition 8.3 Using Git Hooks</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Ignition 8.3’s file-based project structure makes it much easier to use standard Git workflows with SCADA projects. Project resources can now be version-controlled directly as files, which makes branch switching, pull requests, and external editing more practical. This also enables patterns&nbsp;such as&nbsp;<a href="https://static.dmcinfo.com/blog/44390/symbolic-links-shared-ignition-project-libraries/">using symbolic links</a> to share project resources across environments.</p>



<p class="wp-block-paragraph" style="padding-bottom:var(--wp--preset--spacing--30)">One issue that arises with this workflow is that Ignition does not always immediately detect file changes made outside the Designer. After checking out a branch, merging changes, or pulling updates, the gateway will still need a manual file scan from the Gateway before the latest project or configuration files are reflected.</p>



<p class="wp-block-paragraph">To make development workflows smoother for our projects at DMC, we created a script that uses the Ignition 8.3 Gateway API endpoints to trigger project and configuration file scans. By integrating this script into Git hooks, file scans can run automatically after branch checkouts or merges, eliminating the need to manually navigate to the Gateway webpage and trigger them each time (fig1 and fig2). Additionally, developers can manually run the script from Bash or the command line to trigger file scans on demand.</p>



<p class="wp-block-paragraph">In this blog, we have provided a sample script and .env file, and we will walk you through the steps to set this up.</p>



<figure class="wp-block-image aligncenter size-full has-custom-border"><img fetchpriority="high" decoding="async" width="1429" height="277" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-1.png" alt="Screenshot of the &quot;Platform Overview&quot; page in the Ignition Gateway UI." class="has-border-color has-custom-light-blue-border-color wp-image-44728" style="border-width:2px;border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-1.png 1429w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-1-300x58.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-1-1024x198.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-1-768x149.png 768w" sizes="(max-width: 1429px) 100vw, 1429px" /><figcaption class="wp-element-caption"><em>Figure 1: Platform File System Scan Button</em></figcaption></figure>



<figure class="wp-block-image aligncenter size-full has-custom-border"><img decoding="async" width="1427" height="334" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-2.png" alt="Screenshot of the Projects section of Ignition." class="has-border-color has-custom-light-blue-border-color wp-image-44729" style="border-width:2px;border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-2.png 1427w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-2-300x70.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-2-1024x240.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-2-768x180.png 768w" sizes="(max-width: 1427px) 100vw, 1427px" /><figcaption class="wp-element-caption"><em>Figure 2: Project File System Scan Button</em></figcaption></figure>



<h2 id="h-why-this-step-matters" class="wp-block-heading">Why This Step Matters</h2>



<p class="wp-block-paragraph">There are a variety of reasons why automating this step is both important and beneficial. This automation reduces friction in the development workflow, reducing some of the common sources of errors and delays while improving team-wide consistency and clarity. By using Git hooks to automate file syncing in Ignition, developers avoid repeated trips to the Gateway UI and reduce mental load.</p>



<p class="wp-block-paragraph">By adding automated file scans into the development workflow, teams can make Ignition 8.3 development feel more like regular software development, where Git-based practices like branching, merging, and pull requests fit naturally into SCADA projects.</p>



<h2 id="h-set-up-gateway-api-key" class="wp-block-heading">Set Up Gateway API Key</h2>



<p class="wp-block-paragraph">In order to access the API endpoint, we need to set up an API key in the Gateway. Follow <a href="https://www.docs.inductiveautomation.com/docs/8.3/platform/security/api-keys" target="_blank" rel="noreferrer noopener">Ignition’s manual</a> for this.</p>



<p class="wp-block-paragraph">By default, Ignition requires API keys to be used over secure HTTPS connections. Since this script commonly runs against local development Gateways using standard HTTP, the Require secure connections for API Keys setting must be disabled for the requests to succeed.</p>



<p class="wp-block-paragraph">Make sure to copy the ENTIRE api key. We will add it to the <em><strong>.env</strong></em> file in the next section.</p>



<h2 id="h-repo-and-environment-variables-set-up" class="wp-block-heading">Repo and Environment Variables Set Up</h2>



<p class="wp-block-paragraph">Copy the example script (included in the section below) into your desired location in your repo. For example, in this repo, we have put it at the following location and called it <strong>gateway_scan.py</strong>.</p>



<p class="wp-block-paragraph">Path: <em><strong>ignition-docker-8-3\scripts\gateway_scan</strong></em></p>



<figure class="wp-block-image size-full has-custom-border"><img decoding="async" width="1798" height="453" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4.png" alt="Screenshot of a file explorer window displaying a Python source file named gateway_scan.py." class="wp-image-44730" style="border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4.png 1798w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4-300x76.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4-1024x258.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4-768x193.png 768w, https://static.dmcinfo.com/wp-content/uploads/2026/05/ignition-8.3.-git-workflow-image-4-1536x387.png 1536w" sizes="(max-width: 1798px) 100vw, 1798px" /></figure>



<p class="wp-block-paragraph">Next, add the following variables to your .env file:</p>



<p class="wp-block-paragraph"><strong><em>GATEWAY_IP= (your gateway’s IP address)</em><br><em>HTTP_PORT = (your gateway’s port)</em><br><em>GATEWAY_API_TOKEN=(your generated API token for the gateway)</em></strong></p>



<p class="wp-block-paragraph">The example script looks for these variables; if they are already in your <strong>.env</strong> and are named differently, open the example script and do a find-and-replace to update the variable names.</p>



<h2 id="h-git-hook-set-up" class="wp-block-heading">Git Hook Set Up</h2>



<p class="wp-block-paragraph">Git hooks let us automatically run scripts when certain Git actions occur. For this workflow, we typically set up Git hooks to run the gateway_scan.py script after branch checkouts and merges.</p>



<p class="wp-block-paragraph">This means that when a developer switches branches, pulls changes, or merges updates, the Gateway file scan can run automatically without having to open the Gateway webpage and manually trigger it.</p>



<p class="wp-block-paragraph">To set this up, create two files in the <strong>.git/hooks</strong> folder:</p>



<p class="wp-block-paragraph"><em><strong>.git/hooks/post-checkout<br>.git/hooks/post-merge</strong></em></p>



<p class="wp-block-paragraph">Paste the following code into both files:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#!/bin/sh

# Move to the root of the git repository
cd "$(git rev-parse --show-toplevel)" || exit 1

# Run file scan script
py scripts/gateway_scan/gateway_scan.py</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">#!/bin/sh</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Move to the root of the git repository</span></span>
<span class="line"><span style="color: #D4D4D4">cd </span><span style="color: #CE9178">&quot;$(git rev-parse --show-toplevel)&quot;</span><span style="color: #D4D4D4"> || exit </span><span style="color: #B5CEA8">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Run file scan script</span></span>
<span class="line"><span style="color: #D4D4D4">py scripts/gateway_scan/gateway_scan.py</span></span></code></pre></div>



<p class="wp-block-paragraph">The post-checkout hook runs after switching branches. The post-merge hook runs after a merge, which also commonly happens when pulling new changes from the remote repository.</p>



<p class="wp-block-paragraph">The first command moves the terminal to the root of the Git repository. This helps ensure the script runs from the correct location, even if Git triggers the hook from within the repository.</p>



<p class="wp-block-paragraph">The second command runs the Gateway scan script:</p>



<p class="wp-block-paragraph"><em><strong>py scripts/gateway_scan/gateway_scan.py</strong></em></p>



<p class="wp-block-paragraph">Developers can also run this command manually from Bash or the command line whenever they want to trigger a Gateway file scan on demand.</p>



<p class="wp-block-paragraph">If the repository contains multiple gateways you want to automatically file scan for, add a separate set of environment variables for each gateway in the <strong>.env file</strong>, create an API key for each gateway, and then update the <strong>gateway_scan.py</strong> script following the comments, so the script knows which gateways to scan.</p>



<h2 id="h-example-script-amp-env-file" class="wp-block-heading">Example Script &amp; env. File</h2>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#------------------Gateway Scan Trigger Script Example------------------
"""
Run script to trigger file scans for gateways.
"""
import os
from pathlib import Path
from urllib import error, request

REQUEST_TIMEOUT_SECONDS = 5

print("Syncing Ignition Gateway...", flush=True)


def load_env_file(env_path):
	"""
	Load simple KEY=value pairs from a .env file without third-party dependencies.
	"""
	if not env_path.exists():
		return

	for line in env_path.read_text(encoding="utf-8").splitlines():
		line = line.strip()

		if not line or line.startswith("#") or "=" not in line:
			continue

		key, value = line.split("=", 1)
		os.environ.setdefault(key.strip(), value.strip().strip("\"'"))


# Read in .env file
load_env_file(Path(__file__).resolve().parents&#91;2&#93; / ".env")

# Grab environment variables
# TODO: VERIFY YOUR .ENV FILE HAS THESE VARIABLES SET CORRECTLY
# CREATE ADDITIONAL ENVIRONMENT VARIABLES FOR ADDITIONAL GATEWAYS IF NEEDED
# BY COPYING THE FOLLOWING FORMAT
GATEWAY_PORT = os.getenv("HTTP_PORT_IGN")
GATEWAY_IP = os.getenv("GATEWAY_IP")
GATEWAY_API_TOKEN = os.getenv("GATEWAY_API_TOKEN")

# TODO: ADD ADDITIONAL GATEWAYS HERE IF NEEDED!
gateways = {
	"Ignition": {"ip": GATEWAY_IP, "port": GATEWAY_PORT, "token": GATEWAY_API_TOKEN}
	# Additional gateways can be added here in the same format
}

actions = &#91;"projects", "config"&#93;

def post_scan_request(url, headers):
	"""
	Post a gateway scan request and return the HTTP status code.
	"""
	req = request.Request(url, headers=headers, method="POST")

	with request.urlopen(req, timeout=REQUEST_TIMEOUT_SECONDS) as response:
		return response.status


def trigger_scans():
	"""
	Trigger scans on the specified gateways.
	"""
	for name, config in gateways.items():
		ip = config&#91;"ip"&#93;
		token = config&#91;"token"&#93;
		port = config&#91;"port"&#93;

		if not ip or not token or not port:
			var_name = "ip address" if not ip else "API token" if not token else "Port"
			print(f"Skipping {name}: Missing environment variable '{var_name}'.")
			continue

		headers = {
			"X-Ignition-API-Token": f"{token}"
		}

		for action in actions:
			# Ignition uses the final path segment to choose the scan type
			url = f""

			try:
				status_code = post_scan_request(url, headers)

				if status_code == 200:
					print(f"Success: File Scan {name} {action}")
				else:
					print(f"Failed: File Scan {name} {action} (Status: {status_code})")
			except TimeoutError:
				print(f"Timeout: {name} took too long to respond.")
			except error.HTTPError as err:
				print(f"Failed: File Scan {name} {action} (Status: {err.code})")
			except error.URLError as err:
				print(f"Connection Error: Could not reach {name} at {ip}. ({err.reason})")


if __name__ == "__main__":
	trigger_scans()

# ---------------------.env file example for one gateway--------------------
# HTTP_PORT_IGN= "your gateway's port"
# GATEWAY_IP= "your gateway's IP address"
# GATEWAY_API_TOKEN= "your gateway's API token"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#------------------Gateway Scan Trigger Script Example------------------</span></span>
<span class="line"><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #CE9178">Run script to trigger file scans for gateways.</span></span>
<span class="line"><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> os</span></span>
<span class="line"><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> pathlib </span><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> Path</span></span>
<span class="line"><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> urllib </span><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> error, request</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">REQUEST_TIMEOUT_SECONDS = </span><span style="color: #B5CEA8">5</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Syncing Ignition Gateway...&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">flush</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">load_env_file</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">env_path</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #CE9178">	Load simple KEY=value pairs from a .env file without third-party dependencies.</span></span>
<span class="line"><span style="color: #CE9178">	&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> env_path.exists():</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">return</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> line </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> env_path.read_text(</span><span style="color: #9CDCFE">encoding</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;utf-8&quot;</span><span style="color: #D4D4D4">).splitlines():</span></span>
<span class="line"><span style="color: #D4D4D4">		line = line.strip()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> line </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> line.startswith(</span><span style="color: #CE9178">&quot;#&quot;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;=&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> line:</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">continue</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		key, value = line.split(</span><span style="color: #CE9178">&quot;=&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">		os.environ.setdefault(key.strip(), value.strip().strip(</span><span style="color: #CE9178">&quot;</span><span style="color: #D7BA7D">\&quot;</span><span style="color: #CE9178">&apos;&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Read in .env file</span></span>
<span class="line"><span style="color: #D4D4D4">load_env_file(Path(</span><span style="color: #9CDCFE">__file__</span><span style="color: #D4D4D4">).resolve().parents&#91;</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">&#93; / </span><span style="color: #CE9178">&quot;.env&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Grab environment variables</span></span>
<span class="line"><span style="color: #6A9955"># </span><span style="color: #569CD6">TODO</span><span style="color: #6A9955">: VERIFY YOUR .ENV FILE HAS THESE VARIABLES SET CORRECTLY</span></span>
<span class="line"><span style="color: #6A9955"># CREATE ADDITIONAL ENVIRONMENT VARIABLES FOR ADDITIONAL GATEWAYS IF NEEDED</span></span>
<span class="line"><span style="color: #6A9955"># BY COPYING THE FOLLOWING FORMAT</span></span>
<span class="line"><span style="color: #D4D4D4">GATEWAY_PORT = os.getenv(</span><span style="color: #CE9178">&quot;HTTP_PORT_IGN&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">GATEWAY_IP = os.getenv(</span><span style="color: #CE9178">&quot;GATEWAY_IP&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">GATEWAY_API_TOKEN = os.getenv(</span><span style="color: #CE9178">&quot;GATEWAY_API_TOKEN&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># </span><span style="color: #569CD6">TODO</span><span style="color: #6A9955">: ADD ADDITIONAL GATEWAYS HERE IF NEEDED!</span></span>
<span class="line"><span style="color: #D4D4D4">gateways = {</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #CE9178">&quot;Ignition&quot;</span><span style="color: #D4D4D4">: {</span><span style="color: #CE9178">&quot;ip&quot;</span><span style="color: #D4D4D4">: GATEWAY_IP, </span><span style="color: #CE9178">&quot;port&quot;</span><span style="color: #D4D4D4">: GATEWAY_PORT, </span><span style="color: #CE9178">&quot;token&quot;</span><span style="color: #D4D4D4">: GATEWAY_API_TOKEN}</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #6A9955"># Additional gateways can be added here in the same format</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">actions = &#91;</span><span style="color: #CE9178">&quot;projects&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;config&quot;</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">post_scan_request</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">url</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">headers</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #CE9178">	Post a gateway scan request and return the HTTP status code.</span></span>
<span class="line"><span style="color: #CE9178">	&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">	req = request.Request(url, </span><span style="color: #9CDCFE">headers</span><span style="color: #D4D4D4">=headers, </span><span style="color: #9CDCFE">method</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;POST&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #C586C0">with</span><span style="color: #D4D4D4"> request.urlopen(req, </span><span style="color: #9CDCFE">timeout</span><span style="color: #D4D4D4">=REQUEST_TIMEOUT_SECONDS) </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> response:</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> response.status</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">trigger_scans</span><span style="color: #D4D4D4">():</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #CE9178">	Trigger scans on the specified gateways.</span></span>
<span class="line"><span style="color: #CE9178">	&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> name, config </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> gateways.items():</span></span>
<span class="line"><span style="color: #D4D4D4">		ip = config&#91;</span><span style="color: #CE9178">&quot;ip&quot;</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">		token = config&#91;</span><span style="color: #CE9178">&quot;token&quot;</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">		port = config&#91;</span><span style="color: #CE9178">&quot;port&quot;</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> ip </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> token </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> port:</span></span>
<span class="line"><span style="color: #D4D4D4">			var_name = </span><span style="color: #CE9178">&quot;ip address&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> ip </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;API token&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> token </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Port&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Skipping </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178">: Missing environment variable &apos;</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">var_name</span><span style="color: #569CD6">}</span><span style="color: #CE9178">&apos;.&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">continue</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		headers = {</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #CE9178">&quot;X-Ignition-API-Token&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">token</span><span style="color: #569CD6">}</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">		}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> action </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> actions:</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #6A9955"># Ignition uses the final path segment to choose the scan type</span></span>
<span class="line"><span style="color: #D4D4D4">			url = </span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;http://</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">ip</span><span style="color: #569CD6">}</span><span style="color: #CE9178">:</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">port</span><span style="color: #569CD6">}</span><span style="color: #CE9178">/data/api/v1/scan/</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">action</span><span style="color: #569CD6">}</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">try</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">				status_code = post_scan_request(url, headers)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> status_code == </span><span style="color: #B5CEA8">200</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">					</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Success: File Scan </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">action</span><span style="color: #569CD6">}</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #C586C0">else</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">					</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Failed: File Scan </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">action</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> (Status: </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">status_code</span><span style="color: #569CD6">}</span><span style="color: #CE9178">)&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">except</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TimeoutError</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Timeout: </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> took too long to respond.&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">except</span><span style="color: #D4D4D4"> error.HTTPError </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> err:</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Failed: File Scan </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">action</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> (Status: </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">err.code</span><span style="color: #569CD6">}</span><span style="color: #CE9178">)&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">except</span><span style="color: #D4D4D4"> error.URLError </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> err:</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Connection Error: Could not reach </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">name</span><span style="color: #569CD6">}</span><span style="color: #CE9178"> at </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">ip</span><span style="color: #569CD6">}</span><span style="color: #CE9178">. (</span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">err.reason</span><span style="color: #569CD6">}</span><span style="color: #CE9178">)&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">__name__</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;__main__&quot;</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">	trigger_scans()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># ---------------------.env file example for one gateway--------------------</span></span>
<span class="line"><span style="color: #6A9955"># HTTP_PORT_IGN= &quot;your gateway&apos;s port&quot;</span></span>
<span class="line"><span style="color: #6A9955"># GATEWAY_IP= &quot;your gateway&apos;s IP address&quot;</span></span>
<span class="line"><span style="color: #6A9955"># GATEWAY_API_TOKEN= &quot;your gateway&apos;s API token&quot;</span></span></code></pre></div>



<h2 id="h-conclusion" class="wp-block-heading" style="padding-top:var(--wp--preset--spacing--40)">Conclusion</h2>



<p class="wp-block-paragraph" style="padding-bottom:var(--wp--preset--spacing--40)">Automating file syncs in Ignition 8.3 is a simple configuration change that can deliver meaningful improvements to your development workflow. By reducing manual steps and ensuring the Gateway always reflects the latest project state, teams can work more efficiently and with greater confidence. For engineers using Git to manage their Ignition projects, this approach unlocks the full benefits of modern version control while keeping SCADA development reliable and consistent.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Starting an Ignition project? DMC can help you take the next step.</strong></h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Find out more about our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/" target="_blank" rel="noreferrer noopener">Manufacturing Automation</a> and <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/" target="_blank" rel="noreferrer noopener">SCADA programming</a> solutions and reach out to an expert today.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/44721/ignition-8-3-gateway-file-sync-git/">Triggering Gateway File Syncs for Ignition 8.3 Using Git Hooks</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>FactoryTalk Optix Series 3 &#8211; NetLogic Overview and Examples</title>
		<link>https://static.dmcinfo.com/blog/16280/factorytalk-optix-series-3-netlogic-overview-and-examples/</link>
		
		<dc:creator><![CDATA[Ben Clare]]></dc:creator>
		<pubDate>Tue, 14 May 2024 17:21:41 +0000</pubDate>
				<category><![CDATA[Allen Bradley PLC]]></category>
		<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[FactoryTalk]]></category>
		<category><![CDATA[FactoryTalk Optix]]></category>
		<category><![CDATA[FT Optix]]></category>
		<category><![CDATA[HMI]]></category>
		<category><![CDATA[Optix]]></category>
		<category><![CDATA[SCADA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16280/factorytalk-optix-series-3-netlogic-overview-and-examples/</guid>

					<description><![CDATA[<p>HMI Programming and SCADA Programming are essential for creating efficient and responsive automation systems. When working with Optix, leveraging NetLogic allows for seamless integration between C# code and the SCADA environment, enabling advanced control and data exchange.&#160; NetLogic is C# code&#160;that is linked to Optix. Optix can call methods with parameters, set private C# variables, [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16280/factorytalk-optix-series-3-netlogic-overview-and-examples/">FactoryTalk Optix Series 3 &#8211; NetLogic Overview and Examples</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming"><strong>HMI Programming and SCADA Programming</strong></a> are essential for creating efficient and responsive automation systems. When working with Optix, leveraging NetLogic allows for seamless integration between C# code and the SCADA environment, enabling advanced control and data exchange.&nbsp;</p>



<p class="wp-block-paragraph">NetLogic is C# code&nbsp;that is linked to Optix. Optix can call methods with parameters, set private C# variables, and has numerous C# Libraries integrated by default to assist with passing data between Optix and your C# code. Optix also allows you to link the monitoring of C# code to an Optix runtime instance.</p>



<h2 id="h-linking-variables" class="wp-block-heading">Linking Variables</h2>



<p class="wp-block-paragraph">When creating NetLogic, you can define variables that interface with the C# code, and can be both written to and read from said C# code. You can also define variable categories to assist with organization.</p>



<ul class="wp-block-list">
<li>First, Variables are added onto the NetLogic object in Optix.</li>
</ul>



<p class="wp-block-paragraph"><p style="text-align: center;">&nbsp;<img decoding="async" alt="Linking Netlogic Variables" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/net-logic-linking-variables.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example of variables attached to a NetLogic object</em></p></p>



<p class="wp-block-paragraph">These variables can be referenced in the C# logic by utilizing the “GetVariable” method on our LogicObject.</p>



<ul class="wp-block-list">
<li>For any variables at the top-most level, simply call: LogicObject.GetVariable(“YourVariable”).</li>



<li>For nested variables (such as variables under “Table” in the example above), define a new IUAVariable for the nested name (Tables in this case), and then reference the individual elements of that new variable.</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C#</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
private void ParametersSetup()

{
	DB_SERVER_IP = LogicObject.GetVariable("Server IP").Value;
	DB_SERVER_PORT = uint.Parse(LogicObject.GetVariable("Server port").Value);
	SERVICE_NAME = LogicObject.GetVariable("Service name").Value;
	DB_USERNAME = LogicObject.GetVariable("Username").Value;
	DB_PASSWORD = LogicObject.GetVariable("Password").Value;
	DB_QUERIES_FEEDBACK = LogicObject.GetVariable("Queries feedback");
	TABLES = LogicObject.GetVariable("Tables");

	TABLE_DESTINATION = TABLES.GetVariable("Destination").Value;
	TABLE_DISTANCE = TABLES.GetVariable("Distance").Value;
	TABLE_LOCATIONCHANGE = TABLES.GetVariable("LocationChange").Value;
	TABLE_EQUIPMENTSTATUS = TABLES.GetVariable("EquipmentStatus").Value;
	NUMBER_OF_DEVICES = LogicObject.GetVariable("Number of devices").Value;
	NUMBER_OF_EQUIPMENT_AREAS = LogicObject.GetVariable("Number of equipment areas").Value;
	CONNECTIONSTRING = $"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={DB_SERVER_IP})(PORT={(int)DB_SERVER_PORT})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={SERVICE_NAME})));User Id={DB_USERNAME};Password={DB_PASSWORD};";
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">ParametersSetup</span><span style="color: #D4D4D4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">DB_SERVER_IP</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Server IP&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">DB_SERVER_PORT</span><span style="color: #D4D4D4"> = </span><span style="color: #569CD6">uint</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">Parse</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Server port&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">SERVICE_NAME</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Service name&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">DB_USERNAME</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Username&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">DB_PASSWORD</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Password&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">DB_QUERIES_FEEDBACK</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Queries feedback&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Tables&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">TABLE_DESTINATION</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Destination&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">TABLE_DISTANCE</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Distance&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">TABLE_LOCATIONCHANGE</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;LocationChange&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">TABLE_EQUIPMENTSTATUS</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;EquipmentStatus&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">NUMBER_OF_DEVICES</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Number of devices&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">NUMBER_OF_EQUIPMENT_AREAS</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">LogicObject</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetVariable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Number of equipment areas&quot;</span><span style="color: #D4D4D4">).</span><span style="color: #9CDCFE">Value</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">CONNECTIONSTRING</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">$&quot;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={</span><span style="color: #9CDCFE">DB_SERVER_IP</span><span style="color: #CE9178">})(PORT={(</span><span style="color: #569CD6">int</span><span style="color: #CE9178">)</span><span style="color: #9CDCFE">DB_SERVER_PORT</span><span style="color: #CE9178">})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={</span><span style="color: #9CDCFE">SERVICE_NAME</span><span style="color: #CE9178">})));User Id={</span><span style="color: #9CDCFE">DB_USERNAME</span><span style="color: #CE9178">};Password={</span><span style="color: #9CDCFE">DB_PASSWORD</span><span style="color: #CE9178">};&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C#</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
private IUAVariable DB_QUERIES_FEEDBACK;
private string DB_SERVER_IP;
private uint DB_SERVER_PORT;
private string SERVICE_NAME;
private string DB_USERNAME;
private string DB_PASSWORD;
public IUAVariable TABLES;
private string TABLE_DESTINATION;
private string TABLE_DISTANCE;
private string TABLE_LOCATIONCHANGE;
private string TABLE_EQUIPMENTSTATUS;
private Int32 NUMBER_OF_DEVICES;
private Int32 NUMBER_OF_EQUIPMENT_AREAS;

</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IUAVariable</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">DB_QUERIES_FEEDBACK</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">DB_SERVER_IP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">uint</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">DB_SERVER_PORT</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SERVICE_NAME</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">DB_USERNAME</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">DB_PASSWORD</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IUAVariable</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">TABLES</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">TABLE_DESTINATION</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">TABLE_DISTANCE</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">TABLE_LOCATIONCHANGE</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">TABLE_EQUIPMENTSTATUS</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Int32</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">NUMBER_OF_DEVICES</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Int32</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">NUMBER_OF_EQUIPMENT_AREAS</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<h2 id="h-calling-methods" class="wp-block-heading">Calling Methods</h2>



<p class="wp-block-paragraph">C# Methods can be called directly from Optix when the [ExportMethod] Line is added above said method. Any parameters associated with the Method will also be exposed, allowing you to set them dynamically from Optix, using a MethodInvocation or by linking them to events.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Invoking C# Methods from Optix" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/method-invocation.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example method invocation that shows all the [ExportMethod] methods from the Netlogic C# code</em></p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C#</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
&#91;ExportMethod&#93;

public void SelectAllDevicesDestination()

{

…

</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D4D4D4">&#91;</span><span style="color: #4EC9B0">ExportMethod</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">SelectAllDevicesDestination</span><span style="color: #D4D4D4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">…</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<h2 id="h-monitoring-code" class="wp-block-heading">Monitoring Code</h2>



<p class="wp-block-paragraph">When NetLogic is created, Optix automatically configures the codespace (if utilizing VSCode) to attach to the Optix runtime instance, allowing you to monitor your C# card while the Optix application is running.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Monitoring an Optix Project in Visual Code" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/visual-code-monitoring.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Visual Code is attached to the Optix Runtime when monitoring</em></p></p>



<h2 id="h-logging-and-error-handling" class="wp-block-heading">Logging and Error Handling</h2>



<p class="wp-block-paragraph">Optix has a C# library for logging code that should be utilized, as it will output to the console in FT Optix Studio, as well as to the log file for the Optix application.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C#</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
catch (System.Exception ex)
{
	Log.Error(MethodBase.GetCurrentMethod().Name, ex.Message);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #C586C0">catch</span><span style="color: #D4D4D4"> (</span><span style="color: #4EC9B0">System</span><span style="color: #D4D4D4">.</span><span style="color: #4EC9B0">Exception</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">ex</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #9CDCFE">Log</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">Error</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">MethodBase</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">GetCurrentMethod</span><span style="color: #D4D4D4">().</span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">ex</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Message</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><p style="text-align: center;">&nbsp;<img decoding="async" alt="Location of Optix Log Files" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/optix-runtime-logs.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>The location&nbsp;of Optix log files for an emulated project</em></p></p>



<h2 id="h-read-the-other-articles-in-this-series" class="wp-block-heading">Read the Other Articles in this Series</h2>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10576/factorytalk-optix-series-1--getting-started-with-factorytalk-optix">FactoryTalk Optix Series 1 &#8211; Getting Started with FactoryTalk Optix</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10609/factorytalk-optix-series-2--variables-attributes-dynamic-links-and-converters">FactoryTalk Optix Series 2 &#8211; Variables, Attributes, Dynamic Links, and Converters</a></li>
</ul>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Extend FactoryTalk Optix with C# NetLogic</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Explore our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/" data-type="page" data-id="420">Automation</a> expertise in integrating C# methods, variables, runtime monitoring, and error handling into <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/rockwell-factorytalk-programming/factorytalk-optix-programming/" data-type="page" data-id="44850">FactoryTalk Optix</a> applications.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16280/factorytalk-optix-series-3-netlogic-overview-and-examples/">FactoryTalk Optix Series 3 &#8211; NetLogic Overview and Examples</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>FactoryTalk Optix Series 2 &#8211; Variables, Attributes, Dynamic Links, and Converters</title>
		<link>https://static.dmcinfo.com/blog/16293/factorytalk-optix-series-2-variables-attributes-dynamic-links-and-converters/</link>
		
		<dc:creator><![CDATA[Ben Clare]]></dc:creator>
		<pubDate>Tue, 14 May 2024 17:15:21 +0000</pubDate>
				<category><![CDATA[Allen Bradley PLC]]></category>
		<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[FactoryTalk]]></category>
		<category><![CDATA[FactoryTalk Optix]]></category>
		<category><![CDATA[FT Optix]]></category>
		<category><![CDATA[HMI]]></category>
		<category><![CDATA[Optix]]></category>
		<category><![CDATA[SCADA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16293/factorytalk-optix-series-2-variables-attributes-dynamic-links-and-converters/</guid>

					<description><![CDATA[<p>Overview Variables, Attributes, Dynamic Links, and converters are the building blocks of Optix UI design. Each variable has a number of attributes associated with it, and Dynamic links and Converters can be used to define a relationship between two or more variables/attributes. A map of the relationships between Variables, Attributes, Dynamic Links, and Converters Variables [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16293/factorytalk-optix-series-2-variables-attributes-dynamic-links-and-converters/">FactoryTalk Optix Series 2 &#8211; Variables, Attributes, Dynamic Links, and Converters</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-overview" class="wp-block-heading">Overview</h2>



<p class="wp-block-paragraph">Variables, Attributes, Dynamic Links, and converters are the building blocks of Optix UI design. Each variable has a number of attributes associated with it, and Dynamic links and Converters can be used to define a relationship between two or more variables/attributes.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Variables, Attributes, Converters, and Dynamic Link Relationships" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/variables-attributes-converters-dynamic-links.png"></p></p>



<p class="has-text-align-center wp-block-paragraph"><em>A map of the relationships between Variables, Attributes, Dynamic Links, and Converters</em></p>



<h2 id="h-variables-and-scope" class="wp-block-heading">Variables and Scope</h2>



<p class="wp-block-paragraph">Variable scope is influenced by the containers they are in. All variables with a given container (screen or panel) can access each other. Variables in nested panels have access to the variables in other nested panels and parent/children panels, and vice versa.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Nested Variables in Scope" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/nested-variable-scope.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example of variable scope extending to variables nested in other related panels</em></p></p>



<p class="wp-block-paragraph">However, scope is limited when variables are not contained within a shared container, which happens most commonly with panels utilized in popups and panel loaders. However, the scope of panel loaders is unrestricted, so variables can be added to panel loaders and modified/updated anywhere in the Optix application, and the panels being loaded by said panel loader can then reference its variables to dynamically display information.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Out of Scope for the Selected Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/variable-out-of-scope.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example showing the limitations of scope when creation relationships between variables</em></p></p>



<p class="wp-block-paragraph">To see an example of a panel loader utilizing variables to allow the Main UI to interact with individual panels being loaded by a panel loader, stay tuned for our upcoming&nbsp;Optix Series – Device Sidebar Example blog.</p>



<h2 id="h-attributes" class="wp-block-heading">Attributes</h2>



<p class="wp-block-paragraph">Understanding attributes and their relationship to their parent variable is necessary to form complex Dynamic Links for UI functionality. Below is a list of the most common variable attributes.</p>


<table border="1" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="width:168px;">


<p class="wp-block-paragraph">BrowseName</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Name of the variable in the project.</p>



<p class="wp-block-paragraph">DataType</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Data type of the variable.</p>



<p class="wp-block-paragraph">DataType BrowseName</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Name of the DataType of the variable.</p>



<p class="wp-block-paragraph">Description</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Description of the variable (as set in FT Optix).</p>



<p class="wp-block-paragraph">DisplayName</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Translatable variable name that can appear on the interface at runtime.</p>



<p class="wp-block-paragraph">NodeId</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Automatically assigned unique identifier.</p>



<p class="wp-block-paragraph">Value</p>


</td>
<td style="width:456px;">


<p class="wp-block-paragraph">Value of the variable.</p>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">To see an example of different attributes being used to create a clean, complex solution, stay tuned for our upcoming Optix Series – Device Sidebar Example blog, which utilizes NodeId, BrowseName, and DataType BrowseName attributes.</p>



<h2 id="h-converters" class="wp-block-heading">Converters</h2>



<ul class="wp-block-list">
<li>Conditional Converter
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Sets the output variable&rsquo;s value based on a true/false evaluation of the input.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="Conditional Converter" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/conditional-converter.png"></p></p>



<ul class="wp-block-list">
<li>Engineering Unit Converter
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Scales the output linearly based on the input.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="Engineering Unit Converter" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/engineering-unit-converter.png"></p></p>



<ul class="wp-block-list">
<li>Linear Converter
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Scale the output based on a defined slope and intercept.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="Linear Converter" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/linear-converter.png"></p></p>



<ul class="wp-block-list">
<li>Key-value Converter
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Matches an output value to the input &ldquo;Key&rdquo;.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="Key-Value Converter" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/key-value-converter.png"></p></p>



<ul class="wp-block-list">
<li>Expression Evaluator
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Evaluates an expression consisting of one or more input variables.</li>


  

<li>To see all of the valid operators that can be used in an expression, see <a href="https://www.rockwellautomation.com/docs/en/factorytalk-optix/1-03/contents-ditamap/using-the-software/converters/expression-evaluator.html">Rockwell&rsquo;s documentation</a>.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="Expression Evaulator" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/expression-evaluator.png"></p></p>



<ul class="wp-block-list">
<li>String Formatter
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Outputs a string that can be defined using variables and various formatting options.</li>


 </ul>
</li>
</ul>



<p class="wp-block-paragraph"><p style="margin-left:1.0in;"><img decoding="async" alt="String Formatter" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/string-formatter.png"></p></p>



<h3 id="h-dynamic-links" class="wp-block-heading">Dynamic Links</h3>



<p class="wp-block-paragraph">Dynamic links are defined relationships between two or more variables. Dynamic links can implement converters to create complex relationships and can be pointed at both variables and attributes.</p>



<h3 id="h-aliases" class="wp-block-heading">Aliases</h3>



<p class="wp-block-paragraph">Aliases are a unique property type that allows you to specify the structure of a variable.&nbsp; This is useful when creating panels that should be referencing a specific Data Types, such as a motor or valve Data Type. An alias allows you to reference all the elements of the defined Data Type, while still allowing the alias variable to be linked dynamically, allowing graphics to be updated in real time, such as being able to swap which motor a panel is pointing to.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Aliases" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/aliases.png"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example of an alias to a Motor Data Type</em></p></p>



<p class="wp-block-paragraph">An example use case of aliases is for a device sidebar that utilizes a panel loader to swap in faceplates panels for different types of devices. The panel loader would have a NodeId variable (Let’s call it “Device Tag”) that would be updated at runtime to point to a desired device tag. For each device type, one panel would be created with a tag alias with the “Kind” attribute bound to the UDT of said device and the “NodeID” attribute bound to the “Device Tag” Attribute on the panel loader. Typically, you cannot create property bindings between variables that are not within the same window or screen (or the same panel for panels that are not directly placed on windows or screens), but panel loaders can be referenced regardless of project scope, allowing us to make use of the “Device Tag” variable we attached to ours.</p>



<p class="wp-block-paragraph">For an in-depth example, Stay tuned for our upcoming Optix Series – Device Sidebar Example blog.</p>



<h2 id="h-read-the-other-articles-in-this-series" class="wp-block-heading">Read the Other Articles in this Series</h2>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10576/factorytalk-optix-series-1--getting-started-with-factorytalk-optix">FactoryTalk Optix Series 1 &#8211; Getting Started with FactoryTalk Optix</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10610/factorytalk-optix-series-3--netlogic-overview-and-examples">FactoryTalk Optix Series 3 &#8211; NetLogic Overview and Examples</a></li>
</ul>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Build More Dynamic FactoryTalk Optix Interfaces</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Explore our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/" data-type="page" data-id="420">Automation</a> expertise in <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/rockwell-factorytalk-programming/factorytalk-optix-programming/" data-type="page" data-id="44850">FactoryTalk Optix</a> variables, attributes, dynamic links, aliases, and converters for creating flexible <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/" data-type="page" data-id="497">HMI and SCADA</a> applications.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16293/factorytalk-optix-series-2-variables-attributes-dynamic-links-and-converters/">FactoryTalk Optix Series 2 &#8211; Variables, Attributes, Dynamic Links, and Converters</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>FactoryTalk Optix Series 1 &#8211; Getting Started with FactoryTalk Optix</title>
		<link>https://static.dmcinfo.com/blog/16514/factorytalk-optix-series-1-getting-started-with-factorytalk-optix/</link>
		
		<dc:creator><![CDATA[Ben Clare]]></dc:creator>
		<pubDate>Mon, 25 Mar 2024 08:56:32 +0000</pubDate>
				<category><![CDATA[Allen Bradley PLC]]></category>
		<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[C# Integration]]></category>
		<category><![CDATA[Data Stores]]></category>
		<category><![CDATA[FactoryTalk]]></category>
		<category><![CDATA[FactoryTalk Optix]]></category>
		<category><![CDATA[FT Optix]]></category>
		<category><![CDATA[HMI]]></category>
		<category><![CDATA[NetLogic]]></category>
		<category><![CDATA[Optix]]></category>
		<category><![CDATA[Presentation Engines]]></category>
		<category><![CDATA[Property Bindings]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[Style Sheets]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16514/factorytalk-optix-series-1-getting-started-with-factorytalk-optix/</guid>

					<description><![CDATA[<p>FactoryTalk Optix is the next generation of visualization software from Rockwell Automation, meant to provide a higher degree of customized development with its integrated C# support and flexibility for HMI and SCADA applications. This blog series covers the essentials to creating your own HMI and SCADA applications using Optix as well as some helpful examples [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16514/factorytalk-optix-series-1-getting-started-with-factorytalk-optix/">FactoryTalk Optix Series 1 &#8211; Getting Started with FactoryTalk Optix</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">FactoryTalk Optix is the next generation of visualization software from <a href="https://www.rockwellautomation.com/en-us.html" target="_blank">Rockwell Automation</a>, meant to provide a higher degree of customized development with its integrated C# support and flexibility for HMI and SCADA applications.</p>



<p class="wp-block-paragraph">This blog series covers the essentials to creating your own HMI and SCADA applications using Optix as well as some helpful examples for common applications.</p>



<h2 id="h-installation" class="wp-block-heading">Installation</h2>



<p class="wp-block-paragraph">FactoryTalk Optix Studio is installed via <a href="https://home.cloud.rockwellautomation.com/sign-in?returnTo=%2Fdashboard" target="_blank">FactoryTalk Hub</a>, and it is the IDE used to program Optix projects. You can either download the IDE application&nbsp;or utilize a web-based IDE if your license supports it.</p>



<p class="wp-block-paragraph">The Optix Runtime tools are also installed via FactoryTalk Hub, and they are required on any machine that is going to run an Optix application.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="FactoryTalk Optix Hub" height="437px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-ft-optix-hub.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>FactoryTalk Hub:&nbsp;which hosts a number of FT applications (including FactoryTalk Design Studio for Optix)</em></p></p>



<h2 id="h-licensing-and-pricing" class="wp-block-heading">Licensing and Pricing</h2>



<p class="wp-block-paragraph">Optix licensing is done on a token-based system, with more features requiring more tokens, and, therefore, a larger license. Generally speaking, the largest contributors to token usage are multiple concurrent web clients, OPC-UA connections, or database connections.</p>



<p class="wp-block-paragraph">Examples of features that affect the sizing of your application include the following:</p>



<ul class="wp-block-list">
<li>Controller connections</li>



<li>Multiple web clients</li>



<li>Alarming</li>



<li>Recipes</li>



<li>PDF reports</li>



<li>Data logging</li>



<li>Database connectivity</li>



<li>OPC UA connectivity</li>
</ul>



<p class="wp-block-paragraph">For more information on tokens and licensing, please see <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/at/optix-at001_-en-p.pdf" target="_blank">Rockwell’s documentation</a>.</p>



<h2 id="h-presentation-engines" class="wp-block-heading">Presentation Engines</h2>



<p class="wp-block-paragraph">Presentation engines are responsible for rendering and displaying UI elements during runtime. There are two available presentation engines that can be used simultaneously – the native presentation engine and the web presentation engine.</p>



<p class="wp-block-paragraph">The native presentation engine launches the project in its own window as an application.</p>



<p class="wp-block-paragraph">The web presentation engine hosts the application on a web server, accessible via the defined web page. Multiple concurrent web clients can access the application (if multiple connections are defined in the web presentation engine), but more concurrent clients require more tokens.</p>



<p class="wp-block-paragraph">Optix can make use of session-specific tools to allow concurrent clients to have different screens/panels open, have different users logged in, and display different information, provided that the Optix project was designed with multiple clients in mind.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Optix Presentation Engine" height="680px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-optix-presentation-engine.png" width="449px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example configured Web Presentation Engine</em></p></p>



<h2 id="h-style-sheets" class="wp-block-heading">Style Sheets</h2>



<p class="wp-block-paragraph">Style sheets allow the definition of default colors, shapes, sizes, and other UI element configurations. A project’s style sheet can be swapped during runtime. Some properties can be defined both in the style sheet and in an individual UI element. In the case that a property is explicitly defined for an individual element, it will override the style sheet.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Style Sheet Example" height="506px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-style-sheet-example.png" width="585px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example Style Sheet</em></p></p>



<h2 id="h-screens-and-panels" class="wp-block-heading">Screens and Panels</h2>



<p class="wp-block-paragraph">FT Optix uses screens, panels, and popups as the main methods for displaying UI elements. Screens and popups can both contain multiple panel loaders, which can be used to dynamically change displayed content when a defined action is performed, such as hitting a button.</p>



<p class="wp-block-paragraph">To see panel loaders being implemented to create a dynamic device sidebar that changes what device it controls (and the associated UI elements) at the push of a button, stay tuned for our upcoming&nbsp;<em>F</em><em>actoryTalk Optix &#8211;&nbsp;Dynamic Device Faceplate</em> blog post.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Panel Loader" height="398px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-panel-loader.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A panel loader that is a part of the main overlay of an application. It has the ability to load either a Motor or a GroundRack panel into the panel loader.</em></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Motor Panel Loaded" height="392px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-motor-panel-loaded.png" width="900px">&nbsp;</p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A runtime instance with the &#8220;Motor&#8221; panel loaded into the panel loader</em></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Rack Panel Loaded" height="391px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6-rack-panel-loaded.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A runtime instance with the &#8220;Ground Rack&#8221; panel loaded into the panel loader</em></p></p>



<h2 id="h-converters" class="wp-block-heading">Converters</h2>



<p class="wp-block-paragraph">Converters allow you to modify variables dynamically based on other variables. For instance, a key-value converter could change the text displayed in a string variable when a different integer variable’s value changes, and an engineering unit converter can be used to scale variable values differently.</p>



<p class="wp-block-paragraph">There are more converter types and use cases that were not mentioned above. For more information on converters, stay tuned for our upcoming&nbsp;<em>FactoryTalk Optix &#8211; Variables, Attributes, Dynamic Links, and Converters</em> blog post.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Converter" height="346px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-converter.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A Key-Value converter that parses an integer out into valve status strings</em></p></p>



<h2 id="h-dynamic-links" class="wp-block-heading">Dynamic Links</h2>



<p class="wp-block-paragraph">Dynamic links are used to define relationships between two or more variables or attributes&nbsp;within the FT Optix project. Complex dynamic links&nbsp;allow the&nbsp;use of built-in converters, allowing further customization of UI elements.</p>



<p class="wp-block-paragraph">For further information on Property Bindings, stay tuned for our upcoming<em>&nbsp;FactoryTalk Optix &#8211; Variables, Attributes, Dynamic Links, and Converters</em>&nbsp;blog post.</p>



<p class="wp-block-paragraph">For an example of leveraging complex dynamic links, stay tuned for our upcoming <em>F</em><em>actoryTalk Optix &#8211;&nbsp;Dynamic Device Faceplate</em> blog post.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Dynamic Link" height="532px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-dynamic-link.png" width="580px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A dynamic link that performs mathematical operations on several variables to return an adjusted distance</em></p></p>



<h2 id="h-events" class="wp-block-heading">Events</h2>



<p class="wp-block-paragraph">Events call methods when a specific trigger happens, such as a button being pressed or a variable&#8217;s value changing. Events can be added onto most UI elements, and they can trigger multiple methods.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Example Event" height="645px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-example-event.png" width="609px"></p></p>



<h2 id="h-methods" class="wp-block-heading">Methods</h2>



<p class="wp-block-paragraph">Methods are called by events. FT Optix has a number of built-in methods, but custom methods can be defined through NetLogic as well.</p>



<p class="wp-block-paragraph">You can also create pre-defined method invocations, which allow the calling of methods with pre-defined parameters.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Methods" height="511px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-methods.png" width="500px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A list of common methods available in FT Optix</em></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Method Invocation" height="137px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-method-invocation.png" width="450px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>A custom method invocation for renaming a MySQL Database table</em></p></p>



<h2 id="h-netlogic" class="wp-block-heading">NetLogic</h2>



<p class="wp-block-paragraph">NetLogic allows C# code to be integrated and run in an FT Optix project. FT Optix can call parameterized methods, and they can send and receive variables with the C# project.</p>



<p class="wp-block-paragraph">For further information on NetLogic, stay tuned for our upcoming&nbsp;<em>FactoryTalk Optix &#8211; NetLogic Overview and Examples</em> blog post.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Net Logic" height="766px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-net-logic.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example NetLogic snippet that returns a localized time</em></p></p>



<h2 id="h-data-stores" class="wp-block-heading">Data Stores</h2>



<p class="wp-block-paragraph">Data stores are databases used to store values from different loggers and NetLogic (if you so choose). You can either use an embedded database, which is a simple SQLite database created with minimal overhead, or you can choose to create a connection to a database (SQL Server or MySQL). Other database types may be supported through ODBC connections, but they have not been tested or confirmed yet.</p>



<p class="wp-block-paragraph">Loggers can be linked directly to a data store and will automatically configure tables for themselves on said database.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Data Store Table" height="644px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-datastore-table.png" width="504px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>An example data store with an &#8220;Alarm Logger&#8221; linked to it, auto generating the necessary tables</em></p></p>



<h2 id="h-communication-drivers" class="wp-block-heading">Communication Drivers</h2>



<p class="wp-block-paragraph">Communication Drivers allow defining communication paths to PLCs and other devices, as well as the importing of tags and other information to be used in the Optix project. A list of the currently available communication drivers is available below.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Available Comm Drivers" height="640px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-available-comm-drivers.png" width="400px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>All available communication drivers in Optix</em></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Comm Driver" height="456px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/15-comm-driver.png" width="900px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>The tag importer display from an example Rockwell Ethernet Driver linked to a PLC</em></p></p>



<h2 id="h-template-library" class="wp-block-heading">Template Library</h2>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Template Library" height="888px" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/16-template-library.png" width="819px"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><i>Optix&#8217;s Template Library</i></p></p>



<p class="wp-block-paragraph">The template library stores templates created by Rockwell and allows you to create/import your own libraries as well. Some examples of useful templates that are included with Optix are:</p>



<ul class="wp-block-list">
<li>Alarm Grid</li>



<li>Alam History</li>



<li>Alarm Banner</li>



<li>User Login Popup</li>



<li>Confirmation Dialog</li>



<li>Date and Time Display</li>



<li>File Selector</li>



<li>File System Browser</li>



<li>Alarm Importer and Exporter</li>



<li>Alarm Logger</li>
</ul>



<h2 id="h-read-the-other-articles-in-this-series" class="wp-block-heading">Read the Other Articles in this Series</h2>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10609/factorytalk-optix-series-2--variables-attributes-dynamic-links-and-converters">FactoryTalk Optix Series 2 &#8211; Variables, Attributes, Dynamic Links, and Converters</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10610/factorytalk-optix-series-3--netlogic-overview-and-examples">FactoryTalk Optix Series 3 &#8211; NetLogic Overview and Examples</a></li>
</ul>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Build Modern HMI and SCADA Applications with FactoryTalk Optix</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Explore our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/" data-type="page" data-id="420">Automation</a> expertise in <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/rockwell-factorytalk-programming/factorytalk-optix-programming/" data-type="page" data-id="44850">FactoryTalk Optix</a> for flexible visualization, web-based HMIs, C# NetLogic, and industrial data integration.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16514/factorytalk-optix-series-1-getting-started-with-factorytalk-optix/">FactoryTalk Optix Series 1 &#8211; Getting Started with FactoryTalk Optix</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating Custom Graphics for SCADA HMIs with Ignition Perspective and Photoshop</title>
		<link>https://static.dmcinfo.com/blog/18518/creating-custom-graphics-for-scada-hmis-with-ignition-perspective-and-photoshop/</link>
		
		<dc:creator><![CDATA[Lukas Wavrin]]></dc:creator>
		<pubDate>Wed, 11 May 2022 09:23:19 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Ignition]]></category>
		<category><![CDATA[Adobe Photoshop]]></category>
		<category><![CDATA[HMI]]></category>
		<category><![CDATA[Perspective]]></category>
		<category><![CDATA[SCADA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18518/creating-custom-graphics-for-scada-hmis-with-ignition-perspective-and-photoshop/</guid>

					<description><![CDATA[<p>In automation, one of the most requested screens for a SCADA application is the plant or department overview screen. This screen is developed to quickly provide the user an understanding of the manufacturing floor status. Often, the key to an effective overview screen is an effective graphic. This graphic may come in many forms. A [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18518/creating-custom-graphics-for-scada-hmis-with-ignition-perspective-and-photoshop/">Creating Custom Graphics for SCADA HMIs with Ignition Perspective and Photoshop</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">In automation, one of the most requested screens for a SCADA application is the plant or department overview screen. This screen is developed to quickly provide the user an understanding of the manufacturing floor status. Often, the key to an effective overview screen is an effective graphic.</p>

<p class="wp-block-paragraph">This graphic may come in many forms. A steam plant, for example, may utilize a piping and instrumentation diagram (P&amp;ID) to illustrate the movement and temperature of fluids throughout the building. The packaging room of a product manufacturing plant may utilize a CAD drawing of manufacturing equipment with overlays to indicate status. In any case, the graphic should be easily recognizable, quickly interpretable, and useful to a wide range of users.</p>

<p class="wp-block-paragraph">In this blog, we will demonstrate how to create a custom animated graphic that satisfies these requirements for a SCADA application built in Ignition Perspective.</p>

<p class="wp-block-paragraph"><a href="https://inductiveautomation.com/ignition/" target="_blank">Ignition </a>is one of the fastest-growing SCADA/HMI platforms Inductive Automation developed, and <a href="https://inductiveautomation.com/ignition/modules/perspective" target="_blank">Perspective </a>is the web-friendly visualization module that hosts user interfaces accessed from any web browser. Our clients often implement Perspective applications that are simultaneously accessed from industrial HMIs, tablets, laptop computers, and cell phones with ease.</p>

<p class="wp-block-paragraph">The custom graphic created in this tutorial was implemented in the Ignition Perspective SCADA application of a client operating a consumer goods packaging plant. This tutorial is broken into the following sections.</p>

<ol class="wp-block-list">
 <li>Converting existing illustration to a web-friendly format</li>
 <li>Importing drawings to Perspective</li>
 <li>Creating an effective graphic with dynamic bindings</li>
</ol>

<p class="wp-block-paragraph">The following tools are needed to follow along with this guide:</p>

<ul class="wp-block-list">
 <li>Inductive Automation Ignition, including the Perspective module and Designer installation &mdash;</li>
 <li>Adobe Creative Suite, including Photoshop and Illustrator
 <ul class="wp-block-list">
  <li>Note &ndash; free programs, such as <a href="https://www.gimp.org/" target="_blank">Gimp</a>, can also be used to follow this tutorial. Because DMC is a subscriber of the Adobe Creative Suite, which happens to provide some of most efficient tools for the job, these steps are not outlined in detail</li>
 </ul>
 </li>
</ul>

<p class="wp-block-paragraph">Keep reading for step-by-step instructions to convert a 2D CAD drawing to a customizable Perspective graphic.</p>

<h2 class="wp-block-heading">Converting Existing Illustration to SVG</h2>

<p class="wp-block-paragraph">A major benefit of Ignition Perspective is the ability to embed custom scalable vector graphics (SVGs) in the user interface. An SVG is a drawing file, like a CAD or PDF file, consisting of defined paths rather than fixed pixels. This difference allows the graphic to scale predictably without losing definition or quality. Scalability is an excellent quality for a graphic that will be displayed on devices with varying resolution. SVGs provide a path to custom graphics in Perspective without the need for a Designer-based illustration tool like that used in the Vision module.</p>

<p class="wp-block-paragraph"><strong>Option 1: Convert straight to SVG</strong></p>

<p class="wp-block-paragraph">Some drawing files may be imported directly to Adobe Illustrator and saved to an SVG. This is the best-case scenario because only the pixels of interest will be saved from the drawing file. To do this, we simply open the file in Adobe Illustrator, crop if needed, and Export As an SVG. At this stage, ensure each piece of equipment in the drawing is separated into objects with appropriate names. This can be accomplished in Illustrator by creating layers with apt naming prior to export.</p>

<p class="wp-block-paragraph">To confirm your SVG is in the correct format, open it with any text editor. The SVG should consist of some header information describing styles, size, and viewbox as well as a list of path objects. These objects will be displayed in Perspective as individual elements.</p>

<figure class="wp-block-image"><img decoding="async" alt="Example of CSV with single element, &quot;sorterFill.&quot; Note: that path has been cutoff for conciseness." src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_1.png"  /></figure>

<p class="wp-block-paragraph" style="text-align: center;"><em>Figure 1: Example of CSV with single element, &quot;sorterFill.&quot; Note: that path has been cutoff for conciseness.</em></p>

<p class="wp-block-paragraph"><strong>Option 2: Extract drawing with image editing software</strong></p>

<p class="wp-block-paragraph">Other drawing files are not provided in a scalable format or are too complex to be redrawn on your machine. In this case, we can use an image editing software to extract the shapes of interest from the provided drawing.</p>

<p class="wp-block-paragraph"><strong>Step 1: Import illustration to Photoshop (or other photo editing software)</strong></p>

<p class="wp-block-paragraph">For this example, we start with a customer&rsquo;s 2D drawing file in the locked DWG format. Similar processes can be followed for PDFs, DWFs, PNGs, etc. This file contains the top-down drawing of the packaging room floor. Since our photo editing software cannot directly import a DWG file, we will first print the drawing to a high quality TIF image. We will do this with &nbsp;DWG TrueView, a free program from Autodesk. The output filetype is not as important as the quality and size of the image. We only need to convert it to a filetype that our image editing software can process.&nbsp;</p>

<figure class="wp-block-image"><img decoding="async" alt="Import illustration to Photoshop" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_2_Screenshot.png"  /></figure>

<p class="wp-block-paragraph">This TIF file can be dropped into the image editing software. In this guide, we will use Adobe Photoshop. Once dropped into Photoshop, adjust the image to fill your canvas, and rasterize it with the confirmation button.</p>

<figure class="wp-block-image"><img decoding="async" alt="Rasterizing in Photoshop with the confirmation button" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_3.png"  /></figure>

<p class="wp-block-paragraph"><strong>Step 2: Use the Magic Wand tool to select the parts of the drawing to be animated</strong></p>

<p class="wp-block-paragraph"><strong>Hint:</strong> unchecking the &ldquo;Contiguous&rdquo; box in the Magic Wand properties ribbon allows for quick selection of background in grayscale images. In our example, we use the Magic Wand to quickly select all white pixels.<strong> Right click &gt;&nbsp;Select Inverse</strong> yields the selection of all grayscale pixels.&nbsp;</p>

<figure class="wp-block-image"><img decoding="async" alt="Use the Magic Wand tool to select the parts of the drawing to be animated" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_3_Gif_1.gif"  /></figure>

<p class="wp-block-paragraph"><strong>Step 3: Layer Via Copy</strong></p>

<p class="wp-block-paragraph" style="margin-left:.5in;">Right click the selection and create a new layer via copy using the provided menu. The original layer can be disabled to view only the selected pixels.</p>

<p class="wp-block-paragraph"><strong>Step 4: Clean up Selection</strong></p>

<p class="wp-block-paragraph" style="margin-left:.5in;">At this point, we can use our photo editing software&rsquo;s eraser tool to remove pixels from the animation. In our example, we will remove electrical enclosures and repeated hardware.</p>

<figure class="wp-block-image"><img decoding="async" alt="Clean up Selection tool to remove electrical enclosures and repeated hardware" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_4_Gif_2.gif"  /></figure>

<p class="wp-block-paragraph"><strong>Step 5: Separate equipment into unique layers and create Fill Layers</strong></p>

<p class="wp-block-paragraph" style="margin-left:.5in;">Use any selection tools necessary to select and separate the drawing into equipment regions. Separate the regions by right clicking the selections and creating new layers via cut. When finished, we should have a layer for each piece of equipment and nothing else. Delete any background or leftover layers.</p>

<figure class="wp-block-image"><img decoding="async" alt="Separate equipment into unique layers and create Fill Layers" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_5_Gif_3.gif"  /></figure>

<p class="wp-block-paragraph">Once the equipment is separated into layers, each one must be used to create a new Fill Layer. A Fill Layer is needed to vectorize the pixels in preparation for exporting to SVG. First, select all the pixels for a given equipment layer. This can be done by right clicking the layer preview and selecting &ldquo;Select Pixels.</p>

<p class="wp-block-paragraph">Once the pixels are selected, right click the selection, and select &ldquo;Make Work Path.&rdquo;A popup will prompt the user for a tolerance. This setting may be adjusted if results are not satisfactory. For our example, we selected a tolerance of 1 pixel. Images with denser pixel date may not require such a tight tolerance.</p>

<p class="wp-block-paragraph">Create a new Fill Layer using the dropdown navigation: <strong>Layer -&gt; New Fill Layer -&gt; Solid Color</strong>. Select a neutral color, presumably black, and name the layer appropriately. Names selected here will be displayed as properties in the Perspective project object, so they should be intuitive.</p>

<figure class="wp-block-image"><img decoding="async" alt="Create a new Fill Layer using the dropdown navigation: Layer  New Fill Layer  Solid Color" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_6_Gif_4.gif"  /></figure>

<p class="wp-block-paragraph"><strong>Step 6: Export as SVG</strong></p>

<p class="wp-block-paragraph">Once a fill layer is created for each division of equipment, disable all other layers. Only the fill layers should be displayed in the editing window. At this stage, we are ready to export our SVG. Use the dropdown navigation to select Export As, and select SVG from the dropdown menu in the popup that appears.</p>

<figure class="wp-block-image"><img decoding="async" alt="Export as SVG" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_7.png"  /></figure>

<p class="wp-block-paragraph"><strong>Note:</strong> you may want to ensure the drawing is in the proper orientation. This step is not critical but will make responsive resizing in Perspective windows much smoother. Image rotation in Perspective can be accomplished, but it currently requires nesting in a coordinate container.</p>

<h2 class="wp-block-heading">Import SVG to Ignition Perspective Project</h2>

<p class="wp-block-paragraph">Now that the SVG was created from the provided system drawing, it can be imported to the Ignition designer. The easiest way to do this is to drag and drop the file into a blank Perspective view. For this example, we are employing a flex container. Ensure that the SVG is embedded and not linked in the view.</p>

<figure class="wp-block-image"><img decoding="async" alt="Import SVG to Ignition Perspective Project" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_8.png"  /></figure>

<p class="wp-block-paragraph">Once the drawing is embedded, the component will appear in the Project Browser. Browse the `elements` property to ensure that all layers have imported successfully as separate elements.</p>

<p class="wp-block-paragraph">For our example, we set Grow and Shrink properties to 1and allowed the basis to be set automatically. This ensures maximum responsiveness in embedding views. It may also be reasonable to set minHeight and minWidth constraints on the SVG component, or flex container, if needed for a given application.</p>

<h2 class="wp-block-heading">Create Intuitive Overlays and Animations in Perspective</h2>

<p class="wp-block-paragraph">Each element of the SVG component can be customized like other Perspective components. Namely, a &ldquo;style&rdquo; object may be defined for each element to employ standard Perspective CSS-esque customization. For this example, we will be animating/coloring the pieces of equipment drawing based on OPC status tags using Perspective styles.</p>

<p class="wp-block-paragraph"><strong>Step 1: Create Perspective styles</strong></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">For this example, we will use style to change the color and of each piece of equipment. This is not the only way of animating equipment with styles. Border, transparency, and visibility can also be customized for a more inclusive design. Let&rsquo;s first define our &ldquo;alarm&rdquo; class. When this class is applied, we want the equipment to flash between red and black at a fixed rate. Use the Timing and Shape/Fill properties to accomplish this.</p>

<figure class="wp-block-image"><img decoding="async" alt="Create Perspective styles" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_9.png"  /></figure>

<p class="wp-block-paragraph"><strong>Step 2: Create dynamic bindings</strong></p>

<p class="wp-block-paragraph">Once styles have been created, they need to be dynamically assigned to the class property of each element of the SVG. This can be accomplished in a few ways:</p>

<p class="wp-block-paragraph" style="margin-left:.5in;"><strong>Option 1: Create bindings for each element</strong></p>

<p class="wp-block-paragraph" style="margin-left: 80px;">For simple drawings, a binding may be defined for each object in the SVG. For each element, create a &ldquo;style&rdquo; object with a &ldquo;classes&rdquo; value. This value will be bound to the appropriate OPC tag. In our example, we use an indirect tag binding to retrieve the equipment status from tag UDTs. Two transforms are then applied: a script transform to check tag quality &mdash; end user wanted custom error behavior &mdash; and a map transform to select the appropriate predefined style from an enumeration.</p>

<p class="wp-block-paragraph"><figure class="wp-block-image"><img decoding="async" alt="Creating dynamic bindings for each element" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_10.png"  /></figure><figure class="wp-block-image"><img decoding="async" alt="Creating dynamic bindings for each element" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_11_Gif_5.gif"  /></figure></p>

<p class="wp-block-paragraph" style="margin-left: 40px;"><strong>Option 2: Update style classes via scripting</strong></p>

<p class="wp-block-paragraph" style="margin-left: 80px;">For complicated drawings with many pieces of equipment, scripting may be a more efficient use of developer time. Consider creating a timed event or a custom root property with a polling expression binding to execute the following pseudo code:</p>

<figure class="wp-block-image"><img decoding="async" alt="Update style classes via scripting" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_12.png"  /></figure>

<p class="wp-block-paragraph">This allows the styling to be set without configuring individual bindings on each element. For this code to work, the names of SVG elements must match tag names in the tag provider UDT that is supplying status information, and the eqPath parameter of the view must be a valid tag path to a UDT instance.</p>

<p class="wp-block-paragraph">Once our bindings have been created, we are ready to embed the animation throughout the project.</p>

<figure class="wp-block-image"><img decoding="async" alt="Update style classes via scripting" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Photo_13_Gif_5.gif"  /></figure>

<p class="wp-block-paragraph">In this guide, we&apos;ve learned how to create a custom illustration and animation from a 2D drawing file and import it to an Ignition Perspective project. To learn more designing dynamic Perspective projects, see Caz&rsquo;s series of blogs listed below!</p>

<p class="wp-block-paragraph">Learn more about DMC&apos;s <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/ignition-programming">Ignition expertise</a>, and <a href="https://static.dmcinfo.com/contact">contact us</a> to get started on your next <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming">HMI</a>, <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming">SCADA</a>, or <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/manufacturing-execution-systems-services">MES </a>project!</p>

<p class="wp-block-paragraph"><strong>See other blogs related to this topic:</strong> Creating Dynamic Ignition Perspective Projects<br />
<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10250/creating-dynamic-ignition-perspective-projects-part-one-bindings-and-transforms">Part 1: Bindings and Transforms</a><br />
<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10251/creating-dynamic-ignition-perspective-projects-part-2-button-event-actions">Part 2: Button Event Actions</a><br />
<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10252/creating-dynamic-ignition-perspective-projects-part-3-embedded-views-and-flex-containers">Part 3: Embedded Views and Flex Containers</a><br />
<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10253/creating-dynamic-ignition-perspective-projects-part-4-parameters-indirect-bindings-and-flex-repeaters">Part 4: View Parameters, Indirect Bindings, and Flex Repeaters</a></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18518/creating-custom-graphics-for-scada-hmis-with-ignition-perspective-and-photoshop/">Creating Custom Graphics for SCADA HMIs with Ignition Perspective and Photoshop</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How To Setup a WinCC OA Application to Push Data to MindSphere</title>
		<link>https://static.dmcinfo.com/blog/20593/how-to-setup-a-wincc-oa-application-to-push-data-to-mindsphere/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Thu, 07 Nov 2019 10:39:24 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Siemens PLC]]></category>
		<category><![CDATA[Web Application Development]]></category>
		<category><![CDATA[Data Processing]]></category>
		<category><![CDATA[Mindsphere]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[WinCC OA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/20593/how-to-setup-a-wincc-oa-application-to-push-data-to-mindsphere/</guid>

					<description><![CDATA[<p>MindSphere and WinCC OA are two powerful tools offered by Siemens that can allow for streamlined aggregation, processing, and visualization of massive volumes of data. Now thanks to some in-built functions within WinCC OA, you can, with a bit of setup and planning, easily pass your data from your OA application up to your MindSphere [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20593/how-to-setup-a-wincc-oa-application-to-push-data-to-mindsphere/">How To Setup a WinCC OA Application to Push Data to MindSphere</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">MindSphere and <a href="/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC OA</a> are two powerful tools offered by Siemens that can allow for streamlined aggregation, processing, and visualization of massive volumes of data. Now thanks to some in-built functions within WinCC OA, you can, with a bit of setup and planning, easily pass your data from your OA application up to your MindSphere tenant. In this blog, I’ll walk you through the steps of setting up this connection, and I’ll offer some added commentary and advice to make your experience easier.</p>



<h2 id="h-setup-wincc-oa-manual-generation" class="wp-block-heading">Setup: WinCC OA Manual Generation</h2>



<p class="wp-block-paragraph">The first thing you need to do is create your assets in both the WinCC OA project and the MindSphere tenant. I’ll start with the WinCC OA project. <strong>Open Gedi </strong>in your project and from the top toolbar navigate to ‘<strong>SysMgm’ &lt; ‘Settings’ &lt; ‘MindSphere Configuration.’</strong> This will open a window like the one shown below.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="The MindSphere Configuration menu allows you to organize you data structure to meet the needs of your SCADA, IoT, or other types of applications" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/MindSphereConfigurator.png"></p></p>



<p class="wp-block-paragraph">Within here you can manually instantiate datapoints for you MindSphere application. There are three levels of organization to your MindSphere data. At the highest level are assets, then within an asset, there are data sources, and within those data sources, there are datapoints.</p>



<p class="wp-block-paragraph">What exactly defines an asset or data source within your project is up to you. For instance, an asset could represent one of several lines on a factory floor, and each data source could be a machine or PLC used within that line. It is up to you to decide how best to structure your data.</p>



<p class="wp-block-paragraph">To create an asset, simply <strong>right click the whitespace</strong> in the column on the left and select <strong>‘Create MindSphere Asset.’</strong> You can right-click that asset to add a data source and right-click that data source to add datapoints. When creating assets and data sources, all you really configure is the name. When creating datapoints, you must also select a datatype and enter the units. Datatype selection is limited to ints, longs, double, Booleans, and floats, so be aware of this when creating your application. It is also crucial that you do not leave units blank.</p>



<p class="wp-block-paragraph">To map your OA data point to a data point in an asset in MindSphere, the units on the two data points must match exactly. We’ll touch more on this later.</p>



<h2 id="h-setup-wincc-oa-scripted-generation" class="wp-block-heading">Setup: WinCC OA Scripted Generation</h2>



<p class="wp-block-paragraph">If you are working with a large volume of datapoints, then manually entering them all, as I showed above, can be impractical. Fortunately, there is a way to script the generation of these points. Whenever an asset, source, or point is created in the MindSphere Configuration menu, an internal datapoint is created in Para of the type<strong> _MC_Asset, _MC_Datapoint</strong>, or<strong> _MC_Datasource</strong> respectively.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="The structure of the internal datapoints created in Para by the MindSphere Configuration tool" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/InternalPoint.png"></p></p>



<p class="wp-block-paragraph">What this means is that you can write a script that uses the <strong>dpCreate</strong> and <strong>dpSet</strong> functions to create your data structure and populate some necessary fields. You must be careful when doing this, though, to set up your data correctly. Make sure your asset’s DataSources is populated with the names of all associated data sources.</p>



<p class="wp-block-paragraph">Do the same for making sure the data source has its associated points and assets entered and that the points have their associated data source. Don’t forget to set your points’ unit and type as well. Type is represented by an integer from 1 to 5, where each number equates to one of the datatypes mentioned earlier. Try first making a simple data structure as I did here and dig around the generated internal points, so you understand how it’s all supposed to be set up.</p>



<h2 id="h-setup-mindconnect-lib-asset" class="wp-block-heading">Setup: MindConnect Lib Asset</h2>



<p class="wp-block-paragraph">Next, we will create our <strong>MindConnect Lib asset</strong>. The MindConnect Lib assets are what your assets in OA are going to establish a connection with an upload data to. There is a one to one relation between MindConnect Lib assets in the tenant and assets in your OA project so you will need to make one MindConnect Lib asset for each asset in your OA project.</p>



<p class="wp-block-paragraph">From your home page in MindSphere, go to the asset manager and select <strong>‘Create asset.’</strong> Select <strong>MindConnectLib</strong> and give your asset a name.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="MindSphere offers assets designed for applications with IoT, OPC UA and much more but here we are interested in the MindConnectLib asset type" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/MindConnectLib.png"></p></p>



<p class="wp-block-paragraph">Next, we’ll set up our connection to the OA asset. Click the large button with the puzzle piece on it and select your preferred security profile.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="MindSphere is the missing piece to the puzzle that is making a complete Cloud based data solution for your Industry 4.0 application" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/MCLAsset.png"></p></p>



<p class="wp-block-paragraph">I’ve used <strong>SHARED_SECRET</strong> for all of my applications. After hitting continue, you’ll be taken to another screen with the boarding configuration. Click the buttons to generate a boarding key and copy it to your clipboard.</p>



<p class="wp-block-paragraph">Now go back to the OA MindSphere configuration menu, click on your asset, and paste the onboarding key into the white box then hit the upload button at the bottom.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Once your asset is onboarded you've established a connection between your MindSphere Tenant and OA project" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Onboarding.png"></p></p>



<p class="wp-block-paragraph">Your assets in the OA project and tenant are now connected. You’ll notice that the Configuration ID has been filled in for your asset and all associated datapoints. Now, if&nbsp;you go back to your asset in the MindSphere tenant and click the button with the puzzle piece on it, you’ll be taken to a new screen.</p>



<p class="wp-block-paragraph">Here you can see the configuration of your asset and its data mappings. The configuration shown should match exactly with what you set up in OA.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="The configuration displayed here should match exactly with your OA configuration" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TenantConfig.png"></p></p>



<h2 id="h-setup-mindsphere-assets-for-data-mapping" class="wp-block-heading">Setup: MindSphere Assets for Data Mapping</h2>



<p class="wp-block-paragraph">To actually work with and visualize the data that you’re sending to you MindConnect Lib asset, you need to create assets to map that data to. To do this, you will need to create some aspects and types. Both aspects and types are configurable data structures. A type will contain aspects, and you’ll create instances of types in the assets menu like how you create the MindConnect Lib asset.</p>



<p class="wp-block-paragraph">Similar to the structure of the MindSphere configuration in the OA project, it’s up to you to decide how best to structure your data. To make an aspect, go to your tenant’s asset manager, select <strong>‘Aspects’</strong> from the menu on the left, and select <strong>‘Create aspect.’</strong> Add at least one variable to make a valid aspect and make sure to set a ‘Unit’ value that exactly matches the units you set up in OA for the data point you intend to map to it. You will not be allowed to map your data points if the units don’t match.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="A simple aspect containing only one data point. Remember to match aspect units to units set on Datapoints in the OA configuration" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Aspect.png"></p></p>



<p class="wp-block-paragraph">Similar to how you created an aspect, you will now create a type. Types are just another layer in the data hierarchy of MindSphere. Types can contain variables, aspects, and have an associated image for an organization. Additionally, an instance of a Type is an asset, whereas you cannot instantiate aspects as assets.</p>



<p class="wp-block-paragraph">Add whatever aspects and variables seem sensible for your type, but be aware that you cannot map your OA data points to the standalone variables in a type. They must be mapped to a datapoint in an aspect in that particular type.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="A simple type containing my aspect and an extra variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TestType.png"></p></p>



<p class="wp-block-paragraph">Now go back to assets and create an instance of the type you just created. Go to the Configuration/Data mappings page for your MindConnect Lib asset and go to the <strong>Data mappings tab</strong>. If you expand the data structure you should see a button that says<strong> ‘Link variable’ </strong>for each data point. Click on that and navigate to the appropriate data point in the instance of the custom type that you created.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Data must be mapped from the MindConnectLib asset to a custom type to be viewed and processed" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/DataMapping.png"></p></p>



<p class="wp-block-paragraph">Once mapped, it should look something like the above image. Something significant to note is that these datapoint mappings are somewhat fragile, and any changes made to your OA assets, like adding points or sources or changes units, will undo these mappings. For that reason, you should try to finalize your data structure as much as possible before going through the effort of mapping points.</p>



<h2 id="h-pushing-data-to-mindsphere" class="wp-block-heading">Pushing Data to MindSphere</h2>



<p class="wp-block-paragraph">You have now made all the necessary arrangements and are ready to push that data up to MindSphere from your OA project. I’ve made a straightforward script that goes over all the essential actions that must be done to upload data.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#uses "classes/mindSphere/MindSphereAsset"

// Example script showing how to push data from OA to MindSphere

main()
{
    // Instantiate a MindSphere asset
    MindSphereAsset asset = MindSphereAsset("TestAsset");

    // Generate sample values
    dyn_int testValues = makeDynInt(
        13,
        67,
        89
    );

    // Create timestamps for the samples
    time currentTime = getCurrentTime();

    dyn_time times = makeDynTime(
        currentTime - 2,
        currentTime - 1,
        currentTime
    );

    // Prepare values for upload
    int err = asset.prepareValues(
        "TestPoint1",
        testValues,
        times
    );

    // Upload values to MindSphere
    err = asset.uploadPreparedValues();

    if (err == 0)
    {
        DebugN("Upload Successful!");
    }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">#uses &quot;classes/mindSphere/MindSphereAsset&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">// Example script showing how to push data from OA to MindSphere</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">main()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    // Instantiate a MindSphere asset</span></span>
<span class="line"><span style="color: #D4D4D4">    MindSphereAsset asset = MindSphereAsset(&quot;TestAsset&quot;);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    // Generate sample values</span></span>
<span class="line"><span style="color: #D4D4D4">    dyn_int testValues = makeDynInt(</span></span>
<span class="line"><span style="color: #D4D4D4">        13,</span></span>
<span class="line"><span style="color: #D4D4D4">        67,</span></span>
<span class="line"><span style="color: #D4D4D4">        89</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    // Create timestamps for the samples</span></span>
<span class="line"><span style="color: #D4D4D4">    time currentTime = getCurrentTime();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    dyn_time times = makeDynTime(</span></span>
<span class="line"><span style="color: #D4D4D4">        currentTime - 2,</span></span>
<span class="line"><span style="color: #D4D4D4">        currentTime - 1,</span></span>
<span class="line"><span style="color: #D4D4D4">        currentTime</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    // Prepare values for upload</span></span>
<span class="line"><span style="color: #D4D4D4">    int err = asset.prepareValues(</span></span>
<span class="line"><span style="color: #D4D4D4">        &quot;TestPoint1&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">        testValues,</span></span>
<span class="line"><span style="color: #D4D4D4">        times</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    // Upload values to MindSphere</span></span>
<span class="line"><span style="color: #D4D4D4">    err = asset.uploadPreparedValues();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    if (err == 0)</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">        DebugN(&quot;Upload Successful!&quot;);</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Note the steps in the above script. You must first instantiate your asset within your script via the MindSphereAsset function. The string inputted here must be identical to the name of the asset you created earlier in the configuration menu.</p>



<p class="wp-block-paragraph">Next, I make an array of sample data to upload. You can also upload points one at a time, but it will be more computationally intensive. For every bit of data that you create, you also need a timestamp. Here I take the current time then have offsets by one and two seconds. Before you upload your values, you must prepare the values for upload.</p>



<p class="wp-block-paragraph">The first input here is the name of the datapoint you’re uploading to, and it must match exactly with the name of the intended datapoint. After you’ve prepared your values, call <strong>asset.uploadPreparedValues</strong> to upload all values that have been prepared for that asset since the last successful attempt to upload values. You can call asset.prepareValues as many times as is necessary before executing the upload, and uploading data in large batches rather than small chunks will be a lot faster computationally.</p>



<p class="wp-block-paragraph">If the upload was successful, then the value of <strong>err</strong>, the output from the upload function, should be equal to zero.</p>



<h2 id="h-viewing-your-data-in-mindsphere" class="wp-block-heading">Viewing Your Data in MindSphere</h2>



<p class="wp-block-paragraph">There’s a ton that you can do with your data once it’s in MindSphere, but that’s a whole different discussion, so here we are simply going to view the time series of our data. To view your data, go back to the home page of your MindSphere tenant and navigate to the <strong>Fleet Manager</strong>. Search for the instance of your custom Type that you created and click on it. The page should then show all the aspects associated with your type in the central window. Click on an aspect to see the time series of incoming data. To view data that cannot be graphed, like strings and Booleans, click on the checkerboard looking button in the bottom right corner under the graph.</p>



<p class="wp-block-paragraph">As you can see in the figure below, there are two instances of the three values I sent with my simple script because I ran the script twice.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="Time series data is conveniently easy to view in the Fleet Manager." src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ViewData.png"></p></p>



<h2 id="h-final-tips" class="wp-block-heading">Final Tips</h2>



<ul class="wp-block-list">
<li>Take time to plan out your data organization in advance.
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>The systems of aspects, types, and assets and points, sources, and assets can seem convoluted at first, but if you take the time to plan out your project, then these organizational layers can prove very useful.</li>


 </ul>
</li>



<li>Be careful of breaking your tag mappings in MindSphere.
 
 
<ul class="wp-block-list" style="list-style-type:circle;">
  

<li>Remember that making any changes to your OA asset configuration will break all of your tag mappings, and you will have to delete and reestablish those mappings manually. This is another reason to have a good organization plan in mind before digging into things.</li>


 </ul>
</li>



<li>One call to Upload 1000 datapoints is a lot faster than 1000 calls to upload one datapoint each.</li>
</ul>



<p class="wp-block-paragraph">Learn more about DMC&#8217;s <a href="/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC OA services</a> and our <a href="/services/manufacturing-automation-and-intelligence/plc-programming/siemens-s7-plc-programming">Siemens expertise</a>. <a href="/contact">Contact us</a> with any inquiries.&nbsp;</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20593/how-to-setup-a-wincc-oa-application-to-push-data-to-mindsphere/">How To Setup a WinCC OA Application to Push Data to MindSphere</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Siemens WinCC OA Open Library</title>
		<link>https://static.dmcinfo.com/blog/21086/siemens-wincc-oa-open-library/</link>
		
		<dc:creator><![CDATA[Leon Grossman]]></dc:creator>
		<pubDate>Tue, 20 Aug 2019 11:07:51 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[Siemens PLC]]></category>
		<category><![CDATA[Open Library]]></category>
		<category><![CDATA[openplclibrary.com]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[Siemens]]></category>
		<category><![CDATA[WinCC OA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/21086/siemens-wincc-oa-open-library/</guid>

					<description><![CDATA[<p>The Siemens WinCC OA Open Library Version 1.0 is now live, and the website is up to date with the latest version and release notes. History WinCC OA is provided to users as a clean sheet. It has incredibly powerful ways of creating reusable and self-configuring objects, but this is “an exercise left to the [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/21086/siemens-wincc-oa-open-library/">Siemens WinCC OA Open Library</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The <strong><a href="https://openplclibrary.com/" target="_blank">Siemens WinCC OA Open Library</a> Version 1.0</strong> is now live, and <a href="https://openplclibrary.com/#latest-versions">the website</a> is up to date with the latest version and release notes.</p>



<h2 class="wp-block-heading" id="h-history">History</h2>



<p class="wp-block-paragraph">WinCC OA is provided to users as a clean sheet. It has incredibly powerful ways of creating reusable and self-configuring objects, but this is “an exercise left to the user,” as my old college professors would say. Rather than continually reinvent the wheel each project, we decided to distill best practices into a set of tools that integrate seamlessly into the <a href="https://openplclibrary.com/">Siemens PLC Open Library</a>. This resulted in the <a href="/latest-thinking/blog/id/9477/siemens-open-library-version-16-and-wincc-oa-open-library-alpha-release">alpha version</a> of a WinCC OA Open library in July 2017.</p>



<p class="wp-block-paragraph">This initial version was a great start for clarifying how to use the new WinCC OA Object-Oriented CTRL++ language that had just been released. Several revisions later, we have an extensible code base covering the key elements of the PLC Open Library and are ready to share it with the world.</p>



<h2 class="wp-block-heading" id="h-components">Components</h2>



<p class="wp-block-paragraph">This latest version has implemented the critical portions of the PLC Open Library with objects for:</p>



<ul class="wp-block-list">
<li>Motor &#8211; Contactor</li>



<li>Motor &#8211; VFD</li>



<li>Pump &#8211; Contactor</li>



<li>Pump &#8211; VFD</li>



<li>Valve &#8211; Solenoid</li>



<li>Valve &#8211; Analog</li>



<li>System Control Object</li>



<li>Interlock Object</li>



<li>PID Compact Object</li>
</ul>



<p class="wp-block-paragraph">There are plenty of helper objects, such as the text indicator and entry objects not listed here that are used by the objects above. These can often be utilized by themselves as part of your project or embedded into your own custom objects!</p>



<h2 class="wp-block-heading" id="h-look-and-feel">Look and Feel</h2>



<p class="wp-block-paragraph">These objects have behavior and visualization that is similar to the <a href="/latest-thinking/blog/id/9896/siemens-open-library-version-40-release">PLC Open Library</a> while still extending the functionality to provide for the benefits of using WinCC OA.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/WaterSystemDevScreen.png" alt="WATER SYSTEM DEV SCREEN"/></figure>



<p class="wp-block-paragraph">One of those extra benefits that WinCC OA provides is the ability to use color schemes. Color schemes are sets of named colors that can be swapped into place on a system during runtime. This ability allows for implementations like day/night mode.</p>



<p class="wp-block-paragraph">In this case, we implemented the DMC Open Library standard color set and a High-Performance HMI color set. You can create your own color set and customize the color scheme to whatever works for your project.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/color-schemes.png" alt=""/></figure>



<h2 class="wp-block-heading" id="h-utilities">Utilities</h2>



<p class="wp-block-paragraph">Tag creation in SCADA systems can be a daunting task. This task is especially true when you have smart objects with a rich tag structure like the PLC Open Library.</p>



<p class="wp-block-paragraph">As a result, we needed to create a better way to manage tag generation for the Open Library. The included tool allows a DB export from a Siemens PLC to be converted to an import file for WinCC OA. With the included capability to handle descriptions, units, formatting, and naming, the work of days can be reduced to minutes with this tool!</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/import-app.png" alt=""/></figure>



<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>



<p class="wp-block-paragraph">WinCC OA is a very powerful platform that gives the user a level of flexibility and capability not seen in other platforms. This power comes at the cost of increased development effort to create a set of objects for any given project.</p>



<p class="wp-block-paragraph">The Open Library toolset helps bring a robust set of pre-built objects to WinCC OA and provides a base to build new objects from without having to start from a clean sheet each time.</p>



<p class="wp-block-paragraph">Learn more about DMC&#8217;s <a href="/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming">HMI Programming</a> and <a href="/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC OA services and expertise</a>. <a href="/contact">Contact us</a> for more information or any project inquiries.</p>
<p>The post <a href="https://static.dmcinfo.com/blog/21086/siemens-wincc-oa-open-library/">Siemens WinCC OA Open Library</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Customizing HMI Alarm Text in TIA Portal</title>
		<link>https://static.dmcinfo.com/blog/25295/customizing-hmi-alarm-text-in-tia-portal/</link>
		
		<dc:creator><![CDATA[Jason Mayes]]></dc:creator>
		<pubDate>Tue, 16 Aug 2016 13:01:15 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Houston]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Siemens PLC]]></category>
		<category><![CDATA[HMI]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[WinCC]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/25295/customizing-hmi-alarm-text-in-tia-portal/</guid>

					<description><![CDATA[<p>Recently, I found the need to create customizable text for&#160;some alarms in a TIA Portal project. In this particular case, I needed to include the name of the operator that was monitoring the machine for traceability, as well as some specific machine information (process tag value) when the alarm occurred. Knowing this must be possible, [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/25295/customizing-hmi-alarm-text-in-tia-portal/">Customizing HMI Alarm Text in TIA Portal</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Recently, I found the need to create customizable text for&nbsp;some alarms in a TIA Portal project. In this particular case, I needed to include the name of the operator that was monitoring the machine for traceability, as well as some specific machine information (process tag value) when the alarm occurred. Knowing this must be possible, I set off to Google, the Siemens forums, and the TIA Portal help files. Surprisingly, I was not able to find very good documentation or examples online. However, the answer turned&nbsp;out to be incredibly simple so I thought it would be worth sharing in case anyone else is ever looking for the same information.</p>

<p class="wp-block-paragraph">For my example, I will demonstrate on a&nbsp;TP700 Comfort Panel, although the same basic procedure can be used for a Basic Panel or an Advanced Runtime system. To start things off, I&apos;ve created three internal HMI tags: An alarm word (<em>UInt</em>) for triggering of my example alarm, a <em>string </em>to contain the name of the logged in user, and a <em>real </em>tag for my process value example.<br />
<br />
<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ExampleTags.png"  /></figure></p>

<p class="wp-block-paragraph">First, I&apos;ve written a short script to capture the name of the logged in user and created a task to call my script on any user change event. Obviously, this part of the demo is specific to WinCC Comfort or Advanced as the Basic panel will not support scripting, but it will not affect our alarm text demo. Next, I&apos;ve created&nbsp;several users&nbsp;to allow myself to log in to our example HMI.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ScriptExample.png"  /></figure>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TaskSetup.png"  /></figure>

<p class="wp-block-paragraph">Now I&apos;ve created a single discrete alarm, triggered off of Bit 0 of my alarm word with some simple static text, &quot;Max Speed Limit Exceeded.&quot;</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/StaticAlarmText.png"  /></figure>

<p class="wp-block-paragraph">Let&apos;s pretend for the moment, though, that we would like to include the actual limit in the alarm text for both display and posterity, as well as the operator that forced the system to exceed that limit. If the limit was not configurable, we could hard code it in the message. And if there were only a few users, we could potentially create an alarm for each user. However, if users can be created dynamically and the limit is a configurable parameter, there is no way of creating all of the possible alarm messages that may occur. Luckily, we can create dynamic alarm text.</p>

<p class="wp-block-paragraph">To create dynamic alarm text, select the alarm from the alarm list and view alarm properties. Now, right-click in the &quot;Alarm Text&quot; field and you will see two options: &quot;Insert tag field&#8230;&quot; and &quot;Insert text list field&#8230;&quot;</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TextFieldOptions.png"  /></figure>

<p class="wp-block-paragraph">I&apos;m going to use &quot;Tag Field.&quot; Notice that when you select it, a dialog will open allowing you to configure the field. In this example, I will use the process value tag I previously created, and configure it to display as a decimal with length three. As you can see, it is also possible to use Text Lists directly within an alarm, which allows you to create even more dynamic alarms.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ProcessTagSelection.png"  /></figure>

<p class="wp-block-paragraph">Next, I added in an additional tag to display the name of the operator.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/UserNameTagSelection.png"  /></figure>

<p class="wp-block-paragraph">That&apos;s it. Now I&apos;m going to set up a quick example screen with an alarm viewer and controls for setting my process tag and triggering my alarm, as well as displaying the currently logged in user. Now if I trigger my alarm, you can see that my alarm text is dynamically generated.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/MultipleAlarms.png"  /></figure>

<p class="wp-block-paragraph">I hope this is helpful!</p>

<p class="wp-block-paragraph">Learn more about&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming">DMC&apos;s PLC Programming services</a>&nbsp;and&nbsp;<a href="https://static.dmcinfo.com/contact">contact us</a>&nbsp;to get started on your next PLC Programming project.</p>
<p>The post <a href="https://static.dmcinfo.com/blog/25295/customizing-hmi-alarm-text-in-tia-portal/">Customizing HMI Alarm Text in TIA Portal</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
