Ever since I met openHAB with rules functionality I feel lack of include functionality known in other languages like JAVA or C++.
I decided to build some workaround allowing me to achieve similar functionality.
Main assumption have been that:
- Syntax have to be compatible with openHAB rules syntax
- Included scripts have to be editable using SmartHome-Designer or Microsoft VS Code + openHAB VS Code Extension
- Included scripts will be stored in include subfolder of rules folder
- Include functionality will be realized by external shell (bash + awk) script executed on openHAB startup or manually
How to use:
- Create include rule and save in include sub-folder of rules folder, for example: ExampleExternalRule.rules
val Functions$Function1<String, Boolean> myExternalRule = [
String someText |
logInfo("ExternalScript", someText)
return true
]
- Put into main rule file lines like bellow and next execute Tools-RulesInclude.sh
//#include ExampleExternalRule.rules
//#endinclude ExampleExternalRule.rules
After execution of Tools-RulesInclude.sh script, content of ExampleExternalRule.rules will be added between //#include and //#endinclude lines.
Result:
//#include ExampleExternalRule.rules
val Functions$Function1<String, Boolean> myExternalRule = [
String someText |
logInfo("ExternalScript", someText)
return true
]
//#endinclude ExampleExternalRule.rules
- Use external script in main rule (useful if You have to use the same code in more then one rule)
rule "MyTestRule"
when
Item TestItem received update 1
then
myExternalRule.apply("Hello world")
end
Script: Tools-RulesInclude.sh
#!/bin/bash
PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:$PATH"
# openHAB root folder
if [ -z "${openHAB_root}" ] ; then openHAB_root=/opt/openhab ; fi
openhab_log=${openHAB_root}/userdata/logs/openhab.log
cd "${openHAB_root}/conf/rules"
IFS=$'\n'
for FileToProccess in `ls *.rules` ; do
rm /tmp/${FileToProccess} > /dev/null 2>&1
awk -v rulesFile="${FileToProccess}" '
function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s }
function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s }
function trim(s) { return rtrim(ltrim(s)); }
BEGIN {
iStart = 0
iEnd = 0
includeFileName = ""
rulesTmpFile = "/tmp/" rulesFile
while (getline < rulesFile)
{
if(iStart == iEnd)
{
print $0 > rulesTmpFile
}
if(index($0, "//#include") > 0)
{
iStart = iStart + 1
includeFileName = trim(substr($0, index($0, "//#include") + length("//#include")))
includeFileName = "include/" includeFileName
if(system("[ -f " includeFileName " ]") == 0)
{
while (getline < includeFileName)
print $0 > rulesTmpFile
close(includeFileName)
}
else
{
iStart = 0 # Critical error
print "'`date +"%Y-%m-%d %H:%M:%S.%3N"`' [ERROR] [pt/openhab/bin/Tools-RulesInclude.sh] - File: " includeFileName " included by " rulesFile " does not exists" >> "'${openhab_log}'"
}
}
else if(index($0, "//#endinclude") > 0 && iStart = iEnd + 1)
{
iEnd = iEnd + 1
print $0 > rulesTmpFile
}
}
close(rulesFile);
if(iStart == 0 || iStart != iEnd)
system("rm \"" rulesTmpFile "\"")
else
print "'`date +"%Y-%m-%d %H:%M:%S.%3N"`' [INFO ] [pt/openhab/bin/Tools-RulesInclude.sh] - Processing file: " rulesFile >> "'${openhab_log}'"
if(iStart != iEnd)
print "'`date +"%Y-%m-%d %H:%M:%S.%3N"`' [ERROR] [pt/openhab/bin/Tools-RulesInclude.sh] - Syntax error in file: " rulesFile >> "'${openhab_log}'"
}
'
if [ -f "/tmp/${FileToProccess}" ] ; then
mv "/tmp/${FileToProccess}" ./
fi
done
I hope that this solution will be useful for openHAB community.