changes in the photoeyes, fixed jams werent showing in the mcm cards
@ -1,879 +0,0 @@
|
||||
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
|
||||
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 138 KiB |
@ -1,20 +0,0 @@
|
||||
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)
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
#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)
|
||||
|
||||
@ -5,11 +5,9 @@
|
||||
"MCM02",
|
||||
"MCM03",
|
||||
"MCM04",
|
||||
"MCM05",
|
||||
"MCM06",
|
||||
"MCM07"
|
||||
"MCM05"
|
||||
],
|
||||
"color": "#00FF00"
|
||||
"color": "#C2C2C2"
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
@ -212,7 +210,7 @@
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.closeDock(\u0027Docked-East-BTN\u0027)\n\tself.getSibling(\"tabs\").props.currentTabIndex \u003d 0"
|
||||
"script": "\tsystem.perspective.closeDock(\u0027Docked-East-EPC\u0027)\n\tself.getSibling(\"tabs\").props.currentTabIndex \u003d 0"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
@ -458,7 +456,7 @@
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "EPC LIGHT"
|
||||
"text": "STATUS"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
@ -472,54 +470,6 @@
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#D5D5D5",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "UNKNOWN",
|
||||
"output": "#FFFFFF"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.color"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "UNKNOWN",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "#FF0000",
|
||||
"output": "ON"
|
||||
},
|
||||
{
|
||||
"input": "#00FF00",
|
||||
"output": "OFF"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.textStyle.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.color"
|
||||
@ -532,6 +482,9 @@
|
||||
"style": {
|
||||
"classes": "Text-Styles/Ariel-Bold-12pt",
|
||||
"paddingLeft": 10
|
||||
},
|
||||
"textStyle": {
|
||||
"color": "#000000"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
@ -586,6 +539,7 @@
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"currentTabIndex": 1,
|
||||
"menuType": "modern",
|
||||
"tabSize": {
|
||||
"width": 1000
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"custom": {
|
||||
"MCM": "",
|
||||
"currentTable": "HISTORY",
|
||||
"currentTable": "HITLIST",
|
||||
"page": "",
|
||||
"view": ""
|
||||
},
|
||||
@ -1022,6 +1022,10 @@
|
||||
"type": "ia.display.table"
|
||||
},
|
||||
{
|
||||
"custom": {
|
||||
"endTime": "value",
|
||||
"startTime": "value"
|
||||
},
|
||||
"events": {
|
||||
"component": {
|
||||
"onRowDoubleClick": {
|
||||
@ -3166,9 +3170,18 @@
|
||||
"position": {
|
||||
"basis": "150px"
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({view.custom.currentTable}\u003d\"ACTIVE\", \"#C3C3C3\", \"#FFFFFF\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#F0F0F0",
|
||||
"borderStyle": "none",
|
||||
"color": "#000000"
|
||||
},
|
||||
@ -3194,9 +3207,18 @@
|
||||
"position": {
|
||||
"basis": "150px"
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({view.custom.currentTable}\u003d\"HITLIST\", \"#C3C3C3\", \"#FFFFFF\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#F0F0F0",
|
||||
"borderStyle": "none",
|
||||
"color": "#000000"
|
||||
},
|
||||
@ -3222,9 +3244,18 @@
|
||||
"position": {
|
||||
"basis": "150px"
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({view.custom.currentTable}\u003d\"HISTORY\", \"#C3C3C3\", \"#FFFFFF\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#F0F0F0",
|
||||
"borderStyle": "none",
|
||||
"color": "#000000"
|
||||
},
|
||||
@ -1,96 +0,0 @@
|
||||
# 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
|
||||
@ -1,65 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 41 KiB |
@ -1,11 +0,0 @@
|
||||
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])
|
||||
|
||||
@ -1,294 +0,0 @@
|
||||
{
|
||||
"custom": {
|
||||
"color": "#000000",
|
||||
"priority": "No Active Alarms",
|
||||
"state": "TagError"
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
"Status/Chutes/Chute_0",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tdata \u003d dict(value) if value else {}\n\t\n\tif data.get(\"bLamp_Enable\"):\n\t return \"#CCFFCC\" \n\treturn \"#000000\"",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.priority": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tdata \u003d dict(value) if value else {}\n\t\n\tif data.get(\"bLamp_Enable\"):\n\t return \"Low\" \n\treturn \"No Active Alarms\"",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"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}/"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tdata \u003d dict(value) if value else {}\n\t\t\n\tif value is None or data.get(\"_quality\") \u003d\u003d \"Bad\" or data.get(\"error\"):\n\t return \"TagError\"\n\tif data.get(\"bLamp_Enable\"):\n\t return \"Enable PB Pressed\" \n\treturn \"Inactive\"",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 25,
|
||||
"width": 25
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
},
|
||||
"position": {
|
||||
"height": 1,
|
||||
"width": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.elements[1].fill.paint": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n {view.custom.state} \u003d \"Closed\",\r\n \"#000000\",\r\n {view.custom.color}\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.style.classes": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({session.custom.colours.colour_impaired} \u003d True,\r\n{view.custom.state} + 100,\r\n{view.custom.state})"
|
||||
},
|
||||
"enabled": false,
|
||||
"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 20 V 20 H 0 Z",
|
||||
"fill": {
|
||||
"paint": "#AAAAAA"
|
||||
},
|
||||
"name": "path",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "1.5"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"d": "m 17,10.5 a 7,7 0 0 1 -7,7 7,7 0 0 1 -7,-7 7,7 0 0 1 7,-7 7,7 0 0 1 7,7 z",
|
||||
"fill": {},
|
||||
"name": "path",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "1"
|
||||
},
|
||||
"type": "path"
|
||||
}
|
||||
],
|
||||
"viewBox": "0 0 20 20"
|
||||
},
|
||||
"type": "ia.shapes.svg"
|
||||
}
|
||||
],
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.openDock(\u0027Docked-East-CHPB\u0027,params\u003d{\u0027tagProps\u0027:self.view.params.tagProps})"
|
||||
},
|
||||
"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,
|
||||
"style": {}
|
||||
}
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.style.classes": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "{view.custom.priority}"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "Alarms-Styles/NoAlarm",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": "Alarms-Styles/High"
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": "Alarms-Styles/Medium"
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": "Alarms-Styles/Low"
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": "Alarms-Styles/Diagnostic"
|
||||
}
|
||||
],
|
||||
"outputType": "style-list",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\n {view.custom.state} !\u003d \"TagError\",\n \"Source Id: \" + {view.params.tagProps[0]} + \", Priority: \" + {view.custom.priority} + \", State: \" + {view.custom.state},\n \"Device Disconnected\"\n)\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.visible": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "session.custom.alarm_filter.show_buttons"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"mode": "percent",
|
||||
"style": {
|
||||
"cursor": "pointer"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.coord"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 93 KiB |
@ -1,21 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
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)
|
||||
@ -1,431 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
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
|
||||
@ -1,211 +0,0 @@
|
||||
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])
|
||||
@ -1,141 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -5,12 +5,10 @@
|
||||
"MCM02",
|
||||
"MCM03",
|
||||
"MCM04",
|
||||
"MCM05",
|
||||
"MCM06",
|
||||
"MCM07"
|
||||
"MCM05"
|
||||
],
|
||||
"start_color": "#00FF00",
|
||||
"stop_color": "#B43434"
|
||||
"start_color": "#C2C2C2",
|
||||
"stop_color": "#C2C2C2"
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
@ -624,7 +622,7 @@
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "if({value}\u003d4, \"ON\", \"OFF\")",
|
||||
"expression": "if(isGood({value}),\r\n if({value} \u003d 4, \"ON\", \"OFF\"),\r\n \"UNKNOWN\"\r\n)\r\n",
|
||||
"type": "expression"
|
||||
}
|
||||
],
|
||||
@ -643,7 +641,7 @@
|
||||
"mappings": [
|
||||
{
|
||||
"input": "ON",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
},
|
||||
{
|
||||
"input": "OFF",
|
||||
@ -727,13 +725,24 @@
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
"name": "Button",
|
||||
"tooltip": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({this.props.enabled},{this.props.text} +\u0027 Button\u0027,\"You do not have Maintenance or Administrator role!\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -794,13 +803,24 @@
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
"name": "Button",
|
||||
"tooltip": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({this.props.enabled},{this.props.text} +\u0027 Button\u0027,\"You do not have Maintenance or Administrator role!\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -1,296 +0,0 @@
|
||||
{
|
||||
"custom": {
|
||||
"activityLogger": {
|
||||
"alt_pageid": "card_view",
|
||||
"start_time": {
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1754319546004
|
||||
],
|
||||
"$ts": 1754319545822
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"page_name": "Home"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"params.page_name": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 1080,
|
||||
"width": 1920
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "FlexRepeater"
|
||||
},
|
||||
"position": {
|
||||
"basis": "1080px"
|
||||
},
|
||||
"props": {
|
||||
"alignContent": "flex-start",
|
||||
"alignItems": "flex-start",
|
||||
"elementPosition": {
|
||||
"grow": 0,
|
||||
"shrink": 0
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
"Counts": {
|
||||
"Diag": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
},
|
||||
"area": "Bulk Inbound",
|
||||
"instancePosition": {},
|
||||
"instanceStyle": {
|
||||
"classes": "",
|
||||
"margin": "5px"
|
||||
},
|
||||
"subarea": "",
|
||||
"tagProps": [
|
||||
"MCM05",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Counts": {
|
||||
"Diag": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
},
|
||||
"area": "Fluid Inbound",
|
||||
"instancePosition": {},
|
||||
"instanceStyle": {
|
||||
"classes": "",
|
||||
"margin": "5px"
|
||||
},
|
||||
"subarea": "",
|
||||
"tagProps": [
|
||||
"MCM04",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Counts": {
|
||||
"Diag": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
},
|
||||
"area": "Fluid Inbound",
|
||||
"instancePosition": {},
|
||||
"instanceStyle": {
|
||||
"classes": "",
|
||||
"margin": "5px"
|
||||
},
|
||||
"subarea": "",
|
||||
"tagProps": [
|
||||
"MCM03",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Counts": {
|
||||
"Diag": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
},
|
||||
"area": "Sorter Destination and Chutes",
|
||||
"instancePosition": {},
|
||||
"instanceStyle": {
|
||||
"classes": "",
|
||||
"margin": "5px"
|
||||
},
|
||||
"subarea": "",
|
||||
"tagProps": [
|
||||
"MCM02",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Counts": {
|
||||
"Diag": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
},
|
||||
"area": "Sorter Destination, Chutes and Bypass",
|
||||
"instancePosition": {},
|
||||
"instanceStyle": {
|
||||
"classes": "",
|
||||
"margin": "5px"
|
||||
},
|
||||
"subarea": "",
|
||||
"tagProps": [
|
||||
"MCM01",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
],
|
||||
"path": "Symbol-Views/Controller-Views/ControllerStatus",
|
||||
"style": {
|
||||
"overflow": "visible"
|
||||
},
|
||||
"wrap": "wrap"
|
||||
},
|
||||
"type": "ia.display.flex-repeater"
|
||||
}
|
||||
],
|
||||
"custom": {
|
||||
"Devices": [
|
||||
[
|
||||
"MCM01",
|
||||
"Bulk Inbound"
|
||||
],
|
||||
[
|
||||
"MCM02",
|
||||
"Fluid Inbound"
|
||||
],
|
||||
[
|
||||
"MCM03",
|
||||
"Fluid Inbound"
|
||||
],
|
||||
[
|
||||
"MCM05",
|
||||
"Sorter Destination and Chutes"
|
||||
],
|
||||
[
|
||||
"MCM04",
|
||||
"Sorter Destination, Chutes and Bypass"
|
||||
]
|
||||
],
|
||||
"count": "value",
|
||||
"delay": 2000,
|
||||
"run_update": true
|
||||
},
|
||||
"events": {
|
||||
"system": {
|
||||
"onStartup": [
|
||||
{
|
||||
"config": {
|
||||
"script": "\tVisualisation.home_page.create_home_page(self)"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
},
|
||||
{
|
||||
"config": {
|
||||
"script": "\twhid \u003d self.session.custom.fc\n\tsession_id \u003d self.session.props.id\n\tpage_id \u003d self.view.params.page_name\n\tCommands.analytics.send_page_details(whid, session_id, page_id)"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "root"
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.update": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "now({this.custom.delay})"
|
||||
},
|
||||
"type": "expr"
|
||||
},
|
||||
"onChange": {
|
||||
"enabled": null,
|
||||
"script": "\n if (self.session.custom.fc \u003d\u003d \u0027\u0027) or (self.session.custom.fc is None):\n \tself.getChild(\"FlexRepeater\").props.instances \u003d []\n \treturn\n \n if self.custom.run_update:\n \tVisualisation.home_page.update_home_status(self)\n# system_tags \u003d system.tag.readBlocking([\"Configuration/FC\", \"System/ActiveAlarms\"])\n# tag_provider \u003d \"[%s_SCADA_TAG_PROVIDER]\" % (system_tags[0].value)\n# status_decoded \u003d system.util.jsonDecode(self.session.custom.id_to_state)\n# if status_decoded:\n#\t values \u003d []\n#\t devices \u003d self.custom.Devices\n#\t for i in devices:\n#\t \tvalue \u003d status_decoded.get(i)\n#\t \tif value \u003d\u003d None:\n#\t \t\tvalues.append(5)\n#\t \telse:\n#\t \t\tvalues.append(value)\n#\t zipped_list \u003d zip(values, devices)\n#\t devices_sorted \u003d [y for x,y in sorted(zipped_list)]\n#\t for i,j in enumerate(devices_sorted):\n#\t try:\n#\t \tself.getChild(\"FlexRepeater\").props.instances[i].tagProps[0] \u003d j\n#\t except:\n#\t \tsystem.perspective.print(i)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 80 KiB |
@ -1,44 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,659 +0,0 @@
|
||||
{
|
||||
"custom": {
|
||||
"PLC_list": [
|
||||
"MCM01",
|
||||
"MCM02",
|
||||
"MCM03",
|
||||
"MCM04",
|
||||
"MCM05"
|
||||
],
|
||||
"button_type": "UNKNOWN",
|
||||
"type": 1
|
||||
},
|
||||
"params": {
|
||||
"forceFaultStatus": null,
|
||||
"tagProps": [
|
||||
"System/MCM06/Chute/NC/S02_203CH",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.PLC_list": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]Configuration/PLC"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tdevices \u003d system.util.jsonDecode(value)\n\tplcList \u003d []\n\tfor k in devices.keys():\n\t\tplcList.append(k)\n\t\t\n\treturn(sorted(set(plcList)))\n",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.button_type": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Button_Type"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "UNKNOWN",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 5,
|
||||
"output": "Chute_JR"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "GS"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "PR"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "Start"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "JR"
|
||||
},
|
||||
{
|
||||
"input": 6,
|
||||
"output": "Enable"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.type": {
|
||||
"persistent": true
|
||||
},
|
||||
"params.forceFaultStatus": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"width": 400
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Label"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "\u0027Source ID: \u0027 + {view.params.tagProps[0]}"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"color": "#FFFF",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.closeDock(\u0027Docked-East-CHPB\u0027)\n\tself.getSibling(\"tabs\").props.currentTabIndex \u003d 0"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Icon",
|
||||
"tooltip": {
|
||||
"enabled": true,
|
||||
"style": {
|
||||
"cursor": "pointer"
|
||||
},
|
||||
"text": "Close faceplate"
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"path": "material/close",
|
||||
"style": {
|
||||
"cursor": "pointer",
|
||||
"marginBottom": 5,
|
||||
"marginLeft": 5,
|
||||
"marginRight": 5,
|
||||
"marginTop": 5
|
||||
}
|
||||
},
|
||||
"type": "ia.display.icon"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer"
|
||||
},
|
||||
"position": {
|
||||
"basis": "30px",
|
||||
"shrink": 0
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"overflow": "hidden"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Label"
|
||||
},
|
||||
"position": {
|
||||
"basis": "32px",
|
||||
"display": false
|
||||
},
|
||||
"propConfig": {
|
||||
"position.display": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({../AlarmTable.props.params.length_of_table_data} \u003d 0, True, False)"
|
||||
},
|
||||
"enabled": false,
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "Labels/Label_1",
|
||||
"marginTop": 20
|
||||
},
|
||||
"text": "No Active Alarms"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "AlarmStatusTable"
|
||||
},
|
||||
"position": {
|
||||
"basis": "400px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.filters.active.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\treturn value[1:]",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"columns": {
|
||||
"active": {
|
||||
"displayPath": {
|
||||
"enabled": false
|
||||
},
|
||||
"priority": {
|
||||
"enabled": false
|
||||
},
|
||||
"source": {
|
||||
"enabled": false
|
||||
},
|
||||
"state": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"active": {
|
||||
"priorities": {
|
||||
"critical": false,
|
||||
"high": false,
|
||||
"low": false,
|
||||
"medium": false
|
||||
},
|
||||
"states": {
|
||||
"clearUnacked": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"refreshRate": 500,
|
||||
"toolbar": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"type": "ia.display.alarmstatustable"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Active_tab"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Name"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "NAME"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "DeviceName"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": " return value.rsplit(\u0027/\u0027, 1)[-1]",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"classes": "Text-Styles/Ariel-Bold-12pt",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Property"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel",
|
||||
"overflow": "hidden"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Name"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Info_tab"
|
||||
},
|
||||
"position": {
|
||||
"tabIndex": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"margin-left": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"events": {
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttag_name \u003d self.view.params.tagProps[0]\n\ttag_path \u003d \"[\" + self.session.custom.fc+ \"_SCADA_TAG_PROVIDER]\"+tag_name+\"/Commands/bBlockHost1\"\n\tsystem.tag.writeBlocking([tag_path],[True])"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"image": {
|
||||
"icon": {
|
||||
"color": "#0B0B0B"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"backgroundColor": "#00FF00",
|
||||
"classes": "Background-Styles/Controller"
|
||||
},
|
||||
"text": "ENABLE",
|
||||
"textStyle": {
|
||||
"color": "#FFFFFF"
|
||||
}
|
||||
},
|
||||
"type": "ia.input.button"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Enable"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel",
|
||||
"padding": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"events": {
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttag_name \u003d self.view.params.tagProps[0]\n\ttag_path \u003d \"[\" + self.session.custom.fc+ \"_SCADA_TAG_PROVIDER]\"+tag_name+\"/Commands/bUnblockHost1\"\n\tsystem.tag.writeBlocking([tag_path],[True])"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"image": {
|
||||
"icon": {
|
||||
"color": "#0B0B0B"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"backgroundColor": "#FF0000",
|
||||
"classes": "Background-Styles/Controller"
|
||||
},
|
||||
"text": "DISABLE",
|
||||
"textStyle": {
|
||||
"color": "#FFFFFF"
|
||||
}
|
||||
},
|
||||
"type": "ia.input.button"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Disable"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel",
|
||||
"padding": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_0"
|
||||
},
|
||||
"position": {
|
||||
"basis": "100px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"gap": 6,
|
||||
"paddingBottom": 20,
|
||||
"paddingLeft": 10,
|
||||
"paddingRight": 10,
|
||||
"paddingTop": 13
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Commands_tab"
|
||||
},
|
||||
"position": {
|
||||
"tabIndex": 2
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"paddingTop": 1
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "tabs"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.tabs": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.type"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\t# This script runs whenever view.custom.type changes\n\tif value \u003d\u003d 0 or value \u003d\u003d 3:\n\t\treturn [\"Alarms\", \"Info\"]\n\telse:\n\t\treturn [\"Alarms\", \"Info\", \"Commands\"]",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"currentTabIndex": 2,
|
||||
"menuType": "modern",
|
||||
"tabSize": {
|
||||
"width": 1000
|
||||
},
|
||||
"tabStyle": {
|
||||
"active": {
|
||||
"classes": "",
|
||||
"color": "#FFFFFF",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
},
|
||||
"inactive": {
|
||||
"classes": "",
|
||||
"color": "#B8B8B8",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "ia.container.tab"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_1"
|
||||
},
|
||||
"position": {
|
||||
"basis": "670px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"border-top": "1px solid white",
|
||||
"gap": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer"
|
||||
},
|
||||
"position": {
|
||||
"basis": "800px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "root"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"classes": "Buttons/Button-Menu"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@
|
||||
"params": {
|
||||
"forceFaultStatus": null,
|
||||
"tagProps": [
|
||||
"System/MCM06/Chute/NC/S02_203CH",
|
||||
"System/MCM01/PE/ULC1_4_TPE1",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
@ -415,11 +415,20 @@
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n indexOf({view.params.tagProps[0]}, \"TPE\") \u003e\u003d 0\r\n || indexOf({view.params.tagProps[0]}, \"JPE\") \u003e\u003d 0,\r\n \"JAM\",\r\n \"FULL\"\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "FULL"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
@ -443,11 +452,11 @@
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "FULL",
|
||||
"input": "TRUE",
|
||||
"output": "#D5D5D5"
|
||||
},
|
||||
{
|
||||
"input": "NOT FULL",
|
||||
"input": "FALSE",
|
||||
"output": "#D5D5D5"
|
||||
}
|
||||
],
|
||||
@ -461,37 +470,15 @@
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Alarm/Full"
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\"UNKNOWN\")",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "UNKNOWN",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 1,
|
||||
"output": "FULL"
|
||||
},
|
||||
{
|
||||
"input": 0,
|
||||
"output": "NOT FULL"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
"code": "\tprovider \u003d self.session.custom.fc + \"_SCADA_TAG_PROVIDER\"\n\tbaseTag \u003d self.view.params.tagProps[0]\n\tbasePath \u003d \"[\" + provider + \"]\" + baseTag\n\t\n\t# Choose correct alarm type based on tag name\n\tif \"TPE\" in baseTag or \"JPE\" in baseTag:\n\t fullPath \u003d basePath + \"/Alarm/Jammed\"\n\telse:\n\t fullPath \u003d basePath + \"/Alarm/Full\"\n\t\n\t# Read tag value\n\ttag \u003d system.tag.readBlocking([fullPath])[0]\n\t\n\t# Return \"TRUE\"/\"FALSE\" as string\n\tif not tag.quality.isGood():\n\t return \"UNKNOWN\"\n\t\n\tif bool(tag.value):\n\t return \"TRUE\"\n\telse:\n\t return \"FALSE\"",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.textStyle.color": {
|
||||
@ -505,12 +492,12 @@
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "FULL",
|
||||
"output": "#0008FF"
|
||||
"input": "TRUE",
|
||||
"output": "#FF1000"
|
||||
},
|
||||
{
|
||||
"input": "NOT FULL",
|
||||
"output": "#47FF47"
|
||||
"input": "FALSE",
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -638,6 +625,14 @@
|
||||
{
|
||||
"input": 0,
|
||||
"output": "NOT JAMMED"
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": "JAMMED"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "NOT JAMMED"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
@ -663,7 +658,7 @@
|
||||
},
|
||||
{
|
||||
"input": "NOT JAMMED",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -837,6 +832,14 @@
|
||||
{
|
||||
"input": 0,
|
||||
"output": "FALSE"
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": "TRUE"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "FALSE"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
@ -862,7 +865,7 @@
|
||||
},
|
||||
{
|
||||
"input": "FALSE",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -1032,6 +1035,14 @@
|
||||
{
|
||||
"input": 0,
|
||||
"output": "NOT HALF FULL"
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": "TRUE"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "NOT HALF FULL"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
@ -1057,7 +1068,7 @@
|
||||
},
|
||||
{
|
||||
"input": "NOT HALF FULL",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -1231,6 +1242,14 @@
|
||||
{
|
||||
"input": 0,
|
||||
"output": "CONTAINER PRESENT"
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": "NO CONTAINER"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "CONTAINER PRESENT"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
@ -1256,7 +1275,7 @@
|
||||
},
|
||||
{
|
||||
"input": "CONTAINER PRESENT",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -1435,11 +1454,11 @@
|
||||
"mappings": [
|
||||
{
|
||||
"input": "READY",
|
||||
"output": "#92FF00"
|
||||
"output": "#008000"
|
||||
},
|
||||
{
|
||||
"input": "ENABLED",
|
||||
"output": "#47FF47"
|
||||
"output": "#008000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
@ -1553,13 +1572,24 @@
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button"
|
||||
"name": "Button",
|
||||
"tooltip": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({this.props.enabled},{this.props.text} +\u0027 Button\u0027,\"You do not have Maintenance or Administrator role!\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -1847,6 +1877,7 @@
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"currentTabIndex": 1,
|
||||
"menuType": "modern",
|
||||
"tabSize": {
|
||||
"width": 1000
|
||||
@ -0,0 +1,947 @@
|
||||
{
|
||||
"custom": {
|
||||
"PLC_list": [
|
||||
"MCM01",
|
||||
"MCM02",
|
||||
"MCM03",
|
||||
"MCM04",
|
||||
"MCM05"
|
||||
],
|
||||
"running_state": -1,
|
||||
"state": 0,
|
||||
"views_data": []
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
"System/MCM04/Station/Chute_JR/FL1038_2_JR1",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.PLC_list": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]Configuration/PLC"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tdevices \u003d system.util.jsonDecode(value)\n\tplcList \u003d []\n\tfor k in devices.keys():\n\t\tplcList.append(k)\n\t\t\n\treturn(sorted(set(plcList)))\n",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.running_state": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "try(jsonGet({session.custom.state_messages},{this.custom.tag_path_to_lookup}),-1)\t\r\n"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "if({value} !\u003d -1, try(jsonGet({value},\"state\"),4),{value})",
|
||||
"type": "expression"
|
||||
}
|
||||
],
|
||||
"type": "expr"
|
||||
},
|
||||
"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}/STATE"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "if(isNull({value}), 0, {value})",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": null,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 3,
|
||||
"output": 3
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": 2
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": 1
|
||||
},
|
||||
{
|
||||
"input": 0,
|
||||
"output": 0
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.views_data": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"struct": {
|
||||
"equipment_id": "{view.params.tagProps[0]}"
|
||||
},
|
||||
"waitOnAll": true
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tproject_info \u003d system.perspective.getProjectInfo()\n\t#self.custom.views_data \u003d project_info\n\tviews \u003d project_info.get(\"views\")\n\t#equipment_id \u003d self.view.params.tagProps[0]\n\tviews_data \u003d [i for i in views if i[\"path\"].startswith(\"Custom-Views/\"+ value.equipment_id)]\n\t#self.custom.views_data \u003d views_data\n\t\n\treturn views_data",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "expr-struct"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"width": 400
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Label"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "\u0027Source ID: \u0027 + {view.params.tagProps[0]}"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"color": "#FFFF",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.closeDock(\u0027Docked-Eas-TPR\u0027)\n\tself.getSibling(\"tabs\").props.currentTabIndex \u003d 0"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Icon",
|
||||
"tooltip": {
|
||||
"enabled": true,
|
||||
"style": {
|
||||
"cursor": "pointer"
|
||||
},
|
||||
"text": "Close faceplate"
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"path": "material/close",
|
||||
"style": {
|
||||
"cursor": "pointer",
|
||||
"marginBottom": 5,
|
||||
"marginLeft": 5,
|
||||
"marginRight": 5,
|
||||
"marginTop": 5
|
||||
}
|
||||
},
|
||||
"type": "ia.display.icon"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer"
|
||||
},
|
||||
"position": {
|
||||
"basis": "30px",
|
||||
"shrink": 0
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"overflow": "hidden"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Label"
|
||||
},
|
||||
"position": {
|
||||
"basis": "32px",
|
||||
"display": false
|
||||
},
|
||||
"propConfig": {
|
||||
"position.display": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({../AlarmTable.props.params.length_of_table_data} \u003d 0, True, False)"
|
||||
},
|
||||
"enabled": false,
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "Labels/Label_1",
|
||||
"marginTop": 20
|
||||
},
|
||||
"text": "No Active Alarms"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "AlarmStatusTable"
|
||||
},
|
||||
"position": {
|
||||
"basis": "400px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.filters.active.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\treturn value[1:]",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"columns": {
|
||||
"active": {
|
||||
"displayPath": {
|
||||
"enabled": false
|
||||
},
|
||||
"priority": {
|
||||
"enabled": false
|
||||
},
|
||||
"source": {
|
||||
"enabled": false
|
||||
},
|
||||
"state": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"active": {
|
||||
"priorities": {
|
||||
"critical": false,
|
||||
"high": false,
|
||||
"low": false,
|
||||
"medium": false
|
||||
},
|
||||
"states": {
|
||||
"clearUnacked": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"refreshRate": 500,
|
||||
"toolbar": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"type": "ia.display.alarmstatustable"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Active_tab"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "NameField"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "NAME"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "DeviceName"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": " return value.rsplit(\u0027/\u0027, 1)[-1]",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"classes": "Text-Styles/Ariel-Bold-12pt",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Name"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel",
|
||||
"overflow": "hidden"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_0"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "NameField"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "TIPPER FAULTED"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "PB_Light"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#D5D5D5",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "UNKNOWN",
|
||||
"output": "#FFFFFF"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Alarm/Tipper_Faulted"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\"UNKNOWN\")",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "UNKNOWN",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": true,
|
||||
"output": "FAULTED"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "NOT FAULTED"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
},
|
||||
"props.textStyle.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "NOT FAULTED",
|
||||
"output": "#008000"
|
||||
},
|
||||
{
|
||||
"input": "FAULTED",
|
||||
"output": "#FF0000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "Text-Styles/Ariel-Bold-12pt",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Name"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px",
|
||||
"shrink": 2
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_1"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "NameField"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
},
|
||||
"text": "DUMPING"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "PB_Light"
|
||||
},
|
||||
"position": {
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#D5D5D5",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "UNKNOWN",
|
||||
"output": "#FFFFFF"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Alarm/Dumping"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\"UNKNOWN\")",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "UNKNOWN",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": true,
|
||||
"output": "TRUE"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "FALSE"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
},
|
||||
"props.textStyle.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.props.text"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "FALSE",
|
||||
"output": "#008000"
|
||||
},
|
||||
{
|
||||
"input": "TRUE",
|
||||
"output": "#FF0000"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "Text-Styles/Ariel-Bold-12pt",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Name"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px",
|
||||
"shrink": 2
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_2"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Info_tab"
|
||||
},
|
||||
"position": {
|
||||
"tabIndex": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"margin-left": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"events": {
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttag_name \u003d self.view.params.tagProps[0]\n\ttag_path \u003d \"[\" + self.session.custom.fc+ \"_SCADA_TAG_PROVIDER]\"+tag_name+\"/Enable_PB\"\n\tsystem.tag.writeBlocking([tag_path],[True])"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button",
|
||||
"tooltip": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"basis": "80px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({this.props.enabled},{this.props.text} +\u0027 Button\u0027,\"You do not have Maintenance or Administrator role!\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.style.backgroundColor": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n {this.props.enabled} \u003d False,\r\n \"#B17B50\",\r\n if(\r\n {this.props.text} \u003d \"ENABLED\",\r\n \"#00FF00\",\r\n if(\r\n {this.props.text} \u003d \"DISABLED\",\r\n \"#FF0000\",\r\n \"#FFFFFF\"\r\n )\r\n )\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Enable_PB"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "DISABLE",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 1,
|
||||
"output": "ENABLE"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"image": {
|
||||
"icon": {
|
||||
"path": "material/sync_problem"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"classes": "Background-Styles/Controller"
|
||||
}
|
||||
},
|
||||
"type": "ia.input.button"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Reset Jam"
|
||||
},
|
||||
"position": {
|
||||
"basis": "35px"
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"classes": "PopUp-Styles/InfoLabel",
|
||||
"padding": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_0"
|
||||
},
|
||||
"position": {
|
||||
"basis": "100px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"gap": 6,
|
||||
"paddingBottom": 20,
|
||||
"paddingLeft": 10,
|
||||
"paddingRight": 10,
|
||||
"paddingTop": 13
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "Commands_tab"
|
||||
},
|
||||
"position": {
|
||||
"tabIndex": 2
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"paddingTop": 1
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "tabs"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"currentTabIndex": 2,
|
||||
"menuType": "modern",
|
||||
"tabSize": {
|
||||
"width": 1000
|
||||
},
|
||||
"tabStyle": {
|
||||
"active": {
|
||||
"classes": "",
|
||||
"color": "#FFFFFF",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
},
|
||||
"inactive": {
|
||||
"classes": "",
|
||||
"color": "#B8B8B8",
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"fontWeight": "bold",
|
||||
"paddingLeft": 10
|
||||
}
|
||||
},
|
||||
"tabs": [
|
||||
"Alarms",
|
||||
"Info",
|
||||
"Commands"
|
||||
]
|
||||
},
|
||||
"type": "ia.container.tab"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_1"
|
||||
},
|
||||
"position": {
|
||||
"basis": "670px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"border-top": "1px solid white",
|
||||
"gap": ""
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer"
|
||||
},
|
||||
"position": {
|
||||
"basis": "800px",
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"direction": "column"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "root"
|
||||
},
|
||||
"props": {
|
||||
"direction": "column",
|
||||
"style": {
|
||||
"classes": "Buttons/Button-Menu"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,9 @@
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1758189672504
|
||||
1758634747140
|
||||
],
|
||||
"$ts": 1758189672504
|
||||
"$ts": 1758634747140
|
||||
}
|
||||
},
|
||||
"deviceMapping": {}
|
||||
@ -47,8 +47,8 @@
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 325,
|
||||
"width": 700
|
||||
"height": 339,
|
||||
"width": 767
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
@ -310,7 +310,7 @@
|
||||
"$": [
|
||||
"ds",
|
||||
192,
|
||||
1758189672544
|
||||
1758634747196
|
||||
],
|
||||
"$columns": [
|
||||
{
|
||||
@ -337,11 +337,7 @@
|
||||
"textIndent": "15px"
|
||||
},
|
||||
"pager": {
|
||||
"style": {
|
||||
"backgroundColor": "#D3D3D3",
|
||||
"color": "#FFFFFF",
|
||||
"fontWeight": "bold"
|
||||
}
|
||||
"activeOption": 50
|
||||
},
|
||||
"rows": {
|
||||
"highlight": {
|
||||
|
Before Width: | Height: | Size: 95 KiB |
@ -1,64 +0,0 @@
|
||||
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"
|
||||
@ -0,0 +1,418 @@
|
||||
{
|
||||
"custom": {
|
||||
"dpm1-dpm2": false,
|
||||
"dpm2-mcm": false,
|
||||
"mcm-dpm1": false
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
"System/MCM05/Rack",
|
||||
"System/MCM05/IO_BLOCK/DPM/DPM01_VS01B",
|
||||
"System/MCM05/IO_BLOCK/DPM/DPM01_VS01C"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.dpm1-dpm2": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"1": "{view.params.tagProps[1]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{1}/Communication_Faulted"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},true)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": false,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": false,
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": false
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.dpm2-mcm": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"2": "{view.params.tagProps[2]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{2}/Communication_Faulted"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},true)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": false,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": false,
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": false
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.mcm-dpm1": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Communication_Faulted"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},true)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": false,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": false,
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"input": true,
|
||||
"output": false
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 894,
|
||||
"width": 1920
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tself.session.custom.dpm_view_path \u003d self.props.params.view\n\tself.session.custom.show_dpm_device_view \u003d True"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "MCM"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.5,
|
||||
"width": 0.5,
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"propConfig": {
|
||||
"props.params.InOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm2-mcm"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.params.OutOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.mcm-dpm1"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"params": {
|
||||
"InDown": false,
|
||||
"InLeft": true,
|
||||
"InUp": false,
|
||||
"OutDown": false,
|
||||
"OutRight": false,
|
||||
"OutUp": true
|
||||
},
|
||||
"path": "Windows/Tabs/Enternet Windows/Components/EN4TR"
|
||||
},
|
||||
"type": "ia.display.view"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tself.session.custom.dpm_view_path \u003d self.props.params.view\n\tself.session.custom.show_dpm_device_view \u003d True"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "DPM01_VS01B"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.5,
|
||||
"width": 0.5,
|
||||
"x": 0.5
|
||||
},
|
||||
"propConfig": {
|
||||
"props.params.DownOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.mcm-dpm1"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.params.InOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm1-dpm2"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.params.OutOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.mcm-dpm1"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"params": {
|
||||
"Down1": false,
|
||||
"Down2": false,
|
||||
"Down3": true,
|
||||
"DownLeft": false,
|
||||
"DownRight": false,
|
||||
"InDown": false,
|
||||
"InLeft": true,
|
||||
"InUp": false,
|
||||
"OutDown": true,
|
||||
"OutRight": false,
|
||||
"OutUp": false,
|
||||
"view": "Windows/Tabs/Enternet Windows/DPMs/DPM Devices/MCM05/DPM01_VS01B"
|
||||
},
|
||||
"path": "Windows/Tabs/Enternet Windows/Components/DPM_BLOCK"
|
||||
},
|
||||
"type": "ia.display.view"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tself.session.custom.dpm_view_path \u003d self.props.params.view\n\tself.session.custom.show_dpm_device_view \u003d True"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "DPM01_VS01C"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.5,
|
||||
"width": 0.5
|
||||
},
|
||||
"propConfig": {
|
||||
"props.params.DownOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm2-mcm"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.params.InOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm2-mcm"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.params.OutOn": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm1-dpm2"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"params": {
|
||||
"Down1": false,
|
||||
"Down2": true,
|
||||
"Down3": false,
|
||||
"DownLeft": false,
|
||||
"DownRight": false,
|
||||
"InDown": true,
|
||||
"InLeft": false,
|
||||
"InUp": false,
|
||||
"OutDown": false,
|
||||
"OutRight": true,
|
||||
"OutUp": false,
|
||||
"view": "Windows/Tabs/Enternet Windows/DPMs/DPM Devices/MCM05/DPM01_VS01C"
|
||||
},
|
||||
"path": "Windows/Tabs/Enternet Windows/Components/DPM_BLOCK"
|
||||
},
|
||||
"type": "ia.display.view"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "DPM1_label"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.0358,
|
||||
"width": 0.0547,
|
||||
"x": 0.5,
|
||||
"y": 0.1
|
||||
},
|
||||
"props": {
|
||||
"text": "DPM01_VS01B 11.200.1.3",
|
||||
"textStyle": {
|
||||
"fontSize": "1vmin"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "DPM2_label"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.0358,
|
||||
"width": 0.0547,
|
||||
"x": 0.01,
|
||||
"y": 0.1
|
||||
},
|
||||
"props": {
|
||||
"text": "DPM01_VS01C 11.200.1.2",
|
||||
"textStyle": {
|
||||
"fontSize": "1vmin"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tself.session.custom.dpm_view_path \u003d self.props.params.view\n\tself.session.custom.show_dpm_device_view \u003d True"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "DPM2_DEVICE_0"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.5,
|
||||
"width": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"propConfig": {
|
||||
"props.params.On": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.dpm2-mcm"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"params": {
|
||||
"LD": false,
|
||||
"LR": false,
|
||||
"LRD": false,
|
||||
"LRU": false,
|
||||
"LU": false,
|
||||
"RD": false,
|
||||
"RLD": false,
|
||||
"RLU": true,
|
||||
"RU": false
|
||||
},
|
||||
"path": "Windows/Tabs/Enternet Windows/Components/CommLines"
|
||||
},
|
||||
"type": "ia.display.view"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "root"
|
||||
},
|
||||
"position": {
|
||||
"x": 120,
|
||||
"y": -723
|
||||
},
|
||||
"props": {
|
||||
"mode": "percent",
|
||||
"style": {
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.coord"
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 321 B |
@ -0,0 +1,609 @@
|
||||
{
|
||||
"custom": {
|
||||
"alarm_message": null,
|
||||
"color": "#C2C2C2",
|
||||
"priority": "No Active Alarms",
|
||||
"state": "Closed"
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
"System/MCM03/PDP3_PMM",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Color"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "#C2C2C2"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "#FF0000"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "#FFA500"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "#0008FF"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "#00FF00"
|
||||
},
|
||||
{
|
||||
"input": 5,
|
||||
"output": "#FFF700"
|
||||
},
|
||||
{
|
||||
"input": 6,
|
||||
"output": "#87CEEB"
|
||||
},
|
||||
{
|
||||
"input": 7,
|
||||
"output": "#90EE90"
|
||||
},
|
||||
{
|
||||
"input": 8,
|
||||
"output": "#964B00"
|
||||
},
|
||||
{
|
||||
"input": 9,
|
||||
"output": "#FFFFFF"
|
||||
},
|
||||
{
|
||||
"input": 10,
|
||||
"output": "#000000"
|
||||
},
|
||||
{
|
||||
"input": 11,
|
||||
"output": "#8B0000"
|
||||
},
|
||||
{
|
||||
"input": 12,
|
||||
"output": "#808080"
|
||||
},
|
||||
{
|
||||
"input": 13,
|
||||
"output": "#8B8000"
|
||||
},
|
||||
{
|
||||
"input": 14,
|
||||
"output": "#006400"
|
||||
},
|
||||
{
|
||||
"input": 15,
|
||||
"output": "#FFFFC5"
|
||||
},
|
||||
{
|
||||
"input": 16,
|
||||
"output": "#00008B"
|
||||
},
|
||||
{
|
||||
"input": 17,
|
||||
"output": "#FF7276"
|
||||
},
|
||||
{
|
||||
"input": 18,
|
||||
"output": "#556B2F"
|
||||
},
|
||||
{
|
||||
"input": 19,
|
||||
"output": "#B43434"
|
||||
},
|
||||
{
|
||||
"input": 20,
|
||||
"output": "#4682B4"
|
||||
},
|
||||
{
|
||||
"input": 21,
|
||||
"output": "#FFD700"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.priority": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Priority"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": null,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "No Active Alarms"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "High"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "Medium"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "Low"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "Diagnostic"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"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}/State"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "Unknown",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "Closed"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "Actuated"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "Communication Faulted"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "Conveyor Running In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "Disabled"
|
||||
},
|
||||
{
|
||||
"input": 5,
|
||||
"output": "Disconnected"
|
||||
},
|
||||
{
|
||||
"input": 6,
|
||||
"output": "Stopped"
|
||||
},
|
||||
{
|
||||
"input": 7,
|
||||
"output": "Enabled Not Running"
|
||||
},
|
||||
{
|
||||
"input": 8,
|
||||
"output": "Encoder Fault"
|
||||
},
|
||||
{
|
||||
"input": 9,
|
||||
"output": "Energy Management"
|
||||
},
|
||||
{
|
||||
"input": 10,
|
||||
"output": "ESTOP Was Actuated"
|
||||
},
|
||||
{
|
||||
"input": 11,
|
||||
"output": "EStopped"
|
||||
},
|
||||
{
|
||||
"input": 12,
|
||||
"output": "EStopped Locally"
|
||||
},
|
||||
{
|
||||
"input": 13,
|
||||
"output": "Extended Faulted"
|
||||
},
|
||||
{
|
||||
"input": 14,
|
||||
"output": "Full"
|
||||
},
|
||||
{
|
||||
"input": 15,
|
||||
"output": "Gaylord Start Pressed"
|
||||
},
|
||||
{
|
||||
"input": 16,
|
||||
"output": "Jam Fault"
|
||||
},
|
||||
{
|
||||
"input": 17,
|
||||
"output": "Jammed"
|
||||
},
|
||||
{
|
||||
"input": 18,
|
||||
"output": "Loading Allowed"
|
||||
},
|
||||
{
|
||||
"input": 19,
|
||||
"output": "Loading Not Allowed"
|
||||
},
|
||||
{
|
||||
"input": 20,
|
||||
"output": "Low Air Pressure Fault Was Present"
|
||||
},
|
||||
{
|
||||
"input": 21,
|
||||
"output": "Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 22,
|
||||
"output": "Conveyor Stopped In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 23,
|
||||
"output": "Motor Faulted"
|
||||
},
|
||||
{
|
||||
"input": 24,
|
||||
"output": "Motor Was Faulted"
|
||||
},
|
||||
{
|
||||
"input": 25,
|
||||
"output": "Normal"
|
||||
},
|
||||
{
|
||||
"input": 26,
|
||||
"output": "Off Inactive"
|
||||
},
|
||||
{
|
||||
"input": 27,
|
||||
"output": "Open"
|
||||
},
|
||||
{
|
||||
"input": 28,
|
||||
"output": "PLC Ready To Run"
|
||||
},
|
||||
{
|
||||
"input": 29,
|
||||
"output": "Package Release Pressed"
|
||||
},
|
||||
{
|
||||
"input": 30,
|
||||
"output": "Power Branch Was Faulted"
|
||||
},
|
||||
{
|
||||
"input": 31,
|
||||
"output": "Pressed"
|
||||
},
|
||||
{
|
||||
"input": 32,
|
||||
"output": "Ready To Receive"
|
||||
},
|
||||
{
|
||||
"input": 33,
|
||||
"output": "Running"
|
||||
},
|
||||
{
|
||||
"input": 34,
|
||||
"output": "Started"
|
||||
},
|
||||
{
|
||||
"input": 35,
|
||||
"output": "Stopped"
|
||||
},
|
||||
{
|
||||
"input": 36,
|
||||
"output": "System Started"
|
||||
},
|
||||
{
|
||||
"input": 37,
|
||||
"output": "Unknown"
|
||||
},
|
||||
{
|
||||
"input": 38,
|
||||
"output": "VFD Fault"
|
||||
},
|
||||
{
|
||||
"input": 39,
|
||||
"output": "Conveyor Running In Power Saving Mode"
|
||||
},
|
||||
{
|
||||
"input": 40,
|
||||
"output": "Conveyor Jogging In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 41,
|
||||
"output": "VFD Reset Required"
|
||||
},
|
||||
{
|
||||
"input": 42,
|
||||
"output": "Jam Reset Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 43,
|
||||
"output": "Start Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 44,
|
||||
"output": "Stop Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 45,
|
||||
"output": "No Container"
|
||||
},
|
||||
{
|
||||
"input": 46,
|
||||
"output": "Ready To Be Enabled"
|
||||
},
|
||||
{
|
||||
"input": 47,
|
||||
"output": "Half Full"
|
||||
},
|
||||
{
|
||||
"input": 48,
|
||||
"output": "Enabled"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "inout",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 19,
|
||||
"width": 28
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "PMM_Symbol"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.elements[5].fill.paint": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n {view.custom.state} \u003d \"Closed\",\r\n \"#000000\",\r\n {view.custom.color}\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"elements": [
|
||||
{
|
||||
"d": "M 10 10 L 50 10 L 50 30 L 10 30 Z",
|
||||
"fill": {
|
||||
"paint": "#CCCCCC"
|
||||
},
|
||||
"name": "module_body",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "2"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"d": "M 0 20 L 10 20",
|
||||
"fill": {},
|
||||
"name": "power_input",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "2"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"d": "M 50 15 L 60 15",
|
||||
"fill": {},
|
||||
"name": "output_1",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "2"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"d": "M 50 20 L 60 20",
|
||||
"fill": {},
|
||||
"name": "output_2",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "2"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"d": "M 50 25 L 60 25",
|
||||
"fill": {},
|
||||
"name": "output_3",
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "2"
|
||||
},
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"cx": "30",
|
||||
"cy": "20",
|
||||
"fill": {},
|
||||
"name": "status_led",
|
||||
"r": 6,
|
||||
"stroke": {
|
||||
"paint": "#000000",
|
||||
"width": "1"
|
||||
},
|
||||
"type": "circle"
|
||||
}
|
||||
],
|
||||
"style": {
|
||||
"overflow": "hidden"
|
||||
},
|
||||
"viewBox": "0 0 60 40"
|
||||
},
|
||||
"type": "ia.shapes.svg"
|
||||
}
|
||||
],
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.openDock(\u0027Docked-East-DS\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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "root",
|
||||
"tooltip": {
|
||||
"enabled": true,
|
||||
"location": "top-left",
|
||||
"style": {}
|
||||
}
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.style.classes": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "{view.custom.priority}"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "Alarms-Styles/NoAlarm",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": "Alarms-Styles/High"
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": "Alarms-Styles/Medium"
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": "Alarms-Styles/Low"
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": "Alarms-Styles/Diagnostic"
|
||||
}
|
||||
],
|
||||
"outputType": "style-list",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\n {view.custom.state} !\u003d \"Closed\",\n \"Source Id: \" + {view.params.tagProps[0]} + \", Priority: \" + {view.custom.priority} + \", State: \" + {view.custom.state},\n \"Device Disconnected\"\n)\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.visible": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "session.custom.alarm_filter.show_running"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"justify": "center",
|
||||
"style": {
|
||||
"borderColor": "#FF0000",
|
||||
"borderStyle": "none",
|
||||
"borderWidth": "2px",
|
||||
"cursor": "pointer"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
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
|
||||
|
Before Width: | Height: | Size: 231 B |
@ -1024,13 +1024,6 @@
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
After Width: | Height: | Size: 20 KiB |
@ -1,28 +0,0 @@
|
||||
SELECT
|
||||
ae.id AS ID,
|
||||
ae.eventtime AS StartTimestamp,
|
||||
CONCAT(
|
||||
LPAD(FLOOR(TIMESTAMPDIFF(SECOND, ae.eventtime, NOW())/3600), 2, '0'), ':',
|
||||
LPAD(FLOOR((TIMESTAMPDIFF(SECOND, ae.eventtime, NOW())%3600)/60), 2, '0'), ':',
|
||||
LPAD( (TIMESTAMPDIFF(SECOND, ae.eventtime, NOW())%60), 2, '0')
|
||||
) AS Duration,
|
||||
CONCAT(REPLACE(ae.displaypath,'_','-'),' ', SUBSTRING_INDEX(ae.source,':/alm:',-1)) AS Description,
|
||||
CASE ae.priority
|
||||
WHEN 0 THEN 'Diagnostic' WHEN 1 THEN 'Low' WHEN 2 THEN 'Medium'
|
||||
WHEN 3 THEN 'High' WHEN 4 THEN 'Critical' ELSE 'Unknown'
|
||||
END AS Priority,
|
||||
CONCAT(ae.displaypath,'.HMI.Alarm.', SUBSTRING_INDEX(aed.strValue,'/',-1)) AS Tag,
|
||||
SUBSTRING_INDEX(SUBSTRING_INDEX(aed.strValue,'/',2),'/',-1) AS Location,
|
||||
aed.strValue AS FullTag,
|
||||
ae.displaypath AS Device
|
||||
FROM alarm_events ae
|
||||
LEFT JOIN alarm_events clr
|
||||
ON clr.eventid = ae.eventid AND clr.eventtype = 1
|
||||
LEFT JOIN alarm_event_data aed
|
||||
ON aed.id = ae.id AND aed.propname = 'myTag'
|
||||
WHERE ae.eventtype = 0
|
||||
AND clr.eventid IS NULL
|
||||
AND ae.displaypath NOT LIKE '%System Startup%'
|
||||
AND ae.source NOT LIKE '%System Startup%'
|
||||
AND (:priorityList = '' OR FIND_IN_SET(CAST(ae.priority AS CHAR), :priorityList) > 0)
|
||||
ORDER BY ae.eventtime DESC;
|
||||
@ -1,293 +0,0 @@
|
||||
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)
|
||||
|
||||
|
After Width: | Height: | Size: 9.4 KiB |
@ -1,34 +0,0 @@
|
||||
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)
|
||||
@ -61,14 +61,6 @@
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.image.icon.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -261,14 +253,6 @@
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.image.icon.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -973,14 +957,6 @@
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.enabled": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "indexOf({session.props.auth.user.roles}, \"Administrator\") \u003e\u003d 0 || indexOf({session.props.auth.user.roles}, \"Maintenance\") \u003e\u003d 0"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.image.icon.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -1146,10 +1122,21 @@
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttag_name \u003d self.view.params.value.tagProps[0]\n\ttag_path \u003d \"[\" + self.session.custom.fc+ \"_SCADA_TAG_PROVIDER]\"+\"System/\"+tag_name +\"/\" + tag_name+\"/Setup_Motor_Speeds\"\n\tsystem.tag.writeBlocking([tag_path],[True])"
|
||||
"draggable": true,
|
||||
"id": "3LC69yrX",
|
||||
"modal": false,
|
||||
"overlayDismiss": false,
|
||||
"resizable": true,
|
||||
"showCloseIcon": true,
|
||||
"type": "open",
|
||||
"viewParams": {
|
||||
"MCM": "{view.params.value.tagProps[0]}"
|
||||
},
|
||||
"viewPath": "PopUp-Views/SetupMotorSpeeds",
|
||||
"viewportBound": false
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
"scope": "C",
|
||||
"type": "popup"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
After Width: | Height: | Size: 140 KiB |
@ -1,122 +0,0 @@
|
||||
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)])
|
||||
@ -1,64 +0,0 @@
|
||||
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"]
|
||||
@ -1,237 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
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))
|
||||
@ -1,302 +0,0 @@
|
||||
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))
|
||||
@ -1,32 +0,0 @@
|
||||
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"
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
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)
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
"MCM02",
|
||||
"MCM03",
|
||||
"MCM04",
|
||||
"MCM05",
|
||||
"MCM06",
|
||||
"MCM07"
|
||||
"MCM05"
|
||||
],
|
||||
"running_state": -1,
|
||||
"state": 0,
|
||||
|
After Width: | Height: | Size: 150 KiB |
@ -12,7 +12,7 @@
|
||||
},
|
||||
"params": {
|
||||
"tagProps": [
|
||||
"System/MCM01/Conveyor/VFD/UL1_3_VFD1",
|
||||
"System/MCM01/Conveyor/VFD/ULC1_4_VFD1",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
@ -519,7 +519,7 @@
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\tparts \u003d value.split(\"/\")\n\tname \u003d parts[-1]\n\t\n\t# Split on \"_\" and remove the last part\n\tname_parts \u003d name.split(\"_\")\n\tnew_name \u003d \"_\".join(name_parts[:-1])\n\t\n\treturn new_name + \"_PE*,\" + new_name + \"_VFD*\"",
|
||||
"code": " parts \u003d str(value).split(\"/\")\n name \u003d parts[-1]\n\n # Split on \"_\" and remove the last part\n name_parts \u003d name.split(\"_\")\n new_name \u003d \"_\".join(name_parts[:-1])\n\n # Return with TPE, JPE, and VFD wildcards\n return new_name + \"_TPE*,\" + new_name + \"_JPE*,\" + new_name + \"_VFD*\"",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
@ -531,7 +531,10 @@
|
||||
"columns": {
|
||||
"active": {
|
||||
"displayPath": {
|
||||
"enabled": false
|
||||
"width": 120
|
||||
},
|
||||
"name": {
|
||||
"width": 100
|
||||
},
|
||||
"priority": {
|
||||
"enabled": false
|
||||
@ -939,48 +942,11 @@
|
||||
"basis": "50%",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/VFD_Type"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\u0027UNKNOWN (FREQ/VELOCITY)\u0027)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "UNKNOWN (FREQ/VELOCITY)",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 1,
|
||||
"output": "VELOCITY"
|
||||
},
|
||||
{
|
||||
"input": 0,
|
||||
"output": "FREQUENCY"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"paddingLeft": 20
|
||||
}
|
||||
},
|
||||
"text": "VELOCITY"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
@ -1024,12 +990,12 @@
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/VFD_Type"
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Velocity"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": " provider \u003d self.session.custom.fc + \"_SCADA_TAG_PROVIDER\"\n baseTag \u003d self.view.params.tagProps[0]\n basePath \u003d \"[\"+ provider + \"]\" + baseTag\n child \u003d \"\"\n unit \u003d \"\"\n \n\n if value \u003d\u003d 1:\n child \u003d \"Velocity\"\n unit \u003d \" Rev/s\"\n else:\n child \u003d \"Frequency\"\n unit \u003d \" Hz\"\n\n fullPath \u003d basePath + \"/\" + child\n tagValue \u003d system.tag.readBlocking([fullPath])[0]\n result \u003d tagValue.value\n\t\n if result is None or str(result) \u003d\u003d \"None\":\n return \"UNKNOWN\"\n else:\n return str(result) + unit",
|
||||
"type": "script"
|
||||
"expression": "if(coalesce({value},{view.params.forceFaultStatus},\u0027UNKNOWN\u0027) \u003d \u0027UNKNOWN\u0027, \u0027UNKNOWN\u0027, coalesce({value},{view.params.forceFaultStatus}) + \" Rev/s\")",
|
||||
"type": "expression"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
@ -1652,48 +1618,11 @@
|
||||
"basis": "50px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/VFD_Type"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\u0027UNKNOWN (60hz/30rev)\u0027)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "Unknown (60hz/30rev)",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 1,
|
||||
"output": "Speed At 30 rev/s"
|
||||
},
|
||||
{
|
||||
"input": 0,
|
||||
"output": "Speed At 60Hz"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"padding": 20
|
||||
},
|
||||
"text": "Speed At 30rev",
|
||||
"textStyle": {
|
||||
"color": "#7D7D7D"
|
||||
}
|
||||
@ -2600,6 +2529,7 @@
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"currentTabIndex": 1,
|
||||
"menuType": "modern",
|
||||
"tabSize": {
|
||||
"width": 1000
|
||||
@ -1,113 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -4,36 +4,21 @@
|
||||
"$": [
|
||||
"ds",
|
||||
192,
|
||||
1758118477540
|
||||
1758705750254
|
||||
],
|
||||
"$columns": [
|
||||
{
|
||||
"data": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"MCM01"
|
||||
],
|
||||
"data": [],
|
||||
"name": "Location",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"data": [
|
||||
"High",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High"
|
||||
],
|
||||
"data": [],
|
||||
"name": "Priority",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"data": [
|
||||
294,
|
||||
257,
|
||||
230,
|
||||
2
|
||||
],
|
||||
"data": [],
|
||||
"name": "Count",
|
||||
"type": "Long"
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
{
|
||||
"custom": {},
|
||||
"params": {
|
||||
"MCM": "value"
|
||||
},
|
||||
"propConfig": {
|
||||
"params.MCM": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 121,
|
||||
"width": 400
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Label"
|
||||
},
|
||||
"position": {
|
||||
"basis": "32px"
|
||||
},
|
||||
"props": {
|
||||
"text": "Are you sure that you want to Setup Motor Speeds?"
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"alignItems": "flex-start",
|
||||
"direction": "column",
|
||||
"justify": "space-around",
|
||||
"style": {
|
||||
"paddingLeft": 5,
|
||||
"paddingRight": 5
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"events": {
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttag_name \u003d self.view.params.MCM\n\ttag_path \u003d \"[\" + self.session.custom.fc+ \"_SCADA_TAG_PROVIDER]\"+tag_name+\"/Setup_Motor_Speeds\"\n\tsystem.tag.writeBlocking([tag_path],[True])\n\tsystem.perspective.closePopup(\"\")"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button_0"
|
||||
},
|
||||
"position": {
|
||||
"basis": "144px"
|
||||
},
|
||||
"props": {
|
||||
"primary": false,
|
||||
"style": {
|
||||
"marginTop": 3
|
||||
},
|
||||
"text": "Yes"
|
||||
},
|
||||
"type": "ia.input.button"
|
||||
},
|
||||
{
|
||||
"events": {
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.closePopup(\"\")"
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "Button_1"
|
||||
},
|
||||
"position": {
|
||||
"basis": "144px"
|
||||
},
|
||||
"props": {
|
||||
"primary": false,
|
||||
"style": {
|
||||
"marginTop": 3
|
||||
},
|
||||
"text": "No"
|
||||
},
|
||||
"type": "ia.input.button"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "FlexContainer_0"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"props": {
|
||||
"alignItems": "center",
|
||||
"justify": "space-around",
|
||||
"style": {
|
||||
"paddingLeft": 5,
|
||||
"paddingRight": 5
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "root"
|
||||
},
|
||||
"props": {
|
||||
"alignContent": "flex-start",
|
||||
"direction": "column",
|
||||
"justify": "space-around"
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -1,184 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,787 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
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
|
||||
@ -1,50 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
/* Direct stylesheet authoring is an advanced feature. Knowledge of CSS required.*/
|
||||
|
||||
.psc-x1 { transition: all .2s ease-in-out; }
|
||||
.psc-x1:hover { transform: scale(1.5) !important; z-index: 5;}
|
||||
|
||||
|
||||
.psc-x2 { transition: all .2s ease-in-out; }
|
||||
.psc-x2:hover { transform: scale(2) !important; z-index: 5;}
|
||||
|
||||
.psc-x3 { transition: all .2s ease-in-out; }
|
||||
.psc-x3:hover { transform: scale(3) !important; z-index: 5;}
|
||||
|
||||
/* Set the styling for the Table component checkbox colour.*/
|
||||
.ia_tableComponent[data-component="ia.display.table"] .ia_checkbox__checkedIcon {
|
||||
color: black;
|
||||
}
|
||||
.ia_tableComponent[data-component="ia.display.table"] .ia_checkbox__uncheckedIcon {
|
||||
color: black;
|
||||
}
|
||||
|
||||
div[data-component="ia.input.fileupload"] .ia_button--primary {
|
||||
background-color: var(--neutral-30);
|
||||
border-style: None;
|
||||
color: black;
|
||||
border-radius:20px;
|
||||
}
|
||||
|
||||
|
||||
/* Help page styles */
|
||||
|
||||
.psc-background:hover {
|
||||
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
transition: box-shadow 0.9s ease-in-out;
|
||||
}
|
||||
|
||||
.psc-background-none {
|
||||
box-shadow: 0 0px 0px 0 , 0 0px 0px 0;
|
||||
transition: box-shadow 0.9s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn{
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
.psc-FadeInFast {
|
||||
animation: fadeIn 2s;
|
||||
}
|
||||
|
||||
.psc-FadeInMedium {
|
||||
animation: fadeIn 4s;
|
||||
}
|
||||
|
||||
.psc-FadeInSlow {
|
||||
animation: fadeIn 6s;
|
||||
}
|
||||
|
||||
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
.psc-rotate {
|
||||
animation: rotation 2s infinite linear;
|
||||
}
|
||||
|
||||
.psc-hover-zoom {
|
||||
|
||||
position: relative;
|
||||
transform-origin: 50% 50%;
|
||||
transform: translateZ(0) scale(1);
|
||||
transition: transform 220ms cubic-bezier(.2,.8,.2,1), filter 220ms cubic-bezier(.2,.8,.2,1);
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.psc-hover-zoom:hover,
|
||||
.psc-hover-zoom:focus-visible {
|
||||
transform: translateZ(0) scale(var(--psc-zoom, 1.8));
|
||||
z-index: 9999;
|
||||
filter: drop-shadow(0 8px 18px rgba(0,0,0,.28));
|
||||
}
|
||||
|
||||
.psc-stack { position: relative; }
|
||||
|
||||
.psc-stack:has(.psc-hover-zoom:hover) {
|
||||
z-index: 2147483646;
|
||||
}
|
||||
|
||||
.psc-stack-tier-1:has(.psc-hover-zoom:hover) { z-index: 1000; }
|
||||
.psc-stack-tier-2:has(.psc-hover-zoom:hover) { z-index: 2000; }
|
||||
.psc-stack-tier-3:has(.psc-hover-zoom:hover) { z-index: 3000; }
|
||||
|
||||
.psc-overflow-visible { overflow: visible; }
|
||||
|
||||
.psc-zoom-150 { --psc-zoom: 1.5; }
|
||||
.psc-zoom-180 { --psc-zoom: 1.8; }
|
||||
.psc-zoom-200 { --psc-zoom: 2; }
|
||||
.psc-zoom-300 { --psc-zoom: 3; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.psc-hover-zoom { transition: none; filter: none; }
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
.psc-hover-zoom,
|
||||
.psc-hover-zoom:hover,
|
||||
.psc-stack:has(.psc-hover-zoom:hover) {
|
||||
transform: none !important;
|
||||
filter: none !important;
|
||||
z-index: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-hover {
|
||||
transform-origin: 50% 50%;
|
||||
transition: scale 100ms linear;
|
||||
scale: 1;
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-hover:hover {
|
||||
scale: 2;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-conveyor.psc-hover:hover {
|
||||
scale: 1.3;
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
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")
|
||||
@ -46,7 +46,7 @@
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
"path": "/root.custom.MCM"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
@ -87,11 +87,21 @@
|
||||
"basis": "10px",
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"props.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "/root.custom.totalJams"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"marginRight": "10px"
|
||||
"marginRight": "20px",
|
||||
"overflow": "visible"
|
||||
},
|
||||
"text": 0,
|
||||
"textStyle": {
|
||||
"textAlign": "end"
|
||||
}
|
||||
@ -427,7 +437,7 @@
|
||||
"basis": "32px"
|
||||
},
|
||||
"props": {
|
||||
"text": 0,
|
||||
"text": 37,
|
||||
"textStyle": {
|
||||
"fontSize": 10,
|
||||
"textAlign": "center"
|
||||
@ -456,7 +466,7 @@
|
||||
"basis": "32px"
|
||||
},
|
||||
"props": {
|
||||
"text": 0,
|
||||
"text": 2,
|
||||
"textStyle": {
|
||||
"fontSize": 10,
|
||||
"textAlign": "center"
|
||||
@ -485,7 +495,7 @@
|
||||
"basis": "32px"
|
||||
},
|
||||
"props": {
|
||||
"text": 0,
|
||||
"text": 7,
|
||||
"textStyle": {
|
||||
"fontSize": 10,
|
||||
"textAlign": "center"
|
||||
@ -543,7 +553,7 @@
|
||||
"basis": "32px"
|
||||
},
|
||||
"props": {
|
||||
"text": 0,
|
||||
"text": 46,
|
||||
"textStyle": {
|
||||
"fontSize": 10,
|
||||
"textAlign": "center"
|
||||
@ -609,9 +619,9 @@
|
||||
"counts": {
|
||||
"Critical": 0,
|
||||
"Diagnostic": 0,
|
||||
"High": 0,
|
||||
"Low": 0,
|
||||
"Medium": 0
|
||||
"High": 37,
|
||||
"Low": 7,
|
||||
"Medium": 2
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
@ -629,6 +639,14 @@
|
||||
"name": "root"
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.MCM": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.params.tagProps[0]"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"custom.Total": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -637,18 +655,10 @@
|
||||
"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})"
|
||||
"expression": "jsonGet({this.custom.plc_dict}, \"Area\")"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
@ -678,70 +688,6 @@
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"custom.table": {
|
||||
"binding": {
|
||||
"config": {
|
||||
@ -758,6 +704,23 @@
|
||||
"script": "\ttry:\n\t\tMCM \u003d self.view.params.tagProps[0]\n\t\tdata \u003d currentValue.value\n\t\t\n\t\t# Convert dataset to PyDataSet\n\t\trows \u003d system.dataset.toPyDataSet(data)\n\t\t\n\t\t# Initialize counts dictionary with first-letter uppercase keys\n\t\tcounts \u003d {\n\t\t\t\"Low\": 0,\n\t\t\t\"Medium\": 0,\n\t\t\t\"High\": 0,\n\t\t\t\"Critical\": 0,\n\t\t\t\"Diagnostic\": 0\n\t\t}\n\t\t\n\t\t# Loop through rows and filter for current MCM\n\t\tfor row in rows:\n\t\t\tif row[\"Location\"] \u003d\u003d MCM:\n\n\t\t\t\tpriority \u003d row[\"Priority\"].capitalize()\n\t\t\t\tif priority in counts:\n\t\t\t\t\tcounts[priority] \u003d row[\"Count\"]\n\t\t\n\t\tself.custom.counts \u003d counts\n\t\n\texcept Exception as e:\n\t\tsystem.perspective.print(\"Error gaq dzma: \" + str(e))"
|
||||
}
|
||||
},
|
||||
"custom.totalJams": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"parameters": {
|
||||
"priorityList": "3"
|
||||
},
|
||||
"queryPath": "autStand/Alarms/Active"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\t# value is the dataset from the database\n\tfrom java.util import HashSet\n\t\n\t# To track unique jammed devices\n\tunique_devices \u003d HashSet()\n\t\n\tfor rowIndex in range(value.getRowCount()):\n\t device \u003d value.getValueAt(rowIndex, \"Device\")\n\t tag \u003d value.getValueAt(rowIndex, \"Tag\")\n\t location \u003d value.getValueAt(rowIndex, \"Location\")\n\t \n\t if \"TPE\" in str(device) and \"Jammed\" in str(tag) and self.custom.MCM \u003d\u003d str(location):\n\t unique_devices.add(device)\n\t\n\t# Return total count as a number\n\ttotalJams \u003d unique_devices.size()\n\treturn totalJams",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "query"
|
||||
}
|
||||
},
|
||||
"meta.visible": {
|
||||
"binding": {
|
||||
"config": {
|
||||
|
After Width: | Height: | Size: 63 KiB |
@ -0,0 +1,151 @@
|
||||
/* Direct stylesheet authoring is an advanced feature. Knowledge of CSS required.*/
|
||||
|
||||
.psc-x1 { transition: all .2s ease-in-out; }
|
||||
.psc-x1:hover { transform: scale(1.5) !important; z-index: 5;}
|
||||
|
||||
|
||||
.psc-x2 { transition: all .2s ease-in-out; }
|
||||
.psc-x2:hover { transform: scale(2) !important; z-index: 5;}
|
||||
|
||||
.psc-x3 { transition: all .2s ease-in-out; }
|
||||
.psc-x3:hover { transform: scale(3) !important; z-index: 5;}
|
||||
|
||||
/* Set the styling for the Table component checkbox colour.*/
|
||||
.ia_tableComponent[data-component="ia.display.table"] .ia_checkbox__checkedIcon {
|
||||
color: black;
|
||||
}
|
||||
.ia_tableComponent[data-component="ia.display.table"] .ia_checkbox__uncheckedIcon {
|
||||
color: black;
|
||||
}
|
||||
|
||||
div[data-component="ia.input.fileupload"] .ia_button--primary {
|
||||
background-color: var(--neutral-30);
|
||||
border-style: None;
|
||||
color: black;
|
||||
border-radius:20px;
|
||||
}
|
||||
|
||||
|
||||
/* Help page styles */
|
||||
|
||||
.psc-background:hover {
|
||||
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
transition: box-shadow 0.9s ease-in-out;
|
||||
}
|
||||
|
||||
.psc-background-none {
|
||||
box-shadow: 0 0px 0px 0 , 0 0px 0px 0;
|
||||
transition: box-shadow 0.9s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn{
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
.psc-FadeInFast {
|
||||
animation: fadeIn 2s;
|
||||
}
|
||||
|
||||
.psc-FadeInMedium {
|
||||
animation: fadeIn 4s;
|
||||
}
|
||||
|
||||
.psc-Disconnects\/Device-Connected.ia_container--primary.coord-aspect-ratio.aspect-horizontal.view
|
||||
.inner-container:has(svg path[d="M 0.01621377,0.01595147 H 25.93719 V 41.138171 H 0.01621377 Z"]:only-of-type) {
|
||||
flex: 0 0 12px !important;
|
||||
}
|
||||
|
||||
.psc-Disconnects\/Device-Connected.ia_container--primary.coord-aspect-ratio.aspect-horizontal.view
|
||||
.inner-container:has(
|
||||
svg[viewBox="-0.5 -0.5 27 42"]
|
||||
path[d="m 13.785537,6.4238337 -7.0747349,-3.1261989 -0.985,1.7060701 6.2447349,4.563801 z"]
|
||||
):has(
|
||||
svg[viewBox="-0.5 -0.5 27 42"]
|
||||
path[d="m 12.141737,10.447495 -5.3573679,5.578853 1.2662916,1.509108 6.4243953,-4.30722 z"]
|
||||
) {
|
||||
flex: 0 0 16px !important;
|
||||
}
|
||||
|
||||
|
||||
.psc-FadeInSlow {
|
||||
animation: fadeIn 6s;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
.psc-rotate {
|
||||
animation: rotation 2s infinite linear;
|
||||
}
|
||||
|
||||
.psc-hover-zoom {
|
||||
|
||||
position: relative;
|
||||
transform-origin: 50% 50%;
|
||||
transform: translateZ(0) scale(1);
|
||||
transition: transform 220ms cubic-bezier(.2,.8,.2,1), filter 220ms cubic-bezier(.2,.8,.2,1);
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.psc-hover-zoom:hover,
|
||||
.psc-hover-zoom:focus-visible {
|
||||
transform: translateZ(0) scale(var(--psc-zoom, 1.8));
|
||||
z-index: 9999;
|
||||
filter: drop-shadow(0 8px 18px rgba(0,0,0,.28));
|
||||
}
|
||||
|
||||
.psc-stack { position: relative; }
|
||||
|
||||
.psc-stack:has(.psc-hover-zoom:hover) {
|
||||
z-index: 2147483646;
|
||||
}
|
||||
|
||||
.psc-stack-tier-1:has(.psc-hover-zoom:hover) { z-index: 1000; }
|
||||
.psc-stack-tier-2:has(.psc-hover-zoom:hover) { z-index: 2000; }
|
||||
.psc-stack-tier-3:has(.psc-hover-zoom:hover) { z-index: 3000; }
|
||||
|
||||
.psc-overflow-visible { overflow: visible; }
|
||||
|
||||
.psc-zoom-150 { --psc-zoom: 1.5; }
|
||||
.psc-zoom-180 { --psc-zoom: 1.8; }
|
||||
.psc-zoom-200 { --psc-zoom: 2; }
|
||||
.psc-zoom-300 { --psc-zoom: 3; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.psc-hover-zoom { transition: none; filter: none; }
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
.psc-hover-zoom,
|
||||
.psc-hover-zoom:hover,
|
||||
.psc-stack:has(.psc-hover-zoom:hover) {
|
||||
transform: none !important;
|
||||
filter: none !important;
|
||||
z-index: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-hover {
|
||||
transform-origin: 50% 50%;
|
||||
transition: scale 100ms linear;
|
||||
scale: 1;
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-hover:hover {
|
||||
scale: 2;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
[data-component="ia.display.view"].psc-conveyor.psc-hover:hover {
|
||||
scale: 1.3;
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
{"onStartup":"\t# Auto-login for SAT9_SCADA\n\tif not session.props.auth.authenticated:\n\t # Auto-login with minimal credentials for local access\n\t try:\n\t system.perspective.login(username='auto', password='auto', force=True)\n\t except:\n\t pass\n\t\n\t# Initialize session properties from parent\n\ttags_to_read = system.tag.readBlocking([\"Configuration/FC\", \"Configuration/aws\"])\n\tsession.custom.fc = tags_to_read[0].value if tags_to_read[0].quality.isGood() else \"SAT9\"\n\ttry:\n\t aws = system.util.jsonDecode(tags_to_read[1].valu\n\t prefix = aws.get(\"prefix\", \"eu\")e) if tags_to_read[1].quality.isGood() else {\"prefix\": \"eu\", \"region\": \"eu-west-1\"}\n\t region = aws.get(\"region\", \"eu-west-1\")\n\t session.custom.aws.prefix = prefix\n\t session.custom.aws.region = region\n\texcept:\n\t session.custom.aws.prefix = \"eu\"\n\t session.custom.aws.region = \"eu-west-1\"\n\t\n\tsession.custom.covert = False\n\tsession.custom.download_url = None\n\tsession.custom.alarm_filter.show_map = False\n\tsession.custom.alarm_filter.magnificaiton = \"x2\"","onShutdown":"#\tsystem.perspective.logout()","onBarcodeDataReceived":"\t","onBluetoothReceived":"\t","onAccelerometerDataReceived":"\t","onNdefDataReceived":"\t"}
|
||||
|
After Width: | Height: | Size: 24 KiB |
@ -398,109 +398,6 @@
|
||||
"path": "autStand/Custom_Views/Enternet-Windows/Components/CommLines"
|
||||
},
|
||||
"type": "ia.display.view"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "Communication_Faulted_Text"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.4836,
|
||||
"width": 0.8826,
|
||||
"x": 0.0701,
|
||||
"y": -0.0785
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"borderColor": "#1A1A1A",
|
||||
"overflow": "hidden",
|
||||
"whiteSpace": "normal",
|
||||
"wordBreak": "break-all"
|
||||
},
|
||||
"text": "Communication Faulted",
|
||||
"textStyle": {
|
||||
"fontFamily": "inherit",
|
||||
"fontSize": "1.5vmin",
|
||||
"textAlign": "start"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "Communication_Not_Faulted_Text"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.6066,
|
||||
"width": 0.9032,
|
||||
"x": 0.0698,
|
||||
"y": 0.247
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"borderColor": "#1A1A1A",
|
||||
"overflow": "hidden",
|
||||
"whiteSpace": "normal",
|
||||
"wordBreak": "break-all"
|
||||
},
|
||||
"text": "Communication Not Faulted",
|
||||
"textStyle": {
|
||||
"fontFamily": "inherit",
|
||||
"fontSize": "1.5vmin",
|
||||
"textAlign": "start"
|
||||
}
|
||||
},
|
||||
"type": "ia.display.label"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "CoordinateContainer_0"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.0242,
|
||||
"width": 0.0508,
|
||||
"x": 0.0122,
|
||||
"y": 0.176
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#FF0000"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.coord"
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"name": "CoordinateContainer_1"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.0242,
|
||||
"width": 0.0508,
|
||||
"x": 0.0122,
|
||||
"y": 0.5164
|
||||
},
|
||||
"props": {
|
||||
"style": {
|
||||
"backgroundColor": "#00FF00"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.coord"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"name": "CoordinateContainer"
|
||||
},
|
||||
"position": {
|
||||
"height": 0.1365,
|
||||
"width": 0.9083,
|
||||
"x": 0.0083,
|
||||
"y": 0.7752
|
||||
},
|
||||
"props": {
|
||||
"mode": "percent"
|
||||
},
|
||||
"type": "ia.container.coord"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
|
After Width: | Height: | Size: 896 B |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
@ -0,0 +1,836 @@
|
||||
{
|
||||
"custom": {
|
||||
"alarm_message": null,
|
||||
"color": "#C2C2C2",
|
||||
"priority": "No Active Alarms",
|
||||
"state": "Closed"
|
||||
},
|
||||
"params": {
|
||||
"angle": 0,
|
||||
"directionLeft": false,
|
||||
"tagProps": [
|
||||
"System/MCM01/Conveyor/VFD/UL1_3_VFD1",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"propConfig": {
|
||||
"custom.color": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Color"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "#C2C2C2"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "#FF0000"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "#FFA500"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "#0008FF"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "#00FF00"
|
||||
},
|
||||
{
|
||||
"input": 5,
|
||||
"output": "#FFF700"
|
||||
},
|
||||
{
|
||||
"input": 6,
|
||||
"output": "#87CEEB"
|
||||
},
|
||||
{
|
||||
"input": 7,
|
||||
"output": "#90EE90"
|
||||
},
|
||||
{
|
||||
"input": 8,
|
||||
"output": "#964B00"
|
||||
},
|
||||
{
|
||||
"input": 9,
|
||||
"output": "#FFFFFF"
|
||||
},
|
||||
{
|
||||
"input": 10,
|
||||
"output": "#000000"
|
||||
},
|
||||
{
|
||||
"input": 11,
|
||||
"output": "#8B0000"
|
||||
},
|
||||
{
|
||||
"input": 12,
|
||||
"output": "#808080"
|
||||
},
|
||||
{
|
||||
"input": 13,
|
||||
"output": "#8B8000"
|
||||
},
|
||||
{
|
||||
"input": 14,
|
||||
"output": "#006400"
|
||||
},
|
||||
{
|
||||
"input": 15,
|
||||
"output": "#FFFFC5"
|
||||
},
|
||||
{
|
||||
"input": 16,
|
||||
"output": "#00008B"
|
||||
},
|
||||
{
|
||||
"input": 17,
|
||||
"output": "#FF7276"
|
||||
},
|
||||
{
|
||||
"input": 18,
|
||||
"output": "#556B2F"
|
||||
},
|
||||
{
|
||||
"input": 19,
|
||||
"output": "#B43434"
|
||||
},
|
||||
{
|
||||
"input": 20,
|
||||
"output": "#4682B4"
|
||||
},
|
||||
{
|
||||
"input": 21,
|
||||
"output": "#FFD700"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"custom.priority": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Priority"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": null,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "No Active Alarms"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "High"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "Medium"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "Low"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "Diagnostic"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"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}/State"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},0)",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "Unknown",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": 0,
|
||||
"output": "Closed"
|
||||
},
|
||||
{
|
||||
"input": 1,
|
||||
"output": "Actuated"
|
||||
},
|
||||
{
|
||||
"input": 2,
|
||||
"output": "Communication Faulted"
|
||||
},
|
||||
{
|
||||
"input": 3,
|
||||
"output": "Conveyor Running In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 4,
|
||||
"output": "Disabled"
|
||||
},
|
||||
{
|
||||
"input": 5,
|
||||
"output": "Disconnected"
|
||||
},
|
||||
{
|
||||
"input": 6,
|
||||
"output": "Stopped"
|
||||
},
|
||||
{
|
||||
"input": 7,
|
||||
"output": "Enabled Not Running"
|
||||
},
|
||||
{
|
||||
"input": 8,
|
||||
"output": "Encoder Fault"
|
||||
},
|
||||
{
|
||||
"input": 9,
|
||||
"output": "Energy Management"
|
||||
},
|
||||
{
|
||||
"input": 10,
|
||||
"output": "ESTOP Was Actuated"
|
||||
},
|
||||
{
|
||||
"input": 11,
|
||||
"output": "EStopped"
|
||||
},
|
||||
{
|
||||
"input": 12,
|
||||
"output": "EStopped Locally"
|
||||
},
|
||||
{
|
||||
"input": 13,
|
||||
"output": "Extended Faulted"
|
||||
},
|
||||
{
|
||||
"input": 14,
|
||||
"output": "Full"
|
||||
},
|
||||
{
|
||||
"input": 15,
|
||||
"output": "Gaylord Start Pressed"
|
||||
},
|
||||
{
|
||||
"input": 16,
|
||||
"output": "Jam Fault"
|
||||
},
|
||||
{
|
||||
"input": 17,
|
||||
"output": "Jammed"
|
||||
},
|
||||
{
|
||||
"input": 18,
|
||||
"output": "Loading Allowed"
|
||||
},
|
||||
{
|
||||
"input": 19,
|
||||
"output": "Loading Not Allowed"
|
||||
},
|
||||
{
|
||||
"input": 20,
|
||||
"output": "Low Air Pressure Fault Was Present"
|
||||
},
|
||||
{
|
||||
"input": 21,
|
||||
"output": "Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 22,
|
||||
"output": "Conveyor Stopped In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 23,
|
||||
"output": "Motor Faulted"
|
||||
},
|
||||
{
|
||||
"input": 24,
|
||||
"output": "Motor Was Faulted"
|
||||
},
|
||||
{
|
||||
"input": 25,
|
||||
"output": "Normal"
|
||||
},
|
||||
{
|
||||
"input": 26,
|
||||
"output": "Off Inactive"
|
||||
},
|
||||
{
|
||||
"input": 27,
|
||||
"output": "Open"
|
||||
},
|
||||
{
|
||||
"input": 28,
|
||||
"output": "PLC Ready To Run"
|
||||
},
|
||||
{
|
||||
"input": 29,
|
||||
"output": "Package Release Pressed"
|
||||
},
|
||||
{
|
||||
"input": 30,
|
||||
"output": "Power Branch Was Faulted"
|
||||
},
|
||||
{
|
||||
"input": 31,
|
||||
"output": "Pressed"
|
||||
},
|
||||
{
|
||||
"input": 32,
|
||||
"output": "Ready To Receive"
|
||||
},
|
||||
{
|
||||
"input": 33,
|
||||
"output": "Running"
|
||||
},
|
||||
{
|
||||
"input": 34,
|
||||
"output": "Started"
|
||||
},
|
||||
{
|
||||
"input": 35,
|
||||
"output": "Stopped"
|
||||
},
|
||||
{
|
||||
"input": 36,
|
||||
"output": "System Started"
|
||||
},
|
||||
{
|
||||
"input": 37,
|
||||
"output": "Unknown"
|
||||
},
|
||||
{
|
||||
"input": 38,
|
||||
"output": "VFD Fault"
|
||||
},
|
||||
{
|
||||
"input": 39,
|
||||
"output": "Conveyor Running In Power Saving Mode"
|
||||
},
|
||||
{
|
||||
"input": 40,
|
||||
"output": "Conveyor Jogging In Maintenance Mode"
|
||||
},
|
||||
{
|
||||
"input": 41,
|
||||
"output": "VFD Reset Required"
|
||||
},
|
||||
{
|
||||
"input": 42,
|
||||
"output": "Jam Reset Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 43,
|
||||
"output": "Start Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 44,
|
||||
"output": "Stop Push Button Pressed"
|
||||
},
|
||||
{
|
||||
"input": 45,
|
||||
"output": "No Container"
|
||||
},
|
||||
{
|
||||
"input": 46,
|
||||
"output": "Ready To Be Enabled"
|
||||
},
|
||||
{
|
||||
"input": 47,
|
||||
"output": "Half Full"
|
||||
},
|
||||
{
|
||||
"input": 48,
|
||||
"output": "Enabled"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
"persistent": true
|
||||
},
|
||||
"params.angle": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
},
|
||||
"params.directionLeft": {
|
||||
"paramDirection": "input",
|
||||
"persistent": true
|
||||
},
|
||||
"params.tagProps": {
|
||||
"paramDirection": "inout",
|
||||
"persistent": true
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"defaultSize": {
|
||||
"height": 20,
|
||||
"width": 29
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"name": "RunningStatus"
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"position.display": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({view.custom.priority} \u003d \"No Active Alarms\", true, false)"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.elements[0].fill.paint": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n {view.custom.state} \u003d \"Closed\",\r\n \"#000000\",\r\n {view.custom.color}\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.style.transform": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Maintenance/Direction"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\"\")",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": true,
|
||||
"output": "scaleX(-1)"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": "ErrorStatus",
|
||||
"tooltip": {
|
||||
"style": {
|
||||
"fontSize": 16
|
||||
}
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"grow": 1
|
||||
},
|
||||
"propConfig": {
|
||||
"position.display": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if({view.custom.priority} \u003d \"No Active Alarms\", false, true)"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.elements[0].fill.paint": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.priority"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": "#FF0000"
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": "#FF8C00"
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": "#FFFF00"
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": "#007EFC"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.elements[1].fill.paint": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\r\n {view.custom.state} \u003d \"Closed\",\r\n \"#000000\",\r\n {view.custom.color}\r\n)\r\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"props.elements[2].fill": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.priority"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "#000000",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": "#FFFFFF"
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": "#000000"
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": "#000000"
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": "#FFFFFF"
|
||||
}
|
||||
],
|
||||
"outputType": "color",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.elements[2].text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.priority"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": 0,
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": 1
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": 3
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": 2
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": 1
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.style.transform": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"fallbackDelay": 2.5,
|
||||
"mode": "indirect",
|
||||
"references": {
|
||||
"0": "{view.params.tagProps[0]}",
|
||||
"fc": "{session.custom.fc}"
|
||||
},
|
||||
"tagPath": "[{fc}_SCADA_TAG_PROVIDER]{0}/Maintenance/Direction"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"expression": "coalesce({value},{view.params.forceFaultStatus},\"\")",
|
||||
"type": "expression"
|
||||
},
|
||||
{
|
||||
"fallback": "",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": true,
|
||||
"output": "scaleX(-1)"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "tag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"width": 2
|
||||
},
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"events": {
|
||||
"dom": {
|
||||
"onClick": {
|
||||
"config": {
|
||||
"script": "\tsystem.perspective.openDock(\u0027Docked-East-VFD\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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "root",
|
||||
"tooltip": {
|
||||
"enabled": true,
|
||||
"location": "top-left",
|
||||
"style": {}
|
||||
}
|
||||
},
|
||||
"propConfig": {
|
||||
"meta.tooltip.style.classes": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "{view.custom.priority}"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "Alarms-Styles/NoAlarm",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": "High",
|
||||
"output": "Alarms-Styles/High"
|
||||
},
|
||||
{
|
||||
"input": "Medium",
|
||||
"output": "Alarms-Styles/Medium"
|
||||
},
|
||||
{
|
||||
"input": "Low",
|
||||
"output": "Alarms-Styles/Low"
|
||||
},
|
||||
{
|
||||
"input": "Diagnostic",
|
||||
"output": "Alarms-Styles/Diagnostic"
|
||||
}
|
||||
],
|
||||
"outputType": "style-list",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.tooltip.text": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "if(\n {view.custom.state} !\u003d \"Closed\",\n \"Source Id: \" + {view.params.tagProps[0]} + \", Priority: \" + {view.custom.priority} + \", State: \" + {view.custom.state},\n \"Device Disconnected\"\n)\n"
|
||||
},
|
||||
"type": "expr"
|
||||
}
|
||||
},
|
||||
"meta.visible": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "session.custom.alarm_filter.show_running"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.style.borderStyle": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "view.custom.disconnected"
|
||||
},
|
||||
"enabled": false,
|
||||
"transforms": [
|
||||
{
|
||||
"fallback": "",
|
||||
"inputType": "scalar",
|
||||
"mappings": [
|
||||
{
|
||||
"input": true,
|
||||
"output": "solid"
|
||||
},
|
||||
{
|
||||
"input": false,
|
||||
"output": "none"
|
||||
}
|
||||
],
|
||||
"outputType": "scalar",
|
||||
"type": "map"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"justify": "center",
|
||||
"style": {
|
||||
"borderColor": "#FF0000",
|
||||
"borderStyle": "none",
|
||||
"borderWidth": "2px",
|
||||
"cursor": "pointer"
|
||||
}
|
||||
},
|
||||
"type": "ia.container.flex"
|
||||
}
|
||||
}
|
||||
@ -279,13 +279,6 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1,125 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||