[Ecobee] Binding not working anymore to sethold

Hello,

I’ve notice today that when I try to do a sethold in my ecobee, nothing happen. Looking at the log, I see this:

‘setHold’ is not a member of 'org.openhab.core.thing.binding.ThingActions

I have the exact exemple from the binding. It used to work great this winter, I just notice today it’s not working. I did try to restart openhab and changed nothing. In OpenHab, I do see the things for all my sensor, thermostat and account green. I also have all the status of all the variable. I can change the mode from cool to off, heat and such, but if I try to change the schedule to away, sleep or something like that, it’s throwing that error.

Here’s the rule code that is throwing it:

rule "Set Temperature Cool Hold"

when

    Item ecobee_desiredCool received command

then

  var String holdType = "indefinite"

  var Number holdHours = 0

  switch EcobeeHoldType.state {

    case "twoHours":{

      holdType = "holdHours"

      holdHours = 2

    }



    case "fourHours":{

      holdType = "holdHours"

      holdHours = 4

    }



    case "nextTransition":{

      holdType = "nextTransition"

    }



    case "indefinite":{

      holdType = "indefinite"

    }



    case "default": {

      holdType = "indefinite"

    }

  }

  switch ecobee_hvacMode.state.toString {

      case "cool" :{

        if (ecobee_userCool.state instanceof QuantityType) {

          

          var QuantityType<Temperature> ecobee_desiredHeatTemp

          if (ecobee_desiredHeat.state instanceof QuantityType) {

            ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>

          } else {

            ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)

          }

          val params = newLinkedHashMap(

              'coolHoldTemp' -> ecobee_userCool.state,

              'heatHoldTemp' -> ecobee_desiredHeatTemp)

          val ecobeeActions = getActions("ecobee","ecobee:thermostat:2e504bcb:311056396354")

          if (holdHours != 0){

            logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")

            ecobeeActions.setHold( params, holdType, holdHours, null, null)

          }else{

            logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)

            ecobeeActions.setHold( params, holdType, null, null, null)

          }

        }

      }

      case "heat" : {

         logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")

         return

      }



      case "auto" :  {

        if (ecobee_userCool.state instanceof QuantityType &&  ecobee_userHeat.state instanceof QuantityType) {

           val params = newLinkedHashMap(

              'coolHoldTemp' -> ecobee_userCool.state,

              'heatHoldTemp' -> ecobee_userHeat.state)

          val ecobeeActions = getActions("ecobee","ecobee:thermostat:2e504bcb:311056396354")

          if (holdHours != 0){

            logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")

            ecobeeActions.setHold( params, holdType, holdHours, null, null)

          }else{

            logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state  + " for " + holdType)

            ecobeeActions.setHold( params, holdType, null, null, null)

          }

          

        }

      }



      case "off"  :  {

          logWarn("ecobee", "HVAC mode is off, temperature hold ignored")

          return

      }

      case "default" : {

          logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", ecobee_hvacMode.state)

      }

  }

end

I’m on openhab 5.2.0, running as a docker on Unraid 7.3.1, ecobee binding 5.2.0

I did verify that the ecobee:thermostat ID is the one from openhab.

Very odd as I don’t believe anything has changed in the binding.

You tried restarting OH?

Ummm, you should remove your thermostat ID from the rule example (in the thing id).

Yup, I restarted OH and this morning, I removed all ecobee binding things and reinstall them, changed the rule for the new id and just sent a sethold, got the same error.

When I try from the thing directly, it works

edit: I tried a resumeProgram and I’m getting the same error. It’s like this line return nothing:

val ecobeeActions = getActions("ecobee","ecobee:thermostat:2cbb9ca8f2:311056396354")

This means that the method itself isn’t found. So, either something has gone wrong with how extensions are registered, or the method signature has changed so that it doesn’t match.

If nothing has changed in the binding, it points to some issue with the extension registration. If that’s the case, it’s probably a general problem using Thing actions from DSL. This needs to be investigated.

edit: I just checked the Git history, and there are no changed to the binding since 5.1 other than updating the year to 2026 and some formatting changes.

Can you try a logInfo("debugging", ecobeeActions) right after retrieving it? Perhaps the output can tell us something…

Once I come back home I’ll try. I tried another way that result in nothing though.

