diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-callscript.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-callscript.js deleted file mode 100644 index 2acface1a1..0000000000 --- a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-callscript.js +++ /dev/null @@ -1,27 +0,0 @@ -import Blockly from 'blockly' -import { FieldItemModelPicker } from './ohitemfield' - -export default function defineOHBlocks_Subsystem (f7, scripts) { - Blockly.Blocks['oh_callscript'] = { - init: function () { - this.appendValueInput('script') - .setCheck(null) - .appendField('Call Script') - this.setInputsInline(true) - this.setPreviousStatement(true, null) - this.setNextStatement(true, null) - this.setColour(230) - this.setTooltip('Calls a script which must be located in the $OPENHAB_CONF/scripts folder') - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html') - } - } - - Blockly.JavaScript['oh_callscript'] = function (block) { - const scriptExecution = Blockly.JavaScript.provideFunction_( - 'scriptExecution', - ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.model.script.actions.ScriptExecution\');']) - let script = Blockly.JavaScript.valueToCode(block, 'script', Blockly.JavaScript.ORDER_ATOMIC) - let code = scriptExecution + '.callScript(' + script + ');\n' - return code - } -} diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-ephemeris.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-ephemeris.js deleted file mode 100644 index b14a29f982..0000000000 --- a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/_tmp/blocks-ephemeris.js +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Ephemeris provides calendar related information -* This code has been originally provided by https://github.com/bigbasec -* -* See more background info on openHAB ephemeris here: https://www.openhab.org/docs/configuration/actions.html#ephemeris -*/ - -import Blockly from 'blockly' -import { FieldItemModelPicker } from './ohitemfield' - -export default function defineOHBlocks_Ephemeris (f7) { - Blockly.Blocks['oh_ephemeris_basic'] = { - init: function () { - this.appendDummyInput() - .appendField(new Blockly.FieldDropdown([['isWeekend', 'isWeekend'], ['getBankHolidayName', 'getBankHolidayName'], ['getNextBankHoliday', 'getNextBankHoliday'], ['isBankHoliday', 'isBankHoliday']]), 'type') - this.setOutput(true, null) - this.setColour(0) - this.setTooltip('provides calendar related information') - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_ephemeris_basic'] = function (block) { - addEphemeris() - let type = block.getFieldValue('type') - let code = `ephemeris.${type}()` - return [code, Blockly.JavaScript.ORDER_NONE] - } - - Blockly.Blocks['oh_ephemeris_offset'] = { - init: function () { - this.appendValueInput('offset') - .setCheck('Number') - .appendField(new Blockly.FieldDropdown([['isWeekend', 'isWeekend'], ['getBankHolidayName', 'getBankHolidayName'], ['getNextBankHoliday', 'getNextBankHoliday'], ['isBankHoliday', 'isBankHoliday']]), 'type') - .appendField('offset days') - this.setOutput(true, null) - this.setColour(0) - this.setTooltip('the offset to the given type in days') - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_ephemeris_offset'] = function (block) { - addEphemeris() - let type = block.getFieldValue('type') - let offsetValue = Blockly.JavaScript.valueToCode(block, 'offset', Blockly.JavaScript.ORDER_ATOMIC) - let code = `ephemeris.${type}(${offsetValue})` - return [code, Blockly.JavaScript.ORDER_NONE] - } - - Blockly.Blocks['oh_ephemeris_getBankHolidayName'] = { - init: function () { - this.appendValueInput('offsetDays') - .appendField('getBankHolidayName') - this.setColour(0) - this.setInputsInline(true) - this.setTooltip('name of the holiday today, or null if today is not a bank holiday') - this.setOutput(true, null) - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_ephemeris_getBankHolidayName'] = function (block) { - addEphemeris() - let code = 'ephemeris.getBankHolidayName' - return [code, 0] - } - - Blockly.Blocks['oh_Ephemeris_getNextBankHoliday'] = { - init: function () { - this.appendValueInput('offsetDays') - .appendField('getNextBankHoliday') - this.setColour(0) - this.setInputsInline(true) - this.setTooltip('name of the next bank holiday') - this.setOutput(true, null) - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_Ephemeris_getNextBankHoliday'] = function (block) { - addEphemeris() - let code = 'ephemeris.getNextBankHoliday' - return [code, 0] - } - - Blockly.Blocks['oh_Ephemeris_isBankHoliday'] = { - init: function () { - this.appendValueInput('offsetDays') - .appendField('isBankHoliday') - this.setColour(0) - this.setInputsInline(true) - this.setTooltip('true if today is a bank holiday, false otherwise') - this.setOutput(true, null) - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_Ephemeris_isBankHoliday'] = function (block) { - addEphemeris() - let code = 'ephemeris.isBankHoliday' - return [code, 0] - } - - Blockly.Blocks['oh_Ephemeris_isWeekend'] = { - init: function () { - this.appendValueInput('offsetDays') - .appendField('isWeekend') - this.setColour(0) - this.setInputsInline(true) - this.setTooltip('true if today is a weekend, false otherwise') - this.setOutput(true, null) - this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') - } - } - - Blockly.JavaScript['oh_Ephemeris_isWeekend'] = function (block) { - addEphemeris() - let code = 'ephemeris.isWeekend' - return [code, 0] - } - - function addEphemeris () { - Blockly.JavaScript.provideFunction_( - 'ephemeris', - ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.model.script.actions.Ephemeris\')']) - } -} diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-ephemeris.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-ephemeris.js new file mode 100644 index 0000000000..3c40525664 --- /dev/null +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-ephemeris.js @@ -0,0 +1,289 @@ +/* +* Ephemeris provides calendar related information +* @author stefan.hoehn +* +* See more background info on openHAB ephemeris here: https://www.openhab.org/docs/configuration/actions.html#ephemeris +* See usage discussion here: https://community.openhab.org/t/wip-ephemeris-documentation/84536 +*/ +import Blockly from 'blockly' +import { FieldDatePicker } from './fields/date-field' + +export default function (f7) { + /* + * Typed (EphemerisDay) block that can be used with the Ephemeris check block + * Note that the block basically returns a zero day offset for the check + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_today'] = { + init: function () { + this.appendDummyInput() + .appendField('today') + this.setOutput(true, 'EphemerisDay') + this.setColour(70) + this.setTooltip('today\'s date for ephemeris check block') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Typed block that can be used with Ephemeris check block + * Code part + */ + Blockly.JavaScript['oh_ephemeris_today'] = function (block) { + addEphemeris() + let code = '0' + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Typed (EphemerisDay) block with a day positve or negative offset that can be used with the Ephemeris check block + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_today_offset'] = { + init: function () { + this.appendValueInput('offset') + .setCheck('Number') + .appendField('today +/-') + this.appendDummyInput() + .appendField('days') + this.setOutput(true, 'EphemerisDay') + this.setColour(70) + this.setTooltip('today with a positive or negative day offset for ephemeris check block') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Typed (EphemerisDay) block with a day positve or negative offset that can be used with the Ephemeris check block + * Code part + */ + Blockly.JavaScript['oh_ephemeris_today_offset'] = function (block) { + let offsetValue = Blockly.JavaScript.valueToCode(block, 'offset', Blockly.JavaScript.ORDER_ATOMIC) + let code = `${offsetValue}` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Typed (EphemerisDate) block that can be used with the Ephemeris check block + * Allows the selection of a date. The default is the current date + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_date'] = { + init: function () { + this.appendDummyInput() + .appendField('date') + .appendField(new FieldDatePicker('', null, { f7 }, 'date'), 'day') + this.setOutput(true, 'EphemerisDate') + this.setColour(70) + this.setTooltip('Calender entry for ephemeris check block or other openHAB Blocks that require a day input') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Typed (EphemerisDate) block that can be used with the Ephemeris check block + * Code part + */ + Blockly.JavaScript['oh_ephemeris_date'] = function (block) { + const { dtf, zdt, getZonedDateTime } = addDateSupport() + let day = block.getFieldValue('day') + let code = `${getZonedDateTime}('${day}')` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Typed (EphemerisDate) block that can be used with the Ephemeris check block + * Allows input as string in the format yyyy-MM-dd + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_date_text'] = { + init: function () { + this.appendValueInput('day') + .appendField('date') + this.setOutput(true, 'EphemerisDate') + this.setColour(70) + this.setTooltip('Calender entry as yyyy-MM-dd for ephemeris check block or other openHAB Blocks that require a day input') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Typed (EphemerisDate) block that can be used with the Ephemeris check block + * Code part + */ + Blockly.JavaScript['oh_ephemeris_date_text'] = function (block) { + const { dtf, zdt, getZonedDateTime } = addDateSupport() + let day = Blockly.JavaScript.valueToCode(block, 'day', Blockly.JavaScript.ORDER_ATOMIC) + let code = `${getZonedDateTime}(${day})` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Returns a string representation of an ephemeris date + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_text_of_date'] = { + init: function () { + this.appendValueInput('date') + .appendField('text of') + .setCheck('EphemerisDate') + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([['without time', 'without'], ['with time', 'with']]), 'withtime') + + this.setOutput(true, 'String') + this.setColour(160) + this.setTooltip('converts an ephemeris date into a date string') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Returns a string representation of an ephemeris date + * Code part + */ + Blockly.JavaScript['oh_ephemeris_text_of_date'] = function (block) { + const { dtf, zdt, getZonedDatetime } = addDateSupport() + let date = Blockly.JavaScript.valueToCode(block, 'date', Blockly.JavaScript.ORDER_ATOMIC) + let withtime = block.getFieldValue('withtime') + let pattern = 'yyyy-MM-dd' + if (withtime === 'with') { + pattern = 'yyyy-MM-dd HH:mm:ss' + } + let code = `${date}.format(${dtf}.ofPattern('${pattern}'))` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Checks if the provided day is a + * - bank holiday (needs to be configured in openHAB + * - weekend + * - weekday + * Only EphemerisDay and EphemerisDate blocks are allowed as an input + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_check'] = { + init: function () { + this.appendValueInput('dayInfo') + .setCheck(['EphemerisDay', 'EphemerisDate']) + this.appendDummyInput() + .appendField('is') + .appendField(new Blockly.FieldDropdown([['a holiday', 'holiday'], ['the weekend', 'weekend'], ['a weekday', 'weekday']]), 'checkType') + this.setColour(0) + this.setInputsInline(true) + this.setTooltip('checks if the given day is a holiday, weekend or weekday') + this.setOutput(true, null) + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Checks if the provided day is a bank holiday, weekend or weekday + * Code part + */ + Blockly.JavaScript['oh_ephemeris_check'] = function (block) { + const ephemeris = addEphemeris() + + let dayInfo = Blockly.JavaScript.valueToCode(block, 'dayInfo', Blockly.JavaScript.ORDER_NONE) + let checkType = block.getFieldValue('checkType') + let code = '' + + switch (checkType) { + case 'weekend': + code += `${ephemeris}.isWeekend(${dayInfo})` + break + case 'weekday': + code += `!${ephemeris}.isWeekend(${dayInfo})` + break + case 'holiday': + code += `${ephemeris}.isBankHoliday(${dayInfo})` + break + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL] + } + + /* + * Retrieve the current bonk holiday name + * Only EphemerisDay and EphemerisDate blocks are allowed as an input + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_getHolidayName'] = { + init: function () { + this.appendValueInput('dayInfo') + .appendField('holiday name for') + .setCheck(['EphemerisDay', 'EphemerisDate']) + this.setColour(0) + this.setInputsInline(true) + this.setTooltip('name of the holiday for the given day') + this.setOutput(true, null) + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Retrieve the current bonk holiday name + * Code part + */ + Blockly.JavaScript['oh_ephemeris_getHolidayName'] = function (block) { + const ephemeris = addEphemeris() + let dayInfo = Blockly.JavaScript.valueToCode(block, 'dayInfo', Blockly.JavaScript.ORDER_NONE) + let code = `${ephemeris}.getBankHolidayName(${dayInfo})` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Retrieve the number of days from today until the given bank holiday name + * Blockly part + */ + Blockly.Blocks['oh_ephemeris_getDaysUntilHoliday'] = { + init: function () { + this.appendValueInput('holidayName') + .appendField('days until holiday named') + .setCheck('String') + this.setColour(0) + this.setInputsInline(true) + this.setTooltip('days from today until the given bank holiday name') + this.setOutput(true, null) + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html#ephemeris') + } + } + + /* + * Retrieve the number of days from today until the given bank holiday name + * Code part + */ + Blockly.JavaScript['oh_ephemeris_getDaysUntilHoliday'] = function (block) { + const ephemeris = addEphemeris() + let holidayName = Blockly.JavaScript.valueToCode(block, 'holidayName', Blockly.JavaScript.ORDER_NONE) + let code = `${ephemeris}.getDaysUntil(${holidayName})` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Add ephemeris support to rule + */ + function addEphemeris () { + return Blockly.JavaScript.provideFunction_( + 'ephemeris', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type("org.openhab.core.model.script.actions.Ephemeris");']) + } + + /* + * Add ZoneDateTime and DateTimeFormatter support to rule + */ + function addDateSupport () { + const dtf = Blockly.JavaScript.provideFunction_( + 'dtf', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type("java.time.format.DateTimeFormatter");']) + const zdt = Blockly.JavaScript.provideFunction_( + 'zdt', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type("java.time.ZonedDateTime");']) + const getZonedDateTime = Blockly.JavaScript.provideFunction_( + 'getZonedDateTime', + [ + 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' (datetime) {', + ` return ${zdt}.parse(datetime + ' 00:00:00 +00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ss z'))`, + '}' + ]) + return { dtf, zdt, getZonedDateTime } + } +} 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 new file mode 100644 index 0000000000..4880bde1f4 --- /dev/null +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-persistence.js @@ -0,0 +1,168 @@ +/* +* These blocks support the persistence module which stores the data in the database and allows to retrieve historical and statistical data +*/ +import Blockly from 'blockly' + +export default function defineOHBlocks_Persistence (f7) { + /* + * Checks if an item has changed or has been updated since some given date + * Blockly part + */ + Blockly.Blocks['oh_persist_changed'] = { + init: function () { + this.appendValueInput('itemName') + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([['has changed since', 'changedSince'], ['has been updated since', 'updatedSince']]), 'methodName') + this.appendValueInput('dayInfo') + .setCheck(['EphemerisDay', 'EphemerisDate']) + this.setInputsInline(true) + this.setOutput(true, null) + this.setColour(0) + + let thisBlock = this + this.setTooltip(function () { + let methodName = thisBlock.getFieldValue('methodName') + let TIP = { + 'changedSince': 'Checks if the State of the Item has (ever) changed since a certain point in time', + 'updatedSince': 'Checks if the State of the Item has been updated since a certain point in time' + } + return TIP[methodName] + }) + + this.setHelpUrl('https://www.openhab.org/docs/configuration/persistence.html') + } + } + + /* + * Checks if an item has changed or has been updated since some given date + * Code part + */ + Blockly.JavaScript['oh_persist_changed'] = function (block) { + addPersistence() + addDateSupport() + const itemName = Blockly.JavaScript.valueToCode(block, 'itemName', Blockly.JavaScript.ORDER_ATOMIC) + const methodName = block.getFieldValue('methodName') + const dayInfo = Blockly.JavaScript.valueToCode(block, 'dayInfo', Blockly.JavaScript.ORDER_ATOMIC) + let code = `persistence.${methodName}(itemRegistry.getItem(${itemName}),${dayInfo})` + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Provides a number of different (non-)statistical metrics for an item according to the given date + * Blockly part + */ + Blockly.Blocks['oh_get_persistvalue'] = { + init: function () { + this.appendValueInput('itemName') + .appendField('get') + .appendField(new Blockly.FieldDropdown([ + ['average value', 'averageSince'], ['delta value', 'deltaSince'], + ['deviation value', 'deviationSince'], ['variance value', 'varianceSince'], ['evolution rate value', 'evolutionRate'], + ['minimum value', 'minimumSince'], ['maximum value', 'maximumSince'], + ['summed up value', 'sumSince'], ['previous value', 'previousState'] + ] + ), 'methodName') + .appendField('of item') + .setCheck('oh_itemtype') + this.appendValueInput('dayInfo') + .appendField('since') + .setCheck(['EphemerisDay', 'EphemerisDate']) + this.setInputsInline(true) + this.setOutput(true, null) + this.setColour(0) + let thisBlock = this + this.setTooltip(function () { + let methodName = thisBlock.getFieldValue('methodName') + let TIP = { + 'averageSince': 'Gets the average value of the State of a persisted Item since a certain point in time. This method uses a time-weighted average calculation', + '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', + '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', + 'previousState': 'Gets the previous value of the State of a persisted Item' + } + return TIP[methodName] + }) + this.setHelpUrl('https://www.openhab.org/docs/configuration/persistence.html') + } + } + + /* + * Provides a number of different (non-)statistical metrics for an item according to the given date + * Code part + */ + Blockly.JavaScript['oh_get_persistvalue'] = function (block) { + addPersistence() + addDateSupport() + const itemName = Blockly.JavaScript.valueToCode(block, 'itemName', Blockly.JavaScript.ORDER_ATOMIC) + const methodName = block.getFieldValue('methodName') + const dayInfo = Blockly.JavaScript.valueToCode(block, 'dayInfo', Blockly.JavaScript.ORDER_ATOMIC) + let code = '' + if (methodName === 'maximumSince' || methodName === 'minimumSince') { + code = `persistence.${methodName}(itemRegistry.getItem(${itemName}),${dayInfo}).getState()` + } else if (methodName === 'previousState') { + code = `persistence.${methodName}(itemRegistry.getItem(${itemName}))` + } else { + code = `persistence.${methodName}(itemRegistry.getItem(${itemName}),${dayInfo})` + } + + return [code, Blockly.JavaScript.ORDER_NONE] + } + + /* + * Returns the state before the current state of that item + * Blockly part + */ + Blockly.Blocks['oh_get_persistence_lastupdate'] = { + init: function () { + this.appendDummyInput() + .appendField('last updated date of') + this.appendValueInput('itemName') + this.setInputsInline(true) + this.setOutput(true, 'EphemerisDate') + this.setColour(0) + + let thisBlock = this + this.setTooltip(function () { + let methodName = thisBlock.getFieldValue('methodName') + let TIP = { + 'changedSince': 'Checks if the State of the Item has (ever) changed since a certain point in time', + 'updatedSince': 'Checks if the State of the Item has been updated since a certain point in time' + } + return TIP[methodName] + }) + + this.setHelpUrl('https://www.openhab.org/docs/configuration/persistence.html') + } + } + + /* + * Returns the state before the current state of that item + * Code part + */ + Blockly.JavaScript['oh_get_persistence_lastupdate'] = function (block) { + addPersistence() + addDateSupport() + const itemName = Blockly.JavaScript.valueToCode(block, 'itemName', Blockly.JavaScript.ORDER_ATOMIC) + let code = `persistence.lastUpdate(itemRegistry.getItem(${itemName}))` + return [code, 0] + } + + function addPersistence () { + Blockly.JavaScript.provideFunction_( + 'persistence', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.persistence.extensions.PersistenceExtensions\');']) + } + + function addDateSupport () { + Blockly.JavaScript.provideFunction_( + 'dtf', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type("java.time.format.DateTimeFormatter");']) + Blockly.JavaScript.provideFunction_( + 'zdt', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type("java.time.ZonedDateTime");']) + } +} diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-scripts.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-scripts.js new file mode 100644 index 0000000000..1f370309ab --- /dev/null +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/blocks-scripts.js @@ -0,0 +1,161 @@ +/* +* These blocks allow to run scripts from the current rule. There are two types of scripts which are supported by different blocks +* - Script Files that are stored on openHAB's server in the scripts folder +* - Scripts that have been provided via the openHAB UI +* Additionally there is a block that allows transformations based on the Map-File functionality, regular-expressions and applying JSON-paths +*/ +import Blockly from 'blockly' +import { addOSGiService } from './utils' + +export default function defineOHBlocks_Scripts (f7, scripts) { + /* + * Calls a script that is provided in openHABs scripts folder + * Blockly part + */ + Blockly.Blocks['oh_callscriptfile'] = { + init: function () { + this.appendValueInput('scriptfile') + .setCheck('String') + .appendField('call script file') + this.setInputsInline(true) + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(0) + this.setTooltip('Calls a script file which must be located in the $OPENHAB_CONF/scripts folder') + this.setHelpUrl('https://www.openhab.org/docs/configuration/actions.html') + } + } + + /* + * Calls a script that is provided in openHABs scripts folder + * Code part + */ + Blockly.JavaScript['oh_callscriptfile'] = function (block) { + const scriptExecution = Blockly.JavaScript.provideFunction_( + 'scriptExecution', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.model.script.actions.ScriptExecution\');']) + let scriptfile = Blockly.JavaScript.valueToCode(block, 'scriptfile', Blockly.JavaScript.ORDER_ATOMIC) + let code = `${scriptExecution}.callScript(${scriptfile});\n` + return code + } + + /* + * Calls a script that has been provided via the UI. + * Parameters can be provided with the special parameter block oh_scriptparam + * Blockly part + */ + Blockly.Blocks['oh_runrule'] = { + init: function () { + this.appendValueInput('ruleUID') + .setCheck('String') + .appendField('run rule or script') + this.appendValueInput('parameters') + .appendField('with parameters') + .setCheck('Dictionary') + this.setInputsInline(false) + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(0) + this.setTooltip('Run a rule or script with a certain UID, and optional parameters') + // this.setHelpUrl('') // TODO provide a openhab documentation URL + } + } + + /* + * Calls a script that has been provided via the UI. + * Parameters can be provided with the special parameter block oh_scriptparam + * Code part + */ + Blockly.JavaScript['oh_runrule'] = function (block) { + const ruleManager = addOSGiService('ruleManager', 'org.openhab.core.automation.RuleManager') + const ruleUID = Blockly.JavaScript.valueToCode(block, 'ruleUID', Blockly.JavaScript.ORDER_ATOMIC) + const scriptParameters = Blockly.JavaScript.valueToCode(block, 'parameters', Blockly.JavaScript.ORDER_ATOMIC) + + // create a function for the generated code that maps json key-values into a map structure + const convertDictionaryToHashMap = Blockly.JavaScript.provideFunction_( + 'convertDictionaryToHashMap', + [ + 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' (dict) {', + ' if (!dict || dict.length === 0) return null;', + ' var map = new java.util.HashMap();', + ' Object.keys(dict).forEach(function (key) {', + ' map.put(key, dict[key]);', + ' });', + ' return map;', + '}' + ]) + + let code = `${ruleManager}.runNow(${ruleUID}, true, ${convertDictionaryToHashMap}(${scriptParameters}));\n` + return code + } + + /* + * Allow transformations via different methods + * inputs + * - value to be transformed + * - method Map, Regular Expression, JSON-Path + * - transformation method input + * - Map: map file found in openHABs transform-folder + * - Regex: regex-expression + * - JSON-Path: JSON-Path + * Blockly part + */ + Blockly.Blocks['oh_transformation'] = { + init: function () { + this.appendValueInput('value') + .setAlign(Blockly.ALIGN_RIGHT) + .appendField('transform') + this.appendValueInput('function') + .appendField('apply') + .appendField(new Blockly.FieldTextInput('MAP'), 'type') + // .appendField(new Blockly.FieldDropdown([['MAP', 'MAP'], ['REGEX', 'REGEX'], ['JSONPATH', 'JSONPATH']]), 'type') + .appendField('with') + + this.setInputsInline(false) + this.setOutput(true, null) + this.setColour(0) + + let thisBlock = this + this.setTooltip(function () { + const type = thisBlock.getFieldValue('type') + switch (type) { + case 'MAP': + return 'transforms an input via a map file. Specify the file as the function' + case 'REGEX': + return 'transforms / filters an input by applying the provided regular expression' + case 'JSONPATH': + return 'transforms / filters an JSON input by executing the provided JSONPath query' + default: + return 'transforms the input with the ' + type + ' transformation' + } + }) + this.setHelpUrl(function () { + const type = thisBlock.getFieldValue('type') + return 'https://www.openhab.org/addons/transformations/' + type.toLowerCase() + '/' + }) + } + } + + /* + * Allow transformations via different methods + * Code part + */ + Blockly.JavaScript['oh_transformation'] = function (block) { + const transformation = addTransformation() + const transformationType = block.getFieldValue('type') + const transformationFunction = Blockly.JavaScript.valueToCode(block, 'function', Blockly.JavaScript.ORDER_ATOMIC) + const transformationValue = Blockly.JavaScript.valueToCode(block, 'value', Blockly.JavaScript.ORDER_ATOMIC) + + let code = `${transformation}.transform('${transformationType}', ${transformationFunction}, ${transformationValue})` + return [code, 0] + } + + /* + * add transformation class to rule + */ + function addTransformation () { + return Blockly.JavaScript.provideFunction_( + 'transformation', + ['var ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = Java.type(\'org.openhab.core.transform.actions.Transformation\');']) + } +} diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/fields/date-field.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/fields/date-field.js new file mode 100644 index 0000000000..3592f471ad --- /dev/null +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/fields/date-field.js @@ -0,0 +1,57 @@ +/* + * Field allowing to pick a date from a calendar + */ + +import Blockly from 'blockly' +import dayjs from 'dayjs' + +export class FieldDatePicker extends Blockly.FieldTextInput { + constructor (optValue, optValidator, optConfig) { + let value = optValue + if (value === '') { + value = dayjs().format('YYYY-MM-DD') + } + super(value, optValidator, optConfig) + if (optConfig.f7) this.f7 = optConfig.f7 + } + + static fromJson (options) { + return new FieldDatePicker(options['options'], undefined, options) + } + + showEditor_ (options) { + if (this.f7) { + let inputEl = document.createElement('input') + inputEl.setAttribute('type', 'text') + inputEl.setAttribute('value', this.value_) + options.target.appendChild(inputEl) + const self = this + if (this.calendarPicker_) { + this.calendarPicker_.setValue([this.value_]) + } else { + this.calendarPicker_ = this.f7.calendar.create({ + inputEl: options.target, + openIn: 'popup', + closeOnSelect: true, + value: (this.value_) ? [this.value_] : undefined, + on: { + change (calendar, value) { + if (value.length < 1) return + if (!value[0].toISOString) return + self.value_ = dayjs(value[0]).format('YYYY-MM-DD') + self.setEditorValue_(self.value) + } + } + }) + } + this.calendarPicker_.open() + } + } + + dispose () { + if (this.calendarPicker_) this.calendarPicker_.destroy() + super.dispose() + } +} + +Blockly.fieldRegistry.register('oh_date_field', FieldDatePicker) 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 6e1b698cd2..bff304438a 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 @@ -7,6 +7,9 @@ import defineLoggingBlocks from './blocks-logging' import defineNotificationBlocks from './blocks-notifications' import defineTimerBlocks from './blocks-timers' import defineValueStorageBlocks from './blocks-valuestorage' +import defineEphemerisBlocks from './blocks-ephemeris' +import defineOHBlocksScripts from './blocks-scripts' +import defineOHBlocksPersistence from './blocks-persistence' export default function (f7, data) { defineDictionaryBlocks(f7) @@ -18,4 +21,7 @@ export default function (f7, data) { defineLoggingBlocks(f7) defineTimerBlocks(f7) defineValueStorageBlocks(f7) + defineEphemerisBlocks(f7) + defineOHBlocksScripts(f7) + defineOHBlocksPersistence(f7) } diff --git a/bundles/org.openhab.ui/web/src/assets/definitions/blockly/utils.js b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/utils.js new file mode 100644 index 0000000000..e5b331426a --- /dev/null +++ b/bundles/org.openhab.ui/web/src/assets/definitions/blockly/utils.js @@ -0,0 +1,19 @@ +import Blockly from 'blockly' + +/* +* function that allow to call classes within the osgi container +* e.g. service -> 'ruleManager', class -> 'org.openhab.core.automation.RuleManager' +*/ +export function addOSGiService (serviceName, serviceClass) { + const addServiceName = Blockly.JavaScript.provideFunction_( + 'addFrameworkService', [ + 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' (serviceClass) {', + ' var bundleContext = Java.type(\'org.osgi.framework.FrameworkUtil\').getBundle(scriptExtension.class).getBundleContext();', + ' var serviceReference = bundleContext.getServiceReference(serviceClass);', + ' return bundleContext.getService(serviceReference);', + '}' + ]) + return Blockly.JavaScript.provideFunction_( + serviceName, + [`var ${Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_} = ${addServiceName}('${serviceClass}');`]) +} diff --git a/bundles/org.openhab.ui/web/src/pages/settings/rules/script/blockly-editor.vue b/bundles/org.openhab.ui/web/src/pages/settings/rules/script/blockly-editor.vue index 29b7b6effc..f6b8006c55 100644 --- a/bundles/org.openhab.ui/web/src/pages/settings/rules/script/blockly-editor.vue +++ b/bundles/org.openhab.ui/web/src/pages/settings/rules/script/blockly-editor.vue @@ -476,6 +476,50 @@ + + + + + + + 0 + + + + + + + + + {{ new Date().toISOString().split('T')[0] }} + + + + + + + + + + + + + + + + + + + + + + + CHRISTMAS + + + + + @@ -518,6 +562,24 @@ + + + + + + + + + + + + + + + + + + @@ -540,6 +602,41 @@ + + + + + scriptname.script + + + + + + + ruleUID + + + + + + + + + + + + + function + + + + + value + + + + +