[Project] Initial Commit
This commit is contained in:
parent
b040e85637
commit
a90ad2dfd1
|
@ -0,0 +1,4 @@
|
|||
# Created by .ignore support plugin (hsz.mobi)
|
||||
.idea/
|
||||
bower_components/
|
||||
*.iml
|
|
@ -1,2 +1,2 @@
|
|||
# strolch-plc-ui
|
||||
The UI for the software PLC based on Strolch's runtime
|
||||
# strolch-wc-plc
|
||||
The UI components for the software PLC based on Strolch's runtime
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"name": "strolch-wc-plc",
|
||||
"description": "Strolch PLC WebComponents",
|
||||
"version": "0.1.0",
|
||||
"authors": ["Robert von Burg"],
|
||||
"keywords": [
|
||||
"strolch",
|
||||
"inspector"
|
||||
],
|
||||
"main": "strolch-wc-plc-logical-devices.html",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:4treesCH/strolch-wc-plc.git"
|
||||
},
|
||||
"license": "https://github.com/4treesCH/strolch-wc-plc/blob/master/LICENSE",
|
||||
"homepage": "https://github.com/4treesCH/strolch-wc-plc",
|
||||
"ignore": [],
|
||||
"dependencies": {
|
||||
"strolchjs": "4treesCH/strolchjs#^0.2.7",
|
||||
"strolch-wc-styles": "4treesCH/strolch-wc-styles#^0.3.0",
|
||||
"strolch-wc-debounced-input": "4treesCH/strolch-wc-debounced-input#^0.1.0",
|
||||
"strolch-wc-tree": "4treesCH/strolch-wc-tree#^0.1.5",
|
||||
"strolch-wc-ws-observer": "4treesCH/strolch-wc-ws-observer#^0.1.5",
|
||||
"strolch-wc-localize-behavior": "4treesCH/strolch-wc-localize-behavior#^1.1.4",
|
||||
|
||||
"polymer": "Polymer/polymer#^1.11.3",
|
||||
|
||||
"iron-ajax": "PolymerElements/iron-ajax#^1.4.4",
|
||||
"iron-pages": "PolymerElements/iron-pages#^1.0.9",
|
||||
"iron-icons": "PolymerElements/iron-icons#^1.2.1",
|
||||
"iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.9",
|
||||
|
||||
"app-route": "PolymerElements/app-route#^1.0.1",
|
||||
"app-layout": "PolymerElements/app-layout#^1.0.1",
|
||||
|
||||
"paper-material": "PolymerElements/paper-material#^1.0.7",
|
||||
"paper-header-panel": "PolymerElements/paper-header-panel#^1.1.7",
|
||||
"paper-card": "PolymerElements/paper-card#^1.1.6",
|
||||
"paper-badge": "PolymerElements/paper-badge#^1.1.4",
|
||||
"paper-dialog": "PolymerElements/paper-dialog#^1.1.0",
|
||||
"paper-button": "PolymerElements/paper-button#^1.0.15",
|
||||
"paper-toolbar": "PolymerElements/paper-toolbar#^1.1.7",
|
||||
"paper-icon-button": "PolymerElements/paper-icon-button#^1.1.6",
|
||||
"paper-tabs": "PolymerElements/paper-tabs#^1.8.0",
|
||||
"paper-dropdown-menu": "PolymerElements/paper-dropdown-menu#^1.5.1",
|
||||
"paper-styles": "PolymerElements/paper-styles#^1.3.1",
|
||||
"paper-listbox": "polymerelements/paper-listbox#^1.1.3",
|
||||
"paper-item": "PolymerElements/paper-item#^1.2.2",
|
||||
"paper-input": "PolymerElements/paper-input#^1.2.1",
|
||||
"paper-checkbox": "PolymerElements/paper-checkbox#^1.4.2",
|
||||
"paper-radio-group": "PolymerElements/paper-radio-group#^1.2.2",
|
||||
|
||||
"vaadin-date-picker": "vaadin/vaadin-date-picker#^1.2.4",
|
||||
"vaadin-upload": "vaadin/vaadin-upload#v2.1.3"
|
||||
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"de": {
|
||||
"refresh": "Aktualisieren",
|
||||
"close": "Schliessen",
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "Ok",
|
||||
"plcConnections": "SPS Verbindungen",
|
||||
"plcLogicalDevices": "SPS Logische Geräte",
|
||||
"class": "Klasse",
|
||||
"connect": "Verbinden",
|
||||
"disconnect": "Trennen",
|
||||
"Connected": "Verbunden",
|
||||
"Disconnected": "Getrennt",
|
||||
"addresses": "Adressen",
|
||||
"notifications": "Benachrichtigungen",
|
||||
"telegrams": "Telegramme",
|
||||
"send": "Senden",
|
||||
"notify": "Benachrichtigen",
|
||||
"id": "ID",
|
||||
"name": "Name",
|
||||
"on": "Ein",
|
||||
"off": "Aus",
|
||||
"address": "Adresse",
|
||||
"i2cBus": "I2C Bus",
|
||||
"interruptPinName": "Interrupt Pin",
|
||||
"virtualAddresses": "Virtuelle Adressen",
|
||||
"errorOccurred": "Fehler aufgetreten",
|
||||
"plc": "SPS",
|
||||
"start": "Starten",
|
||||
"stop": "Stoppen",
|
||||
"reconfigure": "Neu Konfigurieren",
|
||||
"info": "Info",
|
||||
"reconnect": "Wiederhestellen"
|
||||
},
|
||||
"en": {
|
||||
"info": "Info",
|
||||
"start": "Start",
|
||||
"stop": "Stop",
|
||||
"reconfigure": "Reconfigure",
|
||||
"plc": "PLC",
|
||||
"errorOccurred": "Error Occurred",
|
||||
"virtualAddresses": "Virtual Addresses",
|
||||
"on": "On",
|
||||
"off": "Off",
|
||||
"address": "Address",
|
||||
"i2cBus": "I2C Bus",
|
||||
"interruptPinName": "Interrupt Pin",
|
||||
"id": "ID",
|
||||
"name": "Name",
|
||||
"send": "Send",
|
||||
"notify": "Notify",
|
||||
"addresses": "Addresses",
|
||||
"notifications": "Notifications",
|
||||
"telegrams": "Telegrams",
|
||||
"Connected": "Connected",
|
||||
"Disconnected": "Disconnected",
|
||||
"connect": "Connect",
|
||||
"disconnect": "Disconnect",
|
||||
"class": "Class",
|
||||
"plcConnections": "PLC Connections",
|
||||
"plcLogicalDevices": "PLC Logical Devices",
|
||||
"logout": "Logout",
|
||||
"refresh": "Refresh",
|
||||
"close": "Close",
|
||||
"cancel": "Cancel",
|
||||
"ok": "Ok",
|
||||
"reconnect": "Reconnect"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<link rel="import" href="../polymer/polymer.html">
|
||||
|
||||
<script>
|
||||
StrolchPlcBehavior = {
|
||||
|
||||
properties: {
|
||||
localesPath: {
|
||||
type: String,
|
||||
value: './locales.json'
|
||||
}
|
||||
},
|
||||
|
||||
arrayFilled: function (array) {
|
||||
return !!(array && array.length && array.length > 0);
|
||||
},
|
||||
|
||||
isTelegram: function (addressType) {
|
||||
return addressType === "Telegram";
|
||||
},
|
||||
isNotification: function (addressType) {
|
||||
return addressType === "Notification";
|
||||
},
|
||||
|
||||
isBoolean: function (type) {
|
||||
return type === 'Boolean';
|
||||
},
|
||||
isNumber: function (type) {
|
||||
switch (type) {
|
||||
case 'Short':
|
||||
case 'Integer':
|
||||
case 'Long':
|
||||
case 'Float':
|
||||
case 'Double':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isInteger: function (type) {
|
||||
switch (type) {
|
||||
case 'Short':
|
||||
case 'Integer':
|
||||
case 'Long':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isFloat: function (type) {
|
||||
switch (type) {
|
||||
case 'Float':
|
||||
case 'Double':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isString: function (type) {
|
||||
switch (type) {
|
||||
case 'String':
|
||||
case 'ByteArray':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
isPlcError: function (plc) {
|
||||
return plc.state === "Failed";
|
||||
},
|
||||
isError: function (device) {
|
||||
return device.state === "Error" || device.stateMsg !== "";
|
||||
},
|
||||
isOn: function (device) {
|
||||
return device.state === "On";
|
||||
},
|
||||
|
||||
onRequestError: function (e) {
|
||||
this.fire("strolch-ajax-request-error", e.detail);
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,233 @@
|
|||
<link rel="import" href="../polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../iron-ajax/iron-ajax.html">
|
||||
<link rel="import" href="../iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../iron-icons/notification-icons.html">
|
||||
<link rel="import" href="../iron-icons/maps-icons.html">
|
||||
<link rel="import" href="../iron-icons/av-icons.html">
|
||||
<link rel="import" href="../iron-icons/communication-icons.html">
|
||||
<link rel="import" href="../iron-icons/device-icons.html">
|
||||
<link rel="import" href="../iron-icons/hardware-icons.html">
|
||||
<link rel="import" href="../iron-icons/editor-icons.html">
|
||||
<link rel="import" href="../iron-icons/places-icons.html">
|
||||
<link rel="import" href="../iron-icons/social-icons.html">
|
||||
|
||||
<link rel="import" href="../paper-material/paper-material.html">
|
||||
<link rel="import" href="../paper-card/paper-card.html">
|
||||
<link rel="import" href="../paper-button/paper-button.html">
|
||||
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
|
||||
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html">
|
||||
|
||||
<link rel="import" href="../strolch-wc-localize-behavior/strolch-wc-localize-behavior.html">
|
||||
|
||||
<link rel="import" href="./strolch-wc-plc-style.html">
|
||||
<link rel="import" href="./strolch-wc-plc-behavior.html">
|
||||
|
||||
<dom-module id="strolch-wc-plc-connections">
|
||||
<template>
|
||||
|
||||
<style is="custom-style" include="strolch-wc-plc-style">
|
||||
.label {
|
||||
min-width: 250px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="actions">
|
||||
<paper-icon-button icon="refresh" on-tap="_refresh"></paper-icon-button>
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
<paper-card class="item" elevation="1">
|
||||
<div class="header"><h3>[[localize('plc')]]</h3></div>
|
||||
<div class="card-content g-flex-table">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">[[localize('class')]]</div>
|
||||
<div class="g-flex-table-cell">[[plc.className]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">
|
||||
<template is="dom-if" if="[[isPlcError(plc)]]">
|
||||
<iron-icon class="error-icon" icon="warning"></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isPlcError(plc)]]">
|
||||
<iron-icon icon="info-outline"></iron-icon>
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-if" if="[[isPlcError(plc)]]">
|
||||
<div class="g-flex-table-cell">[[plc.stateMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isPlcError(plc)]]">
|
||||
<div class="g-flex-table-cell">[[localize(plc.state)]]</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<dfiv class="card-actions-right">
|
||||
<paper-button on-tap="startPlc" raised>[[localize('start')]]
|
||||
</paper-button>
|
||||
<paper-button on-tap="stopPlc" raised>[[localize('stop')]]
|
||||
</paper-button>
|
||||
<paper-button on-tap="reconfigurePlc" raised>[[localize('reconfigure')]]
|
||||
</paper-button>
|
||||
</dfiv>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<template is="dom-repeat" items="[[connections]]" as="connection">
|
||||
|
||||
<paper-card class="item" elevation="1">
|
||||
<div class="header"><h3>[[connection.id]] / [[connection.name]]</h3></div>
|
||||
<div class="card-content g-flex-table">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">[[localize('id')]]</div>
|
||||
<div class="g-flex-table-cell">[[connection.id]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">[[localize('name')]]</div>
|
||||
<div class="g-flex-table-cell">[[connection.name]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">[[localize('class')]]</div>
|
||||
<div class="g-flex-table-cell">[[connection.className]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">
|
||||
<template is="dom-if" if="[[isError(connection)]]">
|
||||
<iron-icon class="error-icon" icon="warning"></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isError(connection)]]">
|
||||
<iron-icon icon="info-outline"></iron-icon>
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-if" if="[[isError(connection)]]">
|
||||
<div class="g-flex-table-cell">[[connection.stateMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isError(connection)]]">
|
||||
<div class="g-flex-table-cell">[[localize(connection.state)]]</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template is="dom-repeat" items="[[connection.parameters]]" as="param">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell label">[[param.id]]</div>
|
||||
<div class="g-flex-table-cell">[[param.value]]</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<dfiv class="card-actions-right">
|
||||
<paper-button on-tap="connect" raised>[[localize('connect')]]
|
||||
</paper-button>
|
||||
<paper-button on-tap="disconnect" raised>[[localize('disconnect')]]
|
||||
</paper-button>
|
||||
</dfiv>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<iron-ajax id="ajaxGetPlc"
|
||||
url="[[baseRestPath]]/plc/state"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetPlcResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxGetConnections"
|
||||
url="[[baseRestPath]]/plc/connections"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetConnectionsResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxPutPlcState"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="PUT"
|
||||
on-response="_refresh"
|
||||
on-error="onAjaxError"></iron-ajax>
|
||||
<iron-ajax id="ajaxPutConnectionState"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="PUT"
|
||||
on-response="_refresh"
|
||||
on-error="onAjaxError"></iron-ajax>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'strolch-wc-plc-connections',
|
||||
|
||||
behaviors: [
|
||||
StrolchLocalizeBehavior, StrolchPlcBehavior
|
||||
],
|
||||
|
||||
properties: {
|
||||
plc: {
|
||||
type: Object
|
||||
},
|
||||
connections: {
|
||||
type: Array,
|
||||
value: []
|
||||
}
|
||||
},
|
||||
|
||||
onGetConnectionsResponse: function (e) {
|
||||
this.connections = e.detail.response.data;
|
||||
},
|
||||
onGetPlcResponse: function (e) {
|
||||
this.plc = e.detail.response.data;
|
||||
},
|
||||
|
||||
isError: function (connection) {
|
||||
return connection != null && connection.state === "Failed";
|
||||
},
|
||||
|
||||
connect: function (e) {
|
||||
this.sendSwitchState(e.model.connection.id, "Connected");
|
||||
},
|
||||
disconnect: function (e) {
|
||||
this.sendSwitchState(e.model.connection.id, "Disconnected");
|
||||
},
|
||||
sendSwitchState: function (connectionId, state) {
|
||||
this.$.ajaxPutConnectionState.url = this.baseRestPath + "/plc/connections/" + connectionId + "/state/" + state;
|
||||
this.$.ajaxPutConnectionState.body = null;
|
||||
this.$.ajaxPutConnectionState.generateRequest();
|
||||
},
|
||||
|
||||
startPlc: function (e) {
|
||||
this.sendPlcState("Started");
|
||||
},
|
||||
stopPlc: function (e) {
|
||||
this.sendPlcState("Stopped");
|
||||
},
|
||||
reconfigurePlc: function (e) {
|
||||
this.sendPlcState("Configured");
|
||||
},
|
||||
sendPlcState: function (state) {
|
||||
this.$.ajaxPutPlcState.url = this.baseRestPath + "/plc/state/" + state;
|
||||
this.$.ajaxPutPlcState.body = null;
|
||||
this.$.ajaxPutPlcState.generateRequest();
|
||||
},
|
||||
|
||||
reload: function (e) {
|
||||
this._refresh();
|
||||
},
|
||||
_refresh: function (e) {
|
||||
this.$.ajaxGetPlc.generateRequest();
|
||||
this.$.ajaxGetConnections.generateRequest();
|
||||
},
|
||||
onAjaxError: function (e) {
|
||||
this._refresh();
|
||||
this.onRequestError(e);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
|
@ -0,0 +1,286 @@
|
|||
<link rel="import" href="../polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../iron-ajax/iron-ajax.html">
|
||||
<link rel="import" href="../iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../iron-icons/notification-icons.html">
|
||||
<link rel="import" href="../iron-icons/maps-icons.html">
|
||||
<link rel="import" href="../iron-icons/av-icons.html">
|
||||
<link rel="import" href="../iron-icons/communication-icons.html">
|
||||
<link rel="import" href="../iron-icons/device-icons.html">
|
||||
<link rel="import" href="../iron-icons/hardware-icons.html">
|
||||
<link rel="import" href="../iron-icons/editor-icons.html">
|
||||
<link rel="import" href="../iron-icons/places-icons.html">
|
||||
<link rel="import" href="../iron-icons/social-icons.html">
|
||||
|
||||
<link rel="import" href="../paper-material/paper-material.html">
|
||||
<link rel="import" href="../paper-card/paper-card.html">
|
||||
<link rel="import" href="../paper-button/paper-button.html">
|
||||
<link rel="import" href="../paper-input/paper-input.html">
|
||||
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
|
||||
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html">
|
||||
<link rel="import" href="../paper-radio-group/paper-radio-group.html">
|
||||
|
||||
<link rel="import" href="../strolch-wc-localize-behavior/strolch-wc-localize-behavior.html">
|
||||
|
||||
<link rel="import" href="./strolch-wc-plc-style.html">
|
||||
<link rel="import" href="./strolch-wc-plc-behavior.html">
|
||||
|
||||
<dom-module id="strolch-wc-plc-logical-device">
|
||||
<template>
|
||||
|
||||
<style is="custom-style" include="strolch-wc-plc-style">
|
||||
|
||||
</style>
|
||||
|
||||
<paper-card elevation="1">
|
||||
<div class="header"><h3>[[device.name]]</h3></div>
|
||||
<div class="card-content">
|
||||
|
||||
<div class="g-row">
|
||||
<div class="g-5">
|
||||
<h4>[[localize('addresses')]]</h4>
|
||||
<template is="dom-repeat" items="[[addresses]]" as="address">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell address-field" title="[[address.id]]">
|
||||
<div class="address">[[address.resource]] - [[address.action]]</div>
|
||||
<div class="hw-address">[[address.address]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-cell address-field no-grow">
|
||||
<template is="dom-if" if="[[isBoolean(address.valueType)]]">
|
||||
<template is="dom-if" if="[[address.value]]">
|
||||
<iron-icon style="color:#0b8043"
|
||||
icon="icons:radio-button-checked"></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!address.value]]">
|
||||
<iron-icon style="color:cornflowerblue"
|
||||
icon="icons:radio-button-unchecked"></iron-icon>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isNumber(address.valueType)]]">
|
||||
[[address.value]]
|
||||
</template>
|
||||
<template is="dom-if" if="[[isString(address.valueType)]]">
|
||||
[[address.value]]
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="g-7">
|
||||
<template is="dom-if" if="[[arrayFilled(telegrams)]]">
|
||||
<h4>[[localize('telegrams')]]</h4>
|
||||
<template is="dom-repeat" items="[[telegrams]]" as="telegram">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell address-field" title="[[telegram.id]]">
|
||||
<div class="address">[[telegram.resource]] - [[telegram.action]]</div>
|
||||
<div class="hw-address">[[telegram.address]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow value-cell">
|
||||
|
||||
<template is="dom-if" if="[[isBoolean(telegram.valueType)]]">
|
||||
<paper-radio-button checked="{{telegram.value}}">[[localize('on')]]
|
||||
</paper-radio-button>
|
||||
<paper-radio-button checked="{{!telegram.value}}">[[localize('off')]]
|
||||
</paper-radio-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isNumber(telegram.valueType)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{telegram.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isString(telegram.valueType)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{telegram.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow">
|
||||
<paper-button raised on-tap="sendTelegram">[[localize('send')]]
|
||||
</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[arrayFilled(notifications)]]">
|
||||
<h4>[[localize('notifications')]]</h4>
|
||||
<template is="dom-repeat" items="[[notifications]]" as="notification">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell address-field" title="[[notification.id]]">
|
||||
<div class="address">[[notification.resource]] - [[notification.action]]</div>
|
||||
<div class="hw-address">[[notification.address]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow value-cell">
|
||||
|
||||
<template is="dom-if" if="[[isBoolean(notification.valueType)]]">
|
||||
<paper-radio-button checked="{{notification.value}}">[[localize('on')]]
|
||||
</paper-radio-button>
|
||||
<paper-radio-button checked="{{!notification.value}}">[[localize('off')]]
|
||||
</paper-radio-button>
|
||||
</paper-radio-group>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isNumber(notification.valueType)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{notification.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isString(notification.valueType)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{notification.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow">
|
||||
<paper-button raised on-tap="sendNotification">[[localize('notify')]]
|
||||
</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<iron-ajax id="ajaxGetAddresses"
|
||||
url="[[baseRestPath]]/plc/logicalDevices/[[logicalDeviceId]]/addresses"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetAddressesResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxGetTelegrams"
|
||||
url="[[baseRestPath]]/plc/logicalDevices/[[logicalDeviceId]]/telegrams"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetTelegramsResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxGetNotifications"
|
||||
url="[[baseRestPath]]/plc/logicalDevices/[[logicalDeviceId]]/notifications"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetNotificationsResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxPutAddress"
|
||||
url="[[baseRestPath]]/plc/addresses"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="PUT"
|
||||
on-response="_refresh"
|
||||
on-error="onAjaxError"></iron-ajax>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'strolch-wc-plc-logical-device',
|
||||
|
||||
behaviors: [
|
||||
StrolchLocalizeBehavior, StrolchPlcBehavior
|
||||
],
|
||||
|
||||
properties: {
|
||||
observerHandler: {
|
||||
type: Object
|
||||
},
|
||||
logicalDeviceId: {
|
||||
type: String
|
||||
},
|
||||
device: {
|
||||
type: Object,
|
||||
observer: 'deviceChanged'
|
||||
},
|
||||
addresses: {
|
||||
type: Array,
|
||||
value: []
|
||||
},
|
||||
telegrams: {
|
||||
type: Array,
|
||||
value: []
|
||||
},
|
||||
notifications: {
|
||||
type: Array,
|
||||
value: []
|
||||
}
|
||||
},
|
||||
|
||||
/* Listeners */
|
||||
onGetAddressesResponse: function (e) {
|
||||
var addresses = e.detail.response.data;
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
var a = addresses[i];
|
||||
this.observerHandler.register(a.objectType, a.type, a.id, this.handleAddressUpdate.bind(this));
|
||||
}
|
||||
|
||||
this.addresses = addresses;
|
||||
},
|
||||
onGetTelegramsResponse: function (e) {
|
||||
this.telegrams = e.detail.response.data;
|
||||
},
|
||||
onGetNotificationsResponse: function (e) {
|
||||
this.notifications = e.detail.response.data;
|
||||
},
|
||||
deviceChanged: function (newValue) {
|
||||
if (newValue != null) {
|
||||
this.logicalDeviceId = newValue.id;
|
||||
this.$.ajaxGetAddresses.generateRequest();
|
||||
this.$.ajaxGetTelegrams.generateRequest();
|
||||
this.$.ajaxGetNotifications.generateRequest();
|
||||
}
|
||||
},
|
||||
|
||||
sendTelegram: function (e) {
|
||||
var a = e.model.telegram;
|
||||
this.sendAddress("Telegram", a.resource, a.action, a.value);
|
||||
},
|
||||
sendNotification: function (e) {
|
||||
var a = e.model.notification;
|
||||
this.sendAddress("Notification", a.resource, a.action, a.value);
|
||||
},
|
||||
sendAddressNotification: function (e) {
|
||||
var a = e.model.address;
|
||||
this.sendAddress("Notification", a.resource, a.action, a.value);
|
||||
},
|
||||
|
||||
sendAddress: function (type, resource, action, value) {
|
||||
console.log("Sending " + type + " for " + resource + " - " + action + ": " + value);
|
||||
this.$.ajaxPutAddress.body = {
|
||||
type: type,
|
||||
resource: resource,
|
||||
action: action,
|
||||
value: value
|
||||
};
|
||||
this.$.ajaxPutAddress.generateRequest();
|
||||
},
|
||||
|
||||
_refresh: function () {
|
||||
console.log("Should refresh!");
|
||||
},
|
||||
onAjaxError: function (e) {
|
||||
this._refresh();
|
||||
this.onRequestError(e);
|
||||
},
|
||||
|
||||
handleAddressUpdate: function (address) {
|
||||
for (var i = 0; i < this.addresses.length; i++) {
|
||||
if (this.addresses[i].id === address.id) {
|
||||
this.set("addresses." + i + ".value", address.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Lifecycle */
|
||||
reload: function () {
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
|
@ -0,0 +1,260 @@
|
|||
<link rel="import" href="../polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../iron-ajax/iron-ajax.html">
|
||||
<link rel="import" href="../iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../iron-icons/notification-icons.html">
|
||||
<link rel="import" href="../iron-icons/maps-icons.html">
|
||||
<link rel="import" href="../iron-icons/av-icons.html">
|
||||
<link rel="import" href="../iron-icons/communication-icons.html">
|
||||
<link rel="import" href="../iron-icons/device-icons.html">
|
||||
<link rel="import" href="../iron-icons/hardware-icons.html">
|
||||
<link rel="import" href="../iron-icons/editor-icons.html">
|
||||
<link rel="import" href="../iron-icons/places-icons.html">
|
||||
<link rel="import" href="../iron-icons/social-icons.html">
|
||||
|
||||
<link rel="import" href="../paper-material/paper-material.html">
|
||||
<link rel="import" href="../paper-card/paper-card.html">
|
||||
<link rel="import" href="../paper-button/paper-button.html">
|
||||
<link rel="import" href="../paper-input/paper-input.html">
|
||||
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
|
||||
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html">
|
||||
<link rel="import" href="../paper-radio-group/paper-radio-group.html">
|
||||
|
||||
<link rel="import" href="../strolch-wc-localize-behavior/strolch-wc-localize-behavior.html">
|
||||
<link rel="import" href="../strolch-wc-ws-observer/strolch-wc-ws-observer.html">
|
||||
|
||||
<link rel="import" href="./strolch-wc-plc-style.html">
|
||||
<link rel="import" href="./strolch-wc-plc-behavior.html">
|
||||
<link rel="import" href="./strolch-wc-plc-logical-device.html">
|
||||
|
||||
<dom-module id="strolch-wc-plc-logical-devices">
|
||||
<template>
|
||||
|
||||
<style is="custom-style" include="strolch-wc-plc-style">
|
||||
|
||||
</style>
|
||||
|
||||
<div class="actions">
|
||||
<paper-icon-button class="g-pull-right" icon="refresh" on-tap="_refresh"></paper-icon-button>
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[arrayFilled(virtualAddresses)]]">
|
||||
<h2>[[localize('virtualAddresses')]]</h2>
|
||||
<paper-card elevation="1">
|
||||
<div class="card-content">
|
||||
|
||||
<div class="g-row">
|
||||
<div class="g-12">
|
||||
|
||||
<template is="dom-repeat" items="[[virtualAddresses]]" as="address">
|
||||
<div class="g-flex-table-row">
|
||||
<div class="g-flex-table-cell address-field">
|
||||
<div class="address">[[address.resource]] - [[address.action]]</div>
|
||||
<div class="hw-address">[[address.address]]</div>
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow value-cell">
|
||||
|
||||
<template is="dom-if" if="[[isBoolean(address.type)]]">
|
||||
<paper-radio-group selected="{{address.value}}" attr-for-selected="name">
|
||||
<paper-radio-button name="true">[[localize('on')]]
|
||||
</paper-radio-button>
|
||||
<paper-radio-button name="false">[[localize('off')]]
|
||||
</paper-radio-button>
|
||||
</paper-radio-group>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isNumber(address.type)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{address.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isString(address.type)]]">
|
||||
<paper-input class="value-input"
|
||||
value="{{address.value}}"
|
||||
no-label-float></paper-input>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="g-flex-table-cell no-grow">
|
||||
<paper-button raised on-tap="sendAddressNotification">[[localize('notify')]]
|
||||
</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
|
||||
<template is="dom-repeat" items="[[devicesByGroup]]" as="group">
|
||||
|
||||
<h2>[[group.name]]</h2>
|
||||
|
||||
<template is="dom-repeat" items="[[group.data]]" as="device">
|
||||
|
||||
<strolch-wc-plc-logical-device device="[[device]]"
|
||||
base-rest-path="[[baseRestPath]]"
|
||||
observer-handler="[[observerHandler]]"></strolch-wc-plc-logical-device>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<iron-ajax id="ajaxGetDevices"
|
||||
url="[[baseRestPath]]/plc/logicalDevices"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetDevicesResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxGetVirtualAddresses"
|
||||
url="[[baseRestPath]]/plc/addresses/virtual"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="GET"
|
||||
on-response="onGetVirtualAddressesResponse"
|
||||
on-error="onRequestError"></iron-ajax>
|
||||
|
||||
<iron-ajax id="ajaxPutAddress"
|
||||
url="[[baseRestPath]]/plc/addresses"
|
||||
content-type="application/json"
|
||||
handle-as="json"
|
||||
method="PUT"
|
||||
on-response="_refresh"
|
||||
on-error="onAjaxError"></iron-ajax>
|
||||
|
||||
<strolch-wc-ws-observer id="observerHandler" ws-path="[[wsObserverPath]]"></strolch-wc-ws-observer>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'strolch-wc-plc-logical-devices',
|
||||
|
||||
behaviors: [
|
||||
StrolchLocalizeBehavior, StrolchPlcBehavior
|
||||
],
|
||||
|
||||
properties: {
|
||||
observerHandler: {
|
||||
type: Object,
|
||||
value: function () {
|
||||
return ObserverHandler;
|
||||
}
|
||||
},
|
||||
registeredForUpdates: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
virtualAddresses: {
|
||||
type: Array,
|
||||
value: []
|
||||
},
|
||||
devicesByGroup: {
|
||||
type: Array,
|
||||
value: []
|
||||
},
|
||||
wsObserverPath: {
|
||||
type: String,
|
||||
value: function () {
|
||||
return CustomWeb.baseWsPath + "/plc/observer";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Listeners */
|
||||
onGetDevicesResponse: function (e) {
|
||||
this.devicesByGroup = e.detail.response.data;
|
||||
},
|
||||
onGetVirtualAddressesResponse: function (e) {
|
||||
this.virtualAddresses = e.detail.response.data;
|
||||
},
|
||||
|
||||
sendAddressNotification: function (e) {
|
||||
var a = e.model.address;
|
||||
this.sendAddress("Notification", a.resource, a.action, a.value);
|
||||
},
|
||||
sendAddress: function (type, resource, action, value) {
|
||||
console.log("Sending " + type + " for " + resource + " - " + action + ": " + value);
|
||||
this.$.ajaxPutAddress.body = {
|
||||
type: type,
|
||||
resource: resource,
|
||||
action: action,
|
||||
value: value
|
||||
};
|
||||
this.$.ajaxPutAddress.generateRequest();
|
||||
},
|
||||
|
||||
_refresh: function () {
|
||||
this.$.ajaxGetDevices.generateRequest();
|
||||
this.$.ajaxGetVirtualAddresses.generateRequest();
|
||||
|
||||
if (!this.registeredForUpdates) {
|
||||
this.$.observerHandler.register("Resource", "PlcAddress", "strolch-wc-plc-logical-devices", true, this.handleUpdate.bind(this));
|
||||
this.registeredForUpdates = true;
|
||||
}
|
||||
},
|
||||
onAjaxError: function (e) {
|
||||
this._refresh();
|
||||
this.onRequestError(e);
|
||||
},
|
||||
|
||||
/* Lifecycle */
|
||||
reload: function () {
|
||||
this._refresh();
|
||||
},
|
||||
handleUpdate: function (notifyType, objectType, type, elements) {
|
||||
console.log("Received updates for " + elements.length + " " + objectType + " " + type + " elements.");
|
||||
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
this.observerHandler.notifyUpdate(objectType, type, elements[i].id, elements[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var registrations = {};
|
||||
|
||||
ObserverHandler = {
|
||||
register: function (objectType, type, id, callback) {
|
||||
if (objectType == null || type == null || id == null || callback == null)
|
||||
throw "One of objectType, type, id or callback is null: " + objectType + ", " + type + ", " + id + ", " + callback;
|
||||
var byObjectType = registrations[objectType];
|
||||
if (byObjectType == null) {
|
||||
byObjectType = {};
|
||||
registrations[objectType] = byObjectType;
|
||||
}
|
||||
|
||||
var byType = byObjectType[type];
|
||||
if (byType == null) {
|
||||
byType = {};
|
||||
byObjectType[type] = byType;
|
||||
}
|
||||
|
||||
byType[id] = callback;
|
||||
},
|
||||
|
||||
notifyUpdate: function (objectType, type, id, element) {
|
||||
if (objectType == null || type == null || id == null || element == null)
|
||||
throw "One of objectType, type, id or element is null: " + objectType + ", " + type + ", " + id + ", " + element;
|
||||
|
||||
var byObjectType = registrations[objectType];
|
||||
if (byObjectType == null) {
|
||||
console.log("No observers for objectType " + objectType);
|
||||
return;
|
||||
}
|
||||
|
||||
var byType = byObjectType[type];
|
||||
if (byType == null) {
|
||||
console.log("No observers for byType " + byType);
|
||||
return;
|
||||
}
|
||||
|
||||
var callback = byType[id];
|
||||
callback(element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</dom-module>
|
|
@ -0,0 +1,119 @@
|
|||
<link rel="import" href="../polymer/polymer.html">
|
||||
<link rel="import" href="../paper-styles/color.html">
|
||||
|
||||
<link rel="import" href="../strolch-wc-styles/strolch-wc-styles.html">
|
||||
|
||||
<dom-module id="strolch-wc-plc-style">
|
||||
<template>
|
||||
<style is="strolch-wc-plc-style" include="strolch-wc-styles">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
paper-icon-button, iron-icon {
|
||||
color: var(--app-secondary-color);
|
||||
}
|
||||
|
||||
paper-toggle-button {
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
h2, h3 {
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2, h3, h4 {
|
||||
margin: 10px 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex; /* or inline-flex */
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.item {
|
||||
order: 0; /* default is 0 */
|
||||
flex-grow: 0; /* default 0 */
|
||||
flex-shrink: 0; /* default 1 */
|
||||
flex-basis: auto; /* default auto */
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex; /* or inline-flex */
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex; /* or inline-flex */
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.card-actions-right {
|
||||
display: flex; /* or inline-flex */
|
||||
flex-grow: 1; /* default 0 */
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.g-flex-table-cell {
|
||||
padding: 0;
|
||||
flex-basis: 150px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.label {
|
||||
flex-flow: row-reverse;
|
||||
flex-basis: 150px;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
color: var(--app-dark-warning-bg-color);
|
||||
}
|
||||
|
||||
.no-grow {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.value-input {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.address-field {
|
||||
display: block;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.address {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hw-address {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: smaller;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
paper-radio-button {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</template>
|
||||
</dom-module>
|
Loading…
Reference in New Issue