Foreach ecobeeActions[a] : loginfo(“ecobee”, a.tostring)

(something like that, writing from memory)

I also enable trace logging but it yield nothing more

Forget my suggestion to print the actions, they have no toString() implementation, so the output is worthless.

I don’t have any ecobee device to test against, but I created an account/bridge without valid credentials and a Think linked to it, and created a rule to call an action. This is what I get:

Could not call method 'public java.lang.Boolean org.openhab.binding.ecobee.internal.action.EcobeeActions.setHold(java.lang.String)' from module type 'ecobee.setHold#42c25be3a5db3f1f8377f4c2db62bfe9'.
java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.openhab.core.automation.internal.module.handler.AnnotationActionHandler.execute(AnnotationActionHandler.java:127)
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1424)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1828)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalArgumentException: hold climate ref is missing or invalid
	at org.openhab.binding.ecobee.internal.action.EcobeeActions.setHold(EcobeeActions.java:332)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	... 10 more

That is quite different, and actually seems to be “legitimate”, because the cause of the exception is:

Caused by: java.lang.IllegalArgumentException: hold climate ref is missing or invalid
	at org.openhab.binding.ecobee.internal.action.EcobeeActions.setHold(EcobeeActions.java:332)

..which means that it’s the Ecobee binding itself that rejects the ref I’m sending because it’s invalid - which it obviously is, because I have no idea what it should be.

But, crucially, it seems that the action itself is found, and the error is the result of me sending invalid arguments.

When I run this DSL rule:

rule "ecobee action DSL" uid="b585bb72be"
then
	val ecobeeActions = getActions("ecobee","ecobee:thermostat:8664a14ebf")
	 
	ecobeeActions.setHold("ref")
end

…I get a similar result:

Script execution of rule with UID 'b585bb72be' failed: hold climate ref is missing or invalid
javax.script.ScriptException: hold climate ref is missing or invalid
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:146)
	at org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler.eval(AbstractScriptModuleHandler.java:264)
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:116)
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1424)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1828)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.openhab.core.model.script.engine.ScriptExecutionException: hold climate ref is missing or invalid
	at org.openhab.core.model.script.runtime.internal.engine.ScriptImpl.execute(ScriptImpl.java:88)
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:142)
	... 10 more
Caused by: java.lang.IllegalArgumentException: hold climate ref is missing or invalid
	at org.openhab.binding.ecobee.internal.action.EcobeeActions.setHold(EcobeeActions.java:332)
	at org.openhab.binding.ecobee.internal.action.EcobeeActions.setHold(EcobeeActions.java:340)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1195)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1170)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1156)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1101)
	at org.openhab.core.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:148)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:881)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:243)
	at org.openhab.core.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:227)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:475)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:251)
	at org.openhab.core.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:227)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:213)
	at org.openhab.core.model.script.runtime.internal.engine.ScriptImpl.execute(ScriptImpl.java:80)
	... 11 more

..which indicates that at least this action is “working”.

You call a different overload of setHold(), so perhaps there is some problem with matching the signature of that method.

When I paste your rule verbatim into a new rule in my system, I get completely different errors, it seems like it all starts with The method or field EcobeeHoldType is undefined; line 6, column 79, length 14.

How come that you don’t get this error?

edit: Of course, you’re referring to Items I don’t have…

edit2: I’m confused by your switch statements, you don’t seem to use break, which normally means that it will continue onto the next case statement. I don’t know if there is some “special DSL magic” that means you don’t need to use break, but if there isn’t, the switch statements won’t work as you expect. Each case needs to terminate with either return or break.

@dpa-openhab Do you understand any of this, I get all kind of strange errors when trying to run the rule (after creating some dummy Items), like this line:

var QuantityType<Temperature> ecobee_desiredHeatTemp

producing errors like this:

1. Type mismatch: cannot convert from int to String; line 18, column 625, length 2
   2. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 27, column 1088, length 6
   3. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 30, column 1290, length 6
   4. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 61, column 2158, length 6
   5. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 67, column 2411, length 6

I don’t get why it tries to convert int to string in that line, and I don’t understand the subsequent errors either, LinkedHashMap<String, State> is a Map<String, Object>, so why does it try to “convert” it?

