[SOLVED] OH3 with DSL rules from OH2, not working

  • Platform information:
  • Hardware: Raspberry Pi 4 8GB
  • OS: Raspbian
  • openHAB version: 3.2

I’ve been using OH2 on a RPi3 for some time now, running near to 100 different devices all connected to the same little server that I’ve been improving for the past 3 years or so.

It all was great. Took me months to optimize OH2 but in the last year or so I barely needed to do anything because it just runs very smooth.

I’ve now installed OH3 in my new RPi4 and my oh my, I’ve spent some days on this already and I’m not new to this so I can only imagine the pain of someone new to the software.

The learning curve is really, really steep and this makes me wonder if it wouldn’t simply be easier to move once and for all to HA. :frowning:

And thinking about this makes me actually sad, because I’ve invested SO MUCH TIME with OH2. I mean, really a lot. One would hope OH3 would be an IMPROVEMENT over OH2 but so far, days have gone by trying to use it and it has been problems after problems…

The latest problem I have is, my old rules are not working and I read everywhere that “they should”.

So here is one of my many rules that I had working on my previous OH2.

rule "Sensor 433mhz Sonoff Bridge"

   Item Sensor433Mhz changed

   //val variable = newArrayList("names")
   //logInfo("433mhz","433MHz signal received [" + Sensor433Mhz.state + "]")
   //val actions = getActions("mqtt","mqtt:broker:mqtt-broker")
   var Timer offTimer = null
   val Number hours = now.getHour
   val PorSol = new DateTime(Por_Sol.historicState(now).state.toString)
   switch Sensor433Mhz.state {

      case "79E006": {
         if ((now.isAfter(PorSol).toString == "true" || hours < 3)
             && Luz_Entrada_Frente.historicState(now).state.toString == "OFF") {
            if(Alexa_Boas_Vindas.state == ON) {
               offTimer = createTimer(now.plusSeconds(10), [|
                  if(Sensor433Mhz.state.toString == "29E006" || Sensor433Mhz.state.toString == "1961E6") {
            offTimer = ScriptExecution.createTimer(now.plusSeconds(20), [|
         }else if(Alexa_Boas_Vindas.state == ON) {
            offTimer = createTimer(now.plusSeconds(10), [|
               if(Sensor433Mhz.state.toString == "29E006" || Sensor433Mhz.state.toString == "1961E6") {

      case "1961E6": {
         if((now.isAfter(PorSol).toString == "true" || hours < 6)
            && Luz_Corredor.historicState(now).state.toString == "OFF") {
            offTimer = createTimer(now.plusSeconds(30), [|
      case "1A23A6",
      case "E53803": {
         if((now.isAfter(PorSol).toString == "true" || hours < 6)
            && Luz_Corrimao.historicState(now).state.toString == "OFF") {
            offTimer = createTimer(now.plusSeconds(60), [|

      case "7CAC81": {

      case "7CAC82": {

      case "1E9D56",
      case "F504E6": {
         Conta_Alexa.sendCommand("Atenção, chegou correio! Atenção, chegou correio!")
         sendBroadcastNotification("Chegou correio a casa!")

      case "644C68": {
         sendBroadcastNotification("FUMO DETETADO EM CASA!!!")

      case "0A2F13": {
         sendBroadcastNotification("O portão da garagem foi aberto!")

      case "0A2F19": {
         sendBroadcastNotification("Portão da garagem fechado.")


   if(Sensor433Mhz.state.toString !== "") {
      offTimer = createTimer(now.plusMinutes(1), [|


As I said, this file is running flawlessly on my OH2 installation.

This error message inside openhab.log is what I get whenever the script is suppose to run:

2021-09-29 05:02:28.492 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'sensor433mhz-1' failed: An error occurred during the script execution: null in sensor433mhz

If old rules were supposed to work in OH3, what is going on here?

Thank you in advance for any help.

You are correct. Most OH2 rules run just fine. You’ve just com across one of the few breaking changes with the update to OH3

Search the forum for recent discussions of ZonedDateTime and you’ll get everything you need to be back on your feet.


Hey mate,

yeah, I also tried it the lazy approach first (upgrade and see what happens without researching / preparing properly first).

Just keep in mind that a project that is as alive as OH is the best kind of project. I also changed my behaviour here to assuming I missed something in the first place. The statistics now are overwhelmingly approving that approach.

All the best and hang in there with upgrading, because it really doesn’t take that long and pays off a lot (!).


I think this might be the root of many of your problems and perhaps we can help with some other areas you are having problems with the upgrade. There are several breaking changes between OH 2 and OH 3 when it comes to rules. It was never stated that your OH 2 rules will run without change when moving to OH 3.

The breaking change in this particular rule is Joda DateTime no longer exists. The Joda library has been deprecated for years and it had to be removed. So in this rule’s case the fix looks pretty simple.

val PorSol = (Por_Sol.historicState(now).state as DateTimeType).getZonedDateTime

But one has to ask, why get the historicState for now? Why not just get the Item’s current state? They should be the same and just getting the state means you don’t have go to disk and read the state from the database.

This line too makes little sense. isAfter returns a boolean. Why compare against a String? The following does the same thing


Anyway, that’s neither here nor there but they could point to some additional places where your code may run into trouble. The toString representation of some things may change between OH 2 and OH 3 and that is not typically considered a breaking change. If you often rely upon the string representation like this it seems probable you’ll run into additional problems that are not listed in as breaking changes in the link JustinG posted.

Instead of spending days on stuff like this though, search the forum for help and if you don’t find it post a question like this. You’ll probably have an answer in less than an hour or two.

1 Like

@JustinG thank you for your quick help,it was definitely what I was missing.

@Sebastian_Foerster I don’t consider that I took the “lazy” way since I’ve started literally from scratch. I have not upgraded from OH2 to OH3. I installed with everything new. New RPi, new SSD, etc…

Don’t take me wrong, I love OpenHAB project and I just feel I’ve learned so much about it but I was really getting frustrated because I’ve lost a lot of time already with other configurations that did not worked as it was supposed to, like the persistence. Now it’s properly working with MySQL, but it was not straight forward. Then there was the painly manual process of setting everything (near 100 items) all over again, their rules, etc…

There should be a way to easily transfer settings from OH2 to OH3 (I hope they consider this on a future major release).

@rlkoshak And finally I reach to you. Thank you so much man, this community would definitely not be the same without your support. Unbelievable. Congratulations once again. :slight_smile:

Now, will this rule work normally?

rule "Mexer nos estores quando esta calor"

   Time cron "0 */15 12,13,14,15,16,17,18 * * ? *"
   if(Float::parseFloat(Sensor_Temperatura_Rua.historicState(now).state.toString) > 28
      && Float::parseFloat(Sensor_Temperatura_Rua.historicState(now).state.toString) < 31
      && Estores_Temp_Diario.historicState(now).state.toString == "OFF") {
      if(Float::parseFloat(brisa_sala.historicState(now).state.toString) < 100) {
         sendCommand(brisa_sala, DOWN)
         offTimer = createTimer(now.plusMillis(400), [|
            sendCommand(brisa_sala, STOP)
      if(Float::parseFloat(estore_quarto.historicState(now).state.toString) > 60
         && Float::parseFloat(estore_quarto.historicState(now).state.toString) < 95) {
         sendCommand(estore_quarto, 80)
      if(Float::parseFloat(estore_suite_closet.historicState(now).state.toString) > 60
         && Float::parseFloat(estore_suite_closet.historicState(now).state.toString) < 95) {
         sendCommand(estore_suite_closet, 80)
      if(Float::parseFloat(estore_suite_frente.historicState(now).state.toString) > 60
         && Float::parseFloat(estore_suite_frente.historicState(now).state.toString) < 95) {
         sendCommand(estore_suite_frente, 80)
      if(Float::parseFloat(estore_suite_lateral.historicState(now).state.toString) > 60
         && Float::parseFloat(estore_suite_lateral.historicState(now).state.toString) < 95) {
         sendCommand(estore_suite_lateral, 80)
      sendCommand(Estores_Temp_Diario, ON)

Thank you so much once again.

Often the best way to answer a question like that is to try it out and see what happens. We are people on this forum too, not computers. Often we don’t know

Nothing really stands out as being necessarily wrong or something that may have changed between OH 2 and OH 3. Though again:

  • Why get histroicState(now) when SensorTemperature_Rua.state gives you the exact same thing?

  • Assuming these Items are Number Items, why convert the Number to a String only to parse it back into a Number?

    if(Sensor_Temperature_Rua.state as Number >28

That does the same thing. as what you have now without all that extra work.

  • In Rules DSL it’s better to call MyItem.sendCommand(ON) than sendComand(“MyItem”, ON). For details see the rules docs which has a section that discusses this.

Now you got me with this one! :smiley:

You are absolutely right, I just took now the opposite route (the easiest) and just asked.

I don’t know now why I had to do it this way (I have it running like this for about 2 years now). I know I had to struggle a lot to make it running, but I will try your approach. I’m all in when it comes to cleaner and simplier codding.

Curiously, before you answer I was changing the code exactly for that reason, but thanks a lot for the heads-up.

Cheers. :slight_smile:

Just be sure to pay attention to the “if” parts of those statements. If, for example, the Item is a Number:Temperature instead of just a plain old Number, another approach might be required. But if that where the case then your current code wouldn’t work either.

However, in the transition from OH 2 to OH 3, some bindings changed to use units for their Channels. So even though they were just Numbers before, they might now be Number:Temperature.

There are lots of little details like these that can trip you up.

1 Like

Got ya, thanks! :slight_smile: