Added resources files

This commit is contained in:
nika 2025-05-01 00:04:09 -07:00
parent 32d800d9e5
commit 37d47123af
224 changed files with 158551 additions and 0 deletions

View File

@ -0,0 +1,879 @@
import com.amazonaws.services.s3.AmazonS3ClientBuilder as AmazonS3ClientBuilder
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest as GeneratePresignedUrlRequest
import com.amazonaws.HttpMethod as HttpMethod
import boto3
from botocore.client import BaseClient
from botocore.exceptions import ClientError
import json
from pprint import pformat
from urllib2_aws4auth import aws_urlopen, Request
from urllib2 import HTTPError
from urllib import urlencode
from helper.helper import sanitize_tree
from loggerConfig import getLogger
REGION_NAME = 'us-east-1'
LOGGER = getLogger('S3Manager', 'debug')
def getPresignedURL(self, objectKey):
"""
Generates a uri to retrieve images from an S3 bucket.
Bucket names are globally unique so different regions
must use a prefix for the bucket name.
Region and prefix are stored as custom session variables.
Args:
self: Refrence to the object calling the function.
param2: key to the s3 object returned.
Returns:
s3 Url to display the image in S3.
Raises:
KeyError: None.
"""
bucket_names = {"eu":"ignition-image-repo", "na":"ignition-image-repo-na",
"jp":"jp-ignition-image-repo"}
# aws = system.tag.readBlocking("Configuration/aws")[0].value
# aws = system.util.jsonDecode(aws)
# clientRegion = aws.get("region")
# prefix = aws.get("prefix")
clientRegion = self.session.custom.aws.region
prefix = self.session.custom.aws.prefix
bucketName = bucket_names.get(prefix, "ignition-image-repo")
s3Client = AmazonS3ClientBuilder.standard().withRegion(clientRegion).build();
generatePresignedUrlRequest = GeneratePresignedUrlRequest(bucketName, objectKey).withMethod(HttpMethod.GET);
url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
return url
S3_REPO_BUCKET_NAME = 'ignition-image-repo-na'
S3_SOURCE_BUCKET_NAME = 'ignition-image-source-na'
# api stage config
API_STAGES = ['beta', 'prod']
API_REGIONS = ['na', 'eu']
STAGE_CONFIG = {
'beta': {
'na': {
'region': 'us-east-1',
'lambda_name': 'RMESDScadaS3ManagementFlaskLambda-beta',
'endpoint': 'https://us-east-1.beta.scada-s3-management.scada.eurme.amazon.dev/',
'repo_bucket': 'ignition-image-repo-na',
'source_bucket': 'ignition-image-source-na',
's3_region': 'us-east-1',
'account_id': '006306898152',
'api_call_role': 'arn:aws:iam::604741092380:role/RMESDScadaS3ManagementAPIcallRole-beta-us-east-1'
},
'eu': {
'region': 'eu-west-2',
'lambda_name': 'RMESDScadaS3ManagementFlaskLambda-beta',
'endpoint': 'https://eu-west-2.beta.scada-s3-management.scada.eurme.amazon.dev/',
'repo_bucket': 'ignition-image-repo',
'source_bucket': 'ignition-image-source',
's3_region': 'eu-west-1',
'account_id': '006306898152',
'api_call_role': 'arn:aws:iam::604741092380:role/RMESDScadaS3ManagementAPIcallRole-beta-eu-west-2'
}
},
'prod': {
'na': {
'region': 'us-east-2',
'lambda_name': 'RMESDScadaS3ManagementFlaskLambda-prod',
'endpoint': 'https://us-east-2.scada-s3-management.scada.eurme.amazon.dev/',
'repo_bucket': 'ignition-image-repo-na',
'source_bucket': 'ignition-image-source-na',
's3_region': 'us-east-1',
'account_id': '006306898152',
'api_call_role': 'arn:aws:iam::609617486056:role/RMESDScadaS3ManagementAPIcallRole-prod-us-east-2'
},
'eu': {
'region': 'eu-west-1',
'lambda_name': 'RMESDScadaS3ManagementFlaskLambda-prod',
'endpoint': 'https://eu-west-1.scada-s3-management.scada.eurme.amazon.dev/',
'repo_bucket': 'ignition-image-repo',
'source_bucket': 'ignition-image-source',
's3_region': 'eu-west-1',
'account_id': '006306898152',
'api_call_role': 'arn:aws:iam::609617486056:role/RMESDScadaS3ManagementAPIcallRole-prod-eu-west-1'
}
}
}
OPERATION_MAP = {
'download': {
'method': 'GET',
'reqd_args': ['bucket', 'obj_key']
},
'get_presigned_url': {
'method': 'GET',
'reqd_args': ['bucket', 'obj_key']
},
'list_objects': {
'method': 'GET',
'reqd_args': ['bucket']
},
'list_object_versions': {
'method': 'GET',
'reqd_args': ['bucket']
},
'list_object_delete_markers': {
'method': 'GET',
'reqd_args': ['bucket']
},
'delete': {
'method': 'DELETE',
'reqd_args': ['bucket', 'obj_key']
},
'upload': {
'method': 'PUT',
'reqd_args': ['bucket', 'obj_key', 'obj_data']
},
'add_new_site': {
'method': 'PUT',
'reqd_args': ['site', 'bucket']
},
'copy_single': {
'method': 'POST',
'reqd_args': ['source_bucket', 'dest_bucket', 'source_key', 'dest_key']
},
'fetch_site_list': {
'method': 'GET',
'reqd_args': ['bucket']
},
'fetch_object_list_by_site_and_bucket': {
'method': 'GET',
'reqd_args': ['site', 'bucket']
},
'fetch_upload_url': {
'method': 'PUT',
'reqd_args': ['bucket', 'obj_key', 'region', 'content_type']
},
'query_audit_table': {
'method': 'POST',
'reqd_args': []
}
}
class S3Manager(object):
"""
This class contains convenience methods for working with S3 objects from Ignition python 2.7
"""
def __init__(self, api_stage='prod', api_region_name='na', username='', profile_name=None):
"""
Instantiates an S3 Class.
:param api_stage: str; (default='prod') api target stage (and default S3 folder)
:param api_region_name: str; (default='na') api target region (and account)
:param username: str; ignition session username (from `session.props.auth.user.userName`)
:return: None
"""
self._logger = LOGGER
# sanitize api stage and region values
if api_stage not in API_STAGES:
self._logger.info("`api_stage` must be one of: %s, received: %s" % (API_STAGES, api_stage))
api_stage = 'prod'
if api_region_name not in API_REGIONS:
self._logger.info("`api_region_name` must be one of: %s, received: %s" % (API_REGIONS, api_region_name))
api_region_name = 'na'
self._api_stage = api_stage
self._api_region_name = api_region_name
# grab stage config for this instance from global object
self._stage_config = STAGE_CONFIG.get(api_stage, STAGE_CONFIG['prod']).get(api_region_name, STAGE_CONFIG['prod']['na'])
d = self._stage_config
self._api_region = d.get('region', 'us-east-2')
self._s3_region = d.get('s3_region', 'us-east-1')
self._repo_bucket = d.get('repo_bucket', 'ignition-image-repo-na')
self._source_bucket = d.get('source_bucket', 'ignition-image-source-na')
self._lambda_name = d.get('lambda_name', 'RMESDScadaS3ManagementFlaskLambda-prod')
self._account_id = d.get('account_id', '006306898152')
self._endpoint = d.get('endpoint', 'https://us-east-2.scada-s3-management.scada.eurme.amazon.dev/')
self._service = 'execute-api'
if profile_name:
self._creds = boto3.Session(profile_name=profile_name).get_credentials()
# Define an opener method. The opener will apply AWS Sigv4 signing to requests
self._opener = aws_urlopen(
self._creds.access_key,
self._creds.secret_key,
self._api_region,
self._service,
session_token=self._creds.token,
verify=False
)
else:
# DEVNOTE: As the API has been segregated from the AWS account for the dev server, assume a dedicated role here
sts_client = boto3.Session().client('sts')
role_arn = d.get('api_call_role', None)
if role_arn:
response = sts_client.assume_role(RoleArn=role_arn, RoleSessionName='ignition-s3-mgmt-client')
creds = response['Credentials']
# Define an opener method. The opener will apply AWS Sigv4 signing to requests
self._opener = aws_urlopen(
creds['AccessKeyId'],
creds['SecretAccessKey'],
self._api_region,
self._service,
session_token=creds['SessionToken'],
verify=False
)
else:
# use native boto3 creds if 'api_call_role' not defined in STAGE_CONFIG
self._creds = boto3.Session(profile_name=profile_name).get_credentials()
self._opener = aws_urlopen(
self._creds.access_key,
self._creds.secret_key,
self._api_region,
self._service,
session_token=self._creds.token,
verify=False
)
self._headers = {'Content-type': 'application/json', 'X-Remote-User': username}
def _send(self, operation='download', params={}, print_resp=False, **kwargs):
"""
private method to compile and send the request to api endpoint
:param operation: str; api endpoint method for request (See `OPERATION_MAP` for options)
:param params: dict; dictionary of parameters to pass to request (See `OPERATION_MAP` for reqd args)
:param print_resp: bool; if True, the associated logger will receive a print statement of the raw response, pprint.format'd
:return resp: dict; response object from api
"""
l = self._logger
if operation not in OPERATION_MAP.keys():
msg = 'operation "%s" is not a valid S3Manager operation! Options: %s' % (operation, list(OPERATION_MAP.keys()))
l.error(msg)
raise InvalidOperationS3Manager(msg)
op_config = OPERATION_MAP[operation]
method = op_config['method']
reqd_args = op_config['reqd_args']
missing_args = [x for x in reqd_args if x not in params.keys()]
if len(missing_args):
msg = 'The following required args were not provided in params for "%s" operation: %s' % (operation, missing_args)
l.error(msg)
raise InvalidParametersS3Manager(msg)
if method in ('GET', 'DELETE'):
querystring = '?%s' % urlencode(params)
payload = None
url = self._endpoint + operation + querystring
else:
try:
payload = json.dumps(params)
l.debug('payload for %s operation successfully serialized' % operation)
except:
payload = urlencode(params)
l.debug('payload for %s operation not serialized using json.dumps(), instead used urlencode()' % operation)
url = self._endpoint + operation
# Create a request object
req = Request(url=url, method=method, headers=self._headers, data=payload)
# open the request and process the read
try:
# use self._opener to sign and send the prepared request
resp = self._opener(req)
data = json.loads(resp.read())
if print_resp:
l.info('Response data: %s' % pformat(sanitize_tree(data)))
return data
except HTTPError, e:
try:
body = json.loads(e.fp.read())
e_msg = body.get('message', e.reason)
msg = 'Error sending S3Manager request: %s. Message: %s' % (str(e), e_msg)
l.error(msg)
raise HTTPErrorS3Manager(e.code, e_msg)
except AttributeError, e2:
# failed to extract reason or code from urllib2.HTTPError for some reason
import traceback
msg = 'Failed to extract reason and/or error code from urllib2.HTTPError. Trace: %s' % traceback.format_exc()
l.error(msg)
msg = 'Error sending S3Manager request: %s' % (str(e))
l.error(msg)# raise HTTPErrorS3Manager(e.code, msg)
raise HTTPErrorS3Manager(400, msg)
def upload(self, obj_data, obj_key, bucket=None, content_type='', region=None, **kwargs):
"""
Method to upload a JSON object to S3. Converts S3 to a compressed binary parquet file, then writes
the file to S3.
:param obj_data: JSON data object to upload to S3
:param obj_key: Path and object name of the object to create in S3
:param bucket: S3 bucket to write data to.
:param content_type: str; 'application/json' for json files, 'image/svg+xml' for svg files
:param region: AWS region that hosts the target S3 bucket.
:return: Boto3 `put_object` response
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Uploading %s dataset to bucket %s' % (obj_key, bucket))
l.debug('++ Storing data file in S3')
operation = 'upload'
# check the suffix of obj_key and auto-populate content_type accordingly
if obj_key.endswith('json'):
content_type = 'application/json'
elif obj_key.endswith('svg'):
content_type = 'image/svg+xml'
elif obj_key.endswith('drawio'):
content_type = 'binary/octet-stream'
try:
if isinstance(obj_data, dict):
# serialize the object to a JSON string
obj_data = json.dumps(obj_data)
msg = '++ Uploading. Successfully serialized (json dump) object data for %s' % obj_key
l.debug(msg)
else:
msg = 'Uploading. Type of incoming object data: %s' % type(obj_data)
l.debug(msg)
except:
import traceback
msg = '++ Uploading. Error trying to serialize (json dump) object data: %s' % traceback.format_exc()
l.error(msg)
return msg
# params = {
# 'bucket': bucket,
# 'obj_key': obj_key,
# 'obj_data': obj_data,
# 'content_type': content_type,
# 'region': region
# }
# try:
# resp = self._send(operation, params, print_resp=kwargs.get('print_resp', False))
# l.debug('** Uploading Complete. Successfully uploaded %s' % obj_key)
# return resp
# except HTTPErrorS3Manager, e:
# return {'code': e.code, 'message': e.message}
# DEVNOTE: As there is a 10mb limitation on payload size to API gateway calls, going to use the
# `fetch_upload_url` method to get a presigned upload link and upload via system.net.httpPut
# so the above code will be commented out to use the below code
params = {
'bucket': bucket,
'obj_key': obj_key,
'region': region,
'content_type': content_type
}
try:
upload_url = self.fetch_upload_url(**params)
l.debug('** Fetching Upload URL Complete for object key: %s' % obj_key)
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
try:
# DEVNOTE: Test code below to upload to pre-signed S3 PUT url using urllib2_aws4auth module
# Create a request object using urllib2_aws4auth.Request and aws_urlopen methods
# see if this is limited like with the upload call to API gateway.
# system.net.httpPut call below is not limited
# Results: what works with `system.net.httpPut` fails with `urllib2_aws4auth` module (returns 400: BadRequest)
# if the file is > ~ 75 kb
# req = Request(url=upload_url, method='PUT', headers=self._headers, data=obj_data)
# resp = self._opener(req).read()
# msg = '** Successfully uploaded %s to %s bucket!\nResponse: %s' % (obj_key, bucket, pformat(resp))
resp = system.net.httpPut(upload_url, putData=obj_data, contentType=content_type)
msg = '** Successfully uploaded %s to %s bucket!' % (obj_key, bucket)
l.debug(msg)
return {'code': 200, 'message': msg}
except Exception, e:
msg = '++ Error uploading %s to %s bucket: %s' % (obj_key, bucket, str(e))
l.error(msg)
return {'code': 400, 'message': msg}
def fetch_upload_url(self, obj_key, bucket=None, region=None, expiration=3600, content_type="image/svg+xml", **kwargs):
"""
Retrieves a pre-signed URL for the obj key and bucket and the `put_object` client method.
Caller then uses pre-signed URL to upload the file to S3 directly.
:param obj_key: Path and object name of the object to create in S3
:param bucket: S3 bucket to write data to.
:param region: AWS region that hosts the target S3 bucket.
:param expiration: int; number of seconds until the link expires (default = 3600, 1 hour)
:param content_type: str; the content-type of the object (default = 'image/svg+xml')
:return: str; presigned URL as string.
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Fetching upload pre-signed URL for %s object in %s bucket' % (obj_key, bucket))
operation = 'fetch_upload_url'
params = {
'bucket': bucket,
'obj_key': obj_key,
'expiration': expiration,
'region': region,
'content_type': content_type
}
try:
resp = self._send(operation, params, print_resp=kwargs.get('print_resp', False))
l.debug('** Fetching Upload URL Completed for %s' % obj_key)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def add_new_site(self, site=None, bucket='both', **kwargs):
"""
Adds a new site folder to either repo, source, or both buckets
:param site: str; name of site/WHID. Must be 4 chars in format of "ABC1"
:param bucket: str; name of the bucket (S3_REPO_BUCKET_NAME, S3_SOURCE_BUCKET_NAME, or 'both') to add site folder to
if = 'both', then site folder will be added to both buckets
:return: dict; {'message': str} summarizing the folder add operation
"""
l = self._logger
l.info('Adding site %s folder' % (site))
operation = 'add_new_site'
params = {'site': site, 'bucket': bucket}
try:
resp = self._send(operation, params, print_resp=kwargs.get('print_resp', False))
l.debug('** Adding Site Complete. Successfully added %s to %s bucket(s)' % (site, bucket))
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def download(self, obj_key, bucket=None, region=None):
"""
Downloads a JSON object from S3. File is received as a compressed binary Parquet file
:param obj_key: Path and object name of the data stored in S3
:param bucket: Bucket the target object is stored in.
:param region: AWS Region of the target bucket.
:return: JSON data object generated from the Parquet file stored in S3
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
# - Only used for logging; extract dates and data source from the object key
obj_key_parts = obj_key.split('/')
l.info('-- Downloading %s object from bucket %s' % (obj_key, bucket))
operation = 'download'
params = {
'bucket': bucket,
'obj_key': obj_key,
'region': region
}
try:
resp = self._send(operation, params)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def get_presigned_url(self, bucket=None, obj_key='', client_method='get_object', expiration=3600, region=None, content_type="text/plain"):
"""
Generate a presigned URL to object from S3.
Used primarily for retreiving image objects in Ignition
:param obj_key: str; uri of object to fetch
:param bucket_: str; bucket name where object resides
:param client_method: str; (default = 'get_object')
:param expiration: int; number of seconds until the link expires (default = 3600, 1 hour)
:param content_type: str; the content-type of the object (default = 'text/plain')
:return: str; presigned URL as string. If no client_method or error, returns None.
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
if not content_type:
msg = 'content_type cannot be null!'
l.error(msg)
raise InvalidParametersS3Manager(msg)
l.info('Fetching pre-signed url for %s from bucket %s' % (obj_key, bucket))
operation = 'get_presigned_url'
params = {
'bucket': bucket,
'obj_key': obj_key,
'client_method': client_method,
'expiration': expiration,
'content_type': content_type
}
try:
resp = self._send(operation, params)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def delete(self, obj_key, bucket=None, region=None):
"""
Deletes a JSON object from S3. File is flagged for deletion in the S3 bucket
:param obj_key: Path and object name of the data stored in S3
:param bucket: Bucket the target object is stored in.
:param region: AWS Region of the target bucket.
:return: Boto3 `delete_object` response
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Deleting %s object from bucket %s' % (obj_key, bucket))
operation = 'delete'
params = {
'bucket': bucket,
'obj_key': obj_key,
'region': region
}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully deleted %s' % obj_key)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def list_objects(self, bucket=None, prefix='', start_after='', region=None):
"""
Fetches a list of objects within a specified bucket, prefix, and starting point
:param bucket: str; Bucket target object is located
:param prefix: str; Limits the response to keys that begin with the specified prefix
:param start_after: str; StartAfter is where you want Amazon S3 to start listing from.
Amazon S3 starts listing after this specified key. StartAfter can be any key in the bucket.
:param region: Region of the target S3 Bucket
:return: Boto3 `list_objects_v2.Contents` response. This consists of the following keys per object returned:
{
'ETag': str; unique id,
'Key': str; path to object in bucket,
'LastModified': datetime.datetime(); time object last modified,
'Size': int; size in bytes of the object,
'StorageClass': str; type of storage used on the object
}
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Fetching list of objects from bucket %s' % bucket)
operation = 'list_objects'
params = {
'bucket': bucket,
'prefix': prefix,
'start_after': start_after,
'region': region
}
try:
resp = self._send(operation, params)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def list_object_versions(self, bucket=None, prefix='', region=None):
"""
Fetches a list of object versions within a specified bucket, prefix, and starting point
:param bucket: str; Bucket target object is located
:param prefix: str; Limits the response to keys that begin with the specified prefix
:param region: Region of the target S3 Bucket
:return: Boto3 `list_object_versions.Versions` response. This consists of the following keys per object returned:
{
'ETag': str; unique id,
'IsLatest': bool; only true for the current version,
'Key': str; path to object in bucket,
'LastModified': datetime.datetime(); time object last modified,
'Owner': {'DisplayName': str; name of owner/group, 'ID': str;,}
'Size': int; size in bytes of the object,
'StorageClass': str; type of storage used on the object,
'VersionId': str; ID of object version
}
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Fetching list of object versions from bucket %s' % bucket)
operation = 'list_object_versions'
params = {
'bucket': bucket,
'prefix': prefix,
'region': region
}
try:
resp = self._send(operation, params)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def list_object_delete_markers(self, bucket=None, prefix='', region=None):
"""
Fetches a list of object delete markers within a specified bucket, prefix, and starting point
:param bucket: str; Bucket target object is located
:param prefix: str; Limits the response to keys that begin with the specified prefix
:param region: Region of the target S3 Bucket
:return: Boto3 `list_object_versions.DeleteMarkers` response. This consists of the following keys per object returned:
{
'IsLatest': bool; only true for the current version,
'Key': str; path to object in bucket,
'LastModified': datetime.datetime(); time object last modified,
'Owner': {'DisplayName': str; name of owner/group, 'ID': str;,}
'VersionId': str; ID of object version
}
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Fetching list of object delete markers from bucket %s' % bucket)
operation = 'list_object_delete_markers'
params = {
'bucket': bucket,
'prefix': prefix,
'region': region
}
try:
resp = self._send(operation, params)
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def copy_single(self, source_bucket=None, dest_bucket=None, source_key='', dest_key='', region=None):
"""
Method to copy a single object from source bucket|key to destination bucket|key.
:param source_bucket: str; Source bucket name to copy from
:param dest_bucket: str; Destination bucket name to copy to
:param source_key: str; Source object key name to copy
:param dest_key: str; Destination object key name to copy to
:param region: Region of the target S3 Bucket
:return: null or ClientError; returns null if successfully copied
"""
l = self._logger
if not source_bucket:
# if no source bucket provided, use repo bucket name from stage config
source_bucket = self._repo_bucket
if not dest_bucket:
# if no destination bucket provided, use repo bucket name from stage config
dest_bucket = self._repo_bucket
if not region:
# if no region provided, use region name from stage config
region = self._s3_region
l.info('Copying %s object from bucket %s to object %s in bucket %s' % (source_key, source_bucket, dest_key, dest_bucket))
l.debug('++ Copying data in S3')
operation = 'copy_single'
params = {
'source_bucket': source_bucket,
'dest_bucket': dest_bucket,
'source_key': source_key,
'dest_key': dest_key,
'region': region
}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully copied object %s from bucket %s to object %s in bucket %s' %
(source_key, source_bucket, dest_key, dest_bucket))
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def fetch_site_list(self, bucket=None):
"""
This method will compile a list of all sites configured in the requested S3 bucket
:param bucket: str; the S3 bucket to fetch sites from. (Default = S3_REPO_BUCKET_NAME)
:return: list; array of whids present in the S3 bucket
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
l.info('Requesting site list for bucket: %s' % bucket)
operation = 'fetch_site_list'
params = {
'bucket': bucket
}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully returned %d sites for bucket %s' % (len(resp), bucket))
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def fetch_object_list_by_site_and_bucket(self, site='', bucket=None):
"""
This function fetches the list of file objects
from the S3 folder specified by the bucket and site args supplied.
:param site: str; whid name of the site to fetch from
:param bucket: str; name of the bucket where the files reside
:return: Dict[str, Any]; {'instance_configs': Dict[str,Any], 'flow_views': List[str]}
"""
l = self._logger
if not bucket:
# if no bucket provided, use repo bucket name from stage config
bucket = self._repo_bucket
l.info('Requesting object list for site %s in bucket: %s' % (site, bucket))
operation = 'fetch_object_list_by_site_and_bucket'
params = {
'site': site,
'bucket': bucket
}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully returned object list for site %s on bucket %s' % (site, bucket))
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def query_audit_table(self, start_time = None, end_time = None, operation = None, copy_option = None,
destination_bucket = None, destination_view = None, destination_object_key = None,
destination_site = None, destination_stage = None, destination_version_id = None,
error_message = None, error_occurred = None, expires = None,
source_bucket = None, source_view = None, source_object_key = None, source_site = None,
source_stage = None, source_version_id = None, timestamp = None, username = None,
return_items_only = True, **kwargs):
"""
Query/scan the audit table and return records matching the supplied parameters
:param start_time: Optional[Union[str,datetime]]; if provided, will define the beginning of the
time range to filter on the `timestamp` column. `timestamp` column is a string in the format
"%Y-%m-%d %H:%M:%S"
:param end_time: Optional[Union[str,datetime]]; if provided, will define the beginning of the
time range to filter on the `timestamp` column. `timestamp` column is a string in the format
"%Y-%m-%d %H:%M:%S"
:param operation: Optional[Union[str,List,Dict]]; match on operation column
:param copy_option: Optional[Union[str,List,Dict]]; match on copy_option column ('svg', 'json', 'both')
:param destination_bucket: Optional[Union[str,List,Dict]]; match on destination_bucket column
:param destination_view: Optional[Union[str,List,Dict]]; match on destination_view column
:param destination_object_key: Optional[Union[str,List,Dict]]; match on destination_object_key column
:param destination_site: Optional[Union[str,List,Dict]]; match on destination_site column
:param destination_stage: Optional[Union[str,List,Dict]]; match on destination_stage column
:param destination_version_id: Optional[Union[str,List,Dict]]; match on destination_version_id column
:param error_message: Optional[Union[str,List,Dict]]; match on error_message column
:param error_occurred: Optional[Union[bool,List,Dict]]; match on error_error_occurred column
:param expires: Optional[Union[str,List,Dict]]; match/filter on expires column
:param source_bucket: Optional[Union[str,List,Dict]]; match on source_bucket column
:param source_view: Optional[Union[str,List,Dict]]; match on source_view column
:param source_object_key: Optional[Union[str,List,Dict]]; match on source_object_key column
:param source_site: Optional[Union[str,List,Dict]]; match on source_site column
:param source_stage: Optional[Union[str,List,Dict]]; match on source_stage column
:param source_version_id: Optional[Union[str,List,Dict]]; match on source_version_id column
:param timestamp: Optional[Union[str,List,Dict]]; match/filter on timestamp column
(overridden by `start_time` and `end_time` args)
:param username: Optional[Union[str,List,Dict]]; match on username column
:param return_items_only: bool; if true, strip the `Items` from boto3 response,
if false, return the entire response object
:returns: List[Dict[str,Any]]; array of items that match the scan filters supplied
"""
l = self._logger
# build params to send to Lambda using `locals()`. I know it's frowned upon but I'm not trying to type all that!!
params = {k:v for k,v in locals().items() if k not in ('self', 'l', 'kwargs') and v not in (None, '')}
# override `operation` arg for pass to `_send` method, as the value to query is already packed in `params`
operation = 'query_audit_table'
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully queried audit table using supplied query params')
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def check_user_site_permissions(self, whid = None, obj_key = None):
"""
Check if a given username has permissions to the site folder in the flow-view S3 bucket
:param whid: str; warehouse id/site name to check
:param obj_key: str; [OPTIONAL] if provided, will check user permissions to the object key, rather than the whid
:return: Dict[str,Any]; {
'code': int; 200 if the user has permissions, 403 if Forbidden to access
'message': str; explanation to display, if needed. Will include necessary group memberships missing if Forbidden
}
"""
l = self._logger
operation = 'check_user_site_permissions'
params = {'whid': whid, 'obj_key': obj_key}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully checked user site permissions on backend')
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def fetch_user_site_permissions_and_area_list(self, username = None, stage_name = 'beta'):
"""
Fetch the sites for which the user has flow-view write permissions for the given stage.
Also fetches the list of "area" names that flow-views can be created for
:param username: str; user alias/id to fetch sites for
:param stage_name: str; stage folder of flow-view resources to check permissions on
:return: Dict[str,Any]; response object including a list of sites and area names.
{
"code": int; 200 if successful call, 4** if user not found,
"sites": List[str]; List of site names,
"areas": List[str]; List of valid flow-view area names
}
"""
l = self._logger
operation = 'fetch_user_site_permissions_and_area_list'
params = {'username': username, 'stage_name': stage_name}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully fetched user site permissions and area list')
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
def fetch_master_area_list(self):
"""
Download a master list of valid flow-view area names, stored in S3
:return: List[str]; returns list of area names
"""
l = self._logger
operation = 'fetch_master_area_list'
params = {}
try:
resp = self._send(operation, params)
l.debug('** Complete. Successfully fetched master area list')
return resp
except HTTPErrorS3Manager, e:
return {'code': e.code, 'message': e.message}
class InvalidOperationS3Manager(Exception):
"""
Invalid operation requested for S3Manager class
"""
def __init__(self, code=400, msg='Invalid operation requested for S3Manager class'):
self.code = code
self.message = msg
class InvalidParametersS3Manager(Exception):
"""
Invalid parameters for S3Manager operation
"""
def __init__(self, code=400, msg='Invalid parameters for S3Manager operation'):
self.code = code
self.message = msg
class HTTPErrorS3Manager(Exception):
"""
HTTP Error for S3Manager Request
"""
def __init__(self, code=500, msg='HTTP Error Encountered Sending S3Manager Request'):
self.code = code
self.message = msg

View File

@ -0,0 +1,58 @@
{
"custom": {},
"params": {
"text": "value"
},
"propConfig": {
"params.text": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 30,
"width": 210
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "209px",
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"expression": "{view.params.text}"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Text/CenterAlign_with_Padding"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"alignItems": "center",
"justify": "center",
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,244 @@
{
"custom": {},
"params": {
"device_name": "Test",
"driver": "value",
"enabled": false,
"host_name": "value",
"status": "value"
},
"propConfig": {
"params.device_name": {
"paramDirection": "input",
"persistent": true
},
"params.driver": {
"paramDirection": "input",
"persistent": true
},
"params.enabled": {
"paramDirection": "input",
"persistent": true
},
"params.host_name": {
"paramDirection": "input",
"persistent": true
},
"params.status": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 50,
"width": 1908
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "400px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.device_name"
},
"type": "property"
}
}
},
"props": {
"style": {
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "400px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.driver"
},
"type": "property"
}
}
},
"props": {
"style": {
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_1"
},
"position": {
"basis": "200px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.enabled"
},
"type": "property"
}
}
},
"props": {
"style": {
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_2"
},
"position": {
"basis": "564px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.status"
},
"type": "property"
}
}
},
"props": {
"style": {
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_3"
},
"position": {
"basis": "564px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.host_name"
},
"type": "property"
}
}
},
"props": {
"style": {
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "2px",
"grow": 1
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\timport sys\n\tfrom java.lang import Exception\n\t\n\ttry:\n\t\tif system.tag.exists(\"System/DeviceList\"):\n\t\t\tdevice_cfg \u003d system.tag.read(\"System/DeviceList\").value\n\t\t\tif device_cfg\u003d\u003d\u0027\u0027:\n\t\t\t\tdevice_cfg\u003d\u0027{}\u0027\n\t\t\tcfg \u003d system.util.jsonDecode(device_cfg)\n\t\t\tenabled \u003d self.view.params.enabled\n\t\t\tdevice \u003d self.view.params.device_name\n\t\t\tsystem.perspective.print(enabled)\n\t\t\tif enabled:\n\t\t\t\tdevice_list \u003d cfg.get(\"Devicedisable\",[])\n\t\t\t\tif device not in device_list:\n\t\t\t\t\tdevice_list.append(device)\n\t\t\t\tcfg[\"Devicedisable\"] \u003d device_list\n\t\t\tif not enabled:\n\t\t\t\tdevice_list \u003d cfg.get(\"DeviceEnable\",[])\n\t\t\t\tif device not in device_list:\n\t\t\t\t\tdevice_list.append(device)\n\t\t\t\tcfg[\"DeviceEnable\"] \u003d device_list\n\t\t\tsystem.perspective.print(cfg) \n\t\t\tencode \u003d system.util.jsonEncode(cfg)\n\t\t\tsystem.tag.write(\"System/DeviceList\",encode)\t\n\texcept:\n\t logger \u003d system.util.getLogger(\"Device_Enable\")\n\t exc_type, exc_obj, tb \u003d sys.exc_info()\n\t lineno \u003d tb.tb_lineno\n\t errorMessage\u003d str(lineno) + str(exc_type) + str(exc_obj)\n\t #system.gui.errorBox(errorMessage,\"Error\")\n\t "
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button_0"
},
"position": {
"basis": "50px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"expression": "if({view.params.enabled} \u003d True, \"Disable Device\", \"Enable Device\")"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Buttons/PB_1"
}
},
"type": "ia.input.button"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "2px",
"grow": 1
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "200px"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"custom": {
"update": "value",
"update_enable": "value"
},
"meta": {
"name": "root"
},
"props": {
"style": {
"borderStyle": "ridge"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,20 @@
def navigate_to_additional_view(self):
"""
This function is used to navigate to a page from a navigation button.
This function can be used on any button that has a property called "self.custom.page_id"
which is the target page for the button.
Args:
self: Refrence to the object that is invoking this function.
Returns:
This is a description of what is returned.
Raises:
KeyError: Raises an exception.
"""
page_id = self.custom.page_id
plc = page_id.split("-")[0]
url_to_navigate = "/DetailedView/%s/%s" % (page_id, plc)
system.perspective.navigate(page = url_to_navigate)

View File

@ -0,0 +1,66 @@
#from logging import raiseExceptions
class GetStatus():
def __init__(self, whid, alarm_data):
self.alarm_data = alarm_data
self.priority_dict = {}
self.id_to_status = {}
self.tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
self.logger = system.util.getLogger("%s-Update-Visualisation" % (whid))
def convert_priority(self, priority):
#The alarm priority is converted into a status
#This is based on the highest active alarm priority
if str(priority) == "0":
return 4
elif str(priority) == "1":
return 3
elif str(priority) == "2":
return 2
elif str(priority) == "3" or priority == "4":
return 1
else:
return 6
def check_priority(self, alarm_id, priority):
#We check to see if the current priority is greater
#than the current priority in the priority_dict. This is
#because the status is based on the active alarm. With the
#highest priority.
controller_id = alarm_id.split("/")[0]
if self.priority_dict.get(controller_id) is None:
self.priority_dict[controller_id] = {}
self.priority_dict[controller_id][alarm_id] = self.convert_priority(priority)
elif self.priority_dict[controller_id].get(alarm_id) is None:
self.priority_dict[controller_id][alarm_id] = self.convert_priority(priority)
elif self.priority_dict[controller_id].get(alarm_id) < priority:
self.priority_dict[controller_id][alarm_id] = (
self.convert_priority
(priority)
)
def run_status(self):
for i in self.alarm_data:
alarm_id = i
priority = self.alarm_data.get(i, {}).get("priority")
if priority != None:
self.check_priority(alarm_id, priority)
def update_tags(self):
device_paths = []
status_values = []
if isinstance(self.priority_dict, dict):
for i in self.priority_dict:
device_path = "%sTags/%s/IdToStatus/json" % (self.tag_provider, i)
device_paths.append(device_path)
status_json = self.priority_dict.get(i)
status_values.append(system.util.jsonEncode(status_json, 4))
self.logger.info("device paths " + str(device_paths))
else:
raise TypeError("Not a python dictionary")
system.tag.writeAsync(device_paths, status_values)

View File

@ -0,0 +1,371 @@
{
"custom": {
"activityLogger": {
"alt_pageid": "search",
"buttonid": "search",
"start_time": {
"$": [
"ts",
192,
1710275608985
],
"$ts": 1710275608985
}
}
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tbuttonid \u003d self.custom.activityLogger.buttonid\n\tself.custom.activityLogger.start_time \u003d system.date.now()\n\tactivityLog.productMetrics.callLogger(self, \u0027click\u0027, buttonid)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"params": {},
"propConfig": {
"custom.activityLogger": {
"persistent": true
},
"custom.activityLogger.pageid": {
"binding": {
"config": {
"expression": "{page.props.path}"
},
"transforms": [
{
"code": "\tif value \u003d\u003d\u0027/\u0027 or value \u003d\u003d \u0027\u0027 or value \u003d\u003d None:\n\t\treturn self.custom.activityLogger.alt_pageid.lower()\n\telse:\n\t\treturn value[1:].lower()",
"type": "script"
}
],
"type": "expr"
}
}
},
"props": {
"defaultSize": {
"height": 294,
"width": 500
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "77px"
},
"props": {
"style": {
"backgroundColor": "#555555",
"color": "#FFFFFF",
"fontWeight": "bold",
"textIndent": "15px"
},
"text": "Search"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "30px"
},
"props": {
"color": "#FFFFFF",
"path": "material/search"
},
"type": "ia.display.icon"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "45px"
},
"props": {
"style": {
"backgroundColor": "#555555"
}
},
"type": "ia.container.flex"
},
{
"events": {
"component": {
"onRowDoubleClick": {
"config": {
"script": "\trow \u003d event.value\n\tsource_id \u003d row.get(\"SourceId\") \n\tconfig.project_config.source_id_lookup(self, source_id)\n\tsystem.perspective.closePopup(id \u003d \"Search\")"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Table"
},
"position": {
"basis": "294px"
},
"props": {
"cells": {
"style": {
"textIndent": "15px"
}
},
"columns": [
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "SourceId",
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"justify": "auto",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": false,
"sort": "none",
"sortable": false,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": 200
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Page",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"justify": "auto",
"nullFormat": {
"includeNullStrings": false,
"nullFormatValue": "",
"strict": false
},
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
}
],
"data": {
"$": [
"ds",
192,
1710275544545
],
"$columns": [
{
"data": [],
"name": "SourceId",
"type": "String"
},
{
"data": [],
"name": "Page",
"type": "String"
}
]
},
"filter": {
"enabled": true,
"style": {
"backgroundColor": "#2B2B2B",
"color": "#FFFFFF"
}
},
"headerStyle": {
"backgroundColor": "#2B2B2B",
"color": "#FFFFFF",
"textIndent": "15px"
},
"pager": {
"style": {
"backgroundColor": "#2B2B2B",
"color": "#FFFFFF",
"fontWeight": "bold"
}
},
"rows": {
"highlight": {
"color": "#FFFFFF"
},
"style": {
"classes": "Background-Styles/Controller"
}
},
"virtualized": false
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "search-devices",
"pageScope": true,
"script": "\tself.props.data \u003d payload.get(\"dataset\")",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.display.table"
}
],
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tids \u003d config.project_config.global_project_page_ids\n\tdata \u003d []\n\tfor k,v in ids.items():\n\t items \u003d [str(k),str(v)]\n\t data.append(items)\n\theader \u003d [\"SourceId\", \"Page\"]\n\tdataset \u003d system.dataset.toDataSet(header, data)\n\tself.getChild(\"Table\").props.data \u003d dataset"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,773 @@
{
"custom": {
"api_region_name": "na",
"bucket_options": [
{
"label": "Image Files",
"value": "na-ignition-image-repo"
},
{
"label": "Source Files",
"value": "na-ignition-image-source"
}
],
"default_query_params": {
"bucket": null,
"object_key": null,
"site": null,
"view": null
},
"destination_view_suffix": null,
"object_key": null,
"stage_config": {
"account_id": "925510716640",
"endpoint": "https://scada-s3-management.narme-scada.rme.amazon.dev/",
"lambda_name": "RMESDScadaS3ManagementFlaskLambda-prod",
"region": "us-east-2",
"repo_bucket": "na-ignition-image-repo",
"s3_region": "us-east-1",
"source_bucket": "na-ignition-image-source"
},
"view_options_by_site_and_bucket": [],
"view_suffix": null,
"whid_options": []
},
"params": {
"query_params": {
"bucket": null,
"object_key": null,
"site": null,
"view": null
}
},
"propConfig": {
"custom.api_region_name": {
"binding": {
"config": {
"path": "session.custom.aws.prefix"
},
"type": "property"
},
"persistent": true
},
"custom.bucket_options": {
"binding": {
"config": {
"path": "view.custom.stage_config"
},
"transforms": [
{
"code": "\treturn [{\u0027value\u0027: value.repo_bucket, \u0027label\u0027: \u0027Image Files\u0027},\n\t\t\t{\u0027value\u0027: value.source_bucket, \u0027label\u0027: \u0027Source Files\u0027}]",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"custom.default_query_params": {
"persistent": true
},
"custom.object_key": {
"binding": {
"config": {
"path": "view.params.query_params"
},
"transforms": [
{
"code": "\tstage_config \u003d self.custom.stage_config\n\tbucket \u003d self.params.query_params.bucket\n\tsite \u003d self.params.query_params.site\n\tview \u003d self.params.query_params.view\n\tif bucket and site and view:\n\t\tif bucket \u003d\u003d stage_config.repo_bucket:\n\t\t\tsuffix \u003d \u0027.svg\u0027\n\t\t\tsubfolder \u003d \u0027images\u0027\n\t\telse:\n\t\t\tsuffix \u003d \u0027.drawio\u0027\n\t\t\tsubfolder \u003d \u0027source\u0027\n\t\treturn \"SCADA/%s/%s/%s%s\" % (site, subfolder, view, suffix)\n\telse:\n\t\treturn None\n",
"type": "script"
}
],
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\td \u003d self.params.query_params\n\tif getattr(currentValue, \u0027value\u0027, None):\n\t\tself.params.query_params.object_key \u003d currentValue.value\n\t"
},
"persistent": true
},
"custom.stage_config": {
"binding": {
"config": {
"expression": "{view.custom.api_region_name}"
},
"transforms": [
{
"code": "\treturn AWS.s3.STAGE_CONFIG[\u0027prod\u0027][value]",
"type": "script"
}
],
"type": "expr"
},
"persistent": true
},
"custom.view_options_by_site_and_bucket": {
"binding": {
"config": {
"expression": "{view.params.query_params.site}+{view.params.query_params.bucket}"
},
"transforms": [
{
"code": "\tbucket \u003d self.params.query_params.bucket\n\tsite \u003d self.params.query_params.site\n\tif bucket and site:\n\t\tfrom AWS.s3 import S3Manager\n\t\tfrom helper.helper import sanitize_tree\n\t\tfrom pprint import pformat\n\t\t\n\t\tapi_stage \u003d \u0027prod\u0027\n\t\tusername \u003d self.session.props.auth.user.userName\n\t\tapi_region_name \u003d self.view.custom.api_region_name\n\t\t\n\t\ts3m \u003d S3Manager(api_stage, api_region_name, username)\n\t\tsuffix \u003d self.custom.view_suffix\n\t\tfiles \u003d sanitize_tree(s3m.fetch_object_list_by_site_and_bucket(site, bucket))\n\t\treturn [{\u0027value\u0027: x[\u0027Filename\u0027].replace(suffix,\u0027\u0027), \n\t\t\t\t\u0027label\u0027: x[\u0027Filename\u0027].replace(suffix,\u0027\u0027)} for x in files]\n\treturn []",
"type": "script"
}
],
"type": "expr"
},
"persistent": true
},
"custom.view_suffix": {
"binding": {
"config": {
"path": "view.params.query_params.bucket"
},
"transforms": [
{
"code": "\tif value:\n\t\tstage_config \u003d self.custom.stage_config\n\t\tif value \u003d\u003d stage_config.get(\u0027repo_bucket\u0027, None):\n\t\t\treturn \".svg\"\n\t\tif value \u003d\u003d stage_config.get(\"source_bucket\", None):\n\t\t\treturn \".drawio\"\n\treturn value",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"custom.whid_options": {
"binding": {
"config": {
"path": "view.params.query_params.bucket"
},
"transforms": [
{
"code": "\tif value:\n\t\tfrom AWS.s3 import S3Manager\n\t\t\n\t\tapi_stage \u003d \u0027prod\u0027\n\t\tusername \u003d self.session.props.auth.user.userName\n\t\tapi_region_name \u003d self.custom.api_region_name\n\t\t\n\t\ts3m \u003d S3Manager(\u0027prod\u0027, api_region_name, username)\n\t\t\n\t\treturn [{\u0027value\u0027: x, \u0027label\u0027: x} for x in s3m.fetch_site_list(value)]\n\treturn []",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"params.query_params": {
"onChange": {
"enabled": null,
"script": "\tif not missedEvents and origin in (\u0027Binding\u0027, \u0027Script\u0027, \u0027BindingWriteback\u0027):\n\t\tpayload \u003d currentValue.value\n\t\tsystem.perspective.sendMessage(\u0027list_versions_query_params_changed\u0027, payload, scope\u003d\u0027session\u0027)\n\t\t"
},
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 600
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"borderStyle": "none",
"classes": "Framework/Card/Title_transparent"
},
"text": "Select Query Params"
},
"type": "ia.display.label"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# reset query params to default values \n\t# (stored in `view.custom.default_query_params`)\n\tself.view.params.query_params \u003d self.view.custom.default_query_params"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Clear Button",
"tooltip": {
"enabled": true,
"location": "bottom-right",
"text": "Clear Selections"
}
},
"position": {
"shrink": 0
},
"props": {
"image": {
"icon": {
"path": "material/clear_all"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# refresh version table query via message handler\n\tsystem.perspective.sendMessage(\u0027refresh_version_table_data\u0027, scope\u003d\u0027session\u0027)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Refresh Button",
"tooltip": {
"enabled": true,
"location": "bottom-right",
"text": "Refresh Data"
}
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.bucket})\r\n\u0026\u0026!isNull({view.params.query_params.site})\r\n\u0026\u0026!isNull({view.params.query_params.view})\r\n\u0026\u0026!isNull({view.params.query_params.object_key})"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/refresh"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"grow": 1
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer Header"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Title_transparent",
"marginBottom": "2px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label",
"textAlign": "right"
},
"text": "Bucket"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Dropdown"
},
"position": {
"basis": "540px",
"grow": 1
},
"propConfig": {
"props.options": {
"binding": {
"config": {
"path": "view.custom.bucket_options"
},
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.query_params.bucket"
},
"type": "property"
}
}
},
"props": {
"dropdownOptionStyle": {
"overflowWrap": "break-word",
"whiteSpace": "normal"
},
"showClearIcon": true
},
"type": "ia.input.dropdown"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.view.params.query_params.bucket \u003d None\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Clear Button"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.bucket})\r\n\u0026\u0026{view.params.query_params.bucket}!\u003d\u0027\u0027"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/clear"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "Bucket"
},
"position": {
"basis": "100%",
"grow": 1
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_1"
},
"position": {
"shrink": 0
},
"props": {
"justify": "center"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label",
"textAlign": "right"
},
"text": "Site"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Dropdown"
},
"position": {
"basis": "540px",
"grow": 1
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.bucket})\r\n\u0026\u0026len({view.params.query_params.bucket})\u003e0"
},
"type": "expr"
}
},
"props.options": {
"binding": {
"config": {
"path": "view.custom.whid_options"
},
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.query_params.site"
},
"type": "property"
}
}
},
"props": {
"dropdownOptionStyle": {
"overflowWrap": "break-word",
"whiteSpace": "normal"
},
"showClearIcon": true
},
"type": "ia.input.dropdown"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.view.params.query_params.site \u003d None\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Clear Button"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.site})\r\n\u0026\u0026{view.params.query_params.site}!\u003d\u0027\u0027"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/clear"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "Site"
},
"position": {
"basis": "100%",
"grow": 1
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_2"
},
"position": {
"shrink": 0
},
"props": {
"justify": "center"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label",
"textAlign": "right"
},
"text": "View"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Dropdown"
},
"position": {
"basis": "540px",
"grow": 1
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.bucket})\r\n\u0026\u0026len({view.params.query_params.bucket})\u003e0\r\n\u0026\u0026!isNull({view.params.query_params.site})\r\n\u0026\u0026len({view.params.query_params.site})\u003e0"
},
"type": "expr"
}
},
"props.options": {
"binding": {
"config": {
"path": "view.custom.view_options_by_site_and_bucket"
},
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.query_params.view"
},
"type": "property"
}
}
},
"props": {
"dropdownOptionStyle": {
"overflowWrap": "break-word",
"whiteSpace": "normal"
},
"showClearIcon": true
},
"type": "ia.input.dropdown"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.view.params.query_params.view \u003d None\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Clear Button"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!isNull({view.params.query_params.view})\r\n\u0026\u0026{view.params.query_params.view}!\u003d\u0027\u0027"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/clear"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "View"
},
"position": {
"basis": "100%",
"grow": 1
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_3"
},
"position": {
"shrink": 0
},
"props": {
"justify": "center"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label",
"textAlign": "right"
},
"text": "Object Key"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_0"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.query_params.object_key"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Value",
"textAlign": "left"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "Object Key"
},
"position": {
"basis": "100%",
"grow": 1
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_4"
},
"position": {
"shrink": 0
},
"props": {
"justify": "center"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,97 @@
{
"custom": {},
"params": {
"rowData": {
"Driver": "value"
}
},
"propConfig": {
"params.rowData": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 36,
"width": 227
}
},
"root": {
"children": [
{
"meta": {
"name": "Dropdown"
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"path": "view.params.rowData.Driver"
},
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\tvalue \u003d currentValue.value\n\tsystem.perspective.print(str(origin))\n\tif value is not None:\n\t\tif \u0027Binding\u0027 not in str(origin):\n\t\t\tmsg \u003d \u0027addtable-dropdown-updaterow\u0027\n\t\t\tHostname \u003d self.view.params.rowData[\u0027Hostname\u0027]\n\t\t\tpayload \u003d\t{\n\t\t\t\t\t\t\u0027value\u0027\t\t: value,\n\t\t\t\t\t\t\u0027Hostname\u0027\t: Hostname\n\t\t\t\t\t\t}\n\t\t\tsystem.perspective.sendMessage(msg, payload)"
}
}
},
"props": {
"options": [
{
"label": "S7300",
"value": "S7300"
},
{
"label": "S7400",
"value": "S7400"
},
{
"label": "S71200",
"value": "S71200"
},
{
"label": "S71500",
"value": "S71500"
},
{
"label": "CompactLogix",
"value": "CompactLogix"
},
{
"label": "Legacy Allen-Bradley",
"value": "ControlLogix"
},
{
"label": "ControlLogix",
"value": "ControlLogix"
},
{
"label": "LogixDriver",
"value": "LogixDriver"
},
{
"label": "Allen Bradley MicroLogix",
"value": "MicroLogix"
}
],
"placeholder": {
"text": "Select Driver..."
}
},
"type": "ia.input.dropdown"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,14 @@
{
"custom": {},
"params": {},
"props": {},
"root": {
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,710 @@
{
"custom": {
"font_size": ".57vmax"
},
"params": {},
"propConfig": {
"custom.font_size": {
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 149,
"width": 423
}
},
"root": {
"children": [
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "160px"
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "Color Legend",
"textStyle": {
"paddingLeft": 5
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_4"
},
"position": {
"basis": "35px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#3B3B3B",
"borderColor": "#CAC3C3",
"borderStyle": "solid",
"borderWidth": 1,
"overflow": "hidden",
"paddingLeft": 5
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "MHE Stopped"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "MHE is stopped (State2)"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state0"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 10,
"marginRight": 5,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "MHE Running"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "MHE is running (State3)"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state5"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 5,
"marginRight": 10,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "45px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#3B3B3B",
"borderColor": "#CAC3C3",
"borderStyle": "solid",
"borderWidth": 1,
"overflow": "hidden"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "Healthy"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state5"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 10,
"marginRight": 5,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "Diagnostic"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "Diagnostic Information"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state4"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 5,
"marginRight": 10,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_0",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "Healthy, no active alarms"
}
},
"position": {
"basis": "45px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#3B3B3B",
"borderColor": "#CAC3C3",
"borderStyle": "solid",
"borderWidth": 1,
"overflow": "hidden"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "Low",
"textStyle": {
"color": "#000000"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "Running at reduced capacity"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state3"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 10,
"marginRight": 5,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "Medium"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "Controlled stop"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state2"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 5,
"marginRight": 10,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_1"
},
"position": {
"basis": "45px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#3B3B3B",
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderColor": "#CAC3C3",
"borderStyle": "solid",
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"borderWidth": 1,
"overflow": "hidden",
"paddingLeft": 1
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "148px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"text": "High"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer",
"tooltip": {
"enabled": true,
"sustain": 1500,
"text": "Uncontrolled stop"
}
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state1"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 4,
"borderBottomRightRadius": 4,
"borderTopLeftRadius": 4,
"borderTopRightRadius": 4,
"marginBottom": 0,
"marginLeft": 10,
"marginRight": 5,
"marginTop": 1,
"overflow": "hidden",
"paddingLeft": 10
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"draggable": true,
"id": "K1uUHAix",
"modal": true,
"overlayDismiss": true,
"resizable": true,
"showCloseIcon": true,
"title": "Legend",
"type": "open",
"viewPath": "PopUp-Views/Legend",
"viewportBound": false
},
"scope": "C",
"type": "popup"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"basis": "168px",
"grow": 1
},
"propConfig": {
"props.textStyle.fontSize": {
"binding": {
"config": {
"path": "view.custom.font_size"
},
"type": "property"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/legend_toggle"
},
"style": {
"backgroundColor": "#555555"
}
},
"justify": "start",
"style": {
"backgroundColor": "#555555",
"paddingLeft": 8
},
"text": "DETAILS"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": "200px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#555555",
"marginBottom": 0,
"marginLeft": 5,
"marginRight": 10,
"marginTop": 1
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_2"
},
"position": {
"basis": "45px",
"grow": 1
},
"props": {
"style": {
"backgroundColor": "#3B3B3B",
"borderColor": "#CAC3C3",
"borderStyle": "solid",
"borderWidth": 1,
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_6"
},
"position": {
"basis": "800px",
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "Background-Styles/Controller"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,648 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running_status": 0,
"searchId": "value",
"state": 5,
"state_string": "Unknown"
},
"params": {
"directionLeft": false,
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.directionLeft": {
"paramDirection": "input",
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 25,
"width": 25
}
},
"root": {
"children": [
{
"meta": {
"name": "PressureSwitch_2"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"elements": [
{
"elements": [
{
"id": "stop1507",
"name": "stop1507",
"offset": "0",
"stopColor": "#020101",
"stopOpacity": "1",
"style": {
"stopColor": "#020101",
"stopOpacity": "1"
},
"type": "stop"
}
],
"id": "linearGradient1509",
"name": "linearGradient1509",
"type": "linearGradient"
},
{
"gradientTransform": "matrix(1.0156665,0,0,0.98457489,-0.22712617,-0.22017344)",
"gradientUnits": "userSpaceOnUse",
"href": "#linearGradient1509",
"id": "linearGradient3055",
"name": "linearGradient3055",
"type": "linearGradient",
"x1": "2.4719212",
"x2": "5.6080947",
"y1": "4.8826461",
"y2": "4.8826461"
}
],
"id": "defs2",
"name": "defs2",
"type": "defs"
},
{
"elements": [
{
"fill": {
"opacity": 1
},
"height": "11.216189",
"id": "rect5779",
"name": "rect5779",
"stroke": {
"dasharray": "none",
"linejoin": "round",
"paint": "#000000",
"width": 1.2
},
"style": {
"paintOrder": "stroke fill markers"
},
"type": "rect",
"width": "11.21619",
"x": "7.7715612e-16",
"y": "0"
},
{
"elements": [
{
"fill": {
"opacity": "1",
"url": "url(#linearGradient3055)"
},
"id": "tspan1453",
"name": "tspan1453",
"stroke": {
"dasharray": "none",
"width": "0.116835"
},
"text": "P",
"type": "tspan",
"x": "0.99078566",
"y": "9.0214157"
}
],
"fill": {
"opacity": "1",
"url": "url(#linearGradient3055)"
},
"id": "text1455",
"name": "text1455",
"stroke": {
"dasharray": "none",
"linejoin": "round",
"paint": "#000000",
"width": "0.116835"
},
"style": {
"InkscapeFontSpecification": "\u0027Arial Narrow, Normal\u0027",
"fontFamily": "\u0027Arial Narrow\u0027",
"fontSize": "9.7785px",
"paintOrder": "stroke fill markers"
},
"text": "P",
"transform": "scale(0.98457515,1.0156665)",
"type": "text",
"x": "0.99078566",
"y": "9.0214157"
},
{
"d": "M 7.1327097,2.9635882 9.9122555,5.8103519 6.9937326,8.2419488",
"fill": {
"opacity": "0.0131332",
"paint": "#020101"
},
"id": "path3213",
"name": "path3213",
"stroke": {
"dasharray": "none",
"linejoin": "round",
"paint": "#000000",
"width": "0.663625"
},
"style": {
"paintOrder": "stroke fill markers"
},
"type": "path"
}
],
"id": "layer1",
"name": "layer1",
"transform": "translate(0.22362278,0.22362278)",
"type": "group"
}
],
"preserveAspectRatio": "none",
"style": {},
"viewBox": "0 0 11.663437 11.663435"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,58 @@
{
"custom": {},
"params": {
"text": "value"
},
"propConfig": {
"params.text": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 30,
"width": 210
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "209px",
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"expression": "{view.params.text}"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Text/LeftAlign_with_Padding"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"alignItems": "center",
"justify": "center",
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,96 @@
# These scripts are use to download data from the igniton project into any file type.
def download_file(filename, data , converter):
"""
This script will download data from ignition perspective to the users computer.
Args:
filename: The name of the file to be downloaded .
data: The data to be downloaded. May be a string, a byte[], or an InputStream. Strings will be written in UTF-8 encoding.
converter: This is a function that is used to convert the ignition data into the required format for the file.
If not conversion is required then pass a function that just returns original data.
Returns:
None.
Raises:
ValueError: Raises an Value erorr if no data or converter is provided.
"""
if not data:
raise ValueError("No data provided. Data is required to perform download ")
if not converter:
raise ValueError("Please provide a data converter to transform the data")
_data = converter(data)
system.perspective.download(filename, _data)
def device_data_converter(data):
"""
This script converts a list of dicts to a dataset, it uses the first dict to set the column headers in the dataset.
Args:
data: List of dictionaries.
Returns:
Ignition Data Set
Raises:
None
"""
dataset = []
for index,row in enumerate(data):
if index == 0:
header = row.keys()
row = []
for i in header:
value = data[index][i]
row.append(value)
dataset.append(row)
convert_data = system.dataset.toDataSet(header, dataset)
return system.dataset.toCSV(convert_data)
def detailed_views_converter(data):
"""
This script converts a list of dicts to a dataset, it uses the first dict to set the column headers in the dataset.
Args:
data: List of dictionaries.
Returns:
Ignition Data Set
Raises:
None
"""
dataset = []
for index,row in enumerate(data):
if index == 0:
header = row.keys()
row = []
for i in header:
if i == "Devices":
value = array_to_string(data[index][i])
else:
value = data[index][i]
row.append(value)
dataset.append(row)
convert_data = system.dataset.toDataSet(header, dataset)
return system.dataset.toCSV(convert_data)
def array_to_string(array , deliminator="#"):
converted = ""
if len(array) == 1:
return array[0]
for i , value in enumerate(array):
converted += value
if not i == len(array)-1:
converted += deliminator
return converted

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
{
"custom": {},
"params": {},
"props": {
"defaultSize": {
"height": 24,
"width": 24
}
},
"root": {
"children": [
{
"meta": {
"name": "troubleshoot_white_24dp"
},
"position": {
"height": 1,
"width": 1
},
"props": {
"elements": [
{
"elements": [
{
"fill": {
"paint": "transparent"
},
"height": "24",
"name": "rect",
"type": "rect",
"width": "24"
}
],
"name": "group",
"type": "group"
},
{
"elements": [
{
"elements": [
{
"d": "M22,20.59l-4.69-4.69C18.37,14.55,19,12.85,19,11c0-4.42-3.58-8-8-8c-4.08,0-7.44,3.05-7.93,7h2.02C5.57,7.17,8.03,5,11,5 c3.31,0,6,2.69,6,6s-2.69,6-6,6c-2.42,0-4.5-1.44-5.45-3.5H3.4C4.45,16.69,7.46,19,11,19c1.85,0,3.55-0.63,4.9-1.69L20.59,22 L22,20.59z",
"name": "path",
"type": "path"
},
{
"name": "polygon",
"points": "8.43,9.69 9.65,15 11.29,15 12.55,11.22 13.5,13.5 15.5,13.5 15.5,12 14.5,12 13.25,9 11.71,9 10.59,12.37 9.35,7 7.7,7 6.45,11 1,11 1,12.5 7.55,12.5",
"type": "polygon"
}
],
"name": "group",
"type": "group"
}
],
"name": "group",
"type": "group"
}
],
"fill": {
"paint": "#FFFFFF"
},
"viewBox": "0 0 24 24"
},
"type": "ia.shapes.svg"
}
],
"meta": {
"name": "root"
},
"props": {
"mode": "percent"
},
"type": "ia.container.coord"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
{
"custom": {
"activityLogger": {
"alt_pageid": "site-overview",
"start_time": {
"$": [
"ts",
192,
1709762531101
],
"$ts": 1709762531101
}
}
},
"events": {
"system": {
"onShutdown": {
"config": {
"script": "\tactivityLog.productMetrics.callLogger(self, \u0027page\u0027)"
},
"scope": "G",
"type": "script"
},
"onStartup": {
"config": {
"script": "\tself.custom.activityLogger.start_time \u003d system.date.now()"
},
"scope": "G",
"type": "script"
}
}
},
"params": {},
"propConfig": {
"custom.activityLogger": {
"persistent": true
},
"custom.activityLogger.pageid": {
"binding": {
"config": {
"expression": "{page.props.path}"
},
"transforms": [
{
"code": "\tif value \u003d\u003d\u0027/\u0027 or value \u003d\u003d \u0027\u0027 or value \u003d\u003d None:\n\t\treturn self.custom.activityLogger.alt_pageid.lower()\n\telse:\n\t\treturn value[1:].lower()",
"type": "script"
}
],
"type": "expr"
}
}
},
"props": {
"defaultSize": {
"height": 1080,
"width": 1920
}
},
"root": {
"children": [
{
"custom": {
"s3URI": "SCADA/Other/MAP.svg"
},
"meta": {
"name": "Image"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.source": {
"binding": {
"config": {
"path": "this.custom.s3URI"
},
"transforms": [
{
"code": "\treturn AWS.s3.getPresignedURL(self, value)",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"altText": "none",
"fit": {
"mode": "fill"
}
},
"type": "ia.display.image"
}
],
"meta": {
"name": "root"
},
"props": {
"mode": "percent",
"style": {
"backgroundColor": "#EEEEEE"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,65 @@
{
"custom": {},
"params": {
"color": "#00FF00"
},
"propConfig": {
"params.color": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 20,
"width": 20
}
},
"root": {
"children": [
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tcolor \u003d self.view.params.color\n\tsystem.perspective.sendMessage(messageType\u003d\"color-clicked\", payload\u003d{\"color\":color})"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Label"
},
"position": {
"basis": "20px",
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "view.params.color"
},
"type": "property"
}
}
},
"props": {
"style": {
"cursor": "pointer"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,11 @@
import sys
def error_handler(whid, logger_name):
logger_name = "%s-%s" % (whid, logger_name)
logger = system.util.getLogger(logger_name)
provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
exc_type, exc_obj, tb = sys.exc_info()
lineno = tb.tb_lineno
logger.error("Error: %s, %s, %s" % (lineno, exc_type, exc_obj))
system.tag.writeBlocking([provider + "System/wbsckt_running"], [0])

View File

@ -0,0 +1,155 @@
{
"custom": {
"activityLogger": {
"alt_pageid": "tools",
"start_time": {
"$": [
"ts",
192,
1716471122012
],
"$ts": 1716471122012
}
}
},
"events": {
"system": {
"onShutdown": {
"config": {
"script": "\tactivityLog.productMetrics.callLogger(self, \u0027page\u0027)"
},
"scope": "G",
"type": "script"
},
"onStartup": {
"config": {
"script": "\tself.session.custom.view_in_focus \u003d self.page.props.path\n\tself.custom.activityLogger.start_time \u003d system.date.now()"
},
"scope": "G",
"type": "script"
}
}
},
"params": {},
"propConfig": {
"custom.activityLogger": {
"persistent": true
},
"custom.activityLogger.pageid": {
"binding": {
"config": {
"expression": "{/root.props.currentTabIndex}"
},
"transforms": [
{
"code": "\tpageid\u003d self.custom.activityLogger.alt_pageid+\u0027/\u0027+self.getChild(\"root\").props.tabs[value]\n\treturn pageid.replace(\u0027 \u0027,\u0027\u0027)",
"type": "script"
}
],
"type": "expr"
}
}
},
"props": {
"defaultSize": {
"height": 1080,
"width": 1920
}
},
"root": {
"children": [
{
"meta": {
"name": "CommissioningTool"
},
"props": {
"path": "Main-Views/Commissioning Tool/CT_Main"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "S3"
},
"position": {
"tabIndex": 1
},
"propConfig": {
"props.params.selected_site": {
"binding": {
"config": {
"path": "session.custom.fc"
},
"type": "property"
}
}
},
"props": {
"params": {
"selected_image": null
},
"path": "Main-Views/S3/manage"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "NotifyTool"
},
"position": {
"tabIndex": 2
},
"props": {
"path": "Main-Views/Notify-Tool/Notify-Main"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"tabIndex": 3
},
"props": {
"path": "Main-Views/Config-Tool/MainView"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"propConfig": {
"props.currentTabIndex": {
"onChange": {
"enabled": null,
"script": "\ttry:\n\t\tpageid \u003d self.view.custom.activityLogger.alt_pageid + \u0027/\u0027+ self.props.tabs[previousValue.value]\n\t\tpageid \u003d pageid.replace(\u0027 \u0027,\u0027\u0027)\n\t\tpayload \u003d activityLog.productMetrics.createActivityPayload(self.view, \u0027page\u0027, pageid, pageid)\n\t\tif payload:\n\t\t\tself.view.custom.activityLogger.start_time \u003d system.date.now()\n\t\t\tsystem.perspective.sendMessage(\u0027activityLogger-TabChanged\u0027, payload \u003d payload, scope \u003d \u0027page\u0027)\n\texcept:\n\t\tpass"
}
}
},
"props": {
"currentTabIndex": 3,
"tabs": [
"CT",
"S3",
"Notify Tool",
"Site Config"
]
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "activityLogger-TabChanged",
"pageScope": true,
"script": "\t# implement your handler here\n\tif payload:\n\t\tactivityLog.productMetrics.callActivityLoggerAPI(payload)\n",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.container.tab"
}
}

View File

@ -0,0 +1,21 @@
import json
class SendMessage():
def __init__(self, whid):
self.whid = whid
tag_path = "[%s_SCADA_TAG_PROVIDER]System/wbsckt_messages_send" % (whid)
tags_to_read = system.tag.readBlocking([tag_path])
self.messages_to_send = system.util.jsonDecode(tags_to_read[0].value)
system.tag.writeBlocking([tag_path],[system.util.jsonEncode({})])
self.message_list = {}
def build_message_list(self):
if self.messages_to_send:
self.message_list = json.dumps(self.messages_to_send)
else:
self.message_list = None

View File

@ -0,0 +1,34 @@
def show_alarm_from_docked_window(self,event):
#Get the alarm properties from the alarm object.
"""
Displays the currently active alarm from the south docked alarm table in the detailed view.
If the alarm is on a different page to the current page the function will navigate the user
to the correct page and show the alarm.
Args:
self: Refrence to the object thats invoking this function.
event: Refrence to the event that is invoking this function.
Returns:
The fucntion doses not return any values.
Raises:
KeyError: None
"""
alarm_id = event.value.get("AlarmId")
tags_to_read = system.tag.readBlocking(["System/ActiveAlarms"])
active_alarms = system.util.jsonDecode(tags_to_read[0].value)
UDT = active_alarms.get(alarm_id,{}).get("UDT_tag")
plc = UDT.split("_")[0]
name = active_alarms.get(alarm_id,{}).get("Name")
page_id = active_alarms.get(alarm_id,{}).get("PageId","None")
display_path = active_alarms.get(alarm_id,{}).get("DisplayPath")
#Set the session custom variables to highlight the selected alarm.
self.session.custom.searchId = UDT
self.session.custom.deviceSearchId = display_path
url_to_navigate = "/DetailedView/%s/%s" % (page_id, plc)
system.perspective.navigate(page = url_to_navigate)

View File

@ -0,0 +1,431 @@
{
"custom": {
"box_shadow": "0px 2px 4px rgba(0, 0, 40, 0.15)",
"expanded": true,
"show_content": true
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tself.custom.expanded \u003d self.params.open_expanded\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"anchor_position": null,
"content_shown": true,
"open_expanded": true,
"params": {},
"path": "Objects/Templates/S3/Management/file",
"show_box_shadow_on_expanded": true,
"title": "Card Title",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"propConfig": {
"custom.box_shadow": {
"binding": {
"config": {
"expression": "if(\r\n\t{view.params.show_box_shadow_on_expanded}\u0026\u0026{view.custom.expanded},\r\n\t\u00270px 2px 4px rgba(0, 0, 40, 0.15)\u0027,\r\n\t\u0027\u0027\r\n)"
},
"type": "expr"
},
"persistent": true
},
"custom.expanded": {
"persistent": true
},
"custom.show_content": {
"persistent": true
},
"params.address": {
"paramDirection": "input",
"persistent": true
},
"params.anchor_position": {
"paramDirection": "input",
"persistent": true
},
"params.content_shown": {
"binding": {
"config": {
"path": "view.custom.show_content"
},
"type": "property"
},
"paramDirection": "output",
"persistent": true
},
"params.open_expanded": {
"paramDirection": "input",
"persistent": true
},
"params.params": {
"paramDirection": "input",
"persistent": true
},
"params.path": {
"paramDirection": "input",
"persistent": true
},
"params.show_box_shadow_on_expanded": {
"paramDirection": "input",
"persistent": true
},
"params.system": {
"paramDirection": "input",
"persistent": true
},
"params.title": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultHeight": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultWidth": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 600,
"width": 500
}
},
"root": {
"children": [
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# toggle \u0027show_content\u0027 view custom prop\n\tself.view.custom.show_content \u003d not self.view.custom.show_content"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.image.icon.path": {
"binding": {
"config": {
"expression": "if({view.custom.show_content},\"material/chevron_left\",\"material/chevron_right\")"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {}
},
"primary": false,
"style": {
"borderStyle": "none",
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer Anchor Left"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.params.anchor_position}\u003d\u0027left\u0027"
},
"type": "expr"
}
}
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/Card/Title_transparent",
"margin": "0px",
"padding": "0px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.title"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Title_transparent"
}
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.view.custom.expanded \u003d not self.view.custom.expanded"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"propConfig": {
"props.image.icon.path": {
"binding": {
"config": {
"expression": "if({view.custom.expanded}, \u0027material/expand_less\u0027, \u0027material/expand_more\u0027)"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "24px",
"shrink": 0
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.expanded"
},
"type": "property"
}
},
"props.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"overlayOptOut": true,
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"overlayOptOut": true,
"type": "property"
}
},
"props.useDefaultViewHeight": {
"binding": {
"config": {
"path": "view.params.useDefaultHeight"
},
"type": "property"
}
},
"props.useDefaultViewWidth": {
"binding": {
"config": {
"path": "view.params.useDefaultWidth"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Embedded_transparent"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "100%",
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.show_content"
},
"type": "property"
}
}
},
"props": {
"direction": "column",
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# toggle \u0027show_content\u0027 view custom prop\n\tself.view.custom.show_content \u003d not self.view.custom.show_content"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.image.icon.path": {
"binding": {
"config": {
"expression": "if({view.custom.show_content},\"material/chevron_right\",\"material/chevron_left\")"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {}
},
"primary": false,
"style": {
"borderStyle": "none"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer Anchor Right"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.params.anchor_position}\u003d\u0027right\u0027"
},
"type": "expr"
}
}
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/Card/Title_transparent",
"margin": "0px",
"padding": "0px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"propConfig": {
"props.justify": {
"binding": {
"config": {
"expression": "if({view.params.anchor_position}\u003d\u0027right\u0027,\u0027flex-end\u0027,\u0027flex-start\u0027)"
},
"type": "expr"
}
},
"props.style.boxShadow": {
"binding": {
"config": {
"path": "view.custom.box_shadow"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Card_transparent"
}
},
"type": "ia.container.flex"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
from urllib2_aws4auth import aws_urlopen, Request
from urllib2 import HTTPError
from urllib import urlencode
import json
import system
import boto3
from pprint import pformat
REGION ='us-west-2'
def openSession():
CREDS = boto3.Session().get_credentials()
AWS_ACCESS_KEY_ID = CREDS.access_key
AWS_SECRET_ACCESS_KEY = CREDS.secret_key
TOKEN = CREDS.token
CREDSRETURN = {'AccessKeyId':AWS_ACCESS_KEY_ID,
'SecretAccessKey':AWS_SECRET_ACCESS_KEY,
'SessionToken':TOKEN}
# OPENER = aws_urlopen(
# AWS_ACCESS_KEY_ID,
# AWS_SECRET_ACCESS_KEY,
# REGION,
# SERVICE,
# session_token=TOKEN,
# verify=False)
# return OPENER
return CREDSRETURN
def DynamoReader():
import json
from pprint import pformat
import boto3
from datetime import datetime
from decimal import Decimal
import time
LOGGER = system.util.getLogger('notify_to_dynamodb_log')
# Get STAGE variable
roleArn = 'arn:aws:iam::533266954132:role/ignition_to_aws_scada_notify'
STAGE = 'beta'
# Make sure STAGE is valid. no gamma stage configured
if STAGE not in ['alpha', 'beta', 'gamma', 'prod']:
STAGE = 'beta'
if STAGE == 'gamma':
STAGE = 'beta'
STAGE_CONFIG = {
'alpha':{
'region' : 'us-west-2',
'roleArn' : roleArn,
'tableName' : 'NotificationsEntries'
},
'beta': {
'region':'us-west-2',
'roleArn': roleArn,
'tableName' : 'NotificationsEntries'
},
'prod': {
'region':'us-west-2',
'roleArn': roleArn,
'tableName' : 'NotificationsEntries'
}
}
# create sts session to get credentials from EC2
sts_client = boto3.client('sts')
region_name = STAGE_CONFIG.get(STAGE, 'alpha').get('region', 'us-west-2')
assume_role_response = sts_client.assume_role(
RoleArn = STAGE_CONFIG.get(STAGE, 'beta').get('roleArn', roleArn),
RoleSessionName = 'AssumeRole'
)
temp_credentials = assume_role_response['Credentials']
# create session using the temp creds
b3_session = boto3.Session(
aws_access_key_id = temp_credentials['AccessKeyId'],
aws_secret_access_key = temp_credentials['SecretAccessKey'],
aws_session_token = temp_credentials['SessionToken'],
region_name = 'us-west-2',
)
# create a dynamodb session
dynamodb = b3_session.resource('dynamodb')
table = dynamodb.Table(STAGE_CONFIG.get(STAGE, 'beta').get('tableName', 'NotificationsEntries'))
# response = client.scan(
# TableName='string',
# IndexName='string',
# AttributesToGet=[
# 'string',
# ],
# Limit=123,
# write data directly to dynamodb table
try:
response = table.scan()
# response = table.scan(ProjectionExpression="PrimaryKey, publish, expire, title")
# TableName='NotificationsEntries',
# IndexName='publish',
## ProjectionExpression =['publish', 'expire', 'title'],
# Limit=123)
# system.perspective.print(response)
system.perspective.print('Read from NotificationsEntries DynamoDB Table Successful')
except Exception as e:
system.perspective.print('Read from NotificationsEntries DynamoDB Table NOT Successful')
system.perspective.print(str(e))
LOGGER.error(str(e))
return response

View File

@ -0,0 +1,151 @@
{
"custom": {},
"params": {
"address": "test",
"params": {},
"path": "",
"system": {},
"title": "Card Title",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"propConfig": {
"params.address": {
"paramDirection": "input",
"persistent": true
},
"params.params": {
"paramDirection": "input",
"persistent": true
},
"params.path": {
"paramDirection": "input",
"persistent": true
},
"params.system": {
"paramDirection": "input",
"persistent": true
},
"params.title": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultHeight": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultWidth": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 339,
"width": 369
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "20px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.title"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Title"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"type": "property"
}
},
"props.params.address": {
"binding": {
"config": {
"path": "view.params.address"
},
"type": "property"
}
},
"props.params.system": {
"binding": {
"config": {
"path": "view.params.system"
},
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"type": "property"
}
},
"props.useDefaultViewHeight": {
"binding": {
"config": {
"path": "view.params.useDefaultHeight"
},
"type": "property"
}
},
"props.useDefaultViewWidth": {
"binding": {
"config": {
"path": "view.params.useDefaultWidth"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Embedded"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/Card/Card"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,54 @@
import time
def close_websckt():
"""
This function disconnects the web socket and exits any loops.
Should be called when a project is saved or modified to stop
multiple threads running.
Args:
None
Returns:
N/A
Raises:
N/A
"""
fc = system.tag.readBlocking(["Configuration/FC"])
fc_value = fc[0].value
tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (fc_value)
system.tag.writeBlocking([tag_provider + "System/close_socket"],[0])
running = system.util.getGlobals().get(fc_value, {}).get("wbsckt_running", 0)
if running:
system.util.getGlobals()[fc_value]["wbsckt_running"] = False
system.tag.writeBlocking(tag_provider + "System/wbsckt_running", [0])
time.sleep(2)
system.tag.writeBlocking([tag_provider + "System/close_socket"],[1])
logger = system.util.getLogger("%s-WebSocket-Restart" % (fc))
logger.info("Web-Socket closed due to restart, AWS.wbsckt_abort.close_websckt()")
def check_web_socket():
"""
This function checks to see if the "System/close_socket" tag is active
(boolean on) or inactive (boolean off). If the tag is active the web
socket will run, if it is inactive then the web socket will stop running.
This function is called from the main web socket gateway event.
Used to exit the web socket gateway event.
Args:
None
Returns:
True or False
Raises:
N/A
"""
request_to_close = system.tag.readBlocking(["System/close_socket"])
request_to_close_val = request_to_close[0].value
if not request_to_close_val:
return True
else:
return False

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,551 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running_status": 0,
"searchId": "value",
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"has_state": false,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_gateways},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm}||{session.custom.alarm_filter.show_gateways},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic}||{session.custom.alarm_filter.show_gateways},\r\n\t\t5, {session.custom.alarm_filter.show_gateways},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.has_state": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 47,
"width": 68
}
},
"root": {
"children": [
{
"meta": {
"name": "ControlCabinet"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "M 0 40 L 0 0 L 61 40 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#4c4c4c",
"width": 4
},
"transform": "rotate(-180,30.5,20)",
"type": "path"
},
{
"d": "M 0 40 L 0 0 L 61 40 Z",
"fill": {
"paint": "#4C4C4C"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 4
},
"type": "path"
}
],
"preserveAspectRatio": "none",
"style": {},
"viewBox": "-0.5 -0.5 62 41"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"path": "view.custom.display_icon"
},
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "68:47",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,211 @@
import java.net.http.WebSocketHandshakeException
from java.net.http import HttpClient;
from java.net.http import WebSocket;
from java.net import URI
from java.lang import Thread
import uuid
import json
import time
#Check for a http client stored in the globals.
whid = system.tag.readBlocking(["Configuration/FC"])[0].value
client = system.util.getGlobals().get(whid, {}).get("http_client", None)
#Store the http client as a global variable to be reused on project saves.
if not client:
client = HttpClient.newHttpClient()
system.util.getGlobals()[whid]["http_client"] = client
class Listener(WebSocket.Listener):
"""
Creates a Listener for receiving web socket messages.
The mehtods in this class are standard Java methods
that have been overidden to include additional functionality. onOpen,
onText, onClose and onError are called by the class whenthe web socket
is opened, when the web socket receives data,
when the web socket is closed, when the web socket encounters an error,
respectively. Messages are sent from the web socket by calling the sendText
method on the Listener object.
Args:
whid: Warehouse id for the tag provider (string).
message_handler: A message handler object which parses
the messages received from the onText
method (class)
Returns:
Listener object.
Raises:
Error handling is performed by the onError method.
This method can be overidden with additional logic
for handling errors detected by the Listener object.
"""
def __init__(self, whid, message_handler):
self.whid = whid
self.alarms = {}
self.tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (self.whid)
self.logger = system.util.getLogger("%s-Web-Socket-Listener" % (self.whid))
self.message = ""
self.message_handler = message_handler
def onOpen(self, websocket):
#Generate uuid to help track the connection in aws.
uid = uuid.uuid4()
on_open_subscribe = json.dumps({"action": "subscribe",
"parameters": {"siteId": self.whid,
"clientName": str(uid)}}
)
websocket.sendText(on_open_subscribe, True)
logger = system.util.getLogger("Web-Socket-OnOpen")
self.logger.info("message sent =" + str(on_open_subscribe))
websocket.request(1)
def onText(self, websocket, data, last):
self.message += str(data)
if not last:
websocket.request(1)
else:
json_message = json.loads(self.message)
self.message = ""
self.message_handler.handle_message(json_message)
websocket.request(1)
def onClose(self, websocket, error):
self.logger.info("Onclose method " + str(error))
def onError(self, websocket, error):
self.logger.error("OnError method " + str(error))
def web_socket_main(whid, provider, region, message_handler, secret_name):
"""
Main function for running a web socket. This function can
be called in an asynchronous thread and should only exit
when the socket has been closed or an error is encountered.
The function will create a web socket object and run in a
while loop to keep the socket connection open.
It will exit if an error is encounterd, the socket is manually
closed from the tag provider or the socket is closed.
Args:
whid: Warehouse id for the tag provider (string).
provider: Tag provider that the web socket will use to write messages to/from (string).
region: The AWS region of the api endpoint. Usally the same region as the EC2
running the web socket (string).
message_handler: message handler object used for parsing of the web socket messages (class).
secret_name : name of the secret to be passed into the web socket. This will retreive the api endpoint for AWS.
Returns:
N/A.
Raises:
Secrets manager error
web socket error
"""
thread_name = str(Thread.getId(Thread.currentThread()))
system.tag.writeAsync([provider + "system/thread_id"],[thread_name])
system.util.getGlobals()[whid]["wbsckt_running"] = True
system.tag.writeAsync([provider + "System/wbsckt_running"],[1])
logger_name = "%s-web-socket-main" % (whid)
logger = system.util.getLogger(logger_name)
timer_end = None
timer_started = False
"""The heartbeat is initalised with the current time on first connect
Each time a new heartbeat is recieved in AWS.message_types
the current time is written to the tag wbsckt_heartbeat_interval.
The websocket checks that a heartbeat has been recieved at least every 120 secs.
If a heartbeat is not recieved within the 120 sec duration the connection is closed and the loop will exit.
"""
AWS.heartbeat.get_heartbeat(provider)
tags_to_read = system.tag.readBlocking([provider + "System/wbsckt_heartbeat_interval"])
wbsckt_heartbeat_interval = tags_to_read[0].value
#Return api endpoint from secrets manager.
API_ID, STAGE, ACC_ID, FUNC_URL = AWS.secrets_manager.get_secret(whid, secret_name)
try:
credentials = AWS.credentials.assume_role(profile_name = "default", region = region, arn = ACC_ID, api_id = API_ID, stage = STAGE)
except:
AWS.errors.error_handler(whid, "AWS.credentials.assume_role")
return
logger.info("Building URL ....")
url, headers = AWS.build_url.make_websocket_connection(API_ID, region, STAGE, credentials)
listener = AWS.web_socket.Listener(whid, message_handler)
# client = HttpClient.newHttpClient()
#set the client as global (stored in the system global variables).
global client
uri = URI.create(url)
logger.info(str(uri))
logger.info("Building web-socket object ....")
wsBuilder = client.newWebSocketBuilder()
wsBuilder.header("Authorization", headers["Authorization"])
wsBuilder.header("X-Amz-Date", headers["X-Amz-Date"])
wsBuilder.header("X-Amz-Security-Token", headers["X-Amz-Security-Token"])
try:
wsObj = wsBuilder.buildAsync(uri, listener)
except:
AWS.errors.error_handler(whid, "Build web socket")
return
web_socket = wsObj.get()
logger.info("Web socket object built, starting while loop ....")
running = 1
while True:
time.sleep(0.1)
if running == 1:
logger.info("While loop running ....")
running = 0
if AWS.heartbeat.check_heartbeat(provider, 70):
web_socket.sendClose(web_socket.NORMAL_CLOSURE, "Missing heartbeat")
logger.warn("socket closed , missing heartbeat")
web_socket.abort()
text_val = web_socket.sendText(str({"action":"abort"}), True)
break
check_socket_closed_in_loop = AWS.wbsckt_abort.check_web_socket()
if check_socket_closed_in_loop:
web_socket.sendClose(web_socket.NORMAL_CLOSURE, "")
logger.info("socket close initiated")
# web_socket.abort()
text_val = web_socket.sendText(str({"action":"abort"}), True)
break
if not timer_started:
timer_start = system.date.now()
timer_started = True
timer_end = system.date.now()
time_diff = system.date.secondsBetween(timer_start, timer_end)
if time_diff >= wbsckt_heartbeat_interval:
send_heartbeat = True
timer_started = False
if web_socket.isOutputClosed():
logger.info("Websocket output closed")
break
if web_socket.isInputClosed():
logger.info("Websocket input closed")
break
this_thread = system.tag.readBlocking(provider + "System/thread_id")[0].value
if this_thread != thread_name:
logger.warn("thread_id does not match current thread_id")
break
tags_to_read = system.tag.readBlocking(["System/wbsckt_messages_send"])
messages = system.util.jsonDecode(tags_to_read[0].value)
message_list = messages.get("message_list")
if message_list:
for i in message_list:
message_string = str(i)
formatted_string = message_string.replace("u'","'")
json_string = formatted_string.replace("'","\"")
web_socket.sendText(str(json_string), True)
logger.info("Message sent: " + str(json_string))
system.tag.writeAsync(["System/wbsckt_messages_send"], "{}")
system.util.getGlobals()[whid]["wbsckt_running"] = False
web_socket.abort()
system.tag.writeBlocking([provider + "System/wbsckt_running"], [0])

View File

@ -0,0 +1,141 @@
{
"custom": {},
"params": {
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"params.tagProps": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 41,
"width": 83
}
},
"root": {
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif self.view.params.tagProps[0] is not True:\n\t\tnavigation.additional_view.navigate_to_additional_view(self)\n\telse:\n\t\tnavigation.navigate_to_page.detailed_view(self, self.view.params.tagProps[2],self.view.params.tagProps[2], self.view.params.tagProps[3])"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"basis": "41px"
},
"propConfig": {
"custom.page_id": {
"binding": {
"config": {
"path": "view.params.tagProps[2]"
},
"type": "property"
}
},
"custom.status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "direct",
"tagPath": "Configuration/DetailedViews.value"
},
"transforms": [
{
"code": "\t\n\tjson_decode \u003d system.util.jsonDecode(value)\n\tpage_id \u003d self.custom.page_id\n\tpage_status \u003d json_decode.get(\"AdditionalPages\",{}).get(page_id,5)\n\treturn page_status",
"type": "script"
}
],
"type": "tag"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "{this.custom.status}"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "State-Styles/Background-Fill/State1"
},
{
"input": 2,
"output": "State-Styles/Background-Fill/State2"
},
{
"input": 3,
"output": "State-Styles/Background-Fill/State3"
},
{
"input": 4,
"output": "State-Styles/Background-Fill/State4"
},
{
"input": 5,
"output": "Buttons/Clear-Background"
},
{
"input": 6,
"output": "State-Styles/Background-Fill/State6"
},
{
"input": 0,
"output": "State-Styles/Background-Fill/State0"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/navigation"
}
},
"style": {},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,894 @@
{
"custom": {
"activityLogger": {
"alt_pageid": "home"
}
},
"params": {
"viewFocus": "value"
},
"propConfig": {
"custom.activityLogger": {
"persistent": true
},
"custom.activityLogger.pageid": {
"binding": {
"config": {
"expression": "{page.props.path}"
},
"transforms": [
{
"code": "\tif value \u003d\u003d\u0027/\u0027 or value \u003d\u003d \u0027\u0027 or value \u003d\u003d None:\n\t\treturn self.custom.activityLogger.alt_pageid.lower()\n\telse:\n\t\treturn value[1:].lower()",
"type": "script"
}
],
"type": "expr"
}
},
"custom.activityLogger.start_time": {
"binding": {
"config": {
"expression": "now()"
},
"type": "expr"
}
},
"params.viewFocus": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 326,
"width": 400
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "36px",
"shrink": 0
},
"props": {
"style": {
"background-color": "#555555",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Status Filters"
},
"type": "ia.display.label"
},
{
"children": [
{
"custom": {
"buttonid": "status_filters/all"
},
"events": {
"component": {
"onActionPerformed": [
{
"config": {
"script": "\tpayload \u003d {}\n\tif self.props.selected:\n\t\tvalue \u003d True\n\telse:\n\t\tvalue \u003d False\n\t\n\tpayload[\"data\"] \u003d value\n\t\n\tsystem.perspective.sendMessage(\"select-all-filters\", \n\t\t\t\t\t\t\t\t\tpayload \u003d payload, \n\t\t\t\t\t\t\t\t\tscope \u003d \"view\")"
},
"scope": "G",
"type": "script"
},
{
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
]
}
},
"meta": {
"name": "Select-All",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"expression": "if({session.custom.alarm_filter.show_diagnostic} \u0026\u0026 \r\n{session.custom.alarm_filter.show_gateways} \u0026\u0026\r\n{session.custom.alarm_filter.show_low_alarm} \u0026\u0026\r\n{session.custom.alarm_filter.show_running} \u0026\u0026 \r\n{session.custom.alarm_filter.show_safety}, True, False)"
},
"type": "expr"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Select All"
},
"type": "ia.input.checkbox"
},
{
"custom": {
"buttonid": "status_filters/low_alarms"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Low Alarms",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.show_low_alarm"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Show Low Alarms"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "select-all-filters",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.selected \u003d data\n\tsystem.perspective.print(data)",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.checkbox"
},
{
"custom": {
"buttonid": "status_filters/diagnostic_alarms"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Diagnostic",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.show_diagnostic"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Show Diagnostic Alarms"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "select-all-filters",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.selected \u003d data",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.checkbox"
},
{
"custom": {
"buttonid": "status_filters/running_status"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Running",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.show_running"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Show Running Status"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "select-all-filters",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.selected \u003d data",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.checkbox"
},
{
"custom": {
"buttonid": "status_filters/estops_pullChords"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "E-Stops",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.show_safety"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Show E-Stops \u0026 Pull Chords"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "select-all-filters",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.selected \u003d data",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.checkbox"
},
{
"custom": {
"buttonid": "status_filters/gateways"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif not self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Show-Gateways",
"tooltip": {
"delay": 250
}
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "if ({session.custom.alarm_filter.show_map}\u003dTrue \u0026\u0026 {session.custom.view_in_focus}\u003d\u0027/MAP-Home\u0027, True, False)"
},
"enabled": false,
"type": "expr"
}
},
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.show_gateways"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Show Gateways"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "select-all-filters",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.selected \u003d data",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.checkbox"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"justify": "space-between"
},
"type": "ia.container.flex"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup(\u0027\u0027)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"basis": "30px",
"shrink": 0
},
"props": {
"box-shadow": "5px 5px 5px",
"style": {
"backgroundColor": "#555555",
"classes": "Background-Styles/Controller",
"marginBottom": 5,
"marginLeft": 20,
"marginRight": 20,
"marginTop": 5
},
"text": "Close"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "Status"
},
"position": {
"basis": "200px",
"shrink": 0
},
"props": {
"direction": "column",
"style": {
"borderColor": "#FFFFFF",
"borderStyle": "solid",
"borderWidth": 1
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "36px",
"shrink": 0
},
"props": {
"style": {
"background-color": "#555555",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Accessibility"
},
"type": "ia.display.label"
},
{
"children": [
{
"custom": {
"buttonid": "accessibility/color_blind_icons"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Alt Colours"
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.colours.colour_impaired"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Colour-Blind Friendly Icons"
},
"type": "ia.input.checkbox"
},
{
"children": [
{
"meta": {
"name": "Label_0"
},
"props": {
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Magnification:"
},
"type": "ia.display.label"
},
{
"custom": {
"buttonid": "accessibility/magnify"
},
"meta": {
"name": "Dropdown"
},
"position": {
"basis": "80px",
"shrink": 0
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.magnificaiton"
},
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\ttry:\n\t\tif previousValue.value !\u003d currentValue.value:\n\t\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, self.custom.buttonid)\n\texcept:\n\t\tpass"
}
}
},
"props": {
"options": [
{
"label": "x1",
"value": "x1"
},
{
"label": "x2",
"value": "x2"
},
{
"label": "x3",
"value": "x3"
},
{
"label": "None",
"value": "None"
}
],
"placeholder": {
"text": ""
},
"style": {
"marginBottom": 3,
"marginTop": 3
}
},
"type": "ia.input.dropdown"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "36px"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": 80
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "36px",
"shrink": 0
},
"props": {
"style": {
"background-color": "#555555",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Home Card View"
},
"type": "ia.display.label"
},
{
"children": [
{
"custom": {
"buttonid": "status_filters/orderby"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tif self.props.selected:\n\t\tbuttonid \u003d self.custom.buttonid\n\t\tactivityLog.logger.callLogger(self.view, \u0027click\u0027, buttonid)\n\t\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Order-By"
},
"position": {
"basis": "36px"
},
"propConfig": {
"props.selected": {
"binding": {
"config": {
"bidirectional": true,
"path": "session.custom.alarm_filter.orderby"
},
"type": "property"
}
}
},
"props": {
"checkedIcon": {
"color": {
"disabled": "#FFFFFF",
"enabled": "#FFFFFF"
}
},
"style": {
"color": "#FFFFFF",
"fontFamily": "Arial",
"fontSize": 12,
"fontWeight": "bold",
"marginLeft": 10,
"marginRight": 10
},
"text": "Order Cards By Area"
},
"type": "ia.input.checkbox"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "32px",
"display": false
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.viewFocus"
},
"transforms": [
{
"code": "#\tvalue \u003d value.split(\u0027/\u0027)\n#\tvalue \u003d value.pop()\n\n\treturn value",
"type": "script"
}
],
"type": "property"
}
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": 65,
"grow": 1
},
"props": {
"direction": "column",
"justify": "space-between"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Accessibility"
},
"position": {
"basis": "200px",
"shrink": 0
},
"props": {
"direction": "column",
"style": {
"borderColor": "#FFFFFF",
"borderStyle": "solid",
"borderWidth": 1
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"style": {
"classes": "Background-Styles/Controller"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,318 @@
{
"custom": {
"numberOfColumns": 6,
"test": [
{
"Label": "Seq",
"Value": 2,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "Type",
"Value": "StateChanged",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "When",
"Value": "1670429640000",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "Source",
"Value": "PLC01/054BV55",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "CurrentState",
"Value": "",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "ReasonCode",
"Value": "",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
}
]
},
"params": {
"checkedState": "False",
"index": "value",
"rowData": [
[
"Seq",
2
],
[
"Type",
"StateChanged"
],
[
"When",
"1670429640000"
],
[
"Source",
"PLC01/054BV55"
],
[
"CurrentState",
""
],
[
"ReasonCode",
""
]
]
},
"propConfig": {
"custom.test": {
"persistent": true
},
"params.checkedState": {
"paramDirection": "input",
"persistent": true
},
"params.index": {
"paramDirection": "input",
"persistent": true
},
"params.rowData": {
"onChange": {
"enabled": null,
"script": "\tself.custom.numberOfColumns \u003d len(self.params.rowData)\n\t\n\tsystem.perspective.print(\"ROW SCRIPT\")\n\tsystem.perspective.print(self.params.rowData)\n\tinstances \u003d []\n\t\n\tfor col in self.params.rowData:\n\t\tsystem.perspective.print(col)\n\t\tinstance \u003d {\n\t\t\t \"instanceStyle\": {\n\t\t\t \"classes\": \"\"\n\t\t\t },\n\t\t\t \"instancePosition\": {},\n\t\t\t \"Label\": col[0],\n\t\t\t \"Value\": col[1]\n\t\t\t }\n\t\tinstances.append(instance)\n\t\t\n\tself.getChild(\"root\").getChild(\"FlexRepeater\").props.instances \u003d instances\n\t\n\tself.custom.test \u003d instances\n"
},
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 86,
"width": 1220
}
},
"root": {
"children": [
{
"custom": {
"SelectionData": "value"
},
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.print(self.view.params.index)\n\tmsg \u003d \"update_selectionData\"\n\tpayload \u003d {\n\t\t\"index\" : self.view.params.index,\n\t\t\"state\"\t: self.props.selected\n\t}\n\tsystem.perspective.sendMessage(msg, payload)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Checkbox"
},
"position": {
"basis": "40px",
"shrink": 0
},
"propConfig": {
"props.selected": {
"binding": {
"config": {
"path": "view.params.checkedState"
},
"type": "property"
}
}
},
"props": {
"style": {
"marginRight": "2px"
},
"text": ""
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "tableSelectionData",
"pageScope": true,
"script": "\t# implement your handler here\n\tself.custom.SelectionData \u003d payload",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.input.checkbox"
},
{
"custom": {
"key": {
"backgroundColor": "#F2F3F4",
"borderStyle": "none",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"max-height": "400px",
"overflow": "visible"
}
},
"meta": {
"name": "FlexRepeater"
},
"props": {
"elementPosition": {
"basis": "150px"
},
"instances": [
{
"Label": "Seq",
"Value": 2,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "Type",
"Value": "StateChanged",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "When",
"Value": "1670429640000",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "Source",
"Value": "PLC01/054BV55",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "CurrentState",
"Value": "",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Label": "ReasonCode",
"Value": "",
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
}
],
"path": "Main-Views/Commissioning Tool/Column",
"style": {
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderStyle": "solid",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"borderWidth": "1px",
"margin": "2px",
"marginRight": 5,
"overflow": "hidden",
"radius": "4px"
},
"useDefaultViewHeight": false
},
"type": "ia.display.flex-repeater"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.print(self.view.params.index)\n\tmsg \u003d \"measurementTab_deleteRows\"\n\tpayload \u003d {\"index\" : self.view.params.index}\n\tsystem.perspective.sendMessage(msg, payload)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"position": {
"grow": 1
},
"props": {
"image": {
"icon": {
"path": "material/delete_forever"
}
},
"primary": false,
"style": {
"margin": "10 px",
"max-height": "40px"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "40px",
"shrink": 0
},
"props": {
"direction": "column",
"justify": "center"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"style": {
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"classes": "FadeInFast, background, background-none",
"margin": "5px",
"max-height": "75px"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,656 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "PPI"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"id": "defs1",
"name": "defs1",
"type": "defs"
},
{
"elements": [
{
"cx": "6.6145835",
"cy": "6.6145835",
"fill": {},
"id": "path1",
"name": "path1",
"r": "6.019948",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "circle"
},
{
"d": "m 2.1166666,8.5242134 h 3.175",
"fill": {
"paint": "transparent"
},
"id": "path2",
"name": "path2",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "path"
},
{
"d": "M 7.9374999,8.5242134 H 11.112492",
"fill": {
"paint": "transparent"
},
"id": "path3",
"name": "path3",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "path"
},
{
"d": "M 5.1593748,4.183724 V 8.4170573",
"fill": {
"paint": "transparent"
},
"id": "path5",
"name": "path5",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "path"
},
{
"d": "m 8.2020833,4.1405926 h -3.175",
"fill": {
"paint": "transparent"
},
"id": "path6",
"name": "path6",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "path"
},
{
"d": "M 8.0697914,4.183724 V 8.4170573",
"fill": {
"paint": "transparent"
},
"id": "path7",
"name": "path7",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "path"
}
],
"id": "layer1",
"name": "layer1",
"type": "group"
}
],
"style": {},
"viewBox": "0 0 13.229166 13.229167"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,101 @@
import datetime
import hashlib
import hmac
import boto3
try:
from urllib.parse import quote_plus
except ImportError:
from urllib import quote_plus
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(("AWS4" + key).encode("utf-8"), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, "aws4_request")
return kSigning
def build_querystring(access_key, session_key, algorithm, amz_date, credential_scope):
query_strings = {
"X-Amz-Algorithm": algorithm,
"X-Amz-Credential": quote_plus(access_key + "/" + credential_scope),
"X-Amz-Date": amz_date,
#"X-Amz-Security-Token": quote_plus(session_key),
"X-Amz-SignedHeaders": "host",
}
keys = list(query_strings.keys())
keys.sort()
query = []
for key in keys:
query.append("{}={}".format(key, query_strings[key]))
canonical_query_string = "&".join(
query
#["{}={}".format(key, value) for key, value in query_strings.items()]
)
return canonical_query_string
def make_websocket_connection(api_id, region, stage, credentials):
method = "GET"
service = "execute-api"
host = "{}.{}.{}.amazonaws.com".format(api_id, service, region)
canonical_uri = "/{}".format(stage)
access_key = credentials["AccessKey"]
secret_key = credentials["SecretKey"]
session_key = credentials["SessionKey"]
now = datetime.datetime.utcnow()
amz_date = now.strftime("%Y%m%dT%H%M%SZ")
datestamp = now.strftime("%Y%m%d")
canonical_headers = "host:" + host + "\n"
signed_headers = "host"
algorithm = "AWS4-HMAC-SHA256"
credential_scope = "/".join([datestamp, region, service, "aws4_request"])
canonical_querystring = build_querystring(
access_key, session_key, algorithm, amz_date, credential_scope
)
payload_hash = hashlib.sha256(("").encode("utf-8")).hexdigest()
canonical_request = "\n".join(
[
method,
canonical_uri,
"",
#canonical_querystring,
canonical_headers,
signed_headers,
payload_hash,
]
)
string_to_sign = "\n".join(
[
algorithm,
amz_date,
credential_scope,
hashlib.sha256(canonical_request.encode("utf-8")).hexdigest(),
]
)
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(
signing_key, string_to_sign.encode("utf-8"), hashlib.sha256
).hexdigest()
canonical_querystring += "&X-Amz-Signature=" + signature
request_url = "wss://{}/{}".format(host, stage)
auth_header = algorithm + " Credential=" + access_key + "/" + credential_scope + ", SignedHeaders=" + signed_headers + ", Signature=" + signature
#print('-H "Authorization":"' + auth_header +'" -H "X-Amz-Date":"' + amz_date + '" -H "X-Amz-Security-Token":"' + session_key + '" ')
request_headers = {
"Authorization":auth_header,
"X-Amz-Date": amz_date,
"X-Amz-Security-Token": session_key
}
return request_url, request_headers

View File

@ -0,0 +1,44 @@
def get_state_table(active_states):
faulted = []
stopped = []
running = []
style_class = {}
state_lookup = {1:"Faulted", 2:"Stopped", 3:"Running"}
for i in active_states:
source_id = i
time_stamp = active_states[i].get("timestamp","Unknown")
time_stamp_converted = alarms.alarm_tables.get_timestamp(time_stamp)
state = active_states[i].get("state","Unknown")
if time_stamp !=("Unknown"):
duration = alarms.alarm_tables.convert(int(time_stamp))
else:
duration = 0
state_list = []
if state == 3:
state_list = running
style_class = {"classes":"State-Styles/State5"}
state = state_lookup.get(state, 6)
elif state == 2:
state_list = stopped
style_class = {"classes":"State-Styles/State2"}
state = state_lookup.get(state, 6)
elif state == 1:
state_list = faulted
style_class = {"classes":"State-Styles/State1"}
state = state_lookup.get(state, 6)
else:
pass
state_row = row_builder.build_row_with_view(SourceId = source_id,
TimeStamp = time_stamp_converted,
Duration = duration,
State = state,
StyleClass = style_class )
state_list.append(state_row)
return faulted + stopped + running

View File

@ -0,0 +1,55 @@
{
"custom": {},
"params": {},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "32px"
},
"props": {
"style": {
"fontFamily": "Arial",
"fontSize": 22,
"fontWeight": "bold",
"textAlign": "center"
},
"text": "TEMPERATURE"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Table"
},
"position": {
"basis": "400px"
},
"propConfig": {
"props.data": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "direct",
"tagPath": "[IEC_SCADA_TAG_PROVIDER]Temperature/temperature_monitoring"
},
"type": "tag"
}
}
},
"type": "ia.display.table"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,227 @@
{
"custom": {},
"params": {
"tagProps": [
"",
"",
"",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
},
"params.tagProps[0]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[1]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[2]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[3]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[4]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[5]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[6]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[7]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[8]": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps[9]": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 40,
"width": 40
},
"styles": "value"
},
"root": {
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "264px"
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "if({parent.custom.state}\u003d1||{parent.custom.covert_mode}||{parent.custom.isMatch}\u003e0,true,false)"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "{parent.custom.ref_state}"
},
"overlayOptOut": true,
"transforms": [
{
"fallback": "EmergencyStop-Styles/EstopDeactivated",
"inputType": "scalar",
"mappings": [
{
"input": 0,
"output": "EmergencyStop-Styles/EstopDeactivated"
},
{
"input": 1,
"output": "EmergencyStop-Styles/EstopActivated"
},
{
"input": 101,
"output": "EmergencyStop-Styles/EstopActivated101"
},
{
"input": 100,
"output": "EmergencyStop-Styles/EstopDeactivated100"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"path": "material/lens"
},
"type": "ia.display.icon"
}
],
"custom": {
"status": "value"
},
"events": {
"dom": {
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"DevicePopUP\", \"PopUp-Views/Device/Information-Device\", params \u003d{\"tagProps\":tagProps},resizable \u003d 1)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"propConfig": {
"custom.alarm_active": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"1": "{view.params.tagProps[1]}"
},
"tagPath": "{0}/Alarms/{1}.IsActive"
},
"type": "tag"
}
},
"custom.alarm_shelved": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"1": "{view.params.tagProps[1]}"
},
"tagPath": "{0}/Alarms/{1}.IsShelved"
},
"type": "tag"
}
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "session.custom.covert"
},
"type": "property"
}
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({session.custom.deviceSearchId} \u003d {this.custom.search_path},1,0)"
},
"type": "expr"
},
"onChange": {
"enabled": null,
"script": "\tif currentValue.value \u003d\u003d 1:\n\t\tself.print(self.custom.search_path)\n\t\tself.session.custom.searchId \u003d \"\""
},
"persistent": false
},
"custom.ref_state": {
"binding": {
"config": {
"expression": "if({this.custom.state}\u003d1 \u0026\u0026 {this.custom.isMatch}\u003d1,101,\nif({this.custom.state}\u003d1 \u0026\u0026 {this.custom.isMatch}\u003d0,1,\nif({this.custom.state}\u003d0 \u0026\u0026 {this.custom.isMatch}\u003d1,100,0)))"
},
"type": "expr"
}
},
"custom.search_path": {
"binding": {
"config": {
"expression": "{view.params.tagProps[0]}+\"/\"+{view.params.tagProps[1]}"
},
"type": "expr"
}
},
"custom.state": {
"binding": {
"config": {
"expression": "if({this.custom.alarm_shelved}\u003dTrue,0,\nif({this.custom.alarm_active}\u003dTrue,1,0))"
},
"type": "expr"
}
}
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,522 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running_status": 0,
"searchId": "value",
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"has_state": false,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.has_state": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 40,
"width": 30
}
},
"root": {
"children": [
{
"meta": {
"name": "Icon_0"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours}[\"state\"+{value}] \u003d null, \r\n{session.custom.colours}[\"Fallback\"],\r\n{session.custom.colours}[\"state\"+{value}])",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"color": "#000000",
"path": "material/offline_bolt",
"style": {
"borderColor": "#000000",
"borderStyle": "solid",
"borderWidth": "2px"
}
},
"type": "ia.display.icon"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "40:60",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,237 @@
{
"custom": {},
"params": {},
"props": {
"defaultSize": {
"height": 1080,
"width": 400
}
},
"root": {
"children": [
{
"children": [
{
"children": [
{
"custom": {
"selected_tag": "[BRS1_SCADA_TAG_PROVIDER]System/device_count"
},
"events": {
"component": {
"onNodeClick": {
"config": {
"script": "\tpath \u003d event.path\n\tinfo \u003d system.tag.getConfiguration(path)\n\ttag_type \u003d str(info[0].get(\"tagType\"))\n\tif tag_type \u003d\u003d \"AtomicTag\":\n\t\tself.custom.selected_tag \u003d path\n\telse:\n\t\tself.custom.selected_tag \u003d None"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "TagBrowseTree"
},
"position": {
"basis": "669px"
},
"propConfig": {
"custom.tag_value": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"selected_tag": "{this.custom.selected_tag}"
},
"tagPath": "{selected_tag}"
},
"transforms": [
{
"code": "\timport org.python.core.PyUnicode as uni\n\tif value \u003d\u003d None:\n\t\treturn \"N/A\"\n\t\t\n\tif isinstance(value, uni) and len(value) \u003e 50:\n\t\treturn (value[:50])\n\treturn value",
"type": "script"
}
],
"type": "tag"
},
"onChange": {
"enabled": null,
"script": "\tpayload \u003d {}\n\ttag_value \u003d self.custom.tag_value\n\tpayload[\"data\"] \u003d tag_value \n\tsystem.perspective.sendMessage(\"update-tag-value\", payload, scope \u003d \"view\")"
}
},
"props.root.path": {
"binding": {
"config": {
"expression": "concat(\"[\",{session.custom.fc},\"_SCADA_TAG_PROVIDER]\")"
},
"type": "expr"
}
}
},
"props": {
"root": {},
"selection": {
"mode": "single",
"values": [
"[BRS1_SCADA_TAG_PROVIDER]System/device_count"
]
}
},
"type": "ia.display.tag-browse-tree"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "32px"
},
"props": {
"path": "material/local_offer",
"style": {
"marginLeft": "10px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "80px"
},
"props": {
"style": {
"textIndent": "10px"
},
"text": "Tag Value",
"textStyle": {
"fontSize": "12px",
"fontWeight": "bold"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": "40px"
},
"props": {
"style": {
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderStyle": "none",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"marginLeft": "10px",
"marginRight": "10px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Markdown"
},
"position": {
"basis": "301px"
},
"props": {
"source": "{}",
"style": {
"fontFamily": "Arial",
"textIndent": "10px"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-tag-value",
"pageScope": false,
"script": "\tdata \u003d payload[\"data\"]\n\tself.props.source \u003d data",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.markdown"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "112px"
},
"props": {
"style": {
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderStyle": "solid",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"margin": "10px",
"marginLeft": "10px",
"marginRight": "10px",
"marginTop": "10px",
"paddingBottom": "10px",
"paddingLeft": "10px",
"paddingRight": "10px",
"paddingTop": "10px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "1025px"
},
"props": {
"direction": "column",
"style": {
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderStyle": "solid",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"margin": "10px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "361px",
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,59 @@
{
"custom": {
"show_alarms": false
},
"params": {
"customView": "",
"plcTagPath": ""
},
"propConfig": {
"custom.show_alarms": {
"persistent": true
},
"params.customView": {
"paramDirection": "input",
"persistent": true
},
"params.plcTagPath": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 1080,
"width": 1920
}
},
"root": {
"children": [
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"basis": "320px",
"grow": 1
},
"propConfig": {
"props.path": {
"binding": {
"config": {
"expression": "\"Custom-Views/\"+ {view.params.customView}"
},
"type": "expr"
}
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,64 @@
import csv
from StringIO import StringIO
def check_csv_file(event):
"""
This function checks if the CSV file was saved as CSV-UF8 settings if it has removes extra data bytes from the file.
Args:
event : Containes the file data to be uploaded
Returns:
a string representing the file that is to be uploaded.
Raises:
None
"""
file_bytes = event.file.getBytes()
if bytearray.fromhex("ef bb bf") == bytearray(file_bytes[0:3]):
# Strip first three bytes
file_bytes = file_bytes[3:]
return file_bytes.tostring()
def add_device_btn_code(whid, event):
reader = csv.DictReader(StringIO(FileHandler.uploader.check_csv_file(event)))
data ={}
def get_child():
return {
"Area":"",
"SubArea":""
}
for i, v in enumerate(reader):
child = get_child()
child["Area"] = v["Area"]
child["SubArea"] = v["SubArea"]
data[v["Device"]]= child
system.tag.writeBlocking(["[%s_SCADA_TAG_PROVIDER]Configuration/PLC"%whid], system.util.jsonEncode(data))
return "Success"
def add_detailed_view_btn_code(whid, event):
reader = csv.DictReader(StringIO(FileHandler.uploader.check_csv_file(event)))
data ={}
def convert_dict_value_to_list(string):
device_list = []
for i in string.replace("#", ",").split(","):
device_list.append(i.strip())
return device_list
for v in reader:
data[v["DetailedView"]]= convert_dict_value_to_list(v["Devices"])
system.tag.writeBlocking(["[%s_SCADA_TAG_PROVIDER]Configuration/DetailedViews"%whid], system.util.jsonEncode(data))
return "Success"

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,129 @@
{
"custom": {},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tself.params.request_focus \u003d True\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"enabled": true,
"placeholder": "enter text...",
"request_focus": false,
"text": ""
},
"propConfig": {
"params.enabled": {
"paramDirection": "input",
"persistent": true
},
"params.placeholder": {
"paramDirection": "input",
"persistent": true
},
"params.request_focus": {
"onChange": {
"enabled": null,
"script": "\t# if focus request set externally, set focus via message and clear request\n\tif currentValue.value:\n\t\tsystem.perspective.sendMessage(\u0027request_focus\u0027, scope\u003d\u0027view\u0027)\n\t\tself.params.request_focus \u003d False\n\t"
},
"paramDirection": "inout",
"persistent": true
},
"params.text": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 50,
"width": 200
}
},
"root": {
"children": [
{
"meta": {
"name": "TextField"
},
"position": {
"grow": 1
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"path": "view.params.enabled"
},
"type": "property"
}
},
"props.placeholder": {
"binding": {
"config": {
"path": "view.params.placeholder"
},
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({this.props.enabled},\u0027Input/Text/text_field_enabled\u0027,\u0027Input/Text/text_field_disabled\u0027)"
},
"type": "expr"
}
},
"props.text": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.text"
},
"overlayOptOut": true,
"type": "property"
}
}
},
"props": {
"style": {
"margin": "1%",
"padding": "1%"
}
},
"scripts": {
"customMethods": [
{
"name": "set_focus",
"params": [],
"script": "\tfrom time import sleep\n\tsleep(0.25)\n\tself.focus()\n\t"
}
],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "request_focus",
"pageScope": false,
"script": "\tsystem.util.invokeAsynchronous(self.set_focus())\n\t",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.input.text-field"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,687 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "PLC01",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "LIFT_Symbol"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[4].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[4].elements[1].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\n{view.custom.state} + 100 + {view.custom.isMatch},\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"id": "defs2",
"name": "defs2",
"type": "defs"
},
{
"d": "M 2.5706316,14.829176 A 8.6886292,8.8029537 0 0 1 3.7045976,2.4348857 8.6886292,8.8029537 0 0 1 15.938255,3.5801235 8.6886292,8.8029537 0 0 1 14.811492,15.975088 8.6886292,8.8029537 0 0 1 2.5771713,14.837148",
"fill": {},
"id": "path392",
"name": "path392",
"stroke": {
"dasharray": "none",
"miterlimit": "4",
"paint": "#000000",
"width": "0.301"
},
"type": "path"
},
{
"d": "m 9.5390129,4.6864138 v 4.054911",
"fill": {
"paint": "#ffffff"
},
"id": "path5019",
"name": "path5019",
"stroke": {
"width": "0.995"
},
"style": {
"InkscapeStroke": "none",
"color": "#000000"
},
"type": "path"
},
{
"d": "M 9.4725388,4.3208071 V 10.203752",
"fill": {
"paint": "#ffffff"
},
"id": "path5287",
"name": "path5287",
"stroke": {
"width": "0.264583"
},
"style": {
"InkscapeStroke": "none",
"color": "#000000"
},
"type": "path"
},
{
"elements": [
{
"d": "M 5.5505752,8.3092441 H 12.962422 L 9.2349587,2.4863396 Z",
"fill": {
"opacity": "1"
},
"id": "path5305",
"name": "path5305",
"stroke": {
"dasharray": "none",
"linecap": "butt",
"miterlimit": "4",
"opacity": "1",
"paint": "#000000",
"width": "0.656167"
},
"type": "path"
},
{
"d": "M 5.5653282,10.042435 H 12.977175 L 9.2497117,15.865339 Z",
"fill": {
"opacity": "1"
},
"id": "path5305-1",
"name": "path5305-1",
"stroke": {
"dasharray": "none",
"linecap": "butt",
"miterlimit": "4",
"opacity": "1",
"paint": "#000000",
"width": "0.656167"
},
"type": "path"
}
],
"id": "g5310",
"name": "g5310",
"type": "group"
}
],
"style": {},
"viewBox": "0 0 18.520832 18.520834"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,127 @@
{
"pages": {
"/": {
"title": "",
"viewPath": "Main-Views/Home"
},
"/Command": {
"title": "",
"viewPath": "Main-Views/CommandControl"
},
"/CustomView/:customView": {
"title": "",
"viewPath": "Custom-Views/Detail"
},
"/DetailedView/:detailedView/:plcTagPath": {
"title": "DetailedView",
"viewPath": "Detailed-Views/Detail"
},
"/Device-manager": {
"viewPath": "Main-Views/Device-Manager/DeviceManager"
},
"/Help": {
"title": "Help",
"viewPath": "Main-Views/Help"
},
"/MAP-Home": {
"title": "",
"viewPath": "Additional-Home-View/MAP-Home"
},
"/Monitron": {
"viewPath": "Main-Views/Monitron"
},
"/Oil": {
"viewPath": "Main-Views/OilMonitoring"
},
"/Real-Time": {
"viewPath": "Alarm-Views/RealTime"
},
"/Temperature": {
"title": "",
"viewPath": "Main-Views/TempMonitoring"
},
"/Tools": {
"title": "Tools",
"viewPath": "Main-Views/ToolBox"
},
"/Windows/Statistics": {
"title": "",
"viewPath": ""
},
"/Windows/Status": {
"title": "",
"viewPath": ""
},
"/config": {
"title": "",
"viewPath": "CommissioningTool/PageConfig"
}
},
"sharedDocks": {
"bottom": [
{
"anchor": "fixed",
"autoBreakpoint": 480,
"content": "cover",
"handle": "show",
"iconUrl": "material/notifications_active",
"id": "Docked-South",
"modal": false,
"resizable": false,
"show": "onDemand",
"size": 165,
"viewParams": {},
"viewPath": "Navigation-Views/Docked-South"
}
],
"cornerPriority": "top-bottom",
"left": [
{
"anchor": "fixed",
"autoBreakpoint": 805,
"content": "auto",
"handle": "autoHide",
"iconUrl": "",
"id": "Docked-West",
"modal": false,
"resizable": false,
"show": "auto",
"size": 70,
"viewParams": {},
"viewPath": "Navigation-Views/Docked-West"
}
],
"right": [
{
"anchor": "fixed",
"autoBreakpoint": 480,
"content": "cover",
"handle": "hide",
"iconUrl": "",
"id": "Docked-East",
"modal": false,
"resizable": false,
"show": "onDemand",
"size": 400,
"viewParams": {},
"viewPath": "PopUp-Views/Controller-Equipment/Information-Docked-East"
}
],
"top": [
{
"anchor": "fixed",
"autoBreakpoint": 480,
"content": "auto",
"handle": "hide",
"iconUrl": "",
"id": "",
"modal": false,
"resizable": false,
"show": "visible",
"size": 50,
"viewParams": {},
"viewPath": "Framework/Breakpoint"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
{
"custom": {},
"params": {
"Error_message": "none"
},
"propConfig": {
"params.Error_message": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 242
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "200px"
},
"props": {
"color": "#FFFFFF",
"path": "material/error_outline",
"style": {
"backgroundColor": "#555555"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "250px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.Error_message"
},
"type": "property"
}
}
},
"props": {
"style": {
"backgroundColor": "#000000"
},
"textStyle": {
"color": "#FFFFFF",
"fontWeight": "bold",
"margin": 10,
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "200px"
},
"props": {
"direction": "column",
"style": {
"borderColor": "#FFFFFF",
"borderStyle": "solid",
"borderWidth": "1px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Error"
},
"props": {
"direction": "column",
"style": {
"classes": "Background-Styles/Controller"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,32 @@
def build_row(**kwargs):
"""
Args:
Any number of arguments using kwargs key = value format.
Key StyleClass is used for adding formatting to the row.
StyleClass = {classes:value}
Returns:
A python dict with style formatting for perspective tables..
Raises:
KeyError: Raises an exception.
"""
row = {}
column ={}
for key,value in kwargs.items():
if key != "StyleClass":
column[key]={"value":value}
row["value"]=column
style_class = kwargs.get("StyleClass")
row["style"] = style_class
return row
def build_row_with_view(**kwargs):
row = {}
column ={}
for key,value in kwargs.items():
if key != "StyleClass":
column[key]= value
row["value"]=column
style_class = kwargs.get("StyleClass")
row["style"] = style_class
return row

View File

@ -0,0 +1,99 @@
{
"custom": {},
"params": {
"styleClass": "",
"text": ""
},
"propConfig": {
"params.styleClass": {
"paramDirection": "input",
"persistent": true
},
"params.stylePath": {
"paramDirection": "input",
"persistent": true
},
"params.text": {
"binding": {
"config": {
"expression": "{view.params.text}"
},
"type": "expr"
},
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 40,
"width": 210
}
},
"root": {
"children": [
{
"meta": {
"name": "TextInput"
},
"position": {
"basis": "10px",
"grow": 1
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"expression": "{view.params.styleClass}"
},
"transforms": [
{
"fallback": "Input/Label/Valid_Entry",
"inputType": "scalar",
"mappings": [
{
"input": 0,
"output": "Input/Label/Invalid_Entry"
},
{
"input": 1,
"output": "Input/Label/Valid_Entry"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.text"
},
"type": "property"
}
}
},
"props": {
"placeholder": "Enter Value",
"resize": "both",
"style": {}
},
"type": "ia.input.text-area"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"justify": "center",
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,497 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"searchId": "value",
"state": 5
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "this.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_safety},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_safety},\r\n\t\t4, {session.custom.alarm_filter.show_safety},\r\n\t\t5, {session.custom.alarm_filter.show_safety},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)\r\n",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 10,
"width": 40
}
},
"root": {
"children": [
{
"meta": {
"name": "Light_Curtain",
"tooltip": {
"style": {
"fontSize": 16
}
}
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[0].fill.paint": {
"binding": {
"config": {
"expression": "\u0027#AAAAAA\u0027"
},
"transforms": [
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "expr"
}
},
"props.elements[1].stroke.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state1},\r\n3,{session.custom.colours.state1},\r\n4,{session.custom.colours.state1},\r\n{session.custom.colours.state5}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "m 32.5,0 h 8 v 8 h -8 z m -32,0 h 8 v 8 h -8 z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m 9,4 c 7.666668,0 15.333332,0 23,0",
"name": "path",
"stroke": {
"width": 3
},
"type": "path"
}
],
"style": {},
"viewBox": "-0.5 -0.5 42 9"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"path": "view.custom.display_icon"
},
"type": "property"
}
}
},
"props": {
"aspectRatio": "40:10",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,293 @@
import sys, os, datetime, hashlib, hmac
from StringIO import StringIO
import gzip
import urllib
import urllib2
import json
def get_filters_2(**kwargs):
filter_stack = []
canonical_querystring = ""
url_encoding = kwargs.get("url_encoding")
sources = kwargs.get("sources")
if sources:
source_string = "SourceId=" + ",".join(sources)
filter_stack.append(source_string)
devices = kwargs.get("devices")
if devices:
device_string = "Device=" + ",".join(devices)
filter_stack.append(device_string)
priorities = kwargs.get("priorities")
if priorities:
priority_string = "Priority=" + ",".join(str(item) for item in priorities)
filter_stack.append(priority_string)
types = kwargs.get("types")
if types:
type_string = ("Type=" + ",".join(str(item) for item in types))
filter_stack.append(type_string)
time_from = kwargs.get("start")
if time_from:
time_from_string = "StartTimestamp=" + str(time_from)
filter_stack.append(time_from_string)
time_to = kwargs.get("end")
if time_to:
time_to_string = "EndTimestamp=" + str(time_to)
filter_stack.append(time_to_string)
duration = kwargs.get("duration")
if duration:
duration_string = "MinimumDuration=" + str(duration)
filter_stack.append(duration_string)
if filter_stack:
if url_encoding:
canonical_querystring += "Filter="
for i, j in enumerate(filter_stack):
if i == len(filter_stack)-1 and url_encoding == True:
canonical_querystring += urllib.quote(j, "")
elif i == len(filter_stack)-1:
canonical_querystring += j
elif url_encoding == True:
canonical_querystring += urllib.quote(j + "&", "")
else:
canonical_querystring += (j + "&")
return canonical_querystring
def get_filters(**kwargs):
#Build filter string, filters are passed as key word arguments into the function
#Check if any of the filters have been passed means we need to add Filter=.
#Each filter is then converted using the urllib_parse.
canonical_querystring = ""
sources = kwargs.get("sources")
devices = kwargs.get("devices")
priorities = kwargs.get("priorities")
types = kwargs.get("types")
time_from = kwargs.get("start")
time_to = kwargs.get("end")
duration = kwargs.get("duration")
url_encoding = kwargs.get("url_encoding")
filter_list = [sources, devices, priorities, types, time_from, time_to, duration]
if any(filter_list):
canonical_querystring = "Filter="
if sources:
source_string = ("SourceId=" + ",".join(sources))
if url_encoding == True:
canonical_querystring += urllib.quote(source_string + "&","")
else:
canonical_querystring += source_string + "&"
if devices:
device_string = ("Device=" + ",".join(devices))
if url_encoding == True:
canonical_querystring += urllib.quote(device_string + "&","")
else:
canonical_querystring += device_string +"&"
if priorities:
priority_string = ("Priority=" + ",".join(str(item) for item in priorities))
if url_encoding == True:
canonical_querystring += urllib.quote(priority_string + "&", "")
else:
canonical_querystring += priority_string +"&"
if types:
type_string = ("Type=" + ",".join(str(item) for item in types))
if url_encoding == True:
canonical_querystring += urllib.quote(type_string + "&","")
else:
canonical_querystring += type_string +"&"
if time_from:
if url_encoding == True:
canonical_querystring += urllib.quote("StartTimestamp=" + str(time_from) + "&","")
else:
canonical_querystring += "StartTimestamp=" + str(time_from) +"&"
if time_to:
if url_encoding == True:
canonical_querystring += urllib.quote("EndTimestamp=" + str(time_to) + "&","")
else:
canonical_querystring += "EndTimestamp=" + str(time_to) +"&"
if duration:
if url_encoding == True:
canonical_querystring += urllib.quote("MinimumDuration=" + str(duration) + "&","")
else:
canonical_querystring += "MinimumDuration=" + str(duration) +"&"
system.perspective.print("filtered string = " + canonical_querystring )
canonical_querystring = canonical_querystring.rstrip("&")
return canonical_querystring
def get_response(response):
if response.info().get('Content-Encoding') == 'gzip':
buf = StringIO(response.read())
f = gzip.GzipFile(fileobj=buf)
data = f.read()
return (response.getcode(), data)
else:
buf = StringIO(response.read())
return(response.getcode(), buf.read())
def build_url(credentials, **kwargs):
# ************* REQUEST VALUES *************
method = 'GET'
service = 'lambda'
# This is a lookup in secrets to a return the function url for the lambda that needs called.
# This allows beta and prod to be dynamically retrived.
whid = kwargs.get("fc")
region = kwargs.get("region")
API_ID, STAGE, ACC_ID, FUNC_URL = AWS.secrets_manager.get_secret(str(whid), 'scada/api/endpoint')
api_id = FUNC_URL
host = "%s.%s-url.%s.on.aws" % (api_id, service, region)
endpoint = "https://%s" % (host)
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
# Read AWS access key from env. variables or configuration file. Best practice is NOT
# to embed credentials in code.
# access_key = os.environ.get('AWS_ACCESS_KEY_ID')
# access_key= 'ASIATVSVCYSV2JJJMDPP'
# secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
# secret_key= 'Hc0G/0eACBlgplGSBnfsB98Y6DPqwpvyb4nc1Rvs'
# session_token = os.environ["AWS_SESSION_TOKEN"]
# session_token= 'IQoJb3JpZ2luX2VjEJr//////////wEaCWV1LXdlc3QtMSJHMEUCIQCbrPQoj4OM0SXIo6QtcNAblnplgXfvSYIcA+k8xkXmZwIgN1Pi7Nyc66T8p0HkZSMmuW8pu1qPEVJii41YgYCuiBYqngIIo///////////ARAAGgwyNTI1MDc3Njc5NzkiDKGV69tLNcKNVcoeryryARkU2Lmnj0aa+ilLOrg35FIb81jvmj6bpPR3+5zJ3Wna+vOBgz6cqphyn28+Q8Ryw/lzM6gM0vWH+gV26CuQZtKd1U4ETo9eL9QuluLBqLnZYfT5q+F9hzJy3OQQl0c3VvwcaCjOPrMdbvWnJGEoEZTKe7Xm5v3ok3huJDgKLEIVlE6Z4c2kKNy/N/JfbxB5a33A2eaE9YaGj1V0cQgUFCCkn9uDq8W4TzOPZ3NgKAyj8RoBR6KAC8gEtWXFEwwZR3ZMwYIXryEepcU7HQSHpp66JAFm/X5+HNxRe7WUwTETAveYMNi5ssFzl3rneKh9+U37MPW58psGOp0B11BghSma0KZHgCfXqdsgfGyD7/sBEyYE9wdnzmi8fOpel5EDQoUoYilRSXod2E9wlaXj3h8S+dtBJjGVqsIbHEIrW7WKOEYELxoW4VSDw5hDjZaUuZ5fA3z59c4CEeAz3v5EA6NN6+ulEb7/4pbWF8s3fezNk9T73NpmKnjaMFukcBX8DofesZGJFpfGij2Sx4hQ3qlmG91uac8kMw=='
access_key = credentials["AccessKey"]
secret_key = credentials["SecretKey"]
session_token = credentials["SessionKey"]
if access_key is None or secret_key is None:
system.perspective.print('No access key is available.')
sys.exit()
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ') # Format date as YYYYMMDD'T'HHMMSS'Z'
datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
system.perspective.print("creating header")
system.perspective.print("datestamp = " + str(datestamp) + " region = " + str(region) + "service = " + str(service))
# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
# Because almost all information is being passed in the query string,
# the order of these steps is slightly different than examples that
# use an authorization header.
# Step 1: Define the verb (GET, POST, etc.)--already done.
# Step 2: Create canonical URI--the part of the URI from domain to query
# string (use '/' if no path)
fc = kwargs.get("fc")
canonical_uri = "/history/%s" % (fc)
# Step 3: Create the canonical headers and signed headers. Header names
# must be trimmed and lowercase, and sorted in code point order from
# low to high. Note trailing \n in canonical_headers.
# signed_headers is the list of headers that are being included
# as part of the signing process. For requests that use query strings,
# only "host" is included in the signed headers.
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
# Step 4: Create the canonical query string. In this example, request
# parameters are in the query string. Query string values must
# be URL-encoded (space=%20). The parameters must be sorted by name.
#canonical_querystring = 'Action=CreateUser&UserName=NewUser&Version=2010-05-08'
#canonical_querystring = 'NextToken=' + urllib.parse.quote("1669217267.5230844/PLC09/T00049",'') + '&PageSize=50'
#canonical_querystring = 'PageSize=50&PreviousToken=' + urllib.parse.quote('1669217267.5824845/PLC09/T00099','')
canonical_querystring = ""
#Build filter string, filters are passed as key word arguments int the function
#Check if any of the filters have been passed means we need to add Filter=.
#Each filter is then converted using the urllib_parse.
#Including client id for timestream api.
client_id = kwargs.get("client_id")
if client_id:
canonical_querystring += 'ClientId=' + client_id + '&'
PAGE_SIZE = "200"
filters= kwargs.get("filters","")
if filters != "":
canonical_querystring += filters + "&"
next_token = kwargs.get("next_token")
previous_token = kwargs.get("previous_token")
if next_token != None:
canonical_querystring += 'NextToken=' + urllib.quote(next_token,'') + '&'
system.perspective.print("created string " + canonical_querystring)
if previous_token != None:
canonical_querystring += 'PreviousToken=' + urllib.quote(previous_token,'') + '&'
else:
canonical_querystring += 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + urllib.quote_plus(access_key + '/' + credential_scope)
canonical_querystring += '&X-Amz-Date=' + amz_date
#canonical_querystring += '&X-Amz-Expires=30'
canonical_querystring += "&X-Amz-Security-Token=" + urllib.quote_plus(session_token)
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
# Step 5: Create payload hash. For GET requests, the payload is an
# empty string ("").
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
# Step 6: Combine elements to create canonical request
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
# ************* TASK 2: CREATE THE STRING TO SIGN*************
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# ************* TASK 3: CALCULATE THE SIGNATURE *************
# Create the signing key
signing_key = getSignatureKey(secret_key, datestamp, region, service)
# Sign the string_to_sign using the signing_key
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# The auth information can be either in a query string
# value or in a header named Authorization. This code shows how to put
# everything into a query string.
canonical_querystring += '&X-Amz-Signature=' + signature
# ************* SEND THE REQUEST *************
# The 'host' header is added automatically by the Python 'request' lib. But it
# must exist as a header in the request.
request_url = endpoint + canonical_uri + "?" + canonical_querystring
system.perspective.print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
system.perspective.print('Request URL = ' + request_url)
# r = requests.get(request_url)
request = urllib2.Request(request_url)
request.add_header('Accept-encoding', 'gzip')
try:
response = urllib2.urlopen(request)
except urllib2.HTTPError as e:
return(e.code, None)
except urllib2.URLError as e:
return(e.reason, None)
return get_response(response)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
import logging
LOGGING_MAP_IDE = {
'critical': {'level': logging.CRITICAL, 'value': 50},
'error': {'level': logging.ERROR, 'value': 40},
'warning': {'level': logging.WARNING, 'value': 30},
'info': {'level': logging.INFO, 'value': 20},
'debug': {'level': logging.DEBUG, 'value': 10},
'trace': {'level': 5, 'value': 5},
'notset': {'level': logging.NOTSET, 'value': 0}
}
LOG_LEVELS = ['trace', 'debug', 'info', 'warn', 'error'] ## these are the valid logging levels for use with Ignition system.util.setLoggingLevel() function
def getLoggerIDE(name='', level='info'):
## insure basic logging is set-up
logging.basicConfig()
## Grab a logger object for the given name
logger = logging.getLogger(name)
if level and level in LOGGING_MAP_IDE:
level = LOGGING_MAP_IDE[level]['level']
logger.setLevel(level)
## Check if any handler exists for this logger, if not, create a basic handler config.
## TODO: Add a functionality to customize handlers, particularly for writing to Ignition gateway console or system.perspective.print() etc
# if not len(logger.handlers): logging.basicConfig()
return(logger)
def getLogger(name='', level=None):
## Grab a logger object for the given name from the Ignition system.util function
logger = None
if name not in ['', None]: logger = system.util.getLogger(name)
## if logger created, level arg passed in and valid, set the logging level accordingly
if logger and level and level in LOG_LEVELS: system.util.setLoggingLevel(name, level)
return(logger)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
def send_request(whid,actionCode,parameters):
"""
Creates the request to send to the web socket from a button in SCADA.
Args:
whid = identifier of the warehouse ie MAN2
actionCode : possible actionCode as per MAP data model (int values):
0 -> Not used
1 -> Start
2 -> Stop
3 -> Reset
4 -> Get
5 -> Set
6 -> Enable
7 -> Disable
parameters = dictionary with the parameters of the command
{"commandTarget":id,
"commandCode":action,
"commandTimestamp":time_stamp,
"commandParams":""}
Returns:
a messsage that inform the user about there status of the request
"""
import sys
try:
loggerName=whid+ "_SCADA"
logger = system.util.getLogger(loggerName)
tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
messages_to_send = {}
message_payload = {}
message_list = []
returnMessage=""
time_stamp = system.date.toMillis(system.date.now())
payloadParams={}
if not parameters["commandTarget"] or parameters["commandTarget"] == "":
returnMessage = "Missing commandTarget parameter. Command can\'t be executed"
logger.trace(returnMessage)
return returnMessage
payloadParams["commandTarget"]=parameters["commandTarget"]
if not parameters["commandCode"] or parameters["commandCode"] == "":
returnMessage = "Missing commandCode parameter. Command can\'t be executed"
logger.trace(returnMessage)
return returnMessage
payloadParams["commandCode"]=parameters["commandCode"]
payloadParams["commandTimeout"]=2000
payloadParams["commandTimestamp"]=time_stamp
payloadParams["commandParams"]=parameters["commandParams"]
message_payload["parameters"] = payloadParams
message_payload["action"] = "command"
message_payload["siteId"] = whid
message_list.append(message_payload)
messages_to_send["message_list"] = message_list
system.tag.writeBlocking([tag_provider + "System/wbsckt_messages_send"], [system.util.jsonEncode(messages_to_send)])
return "Message sent correctly"
except:
exc_type, exc_obj, tb = sys.exc_info()
lineno = tb.tb_lineno
exceptionMessage=str(lineno)+" -> "+str(exc_type)+" -> "+str(exc_obj)
errorMessage = "Error while sending a command : "+exceptionMessage
logger.fatal(errorMessage)
return errorMessage
def send_request_old_to_be_removed(whid, id, action):
"""
Creates the request to send to the web socket from a button in SCADA.
Args:
id =Unique material handling equipment id.
request = Type of request i.e Start, Stop, Reset.
Returns:
N/A
"""
"""{"action": "command", "parameters": {"": "Reset", "siteId": "DNG2"}}"""
messages_to_send = {}
message_payload = {}
message_list = []
time_stamp = system.date.toMillis(system.date.now())
parameters = {"commandTarget":id, "commandCode":action, "commandTimestamp":time_stamp,
"commandToken":"", "commandTimeout":2000, "commandParams":""}
message_payload["parameters"] = parameters
message_payload["action"] = "command"
message_payload["siteId"] = whid
message_list.append(message_payload)
messages_to_send["message_list"] = message_list
tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
system.tag.writeBlocking([tag_provider + "System/wbsckt_messages_send"],
[system.util.jsonEncode(messages_to_send)])
def send_download_request(whid, filters, session_id):
"""
Creates the request to download alarm history
to the web socket from a button in SCADA.
Args:
whid = four character whid for the project
filters = filter string for passing with the download request.
These a re similar to the url parameters but do not need encoding.
session_id = unique session id of the perspective session.
Returns:
N/A
Example:
{"action":"download", "parameters":{"siteId":"FED1", "sessionId":"bob2",
"filter": "MinimumDuration=360000&Type=1"}}
"""
messages_to_send = {}
message_payload = {}
message_list = []
time_stamp = system.date.toMillis(system.date.now())
parameters = {"siteId":whid, "sessionId": session_id, "filter": filters}
message_payload["parameters"] = parameters
message_payload["action"] = "download"
# message_payload["siteId"] = whid
message_list.append(message_payload)
messages_to_send["message_list"] = message_list
tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
system.tag.writeBlocking([tag_provider + "System/wbsckt_messages_send"],
[system.util.jsonEncode(messages_to_send)])

View File

@ -0,0 +1,64 @@
def main_alarm_table():
"""
Returns alarms states to filter
the main alarm table
Args:
None
Returns:
Returns a list of filters.
Raises:
None
"""
return["Active", "Not Active"]
def shelved_alarm_table():
"""
Returns alarms states to filter
the shelved alarm table
Args:
None
Returns:
Returns a list of filters.
Raises:
None
"""
return["Shelved"]
def docked_alarm_table():
"""
Returns alarms states to filter
the docked alarm table
Args:
None
Returns:
Returns a list of filters.
Raises:
None
"""
return["Active", "Not Active", "Shelved"]
def information_alarm_table():
"""
Returns alarms states to filter
the information pop up
alarm table.
Args:
None
Returns:
Returns a list of filters.
Raises:
None
"""
return["Active", "Not Active", "Shelved"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1,155 @@
{
"custom": {},
"params": {
"Name": "",
"Path": "",
"forceFault": null,
"forceRunning": null
},
"propConfig": {
"params.Name": {
"binding": {
"config": {
"path": "view.params.Path"
},
"transforms": [
{
"code": "\tstring \u003d value \n\tparts \u003d string.split(\"/\")\n\td \u003d parts[-1]\n\treturn d\n\treturn value",
"type": "script"
}
],
"type": "property"
},
"paramDirection": "inout",
"persistent": true
},
"params.Path": {
"paramDirection": "inout",
"persistent": true
},
"params.forceFault": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunning": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 131,
"width": 120
}
},
"root": {
"children": [
{
"meta": {
"name": "EmbeddedView",
"tooltip": {}
},
"position": {
"basis": "100px",
"grow": 1
},
"propConfig": {
"meta.tooltip.text": {
"binding": {
"config": {
"path": "view.params.Path"
},
"type": "property"
}
},
"props.params.forceFaultStatus": {
"binding": {
"config": {
"path": "view.params.forceFault"
},
"type": "property"
}
},
"props.params.forceRunningStatus": {
"binding": {
"config": {
"path": "view.params.forceRunning"
},
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.Path"
},
"type": "property"
}
}
},
"props": {
"key": "value",
"style": {
"height": "80px",
"pointerEvents": "none",
"width": "80px"
}
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "1px",
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.Name"
},
"type": "property"
}
}
},
"props": {
"alignVertical": "top",
"textStyle": {
"fontSize": 8,
"overflowWrap": "break-word",
"textAlign": "center",
"textOverflow": "ellipsis"
}
},
"type": "ia.display.label"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\t# Send message for and print on system the selected path. \n\tparams \u003d {\u0027UserClickPath\u0027: self.view.params.Path, \u0027UserClickSymbolName\u0027 : self.view.params.Name}\n\tsystem.perspective.sendMessage(\"UserClickInfo\", payload \u003d params, scope \u003d \"page\")\n\tsystem.perspective.print(params)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"alignItems": "center",
"direction": "column",
"justify": "center",
"style": {
"classes": "Background-Styles/Grey-Background",
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,228 @@
{
"custom": {},
"params": {},
"props": {
"defaultSize": {
"height": 1080,
"width": 1920
}
},
"root": {
"children": [
{
"custom": {
"Devices": [
"PLC01",
"PLC02",
"PLC03",
"PLC06",
"PLC07",
"PLC08",
"PLC09",
"PLC13",
"PLC14",
"PLC15",
"PLC16",
"PLC20",
"PLC21",
"PLC22",
"PLC23",
"PLC25",
"PLC26",
"PLC27",
"PLC28",
"PLC29",
"PLC30",
"PLC31",
"PLC32",
"PLC40",
"PLC41",
"PLC42",
"PLC43",
"PLC47",
"PLC48",
"PLC49",
"PLC51",
"PLC52",
"PLC60",
"PLC64",
"PLC65",
"PLC66",
"PLC69",
"PLC70",
"PLC71",
"PLC80",
"PLC96",
"PLC97",
"PLC99",
"ARSAW1301",
"ARSAW1302",
"ARSAW1303",
"ARSAW1304",
"ARSAW1305",
"ARSAW1306",
"ARSAW1307",
"ARSAW1401",
"ARSAW1402",
"ARSAW1403",
"ARSAW1404",
"ARSAW1405",
"ARSAW1406",
"ARSAW1407",
"ARSAW1501",
"ARSAW1502",
"ARSAW1503",
"ARSAW1504",
"ARSAW1505",
"ARSAW1506",
"ARSAW1507",
"ARSAW1601",
"ARSAW1602",
"ARSAW1603",
"ARSAW1604",
"ARSAW1605",
"ARSAW1606",
"ARSAW1607",
"FSC10",
"SLAM301",
"SLAM302",
"SLAM303",
"SLAM304",
"SLAM305",
"SLAM306",
"SLAM307",
"SLAM402",
"SLAM401",
"RWC4"
]
},
"meta": {
"name": "FlexRepeater"
},
"position": {
"basis": "1080px"
},
"props": {
"alignContent": "flex-start",
"alignItems": "flex-start",
"elementPosition": {
"grow": 0,
"shrink": 0
},
"instances": [
{
"instancePosition": {},
"instanceStyle": {
"classes": "",
"margin": "5px"
},
"tagProps": [
"PLC01",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
{
"instancePosition": {},
"instanceStyle": {
"classes": "",
"margin": "5px"
},
"tagProps": [
"PLC02",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
{
"instancePosition": {},
"instanceStyle": {
"classes": "",
"margin": "5px"
},
"tagProps": [
"PLC03",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
{
"instancePosition": {},
"instanceStyle": {
"classes": "",
"margin": "5px"
},
"tagProps": [
"PLC09",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
}
],
"path": "Symbol-Views/Controller-Views/CommandControl",
"style": {
"overflow": "visible"
},
"wrap": "wrap"
},
"type": "ia.display.flex-repeater"
}
],
"custom": {
"Devices": [
"PLC01",
"PLC02",
"PLC03",
"PLC09"
],
"count": "value",
"delay": 4000
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tfc \u003d system.tag.readBlocking([\"Configuration/FC\"])\n\ttag_provider \u003d \"[%s_SCADA_TAG_PROVIDER]\" % (fc[0].value)\n\ttags_to_read \u003d system.tag.readBlocking([tag_provider+\"Configuration/DetailedViews\"])\n\tdevices \u003d system.util.jsonDecode(tags_to_read[0].value)\n\tif devices:\n\t\tinstances \u003d []\n\t\tdashboard_devices \u003d []\n\t\tfor k,v in devices.items():\n\t\t\tdevice_list \u003d v\n\t\t\tfor i in device_list:\n\t\t\t\tdashboard_devices.append(i)\n\t\t\t\tinstances.append({\n\t\t\t\t \"instanceStyle\": {\n\t\t\t\t \"classes\": \"\",\n\t\t\t\t \"margin\": \"5px\"\n\t\t\t\t },\n\t\t\t\t \"instancePosition\": {},\n\t\t\t\t \"tagProps\": [\n\t\t\t\t i,\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\",\n\t\t\t\t \"value\"\n\t\t\t\t ]\n\t\t\t\t })\n\t\tsystem.perspective.print(instances)\n\t\tself.custom.Devices \u003d dashboard_devices\n\t\tself.getChild(\"FlexRepeater\").props.instances \u003d instances"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,237 @@
{
"custom": {
"box_shadow": "0px 2px 4px rgba(0, 0, 40, 0.15)",
"expanded": true
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tself.custom.expanded \u003d self.params.open_expanded\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"open_expanded": true,
"params": {},
"path": "Objects/Templates/EAM/Cards/Editable/Work Order Scheduling",
"show_box_shadow_on_expanded": true,
"title": "Card Title",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"propConfig": {
"custom.box_shadow": {
"binding": {
"config": {
"expression": "if(\r\n\t{view.params.show_box_shadow_on_expanded}\u0026\u0026{view.custom.expanded},\r\n\t\u00270px 2px 4px rgba(0, 0, 40, 0.15)\u0027,\r\n\t\u0027\u0027\r\n)"
},
"type": "expr"
},
"persistent": true
},
"custom.expanded": {
"persistent": true
},
"params.address": {
"paramDirection": "input",
"persistent": true
},
"params.open_expanded": {
"paramDirection": "input",
"persistent": true
},
"params.params": {
"paramDirection": "input",
"persistent": true
},
"params.path": {
"paramDirection": "input",
"persistent": true
},
"params.show_box_shadow_on_expanded": {
"paramDirection": "input",
"persistent": true
},
"params.system": {
"paramDirection": "input",
"persistent": true
},
"params.title": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultHeight": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultWidth": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 339,
"width": 369
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.title"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Title_transparent"
}
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.view.custom.expanded \u003d not self.view.custom.expanded"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button"
},
"propConfig": {
"props.image.icon.path": {
"binding": {
"config": {
"expression": "if({view.custom.expanded}, \u0027material/expand_less\u0027, \u0027material/expand_more\u0027)"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal"
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "24px",
"shrink": 0
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.expanded"
},
"type": "property"
}
},
"props.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"overlayOptOut": true,
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"overlayOptOut": true,
"type": "property"
}
},
"props.useDefaultViewHeight": {
"binding": {
"config": {
"path": "view.params.useDefaultHeight"
},
"type": "property"
}
},
"props.useDefaultViewWidth": {
"binding": {
"config": {
"path": "view.params.useDefaultWidth"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Embedded_transparent"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"propConfig": {
"props.style.boxShadow": {
"binding": {
"config": {
"path": "view.custom.box_shadow"
},
"type": "property"
}
}
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/Card/Card_transparent"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,53 @@
def create_latency_tags(whid):
logger = system.util.getLogger("%s-Create-Latency-Tags" % (whid))
if whid != "" and whid != None:
provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
tag_paths = {"avg_latency":{"name":"avg_latency", "valueSource": "memory",
"dataType": "String", "value" : ""},
"aws_data_copy":{"name":"aws_data_copy", "valueSource": "reference",
"dataType": "String", "sourceTagPath": "[~]System/aws_data.value"},
"first_pass":{"name":"first_pass", "valueSource": "memory",
"dataType": "Boolean", "value" : True},
"last_alarm_change_ts":{"name":"last_alarm_change_ts", "valueSource": "memory",
"dataType": "DateTime", "formatString": "yyyy-MM-dd h:mm:ss aa"},
"prev_key":{"name":"prev_key", "valueSource": "memory",
"dataType": "String", "value" : ""},
"rolling_latency":{"name":"rolling_latency", "valueSource": "memory",
"dataType": "StringArray", "alarmEvalEnabled": True,
"value": [
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0" ],}}
for k,v in tag_paths.items():
if not system.tag.exists("%sLatency/%s" % (provider, k)):
base_path = "%s/Latency" % (provider)
system.tag.configure(base_path, v)
logger.info("Created tag %s" % (k))

View File

@ -0,0 +1,578 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "Robot"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "m 25,50.5 a 25,25 0 0 1 -25,-25 25,25 0 0 1 25,-25 25,25 0 0 1 25,25 25,25 0 0 1 -25,25 z",
"fill": {},
"name": "Circle",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m 44.389999,19.040001 h 1.34 v 5.36 h -1.34 z M 36.349998,27.08 h 5.360001 v 1.34 h -5.360001 z m 4.689681,-7.370001 A 4.0196781,4.0196781 0 0 1 37.02,23.729677 4.0196781,4.0196781 0 0 1 33.000322,19.709999 4.0196781,4.0196781 0 0 1 37.02,15.690321 4.0196781,4.0196781 0 0 1 41.039679,19.709999 Z M 31.989677,12.52 A 4.0196781,4.0196781 0 0 1 27.969999,16.539679 4.0196781,4.0196781 0 0 1 23.950321,12.52 4.0196781,4.0196781 0 0 1 27.969999,8.5003223 4.0196781,4.0196781 0 0 1 31.989677,12.52 Z m 6.46398,5.472982 -3.445342,4.105998 -9.881972,-8.29196 3.445341,-4.1059977 z m -2.103659,1.717017 h 1.340001 v 8.04 H 36.349998 Z M 37.02,19.040001 h 8.04 v 1.34 H 37.02 Z M 20.329678,26.41 A 4.0196781,4.0196781 0 0 1 16.309999,30.429678 4.0196781,4.0196781 0 0 1 12.290321,26.41 4.0196781,4.0196781 0 0 1 16.309999,22.390322 4.0196781,4.0196781 0 0 1 20.329678,26.41 Z m 5.409585,-15.990011 4.105999,3.445342 -11.004525,13.114681 -4.105998,-3.445341 z M 13.63,26.41 h 5.36 V 37.139999 H 13.63 Z M 8.2799997,37.139999 H 24.36 V 42.5 H 8.2799997 Z",
"fill": {
"paint": "#000000"
},
"name": "Robot",
"type": "path"
}
],
"style": {},
"viewBox": "-0.5 -0.5 51 52"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,68 @@
{
"custom": {},
"params": {
"stylePath": "value",
"text": "value"
},
"propConfig": {
"params.stylePath": {
"paramDirection": "input",
"persistent": true
},
"params.text": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 30,
"width": 210
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "209px"
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"expression": "{view.params.stylePath}"
},
"type": "expr"
}
},
"props.text": {
"binding": {
"config": {
"expression": "{view.params.text}"
},
"type": "expr"
}
}
},
"props": {
"style": {}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"alignItems": "center",
"justify": "center",
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,302 @@
from datetime import datetime
import Queue
import copy
"""Global variables required so we can use different event timer scripts to perform
the writing of tag values seperateley from the reading of messages on the web socket.
State tags messages are queued into the global_queue, where they are read on a different
thread by the Update class and writen to tags. All alarms are written to global_alarms.
The alarms are then read by the Visualisation.status class where they are transformed into
an alarm state and written to tags. """
global_alarms = {}
global_states = set([])
global_queue = Queue.Queue(maxsize=100000)
global_first_connect = False
class A2C_MessageHandler():
"""
Handles the incoming A2C messages. Stores values in memory as dictionaries
and then writes them to tags.
Instance Attributes:
self.alarms: Holds the current active alarm data(dict).
self.state: Holds the current active state data(dict).
self.update_state: Flag, set when state data is available to write(bool)
self.update_alarms: Flag, set when alarm data is available to write(bool)
self.whid: Warehouse id for the site(str)
self.tag_provider: Tag provider to write tag values to(str)
self.A2C_MESSAGE_TYPES: Holds a reference to the methods called
for different message types(dict)
Returns:
NA.
Raises:
KeyError: NA.
"""
def __init__(self, whid):
global global_alarms
global global_first_connect
global_first_connect = False
global_alarms = {}
self.whid = whid
self.tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (self.whid)
self.logger = system.util.getLogger("%s-Web-Socket-Message-Handler" % (self.whid))
tag_to_read = "%sSystem/wbsckt_logging" % (self.tag_provider)
self.check_logger_active = system.tag.readBlocking([tag_to_read])[0].value
self.A2C_MESSAGE_TYPES = {
"SCADAMetricsInterface.StateChange": self.handle_state_message,
# "SCADAMetricsInterface.Event": self.handle_alarm_message,
"CloudMetricsInterface.Event": self.handle_alarm_message,
"ScadaCloud.Download": self.handle_download_message,
"ScadaCloud.Connection": self.handle_cloud_connection}
def message_logger(self, message):
if self.check_logger_active:
self.logger.info(message)
def message_lookup(self, message_type, message):
try:
self.A2C_MESSAGE_TYPES[message_type](message)
except KeyError as e:
self.message_logger("Message type not found:"
+ str(message))
def handle_message(self, message):
heartbeat_message = message.get("action")
message_type = message.get("payload", {}).get("payloadType")
format = message.get("payload", {}).get("format")
if message_type == "ScadaCloud.Batch":
messages = message.get("payload", {}).get("messages",[])
for i in messages:
message_type = i.get("payload", {}).get("payloadType")
self.message_lookup(message_type, i)
elif message_type !="ScadaCloud.Batch" and not heartbeat_message:
self.message_lookup(message_type, message)
else:
self.message_logger("Heartbeat:" + str(message))
tag_to_write = "%sSystem/wbsckt_heartbeat_interval" % (self.tag_provider)
current_time = system.date.now()
system.tag.writeAsync([tag_to_write], [current_time])
def handle_alarm_message(self, message):
global global_alarms
header = message.get("header",{})
payload = message.get("payload",{})
source = header.get("sourceId")
alarm_message = payload.get("message")
alarm_type = payload.get("type")
timestamp = payload.get("timestamp")
priority = payload.get("priority")
alarm_id = payload.get("id")
shelve_expiry = payload.get("shelveExpiryEpoch",0)
state = payload.get("state")
if (isinstance(source, unicode) and isinstance(alarm_message, unicode)
and isinstance(alarm_type, int)and isinstance(timestamp, long)
and isinstance(priority, int) and isinstance(shelve_expiry, int)
and isinstance(state, int)) and isinstance(alarm_id, int):
scada_alarm_message = {"sourceId": source,
"message": alarm_message,
"type": alarm_type,
"timestamp": timestamp,
"priority": priority,
"id": alarm_id,
"shelveExpiryEpoch": shelve_expiry,
"state": state}
alarm_id = "%s/alarm/%s" % (source, alarm_id)
if state == 0:
removed_value = global_alarms.pop(alarm_id, "No key found")
self.message_logger("Value removed from aws_data: "
+ str(removed_value) + ":" + str(alarm_id))
else:
global_alarms[alarm_id] = scada_alarm_message
self.message_logger("Value added to aws_data: "
+ str(scada_alarm_message))
else:
self.message_logger("Incorrect type value in message fields: "
+ str(message))
def handle_state_message(self, message):
global global_queue
header = message.get("header",{})
payload = message.get("payload",{})
source_id = header.get("sourceId")
state = payload.get("currentMachineState")
time_stamp = payload.get("timestamp")
if isinstance(source_id, unicode) and isinstance(state, int):
scada_state_message = {"timestamp": time_stamp,
"state":state}
global_queue.put([source_id, state])
self.message_logger("State message written to queue: "
+ str({source_id:scada_state_message}))
else:
self.message_logger("Incorrect type value in message fields: "
+ str(message))
def handle_download_message(self, message):
url = message.get("payload", {}).get("downloadUrl", None)
session_id = message.get("payload", {}).get("sessionId", None)
download = {}
payload = {"session_id":session_id, "url": url}
download["data"] = [payload]
tag_to_write = "%sSystem/download" % (self.tag_provider)
json_payload = system.util.jsonEncode(download)
system.tag.writeAsync([tag_to_write], [json_payload])
self.message_logger("Download message received: "
+ str(message))
def handle_cloud_connection(self, message):
global global_alarms
UNKNOWN = 3
ACTIVE = 1
header = message.get("header",{})
payload = message.get("payload",{})
component_type = payload.get("componentType")
timestamp = header.get("timestamp", 0)
event_type = payload.get("eventType")
component_id = payload.get("componentId")
scada_alarm_message = create_disconnect_message(component_id, timestamp, 1)
if event_type == "DISCONNECT":
self.message_logger(str(scada_alarm_message))
# #Call disconnect routine with a value 3 which is an unknown state.
self.alarms_disconnect(component_id, UNKNOWN, scada_alarm_message)
if event_type == "CONNECT":
#Call disconnect routine with a value 1 which is an active state.
self.alarms_disconnect(component_id, ACTIVE, scada_alarm_message)
if event_type == "SYNC" and component_type == "PLC":
alarm_id = "%s/alarm/%s" % (component_id, message)
for k,v in global_alarms.items():
if k.startswith(component_id):
global_alarms.pop(alarm_id, "No key found")
def alarms_disconnect(self, component_id, value, message):
global global_alarms
#Set alarms in the global_alarms to an unknown state.
#If component id == "DATABRIDGE" set all alarms to unknown
SITE_DISCONNECTS = ["DATABRIDGE", self.whid]
if component_id in SITE_DISCONNECTS:
site_disconnect = True
source_id = ""
else:
source_id = component_id
site_disconnect = False
for k,v in global_alarms.items():
device_name = k.split("/")[0]
if k.startswith(source_id) and device_name not in SITE_DISCONNECTS:
global_alarms[k]["state"] = value
alarm_id = "%s/alarm/%s" % (component_id, "Device disconnected")
#Set the alarms to true for device disconnects
if site_disconnect:
data_bridge_disconnect(self.whid, value, message, component_id)
else:
tag_path = "%s%s/DCN" % (self.tag_provider, source_id)
if value == 3:
create_disconnect_tags(self.whid, source_id)
global_alarms[alarm_id] = message
system.tag.writeBlocking([tag_path], [1])
else:
global_alarms.pop(alarm_id, "No key found")
system.tag.writeBlocking([tag_path], [0])
def create_disconnect_message(component_id, timestamp, state):
alarm_message = {"sourceId": component_id,
"message": "Device disconnected",
"type": 0,
"timestamp":timestamp,
"priority": 4,
"shelveExpiryEpoch": 0,
"state": state}
return alarm_message
def data_bridge_disconnect(whid, value, message, component_id):
global global_alarms
device_list = get_device_list(whid)
time_stamp = message.get("timestamp")
tags_to_write = []
values_to_write = []
if value == 3:
disconnect = True
else:
disconnect = False
for i in device_list:
create_disconnect_tags(whid, i)
alarm_id = "%s/alarm/%s" % (i, "Device disconnected")
tag_path = "[%s_SCADA_TAG_PROVIDER]%s/DCN" % (whid, i)
device_message = create_disconnect_message(i, time_stamp, 3)
tags_to_write.append(tag_path)
if disconnect:
global_alarms[alarm_id] = device_message
values_to_write.append(1)
else:
global_alarms.pop(alarm_id, "No key found")
values_to_write.append(0)
alarm_id = "%s/alarm/%s" % (component_id, "Device disconnected")
if disconnect:
global_alarms[alarm_id] = message
else:
global_alarms.pop(alarm_id, "No key found")
system.tag.writeAsync(tags_to_write, values_to_write)
def get_device_list(whid):
provider = "[%s_SCADA_TAG_PROVIDER]" % (whid)
tag_path = "%sConfiguration/DetailedViews" % (provider)
tags_to_read = system.tag.readBlocking([tag_path])
devices = system.util.jsonDecode(tags_to_read[0].value)
device_list = []
for k,v in devices.items():
for i in v:
device_list.append(i)
return device_list
def create_disconnect_tags(whid, component_id):
logger_name = "%s-Create-Disconnect-Tags" % (whid)
logger = system.util.getLogger(logger_name)
base = "[%s_SCADA_TAG_PROVIDER]%s" % (whid, component_id)
if not system.tag.exists(base + "/DCN"):
tag = {"name": "DCN",
"valueSource": "memory",
"dataType": "Boolean",
"value": True}
create_tag = system.tag.configure(base, tag)
if not create_tag[0].isGood():
logger.warn("Failed to create tag: " + str(source_id))
class Update():
def __init__(self):
tags_to_read = system.tag.readBlocking(["Configuration/FC"])
self.fc = tags_to_read[0].value
self.tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (self.fc)
self.tags_to_write = []
self.values_to_write = []
self.logger = system.util.getLogger("%s-Global variable reader"
% (self.fc))
def read_messages_from_queue(self):
size = global_queue.qsize()
self.logger.info("Queue size: " + str(size))
for i in range(0, size):
message = global_queue.get()
source_id ="%s%s/STATE" % (self.tag_provider, message[0])
create_tags_in_place(source_id, message[1], self.logger)
self.tags_to_write.append(source_id)
self.values_to_write.append(message[1])
def write_tags(self):
alarm_path = "%sSystem/aws_data" % ( self.tag_provider)
alarm_data = system.util.jsonEncode(global_alarms)
self.tags_to_write.append(alarm_path)
self.values_to_write.append(alarm_data)
system.tag.writeBlocking(self.tags_to_write, self.values_to_write)
self.logger.info("State messages written: " + str(len(self.values_to_write)))
def create_tags_in_place(source_id, value, logger):
base = source_id.replace("/STATE", "")
if not system.tag.exists(source_id):
tag = {"name": "STATE",
"valueSource": "memory",
"dataType": "Int1",
"value": value}
create_tag = system.tag.configure(base, tag)
if not create_tag[0].isGood():
logger.warn("Failed to create tag: " + str(source_id))

View File

@ -0,0 +1,32 @@
def get_alarm_state(state):
"""
This function returns a string representing the current alarm state from
a state argument enum 1 to 7.
Args:
state: Enum for current alarm state.
Returns:
String representing current alarm state.
Raises:
KeyError: None.
"""
if state == 0:
return "Not Active"
elif state == 1:
return "Active"
elif state == 2:
return "Shelved"
# elif state == 4:
# return "Return to unacknowledged"
# elif state == 5:
# return "Shelved state"
# elif state == 6:
# return "Suppressed-by-design"
# elif state == 7:
# return "Out-of-service state"
else:
return "Unknown"

View File

@ -0,0 +1,83 @@
from urllib2_aws4auth import aws_urlopen, Request
from urllib2 import HTTPError
from urllib import urlencode
import json
import boto3
from pprint import pformat
REGION = 'us-east-2'
SERVICE = 'execute-api'
ENDPOINT = 'https://l7o38q47a6.execute-api.us-east-2.amazonaws.com/default/ScadaProductMetrics'
LOGGER = system.util.getLogger('activityLog')
def openSession():
CREDS = boto3.Session().get_credentials()
AWS_ACCESS_KEY_ID = CREDS.access_key
AWS_SECRET_ACCESS_KEY = CREDS.secret_key
TOKEN = CREDS.token
OPENER = aws_urlopen(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
REGION,
SERVICE,
session_token=TOKEN,
verify=False)
return OPENER
def createActivityDetails(session, resource_type, resource, current_page, start_time, end_time = None):
user = session.props.auth.user.userName
session_id = session.props.id
site = session.custom.fc
start_time = system.date.format(start_time, 'yyyy-MM-dd HH:mm:ss')
end_time = system.date.format(end_time, 'yyyy-MM-dd HH:mm:ss') if end_time != None else end_time
user_UTCoffset = session.props.device.timezone.utcOffset
activityDetails = {'username':user,
'session_id':session_id,
'site': site,
'start_time': start_time,
'end_time':end_time,
'user_UTCoffset': user_UTCoffset,
'resource_type': resource_type,
'resource': resource,
'current_page': current_page}
return activityDetails
def logActivity(session, resource_type, resource, current_page, start_time, end_time = None):
activityDetails = createActivityDetails(session, resource_type, resource, current_page, start_time, end_time)
user = session.props.auth.user.userName
opener = openSession()
params = activityDetails
payload = json.dumps(params)
method = 'POST'
# in the headers the Ignition session username (session.props.auth.user.userName) must be supplied as 'X-Ignition-User'
headers = {
'Content-type': 'application/json',
'X-Ignition-User': user
}
req = Request(url=ENDPOINT, method=method, data=payload, headers=headers)
# open the request and process the read
try:
resp = opener(req)
response = json.loads(resp.read())
error = None
print pformat(response)
except HTTPError, e:
error = str(e)
response = None
print error
LOGGER.info(error)
return {'error': error, 'response':response }
def callLogger(self, resource_type, resource = None, current_page= None):
""" self is reference to the view. So if calling from shutdown script on the view, pass self.
If calling from a component, pass self.view"""
if self.session.custom.enable_activity_logging:
if self.session.props.device.type != 'designer':
end_time = system.date.now() if resource_type == 'page' else None
start_time = self.custom.activityLogger.start_time
pageid = self.custom.activityLogger.pageid
resource = pageid if resource == None else resource
current_page = pageid if current_page == None else current_page
logActivity(self.session, resource_type, resource, current_page, start_time, end_time)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,736 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"searchId": "value",
"state": 5
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "this.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_safety},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_safety},\r\n\t\t4, {session.custom.alarm_filter.show_safety},\r\n\t\t5, {session.custom.alarm_filter.show_safety},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 25,
"width": 25
}
},
"root": {
"children": [
{
"meta": {
"name": "Closed"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "{view.custom.state} \u003d 5"
},
"type": "expr"
}
},
"position.rotate.angle": {
"binding": {
"config": {
"path": "view.params.directionLeft"
},
"enabled": false,
"transforms": [
{
"expression": "if({value}, \u0027180deg\u0027, \u00270deg\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "M 8.6500001,0 H 26.15 c 2.0775,0 3.75,1.6725 3.75,3.75 v 22.5 C 29.9,28.3275 28.2275,30 26.15,30 H 8.6500001 c -2.0775,0 -3.75,-1.6725 -3.75,-3.75 V 3.75 c 0,-2.0775 1.6725,-3.75 3.75,-3.75 z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m 12,15 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m -0.1,28 h 34 v 3 h -34 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "M 12 14.97 L 13.7 14.97 Q 15.4 14.97 15.4 14.97 L 15.4 14.97",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
}
],
"preserveAspectRatio": "xMidYMin",
"style": {
"overflow": "hidden"
},
"viewBox": "-0.5 -0.5 35 32"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "Open"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "{view.custom.state} !\u003d 5"
},
"type": "expr"
}
},
"position.rotate.angle": {
"binding": {
"config": {
"path": "view.params.directionLeft"
},
"enabled": false,
"transforms": [
{
"expression": "if({value}, \u0027180deg\u0027, \u00270deg\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state1},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state1},\r\n3,{session.custom.colours.state1},\r\n4,{session.custom.colours.state1},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "m 8.75,0 h 17.5 C 28.3275,0 30,1.6725 30,3.75 v 22.5 C 30,28.3275 28.3275,30 26.25,30 H 8.75 C 6.6725,30 5,28.3275 5,26.25 V 3.75 C 5,1.6725 6.6725,0 8.75,0 Z",
"fill": {
"paint": "#D5D5D5"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m 13,0 h 14 c 1.662,0 3,1.338 3,3 v 24 c 0,1.662 -1.338,3 -3,3 H 13 c -1.662,0 -3,-1.338 -3,-3 V 3 c 0,-1.662 1.338,-3 3,-3 z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m 16.1,15 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "M 15 15 L 18 18",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m 0,28 h 34 v 3 H 0 Z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
}
],
"preserveAspectRatio": "xMidYMin",
"style": {
"overflow": "hidden"
},
"viewBox": "-0.5 -0.5 35 32"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"path": "view.custom.display_icon"
},
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,113 @@
{
"custom": {},
"params": {
"breakpoint": 500,
"params": {},
"path": "Header/Header"
},
"propConfig": {
"params.breakpoint": {
"paramDirection": "input",
"persistent": true
},
"params.params": {
"paramDirection": "input",
"persistent": true
},
"params.path": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 58,
"width": 512
}
},
"root": {
"children": [
{
"meta": {
"name": "Large"
},
"position": {
"size": "large"
},
"propConfig": {
"props.params.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"type": "property"
}
}
},
"props": {
"params": {
"size": "medium"
},
"style": {
"backgroundColor": "#2B2B2B"
}
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Small"
},
"propConfig": {
"props.params.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"type": "property"
}
}
},
"props": {
"params": {
"size": "small"
},
"style": {
"backgroundColor": "#2B2B2B"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"propConfig": {
"props.breakpoint": {
"binding": {
"config": {
"path": "view.params.breakpoint"
},
"type": "property"
}
}
},
"type": "ia.container.breakpt"
}
}

View File

@ -0,0 +1,184 @@
{
"custom": {},
"params": {},
"props": {
"defaultSize": {
"height": 240,
"width": 400
}
},
"root": {
"children": [
{
"meta": {
"name": "Header"
},
"position": {
"height": 32,
"width": 400
},
"props": {
"style": {
"background-color": "#555555",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Command Authentication"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Password Label"
},
"position": {
"height": 32,
"width": 152,
"x": 115.5,
"y": 68
},
"props": {
"style": {
"classes": "Text-Styles/Ariel-Bold-White-12pt",
"fontSize": 18
},
"text": "Enter Username"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "PasswordField"
},
"position": {
"height": 32,
"width": 229,
"x": 85.5,
"y": 116
},
"props": {
"style": {
"classes": "Text-Styles/Ariel-Bold-12pt",
"fontSize": 16
}
},
"type": "ia.input.password-field"
},
{
"meta": {
"name": "Error Label",
"visible": false
},
"position": {
"height": 32,
"width": 270,
"x": 56.5,
"y": 143
},
"props": {
"style": {
"classes": "Text-Styles/Ariel-Bold-12pt",
"color": "#FF8000",
"fontSize": 16,
"textAlign": "center"
},
"text": "Login does not match"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tusername \u003d self.session.props.auth.user.userName\n\tlogin \u003d self.getSibling(\"PasswordField\").props.text\n\t\n\tif username \u003d\u003d login.lower():\n\t\tuser_valid \u003d True\n\telse:\n\t\tuser_valid \u003d False\n\t\n\trme_role \u003d self.session.custom.fc +\"-rme-c2c-all\"\n\tadmin_role \u003d \"eurme-ignition-admins\"\n\troles \u003d (self.session.props.auth.user.roles)\n\tif (rme_role.lower() in roles \n\tor rme_role.upper() in roles) or admin_role in roles:\n\t\thas_role \u003d True\n\telse:\n\t\thas_role \u003d False\n\t\n\tif user_valid and has_role:\n\t\tself.session.custom.command_auth.auth_time \u003d system.date.now()\n\t\tself.session.custom.command_auth.enabled \u003d True\n\t\tsystem.perspective.closePopup(\u0027\u0027)\n\telse:\n\t\tself.getSibling(\"Error Label\").meta.visible \u003d True"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Authenticate"
},
"position": {
"height": 34,
"width": 120,
"x": 71,
"y": 191
},
"props": {
"image": {
"height": 20,
"width": 20
},
"style": {
"backgroundColor": "#555555",
"classes": "Background-Styles/Controller"
},
"text": "Authenticate"
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup(\u0027\u0027)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Cancel"
},
"position": {
"height": 34,
"width": 120,
"x": 209,
"y": 191
},
"props": {
"image": {
"height": 20,
"width": 20
},
"style": {
"backgroundColor": "#555555",
"classes": "Background-Styles/Controller"
},
"text": "Cancel"
},
"type": "ia.input.button"
}
],
"custom": {
"tags_data": {
"$": [
"ds",
192,
1671029641714
],
"$columns": [
{
"data": [],
"name": "Tags",
"type": "String"
}
]
}
},
"meta": {
"name": "root"
},
"props": {
"style": {
"classes": "Background-Styles/Controller"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,787 @@
{
"custom": {},
"params": {
"color": "#FFFFFF"
},
"propConfig": {
"params.color": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 380,
"width": 250
}
},
"root": {
"children": [
{
"meta": {
"name": "Color Palette"
},
"position": {
"grow": 1
},
"props": {
"alignContent": "flex-start",
"alignItems": "flex-start",
"elementPosition": {
"basis": "20px",
"grow": 0,
"shrink": 0
},
"instances": [
{
"color": "#FFFFFF"
},
{
"color": "#D5D5D5"
},
{
"color": "#AAAAAA"
},
{
"color": "#808080"
},
{
"color": "#555555"
},
{
"color": "#2B2B2B"
},
{
"color": "#000000"
},
{
"color": "#FFCCCC"
},
{
"color": "#FF8A8A"
},
{
"color": "#FF4747"
},
{
"color": "#FF0000"
},
{
"color": "#D90000"
},
{
"color": "#AC0000"
},
{
"color": "#800000"
},
{
"color": "#FFE8CC"
},
{
"color": "#FFCA8A"
},
{
"color": "#FFAC47"
},
{
"color": "#FF8C00"
},
{
"color": "#D97700"
},
{
"color": "#AC5F00"
},
{
"color": "#804600"
},
{
"color": "#FFFFCC"
},
{
"color": "#FFFF8A"
},
{
"color": "#FFFF47"
},
{
"color": "#FFFF00"
},
{
"color": "#D9D900"
},
{
"color": "#ACAC00"
},
{
"color": "#808000"
},
{
"color": "#CCFFCC"
},
{
"color": "#8AFF8A"
},
{
"color": "#47FF47"
},
{
"color": "#00FF00"
},
{
"color": "#00D900"
},
{
"color": "#00AC00"
},
{
"color": "#008000"
},
{
"color": "#CCFFFF"
},
{
"color": "#8AFFFF"
},
{
"color": "#47FFFF"
},
{
"color": "#00FFFF"
},
{
"color": "#00D9D9"
},
{
"color": "#00ACAC"
},
{
"color": "#008080"
},
{
"color": "#CCCCFF"
},
{
"color": "#8A8AFF"
},
{
"color": "#4747FF"
},
{
"color": "#0000FF"
},
{
"color": "#0000D9"
},
{
"color": "#0000AC"
},
{
"color": "#000080"
},
{
"color": "#FFCCFF"
},
{
"color": "#FF8AFF"
},
{
"color": "#FF47FF"
},
{
"color": "#FF00FF"
},
{
"color": "#D900D9"
},
{
"color": "#AC00AC"
},
{
"color": "#800080"
}
],
"key": "value",
"path": "Framework/Color Picker/Color",
"style": {
"backgroundColor": "#FFFFFF"
},
"useDefaultViewHeight": false,
"useDefaultViewWidth": false,
"wrap": "wrap"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "color-clicked",
"pageScope": true,
"script": "\tcolor \u003d payload[\"color\"]\n\tself.view.params.color \u003d color",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.display.flex-repeater"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "40px",
"shrink": 0
},
"props": {
"style": {
"marginLeft": "6px"
},
"text": "Red"
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "NumericEntryField"
},
"position": {
"basis": "32px",
"shrink": 0
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"path": "view.params.color"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn int(value[1:3], 16)\n\texcept:\n\t\treturn None",
"type": "script"
}
],
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\tif origin in [\"Browser\", \"BindingWriteback\"]:\n\t\tif currentValue.value !\u003d None:\n\t\t\tcolor \u003d self.view.params.color\n\t\t\thexColor \u003d hex(currentValue.value).replace(\"0x\",\"\").upper().replace(\"L\",\"\")\n\t\t\tif len(hexColor) \u003d\u003d 1:\n\t\t\t\thexColor \u003d \"0%s\" % hexColor\n\t\t\tcolor \u003d \"#\" + hexColor + color[3:]\n\t\t\tself.view.params.color \u003d color"
}
}
},
"props": {
"format": "0,0",
"inputBounds": {
"maximum": 255,
"minimum": 0
},
"style": {
"borderRadius": "4px"
}
},
"type": "ia.input.numeric-entry-field"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "50px",
"shrink": 0
},
"props": {
"direction": "column",
"justify": "center",
"style": {
"marginLeft": "10px",
"marginRight": "10px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Slider"
},
"position": {
"grow": 1
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "../FlexContainer/NumericEntryField.props.value"
},
"type": "property"
}
}
},
"props": {
"labels": {
"interval": 42.5,
"show": true
},
"max": 255,
"style": {
"marginLeft": "10px",
"marginRight": "20px"
}
},
"type": "ia.input.slider"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "72px",
"shrink": 0
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "40px",
"shrink": 0
},
"props": {
"style": {
"marginLeft": "6px"
},
"text": "Blue"
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "NumericEntryField"
},
"position": {
"basis": "32px",
"shrink": 0
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"path": "view.params.color"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn int(value[3:5], 16)\n\texcept:\n\t\treturn None",
"type": "script"
}
],
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\tif origin in [\"Browser\", \"BindingWriteback\"]:\n\t\tif currentValue.value !\u003d None:\n\t\t\tcolor \u003d self.view.params.color\n\t\t\thexColor \u003d hex(currentValue.value).replace(\"0x\",\"\").upper().replace(\"L\",\"\")\n\t\t\tif len(hexColor) \u003d\u003d 1:\n\t\t\t\thexColor \u003d \"0%s\" % hexColor\n\t\t\tcolor \u003d \"#\" + color[1:3] + hexColor + color[5:]\n\t\t\tself.view.params.color \u003d color"
}
}
},
"props": {
"format": "0,0",
"inputBounds": {
"maximum": 255,
"minimum": 0
},
"style": {
"borderRadius": "4px"
}
},
"type": "ia.input.numeric-entry-field"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "50px",
"shrink": 0
},
"props": {
"direction": "column",
"justify": "center",
"style": {
"marginLeft": "10px",
"marginRight": "10px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Slider"
},
"position": {
"grow": 1
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "../FlexContainer/NumericEntryField.props.value"
},
"type": "property"
}
}
},
"props": {
"labels": {
"interval": 42.5,
"show": true
},
"max": 255,
"style": {
"marginLeft": "10px",
"marginRight": "20px"
}
},
"type": "ia.input.slider"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "72px",
"shrink": 0
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_1"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "40px",
"shrink": 0
},
"props": {
"style": {
"marginLeft": "6px"
},
"text": "Green"
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "NumericEntryField"
},
"position": {
"basis": "32px",
"shrink": 0
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"path": "view.params.color"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn int(value[5:], 16)\n\texcept:\n\t\treturn None",
"type": "script"
}
],
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\tif origin in [\"Browser\", \"BindingWriteback\"]:\n\t\tif currentValue.value !\u003d None:\n\t\t\tcolor \u003d self.view.params.color\n\t\t\thexColor \u003d hex(currentValue.value).replace(\"0x\",\"\").upper().replace(\"L\",\"\")\n\t\t\tif len(hexColor) \u003d\u003d 1:\n\t\t\t\thexColor \u003d \"0%s\" % hexColor\n\t\t\tcolor \u003d \"#\" + color[1:5] + hexColor\n\t\t\tself.view.params.color \u003d color"
}
}
},
"props": {
"format": "0,0",
"inputBounds": {
"maximum": 255,
"minimum": 0
},
"style": {
"borderRadius": "4px"
}
},
"type": "ia.input.numeric-entry-field"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "50px",
"shrink": 0
},
"props": {
"direction": "column",
"justify": "center",
"style": {
"marginLeft": "10px",
"marginRight": "10px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Slider"
},
"position": {
"grow": 1
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "../FlexContainer/NumericEntryField.props.value"
},
"type": "property"
}
}
},
"props": {
"labels": {
"interval": 42.5,
"show": true
},
"max": 255,
"style": {
"marginLeft": "10px",
"marginRight": "20px"
}
},
"type": "ia.input.slider"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "72px",
"shrink": 0
},
"props": {
"style": {
"overflow": "hidden"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_2"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"marginLeft": "6px",
"marginRight": "6px"
},
"text": "Color"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "TextField"
},
"position": {
"basis": "100px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.params.color"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderRadius": "4px"
}
},
"type": "ia.input.text-field"
},
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "20px"
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "view.params.color"
},
"type": "property"
}
}
},
"props": {
"style": {
"borderColor": "#D3D3D3",
"borderRadius": "32px",
"borderStyle": "solid",
"borderWidth": "1px",
"margin": "6px"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t## Send message back to view/component that called color picker popup\n\tsystem.perspective.sendMessage(\n\t\t\"updateFromColorPicker\",\n\t\tpayload\u003d{\"color\": self.view.params.color},\n\t\tscope\u003d\"session\"\n\t)\n\t## close color picker poup\n\tsystem.perspective.closePopup(\"ColorPicker\")"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button Update and Close",
"tooltip": {
"enabled": true,
"location": "center-left",
"text": "Update and close"
}
},
"props": {
"image": {
"icon": {
"path": "material/exit_to_app"
}
},
"text": ""
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"grow": 1
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": "32px",
"shrink": 0
},
"props": {
"style": {
"marginBottom": "10px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/ColorPicker/Container"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,19 @@
import time
def close_websckt():
fc = system.tag.readBlocking(["Configuration/FC"])
fc_value = fc[0].value
tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (fc_value)
system.tag.writeBlocking([tag_provider + "System/close_socket"],[1])
time.sleep(1)
system.tag.writeBlocking([tag_provider + "System/close_socket"],[0])
logger = system.util.getLogger("%s-Project-Update" % (fc))
logger.info("Web-Socket closed due to project update")
def check_web_socket():
request_to_close = system.tag.readBlocking(["System/close_socket"])
request_to_close_val = request_to_close[0].value
if request_to_close_val:
return True
else:
return False

View File

@ -0,0 +1,50 @@
def detailed_view(self, tag_name, device_id, area):
"""
This function is used to naviagte to a detailed view
For example an on click event of a component.
The input paramter array to the component contains a reference to the PLC.
Detail view display all devices and equipement connected to a particular PLC.
The PLC ID is looked up in the "Configuration/DetailedViews" dictionary.
if found it navigates to the detailed view of the page_name {/<PLCid>}.
Args:
self: This is a reference to the object that is clicked on the screen.
tag_name: Hold information on the particular event that call this function.
area : The area within the FC
Returns:
None.
Raises:
None.
"""
device = tag_name.split("_")
device = device[0]
# Example: page_name = /F01
pages = system.tag.readBlocking(["Configuration/DetailedViews"])
pages_value = pages[0].value
pages_decoded = system.util.jsonDecode(pages_value)
for view , devices in pages_decoded.items():
if device in devices:
self.session.custom.searchId = tag_name
self.session.custom.deviceSearchId = device_id
system.perspective.sendMessage("plc-to-display", payload = {"device":view,"show_controls":True,"area":area}, scope = "page")
url_to_navigate = "/DetailedView/%s/%s" % (view, view)
system.perspective.navigate(page = url_to_navigate)
return
def navigate_to_deatiled_view(source):
page_id = config.project_config.get_project_config.global_project_page_ids.get(source)
if page_id:
url_to_navigate = "/DetailedView/%s/%s" % (page_id, page_id)
navigation.amzl_navigation.set_session_variables(self, page_id, False)
system.perspective.navigate(page = url_to_navigate)
elif not page_id:
data = source.split("/")
pass

View File

@ -0,0 +1,555 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"searchId": "value",
"state": 5
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "this.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_safety},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_safety},\r\n\t\t4, {session.custom.alarm_filter.show_safety},\r\n\t\t5, {session.custom.alarm_filter.show_safety},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 10,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "PullChord_Line2"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[0].visibility": {
"binding": {
"config": {
"path": "view.custom.error"
},
"transforms": [
{
"expression": "if({value}, \u0027visible\u0027,\u0027hidden\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].visibility": {
"binding": {
"config": {
"path": "view.custom.error"
},
"transforms": [
{
"expression": "if({value}, \u0027visible\u0027,\u0027hidden\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[2].stroke.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state1},\r\n3,{session.custom.colours.state1},\r\n4,{session.custom.colours.state1},\r\n\u0027#000000\u0027\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "m -0.38931298,0.28431365 c 33.95623398,0 67.91246898,0 101.86870298,0",
"fill": {
"paint": "#FFFFFF"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m -0.38931298,10.850587 c 33.95623398,0 67.91246898,0 101.86870298,0",
"fill": {
"paint": "#FFFFFF"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m -0.38931298,5.5674501 c 33.95623398,0 67.91246898,0 101.86870298,0",
"fill": {
"paint": "#FFFFFF"
},
"name": "path",
"opacity": 1,
"stroke": {
"dasharray": "8, 8, 8",
"dashoffset": "\"20\"",
"key": "\"2.15848\"",
"miterlimit": "\"10\"",
"width": 3
},
"type": "path"
}
],
"preserveAspectRatio": "none",
"style": {},
"viewBox": "-0.5 -0.5 102 12"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"path": "view.custom.display_icon"
},
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"mode": "percent",
"style": {
"cursor": "pointer",
"overflow": "visible"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,172 @@
{
"custom": {},
"params": {
"active": false,
"color": "",
"id": "",
"text": ""
},
"propConfig": {
"params.active": {
"paramDirection": "inout",
"persistent": true
},
"params.color": {
"paramDirection": "input",
"persistent": true
},
"params.id": {
"paramDirection": "input",
"persistent": true
},
"params.text": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 28,
"width": 183
}
},
"root": {
"children": [
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.sendMessage(\u0027activate-filter\u0027, payload \u003d {\u0027id\u0027:self.view.params.id}, scope \u003d \u0027page\u0027)\n\tself.view.params.active \u003d True "
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "AddButton"
},
"position": {
"basis": "30px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "!{view.params.active}"
},
"type": "expr"
}
},
"props.color": {
"binding": {
"config": {
"path": "view.params.color"
},
"type": "property"
}
}
},
"props": {
"path": "material/add",
"style": {
"cursor": "pointer"
}
},
"type": "ia.display.icon"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.sendMessage(\u0027deactivate-filter\u0027, payload \u003d {\u0027id\u0027:self.view.params.id}, scope \u003d \u0027page\u0027)\n\tself.view.params.active \u003d False "
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "RemoveButton"
},
"position": {
"basis": "30px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.params.active}"
},
"type": "expr"
}
},
"props.color": {
"binding": {
"config": {
"path": "view.params.color"
},
"type": "property"
}
}
},
"props": {
"path": "material/remove",
"style": {
"cursor": "pointer"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "FilterText"
},
"position": {
"basis": "153px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.text"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Page/Text",
"fontSize": 12
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"style": {
"overflow": "hidden"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "deactivate-filter",
"pageScope": true,
"script": "\t# implement your handler here\n\tif payload[\u0027id\u0027] \u003d\u003d self.view.params.id or payload[\u0027id\u0027] \u003d\u003d -1:\n\t\tself.view.params.active \u003d False",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,44 @@
def generate_tag_config(self,event):
"""This function generates the tag config in the search window.
Args:
self: A reference to the object that is invoking this function.
event: A reference to the event object that is being called by this function..
Returns:
This is a description of what is returned.
Raises:
None.
"""
tag = event.value.get("Tags")
fc = system.tag.read("Configuration/FC").value
path ="[%s_SCADA_TAG_PROVIDER]%s/OPC/" % (fc, tag)
results = system.tag.browse( path = path)
tag_list = results.getResults()
data = [i["fullPath"] for i in tag_list]
table_data = []
for i in data:
config = system.tag.getConfiguration(i)
alarms = [x.get("alarms") for x in config]
try:
for alarm in alarms:
for x in alarm:
# replace = "[%s_SCADA_TAG_PROVIDER]" % (fc)
system.perspective.print(x)
full_path = str(i)
name = x.get("name")
additional_info = x.get("AdditionalInfo")
priority = x.get("priority")
bit_position = x.get("bitPosition")
row = row_builder.build_row(FullPath = full_path, AdditionalInfo = additional_info,
Priority = priority, Name = name, StyleClass = {"classes":"Alarms-Styles/NoAlarms"})
table_data.append(row)
except:
system.perspective.print("object not iterable")
# self.getSibling("Table_0").props.data = table_data
payload = {}
payload["table_data"] = table_data
system.perspective.sendMessage("build-tag-config", payload = payload, scope = "view")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,628 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "SLAM"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"position.rotate.angle": {
"binding": {
"config": {
"path": "view.params.directionLeft"
},
"enabled": false,
"transforms": [
{
"expression": "if({value}, \u0027180deg\u0027, \u00270deg\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "M 25.072251,49.491677 C 8.305025,50.18642 -4.5893078,30.832553 2.4672281,15.562464 8.2437711,-0.23935905 31.006999,-4.7804171 42.373386,7.6015452 54.088036,18.389216 50.750821,39.438697 36.798277,46.490083 33.221446,48.453809 29.149949,49.49602 25.072251,49.491677 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1.5
},
"type": "path"
},
{
"d": "m 25.27,19.376563 c -3.799453,0.197118 -4.03784,-6.218759 0,-6.053125 3.946982,-0.08033 3.946979,6.133451 0,6.053125 z m 7,0 c -3.799453,0.197118 -4.03784,-6.218759 0,-6.053125 3.946982,-0.08033 3.946979,6.133451 0,6.053125 z m -0.240001,-0.316562 c 0,2.383333 0,4.766667 0,7.15 -2.173333,0 -4.346667,0 -6.52,0 0,-2.383333 0,-4.766667 0,-7.15 2.173333,0 4.346667,0 6.52,0 z M 17.07,23.24 c 0,4.116667 0,8.233333 0,12.35 -0.666667,0 -1.333333,0 -2,0 0,-4.116667 0,-8.233333 0,-12.35 0.666667,0 1.333333,0 2,0 z m 25.119999,4.220001 c 0,1.3 0,2.6 0,3.9 -8.69,0 -17.38,0 -26.07,0 0,-1.3 0,-2.6 0,-3.9 8.69,0 17.38,0 26.07,0 z M 12.079999,8.75 c 0,10.833333 0,21.666667 0,32.5 -1.086667,0 -2.173333,0 -3.26,0 0,-10.833333 0,-21.666667 0,-32.5 1.086667,0 2.173333,0 3.26,0 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 0.5
},
"type": "path"
}
],
"style": {
"overflow": "hidden"
},
"viewBox": "-0.5 -0.5 51 51"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "SLAMs"
},
"position": {
"height": 0.005,
"width": 0.005,
"x": 0.0225,
"y": 0.0277
},
"props": {
"params": {
"tagProps": [
"",
"",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"path": "Symbol-Views/Equipment-Views/SLAMs"
},
"type": "ia.display.view"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,792 @@
{
"custom": {
"activityLogger": {
"alt_pageid": "help",
"start_time": {
"$": [
"ts",
192,
1718194270770
],
"$ts": 1718194270770
}
}
},
"events": {
"system": {
"onShutdown": {
"config": {
"script": "#\tactivityLog.logger.callLogger(self, \u0027page\u0027)\n\tactivityLog.productMetrics.callLogger(self, \u0027page\u0027)"
},
"scope": "G",
"type": "script"
},
"onStartup": {
"config": {
"script": "\tself.custom.activityLogger.start_time \u003d system.date.now()"
},
"scope": "G",
"type": "script"
}
}
},
"params": {},
"propConfig": {
"custom.activityLogger": {
"persistent": true
},
"custom.activityLogger.pageid": {
"binding": {
"config": {
"expression": "{page.props.path}"
},
"transforms": [
{
"code": "\tif value \u003d\u003d\u0027/\u0027 or value \u003d\u003d \u0027\u0027 or value \u003d\u003d None:\n\t\treturn self.custom.activityLogger.alt_pageid.lower()\n\telse:\n\t\treturn value[1:].lower()",
"type": "script"
}
],
"type": "expr"
}
}
},
"props": {
"defaultSize": {
"height": 1080,
"width": 1920
}
},
"root": {
"children": [
{
"meta": {
"name": "Header"
},
"position": {
"basis": "50px"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Body header"
},
"position": {
"basis": "1920px"
},
"props": {
"text": "How can we help you ?",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "45px",
"fontWeight": "bolder",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "120px",
"grow": 1
},
"props": {
"justify": "center",
"style": {
"opacity": "0.73",
"textShadow": "#AAAAAA 1px 2px 2px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Markdown"
},
"position": {
"basis": "94px",
"grow": 1
},
"props": {
"markdown": {
"escapeHtml": false
},
"source": "\u003chtml\u003eThis page provides help on all things SCADA related. Cant find what your looking for ?. \u003cbr\u003eReach out to the MAP team for assistance.\u003c/html\u003e",
"style": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "20px",
"fontWeight": "lighter",
"lineHeight": "1.5",
"marginBottom": "20px",
"textAlign": "center"
}
},
"type": "ia.display.markdown"
},
{
"children": [
{
"children": [
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/menu_book",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "User Guide",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"marginTop": "",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/user_guide"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://w.amazon.com/bin/view/EURME/MAP/Product_Management/SCADA2/Resources/UserGuide"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "UserGuideCard"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": "50px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/developer_mode",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Developer Guide",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/dev_guide"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://w.amazon.com/bin/view/EURME/MAP/Projects/Amazon_SCADA/Expanding_BU_and_New_Regions_SCADA/AMZL/DeveloperGuide/"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "DevelopmentGuideCard"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": "50px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/comment",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Provide Feedback",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/feedback"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://quip-amazon.com/BSxOAUz9geea/SCADA-20-Feedback"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "DevelopmentGuideCard_0"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": 50,
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/healing",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Report Safety Concern",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/reportsafetyconcern"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://atoz.amazon.work/safety_observations"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "SafetyConcernsCard"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "CardsTopRow"
},
"position": {
"basis": "280px"
},
"props": {
"justify": "center",
"style": {
"marginBottom": "20px",
"marginTop": "20px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/confirmation_number",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Open a Ticket",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/ticket"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://river.amazon.com/?org\u003dGlobal_RME"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "Open a Ticket"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": "50px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/playlist_add_check",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Commissioning Tool Guide",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/commission_guide"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"newTab": true,
"url": "https://w.amazon.com/bin/view/EURME/MAP/Product_Management/SCADA2/Resources/CommissioningToolUserGuide"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "Commissioning Tool guide"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": "50px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "58px"
},
"props": {
"color": "#4D9CCE",
"path": "material/local_library",
"style": {
"margin": "10px",
"marginTop": "50px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"text": "Symbol Library",
"textStyle": {
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "22px",
"fontWeight": "bold",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"custom": {
"buttonid": "help/symbol_library"
},
"events": {
"dom": {
"onClick": [
{
"config": {
"script": "\tbuttonid \u003d self.custom.buttonid\n\tactivityLog.productMetrics.callLogger(self.view, \u0027click\u0027, buttonid)"
},
"scope": "G",
"type": "script"
},
{
"config": {
"params": {},
"view": "Symbol-Views/Symbol-Library-Views/SymbolLibraryMain"
},
"scope": "C",
"type": "nav"
}
]
}
},
"meta": {
"name": "Symbol Library"
},
"position": {
"basis": "400px"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#F2F3F4",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"marginBottom": "10px",
"marginRight": "0px",
"marginTop": "10px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "CardsBottomRow"
},
"position": {
"basis": "260px"
},
"props": {
"justify": "center",
"style": {
"marginTop": "20px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Card body"
},
"position": {
"basis": "734px",
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Body"
},
"position": {
"basis": "980px"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Footer"
},
"position": {
"basis": "50px"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#EDEDED"
}
},
"type": "ia.container.flex"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,931 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown",
"visible_status": false
},
"params": {
"directionLeft": false,
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
}
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {view.custom.isMatch}\u003e0,\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {view.custom.isMatch}\u003e0,\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.visible_status": {
"binding": {
"config": {
"expression": "{view.custom.state} !\u003d 5"
},
"type": "expr"
},
"persistent": true
},
"params.directionLeft": {
"paramDirection": "input",
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 20,
"width": 29
}
},
"root": {
"children": [
{
"meta": {
"name": "ErrorStatus",
"tooltip": {
"style": {
"fontSize": 16
}
}
},
"position": {
"grow": 1
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "{view.custom.display_icon} \u0026\u0026 {view.custom.error} \u0026! {view.params.directionLeft}"
},
"type": "expr"
}
},
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.display_icon} \u0026\u0026 {view.custom.error} \u0026! {view.params.directionLeft} \u0026\u0026 {view.custom.show_error}"
},
"type": "expr"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours}[\"state\"+{value}] \u003d null, \r\n{session.custom.colours}[\"Fallback\"],\r\n{session.custom.colours}[\"state\"+{value}])",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].fill.paint": {
"binding": {
"config": {
"path": "view.custom.running_status"
},
"transforms": [
{
"expression": "case(\t{value}, \r\n\t\t1, {session.custom.colours.state0},\r\n\t\t2, {session.custom.colours.state0},\r\n\t\t3, {session.custom.colours.state5},\r\n\t\t\u0027#000000\u0027\r\n\t)",
"type": "expression"
},
{
"expression": "if({session.custom.alarm_filter.show_running},{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].stroke.width": {
"binding": {
"config": {
"expression": "if({session.custom.alarm_filter.show_running},2,0)"
},
"type": "expr"
}
},
"props.elements[2].fill": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired}, \r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#FFFFFF\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#000000\u0027,\r\n\t\t\t\u0027#000000\u0027),\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[2].text": {
"binding": {
"config": {
"path": "view.custom.priority"
},
"type": "property"
}
}
},
"props": {
"elements": [
{
"d": "M 32 2 L 62 32 L 32 62 L 2 32 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 2
},
"type": "path"
},
{
"d": "M 38 2 L 57.96 2 L 57.96 2 L 88 32 L 57.96 62 L 57.96 62 L 38 62 L 67.96 32 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000"
},
"type": "path"
},
{
"style": {
"classes": "",
"fontSize": 42,
"fontWeight": "bolder"
},
"type": "text",
"x": 20,
"y": 44.5
}
],
"style": {
"overflow": "hidden"
},
"viewBox": "0.5 0.5 89 64"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "ErrorStatus_Left"
},
"position": {
"grow": 1
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "{view.custom.display_icon} \u0026\u0026 {view.custom.error} \u0026\u0026 {view.params.directionLeft}"
},
"type": "expr"
}
},
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.display_icon} \u0026\u0026 {view.custom.error} \u0026\u0026 {view.params.directionLeft} \u0026\u0026 {view.custom.show_error}"
},
"type": "expr"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].fill.paint": {
"binding": {
"config": {
"path": "view.custom.running_status"
},
"transforms": [
{
"expression": "case(\t{value}, \r\n\t\t1, {session.custom.colours.state0},\r\n\t\t2, {session.custom.colours.state0},\r\n\t\t3, {session.custom.colours.state5},\r\n\t\t\u0027#000000\u0027\r\n\t)",
"type": "expression"
},
{
"expression": "if({session.custom.alarm_filter.show_running},{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[1].stroke.width": {
"binding": {
"config": {
"expression": "if({session.custom.alarm_filter.show_running},2,0)"
},
"type": "expr"
}
},
"props.elements[2].fill": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired}, \r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#FFFFFF\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#000000\u0027,\r\n\t\t\t\u0027#000000\u0027),\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[2].text": {
"binding": {
"config": {
"path": "view.custom.priority"
},
"type": "property"
}
}
},
"props": {
"elements": [
{
"d": "M 56,2 C 66,12 76,22 86,32 76,42 66,52 56,62 46,52 36,42 26,32 36,22 46,12 56,2 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 2
},
"type": "path"
},
{
"d": "M 50,2 C 43.346667,2 36.693333,2 30.04,2 20.026667,12 10.013333,22 0,32 10.013333,42 20.026667,52 30.04,62 36.693333,62 43.346667,62 50,62 40.013333,52 30.026667,42 20.04,32 30.026667,22 40.013333,12 50,2 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000"
},
"type": "path"
},
{
"style": {
"classes": "",
"fontSize": 42,
"fontWeight": "bolder",
"textOrientation": "upright",
"writingMode": "horizontal-tb"
},
"type": "text",
"x": 44.5,
"y": 44.5
}
],
"style": {
"overflow": "hidden"
},
"viewBox": "0.5 0.5 89 64"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "RunningStatus"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "if((({view.custom.display_icon} \u0026\u0026 !{view.custom.error}) || ({view.custom.show_running} \u0026! {view.custom.show_error})) \u0026! {view.params.directionLeft},True, False)"
},
"type": "expr"
}
},
"position.rotate.angle": {
"binding": {
"config": {
"path": "view.params.directionLeft"
},
"transforms": [
{
"expression": "if({value}, \u0027180deg\u0027, \u00270deg\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.running_status"
},
"transforms": [
{
"expression": "case(\t{value}, \r\n\t\t1, {session.custom.colours.state0},\r\n\t\t2, {session.custom.colours.state0},\r\n\t\t3, {session.custom.colours.state5},\r\n\t\t\u0027#000000\u0027\r\n\t)\r\n\t\t\r\n",
"type": "expression"
}
],
"type": "property"
}
}
},
"props": {
"elements": [
{
"d": "M 0 0 L 40 0 L 40 0 L 70 30 L 40 60 L 40 60 L 0 60 L 30 30 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#4c4c4c",
"width": "2"
},
"type": "path"
}
],
"style": {
"overflow": "hidden"
},
"viewBox": "-1.5 -1.5 73 63"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "RunningStatus_Left"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "if((({view.custom.display_icon} \u0026\u0026 !{view.custom.error}) || ({view.custom.show_running} \u0026! {view.custom.show_error})) \u0026\u0026 {view.params.directionLeft},True, False)"
},
"type": "expr"
}
},
"position.rotate.angle": {
"binding": {
"config": {
"path": "view.params.directionLeft"
},
"transforms": [
{
"expression": "if({value}, \u0027180deg\u0027, \u00270deg\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.running_status"
},
"transforms": [
{
"expression": "case(\t{value}, \r\n\t\t1, {session.custom.colours.state0},\r\n\t\t2, {session.custom.colours.state0},\r\n\t\t3, {session.custom.colours.state5},\r\n\t\t\u0027#000000\u0027\r\n\t)\r\n\t\t\r\n",
"type": "expression"
}
],
"type": "property"
}
}
},
"props": {
"elements": [
{
"d": "M 70,60 C 56.666667,60 43.333333,60 30,60 20,50 10,40 0,30 10,20 20,10 30,0 43.333333,0 56.666667,0 70,0 60,10 50,20 40,30 50,40 60,50 70,60 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#4c4c4c",
"width": "2"
},
"type": "path"
}
],
"style": {
"overflow": "hidden"
},
"viewBox": "-0.5 -0.5 71 61"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.Fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"path": "view.custom.display_icon"
},
"type": "property"
}
},
"props.style.borderStyle": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "solid"
},
{
"input": false,
"output": "none"
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"justify": "center",
"style": {
"borderColor": "#FF0000",
"borderWidth": "2px",
"cursor": "pointer"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,125 @@
{
"custom": {},
"params": {
"params": {},
"path": "",
"title": "Card Title",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"propConfig": {
"params.params": {
"paramDirection": "input",
"persistent": true
},
"params.path": {
"paramDirection": "input",
"persistent": true
},
"params.title": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultHeight": {
"paramDirection": "input",
"persistent": true
},
"params.useDefaultWidth": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 339,
"width": 369
}
},
"root": {
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "20px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.title"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Title"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.params": {
"binding": {
"config": {
"path": "view.params.params"
},
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.path"
},
"type": "property"
}
},
"props.useDefaultViewHeight": {
"binding": {
"config": {
"path": "view.params.useDefaultHeight"
},
"type": "property"
}
},
"props.useDefaultViewWidth": {
"binding": {
"config": {
"path": "view.params.useDefaultWidth"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "Framework/Card/Embedded"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "Framework/Card/Card"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,918 @@
{
"custom": {
"api_region_name": "eu",
"api_stage": "prod",
"enable_site_selection": true,
"help_url": "https://w.amazon.com/bin/view/EURME/MAP/Projects/Amazon_SCADA/Expanding_BU_and_New_Regions_SCADA/AMZL/DeveloperGuide/#H7.1SCADAFileManagementUtility",
"image_file_container_basis": "50%",
"image_file_content_shown": true,
"image_file_prefix": "SCADA//images/",
"image_file_suffix": ".svg",
"instances_file_prefix": "SCADA/EWR4/instance_configs/",
"loading": false,
"migrate_enabled": false,
"selected_image": null,
"selected_whid": "",
"site_folder": "SCADA//",
"site_image_list": [],
"site_source_list": [],
"source_file_container_basis": "50%",
"source_file_content_shown": true,
"source_file_prefix": "SCADA//source/",
"source_file_suffix": ".drawio",
"stage_config": {
"account_id": "006306898152",
"api_call_role": "arn:aws:iam::609617486056:role/RMESDScadaS3ManagementAPIcallRole-prod-eu-west-1",
"endpoint": "https://eu-west-1.scada-s3-management.scada.eurme.amazon.dev/",
"lambda_name": "RMESDScadaS3ManagementFlaskLambda-prod",
"region": "eu-west-1",
"repo_bucket": "ignition-image-repo",
"s3_region": "eu-west-1",
"source_bucket": "ignition-image-source"
},
"title_text": "S3 File Management",
"upload_enabled": true,
"user_roles": [
"rme-ctrl-map-all",
"rme-ctrl-all",
"rme-grt-all",
"na-rme-all",
"watrmecomms-l4-l8-bb-all",
"eurme-ignition-developers",
"eurme-ignition-admins",
"eurme-ignition-managers",
"eurme-ignition-users",
"maplab-rme-all",
"eurme-ignition-ae-india"
],
"whid": ""
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tselected_image \u003d self.params.selected_image\n\tself.custom.selected_image \u003d selected_image\n\tselected_site \u003d self.params.selected_site\n\tif not selected_site:\n\t\tselected_site \u003d self.custom.whid\n\tself.custom.selected_whid \u003d selected_site"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"selected_image": null,
"selected_site": null
},
"propConfig": {
"custom.api_region_name": {
"binding": {
"config": {
"path": "session.custom.aws.prefix"
},
"type": "property"
},
"persistent": true
},
"custom.api_stage": {
"persistent": true
},
"custom.enable_site_selection": {
"binding": {
"config": {
"expression": "isAuthorized(false, \u0027Authenticated/Roles/eurme-ignition-developers\u0027)"
},
"type": "expr"
},
"persistent": true
},
"custom.help_url": {
"persistent": true
},
"custom.image_file_container_basis": {
"binding": {
"config": {
"expression": "if(!{view.custom.image_file_content_shown},\u0027auto\u0027,\r\n\tif({view.custom.source_file_content_shown},\u002750%\u0027,\u0027100%\u0027))"
},
"type": "expr"
},
"persistent": true
},
"custom.image_file_content_shown": {
"binding": {
"config": {
"path": "/root/FlexContainer File Configs/Image File Config.props.params.content_shown"
},
"type": "property"
},
"persistent": true
},
"custom.image_file_prefix": {
"binding": {
"config": {
"expression": "{view.custom.site_folder}+\u0027images/\u0027"
},
"type": "expr"
},
"persistent": true
},
"custom.image_file_suffix": {
"persistent": true
},
"custom.loading": {
"persistent": true
},
"custom.migrate_enabled": {
"binding": {
"config": {
"expression": "{view.custom.flow_view_edit_mode.reviewer_enabled}\r\n\u0026\u0026!isNull({view.custom.stage_source})\r\n\u0026\u0026len({view.custom.stage_source})\r\n\u0026\u0026!isNull({view.custom.stage_destination})\r\n\u0026\u0026len({view.custom.stage_destination})"
},
"type": "expr"
},
"persistent": true
},
"custom.selected_image": {
"persistent": true
},
"custom.selected_whid": {
"onChange": {
"enabled": null,
"script": "\t# DEVNOTE: During peer review, noticed that when files are selected and then \n\t# the whid is changed, that a loop of file updates can be triggered\n\t# therefore, clear the \"selected_image\" custom prop on whid change\n\tself.custom.selected_image \u003d None\n\t"
},
"persistent": true
},
"custom.site_folder": {
"binding": {
"config": {
"expression": "stringFormat(\u0027SCADA/%s/\u0027, {view.custom.selected_whid})"
},
"type": "expr"
},
"persistent": true
},
"custom.site_image_list": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"transforms": [
{
"code": "\tif not value:\n\t\treturn []\n\tfrom AWS.s3 import S3Manager\n\t\n\tusername \u003d self.session.props.auth.user.userName\n\tapi_region_name \u003d self.custom.api_region_name\n\t\n\ts3m \u003d S3Manager(api_region_name\u003dapi_region_name, username\u003dusername)\n\t\n\tsite \u003d value\n\tbucket \u003d self.custom.stage_config.repo_bucket\n\t\n\treturn s3m.fetch_object_list_by_site_and_bucket(site, bucket)",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"custom.site_source_list": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"transforms": [
{
"code": "\tif not value:\n\t\treturn []\n\tfrom AWS.s3 import S3Manager\n\t\n\tusername \u003d self.session.props.auth.user.userName\n\tapi_region_name \u003d self.custom.api_region_name\n\t\n\ts3m \u003d S3Manager(api_region_name\u003dapi_region_name, username\u003dusername)\n\t\n\tsite \u003d value\n\tbucket \u003d self.custom.stage_config.source_bucket\n\t\n\treturn s3m.fetch_object_list_by_site_and_bucket(site, bucket)",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"custom.source_file_container_basis": {
"binding": {
"config": {
"expression": "if(!{view.custom.source_file_content_shown},\u0027auto\u0027,\r\n\tif({view.custom.image_file_content_shown},\u002750%\u0027,\u0027100%\u0027))"
},
"type": "expr"
},
"persistent": true
},
"custom.source_file_content_shown": {
"binding": {
"config": {
"path": "/root/FlexContainer File Configs/Source File Config.props.params.content_shown"
},
"type": "property"
},
"persistent": true
},
"custom.source_file_prefix": {
"binding": {
"config": {
"expression": "{view.custom.site_folder}+\u0027source/\u0027"
},
"type": "expr"
},
"persistent": true
},
"custom.source_file_suffix": {
"persistent": true
},
"custom.stage_config": {
"binding": {
"config": {
"expression": "{view.custom.api_region_name}"
},
"transforms": [
{
"code": "\treturn AWS.s3.STAGE_CONFIG[\u0027prod\u0027][value]",
"type": "script"
}
],
"type": "expr"
},
"persistent": true
},
"custom.title_text": {
"persistent": true
},
"custom.upload_enabled": {
"persistent": true
},
"custom.user_roles": {
"binding": {
"config": {
"path": "session.props.auth.user.roles"
},
"type": "property"
},
"persistent": true
},
"custom.whid": {
"binding": {
"config": {
"path": "session.custom.fc"
},
"type": "property"
},
"persistent": true
},
"params.selected_image": {
"paramDirection": "input",
"persistent": true
},
"params.selected_site": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 825,
"width": 1200
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Header"
},
"position": {
"grow": 1
},
"props": {
"style": {
"opacity": "0.73",
"overflow": "auto",
"textShadow": "#AAAAAA 1px 2px 2px"
},
"text": "S3 SCADA File Management",
"textStyle": {
"fontSize": 30,
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"events": {
"dom": {
"onClick": {
"config": {
"newTab": true,
"url": "{view.custom.help_url}"
},
"scope": "C",
"type": "nav"
}
}
},
"meta": {
"name": "Icon",
"tooltip": {
"enabled": true,
"text": "View documentation for this tool"
}
},
"position": {
"basis": "30px"
},
"props": {
"path": "material/help_outline",
"style": {
"cursor": "pointer"
}
},
"type": "ia.display.icon"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "30px",
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Header"
},
"position": {
"basis": "75px",
"shrink": 0
},
"props": {
"justify": "center",
"style": {
"classes": "Framework/Card/Title_transparent",
"textTransform": "capitalize"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Folder Config"
},
"position": {
"basis": "50%",
"grow": 1
},
"propConfig": {
"props.params.params.enables.site": {
"binding": {
"config": {
"path": "view.custom.enable_site_selection"
},
"type": "property"
}
},
"props.params.params.image_count": {
"binding": {
"config": {
"expression": "try(len({view.custom.site_image_list}),0)"
},
"type": "expr"
}
},
"props.params.params.selected_whid": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"type": "property"
}
},
"props.params.params.source_count": {
"binding": {
"config": {
"expression": "try(len({view.custom.site_source_list}),0)"
},
"type": "expr"
}
}
},
"props": {
"params": {
"open_expanded": true,
"params": {
"enables": {}
},
"path": "Objects/Templates/S3/Management/manage",
"show_box_shadow_on_expanded": true,
"title": "Bucket Configuration",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"path": "Framework/Card/Card_Collapsible_Transparent"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Site Config"
},
"position": {
"basis": "50%",
"grow": 1
},
"propConfig": {
"props.params.params.enables.site": {
"binding": {
"config": {
"path": "view.custom.enable_site_selection"
},
"type": "property"
}
},
"props.params.params.image_count": {
"binding": {
"config": {
"expression": "try(len({view.custom.site_image_list}),0)"
},
"type": "expr"
}
},
"props.params.params.selected_whid": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"type": "property"
}
},
"props.params.params.source_count": {
"binding": {
"config": {
"expression": "try(len({view.custom.site_source_list}),0)"
},
"type": "expr"
}
}
},
"props": {
"params": {
"open_expanded": true,
"params": {
"enables": {}
},
"path": "Objects/Templates/S3/Management/site",
"show_box_shadow_on_expanded": true,
"title": "Site Configuration",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"path": "Framework/Card/Card_Collapsible_Transparent"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer Site"
},
"position": {
"shrink": 0
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Image File Config"
},
"position": {
"grow": 1
},
"propConfig": {
"position.basis": {
"binding": {
"config": {
"path": "view.custom.image_file_container_basis"
},
"type": "property"
}
},
"props.params.params.bucket": {
"binding": {
"config": {
"path": "view.custom.stage_config.repo_bucket"
},
"type": "property"
}
},
"props.params.params.enables.delete": {
"binding": {
"config": {
"path": "view.custom.upload_enabled"
},
"type": "property"
}
},
"props.params.params.enables.upload": {
"binding": {
"config": {
"path": "view.custom.upload_enabled"
},
"type": "property"
}
},
"props.params.params.files": {
"binding": {
"config": {
"path": "view.custom.site_image_list"
},
"type": "property"
}
},
"props.params.params.prefix": {
"binding": {
"config": {
"path": "view.custom.image_file_prefix"
},
"type": "property"
}
},
"props.params.params.selected_file": {
"binding": {
"config": {
"path": "view.custom.selected_image"
},
"type": "property"
}
},
"props.params.params.suffix": {
"binding": {
"config": {
"path": "view.custom.image_file_suffix"
},
"type": "property"
}
},
"props.params.params.whid": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"type": "property"
}
}
},
"props": {
"params": {
"anchor_position": "left",
"content_shown": true,
"open_expanded": true,
"params": {
"enables": {
"download": true,
"file": true,
"object_key": false
},
"upload_file_types": [
"svg"
]
},
"path": "Objects/Templates/S3/Management/file",
"show_box_shadow_on_expanded": true,
"title": "Image SVG Files",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"path": "Framework/Card/Card_Collapsible_Transparent_with_Anchor",
"style": {
"overflow": "auto"
}
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Source File Config"
},
"position": {
"grow": 1
},
"propConfig": {
"position.basis": {
"binding": {
"config": {
"path": "view.custom.source_file_container_basis"
},
"type": "property"
}
},
"props.params.params.bucket": {
"binding": {
"config": {
"path": "view.custom.stage_config.source_bucket"
},
"type": "property"
}
},
"props.params.params.enables.delete": {
"binding": {
"config": {
"path": "view.custom.upload_enabled"
},
"type": "property"
}
},
"props.params.params.enables.upload": {
"binding": {
"config": {
"path": "view.custom.upload_enabled"
},
"type": "property"
}
},
"props.params.params.files": {
"binding": {
"config": {
"path": "view.custom.site_source_list"
},
"type": "property"
}
},
"props.params.params.prefix": {
"binding": {
"config": {
"path": "view.custom.source_file_prefix"
},
"type": "property"
}
},
"props.params.params.selected_file": {
"binding": {
"config": {
"path": "view.custom.selected_image"
},
"type": "property"
}
},
"props.params.params.suffix": {
"binding": {
"config": {
"path": "view.custom.source_file_suffix"
},
"type": "property"
}
},
"props.params.params.whid": {
"binding": {
"config": {
"path": "view.custom.selected_whid"
},
"type": "property"
}
}
},
"props": {
"params": {
"anchor_position": "right",
"content_shown": true,
"open_expanded": true,
"params": {
"enables": {
"download": true,
"file": true,
"object_key": false
},
"upload_file_types": [
"drawio"
]
},
"path": "Objects/Templates/S3/Management/file",
"show_box_shadow_on_expanded": true,
"title": "Source DRAWIO Files",
"useDefaultHeight": false,
"useDefaultWidth": false
},
"path": "Framework/Card/Card_Collapsible_Transparent_with_Anchor",
"style": {
"overflow": "auto"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer File Configs"
},
"position": {
"shrink": 0
},
"props": {
"justify": "space-between"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"newTab": true,
"url": "{view.custom.help_url}"
},
"scope": "C",
"type": "nav"
}
}
},
"meta": {
"name": "Button Documentation",
"tooltip": {
"enabled": true,
"location": "bottom",
"text": "View online documentation for this utility"
}
},
"props": {
"image": {
"icon": {
"path": "material/info"
}
},
"primary": false,
"style": {
"margin": "4px",
"padding": "4px"
},
"text": "Documentation"
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsite \u003d self.view.params.selected_site\n\tnull \u003d None\n\tquery_params \u003d {\n\t\t\"copy_option\": null,\n\t\t\"destination_view\": null,\n\t\t\"destination_site\": site,\n\t\t\"destination_bucket\": null,\n\t\t\"end_time\": null,\n\t\t\"error_occurred\": null,\n\t\t\"operation\": null,\n\t\t\"source_view\": null,\n\t\t\"source_site\": null,\n\t\t\"source_bucket\": null,\n\t\t\"start_time\": null,\n\t\t\"username\": self.session.props.auth.user.userName\n\t}\n\t# Open audit log viewer\n\tview_path \u003d \u0027PopUp-Views/S3/Audit/Log_Viewer\u0027\n\tparams \u003d {\u0027query_params\u0027: query_params}\n\tsystem.perspective.openPopup(\u0027Audit Log Viewer\u0027, view_path, \n\t\t\t\t\t\t\t\tparams, \u0027SCADA Audit Logs\u0027)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button Audit Log",
"tooltip": {
"enabled": true,
"location": "bottom",
"text": "View SCADA S3 audit logs for current user and site"
}
},
"props": {
"image": {
"icon": {
"path": "material/table_view"
}
},
"primary": false,
"style": {
"margin": "4px",
"padding": "4px"
},
"text": "Audit Logs"
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# build out the object key from repo bucket, site, selected view, and suffix\n\tbucket \u003d self.view.custom.stage_config.repo_bucket\n\tsite \u003d self.view.params.selected_site\n\tprefix \u003d self.view.custom.source_file_prefix\n\tview \u003d self.view.params.selected_image\n\tsuffix \u003d self.view.custom.image_file_suffix\n\tobj_key \u003d \u0027%s%s%s\u0027 % (prefix, view, suffix)\n\t# build out query params from local variables\n\tquery_params \u003d {\n\t\t\"view\": view,\n\t\t\"object_key\": obj_key,\n\t\t\"site\": site,\n\t\t\"bucket\": bucket\n\t}\n\t# Open version history log viewer\n\tview_path \u003d \u0027PopUp-Views/S3/Versions/Log_Viewer\u0027\n\tparams \u003d {\u0027query_params\u0027: query_params}\n\tsystem.perspective.openPopup(\u0027Version Log Viewer\u0027, view_path, \n\t\t\t\t\t\t\t\tparams, \u0027SCADA S3 Version History Log Viewer\u0027)\n\t\t\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Button Version History",
"tooltip": {
"enabled": true,
"location": "bottom",
"text": "View SCADA S3 version history for currently selected file"
}
},
"props": {
"image": {
"icon": {
"path": "material/history"
}
},
"primary": false,
"style": {
"margin": "4px",
"padding": "4px"
},
"text": "Version History"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer Buttons"
},
"position": {
"basis": "50px",
"shrink": 0
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "50px",
"grow": 1,
"shrink": 0
},
"props": {
"direction": "column",
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"scripts": {
"customMethods": [
{
"name": "show_confirm_dialog",
"params": [],
"script": "\t# ~~ 12 PARAMETERS ~~\n\t\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t\t# show close button\t\t(default \u003d true) boolean\n\t\t# btn text primary\t\t(default \u003d \"Primary\")\n\t\t# btn text secondary\t(default \u003d \"Secondary\")\n\t\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t\n\t\tmsg \u003d \"Update Instance Configuration for MP%s?\" % (self.view.params.instance.viewParams.mhe_id)\n\t\tAlerts.showAlert(\n\t\t\t\"info\", \n\t\t\t\"Update Instance Config?\", \n\t\t\tmsg, \n\t\t\t\"true\",\n\t\t\t\"Continue\", \n\t\t\t\"Cancel\", \n\t\t\t\"chevron_right\", \n\t\t\t\"\", \n\t\t\t\"right\", \n\t\t\t\"confirm_update_instance_config\", \n\t\t\t\"closePopup\", \n\t\t\t\"closePopup\"\n\t\t)\n\t\t"
},
{
"name": "show_success_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"success\", \n\t\t\"Instance Updated\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"right\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t"
},
{
"name": "show_warning_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 12 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\n\tAlerts.showAlert(\n\t\t\"warning\", \n\t\t\"Instance Not Updated\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"right\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\"\n\t)\n\t\t"
},
{
"name": "show_error_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 12 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\n\tAlerts.showAlert(\n\t\t\"error\", \n\t\t\"Instance Update Error!\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"right\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\"\n\t)\n\t\t"
},
{
"name": "update_bindings",
"params": [],
"script": "\tself.view.custom.loading \u003d False\n\t\t"
}
],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update_selected_whid",
"pageScope": false,
"script": "\t# implement your handler here\n\tself.view.custom.selected_whid \u003d payload.get(\u0027whid\u0027, None)\n",
"sessionScope": true,
"viewScope": true
},
{
"messageType": "update_selected_image",
"pageScope": false,
"script": "\t# implement your handler here\n\tself.view.custom.selected_image \u003d payload.get(\u0027image\u0027, None)\n\t",
"sessionScope": true,
"viewScope": true
},
{
"messageType": "update_file_binding",
"pageScope": false,
"script": "\t# update the appropriate binding to fetch an updated dataset of S3 objects,\n\t# depending upon which bucket was updated\n\tbucket \u003d payload.get(\u0027bucket\u0027, None)\n\tif bucket \u003d\u003d self.view.custom.stage_config.repo_bucket:\n\t\tself.view.refreshBinding(\u0027custom.site_image_list\u0027)\n\tif bucket \u003d\u003d self.view.custom.stage_config.source_bucket:\n\t\tself.view.refreshBinding(\u0027custom.site_source_list\u0027)",
"sessionScope": true,
"viewScope": false
}
]
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,732 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "PLC01",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "Spiral"
},
"position": {
"height": 0.005,
"width": 0.005,
"x": 0.0225,
"y": 0.0277
},
"props": {
"params": {
"tagProps": [
"",
"",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"path": "Symbol-Views/Equipment-Views/Spiral"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Spiral_Symbol"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"id": "defs2",
"name": "defs2",
"type": "defs"
},
{
"elements": [
{
"cx": "6.6145835",
"cy": "6.6145835",
"fill": {},
"id": "path234",
"name": "path234",
"r": "6.303678",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.23"
},
"type": "circle"
},
{
"cx": "6.6145835",
"cy": "6.6145835",
"fill": {
"paint": "transparent"
},
"id": "path234-7",
"name": "path234-7",
"r": "3.313657",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.221"
},
"type": "circle"
},
{
"d": "M 6.6188113,9.8749524 6.6103553,3.3542142",
"fill": {
"paint": "transparent"
},
"id": "path3429",
"name": "path3429",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "path"
},
{
"d": "M 4.978764,9.47052 8.23181,3.819167",
"fill": {
"paint": "transparent"
},
"id": "path3429-8",
"name": "path3429-8",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "path"
},
{
"d": "M 3.818909,8.2200703 9.461806,4.9523781",
"fill": {
"paint": "transparent"
},
"id": "path3429-8-2",
"name": "path3429-8-2",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "path"
},
{
"d": "M 3.3168328,6.6175189 9.837571,6.6090589",
"fill": {
"paint": "transparent"
},
"id": "path3429-8-2-6",
"name": "path3429-8-2-6",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "path"
},
{
"d": "M 3.7180036,4.9712623 6.8282074,6.7528116",
"fill": {
"paint": "transparent"
},
"id": "path3429-8-2-6-5",
"name": "path3429-8-2-6-5",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.219869"
},
"type": "path"
},
{
"d": "M 4.9523763,3.7647768 8.2200718,9.4076712",
"fill": {
"paint": "transparent"
},
"id": "path3429-8-2-6-5-5",
"name": "path3429-8-2-6-5-5",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "path"
},
{
"cx": "6.6145835",
"cy": "6.6145835",
"fill": {
"opacity": "1",
"paint": "#fefefe"
},
"id": "path234-7-0",
"name": "path234-7-0",
"r": "0.26523831",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.218"
},
"type": "circle"
}
],
"id": "layer1",
"name": "layer1",
"type": "group"
}
],
"style": {},
"viewBox": "0 0 13.229166 13.229167"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,897 @@
{
"custom": {},
"params": {
"Counts": {
"Diag": 0,
"High": 0,
"Low": 0,
"Medium": 0
},
"Status": "",
"tagProps": [
"PLC03",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"params.Counts": {
"paramDirection": "input",
"persistent": true
},
"params.Status": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 212,
"width": 336
},
"key": "value"
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "400px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"type": "property"
}
}
},
"props": {
"textStyle": {
"textIndent": "10px"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "JAM",
"tooltip": {
"enabled": true,
"text": "Jams"
}
},
"position": {
"basis": "24px",
"shrink": 0
},
"props": {
"path": "Symbol-Views/Equipment-Views/JAM",
"style": {
"marginRight": "5px"
}
},
"type": "ia.display.view"
},
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "10px",
"grow": 1
},
"props": {
"style": {
"marginRight": "10px"
},
"text": 0,
"textStyle": {
"textAlign": "end"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "60px"
},
"props": {
"style": {
"backgroundColor": "#555555",
"key": "value"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "50px"
},
"props": {
"style": {
"marginLeft": 10
},
"text": "AREA",
"textStyle": {
"fontFamily": "Roboto",
"fontSize": 12
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "195px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "/root.custom.area_display"
},
"type": "property"
}
}
},
"props": {
"style": {
"marginLeft": 50
},
"textStyle": {
"fontSize": 12
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": "80px"
},
"props": {
"style": {
"borderBottomColor": "#555555",
"borderBottomStyle": "solid",
"borderBottomWidth": 0.5,
"borderLeftColor": "#555555",
"borderLeftStyle": "none",
"borderLeftWidth": 0.5,
"borderRightColor": "#555555",
"borderRightStyle": "none",
"borderRightWidth": 0.5,
"borderTopColor": "#555555",
"borderTopStyle": "solid",
"borderTopWidth": 0.5
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "50px"
},
"props": {
"style": {
"marginLeft": 10
},
"text": "STATUS",
"textStyle": {
"fontFamily": "Roboto",
"fontSize": 12
}
},
"type": "ia.display.label"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tself.session.custom.covert\u003d False\n\tnavigation.navigate_to_page.detailed_view(self, self.view.params.tagProps[0],self.view.params.tagProps[0], self.view.params.tagProps[3])"
},
"enabled": false,
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Label"
},
"position": {
"basis": "236px"
},
"propConfig": {
"custom.status": {
"binding": {
"config": {
"path": "/root.custom.status"
},
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "this.custom.status"
},
"transforms": [
{
"fallback": "State-Styles/State0",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "State-Styles/Background-Fill/State1"
},
{
"input": 2,
"output": "State-Styles/Background-Fill/State2"
},
{
"input": 3,
"output": "State-Styles/Background-Fill/State3"
},
{
"input": 4,
"output": "State-Styles/Background-Fill/State4"
},
{
"input": 5,
"output": "State-Styles/Background-Fill/State5"
},
{
"input": 6,
"output": "State-Styles/Background-Fill/State6"
},
{
"input": 0,
"output": "State-Styles/State0"
}
],
"outputType": "style-list",
"type": "map"
},
{
"expression": "if({session.custom.colours.colour_impaired},{value}+\u0027_Alt\u0027,{value})",
"type": "expression"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "this.custom.status"
},
"transforms": [
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 5,
"output": "HEALTHY"
},
{
"input": 4,
"output": "DIAGNOSTIC"
},
{
"input": 3,
"output": "PROCESS DEGRADED"
},
{
"input": 2,
"output": "STOPPED"
},
{
"input": 1,
"output": "FAULTED"
},
{
"input": 6,
"output": null
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"borderBottomLeftRadius": 5,
"borderBottomRightRadius": 5,
"borderColor": "#555555",
"borderStyle": "solid",
"borderTopLeftRadius": 5,
"borderTopRightRadius": 5,
"borderWidth": 2,
"marginBottom": 10,
"marginLeft": 50,
"marginRight": 10,
"marginTop": 10
},
"textStyle": {
"fontSize": 12,
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_1"
},
"position": {
"basis": "80px"
},
"props": {
"style": {
"borderBottomColor": "#555555",
"borderBottomStyle": "solid",
"borderBottomWidth": 0.5
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "25px"
},
"props": {
"path": "material/notifications_active",
"style": {
"marginLeft": 10
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "100px"
},
"props": {
"style": {
"marginLeft": 10
},
"text": "ACTIVE ALARMS",
"textStyle": {
"fontFamily": "Roboto",
"fontSize": 12
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_3"
},
"position": {
"basis": "80px"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"children": [
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "32px"
},
"props": {
"text": "High",
"textStyle": {
"fontSize": 10
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_1"
},
"position": {
"basis": "32px"
},
"props": {
"text": "Medium",
"textStyle": {
"fontSize": 10
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_2"
},
"position": {
"basis": "32px"
},
"props": {
"text": "Low",
"textStyle": {
"fontSize": 10
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_3"
},
"position": {
"basis": "32px"
},
"props": {
"text": "Diag",
"textStyle": {
"fontSize": 10
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_4"
},
"position": {
"basis": "32px"
},
"props": {
"text": "Total",
"textStyle": {
"fontSize": 10
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "200px"
},
"props": {
"justify": "space-between"
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label_0"
},
"position": {
"basis": "32px"
},
"props": {
"text": 0,
"textStyle": {
"fontSize": 10,
"textAlign": "center"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-alarm-count",
"pageScope": false,
"script": "\thigh \u003d payload.get(\"High\",0)\n\tself.props.text \u003d high",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_1"
},
"position": {
"basis": "32px"
},
"props": {
"text": 0,
"textStyle": {
"fontSize": 10,
"textAlign": "center"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-alarm-count",
"pageScope": false,
"script": "\tmedium \u003d payload.get(\"Medium\",0)\n\tself.props.text \u003d medium",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_2"
},
"position": {
"basis": "32px"
},
"props": {
"text": 0,
"textStyle": {
"fontSize": 10,
"textAlign": "center"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-alarm-count",
"pageScope": false,
"script": "\tlow \u003d payload.get(\"Low\",0)\n\tself.props.text \u003d low",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_3"
},
"position": {
"basis": "32px"
},
"props": {
"text": 0,
"textStyle": {
"fontSize": 10,
"textAlign": "center"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-alarm-count",
"pageScope": false,
"script": "\tdiag \u003d payload.get(\"Diagnostic\",0)\n\tself.props.text \u003d diag",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_4"
},
"position": {
"basis": "32px"
},
"props": {
"text": 0,
"textStyle": {
"fontSize": 10,
"textAlign": "center"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "update-alarm-count",
"pageScope": false,
"script": "\tcritical \u003d payload.get(\"Critical\",0)\n\thigh \u003d payload.get(\"High\",0)\n\tmed \u003d payload.get(\"Medium\",0)\n\tlow \u003d payload.get(\"Low\",0)\n\tdiag \u003d payload.get(\"Diagnostic\",0)\n\t\n\ttotal \u003d critical + high + med + low + diag\n\tself.props.text \u003d total\n\t",
"sessionScope": false,
"viewScope": true
}
]
},
"type": "ia.display.label"
}
],
"meta": {
"name": "FlexContainer_1"
},
"position": {
"basis": "200px"
},
"props": {
"justify": "space-between"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "334px"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer_2"
},
"position": {
"basis": "80px"
},
"props": {
"style": {
"marginBottom": 5,
"marginLeft": 10,
"marginRight": 10
}
},
"type": "ia.container.flex"
}
],
"custom": {
"counts": {
"Critical": 0
}
},
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tself.session.custom.covert\u003d False\n\twhid \u003d self.session.custom.fc\n\tsession_id \u003d self.session.props.id\n\tpage_id \u003d \"Detailed-View: \" + self.view.params.tagProps[0]\n\tCommands.analytics.send_page_details(whid, session_id, page_id)\n\tnavigation.navigate_to_page.detailed_view(self, self.view.params.tagProps[0],self.view.params.tagProps[0], self.view.params.tagProps[3])"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"propConfig": {
"custom.Total": {
"binding": {
"config": {
"expression": "{view.params.Counts.High} + {view.params.Counts.Medium} + {view.params.Counts.Low} + {view.params.Counts.Diag}"
},
"type": "expr"
}
},
"custom.area": {
"binding": {
"config": {
"expression": "jsonGet({this.custom.plc_dict}, \"Area\")"
},
"type": "expr"
}
},
"custom.area_display": {
"binding": {
"config": {
"expression": "if(len({this.custom.sub_area})\u003e0,\r\nconcat({this.custom.area} + \"/\" + {this.custom.sub_area}),\r\n{this.custom.area})"
},
"type": "expr"
}
},
"custom.counts": {
"onChange": {
"enabled": null,
"script": "\tsystem.perspective.sendMessage(\"update-alarm-count\", self.custom.counts, \"view\")"
}
},
"custom.counts.Diagnostic": {
"binding": {
"config": {
"path": "view.params.Counts.Diag"
},
"type": "property"
}
},
"custom.counts.High": {
"binding": {
"config": {
"path": "view.params.Counts.High"
},
"type": "property"
}
},
"custom.counts.Low": {
"binding": {
"config": {
"path": "view.params.Counts.Low"
},
"type": "property"
}
},
"custom.counts.Medium": {
"binding": {
"config": {
"path": "view.params.Counts.Medium"
},
"type": "property"
}
},
"custom.plc_dict": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]Configuration/PLC"
},
"transforms": [
{
"expression": "jsonGet({value}, {view.params.tagProps[0]})",
"type": "expression"
}
],
"type": "tag"
}
},
"custom.provider": {
"binding": {
"config": {
"expression": "\"[\"+{session.custom.fc}+\"_SCADA_TAG_PROVIDER]\""
},
"type": "expr"
}
},
"custom.status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "if(isNull({value}), 0, {value})",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
}
},
"custom.sub_area": {
"binding": {
"config": {
"expression": "jsonGet({this.custom.plc_dict}, \"SubArea\")"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"expression": "if({session.custom.covert} \u003d False \u0026\u0026 {this.custom.status} \u003d 5, False, True)"
},
"type": "expr"
}
}
},
"props": {
"direction": "column",
"style": {
"animationFillMode": "both",
"borderBottomLeftRadius": 10,
"borderBottomRightRadius": 10,
"borderColor": "#555555",
"borderStyle": "solid",
"borderTopLeftRadius": 10,
"borderTopRightRadius": 10,
"borderWidth": 1,
"box-shadow": "5px 5px 5px grey",
"classes": "Background-Styles/Controller",
"cursor": "pointer"
}
},
"type": "ia.container.flex"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,727 @@
{
"custom": {
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running_status": 4,
"searchId": "value",
"state": 5,
"state_string": "Unknown",
"tag_path_to_lookup": "[\"value\"]"
},
"params": {
"directionLeft": false,
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"expression": "coalesce(try(jsonGet(jsonGet({session.custom.state_messages},{this.custom.tag_path_to_lookup}),\"state\"),null),{view.params.forceRunningStatus},4)"
},
"type": "expr"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.tag_path_to_lookup": {
"binding": {
"config": {
"expression": "\"[\\\"\" + {view.params.tagProps[0]} + \"\\\"]\""
},
"type": "expr"
},
"persistent": true
},
"params.directionLeft": {
"paramDirection": "input",
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 25,
"width": 40
}
},
"root": {
"children": [
{
"meta": {
"name": "Camera"
},
"position": {
"height": 1,
"width": 1,
"x": 0.0015,
"y": 0.0004
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "!{view.params.directionLeft}"
},
"type": "expr"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "M 0,0 H 39 V 24 H 0 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "M 34,17 26,12 34,7 Z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "M 9.7399998,7 H 25 V 17 H 9.7399998 Z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m 5,7 h 3 v 5 H 5 Z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
}
],
"style": {},
"viewBox": "-0.5 -0.5 40 25"
},
"type": "ia.shapes.svg"
},
{
"meta": {
"name": "Camera_Left"
},
"position": {
"height": 1,
"width": 1,
"x": 0.0015,
"y": 0.0004
},
"propConfig": {
"meta.visible": {
"binding": {
"config": {
"expression": "{view.params.directionLeft}"
},
"type": "expr"
}
},
"props.elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"d": "M 0,0 H 39 V 24 H 0 Z",
"fill": {},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m 31,7 h 3 v 5 h -3 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "M 13.74,7 H 29 V 17 H 13.74 Z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
},
{
"d": "m 5.556602,17 8,-5 -8,-5 z",
"fill": {
"paint": "#000000"
},
"name": "path",
"stroke": {
"paint": "#000000",
"width": 1
},
"type": "path"
}
],
"style": {},
"viewBox": "-0.5 -0.5 40 25"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "40:25",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,115 @@
{
"custom": {},
"params": {
"row": "value",
"rowIndex": "value",
"value": {
"Msg": "Mesg PlaceHolder",
"Timestamp": "TimeStamp Place holder"
}
},
"propConfig": {
"params.row": {
"paramDirection": "input",
"persistent": true
},
"params.rowIndex": {
"paramDirection": "input",
"persistent": true
},
"params.value": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 59,
"width": 891
}
},
"root": {
"children": [
{
"meta": {
"name": "Label_1"
},
"position": {
"basis": "147px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.value"
},
"transforms": [
{
"code": "\treturn value[\"Timestamp\"]",
"type": "script"
}
],
"type": "property"
}
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Label_2"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.value"
},
"transforms": [
{
"code": "\treturn value[\"Msg\"]",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"margin": "5px",
"padding": "5px"
},
"textStyle": {
"fontSize": 14,
"fontWeight": "100",
"overflow": "visible",
"overflowWrap": "break-word",
"wordWrap": "break-word"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"style": {
"backgroundColor": "#AAAAAA",
"borderBottomLeftRadius": "5px",
"borderBottomRightRadius": "5px",
"borderTopLeftRadius": "5px",
"borderTopRightRadius": "5px",
"color": "#000000",
"margin": "10px",
"padding": "5px"
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,954 @@
{
"custom": {
"data": "value"
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tproject_info \u003d system.perspective.getProjectInfo()\n\tviews \u003d project_info.get(\u0027views\u0027,[])\n\tfilter_criterion \u003d \"Symbol-Views\"\n\tfilter_criterion2 \u003d \"Symbol-Library-Views\"\n\tfilter_criterion3 \u003d \"Controller-Views\"\n\tfilter_criterion4 \u003d \"Device-Views\"\n\tfiltered_views \u003d [\n\t\tview for view in views \n\t\t\t\n\t\tif filter_criterion in view.get(\u0027path\u0027,\u0027\u0027) \n\t\tand not filter_criterion2 in view.get(\u0027path\u0027,\u0027\u0027) \n\t\tand not filter_criterion3 in view.get(\u0027path\u0027,\u0027\u0027)\n\t\tand not filter_criterion4 in view.get(\u0027path\u0027,\u0027\u0027)\n\t\t]\n\tjson_structure \u003d []\n\tfor view in filtered_views:\n\t\t\n\t\tif \u0027Test\u0027 not in view[\u0027path\u0027]:\n\t\t\tinstance \u003d {\n\t\t\t\t\"instanceStyle\": {\n\t\t\t\t\t\"classes\": \"\"\n\t\t\t\t},\n\t\t\t\t\"instancePosition\": {},\n\t\t\t\t\"Path\": view.get(\u0027path\u0027,\u0027\u0027),\n\t\t\t\t\"forceRunning\":3,\n\t\t\t\t\"forceFault\": None,\n\t\t\t\t\"has_state\":True\n\t\t\t}\n\t\t\tjson_structure.append(instance)\n\t\t\n\tjson_result \u003d system.util.jsonEncode(json_structure)\n\tself.params.Dataset \u003d filtered_views\n\tself.params.FilteredViews \u003d json_structure\n\tself.session.custom.alarm_filter.show_running \u003d True\n\tself.session.custom.alarm_filter.show_safety \u003d True\n\tself.session.custom.alarm_filter.show_diagnostic \u003d True\n\tself.session.custom.alarm_filter.show_gateways \u003d True\n\tself.session.custom.alarm_filter.show_low_alarm \u003d True\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"Dataset": [
{
"path": "Symbol-Views/Equipment-Views/ARSAW"
},
{
"path": "Symbol-Views/Equipment-Views/AUS"
},
{
"path": "Symbol-Views/Equipment-Views/Camera"
},
{
"path": "Symbol-Views/Equipment-Views/CognexCamera"
},
{
"path": "Symbol-Views/Equipment-Views/ControlCabinet"
},
{
"path": "Symbol-Views/Equipment-Views/Estop"
},
{
"path": "Symbol-Views/Equipment-Views/GoodsLift"
},
{
"path": "Symbol-Views/Equipment-Views/JAM"
},
{
"path": "Symbol-Views/Equipment-Views/Light_Curtain"
},
{
"path": "Symbol-Views/Equipment-Views/Main_Panel"
},
{
"path": "Symbol-Views/Equipment-Views/Network"
},
{
"path": "Symbol-Views/Equipment-Views/Pointer"
},
{
"path": "Symbol-Views/Equipment-Views/PressureSwitch"
},
{
"path": "Symbol-Views/Equipment-Views/PullChord"
},
{
"path": "Symbol-Views/Equipment-Views/PullChord_End"
},
{
"path": "Symbol-Views/Equipment-Views/PullChord_Line"
},
{
"path": "Symbol-Views/Equipment-Views/PullChord_Line_Vertical"
},
{
"path": "Symbol-Views/Equipment-Views/RFID"
},
{
"path": "Symbol-Views/Equipment-Views/Robot"
},
{
"path": "Symbol-Views/Equipment-Views/SLAMs"
},
{
"path": "Symbol-Views/Equipment-Views/SafetyGate"
},
{
"path": "Symbol-Views/Equipment-Views/Stacker_Destacker"
},
{
"path": "Symbol-Views/Equipment-Views/Status"
},
{
"path": "Symbol-Views/Equipment-Views/StatusNonPowered"
},
{
"path": "Symbol-Views/Equipment-Views/StatusNonPowered_NS"
},
{
"path": "Symbol-Views/Equipment-Views/Status_NS"
},
{
"path": "Symbol-Views/Equipment-Views/THEA"
},
{
"path": "Symbol-Views/Equipment-Views/Test"
}
],
"FilteredViews": [
{
"Path": "Symbol-Views/Equipment-Views/ARSAW",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/AUS",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Camera",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/CognexCamera",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/ControlCabinet",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Estop",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/GoodsLift",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/JAM",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Light_Curtain",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Main_Panel",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Network",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Pointer",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/PressureSwitch",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/PullChord",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/PullChord_End",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/PullChord_Line",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/PullChord_Line_Vertical",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/RFID",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Robot",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/SLAMs",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/SafetyGate",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Stacker_Destacker",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Status",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/StatusNonPowered",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/StatusNonPowered_NS",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/Status_NS",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
},
{
"Path": "Symbol-Views/Equipment-Views/THEA",
"forceFault": null,
"forceRunning": 3,
"has_state": true,
"instancePosition": {},
"instanceStyle": {
"classes": ""
}
}
]
},
"propConfig": {
"custom.data": {
"persistent": true
},
"params.Dataset": {
"paramDirection": "output"
},
"params.FilteredViews": {
"paramDirection": "output"
}
},
"props": {
"defaultSize": {
"height": 309,
"width": 378
},
"theme": "dark"
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Table"
},
"propConfig": {
"props.data[1].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state0"
},
"type": "property"
}
},
"props.data[2].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state5"
},
"type": "property"
}
},
"props.data[2].Color.style.color": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired}\u003d true, \u0027#000000\u0027,\u0027#FFFFFF\u0027) "
},
"type": "expr"
}
},
"props.data[4].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state5"
},
"type": "property"
}
},
"props.data[4].Color.style.color": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired}\u003d true, \u0027#000000\u0027,\u0027#FFFFFF\u0027) "
},
"type": "expr"
}
},
"props.data[5].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state4"
},
"type": "property"
}
},
"props.data[6].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state3"
},
"type": "property"
}
},
"props.data[7].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state2"
},
"type": "property"
}
},
"props.data[8].Color.style.backgroundColor": {
"binding": {
"config": {
"path": "session.custom.colours.state1"
},
"type": "property"
}
}
},
"props": {
"cells": {
"style": {
"paddingLeft": 5
}
},
"columns": [
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Color",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": ""
},
"justify": "auto",
"nullFormat": {
"includeNullStrings": false,
"nullFormatValue": "",
"strict": false
},
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": false,
"strictWidth": true,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": 85
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Description",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": ""
},
"justify": "auto",
"nullFormat": {
"includeNullStrings": false,
"nullFormatValue": "",
"strict": false
},
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": false,
"strictWidth": false,
"style": {
"borderLeftStyle": "solid",
"borderLeftWidth": 1,
"borderRightStyle": "solid",
"borderRightWidth": 1,
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": 100
}
],
"data": [
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"backgroundColor": "",
"borderBottomStyle": "solid",
"borderBottomWidth": 1,
"borderLeftStyle": "hidden",
"borderRightStyle": "hidden",
"classes": "",
"font-weight": "bold"
},
"value": "State"
},
"Description": {
"align": "center",
"editable": false,
"justify": "left",
"style": {
"backgroundColor": "",
"borderBottomStyle": "solid",
"borderBottomWidth": 1,
"borderLeftStyle": "hidden",
"classes": "some-class",
"font-weight": "bold"
},
"value": "Description"
}
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": "",
"color": "#000000"
},
"value": "Stopped"
},
"Description": "MHE is stopped (State2)"
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"value": "Running"
},
"Description": "MHE is running (State 3)"
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"backgroundColor": "",
"borderBottomStyle": "solid",
"borderBottomWidth": 1,
"borderLeftStyle": "hidden",
"borderRightStyle": "hidden",
"borderTopStyle": "solid",
"borderTopWidth": 1,
"classes": "",
"font-weight": "bold"
},
"value": "Priority"
},
"Description": {
"align": "center",
"editable": false,
"justify": "left",
"style": {
"backgroundColor": "",
"borderBottomStyle": "solid",
"borderBottomWidth": 1,
"borderLeftStyle": "hidden",
"borderTopStyle": "solid",
"borderTopWidth": 1,
"classes": "",
"font-weight": "bold"
},
"value": "Description"
}
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"value": "Healthy"
},
"Description": "Healthy, no active alarms"
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": "",
"color": "#000000"
},
"value": "Diagnostic"
},
"Description": "Diagnostic Information"
},
{
"Color": {
"align": "center",
"borderLeftColor": "white",
"justify": "left",
"style": {
"classes": "",
"color": "#000000"
},
"value": "Low"
},
"Description": "Running at reduced capacity",
"Status": "Low"
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"value": "Medium"
},
"Description": "Controlled Stop"
},
{
"Color": {
"align": "center",
"justify": "left",
"style": {
"classes": "some-class"
},
"value": "High"
},
"Description": "Uncontrolled Stop"
}
],
"dragOrderable": false,
"enableHeader": false,
"headerStyle": {
"backgroundColor": "#2B2B2B",
"color": "#FFFFFF",
"textIndent": "0px"
},
"pager": {
"bottom": false
},
"rows": {
"highlight": {
"color": "#FFFFFF",
"enabled": false
},
"style": {
"classes": "Background-Styles/Controller"
}
},
"selection": {
"enableRowSelection": false,
"style": {
"fontWeight": "bold"
}
}
},
"type": "ia.display.table"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "EmbeddedView"
},
"position": {
"basis": "320px"
},
"propConfig": {
"props.params.Dataset": {
"binding": {
"config": {
"path": "view.params.Dataset"
},
"type": "property"
}
},
"props.params.FilteredViews": {
"binding": {
"config": {
"path": "view.params.FilteredViews"
},
"type": "property"
}
}
},
"props": {
"path": "PopUp-Views/Legend_Popup/Legend-table"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer_6"
},
"position": {
"basis": "800px",
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"tabIndex": 1
},
"props": {
"direction": "column",
"style": {
"overflow": "visible"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "TabContainer"
},
"position": {
"basis": "1377px"
},
"propConfig": {
"props.tabs[0]": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired}\u003dTrue, \u0027Alt Color\u0027, \u0027Color\u0027)"
},
"type": "expr"
}
}
},
"props": {
"menuStyle": {
"fontWeight": "bold"
},
"style": {
"classes": "Background-Styles/Controller"
},
"tabs": [
null,
"Icons"
]
},
"type": "ia.container.tab"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"backgroundColor": "#3B3B3B",
"opacity": 1
}
},
"type": "ia.container.flex"
}
}

View File

@ -0,0 +1,614 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "Pin Detection"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"id": "defs1",
"name": "defs1",
"type": "defs"
},
{
"elements": [
{
"cx": "6.6145835",
"cy": "6.6145835",
"fill": {},
"id": "path1",
"name": "path1",
"r": "6.0570302",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264583"
},
"type": "circle"
},
{
"d": "M 1.4878915,9.8402065 9.8014876,1.4637334",
"fill": {
"paint": "transparent"
},
"id": "path2",
"name": "path2",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.264726"
},
"type": "path"
},
{
"d": "M 3.5515604,11.84005 11.75248,3.4068377",
"fill": {
"paint": "transparent"
},
"id": "path3",
"name": "path3",
"stroke": {
"dasharray": "none",
"paint": "#000000",
"width": "0.258089"
},
"type": "path"
}
],
"id": "layer1",
"name": "layer1",
"type": "group"
}
],
"style": {},
"viewBox": "0 0 13.229166 13.229167"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

View File

@ -0,0 +1,627 @@
{
"custom": {
"FillColour": "value",
"alarm_message": null,
"covert_mode": true,
"disconnected": false,
"display_icon": true,
"error": false,
"isMatch": 0,
"plc": "value",
"priority": 0,
"priority_string": "No active alarms",
"running": false,
"running_status": 0,
"searchId": "value",
"show_error": false,
"show_running": true,
"state": 5,
"state_string": "Unknown"
},
"params": {
"forceFaultStatus": null,
"forceRunningStatus": null,
"tagProps": [
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value",
"value"
]
},
"propConfig": {
"custom.FillColour": {
"persistent": true
},
"custom.alarm_message": {
"persistent": true
},
"custom.covert_mode": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t0, {session.custom.alarm_filter.show_running},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm} || {session.custom.alarm_filter.show_running},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic} || {session.custom.alarm_filter.show_running},\r\n\t\t5, {session.custom.alarm_filter.show_running},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.disconnected": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"fc": "{session.custom.fc}",
"plc": "{view.custom.plc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{plc}/DCN"
},
"transforms": [
{
"expression": "if(isNull({value}), False, {value})",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.display_icon": {
"binding": {
"config": {
"expression": "{this.custom.covert_mode}//||{this.custom.isMatch}\u003e0"
},
"type": "expr"
},
"persistent": true
},
"custom.error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "0 \u003c {value} \u0026\u0026 {value} \u003c 5",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.isMatch": {
"binding": {
"config": {
"expression": "if({view.params.tagProps[0]}\u003d\"value\",0,\nif({this.custom.searchId}\u003d{view.params.tagProps[0]},100,0))\n"
},
"type": "expr"
},
"persistent": true
},
"custom.plc": {
"binding": {
"config": {
"path": "view.params.tagProps[0]"
},
"transforms": [
{
"expression": "split({value}, \"/\")[0]",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"fallback": 0,
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": 4
},
{
"input": 2,
"output": 3
},
{
"input": 3,
"output": 2
},
{
"input": 4,
"output": 1
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
},
"persistent": true
},
"custom.priority_string": {
"binding": {
"config": {
"expression": "case({view.custom.state},\r\n1, \"High\",\r\n2, \"Medium\",\r\n3, \"Low\",\r\n4, \"Diagnostic\",\r\n5, \"No active alarms\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"custom.running": {
"binding": {
"config": {
"expression": "{view.custom.running_status} \u003d 3"
},
"type": "expr"
},
"persistent": true
},
"custom.running_status": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/STATE"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceRunningStatus},0)",
"type": "expression"
}
],
"type": "tag"
},
"persistent": true
},
"custom.searchId": {
"binding": {
"config": {
"path": "session.custom.searchId"
},
"type": "property"
},
"persistent": true
},
"custom.show_error": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, True,\r\n\t\t2, True,\r\n\t\t3, {session.custom.alarm_filter.show_low_alarm},\r\n\t\t4, {session.custom.alarm_filter.show_diagnostic},\r\n\t\tFalse)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.show_running": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case(\t{value},\r\n\t\t1, False,\r\n\t\t2, False,\r\n\t\t{session.custom.alarm_filter.show_running}\r\n\t\t)",
"type": "expression"
}
],
"type": "property"
},
"persistent": true
},
"custom.state": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"0": "{view.params.tagProps[0]}",
"fc": "{session.custom.fc}"
},
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/ALARMST"
},
"transforms": [
{
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
"type": "expression"
},
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": 4,
"output": 1
},
{
"input": 3,
"output": 2
},
{
"input": 2,
"output": 3
},
{
"input": 1,
"output": 4
},
{
"input": 0,
"output": 5
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "tag"
},
"persistent": true
},
"custom.state_string": {
"binding": {
"config": {
"expression": "case({view.custom.running_status},\r\n1, \"Faulted\",\r\n2, \"Stopped\",\r\n3, \"Running\",\r\n\"Unknown\")"
},
"type": "expr"
},
"persistent": true
},
"params.forceFaultStatus": {
"paramDirection": "input",
"persistent": true
},
"params.forceRunningStatus": {
"paramDirection": "input",
"persistent": true
},
"params.tagProps": {
"paramDirection": "inout",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 100,
"width": 100
}
},
"root": {
"children": [
{
"meta": {
"name": "Goods_Lift"
},
"position": {
"height": 1,
"width": 1
},
"propConfig": {
"props.elements[1].elements[0].elements[0].fill.paint": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,if({view.custom.running},{session.custom.colours.state5},{session.custom.colours.state0}),\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
},
{
"expression": "if({view.custom.display_icon}\u0026\u0026 {view.custom.isMatch}\u003d0,{value},{value}+\u002700\u0027)",
"type": "expression"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"expression": "if({session.custom.colours.colour_impaired} \u003d True \u0026\u0026 {view.custom.isMatch} \u003e 0,\r\n{view.custom.state} + 100 + {view.custom.isMatch},\r\n{view.custom.state} + {view.custom.isMatch})"
},
"transforms": [
{
"fallback": "",
"inputType": "scalar",
"mappings": [
{
"input": 101,
"output": "State-Styles/State101"
},
{
"input": 102,
"output": "State-Styles/State102"
},
{
"input": 103,
"output": "State-Styles/State103"
},
{
"input": 104,
"output": "State-Styles/State104"
},
{
"input": 105,
"output": "State-Styles/State105"
},
{
"input": 106,
"output": "State-Styles/State106"
},
{
"input": 201,
"output": "State-Styles/State201"
},
{
"input": 202,
"output": "State-Styles/State202"
},
{
"input": 203,
"output": "State-Styles/State203"
},
{
"input": 204,
"output": "State-Styles/State204"
},
{
"input": 205,
"output": "State-Styles/State205"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
}
},
"props": {
"elements": [
{
"id": "defs2",
"name": "defs2",
"type": "defs"
},
{
"elements": [
{
"elements": [
{
"cx": "69.035934",
"cy": "129.08073",
"fill": {},
"id": "path509",
"name": "path509",
"rx": "9.5693493",
"ry": "9.4979048",
"stroke": {
"dasharray": "none",
"linejoin": "round",
"paint": "#000000",
"width": 0.5
},
"style": {
"paintOrder": "stroke fill markers"
},
"type": "ellipse"
},
{
"d": "m 67.713019,128.18115 1.322917,-0.66146 1.322917,0.66146 v -3.06917 h -2.645834 z m -1.322916,3.54542 v -1.05833 h 2.645833 v 1.05833 z m -1.322918,2.11667 q -0.3175,0 -0.555625,-0.23812 -0.238125,-0.23813 -0.238125,-0.55563 v -7.93751 q 0,-0.3175 0.238125,-0.55562 0.238125,-0.23813 0.555625,-0.23813 h 7.937499 q 0.3175,0 0.55563,0.23813 0.23812,0.23812 0.23812,0.55562 v 7.93751 q 0,0.3175 -0.23812,0.55563 -0.23813,0.23812 -0.55563,0.23812 z m 0,-8.73126 v 7.93751 z m 0,7.93751 h 7.937499 v -7.93751 h -1.852081 v 4.3524 l -2.116667,-1.05834 -2.116666,1.05834 v -4.3524 h -1.852085 z",
"id": "path132",
"name": "path132",
"stroke": {
"dasharray": "none",
"width": 0
},
"type": "path"
},
{
"d": "m 66.429788,123.74768 -0.568854,-0.56885 3.175,-3.175 3.175,3.16177 -0.568855,0.56885 -2.606145,-2.60614 z",
"id": "path2154",
"name": "path2154",
"stroke": {
"width": 0.264583
},
"type": "path"
},
{
"d": "m 71.642074,134.41379 0.56886,0.56885 -3.175,3.175 -3.175,-3.16177 0.56885,-0.56885 2.60615,2.60614 z",
"id": "path2154-5",
"name": "path2154-5",
"stroke": {
"width": 0.264583
},
"type": "path"
}
],
"id": "g2552",
"name": "g2552",
"type": "group"
}
],
"id": "layer1",
"name": "layer1",
"transform": "translate(-58.814035,-118.93028)",
"type": "group"
}
],
"style": {},
"viewBox": "0 0 20.443798 20.300909"
},
"type": "ia.shapes.svg"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openDock(\u0027Docked-East\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
},
"scope": "G",
"type": "script"
},
"onDoubleClick": {
"config": {
"script": "\ttagProps \u003d self.view.params.tagProps\n\tsystem.perspective.openPopup(\"StatusPopUP\", \"PopUp-Views/Controller-Equipment/Information\", params \u003d{\"tagProps\":tagProps})\n\t"
},
"enabled": false,
"scope": "G",
"type": "script"
},
"onMouseEnter": {
"config": {
"script": "\tfrom time import sleep\n\t\n\talarm \u003d []\n\tmessage \u003d None\n\t\n\tsleep(0.5)\n\t\n\tif system.tag.exists(\"System/aws_data\"):\n\t\tif self.view.params.tagProps[0] !\u003d \"\":\n\t\t\ttags_to_read \u003d system.tag.readBlocking(\"System/aws_data\")\n\t\t\tdecode_alarm_data \u003d system.util.jsonDecode(tags_to_read[0].value)\n\t\t\talarm \u003d [decode_alarm_data[i] for i in decode_alarm_data\n\t\t\t\t\tif decode_alarm_data[i][\u0027sourceId\u0027].startswith(self.view.params.tagProps[0])]\n\t\tif alarm:\n\t\t\talarm \u003d sorted(alarm, key \u003d lambda t:t[\u0027timestamp\u0027], reverse\u003dTrue)\n\t\t\tmessage \u003d max(alarm, key \u003d lambda p:p[\u0027priority\u0027]).get(\u0027message\u0027)\n\t\t\tif len(alarm) \u003e 1:\n\t\t\t\tmessage +\u003d \" (+\" + str(len(alarm)-1) + \")\"\n\tself.view.custom.alarm_message \u003d message"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root",
"tooltip": {
"enabled": true,
"location": "top-left",
"style": {}
}
},
"propConfig": {
"meta.tooltip.style.backgroundColor": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "case({value},\r\n0,{session.custom.colours.state0},\r\n1,{session.custom.colours.state1},\r\n2,{session.custom.colours.state2},\r\n3,{session.custom.colours.state3},\r\n4,{session.custom.colours.state4},\r\n5,{session.custom.colours.state5},\r\n6,{session.custom.colours.state6},\r\n{session.custom.colours.fallback}\r\n)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.style.classes": {
"binding": {
"config": {
"expression": "{view.custom.priority}"
},
"transforms": [
{
"fallback": "Alarms-Styles/NoAlarm",
"inputType": "scalar",
"mappings": [
{
"input": 1,
"output": "Alarms-Styles/Diagnostic"
},
{
"input": 2,
"output": "Alarms-Styles/Low"
},
{
"input": 3,
"output": "Alarms-Styles/Medium"
},
{
"input": 4,
"output": "Alarms-Styles/High"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "expr"
}
},
"meta.tooltip.style.color": {
"binding": {
"config": {
"path": "view.custom.state"
},
"transforms": [
{
"expression": "if({session.custom.colours.colour_impaired},\r\n\t\u0027#000000\u0027,\r\n\tcase(\t{value},\r\n\t\t\t1,\u0027#FFFFFF\u0027,\r\n\t\t\t2,\u0027#000000\u0027,\r\n\t\t\t3,\u0027#000000\u0027,\r\n\t\t\t4,\u0027#FFFFFF\u0027,\r\n\t\t\t5,\u0027#FFFFFF\u0027,\r\n\t\t\t\u0027#000000\u0027)\r\n\t)",
"type": "expression"
}
],
"type": "property"
}
},
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "if({view.custom.disconnected} \u003d False,\n\tif(isNull({view.custom.alarm_message}),\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string},\n\t\"Source Id: \" + {view.params.tagProps[0]} +\n\t\", Alarm: \" + {view.custom.alarm_message} +\n\t\", Priority: \" + {view.custom.priority_string} +\n\t\", State: \" + {view.custom.state_string}),\n\"Source Id: \" +{view.params.tagProps[0]} + \", Priority: Unknown, State: Unknown\")"
},
"type": "expr"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.custom.disconnected"
},
"transforms": [
{
"fallback": "Disconnects/Device-Connected",
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "Disconnects/Device-Disconnected"
},
{
"input": false,
"output": "Disconnects/Device-Connected"
}
],
"outputType": "style-list",
"type": "map"
}
],
"type": "property"
}
}
},
"props": {
"aspectRatio": "1:1",
"mode": "percent",
"style": {
"cursor": "pointer"
}
},
"type": "ia.container.coord"
}
}

Some files were not shown because too many files have changed in this diff Show More