I do not know why this suddently start failing, and I do not have the hardware, too. I do not know why getActions("ecobee", "ecobee:…") returns null.

My reading is that getActions return null, but using MainUI → Settings → Thing → Actions, then it works for any action. Maybe getAction() is called too early, before the add-on is initialized?

How about looping some times with delay of 1s, trying getActions() in each iteration and checking if if returns null, and if all times fail, then give up by logging an error?

Fall-throught for switch expressions is described at Xtext - Integration with Java : one has to use comma ,; the examples do not contain break or return. I guess, a switch is an expression, as everything in Xbase, and if there is a match, the right-hand side after the match is the value of the switch expression. The switch example I posted at https://community.openhab.org/t/network-pingdevice-detects-sometimes-incorrectly-offline-state/ also does not contain fall-through, break, return, but it works.

For Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 27, column 1088, length 6 you can try

  val Map<String, Object> params = newLinkedHashMap('coolHoldTemp' -> ecobee_userCool.state, 'heatHoldTemp' -> ecobee_desiredHeatTemp) // or
  val Map<String, Object> par =                   #{'coolHoldTemp' -> ecobee_userCool.state, 'heatHoldTemp' -> ecobee_desiredHeatTemp}

Of course I do not know what exactly appears on line 27 column 1088.

When I type just

rule a
when
  System reached start level 100
then
  var QuantityType<Temperature> ecobee_desiredHeatTemp
end

I get

[INFO ] [el.core.internal.ModelRepositoryImpl] - Loading DSL model 'a.rules'
[INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in DSL model 'a.rules', using it anyway:
The value of the local variable ecobee_desiredHeatTemp is not used

I suggest creating some minimal script, which by adding a line produces an error and without that line the script runs fine.

Given that DSL Scripts can produce more correct errors/warnings, compared to DSL Rules, meaning at least failing earlier when things go wrong, I suggest to create minimal example, which breaks, as DSL Script, not as DSL Rule.

Here and other places:

if (ecobee_desiredHeat.state instanceof QuantityType) {
    ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
}         

After insteanof and before state as QuantityType<Temperature>, ecobee_desiredHeat.state could be set to NULL, so that ecobee_desiredHeat.state as QuantityType<Temperature> does not work and aborts the execution. To avoid this, casting must be done in try…catch and for that to work first script.model.ScriptInterpreter: emit what cannot be casted to what after a single evaluation of the cast by dilyanpalauzov · Pull Request #5329 · openhab/openhab-core · GitHub must be included.

I’m getting the strangest results here. I’ve now modified the rule somewhat, and created 4 dummy Items that are number/temperature types.

The rule is like this:

rule "Set Temperature Cool Hold File"
when
        Item ecobee_desiredCool received command
then
        var String holdType = "indefinite"
        var Number holdHours = 0

        holdType = "holdHours"
        holdHours = 2

        val hvacMode = "cool"
        switch hvacMode {

          case "cool" :{
                if (ecobee_userCool.state instanceof QuantityType) {
                  var QuantityType<Temperature> ecobee_desiredHeatTemp
                  if (ecobee_desiredHeat.state instanceof QuantityType) {
                        ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
                  } else {
                        ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)
                  }

                  val params = newLinkedHashMap(
                          'coolHoldTemp' -> ecobee_userCool.state,
                          'heatHoldTemp' -> ecobee_desiredHeatTemp)
                  val ecobeeActions = getActions("ecobee","ecobee:thermostat:8664a14ebf")
                  if (holdHours != 0){
                        logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
                        ecobeeActions.setHold( params, holdType, holdHours, null, null)
                  }else{
                        logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)
                        ecobeeActions.setHold( params, holdType, null, null, null)
                  }
                }
          }

          case "heat" : {
                 logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")
                 return
        }
          case "auto" :  {
                if (ecobee_userCool.state instanceof QuantityType &&  ecobee_userHeat.state instanceof QuantityType) {
                   val params = newLinkedHashMap(
                          'coolHoldTemp' -> ecobee_userCool.state,
                          'heatHoldTemp' -> ecobee_userHeat.state)
                  val ecobeeActions = getActions("ecobee","ecobee:thermostat:8664a14ebf")
                  if (holdHours != 0){
                        logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
                        ecobeeActions.setHold( params, holdType, holdHours, null, null)
                  }else{
                        logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state  + " for " + holdType)
                        ecobeeActions.setHold( params, holdType, null, null, null)
                  }
                }
          }
          case "off"  :  {
                  logWarn("ecobee", "HVAC mode is off, temperature hold ignored")
                  return
          }
          case "default" : {
                  logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", hvacMode)
          }
        }
