Condition in rule - need to convert number?

Hi
for my e-car charge point I created a rule which should be (or so I thought) rather simple:

The charge point has different charge modes, relevant for the rule are “charge now” and “solar charge” (i.e. only charge when there is excess power from my solar power system).

The charge point is connected to OH3 by MQTT. The MQTT topic which is published by MQTT is: openWB/lp/1/%Soc and the number format is integer, i.e. 50% is sent as 50

The rule I intended to create was to charge my car to 80% with charge now and then change the charge mode to “solar charge”.

Hence, the rule is:
When (trigger):
Every 15 minutes (I needed a trigger, so I decided to check every 15 minutes whether the car ist charged to 80%)

Then (action):
Send command 2 to Charge Mode (Mode 2 is the solar charge)

But only if (condition):
SOC Status is > 90 % (SOC Status is the state of the battery, i.e. how full it is in %)

No, the issue: Apparently the condition doesn’t work. The rule sets the charge mode to solar charge regardless of what the number in the SOC Status is.

The SOC item is a point item, the value I see in the event log is a “regular” number, i.e. when it’s 50% charged the number in the event log shows 50.
I tried the condition with “90” “90%” and “90 %” (the last is how it is shown in the UI). Also, I thought that maybe OH3 passes the “90%” as “0.9”, so I’ve tried the rule with “> 9000”, but still no luck.

What am I doing wrong, do I need to convert the 90 to something, and if so, how?

Thanks for any help!

I’m not sure, how the UI-condition works, but I suspect, it will check for the UoM (Unit of Measurement) for the item. So, either it should accept the Unit (% in your case) or it’s a bug for that.

IMHO you have two options:

  1. let the rule do the calculating (you can easily strip UoMs in rules) and add a if-condition there:
    ** use items["ITEMNAME"].intValue() if using ECMAScript Rules
    ** use ITEMNAME.state.floatValue if using DSL Rules
  2. use evcc.io for charging your EV
  3. file a issue / bug request on github: Issues · openhab/openhab-core · GitHub

I’d recommend evcc, because it completely takes control over your PV excess loading and works with literally any combination of EV and wallbox. there’s also a binding for openHAB:

It’s much easier for us to read and understand a full rule if you click on the “Code” tab and copy/paste the code you find there and use code fences.

```
code goes here
```

Not relevant to your question, but why not trigger it based on the car’s charge level?

Is SOC Status a Number:Dimensionless Item or just a plain old Number?

In events.log, you should see this Item changing state. What does it’s state look like? Is the % part of it?

Shouldn’t that have been > 0.9?

It should work. Here’s an example of a simple UI rule with a condition that uses the state of an Item with UoM.

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: vCloudiness
    type: core.ItemStateChangeTrigger
conditions:
  - inputs: {}
    id: "4"
    configuration:
      itemName: vIsCloudy
      state: OFF
      operator: "!="
    type: core.ItemStateCondition
  - inputs: {}
    id: "5"
    configuration:
      itemName: vCloudiness
      state: 50 %
      operator: <
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "3"
    configuration:
      command: OFF
      itemName: vIsCloudy
    type: core.ItemCommandAction

Notice I use 50 %. If I don’t and only use 50 there will be a warning in openhab.log that I’m comparing a value with units to one without.

1 Like

Hi Rich

thanks for the extensive answer - and first of all, I’d like to apologize for not using code. I usually do, quite honestly, I’m not sure why I didn’t this time around.

Quite simple - I’m sure there is a way around this, but at least the predefined options in the UI don’t offer to trigger a rule for a specific item condition.

You might argue that I could use the trigger “item state was updated” and then set 80% as the value. However, sometimes (the API for the battery state for my car is not very reliable) the state changes 3 steps at a time, i.e. from 79% directly to 82% - and then the rule would not fire, would it?

Just plain old number - if I changed that to Number:Dimensionless, would the rule work without using script?

No, it’s not. Just showing plain numbers, no % anywhere near

My thought was: If OH3 passes 90% as 0.9, but MQTT uses the percentage, then obviously any number would be higher than 0.9 - which would’ve explained why the rule even fires when the battery state is 1%. Hence, if I tell the rule to pass 9000, my hope was that MQTT receives 90, which would’ve fixed the rule. Apparently it didn’t.

