New rule engine startup - rule initialisation

Im not using the rule engine anymore, because i switched to textual configuration, but may @Kai could tell us about this.

I also have seem similar effects, but not necessarily reproducible ones.
Have a try with a current snapshot, the code of the rule engine is still evolving quickly, so there is some progress.

it seem i have same problem as them
my log is

2017-04-02 20:51:20.413 [RuleStatusInfoEvent       ] - rule_5 updated: UNINITIALIZED (CONFIGURATION_ERROR): Validation of rule rule_5 has failed! Action Type "core.ItemCommandAction" does not exist!

can anyone fix it all rule are like that after startup

I have similar issues. Although my logs don’t show me anything about rules except this:

[ERROR] [xt.xbase.jvmmodel.JvmModelAssociator] - Error calling inferrer
java.lang.IllegalStateException: ScriptServiceUtil not initialized yet!
	at org.eclipse.smarthome.model.script.ScriptServiceUtil.getInstance(ScriptServiceUtil.java:88)
	at org.eclipse.smarthome.model.script.ScriptServiceUtil.getItemRegistry(ScriptServiceUtil.java:94)
	at org.eclipse.smarthome.model.script.internal.engine.ServiceTrackerItemRegistryProvider.get(ServiceTrackerItemRegistryProvider.java:29)
	at org.eclipse.smarthome.model.script.internal.engine.ServiceTrackerItemRegistryProvider.get(ServiceTrackerItemRegistryProvider.java:1)
	at org.eclipse.smarthome.model.rule.jvmmodel.RulesJvmModelInferrer.lambda$0(RulesJvmModelInferrer.java:175)
	at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator$1.run(JvmModelAssociator.java:397)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452]
	at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator.installDerivedState(JvmModelAssociator.java:407)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452]
	at org.eclipse.xtext.resource.DerivedStateAwareResource.installDerivedState(DerivedStateAwareResource.java:242)[142:org.eclipse.xtext:2.9.2]
	at org.eclipse.xtext.xbase.resource.BatchLinkableResource.getContents(BatchLinkableResource.java:148)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452]
	at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.validateModel(ModelRepositoryImpl.java:252)[123:org.eclipse.smarthome.model.core:0.9.0.201704291826]
	at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.addOrRefreshModel(ModelRepositoryImpl.java:90)[123:org.eclipse.smarthome.model.core:0.9.0.201704291826]
	at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.checkFile(FolderObserver.java:244)[123:org.eclipse.smarthome.model.core:0.9.0.201704291826]
	at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.notifyUpdateToModelRepo(FolderObserver.java:170)[123:org.eclipse.smarthome.model.core:0.9.0.201704291826]
	at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.updated(FolderObserver.java:148)[123:org.eclipse.smarthome.model.core:0.9.0.201704291826]
	at org.apache.felix.cm.impl.helper.ManagedServiceTracker.updated(ManagedServiceTracker.java:189)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.helper.ManagedServiceTracker.updateService(ManagedServiceTracker.java:152)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.helper.ManagedServiceTracker.provideConfiguration(ManagedServiceTracker.java:85)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceUpdate.provide(ConfigurationManager.java:1461)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceUpdate.run(ConfigurationManager.java:1417)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.UpdateThread.run0(UpdateThread.java:141)[3:org.apache.felix.configadmin:1.8.12]
	at org.apache.felix.cm.impl.UpdateThread.run(UpdateThread.java:109)[3:org.apache.felix.configadmin:1.8.12]
	at java.lang.Thread.run(Thread.java:748)[:1.8.0_131]

I found that the API has the effect of initialising the rules, so added to my crontab to do this following my daily reboot:

0 5 * * * /sbin/shutdown -r +5
@reboot sleep 300; curl -X PUT --header "Content-Type: application/json" --header "Accept: application/json" -d "{}" "http://192.168.1.80:8080/rest/rules/rule_3/config"

You can get the rule name (rule_3 above) from the PaperUI if you set them up there.

1 Like

Got this problem too with openhab2 build #1020. My “fix” is a php script based on @Kev_Marlow suggestion:

<?php

function curlPost($url) {
  // Set a one-minute timeout for this script
  set_time_limit(60);

  $options = array(
    CURLOPT_RETURNTRANSFER => TRUE, // return web page
    CURLOPT_HEADER => FALSE, // don't return headers
    CURLOPT_POST => TRUE,
    CURLOPT_HTTPHEADER => array("Accept: application/json"),
  );

  $session = curl_init($url);
  curl_setopt_array($session, $options);

  // Tell curl that this is the body of the POST
  curl_setopt($session, CURLOPT_POSTFIELDS, $data);

  // $output contains the output string
  $output = curl_exec($session);
}