end

When I store this in a .rules file and run it, it succeeds. So, it seems to be able to find and use the action, unless I’ve set values to those Items which makes it not invoke the action (I haven’t checked the logic that closely).

However, when I copy the exact same rule into the UI and try to run it, I get all these strange parsing errors about being unable to convert types etc., which obviously prevents the rule from running. What I don’t understand is why it matters if it’s parsed from file or from a “UI rule”. There must be something wrong when parsing “UI rules”/scripts, when the script is parsed in isolation and not part of a Xtext “rule”.

It doesn’t return null, not for me at least. That wasn’t the original error either, it was that it couldn’t find a method what matched the signature:

But, of all the errors I’ve seen, I haven’t seen that particular one.

In short, what I’ve found is a completely different error than what is reported here, it seems that the parsing of scripts/single actions is broken somehow.

edit: I’ve managed to get this error if I don’t have the binding installed, which makes sense at least:

The method setHold(LinkedHashMap<String, State>, String, Number, Object, Object) is undefined for the type ThingActions

I have no idea how to do that - when I just write a few lines manually, I don’t have these parsing problems, but when I paste the rule, I get these parsing problems. So, there is probably something wrong with the pasted text, but I don’t see where it is, so I can’t isolate it.

Ok, I’ve got a pretty minimal rule now:

version: 1
rules:
  "2564f0c711":
    label: Set Temperature Cool Hold File
    actions:
      - id: script
        config:
          type: DSL
          script: |
            var QuantityType<Temperature> ecobee_desiredHeatTemp
            ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)
        type: Script
    triggers:
      - id: "0"
        config:
          itemName: ecobee_desiredCool
        type: ItemReceivedCommand

..produces the following error when run:

21:49:50.268 [ERROR] (OH-rule-2564f0c711-1) [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID '2564f0c711' failed: var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)

   Type mismatch: cannot convert from int to String; line 2, column 108, length 2
javax.script.ScriptException: var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)

   Type mismatch: cannot convert from int to String; line 2, column 108, length 2
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:146)
	at org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler.eval(AbstractScriptModuleHandler.java:264)
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:116)
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1424)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1828)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.openhab.core.model.script.engine.ScriptParsingException: var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)

   Type mismatch: cannot convert from int to String; line 2, column 108, length 2
	at org.openhab.core.model.script.runtime.internal.engine.ScriptEngineImpl.parseScriptIntoXTextEObject(ScriptEngineImpl.java:146)
	at org.openhab.core.model.script.runtime.internal.engine.ScriptEngineImpl.newScriptFromString(ScriptEngineImpl.java:110)
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:137)
	... 10 more

I have no idea what’s going on, it seems like the parsing of scripts is completely broken. Putting the same in a DSL rule file works as expected.

Wanna know the worst? Out of nowhere, it’s working now. I trigger remotely away and I see away in ecobee. And I triggered resume (from openhab mainui, same way I was doing it on my phone) and it’s working.

The only difference is I’m away so it’s through openhab cloud.

Edit: want to add I changed nothing. I’m away from home and just checked my ecobee and saw it was away. I though maybe I set it manually (I have rules that set the ecobee based on my presence) and tried resume then away, and saw the official ecobee app resume, then go away… could it be that maybe the ecobee api had trouble? Everything did show as online though, and it wouldn’t explain why it was working directly in the thing ui

Can the number 90 be a temperature?

While this DSL Script

var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)

produces

