DSL Rules and Items transitioning to Temperature Units

In preparation for my OH upgrade, it appears units of measurement are required.
I have a lot of textual configuration and rules, almost none of which uses units for the number variables (and aren’t declared as a temp/power/etc).
As a test, I decided to try set up a new-ish item file and rule, and am running into errors:

Items:

Number:Temperature CNCRoom_TargetTemperature "CNC Room Target Temperature" { unit="°C" }
Number:Temperature ShopLowWorkingTemperature "CNC Low Working Temperature" { unit="°C" }
Number:Temperature ShopHighWorkingTemperature "CNC High Working Temperature" { unit="°C" }

Rules:

rule "Adjust CNC Sonoff Temperatures"
when
    Item CNCRoom_TargetTemperature received update
then
    logInfo("shopheaters.rules", "Starting Shop Heater Target Temp Change Rule")
	logInfo("shopheaters.rules", "Received temperature: " + CNCRoom_TargetTemperature.state)
	logInfo("shopheaters.rules", "Received temperature as number: " + (CNCRoom_TargetTemperature.state as Number))
    var Number TargetTemp
    TargetTemp=(CNCRoom_TargetTemperature.state as Number)
	logInfo("shopheaters.rules", "Target temperature changed to: " + TargetTemp)
    sonoffCNCRoom_TriggerTemperature.sendCommand(TargetTemp)
    sonoffCNCRoom_StopTemperature.sendCommand(TargetTemp+1)
end

Logs (when changing Target Temperature via a slider in the UI):

2023-10-29 22:26:10.419 [INFO ] [openhab.event.RuleStatusInfoEvent   ] - shopheaters-1 updated: RUNNING

2023-10-29 22:26:10.421 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'CNCRoom_TargetTemperature' changed from 10 °C to 11 °C

==> /var/log/openhab/openhab.log <==

2023-10-29 22:26:10.423 [INFO ] [.core.model.script.shopheaters.rules] - Received temperature: 11 °C

2023-10-29 22:26:10.427 [INFO ] [.core.model.script.shopheaters.rules] - Received temperature as number: 11 °C

2023-10-29 22:26:10.431 [INFO ] [.core.model.script.shopheaters.rules] - Target temperature changed to: 11 °C

==> /var/log/openhab/events.log <==

2023-10-29 22:26:10.435 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'sonoffCNCRoom_TriggerTemperature' received command 11 °C

2023-10-29 22:26:10.440 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'sonoffCNCRoom_StopTemperature' received command 285.15

2023-10-29 22:26:10.511 [INFO ] [openhab.event.RuleStatusInfoEvent   ] - shopheaters-1 updated: IDLE

2023-10-29 22:26:10.514 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'sonoffCNCRoom_TriggerTemperature' predicted to become 11 °C

2023-10-29 22:26:10.521 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'sonoffCNCRoom_StopTemperature' predicted to become 285.15

2023-10-29 22:26:10.529 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'sonoffCNCRoom_TriggerTemperature' changed from 10 °C to 11 °C

2023-10-29 22:26:10.529 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'sonoffCNCRoom_TriggerTemperature' received command 11

2023-10-29 22:26:10.531 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'sonoffCNCRoom_StopTemperature' changed from 284.15 °C to 285.15 °C

2023-10-29 22:26:10.532 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'sonoffCNCRoom_TriggerTemperature' predicted to become 11

==> /var/log/openhab/openhab.log <==

2023-10-29 22:26:10.533 [WARN ] [ab.binding.mqtt.generic.ChannelState] - Incoming payload '' not supported by type 'NumberValue'

It appears that the StopValue is in Kelvin? In DSL is there a way to do this better? Do I need to force the unit to Celsius for every mathematical operation? For this rule it wouldn’t be much, but some of my other rules/files - ugh!

(For context, TriggerTemperature is when the heater is triggered to turn on. StopTemperature is when the heater turns off)

When I change the last line in the rule to:

sonoffCNCRoom_StopTemperature.sendCommand(TargetTemp+1|°C)

I get an even worse stop temp of * 558.3 °C for a target temp of 11°C

Now, fortunately, I have the mqtt channel requires values between 1 and 40, so I don’ need to worry about burning my shop down…

I’ve tried reading through much of the units of measurement discussion on here, but haven’t come up with a solution yet. Do I need to ditch the Number:Temperature and use QuantityType?

If onerous, do I really need to make this change over for my old scripts/items that I know all operate in celsius and have rules that presume this, or can I leave them as dimensionless/unitless Number variables before the big upgrade from OH 3.4.2 to 4.0, or will this break things?

Thanks!

sonoffCNCRoom_StopTemperature is not part of your *.items file and probably has no unit set.
You have to specify the unit there, too.

Or use no UoM at all, the only downside is that you have to do conversions e.g. vom °C → K yourself.
Then your item has to be a plain Number

First, Tutorials and Examples is a place to post working examples, not a place to ask for help. I’ve moved this to a more appropriate category.

Also, you are using OH 4? You mention you are doing stuff in preparation of an upgrade. unit only exists as a thing in OH 4. It’s ignored in OH 3. So if you are testing this on OH 3 you will need to set a stateDescription metadata pattern to indicate the unit to use.

They most definitely are not required. And in fact in OH 4 it’s easier to not have them forced upon you than it ever was in OH 2 and OH 3. Simply define your Items as Number. Even if the Channel says it uses units those will be stripped off if the Item is just Number.