function curlPut($url, $data) {
  // Set a one-minute timeout for this script
  set_time_limit(60);

  $options = array(
    CURLOPT_RETURNTRANSFER => TRUE, // return web page
    CURLOPT_HEADER => FALSE, // don't return headers
    CURLOPT_CUSTOMREQUEST => "PUT",
    CURLOPT_HTTPHEADER => array("Content-Type: application/json", "Accept: application/json"),
  );

  $session = curl_init($url);
  curl_setopt_array($session, $options);

  // Tell curl that this is the body of the POST
  curl_setopt($session, CURLOPT_POSTFIELDS, $data);

  // $output contains the output string
  $output = curl_exec($session);
}

function curlGet($url) {
  // Set a one-minute timeout for this script
  set_time_limit(60);

  $options = array(
    CURLOPT_RETURNTRANSFER => TRUE, // return web page
    CURLOPT_HEADER => FALSE, // don't return headers
    CURLOPT_HTTPGET => TRUE,
    CURLOPT_HTTPHEADER => array("Accept: application/json"),
  );

  $session = curl_init($url);
  curl_setopt_array($session, $options);

  // $output contains the output string
  $output = curl_exec($session);
  return $output;
}

$output = curlGet("http://openhab:8080/rest/rules");
if (preg_match_all('/"uid"\:\"(.*?)\"/', $output, $matches)) {
  foreach ($matches[1] as $rule) {
    curlPut("http://openhab:8080/rest/rules/" . $rule . "/config", "{}");
  }
}

This can be also be done by writing old style rule which send HTTP put message as you suggested for each new JSON based rule configured. You may have to add error handling in this rule. You will have to enable jsonpath and javascript transformations in conf/services/addons.cfg file.