[INFO ] [el.core.internal.ModelRepositoryImpl] - Loading DSL model 'a.script'
[INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in DSL model 'a.script', using it anyway:
The value of the local variable ecobee_desiredHeatTemp is not used
2026-07-15 23:08:35.004 [ERROR] [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID 'a.script' failed: var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)
  

   Type mismatch: cannot convert from int to String; line 2, column 108, length 2

this DSL Script is OK:

var QuantityType<Temperature> ecobee_desiredHeatTemp
ecobee_desiredHeatTemp = new QuantityType<Temperature>(90, SIUnits.CELSIUS)
logError("A", ecobee_desiredHeatTemp.toString)

logs

[INFO ] [el.core.internal.ModelRepositoryImpl] - Loading DSL model 'a.script'
[ERROR] [org.openhab.core.model.script.A     ] - 90 °C

The constructor of QuantityType in openHAB - QuantityType (openHAB Core 5.3.0-SNAPSHOT API) - requires string as parameter, if the constructor has only one parameter.

That fixes one error, but when I paste the full script again:

var String holdType = "indefinite"
var Number holdHours = 0

holdType = "holdHours"
holdHours = 2

val hvacMode = "cool"
switch hvacMode {
	case "cool" :{
		if (ecobee_userCool.state instanceof QuantityType) {
			var QuantityType<Temperature> ecobee_desiredHeatTemp
			if (ecobee_desiredHeat.state instanceof QuantityType) {
				ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
			} else {
				ecobee_desiredHeatTemp = new QuantityType<Temperature>(90)
			}

			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_desiredHeatTemp)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "heat" : {
		 logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")
		 return
	}
	case "auto" : {
		if (ecobee_userCool.state instanceof QuantityType && ecobee_userHeat.state instanceof QuantityType) {
			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "off" : {
		logWarn("ecobee", "HVAC mode is off, temperature hold ignored")
		return
	}
	case "default" : {
		logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", hvacMode)
	}
}

..I still get the remaining errors:

23:25:59.762 [ERROR] (OH-rule-2564f0c711-1) [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID '2564f0c711' failed: var String holdType = "indefinite"
var Number holdHours = 0

holdType = "holdHours"
holdHours = 2

val hvacMode = "cool"
switch hvacMode {
	case "cool" :{
		if (ecobee_userCool.state instanceof QuantityType) {
			var QuantityType<Temperature> ecobee_desiredHeatTemp
			if (ecobee_desiredHeat.state instanceof QuantityType) {
				ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
			} else {
				ecobee_desiredHeatTemp = new QuantityType<Temperature>("90")
			}

			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_desiredHeatTemp)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "heat" : {
		 logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")
		 return
	}
	case "auto" : {
		if (ecobee_userCool.state instanceof QuantityType && ecobee_userHeat.state instanceof QuantityType) {
			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "off" : {
		logWarn("ecobee", "HVAC mode is off, temperature hold ignored")
		return
	}
	case "default" : {
		logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", hvacMode)
	}
}

   1. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 24, column 851, length 6
   2. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 27, column 1015, length 6
   3. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 43, column 1688, length 6
   4. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 46, column 1899, length 6
javax.script.ScriptException: var String holdType = "indefinite"
var Number holdHours = 0

holdType = "holdHours"
holdHours = 2

val hvacMode = "cool"
switch hvacMode {
	case "cool" :{
		if (ecobee_userCool.state instanceof QuantityType) {
			var QuantityType<Temperature> ecobee_desiredHeatTemp
			if (ecobee_desiredHeat.state instanceof QuantityType) {
				ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
			} else {
				ecobee_desiredHeatTemp = new QuantityType<Temperature>("90")
			}

			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_desiredHeatTemp)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "heat" : {
		 logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")
		 return
	}
	case "auto" : {
		if (ecobee_userCool.state instanceof QuantityType && ecobee_userHeat.state instanceof QuantityType) {
			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "off" : {
		logWarn("ecobee", "HVAC mode is off, temperature hold ignored")
		return
	}
	case "default" : {
		logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", hvacMode)
	}
}

   1. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 24, column 851, length 6
   2. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 27, column 1015, length 6
   3. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 43, column 1688, length 6
   4. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 46, column 1899, length 6
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:146)
	at org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler.eval(AbstractScriptModuleHandler.java:264)
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:116)
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1424)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1828)
	at org.openhab.core.automation.internal.RuleEngineImpl$RunRuleCallable.call(RuleEngineImpl.java:1)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.openhab.core.model.script.engine.ScriptParsingException: var String holdType = "indefinite"
var Number holdHours = 0

holdType = "holdHours"
holdHours = 2

val hvacMode = "cool"
switch hvacMode {
	case "cool" :{
		if (ecobee_userCool.state instanceof QuantityType) {
			var QuantityType<Temperature> ecobee_desiredHeatTemp
			if (ecobee_desiredHeat.state instanceof QuantityType) {
				ecobee_desiredHeatTemp = ecobee_desiredHeat.state as QuantityType<Temperature>
			} else {
				ecobee_desiredHeatTemp = new QuantityType<Temperature>("90")
			}

			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_desiredHeatTemp)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "heat" : {
		 logWarn("ecobee", "HVAC mode is heat, temperature hold ignored")
		 return
	}
	case "auto" : {
		if (ecobee_userCool.state instanceof QuantityType && ecobee_userHeat.state instanceof QuantityType) {
			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)
			val ecobeeActions = getActions("ecobee","ecobee:thermostat:7008022299:8664a14ebf")
			if (holdHours != 0){
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdHours + " hours")
				ecobeeActions.setHold( params, holdType, holdHours, null, null)
			}else{
				logInfo("ecobee","Setting auto heat to " + ecobee_userHeat.state + " and cool to " + ecobee_userCool.state + " for " + holdType)
				ecobeeActions.setHold( params, holdType, null, null, null)
			}
		}
	}
	case "off" : {
		logWarn("ecobee", "HVAC mode is off, temperature hold ignored")
		return
	}
	case "default" : {
		logWarn("ecobee", "HVAC mode '{}' is unknown, temperature hold ignored", hvacMode)
	}
}

   1. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 24, column 851, length 6
   2. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 27, column 1015, length 6
   3. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 43, column 1688, length 6
   4. Type mismatch: cannot convert from LinkedHashMap<String, State> to Map<String, Object>; line 46, column 1899, length 6
	at org.openhab.core.model.script.runtime.internal.engine.ScriptEngineImpl.parseScriptIntoXTextEObject(ScriptEngineImpl.java:146)
	at org.openhab.core.model.script.runtime.internal.engine.ScriptEngineImpl.newScriptFromString(ScriptEngineImpl.java:110)
	at org.openhab.core.model.script.runtime.internal.engine.DSLScriptEngine.eval(DSLScriptEngine.java:137)
	... 10 more

I makes no sense to me, here is the method signature from the Java code:

    public static boolean setHold(ThingActions actions, @Nullable Map<String, Object> params, @Nullable String holdType,
            @Nullable Number holdHours, @Nullable Date startDateTime, @Nullable Date endDateTime) {
        return ((EcobeeActions) actions).setHold(params, holdType, holdHours, startDateTime, endDateTime);
    }

I figured out the last error. It’s because of type inference, which I personally can’t stand (life is too short to try to guess what the system has inferred).

Basically, this:

			val params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)

..creates a map of the wrong type (Map<String, State>), what you must do is this:

			val java.util.Map<String, Object> params = newLinkedHashMap(
				'coolHoldTemp' -> ecobee_userCool.state,
				'heatHoldTemp' -> ecobee_userHeat.state)

To my surprise, I discovered that Map isn’t implicitly imported. That is extremely inconvenient IMO, all those “typical types” (Map, Set, Collection, List etc.) should be implicitly imported.

Anyway, this script can’t have worked in previous versions either. I can’t quite explain the errors you have experienced, neither can I understand how it could ever have worked. Have you had some “AI help” here? :innocent:

Regardless, to fix the script, use explicit typing as shown above when creating the maps, and send a string, not an int, to the QuantityType constructor. I think the script should run fine with these changes.

I can’t properly explain this, but I doubt that it is related to the API being unavailable. With the errors in the script, it’s hard to understand how it could ever have worked, I guess it might depend on the state of the Items when it’s run, which determines which path in the code that is being run.

When you get back home, try the above fixes, and see if it things improve :wink:

@Nadahar Thank you for your help on this. It’s very odd what he was experiencing.

Good observation. I couldn’t agree more.

You are correct. If the API was unavailable, there should be something in logs complaining about failed API calls.

Somebody still has to do something about it for it to change. I’m fortunately positioned for that, since I know exactly where and how it must be done, but I have a bit too many things on the plate to do it at this moment. So, it’s in danger of falling through the cracks.

Somebody would need to figure out which concrete classes should be included (the etc. part), and then actually implementing it is quite easy.