随着人机界面(HMI)深度融合各类IT技术,其应用领域得到了持续拓宽,不仅在工业、医疗、能源等领域发挥着重要作用,还深入到了智能家居等多元化系统之中。HMI的广泛应用,正推动着各行各业的智能化进程,提升着系统操作的便捷性和效率。
然而,随着应用领域的不断扩大,HMI在不同行业中所面临的挑战和瓶颈也日益凸显。为了突破这些应用上的限制,威纶通推出了创新的「JS元件」功能。这一功能不仅赋予了用户扩展HMI现有功能的能力,更通过串接多样化的API,满足了各行业对特殊需求的支持,从而进一步拓展了HMI的应用边界。
JS元件的推出,是威纶通在HMI技术领域的一次重大突破。它打破了传统框架的限制,为开发人员提供了更加灵活、强大的工具。结合自行开发的JavaScript程序码,开发人员能够利用JS元件实现存取PLC设备数据、逻辑运算等多种功能。与Macro所提供的功能相比,JS元件展现出更加出色且多元化的性能,能够轻松应对各种复杂的应用场景。
因此,无论是工业生产的自动化控制,还是医疗设备的智能化管理,亦或是智能家居的便捷操作,JS元件都能发挥出其独特的优势,推动HMI在更多领域实现创新应用。威纶通将继续致力于HMI技术的研发与创新,为各行业提供更高效、更智能的解决方案。
操作方法也很简单:
通过编程软件-JS元件添加
编写JS代码进行功能的实现,JavaScript 是一个相当成熟的程序语言,功能强大且实用,有许多现成的程序码可以提供参考。通过EasyBuilder Pro中的「JS资源」功能,让您在设计JS元件时,方便直接套用现有的JavaScript模块,快速打造出独一无二的HMI应用程序。
源代码如下:
// defs
const SectionInterval = 100;
const SectionCount = 3; // for both horizontal and vertical directions
const NumberCount = SectionCount * SectionCount;
const NumberSensibleWidth = 50;
const encoder = new TextEncoder();
const MatchResult = {
Undetermined: 0,
Success: 1,
Failure: 2,
};
// assign JS object to 'self'
var self = this;
// sets up UI
var patternCanvas = new Canvas();
var floatLineCanvas = new Canvas();
var mouseArea = new MouseArea();
self.widget.add(patternCanvas);
self.widget.add(floatLineCanvas);
self.widget.add(mouseArea);
initNumberSensibleRect();
reset();
mouseArea.on('mousedown', (mouseEvent) => {
setMatchResult(MatchResult.Undetermined);
let num = hitTest(mouseEvent);
if (num >= 0) {
addNumberToPattern(num);
}
});
mouseArea.on('mousemove', (mouseEvent) => {
clearFloatLine();
// new number?
let num = hitTest(mouseEvent);
if (num >= 0 && !isNumberInPattern(num)) {
addNumberToPattern(num);
} else if (self.pattern.length > 0 && self.pattern.length < NumberCount) {
addFloatLine(mouseEvent);
}
});
mouseArea.on('mouseup', (mouseEvent) => {
outputPattern();
outputMatchResult();
reset();
});
//===================================================================
function initNumberSensibleRect() {
self.numberSensibleRect = new Array(NumberCount);
for (let x = 0; x < SectionCount; x++) {
for (let y = 0; y < SectionCount; y++) {
let dot = x + y * SectionCount;
self.numberSensibleRect[dot] = {
x: x * SectionInterval + SectionInterval / 2 - NumberSensibleWidth / 2,
y: y * SectionInterval + SectionInterval / 2 - NumberSensibleWidth / 2,
width: NumberSensibleWidth,
height: NumberSensibleWidth
};
}
}
}
function reset() {
console.log('[reset]');
self.pattern = [];
updateNumberValues();
clearCanvas(patternCanvas);
clearCanvas(floatLineCanvas);
}
function hitTest(mouseEvent) {
for (let i = 0; i < self.numberSensibleRect.length; ++i) {
let sensibleRect = self.numberSensibleRect[i];
if (mouseEvent.x >= sensibleRect.x && mouseEvent.x < (sensibleRect.x + sensibleRect.width) &&
mouseEvent.y >= sensibleRect.y && mouseEvent.y < (sensibleRect.y + sensibleRect.height)) {
return i;
}
}
return -1;
}
function addNumberToPattern(num) {
self.pattern.push(num);
console.log('[addNumberToPattern] pattern =', self.pattern);
updateNumberValues();
updatePatternCanvas();
}
function isNumberInPattern(num) {
return (self.pattern.indexOf(num) >= 0);
}
function clearCanvas(canvas) {
canvas.clearRect(0, 0, canvas.width, canvas.height);
}
function updatePatternCanvas() {
if (self.pattern.length >= 2) {
let canvas = patternCanvas;
let startingPoint = pointFromNumber(self.pattern[0]);
clearCanvas(canvas);
canvas.strokeStyle = self.config.lineColor;
canvas.lineWidth = 3;
canvas.beginPath();
canvas.moveTo(startingPoint.x, startingPoint.y);
for (let i = 1; i < self.pattern.length; i++) {
let point = pointFromNumber(self.pattern[i]);
canvas.lineTo(point.x, point.y);
}
canvas.stroke();
}
}
function addFloatLine(mouseEvent) {
if (self.pattern.length > 0) {
let canvas = floatLineCanvas;
let lastPoint = pointFromNumber(self.pattern[self.pattern.length - 1]);
canvas.strokeStyle = self.config.lineColor;
canvas.lineWidth = 3;
canvas.beginPath();
canvas.moveTo(lastPoint.x, lastPoint.y);
canvas.lineTo(mouseEvent.x, mouseEvent.y);
canvas.stroke();
}
}
function clearFloatLine() {
clearCanvas(floatLineCanvas);
}
function outputPattern() {
// prepare pattern string
let strPattern = '';
self.pattern.forEach((num) => {
strPattern += (num + 1);
});
console.log('[outputPattern] pattern =', strPattern);
// output pattern to address
let encodedPattern = encoder.encode(strPattern);
let bufferSize = driver.Address.getDataTypeSize(self.config.savedPatternSub.address.dataType) * self.config.savedPatternSub.length;
let buffer = new ArrayBuffer(bufferSize);
let data = new Uint8Array(buffer);
data.set(encodedPattern);
driver.setData(self.config.patternAddress, buffer);
self.patternDataBuffer = buffer;
}
function setMatchResult(value) {
driver.setData(self.config.matchResultAddress, value);
}
function outputMatchResult() {
setMatchResult(isBufferEqualTo(self.patternDataBuffer, self.config.savedPatternSub.latestData.buffer)
? MatchResult.Success
: MatchResult.Failure);
}
function updateNumberValues() {
let values = new Array(NumberCount);
values.fill(0);
self.pattern.forEach((num) => {
values[num] = 1;
});
driver.setData(self.config.numberValueAddress, values);
}
function pointFromNumber(num) {
let x = num % SectionCount;
let y = Math.floor(num / SectionCount);
return {
x: x * SectionInterval + SectionInterval / 2,
y: y * SectionInterval + SectionInterval / 2
};
}
function isBufferEqualTo(lhs, rhs) {
if (lhs.byteLength == rhs.byteLength) {
let lhs_array = new Uint8Array(lhs);
let rhs_array = new Uint8Array(rhs);
for (let i = 0; i < lhs_array.length ; i++) {
if (lhs_array[i] != rhs_array[i]) {
return false;
}
}
return true;
} else {
return false;
}
}
本文资料来源于威纶通官网