From 67528c8bb520715162dcbad31561304d47f8bde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=B6hn?= Date: Thu, 18 May 2023 20:31:35 +0200 Subject: [PATCH 1/2] [blockly] provide persistence type to blockls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Höhn --- .../definitions/blockly/blocks-persistence.js | 112 +++++++++++++++--- .../src/assets/definitions/blockly/index.js | 2 +- .../config/controls/blockly-editor.vue | 13 +- 3 files changed, 105 insertions(+), 22 deletions(-) diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js index 7e41b1edd2..558d30b9ff 100644 --- a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js @@ -4,9 +4,9 @@ */ import Blockly from 'blockly' import { javascriptGenerator } from 'blockly/javascript' -import { addDateSupport } from './utils' +import { addDateSupport, blockGetCheckedInputType } from './utils' -export default function defineOHBlocks_Persistence (f7, isGraalJs) { +export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceServices) { /* * Provides a number of different (non-)statistical metrics for an item according to the given date * Blockly part @@ -16,18 +16,21 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { this.appendDummyInput() .appendField('get the') .appendField(new Blockly.FieldDropdown([ - ['average', 'averageSince'], ['delta', 'deltaSince'], - ['deviation', 'deviationSince'], ['variance', 'varianceSince'], ['evolution rate', 'evolutionRate'], - ['minimum', 'minimumSince'], ['maximum', 'maximumSince'], ['sum', 'sumSince'], + ['state average', 'averageSince'], ['state delta', 'deltaSince'], + ['state deviation', 'deviationSince'], ['state variance', 'varianceSince'], ['evolution rate', 'evolutionRateSince'], + ['state minimum', 'minimumSince'], ['state maximum', 'maximumSince'], ['state sum', 'sumSince'], ['previous state value', 'previousState'], ['previous state value time', 'previousStateTime'], ['historic state', 'historicState'] ], this.handleTypeSelection.bind(this) ), 'methodName') this.methodName = this.getFieldValue('methodName') this.appendValueInput('itemName') - .appendField('of the state of item named ') + .appendField('of item ') .setAlign(Blockly.ALIGN_RIGHT) - .setCheck(['String', 'oh_item']) + .setCheck(['String', 'oh_item', 'oh_itemtype']) + this.appendValueInput('persistenceName') + .appendField('from') + .setCheck(null) this.updateShape() this.setInputsInline(false) this.setOutput(true, null) @@ -41,7 +44,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { 'deltaSince': 'Gets the difference in value of the State of a given Item since a certain point in time', 'deviationSince': 'Gets the standard deviation of the state of the given Item since a certain point in time', 'varianceSince': 'Gets the variance of the state of the given Item since a certain point in time', - 'evolutionRate': 'Gets the evolution rate of the state of a given Item since a certain point in time', + 'evolutionRateSince': 'Gets the evolution rate of the state of a given Item since a certain point in time', 'minimumSince': 'Gets the minimum value of the State of a persisted Item since a certain point in time', 'maximumSince': 'Gets the maximum value of the State of a persisted Item since a certain point in time', 'sumSince': 'Gets the sum of the previous States of a persisted Item since a certain point in time', @@ -60,6 +63,10 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { } }, updateShape: function () { + let persistenceNameInput = this.getInput('persistenceName') + if (!persistenceNameInput.getShadowDom()) { + persistenceNameInput.setShadowDom(Blockly.Xml.textToDom('')) + } if (this.methodName === 'previousState' || this.methodName === 'previousStateTime') { if (this.getInput('dayInfo')) { this.removeInput('dayInfo') @@ -78,7 +85,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { this.removeInput('dayInfo') } const preposition = (this.methodName === 'historicState') ? 'at' : 'since' - console.log(this.methodName + '->' + preposition) + this.appendValueInput('dayInfo') .appendField(preposition) .setAlign(Blockly.ALIGN_RIGHT) @@ -93,8 +100,11 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { */ javascriptGenerator['oh_get_persistvalue'] = function (block) { const itemName = javascriptGenerator.valueToCode(block, 'itemName', javascriptGenerator.ORDER_ATOMIC) - const methodName = block.getFieldValue('methodName') + const inputType = blockGetCheckedInputType(block, 'itemName') + let itemCode = toItemCode(itemName, inputType) + const methodName = block.getFieldValue('methodName') + const persistenceName = javascriptGenerator.valueToCode(block, 'persistenceName', javascriptGenerator.ORDER_NONE) const persistence = (isGraalJs) ? null : addPersistence() let code = '' @@ -102,26 +112,27 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { let skipPrevious = javascriptGenerator.valueToCode(block, 'skipPrevious', javascriptGenerator.ORDER_NONE) skipPrevious = ((skipPrevious === 'undefined') ? false : skipPrevious) - let itemCode = (isGraalJs) ? `items.getItem(${itemName})` : `itemRegistry.getItem(${itemName})` + const persistenceExtension = (persistenceName === '\'default\'') ? '' : `, ${persistenceName}` + switch (methodName) { case 'maximumSince': case 'minimumSince': case 'historicState': dayInfo = javascriptGenerator.valueToCode(block, 'dayInfo', javascriptGenerator.ORDER_NONE) - code = (isGraalJs) ? `${itemCode}.history.${methodName}(${dayInfo})?.state` : `${persistence}.${methodName}(${itemCode}, ${dayInfo}).getState()` + code = (isGraalJs) ? `${itemCode}.history.${methodName}(${dayInfo}${persistenceExtension})?.state` : `${persistence}.${methodName}(${itemCode}, ${dayInfo}${persistenceExtension}).getState()` break case 'previousState': - code = (isGraalJs) ? `${itemCode}.history.previousState(${skipPrevious})?.state` : `${persistence}.previousState(${itemCode},${skipPrevious}).getState()` + code = (isGraalJs) ? `${itemCode}.history.previousState(${skipPrevious}${persistenceExtension})?.state` : `${persistence}.previousState(${itemCode},${skipPrevious}${persistenceExtension}).getState()` break case 'previousStateTime': - code = (isGraalJs) ? `${itemCode}.history.previousState(${skipPrevious})?.timestamp` : `${persistence}.previousState(${itemCode},${skipPrevious}).getTimestamp()` + code = (isGraalJs) ? `${itemCode}.history.previousState(${skipPrevious}${persistenceExtension})?.timestamp` : `${persistence}.previousState(${itemCode},${skipPrevious}${persistenceExtension}).getTimestamp()` break default: dayInfo = javascriptGenerator.valueToCode(block, 'dayInfo', javascriptGenerator.ORDER_NONE) - code = (isGraalJs) ? `${itemCode}.history.${methodName}(${dayInfo})` : `${persistence}.${methodName}(${itemCode}, ${dayInfo})` + code = (isGraalJs) ? `${itemCode}.history.${methodName}(${dayInfo}${persistenceExtension})` : `${persistence}.${methodName}(${itemCode}, ${dayInfo}${persistenceExtension})` break } @@ -137,10 +148,18 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { this.appendValueInput('itemName') .setAlign(Blockly.ALIGN_RIGHT) .appendField('the state of') + .setCheck(['String', 'oh_item', 'oh_itemtype']) + const persistenceNameInput = this.appendValueInput('persistenceName') + .appendField('from') + .setCheck(null) + if (!persistenceNameInput.getShadowDom()) { + persistenceNameInput.setShadowDom(Blockly.Xml.textToDom('')) + } this.appendValueInput('dayInfo') .appendField(new Blockly.FieldDropdown([['has changed since', 'changedSince'], ['has been updated since', 'updatedSince']]), 'methodName') .setAlign(Blockly.ALIGN_RIGHT) .setCheck(['ZonedDateTime']) + this.setInputsInline(false) this.setOutput(true, null) this.setColour(0) @@ -165,15 +184,21 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { */ javascriptGenerator['oh_persist_changed'] = function (block) { const itemName = javascriptGenerator.valueToCode(block, 'itemName', javascriptGenerator.ORDER_ATOMIC) + const inputType = block.getInput('itemName').connection.targetBlock().outputConnection.getCheck()[0] + let itemCode = toItemCode(itemName, inputType) + const methodName = block.getFieldValue('methodName') const dayInfo = javascriptGenerator.valueToCode(block, 'dayInfo', javascriptGenerator.ORDER_NONE) + const persistenceName = javascriptGenerator.valueToCode(block, 'persistenceName', javascriptGenerator.ORDER_NONE) + const persistenceExtension = (persistenceName === '\'default\'') ? '' : `, ${persistenceName}` + if (isGraalJs) { - return [`items.getItem(${itemName}).history.${methodName}(${dayInfo})`, javascriptGenerator.ORDER_NONE] + return [`${itemCode}.history.${methodName}(${dayInfo}${persistenceExtension})`, javascriptGenerator.ORDER_NONE] } else { const { dtf, zdt, getZonedDatetime } = addDateSupport() const persistence = addPersistence() - return [`${persistence}.${methodName}(itemRegistry.getItem(${itemName}), ${dayInfo})`, javascriptGenerator.ORDER_NONE] + return [`${persistence}.${methodName}(${itemCode}, ${dayInfo}${persistenceExtension})`, javascriptGenerator.ORDER_NONE] } } @@ -186,6 +211,14 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { this.appendDummyInput() .appendField('last updated date of') this.appendValueInput('itemName') + .setCheck(['String', 'oh_item', 'oh_itemtype']) + const persistenceNameInput = this.appendValueInput('persistenceName') + .appendField('from') + .setCheck(null) + if (!persistenceNameInput.getShadowDom()) { + persistenceNameInput.setShadowDom(Blockly.Xml.textToDom('')) + } + this.setInputsInline(true) this.setOutput(true, 'ZonedDateTime') this.setColour(0) @@ -200,20 +233,61 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs) { */ javascriptGenerator['oh_get_persistence_lastupdate'] = function (block) { const itemName = javascriptGenerator.valueToCode(block, 'itemName', javascriptGenerator.ORDER_ATOMIC) + const inputType = block.getInput('itemName').connection.targetBlock().outputConnection.getCheck()[0] + const persistenceName = javascriptGenerator.valueToCode(block, 'persistenceName', javascriptGenerator.ORDER_NONE) + const persistenceExtension = (persistenceName === '\'default\'') ? '' : ((!isGraalJs) ? ',' : '') + ` ${persistenceName}` + + let itemCode = toItemCode(itemName, inputType) if (isGraalJs) { - return [`items.getItem(${itemName}).history.lastUpdate()`, 0] + return [`${itemCode}.history.lastUpdate(${persistenceExtension})`, 0] } else { const { dtf, zdt, getZonedDatetime } = addDateSupport() const persistence = addPersistence() - let code = `${persistence}.lastUpdate(itemRegistry.getItem(${itemName}))` + let code = `${persistence}.lastUpdate(${itemCode}${persistenceExtension})` return [code, 0] } } + function toItemCode (itemName, inputType) { + if (isGraalJs) { + return (inputType === 'oh_item' || inputType === 'String') ? `items.getItem(${itemName})` : `${itemName}` + } else { + return (inputType === 'oh_item' || inputType === 'String') ? `itemRegistry.getItem(${itemName})` : `${itemName}` + } + } + function addPersistence () { return javascriptGenerator.provideFunction_( 'persistence', ['var ' + javascriptGenerator.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.persistence.extensions.PersistenceExtensions\');']) } + + /* + * Provides all available persistence services as a dropdown + */ + Blockly.Blocks['oh_persistence_dropdown'] = { + init: function () { + let input = this.appendDummyInput() + .appendField('persistence') + .appendField(new Blockly.FieldDropdown(this.generateOptions), 'persistence') + this.setOutput(true, null) + }, + generateOptions: function () { + let options = [] + options.push(['default', 'default']) + if (persistenceServices != null && persistenceServices.length > 0) { + for (let key in persistenceServices) { + let persistenceOption = persistenceServices[key] + options.push([persistenceOption.label, persistenceOption.id]) + } + } + return options + } + } + + javascriptGenerator['oh_persistence_dropdown'] = function (block) { + let persistenceName = block.getFieldValue('persistence') + return [`'${persistenceName}'`, javascriptGenerator.ORDER_NONE] + } } diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/index.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/index.js index 3b41605729..f574e64ad7 100644 --- a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/index.js +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/index.js @@ -35,7 +35,7 @@ export default function (f7, libraryDefinitions, data, isGraalJs) { defineValueStorageBlocks(f7, isGraalJs) defineEphemerisBlocks(f7, isGraalJs) defineScriptsBlocks(f7, isGraalJs) - definePersistenceBlocks(f7, isGraalJs) + definePersistenceBlocks(f7, isGraalJs, data.persistenceServices) defineColorBlocks(f7, isGraalJs) defineTextBlocks(f7, isGraalJs) defineListBlocks(f7, isGraalJs) diff --git a/bundles/org.openhab.ui/web/src/components/config/controls/blockly-editor.vue b/bundles/org.openhab.ui/web/src/components/config/controls/blockly-editor.vue index bd851bfa61..740ab4bf2d 100644 --- a/bundles/org.openhab.ui/web/src/components/config/controls/blockly-editor.vue +++ b/bundles/org.openhab.ui/web/src/components/config/controls/blockly-editor.vue @@ -1073,6 +1073,7 @@ export default { voices: [], scripts: [], rules: [], + persistenceServices: [], loading: true, ready: false } @@ -1100,7 +1101,8 @@ export default { this.$oh.api.get('/rest/rules?summary=true'), this.$oh.api.get('/rest/audio/sinks'), this.$oh.api.get('/rest/voice/voices'), - this.libraryDefinitions ? Promise.resolve(this.libraryDefinitions) : this.$oh.api.get('/rest/ui/components/ui:blocks') + this.libraryDefinitions ? Promise.resolve(this.libraryDefinitions) : this.$oh.api.get('/rest/ui/components/ui:blocks'), + this.$oh.api.get('/rest/persistence') ] Promise.all(dataPromises) .then((data) => { @@ -1131,6 +1133,12 @@ export default { this.blockLibraries = data[3] + this.persistenceServices = data[4].sort((a, b) => { + const labelA = a.label + const labelB = b.label + return labelA.localeCompare(labelB) + }) + this.initBlockly(this.blockLibraries) }) .catch((err, status) => { @@ -1140,7 +1148,8 @@ export default { initBlockly (libraryDefinitions) { defineOHBlocks(this.$f7, libraryDefinitions, { sinks: this.sinks, - voices: this.voices + voices: this.voices, + persistenceServices: this.persistenceServices }, this.isGraalJs) this.addLibraryToToolbox(libraryDefinitions || []) From b9cedb346a0882b121b774f25176936778a025d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=B6hn?= Date: Mon, 22 May 2023 21:20:42 +0200 Subject: [PATCH 2/2] review changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Höhn --- .../assets/definitions/blockly/blocks-persistence.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js index 558d30b9ff..54cc35f11c 100644 --- a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js @@ -63,7 +63,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceSe } }, updateShape: function () { - let persistenceNameInput = this.getInput('persistenceName') + const persistenceNameInput = this.getInput('persistenceName') if (!persistenceNameInput.getShadowDom()) { persistenceNameInput.setShadowDom(Blockly.Xml.textToDom('')) } @@ -101,12 +101,12 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceSe javascriptGenerator['oh_get_persistvalue'] = function (block) { const itemName = javascriptGenerator.valueToCode(block, 'itemName', javascriptGenerator.ORDER_ATOMIC) const inputType = blockGetCheckedInputType(block, 'itemName') - let itemCode = toItemCode(itemName, inputType) const methodName = block.getFieldValue('methodName') const persistenceName = javascriptGenerator.valueToCode(block, 'persistenceName', javascriptGenerator.ORDER_NONE) const persistence = (isGraalJs) ? null : addPersistence() + const itemCode = generateItemCode(itemName, inputType) let code = '' let dayInfo = '' let skipPrevious = javascriptGenerator.valueToCode(block, 'skipPrevious', javascriptGenerator.ORDER_NONE) @@ -185,7 +185,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceSe javascriptGenerator['oh_persist_changed'] = function (block) { const itemName = javascriptGenerator.valueToCode(block, 'itemName', javascriptGenerator.ORDER_ATOMIC) const inputType = block.getInput('itemName').connection.targetBlock().outputConnection.getCheck()[0] - let itemCode = toItemCode(itemName, inputType) + let itemCode = generateItemCode(itemName, inputType) const methodName = block.getFieldValue('methodName') const dayInfo = javascriptGenerator.valueToCode(block, 'dayInfo', javascriptGenerator.ORDER_NONE) @@ -237,7 +237,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceSe const persistenceName = javascriptGenerator.valueToCode(block, 'persistenceName', javascriptGenerator.ORDER_NONE) const persistenceExtension = (persistenceName === '\'default\'') ? '' : ((!isGraalJs) ? ',' : '') + ` ${persistenceName}` - let itemCode = toItemCode(itemName, inputType) + let itemCode = generateItemCode(itemName, inputType) if (isGraalJs) { return [`${itemCode}.history.lastUpdate(${persistenceExtension})`, 0] @@ -249,7 +249,7 @@ export default function defineOHBlocks_Persistence (f7, isGraalJs, persistenceSe } } - function toItemCode (itemName, inputType) { + function generateItemCode (itemName, inputType) { if (isGraalJs) { return (inputType === 'oh_item' || inputType === 'String') ? `items.getItem(${itemName})` : `${itemName}` } else {