openhab-core
openhab-core copied to clipboard
`System reached start level 100` differs in 3.4 and 4.0
In a file based rule I have
rule "System started"
when
System reached start level 100
then
getActions("mqtt", "mqtt:broker:b1").publishMQTT("a/rpc", "abc")
end
Once the device receives the request at a/rpc, it sends a reply over MQTT. In OpenHAB-JS (no Nashorn) I have code to handle the mqtt reply. Obviously in order to handle the reply the code must have been loaded before the mqtt reply was sent.
In OpenHAB 3.4 apparently System reached start level 100 was triggered after the code from openhab/js/automation was loaded and executed. That is after openhab/js/automation/myfile.js has installed rules.
In OpenHAB 4.0.2 first the System reached start level 100 is triggered, and then openhab/js/automation/myfile.js is interpreted.
https://www.openhab.org/docs/configuration/rules-dsl.html#system-based-triggers does not say whether System reached start level 100 it is triggered before or after rules from addons (here: GraalVM) have been loaded.
Please adjust System reached start level 100 to execute after the addons have finished their initialization. OpenHAB-JS shall finish its initialization once it executes the .js files.
As a work around I have installed now an artificial delay:
rule "System started"
when
System reached start level 100
then
createTimer(now.plusMinutes(1)) [|
getActions("mqtt", "mqtt:broker:b1").publishMQTT("a/rpc", "abc")
]
end
Startup ordering and dependencies is a hard problem in OH. The underlying platform, karaf, does not allow a simple "first load this and then load that" startup process. Add to that problems where error can occur (e.g. a Thing never comes ONLINE) the problem becomes even more complicated. In short, OH startup is not simple and deterministic and as I understand it, replacing all the Xtend/Xtext stuff would be a prerequisite to simplifying the system (I don't know the details but there are a lot of complicated relationships there that make startup particularly challenging).
The Rule Engine is loaded at level 40. Rules are supposed to start running at level 50. Things get loaded at level 70. Most of the time by the time you get to 100 everything should be up and loaded. However, is add-ons needed to be downloaded or some Things never came online maybe not.
In the mean time, this particular use case can be handled by setting the "Birth Message" properties on the MQTT Broker Thing. When the Thing comes online it will publish that message to that topic automatically. Normally this would be used in conjunction with the LWT settings. Alternatively, you can change the trigger on the rule to run when the MQTT Broker Thing changes state to ONLINE.
Actually… when I think of it, it is possible to introduce a ready marker which could be fired from rule. Start levels are configurable in a file, hence custom user-specific steps can be added.
All you need is access to ready service and properly defined ready marker included in org.openhab.startlevel.cfg.
A tutorial would be most welcome. I kind of follow what you are saying and I see the startlevel.config folder. But what constitutes a "properly defined ready marker" is beyond my knowledge and ability to figure out and I don't really know what you mean by access to the ready service. Do you mean from a rule?
I'm very intrigued by this idea.
In principle you need following:
- To wait for ready marker
import org.openhab.core.service.ReadyMarker;
import org.openhab.core.service.ReadyMarkerFilter;
import org.openhab.core.service.ReadyService;
import org.openhab.core.service.ReadyService.ReadyTracker;
ReadyService readyService = ...;
readyService.registerTracker(new ReadyTracker() {
@Override
public void onReadyMarkerAdded(ReadyMarker readyMarker) {
// ... do the work
}
@Override
public void onReadyMarkerRemoved(ReadyMarker readyMarker) {
// rollback .. dependent work
}
}, new ReadyMarkerFilter().withType("co7io-managed").withIdentifier("item"));
- To fire marker being ready
import org.openhab.core.service.ReadyMarker;
import org.openhab.core.service.ReadyService;
ReadyService readyService = ...;
readyService.markReady(new ReadyMarker("co7io-managed", "item"));
- Custom level in
org.openhab.startlevel.cfg:
15=co7io-managed:item
Bear in mind, that only few of pre-defined startlevels are used by openHAB, rest is just a free fall. State 20 have kind of special meaning, it is waited by persistence restore and rule refresher. By placing something in start level < 20 you can prioritize things yourself. All other start levels have little to no impact to system startup as no other things (or actually very few) depend on them.
Worth to note - the start levle 20 won't be fired unless earlier start levels are ready. Even if its individual ready markers are met.