In any case: The suggestion from @binderth actually did work (thank you for that), though I would’ve preferred a way without using script, even if the script is less than a full line.

Also, one personal remark to @rlkoshak: I’ve been using OH since 1.3 or so, I believe, and whenever I have problems, I (obviously) turn to the forum, and though I can’t code, I did and do try to help when I can. Your work, however, is beyond comparison, quite a few of your posts answered questions that I had as well, or solved problems I experienced. Thank you very much for all the work, and do let me know if I can help in any other way (I’m quite good at marketing, if that helps)

That’s what the condition is for. You trigger the rule using the Item state changing and then set a rule condition so it only runs the rule if it meets the condition (e.g. > 80 <= 80).
You would never add a condition like this in the trigger itself.

OK, then the Item most likely doesn’t carry units. But double check events.log to verify. It is possible to send a number with units to a plain Number Item and the units will stick even if the Item isn’t declared to support units.

Good, so just use a plain number, no % and it really is 90 and not .9.

This should work without the script. It’s working for me. In fact I have rule templates that depend on it. So something must be misconfigured or weird is going on. Assuming it’s just a number a condition of > 90 would only trigger the rule when the Item is above 90. Unless, it’s possible that conditions do not work correctly when the rule is triggered based on Time (e.g. a cron trigger).

Nope, I just tested it and the condition works with a cron trigger both with and without units.

configuration: {}
triggers:
  - id: "1"
    configuration:
      cronExpression: 0/10 * * * * ? *
    type: timer.GenericCronTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: RichOfficeSensors_Temperature
      state: "60"
      operator: <
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "3"
    configuration:
      type: application/javascript;version=ECMAScript-2021
      script: console.log('Test rule ran')
    type: script.ScriptAction

