Here’s a correct (I hope, not tested at all) implementation of the oh_callscript block, hope it answers your questions:
Blockly.JavaScript['oh_callscript'] = function (block) {
const ruleManager = addOSGiService('ruleManager', 'org.openhab.core.automation.RuleManager')
const parameterDict = Blockly.JavaScript.valueToCode(block, 'parameters', Blockly.JavaScript.ORDER_ATOMIC)
const scriptName = Blockly.JavaScript.valueToCode(block, 'scriptname', Blockly.JavaScript.ORDER_ATOMIC)
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;',
'}'
])
return `${ruleManager}.runNow(${scriptName}, true, ${convertDictionaryToHashMap}(${parameterDict}));\n`
}
...
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}');`])
}
in particular:
- if you ever have to define a temporary global variable for the block (not to be reused), then you must get an unique name with
Blockly.JavaScript.variableDB_.getDistinctName
:
const listVar = Blockly.JavaScript.variableDB_.getDistinctName(
'temp_list', Blockly.Variables.NAME_TYPE);
let code = 'var ' + listVar + ' = ' + arg0 + ';\n';
- if you use
Blockly.JavaScript.provideFunction_
to provide a reusable function (or global variable) then you must use the return value to get the actual name, which may change if the user has defined a variable with the same name (note that it’s not done at all in the current code and that would have to be fixed):
const functionName = Blockly.JavaScript.provideFunction_(
'list_lastElement',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(aList) {',
' // Return the last element of a list.',
' return aList[aList.length - 1];',
'}']);
// Generate the function call for this block.
var code = functionName + '(' + arg0 + ')';
- you misunderstood the example I gave you to convert to dictionary to a HashMap, it was not meant to put in the code generation routine, but part of the actual code to be generated. You rarely have to analyze the inputs themselves,
valueToCode
returns a string because that’s code that you have to insert in the final code somewhere.
NB, that addOSGiService
function above could be exported from another file and imported because it’s likely that it will be used in other blocks.