156 lines
6.1 KiB
Plaintext
156 lines
6.1 KiB
Plaintext
################################################################
|
|
################################################################
|
|
## Version: 1.0 / Author: Dillon Uzar
|
|
##
|
|
## DESC: For use in FMS in recording Flow Management data
|
|
## WARN: Modifying code may cause system to function incorrectly
|
|
################################################################
|
|
################################################################
|
|
|
|
import json
|
|
import system
|
|
import time
|
|
|
|
#######################################################
|
|
#######################################################
|
|
#######################################################
|
|
#### Constants
|
|
#######################################################
|
|
|
|
# Logger:
|
|
LOG = system.util.logger("FMS Handler")
|
|
|
|
# For inserting data into database:
|
|
INSERT_QUERY = "INSERT INTO fms_history (conveyor, segment, data) VALUES (?,?,?)"
|
|
|
|
#######################################################
|
|
#######################################################
|
|
#######################################################
|
|
#### Parsing Utils
|
|
#######################################################
|
|
|
|
def extractNibble(val, nibble):
|
|
if val is not None:
|
|
return (val >> (nibble*4)) & 0x0F
|
|
|
|
def logTime(title, conv, seg, data, start_time):
|
|
millisec = round((time.time() - start_time) * 1000, 1)
|
|
LOG.info("%s[CONV=%s][SEG=%s][DATA=%s] took %sms to process" % (title, conv, seg, data, millisec))
|
|
|
|
#######################################################
|
|
#######################################################
|
|
#######################################################
|
|
#### Tag Event Handling
|
|
#######################################################
|
|
|
|
def logSegment(conveyor, segment, data):
|
|
# Log event in SQL:
|
|
# Insert into FMS History:
|
|
start_time = time.time()
|
|
INSERT_QUERY = "INSERT INTO fms_history (conveyor, segment, data) VALUES (?,?,?)"
|
|
system.db.runPrepUpdate(INSERT_QUERY, [conveyor, segment, data])
|
|
#logTime("FMS[DB_INSERT]", conveyor, segment, data, start_time)
|
|
|
|
def dintOnChange(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
|
|
# Don't execute on startup, or if new value is bad quality:
|
|
if currentValue.quality.isGood():
|
|
# Only consider it a change if the value is different:
|
|
if currentValue.value <> previousValue.value:
|
|
id = int(tagPath.split("/")[-1].replace("DINT", ""))
|
|
conveyor = tag['parameters']['LabelFull']
|
|
# ID=0 is unique where the first nibble is the average of all segments, the 7 other segments are normal segments:
|
|
if id == 0:
|
|
# Ignore first nibble, which is the average of all segments:
|
|
for i in range(1, 8):
|
|
# Check if segment changed:
|
|
curVal = extractNibble(currentValue.value, i)
|
|
prevVal = extractNibble(previousValue.value, i)
|
|
if curVal <> prevVal:
|
|
segment = i - 1
|
|
logSegment(conveyor, segment, curVal)
|
|
else:
|
|
for i in range(0, 8):
|
|
# Check if segment changed:
|
|
curVal = extractNibble(currentValue.value, i)
|
|
prevVal = extractNibble(previousValue.value, i)
|
|
if curVal <> prevVal:
|
|
segment = i + (id-1)*8 + 7
|
|
logSegment(conveyor, segment, curVal)
|
|
|
|
#######################################################
|
|
#######################################################
|
|
#######################################################
|
|
#### Graphics Tag Scripts
|
|
#######################################################
|
|
|
|
"""
|
|
radial-gradient(circle at 30%,
|
|
#f5bff5 calc((var(--conv-width) - 4px)/2*0.25),
|
|
#000 calc((var(--conv-width) - 4px)/2*0.25),
|
|
#000 calc((var(--conv-width) - 4px)/2*0.25 + 1px),
|
|
transparent calc((var(--conv-width) - 4px)/2*0.25 + 1px)),
|
|
radial-gradient(circle at 50%, #d900d9 calc((var(--conv-width) - 4px)/2*1), #000 calc((var(--conv-width) - 4px)/2*1), #000 calc((var(--conv-width) - 4px)/2*1 + 1px), transparent calc((var(--conv-width) - 4px)/2*0.25 + 1px)), radial-gradient(circle at 70%, #ec7fec 7px, #000 7px, #000 8px, transparent 8px), radial-gradient(circle at 90%, #e23fe2 10px, #000 10px, #000 11px, transparent 11px), #00D900
|
|
"""
|
|
|
|
|
|
def genSegmentsTable(obj):
|
|
segments = []
|
|
if obj is not None and obj["Count"] is not None:
|
|
for i in range(1, obj["Count"]+1):
|
|
dint = "DINT"+str(int(i/8))
|
|
if obj[dint] is not None:
|
|
percent = extractNibble(obj[dint], i % 8) / 15.0
|
|
segments.append([i, percent])
|
|
return system.dataset.toDataSet(["segment", "fill"], segments)
|
|
|
|
def genSegmentColor(data):
|
|
perc = (data/15.0)
|
|
c1 = 255 - (255 - 217)*perc
|
|
c2 = 255 - (255 - 0)*perc
|
|
return "rgb(%s, %s, %s)" % (c1, c2, c1)
|
|
|
|
def genSegmentsPattern(obj):
|
|
if obj["Count"] is not None and obj["Count"] > 0:
|
|
percUnit = 100 / float(obj["Count"])
|
|
gradients = []
|
|
for i in range(1, obj["Count"]+1):
|
|
dint = "DINT"+str(int(i/8))
|
|
if obj[dint] is not None:
|
|
data = extractNibble(obj[dint], i % 8)
|
|
color = genSegmentColor(data)
|
|
circlePos = ((obj["Count"]-i))*percUnit + percUnit/2.0
|
|
perc = (data/15.0*0.5+0.5) if data > 0 else 0.0 # Make circle size between 50%-100%
|
|
if perc > 0.0:
|
|
output = "radial-gradient(circle at %s%%" % (circlePos)
|
|
output += ", %s calc((var(--conv-width) - 8px)/2*%s)" % (color, perc)
|
|
output += ", #000 calc((var(--conv-width) - 8px)/2*%s)" % (perc)
|
|
output += ", #000 calc((var(--conv-width) - 8px)/2*%s + 1px)" % (perc)
|
|
output += ", transparent calc((var(--conv-width) - 8px)/2*%s + 1px)" % (perc)
|
|
output += ")"
|
|
gradients.append(output)
|
|
if len(gradients) > 0:
|
|
return ", ".join(gradients)+","
|
|
return ""
|
|
|
|
def genSegmentsTooltip(obj):
|
|
if obj["Count"] is not None and obj["Count"] > 0:
|
|
data = extractNibble(obj["DINT0"], 0)
|
|
output = "<br><br>SegmentAVG: %s%%" % (int(round(100 * data / 15.0)))
|
|
for i in range(1, obj["Count"]+1):
|
|
dint = "DINT"+str(int(i/8))
|
|
if obj[dint] is not None:
|
|
data = extractNibble(obj[dint], i % 8)
|
|
output += "<br>Segment%s: %s%%" % (i, int(round(100 * data / 15.0)))
|
|
return output
|
|
return ""
|
|
|
|
def genSegmentHeatmap(obj):
|
|
segments = []
|
|
if obj["Count"] is not None and obj["Count"] > 0:
|
|
for i in range(1, obj["Count"]+1):
|
|
dint = "DINT"+str(int(i/8))
|
|
if obj[dint] is not None:
|
|
data = extractNibble(obj[dint], i % 8)
|
|
color = 255 * data / 15
|
|
segments.append("rgb(255, %s, %s)" % (color, color))
|
|
return json.dumps(segments) |