[SOLVED] Mqtt Item data Problem

I think I have it working now, I’ll keep an eye on it during the day

Thank you for all your help.

If i was to try and grab another value from the string in the same script could i just add the below

WatchmanTemp.postUpdate(transform("JSONPATH", "$.temperature_C", WatchmanTemp.state.toString))
 val float temp = Float::parseFloat(WatchmanTemp.state.toString) as Number
WatchmanTemp.sendCommand(temp)

When I add that I get the error:

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Update oil level': For input string: "NULL"

One line should be enough

val Number height = 89 // height of the tank

rule "Update oil level"
when
    Item RawJson changed
then
    val String id = transform("JSONPATH", "$.id", RawJson.state.toString)
    if (id == "141932971") {
        val Number depth = Float::parseFloat(WatchmanDepth.state.toString) as Number
        val Number left = height - depth
        val Number per = (left / height) * 100
        WatchmanPercentage.postUpdate(per) // update the item that holds the percentage

        WatchmanTemp.postUpdate(transform("JSONPATH", "$.temperature_C", RawJson.state.toString))
    }
end

I have expanded it slightly to send out more info to other items for display on sitemap (litres, temp and percentage) plus depth for grafana

val float height = 90 // height of the tank

rule "Update oil level"
when
    Item WatchmanCalc changed
then
    val String id = transform("JSONPATH", "$.id", WatchmanCalc.state.toString)
    if (id == "141932971") {
    WatchmanDepth.postUpdate(transform("JSONPATH", "$.depth", WatchmanCalc.state.toString))
    val float depth = Float::parseFloat(WatchmanDepth.state.toString) as Number
    val float left = height - depth
    val float per = (left / height) * 100
    WatchmanPercentage.sendCommand(per) // update the item that holds the percentage
    WatchmanTemp.postUpdate(transform("JSONPATH", "$.temperature_C", WatchmanCalc.state.toString))
    val float temp = Float::parseFloat(WatchmanTemp.state.toString) as Number
    val float litre = (left / height) * 1200
    WatchmanLitre.sendCommand(litre)
    WatchmanDepth.sendCommand(depth)
    WatchmanTemp.sendCommand(temp)
}
end

When this runs with dummy data im sending (I can’t wait 40mins between transmissions) I get the following logged


```csv
2019-01-15 21:22:20.500 [vent.ItemStateChangedEvent] - WatchmanDepth changed from 99.0 to 25
2019-01-15 21:22:20.509 [ome.event.ItemCommandEvent] - Item 'WatchmanPercentage' received command -10.0
2019-01-15 21:22:20.519 [ome.event.ItemCommandEvent] - Item 'WatchmanLitre' received command -120.0
2019-01-15 21:22:20.527 [ome.event.ItemCommandEvent] - Item 'WatchmanDepth' received command 99.0
2019-01-15 21:22:20.538 [vent.ItemStateChangedEvent] - WatchmanDepth changed from 25 to 99.0

The correct dummy data gets stored but then it reverts back, I am sending 25 as depth but it reverts back to a previous set number of 99.0

EDIT - I think I have it going now, I didn’t need the SendCommand for temp or depth as it’s already being posted above, grafana is getting the data now and it’s not duplicating itself.

Steep learning curve for me but I’m slowly starting to understand!

EDIT 2 - Not 100% but the script needs to run twice before it calculates percentage on a depth change. If the depth changes, script runs but it doesn’t update anything. The next time it polls it then generates the percentage and so on. Why would this be?

It’s likely to be useful to insert logInfo into your rule to see what it is doing
e.g.
logInfo("calc", "id " + id)
and so on

Negative percentage looks a bit odd, but I’ve not followd your calculations.

You are updating item and then sending a command to them why?

val float height = 90 // height of the tank

rule "Update oil level"
when
    Item WatchmanCalc changed
then
    val String id = transform("JSONPATH", "$.id", WatchmanCalc.state.toString)
    if (id == "141932971") {
    WatchmanDepth.postUpdate(transform("JSONPATH", "$.depth", WatchmanCalc.state.toString))
    val Number depth = Float::parseFloat(WatchmanDepth.state.toString) as Number
    val Number left = height - depth
    val Number per = (left / height) * 100
    WatchmanPercentage.postUpdate(per) // update the item that holds the percentage //postUpdate
    WatchmanTemp.postUpdate(transform("JSONPATH", "$.temperature_C", WatchmanCalc.state.toString))
    // val float temp = Float::parseFloat(WatchmanTemp.state.toString) as Number NOT NEEDED
    val Number litre = (left / height) * 1200 // Number not float
    //WatchmanLitre.sendCommand(litre) postUpdate instead
    WatchmanLitre.postUpdate(litre) postUpdate instead
    // WatchmanDepth.sendCommand(depth) NOT NEEDED
    // WatchmanTemp.sendCommand(temp) NOT NEEDED
}
end

Sorry, I should have updated the previous post with where I was at.

See below. It takes two runs of the script for it to calculate litre changes.

If I send a payload with depth at 40 (from previously being 51), the script runs picking up the depth change. The next time a payload comes through the script is triggered again where it then calculates the litres. I don’t understand why it can’t do all the calculations on the first pass, why does it need to have to be ran twice?

val Number height = 89 // height of the tank

rule "Update oil level"
when
    Item WatchmanCalc changed
then
    val String id = transform("JSONPATH", "$.id", WatchmanCalc.state.toString)
    if (id == "141932971") {
    WatchmanDepth.postUpdate(transform("JSONPATH", "$.depth", WatchmanCalc.state.toString))
    val Number depth = Float::parseFloat(WatchmanDepth.state.toString) as Number
    val Number left = height - depth
    val Number per = (left / height) * 100
    WatchmanPercentage.sendCommand(per) // update the item that holds the percentage
    WatchmanTemp.postUpdate(transform("JSONPATH", "$.temperature_C", WatchmanCalc.state.toString))
    val Number litre = (left / height) * 1200
    WatchmanLitre.postUpdate(litre)
}
end

Because of this:

    WatchmanDepth.postUpdate(transform("JSONPATH", "$.depth", WatchmanCalc.state.toString))
    val Number depth = Float::parseFloat(WatchmanDepth.state.toString) as Number

You are posting an update to the item and then read the item state in the next line. BUT the item state has not yet been updated. It takes time for the event bus to react.

Change it to:

    val depthString = transform("JSONPATH", "$.depth", WatchmanCalc.state.toString)
    WatchmanDepth.postUpdate(depthString)
    val Number depth = Float::parseFloat(depthString) as Number

Also change:

    WatchmanPercentage.sendCommand(per) // update the item that holds the percentage

To:

    WatchmanPercentage.postUpdate(per) // update the item that holds the percentage

aaahhh, interesting.

thank you, so far so good. Was stumped for a bit as I had mistyped something as simple as a capital which I now know can throw the whole script off!

I’ll report back any further issues