But they are pretty useful and I recommend them.

When using UoM, for addition, subtraction, and comparisons, both operators must have units and must have compatible units (multiplication and division usually do not require units but it depends on the unit involved).

That was an inadvertent cut/paste mistake. My items file does indeed have:

Number:Temperature sonoffCNCRoom_StopTemperature "CNC Room Upper Temperature" {channel="mqtt:topic:6da4d316:UpperTemp", unit="°C" }

I had been hopeful this would have been it. Thanks for your keen eye.
I’m suspicious it is the mathematical operation of adding a unitless ‘1’ that may force the conversion…

Thanks Rich.
I had been reading the tutorials section, then decided to post the question, and must have neglected to notice the category was assigned to where I had been reading. Sorry for the oversight and thanks for moving the post.

For mathematical operations in DSL rules, I’ve been having a difficult time finding out how to assign the unit for my temp variable. I have changed the line with math to:

sonoffCNCRoom_StopTemperature.sendCommand(TargetTemp+1|°C)

but still get the log result with the math error:

2023-10-31 08:12:51.678 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'sonoffCNCRoom_TriggerTemperature' received command 9 °C

2023-10-31 08:12:51.684 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'sonoffCNCRoom_StopTemperature' received command 556.30

When I try specify the var Number TargetTemp line with:

var Number TargetTemp |°C

I get an error:

Configuration model 'shopheaters.rules' has errors, therefore ignoring it: [10,27]: mismatched input '|' expecting 'end'

Could this be the issue? How do I correctly define a temp variable as a celsius temperature value. The examples I see online appear to be for javascript or other languages.

Thanks
Ben

The | °C syntax is only valid for constants. You cannot use it with variables.

You’ve also defined the type of that variable to be a Number. Values with Units are of type QuantityType<?>. But a QuantityType<?> is also a Number so that’s not an error but it could be causing problems.

In general, in Rules DSL it’s best to avoid fixing the types of variables anyway unless it’s absolutely necessary.

No. It’s simply not supported that way.

var TargetTemp = CNCRoom_TargetTemperature.state as QuantityType<Temperature>

Declare and define it all on one line. Make sure you cast to QuantityType.

And if you want to make really certain you are working with °C

    var TargetTemp = (CNCRoom_TargetTemperature.state as QuantityType<Temperature>).toUnit('°C')
rule "Adjust CNC Sonoff Temperatures"
when
    Item CNCRoom_TargetTemperature received update
then
    logInfo("shopheaters.rules", "Starting Shop Heater Target Temp Change Rule")
    logInfo("shopheaters.rules", "Received temperature: " + CNCRoom_TargetTemperature.state)
    var TargetTemp = CNCRoom_TargetTemperature.state as QuantityType<Temperature>.toUnit('°C')
    logInfo("shopheaters.rules", "Target temperature changed to: " + TargetTemp)
    sonoffCNCRoom_TriggerTemperature.sendCommand(TargetTemp)
    sonoffCNCRoom_StopTemperature.sendCommand(TargetTemp+1 | °C)
end

You’ve not answered whether you are actually running this code on OH 4 or not though. If not running on OH 4 there might be other problems that need to be dealt with.

Perfect, thanks Rich. This works well. For some reason I had been looking for a simple declaration statement with the type, but this gets to the point and saves a line of code.

I am on 3.4.2, planning on getting my units sorted (or rather, discovering what work is required and deciding if it is worth it) prior to the migration, based on the published breaking changes.

Then be aware that in OH 3.4:

  • unit Item metadata does nothing
  • the State Description Pattern kind of controls the unit of the Item but does so imperfectly (e.g. restoreOnStartup
  • a plain Number Item can end up with a state that includes units (I can’t remember if this was added before 4.0 or not)
  • bindings can silently push State Description Patterns which can override the system default

Be careful you don’t end up fighting problems caused by trying to implement units on 3.4 using the 4.0 approach.

That is good to know, thanks Rich.
I won’t beleaguer testing this out before the upgrade, then. I’ll just backup really well, and pick a week where I am not working too heavily.

I had been under the impression that I needed to sort my units out before the upgrade, based on my read of the breaking changes / release notes. I will hold off, then fix what is broken. The upgrade script may be helpful if I need to process the influxdb tables manually (but I really hope I don’t).

All you really need to do is:

  1. Decide if you want to use units at all.

  2. If so and you are using managed Items do nothing. the upgrade tool will apply the unit metadata for you based on your current settings. If file based Items, add unit metadata and that’s the unit that will be what is used. I’m not recommending that you don’t add the unit metadata prior to the upgrade. But going through a bunch of testing on OH 3.4 after adding that unit isn’t productive because that unit metadata isn’t applied yet.

  3. If you changed anything (i.e. Items that were not using units before are not using units or vise versa) your rules may need to be updated accordingly.

So all you really need to do is, if using .items files, for any Item you are already using units, add unit metadata. That just makes sure that the Item keeps using the units you are already using immediately after the upgrade. If you have managed Items, you need do nothing. The unit metadata for the unit you are already using will be applied by the upgrade tool.

Anything else you should wait until after the upgrade to mess with.

If you were using units before and after the upgrade you end up with different units, then you will have to change the historic data to match. But if you are happy with the units you have now, there’s really no reason to change the units.

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.