OH3 Widget to use - zigbee2mqtt JSON to item and publish formatted payload

Dear all

I ask again your help

I have the following json file as output from a thermovalve,

{
"auto_lock": "MANUAL",
"away_mode": "OFF",
"away_preset_days": 5,
"away_preset_temperature": 20,
"battery_low": false,
"boost_time": 300,
"child_lock": "UNLOCKED",
"comfort_temperature": 35,
"current_heating_setpoint": 17,
"eco_temperature": 13,
"force": "normal",
"holidays": [
    {
        "hour": 6,
        "minute": 0,
        "temperature": 20
    },
    {
        "hour": 8,
        "minute": 0,
        "temperature": 15
    },
    {
        "hour": 11,
        "minute": 30,
        "temperature": 15
    },
    {
        "hour": 12,
        "minute": 30,
        "temperature": 15
    },
    {
        "hour": 17,
        "minute": 30,
        "temperature": 20
    },
    {
        "hour": 22,
        "minute": 0,
        "temperature": 15
    }
],
"last_seen": "2020-12-31T08:45:53.953Z",
"linkquality": 135,
"local_temperature": 22,
"local_temperature_calibration": 2,
"max_temperature": 35,
"min_temperature": 5,
"position": 0,
"preset": "manual",
"system_mode": "auto",
"week": "5+2",
"window_detection": "OFF",
"window_detection_params": {
    "minutes": 17,
    "temperature": 2
},
"workdays": [
    {
        "hour": 6,
        "minute": 15,
        "temperature": 18
    },
    {
        "hour": 8,
        "minute": 15,
        "temperature": 17
    },
    {
        "hour": 11,
        "minute": 45,
        "temperature": 17
    },
    {
        "hour": 13,
        "minute": 15,
        "temperature": 17
    },
    {
        "hour": 18,
        "minute": 15,
        "temperature": 18
    },
    {
        "hour": 22,
        "minute": 15,
        "temperature": 17
    }
]

}

for single properties there is no problem, i retrieve setting using JSONPATH and publish it with formatBeforePublish

        Type string : auto_lock  [ stateTopic="zigbee2mqtt/Termovalvola_Test1", transformationPattern="JSONPATH:$.auto_lock", commandTopic="zigbee2mqtt/Termovalvola_Test1/set", formatBeforePublish="{\"auto_lock\" : \"%s\"}" ]                                

the problem is for the holydays or workdays properties;
there are 6 period for and i need to change it separately:

"holidays": [
{
    "hour": 6,
    "minute": 0,
    "temperature": 20
},
{
    "hour": 8,
    "minute": 0,
    "temperature": 15
},
{
    "hour": 11,
    "minute": 30,
    "temperature": 15
},
{
    "hour": 12,
    "minute": 30,
    "temperature": 15
},
{
    "hour": 17,
    "minute": 30,
    "temperature": 20
},
{
    "hour": 22,
    "minute": 0,
    "temperature": 15
}

],

what I need is to 2 items for each period :
workdays_time_period1 (and need to retrieve 6:00 considering the first period as example)
workdays_temp_period1 (need to retrieve 20)

and the same for all the periords and the question is how can I do this?

and when items changes I need to publish them trasforming time in two parts, hours and minute and publish the entire string for all periods, i done it with a rule declaring tre items for each period

        val mqttActions = getActions("mqtt","mqtt:broker:mosquitto")
    var jsonString = "{\"holidays\":["
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H1h_Config.state +",\"minute\":" + Termovalvola_Test1_H1m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H1T_Config.state +"},"
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H2h_Config.state +",\"minute\":" + Termovalvola_Test1_H2m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H2T_Config.state +"},"
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H3h_Config.state +",\"minute\":" + Termovalvola_Test1_H3m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H3T_Config.state +"},"
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H4h_Config.state +",\"minute\":" + Termovalvola_Test1_H4m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H4T_Config.state +"},"
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H5h_Config.state +",\"minute\":" + Termovalvola_Test1_H5m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H5T_Config.state +"},"
    jsonString = jsonString +  "{\"hour\":" + Termovalvola_Test1_H6h_Config.state +",\"minute\":" + Termovalvola_Test1_H6m_Config.state + ",\"temperature\":" + Termovalvola_Test1_H6T_Config.state +"}"
    jsonString = jsonString + "]}"

    mqttActions.publishMQTT("zigbee2mqtt/Termovalvola_Test1/set/schedule",jsonString) 

but I hope there is a more simple way to do it and the question is what is the simple way?

other question concern the best way to represent the input field for time in main UI,
i use an input item declaring it as time and it works

                - component: oh-input-item
              config:
                label: Orario
                type: time
                item: =props.timeItem
                color: orange
                outline: true
                validate: true
                variable: alarm