The sensor Item is currently 75 °F. I get a warning in the log I already mentioned but it stops the rule from running. If I flip to > the rule runs every ten seconds as expected (no warning in the log though interestingly.

Thanks for the recognition. I like to help people and, selfishly, helping others helps me learn stuff too and keeps my knowledge and skills fresh.

1 Like

If you like to dig a bit further with us (Rich already answered mostly everything already - as usual! :wink: ), drop the Thing-configuration and Items-configuration of your Wallbox and EV. I don’t think it works that way you’re describing - until you have some transformations somewhere in either the MQTT-channel or in a item-configuration. 90 should be 90 and sent/received as 90… at least, that’s what most wallboxes use - and as I glanced over openWB’s docs they also use that…

Hi @rlkoshak and @binderth

Happy to provide more details - always keen to learn more as well.
So, here are my configurations:

OpenWB MQTT config:

UID: mqtt:topic:30198930b0:7288900f1f
label: OpenWG MQTT Thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:30198930b0
channels:
  - id: OpenWB_Lademodus
    channelTypeUID: mqtt:number
    label: OpenWB Lademodus
    description: ""
    configuration:
      commandTopic: openWB/set/ChargeMode
      stateTopic: openWB/global/ChargeMode
  - id: OpenWB_charge_W
    channelTypeUID: mqtt:number
    label: OpenWB aktuelle Ladeleistung
    description: ""
    configuration:
      stateTopic: openWB/lp/1/W
      unit: W
  - id: SOC_Status
    channelTypeUID: mqtt:dimmer
    label: SOC Status
    description: ""
    configuration:
      stateTopic: openWB/lp/1/%Soc
  - id: openWB_BatterieProzent
    channelTypeUID: mqtt:number
    label: openWB_BatterieProzent
    description: ""
    configuration:
      postCommand: true
      unit: "%"
      min: 0
      max: 100
      commandTopic: openWB/config/set/sofort/lp/1/socToChargeTo
      step: 5
      stateTopic: openWB/config/get/sofort/lp/1/socToChargeTo
      transformationPattern: JS:openwb_percent.js

The item for the EV/Battery has the following characteristics:

Type: Dimmer
Semantic Class: Point
Semantic Property: None

Do you need any other info from that item?
And, lastly, the rule (the working version now):

configuration: {}
triggers:
  - id: "3"
    configuration:
      cronExpression: 0 0/15 * * * ? *
    type: timer.GenericCronTrigger
conditions:
  - inputs: {}
    id: "5"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: OpenWGMQTTThing_SOCStatus.state.floatValue > 90
    type: script.ScriptCondition
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: GenericMQTTThing_OpenWBLademodus
      command: "2"
    type: core.ItemCommandAction
  - inputs: {}
    id: "4"
    configuration:
      message: SOC > 90?
      userId: patrick@boch.org
    type: notification.SendNotification

As for the question about the units:
UI, event log, and MQTT Explorer all state plain full numbers, no %, no decimal places. That’s why I was a bit surprised when my initial version of the rule, where the condition “only if SOC State is larger then 90”, set up completely with the UI, didn’t work.

I don’t know openWB, but what I see is, your Channel openWB_BatterieProzent is using “%” as unit and uses a JS-transformation. Can you please also paste the content of openwb_percent.js?

And please look into events.log and openhab.log and paste the last few lines, where GenericMQTTThing_OpenWBLademodus is mentioned. there’s something going on here… :wink:

Are you certain you only receive integers on the SOC_Status Channel? It’s configured as a Dimmer which only supports integer values between 0 and 100. If you ever get something like 52.4 it won’t work. Dimmers are not numbers in the pure sense of the word. They are special in how they are handled in OH. There are no units for Dimmers.

The fact that you’ve define the units on the Battery Percent channel does mean that the Item linked to that channel should be using units, but we aren’t using that Item here.

Based on what’s working for me, if you created a pure UI condition for this instead of the script condition, it should look like the following.

conditions:
  - inputs: {}
    id: "6"
    configuration:
      itemName: OpenWGMQTTThing_SOCStatus
      state: "90"
      operator: >
    type: core.ItemStateCondition

If that doesn’t work, the problem has to be with the fact that it’s a Dimmer Item. Perhaps there’s a bug that makes this type of condition not work with Dimmer Items and we need to file an issue for that.

Sorry, what I did not catch yesterday was that somehow, openWB acts itself as some kind of PV excess logic loading device? Is the socToChargeTo topics configuration within openWB itself?

And the EV-SoC must come somehow from your car. How do you fill the openWB/lp/1/%Soc topic? Does the Wallbox get that directly with a built-in feature in openWB (I read about “EV SoC Modules” for openWB) or do you get SoC-information from your car and send the information directly to that topic?

apart from that: Rich is right, Dimmer is something different, but mostly battery SoC do come as integers, not decimals - and also range from 0 to 100. worth looking into of course.

OK, so here’s what I did so far.
I’ve changed both SOC channel and the corresponding item to be Number instead of Dimmer

“Unfortunately” the SOC Status is currently 100%, so I’m not sure whether the rule will work - I’ll get back later with an update.

However, just for clarification:

SOC_Status indeed only sends integers.

As for the logs, GenericMQTTThing_OpenWBLademodus does show up in the event.log, but not in openhab.log. Here’s what’s in event.log

2022-10-18 16:15:00.957 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'GenericMQTTThing_OpenWBLademodus' predicted to become 2
2022-10-18 16:30:00.961 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'GenericMQTTThing_OpenWBLademodus' received command 2
2022-10-18 16:30:00.961 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'GenericMQTTThing_OpenWBLademodus' predicted to become 2
2022-10-18 16:40:42.457 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'GenericMQTTThing_OpenWBLademodus' changed from 2 to 0
2022-10-19 09:20:49.699 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'GenericMQTTThing_OpenWBLademodus' received command 2
2022-10-19 09:20:49.699 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'GenericMQTTThing_OpenWBLademodus' predicted to become 2
2022-10-19 09:20:49.700 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'GenericMQTTThing_OpenWBLademodus' changed from 0 to 2

Yes, it does. There is, in fact, a setting where I could set the minimum SOC state. The reason I’m still using OH for that has to do with the fact that soon we’ll have two EV, and I want them to be charged to different states.

Yes, that as well - though I can send another value to openWB as well (which I do with a Step Widget)

Again, Yes, OpenWB includes that feature, though the API used in my case (Citroen) is apparently not really reliable. Still works most of the time for me.

I’m a bit confused about the “predicted to become”, “received command” , …
could you add a log entry (either in the script or in “send a log message” in the Rules-UI) so, that the changing of items is directly linked to your rule. I get the feeling, openWB changed the charging mode itself - at least at 16:40 and 09:20? as your trigger is */15 mins?

and please check for the SoC item changes in events.log and can you fetch the MQTT-topics with a tool like MQTT-Explorer or such to see, what is in there?

evcc.io uses the “car connected” status from the EV API to activate a car, perhaps that’s also possible somehow with openWB? so you can have two profiles for cars (two SoC, two target SoC, …) and openWB gets its information from the EV API, which one is connected right now?

If you read through conversations around that, nearly every EV manufacturer does have issues with its API. Be it an openly accessile one or a re-engineered one. Not only is there the issue of rate limiting, but also direct connection “near real time” to the specific EV for charging related information. I nearly everytime get some 2-3% “overcharging”, as the Kia API also does not allow fast polling or simply does only allow direct car connections at certain (seemingly random) times.
only way out of it would be to use the OBD2 interface, something like

http://api.openvehicles.com/

or

https://evnotify.de/

…but I figured, the Car API is sufficient and sometimes it’s ok to “overcharge” a few kWh with PV excess loading instead of using the OBD2. I even tried to use and bluetooth OBD with an ESP32 (or Pi) and an Arduino but got stuck with the specific registers for my Kia EV6:

So my 2cents: go with the Car API, usually there’s a plugin somehow present for accessing it and use that data.

Your original was trying to test for > 90 so the rule should run if it’s at 100. You can flip the condition to < and see if the rule stops running and that will show the condition is working.

You can add a simple script action with a log statement to see the rule running.

Well, what can I say. The rule was running - but wrongly again, i.e. if I replaced > with <, the rule would still “fire”, i.e. charge mode changed.

Here’s what I did. First, since I couldn’t change the original channel from Dimmer to Number, I created a new channel plus a corresponding item:

UID: mqtt:topic:30198930b0:7288900f1f
label: OpenWG MQTT Thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:30198930b0
channels:
  - id: OpenWB_Lademodus
    channelTypeUID: mqtt:number
    label: OpenWB Lademodus
    description: ""
    configuration:
      commandTopic: openWB/set/ChargeMode
      stateTopic: openWB/global/ChargeMode
  - id: OpenWB_charge_W
    channelTypeUID: mqtt:number
    label: OpenWB aktuelle Ladeleistung
    description: ""
    configuration:
      stateTopic: openWB/lp/1/W
      unit: W
  - id: SOC_Status
    channelTypeUID: mqtt:dimmer
    label: SOC Status
    description: ""
    configuration:
      stateTopic: openWB/lp/1/%Soc
  - id: openWB_BatterieProzent
    channelTypeUID: mqtt:number
    label: openWB_BatterieProzent
    description: ""
    configuration:
      postCommand: true
      unit: "%"
      min: 0
      max: 100
      commandTopic: openWB/config/set/sofort/lp/1/socToChargeTo
      step: 5
      stateTopic: openWB/config/get/sofort/lp/1/socToChargeTo
      transformationPattern: JS:openwb_percent.js
  - id: SOCStatus
    channelTypeUID: mqtt:number
    label: SOCStatus
    description: ""
    configuration:
      stateTopic: openWB/lp/1/%Soc
      max: 100
      min: 0

(Note, the old channel is still in there, but not linked to an item). So, theoretically, creating the rule with just using UI should work - it doesn’t. Here’s the rule:

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: OpenWGMQTTThing_SOC_Status
    type: core.ItemStateChangeTrigger
conditions:
  - id: "3"
    configuration:
      itemName: OpenWGMQTTThing_SOC_Status
      operator: <
      state: "90"
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: GenericMQTTThing_OpenWBLademodus
      command: "2"
    type: core.ItemCommandAction
  - inputs: {}
    id: "4"
    configuration:
      message: SOC > 90?
      userId: xxxx
    type: notification.SendNotification

Also, this time around, when I use the scripts suggested by @binderth, it also doesn’t work, i.e. with the state being 100, it also fires when I set the condition to < 90

Also, looking at the logs and what happens with the OpenWBLademodus, if the rule changes the charge mode, the log reads:

2022-10-19 15:50:33.364 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'GenericMQTTThing_OpenWBLademodus' received command 2
2022-10-19 15:50:33.364 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'GenericMQTTThing_OpenWBLademodus' predicted to become 2
2022-10-19 15:59:43.324 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'GenericMQTTThing_OpenWBLademodus' changed from 0 to 2

When I change the charge mode manually, the log only reads:

2022-10-19 16:01:10.418 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'GenericMQTTThing_OpenWBLademodus' changed from 2 to 0

So, no “predicted” here.

As for the numbers: as the logs state, SOC_Status is an integer number, no decimals, no unit. MQTT Explorer shows the same

Just to be clear, when you say “fires” you mean that the two Actions run.

To be precise, the rule fires any time the triggering event(s) occur. In this case, every time the SOC_Status Item changes to any value. But the Actions should only execute when the condition is met.

That’s good. That means it’s working. Something else (presumably the binding) updated the Item to 0. The rule didn’t run and command the Item. You only see that “predicted” log entry when the Item receives a command and autoupdate is configured on that Item (it’s enabled by default). There is nothing in your rule that posts an update to the Item so that change from 2 to 0 didn’t come from this rule.

The condition is working.

Exactly, the actions run, even if the condition is not met.

Yes, I believe so - it was me changing the charge mode from 2 to 0 in the openWB web interface, and I assume the binding passed over this state change and therefore it’s in the logs.

I’m not sure where to go from here. I’ve five rules in my system that work with a condition like this. I created a test rule (see above) that also works.

We know it’s not units that’s the problem.

Add a script action that logs the state of both the SOC_Status and OpenWBLademodus Items. This will show us the rule running and what state these Items are in when it runs.

Then let it run through a few times with the condition the correct way. Copy and paste the rule followed by all the logs in openhab.log and events.log into a repkly.

Then update the rule to flip the condition and let it run through a few times. Copy and paste the rule followed by all those logs as well.

One more question: in the rule I now use “send a command” to change the SOC_Status - would it be better to “update an item state” (and if so, why)?

1 Like

Gotta go a bit more basic. How rules work! :wink:

first of: a rule needs a trigger (When), you switched from “cronbased” to “item change”.
Only after that “change”, your rule should “fire”, because the trigger is a change of the item.
So, the rule only “fires”, if the trigger is met. As long as the item doesn’t change, nothing happens at all.

Second, you have an action (Then), which should happen, when the trigger is met
Here you have a sendCommand-action on the GenericMQTTThing_OpenWBLademodus item to be commanded a value of 2. That means, the value 2 will be sent to the item - AND it’s being send to the binding/channels, and only by that “command” it reaches your device. Using postUpdate-action on a item only updates the value. [1]

And thirdly, you have a condition (only when), which narrows the triggering to that condition.
In your rule it’s the “state condition” of OpenWGMQTTThing_SOC_Status.

With that out of the way:
Your condition is OpenWGMQTTThing_SOC_Status < 90, so what I’d like to see is, what your logs say the states are of this item. We expect an integer without any Units, something like OpenWGMQTTThing_SOC_Status changed from 89 to 91.

There’s two possibilites:

  1. the item received a command of 90, but its state is already 90, so the trigger won’t “fire”, because you said changed
  2. the item changed to a value, which the condition doesn’t interpret as “yeah, that’s it”. So, if your item value is 90 %, then the condition < 90 isn’t met.

So, tl:>dr;
please paste the log entries of your SoC item and your Lademodus item, and then I think we have all we need! :wink:

[1]
Simply put:

  • if you want something to change (lights, set-temperature, …) you want to send a “command” to an item.
  • if you have just a item for logic or whatever reasong, you want to “update” the item

if you’re using the UI (buttons, sliders, widgets, …), the UI sendCommands the items. This causes the state to update automatically at the same time (using autoupdate, activated by default) - resulting the binding to also update the device, etc.
if you’re using the REST API or rules, you can chose between both alternatives.
The rules can either be triggered by receiving commands, items’ states updating, or items’ states changing to a different value…