rule "InitializeAllRules"
when
System started
then
// Get all JSON based rules
var String jsonRules = sendHttpGetRequest(“http://127.0.0.1:8080/rest/rules”)
var String jsonuids = transform(“JSONPATH”, “$…uid”, jsonRules)
var String uidsAsString = jsonuids.substring(1, jsonuids.length - 1)

// Split rules uids
var uidsArray = uidsAsString.split(",")

// Update each rule
for (var i = 0; i < uidsArray.length; i++) {
  // Prepare API URL for config update
  var ruleConfigUrl = "http://127.0.0.1:8080/rest/rules/" 
    + uidsArray.get(i).substring(1, uidsArray.get(i).length - 1) + "/config"

  // Update config - This will initialize rule after starup
  sendHttpPutRequest(ruleConfigUrl, "application/json", "{}")
}

end

Hi @satish-nikam Satish,

Thanks for sharing your rule. I think an extra period has crept into the above script in line:

var String jsonuids = transform("JSONPATH", "$...uid", jsonRules)

The following worked for me:

rule "InitializeExperimentalRules"
  when
    System started
then
  // Get all JSON based rules
  var String jsonRules = sendHttpGetRequest("http://127.0.0.1:8080/rest/rules")
  var String jsonuids = transform("JSONPATH", "$..uid", jsonRules)
  var String uidsAsString = jsonuids.substring(1, jsonuids.length - 1)

  // Split rules uids
  var uidsArray = uidsAsString.split(",")

  // Update each rule
  for (var i = 0; i < uidsArray.length; i++) {
  // Prepare API URL for config update
  logInfo("InitializeExperimentalRules", uidsArray.get(i))
  var ruleConfigUrl = "http://127.0.0.1:8080/rest/rules/" + uidsArray.get(i).substring(1, uidsArray.get(i).length - 1) + "/config"
  

  // Update config - This will initialize rule after starup
  sendHttpPutRequest(ruleConfigUrl, "application/json", "{}")
}
end

Regards, Andy

2 Likes

That did not work for me.

I think it might be that the rules are initialising too soon.
I see this in the rest/rules:

enabled true
status
status “UNINITIALIZED”
statusDetail “CONFIGURATION_ERROR”
description “Validation of rule rule_12 has failed! Condition Type "timer.DayOfWeekCondition" does not exist!”

yet disabling and enabling the rule works

1 Like

Thank you andy, your workaround worked for me!

Hey guys is this workaround still working. i cant get it to work anymore, i am using openHAB 2.3.0 Build #1272. I also tried the script but it generates errors.

1 Like

Hi @satish-nikam and @AndyMB,
I don’t know if there was a change in the rest api in 2.3.0, but I managed to create a workaround, based on your solutions. There are better ways to cut the UID out of the json string than iterating over the chunks of the split until “uid” is found in the string, but it works for me for now.

rule "InitializeExperimentalRules"
  when
    System started
then
  // Get all JSON based rules
  var String jsonRules = sendHttpGetRequest("http://127.0.0.1:8080/rest/rules")
  var String jsonuids = transform("JSONPATH", "$..uid", jsonRules)
  var String uidsAsString = jsonuids.substring(1, jsonuids.length - 1)
  // Split rules uids
  var uidsArray = uidsAsString.split(",")
  // Update each rule
  for (var i = 0; i < uidsArray.length; i++) {
  // Prepare API URL for config update
  //Check if the current chunk of the split string contains "uid" (this is dirty, but works)
  if(uidsArray.get(i).contains("uid")){
    
    //get the substring which represents the uid string e.g. Rule_1
    var String uid = uidsArray.get(i).substring(7, uidsArray.get(i).length - 1)
    //Build the URL for updating the Rule
    var String ruleConfigUrl = "http://127.0.0.1:8080/rest/rules/" + uid + "/config" 
    //Log the Rule update with the UID
    logInfo("INFO","Rule "+uid+" updated: "+ruleConfigUrl)
    //send the http put request to update the rule
    sendHttpPutRequest(ruleConfigUrl, "application/json", "{}")
  }
  
}
end
1 Like

You missed a couple of brackets and the closing END, besides that your script works perfectly.
Here the corrected version

rule "InitializeExperimentalRules"
  when
    System started
then
  // Get all JSON based rules
  var String jsonRules = sendHttpGetRequest("http://127.0.0.1:8080/rest/rules")
  var String jsonuids = transform("JSONPATH", "$..uid", jsonRules)
  var String uidsAsString = jsonuids.substring(1, jsonuids.length - 1)
  // Split rules uids
  var uidsArray = uidsAsString.split(",")
  // Update each rule
  for (var i = 0; i < uidsArray.length; i++) {
  // Prepare API URL for config update
  //Check if the current chunk of the split string contains "uid" (this is dirty, but works)
  if(uidsArray.get(i).contains("uid")){
    
    //get the substring which represents the uid string e.g. Rule_1
    var String uid = uidsArray.get(i).substring(7, uidsArray.get(i).length - 1)
    //Build the URL for updating the Rule
    var String ruleConfigUrl = "http://127.0.0.1:8080/rest/rules/" + uid + "/config" 
    //Log the Rule update with the UID
    logInfo("INFO","Rule "+uid+" updated: "+ruleConfigUrl)
    //send the http put request to update the rule
    sendHttpPutRequest(ruleConfigUrl, "application/json", "{}")
  }
  }
  end

Hello, the problem still exists on my Openhab.
With the OH2 2.3 Release the Script is not working, because the errormessage above.
Any Idea how to fix it ?

Thank you for your help

All brackets and the end are there, you just need to scroll down :wink:

Its a warning, so it might not be the problem. Are you sure there is no error message?

I get this error:
JsonPath expressions with more than one result are not allowed, please adapt your selector. Result: [“64c95514-6b13-44f9-88e0-d7a4ee5bfbb5”,“5b9aa4ca-4e31-495b-8e33-6e16da2aa796”,“1efc53b3-8865-4d7b-a453-9bd9f046b2da”,“9b770b8e-da44-4bba-a161-df6e93f10f84”,“c8f513f6-23aa-4e59-93bd-f251491bfe2a”,“a1ab8298-89c4-4385-9e44-b8939a1bd7e9”]

1 Like

Well it is the same as mine, but i am pretty shure, that it says Warning in front of it, like in my log.

1 Like

same issue on fully stable release updated system for me :

[WARN ] [ternal.JSonPathTransformationService] - JsonPath expressions with more than one result are not allowed, please adapt your selector. Result: ["ae1ddc92-c44d-4c8a-845d-d222fc15cc16","18d4d1db-08ec-47e4-bb7f-59c131a6e70b","fcd460b9-b3d6-4f5b-b302-f4ab3c657fd1","5328b8ef-3292-456d-a2eb-eda38f32651f","5a1e9fa7-0a4f-4607-b8cd-9e8f4a7a9bb5","0e1e1726-fe25-499a-8265-c91fa1c83025","8410fe2c-8eeb-4cae-be65-e0bdd39c84cb","2f5460d3-d2db-42e6-b660-2bb1c2cfae41","6d149182-c9b7-45d1-b2ad-bc380d873baa","59856c87-e815-4e7f-8d24-ae24aea50320","0b211638-5cc5-4793-a0c1-9b6a6d24ffa6","c59f260c-11b1-4ea9-89d9-2c5537967986","91faf007-bca9-4cdb-8bb8-ab53a9809118","0c545fc9-5809-4c3f-99f8-d75d92297d63"]

no other error

@epicurean and @Bernard_Laurenzo_Kem, please use code fences when pasting definitions of things, items or rules, as well as logs. With pasted text inside code fences, it is much easier to read!

How to use code fences

1 Like