but after i need to split hour and minute to format the json string to publish.

thanks in advance for your help

Only a partial help, but I think I’ve seen an example which commanded a String Item to something like

"One, two, three"

and then in the linked Channel formatBeforePublish has three %s which get populated by the words in the comma-separated string.

formatBeforePublish = "My 1 %s; My 2 %s; My 3 %s"

I’d be very interested if my memory is correct!

:rofl:

So you have got it working? That rule dose send the data through MQTT to you thermovalve and now you just want a tidy widget to be able to display the seeing and change them?

O and stop using test everywhere because when you get it working you will never get around to changing it because it works :slight_smile:

Edit: This is a challenge when they use no standard json

It’s working with rule but i haven’t a linked item and the problem is that if data changes out of openhab the virtual items are not synchronized…

What i need is

  1. have a solution to retrieve data from json result and assign them to related items…please suggest me the right method to avoid to write a lot of rules or items if there is one
  2. have a solution for sending back the json formatted, but please note that zigbee2mqtt need for this type of valve a full json with all six period
  3. a furb way to represent it in UI, now I’m using a slider for virtual item period1_hour, one for period1_minute and one for period1_temperature…this repeated for period 1 to 6 replicated for workdays and holidays setting…
    You can image that I have to configure only for scheduler 18 items for each thermovalve…
    I wish I would simplify this…and searching for a solution

I get this error

2020-12-31 21:09:11.182 [WARN ] [ternal.JSonPathTransformationService]
 - JsonPath expressions with more than one result are only supported for Boolean,
 Number and String data types, please adapt your selector. 
Result: [{"hour":6,"minute":0,"temperature":20},{"hour":8,"minute":0,"temperature":15},
{"hour":11,"minute":30,"temperature":15},{"hour":12,"minute":30,"temperature":15},
{"hour":17,"minute":30,"temperature":20},{"hour":22,"minute":0,"temperature":15}]

`

Are you aware of the option in zigbee2mqtt to transmit the attributes on separate topics, rather than using JSON? Might make things easier for you:

Assigning the channel holidays with jsonpath to a string item i received the same error…
That’s why I’m asking your help

I’ll try again in the next days but I already have the attribute active in the configuration yaml of zigbee2mqtt…

I’ll try again

I don’t have this device so that option may not do anything! :man_shrugging:

Ok I have a partial solution. You can deal with it being a time I just did it with strings to see if it works.

Create Items with the names

String Holiday_0
String Holiday_1
String Holiday_2
String Holiday_3
String Holiday_4
String Holiday_5
String incoming_json {channel blah blah blah}

Create Rule

rule "Transform json message to items and numbers"
when
    Item incoming_json changed
then
  val Hour_String = transform("JSONPATH", "$.holidays[*].hour", incoming_json.state.toString) 
  val Hour_Array = Hour_String.replace('[','').replace(']','').replace(' ','')   
  val Hour_Buffer =  Hour_Array.split(",")  

  val minute_String = transform("JSONPATH", "$.holidays[*].minute", incoming_json.state.toString) 
  val minute_Array = minute_String.replace('[','').replace(']','').replace(' ','')   
  val minute_Buffer =  minute_Array.split(",")

  Hour_Buffer.forEach[ Hour , Index | 
   var minute = minute_Buffer.get(Index)
   var item = "Holiday_" + Index
   item.sendCommand(Hour + ":" + minute)
  ]

end

image

OK time to :partying_face:

James Bowler

first of all thanks gor your help, it works, but because input time widget request a hh:mm format I add/changed your code as follow ( I don’t know how but it works, I’m not so skilled in java/rules writing):

    val Hour_String = transform("JSONPATH", "$.holidays[*].hour", incoming_json.state.toString)
val Hour_Array = Hour_String.replace('[','').replace(']','').replace(' ','')   
  val Hour_Buffer =  Hour_Array.split(",") 

  val minute_String = transform("JSONPATH", "$.holidays[*].minute", incoming_json.state.toString) 
  val minute_Array = minute_String.replace('[','').replace(']','').replace(' ','')   
  val minute_Buffer =  minute_Array.split(",")

  Hour_Buffer.forEach[ Hour , Index | 
   var minute = minute_Buffer.get(Index)
   var item = "Holiday_" + Index

   var String long_hour
   var String long_minute

        if (Hour.length<=1){
            long_hour = "0" + Hour
        }
        else {
            long_hour = Hour
        }

        if (minute.length<=1){
            long_minute = "0" + minute
        }
        else {
            long_minute = minute
        }

   item.sendCommand(long_hour + ":" + long_minute)
  ]

Further step is try to send back the “short” format starting from hh:mm string, but it should be simpler…I hope

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