Item changed fast (1s) but only last change is seen by rule?

Then either there is a command in your rule that is taking longer than expected to complete or the events are coming in much faster than one per second.

What is it in your rule that is taking a long time to complete. As I read the Rule it shouldn’t be taking longer than a dozen milliseconds to complete. You should never have a case where more than one instance of it is running at the same time for events that take place over a second apart.

Looking at the time stamps here is what I’m willing to bet money is happening.

You have some Thread::sleeps or calls to actions that take a long time to complete (executeCommandLine, sendHttp*Request, etc).

The Rules Engine only gives you 5 execution threads. This means only 5 rules can run at the same time. When you have Rules that take a long time to complete you have a high likelihood that you run out of execution threads. When that happens no new Rule can run until one of these running Rules exits.

So I’m going to guess that you are running out of Rules threads which is delaying the time when your Rules can execute in response to the change. By the time the Rule does execute, the MQTT_Trigger_Dummy has already changed state so the Rule ends up running twice with the same value.

  1. MQTT_Trigger_Dummy changes to 155548
  2. MQTT_Trigger_Dummy changes to 110806
  3. More than a second later the Rule triggers in response to event 1. But the Item has already changed state to 110806 so that is what the Rule runs with.
  4. The Rule triggers again in response to event 2 and processes with 110806.

So i’m back after a day,
i checked my whole rules:

  • not a single delay
  • one cron entry (checks every hour if one of the sensor updates is older then one hour, if so send telegram message with the sensor not sending info)

And also sometimes i see very fast MQTT Updates like these:

2018-05-15 12:52:01.760 [vent.ItemStateChangedEvent] - MQTT_Trigger_Dummy changed from 130617 to 155521
2018-05-15 12:52:01.809 [vent.ItemStateChangedEvent] - MQTT_Trigger_Dummy changed from 155521 to 110459
2018-05-15 12:52:01.827 [vent.ItemStateChangedEvent] - MQTT_Trigger_Dummy changed from 110459 to 130618

Without the lock these lead to changes during the exection of the rule, in the above example -13000.0 Degrees. Sadly after the check if the value is in legal range g. But i can secure the code a little bit more.
Like reading the state of the item in the beginning of the rule into a extra variable and later only work with the variable and not with the item.state. This should make the code a little bit safer against state changes during rule exection.

Also I will look into the gateway and see if i can limit the mqtt message send per time to something about 1 message per second.

Will keep you updated.

A little bit. But if you use received command for your trigger then the receivedCommand implicit variable will be populated. Does it really matter if older values are skipped for something like humidity values? The value is unlikly to be that different if the messages are arriving fast enough to be causing this problem.

The sensors sends their value between 10 minutes and 60 minutes. (Depends where they are and what they measure). So if in one intervall 2 of lets say 3 values are missed and the next send is 60 minutes away then it indeed does matter if the values are “lost”.

As a explanation: All the sensors send their data via 433Mhz and i use a NodeMcu ESP8266 with OpenMQTTGateway to recieve all 433Mhz messages and transfer these to a MQTT Messages.

But if you receive three values within a few seconds, those previous two will only be in the system for a few seconds before they get replaced by the last value anyway. Unless you have code you haven’t posted, it is only processing data for the FF_Bath_Humidity. So I just don’t see the impact if your FF_Bath_Humidity loses a few values that would only have been set to the FF_Bath_Humidity Item for a few seconds at the most anyway.

FF_Bath_Humidity will always be set to the most recent value received in all cases. So it doesn’t matter if it will be 60 minutes until the next update.

As i posted in the very first posting, the rule above is not complete,
i shortened it to show a example (here humidity).
You couldn’t know there are a lot more Items and values analysed:

Some example from the easiest sensor board in the bath:
It sends three values: Voltage of battery, humidity and temperature.
This looks like the following for the MQTT_Trigger_Dummy.state

  • 155521: 15 says first sensorboard, voltage with 5521mV
  • 110459: 11 says first sensorboard, humidity with 45.9%
  • 130618: 13 says first sensorboard, temperature with 21,8 Degree

And so on for different sensorboards. Additional to above we have x2nnnn in co2 ppm, x4nnnn rain in mliter, x6nnnn pressure in hPa, x7nnnn water level in percent and x8nnnn light level in lumen.

Hopefully this explains why missing a MQTT_Trigger_Dummy with the rule is bad, it is a lost sensor value.

I totally understand, that it looked from the code given in my first post like it only misses a value for humidity, but sadly this is not the case.

If after our discussions the result is, that the rule system is not fitting for a transformation like this, then i have to go the other way: i have to change for every sensor the gateway. So to say make the gateway intelligent and the not need the rules. With the downside to having to go to the gateway everytime something on the sensors have to be changed.

Or you can change your MQTT config on the Items to use command instead of state (assuming that you are not already) and change the Rule trigger to received command and use the receivedCommand implicit variable instead of MQTT_Trigger_Dummy.state.

receivedCommand doesn’t depend on the Item’s actual state so even if the Item changes state while the Rule is processing receivedCommand won’t change on you.

Thank you for this inside.
Will definitly try this also and see what the outcome will be.

Maybe it is jsut the way you try to process this values which makes it slow, you could try somthing different like in this post.

So my idea would be to distribute the received value to an other item and then you can process this items with a other rule. You can then put all e.g. all voltages into one group and have a rule triggered by this group to process the value.

Not tested but something like this.

rule "433MHz RX"
  when
    Item MQTT_Trigger_Dummy changed
 then

    //  keep upper values, remove lower part only
    switch Integer.parseInt(triggeringItem.state) & 0xfffC000 {
      ...
     // only send lower values to item to update.
      case  150000: Sensor_volt_1.postUpdate(triggeringItem.state & 0x3fff )
      case  130000: Sensor_temp_1.postUpdate(triggeringItem.state & 0x3fff )
      case  110000: Sensor_hum_1.postUpdate(triggeringItem.state & 0x3fff )
      ...
    }
 end

One thing to consider is interference on the radio channel. I’ve had to ditch most of my 433MHz stuff due to local radio noise from things such as weather stations. I used to have 2 RFM69 devices that broadcast every 5 seconds and IIRC only about 65% of the messages got through which was a worry as I was using them to load shed to protect the mains fuse.
I moved to Adafruit Huzzah ESP8266 development boards running ESPEasy connected ito the serial port of the Arduinos in the power monitors and it’s no longer a problem. From memory there was no collision detection on 433MHz, so if any transmissions overlapped nothing got through

Hi rikoshak,
i tried to switch to to the command instead of the state.
Or to be more precise i added a second item and added a second rule, so that i could easier test the behavior.
But i did not get the item to recieve a single command.

I mainly found informations how to configure a item as a switch, so i tried the following as the item config:

Number MQTT_Trigger_Dummy2    "[%.1f]"        {mqtt="<[openhabian:home/433toMQTT:command:*:default]"}

So apperently this is wrong, any idea how to correct it or if you have a example which is not a switch command (on off) i would be thankfull.

For the rule is started like this:

rule "MQTT_Transform2"

when
        Item MQTT_Trigger_Dummy2 received command
then

              logInfo("MQTT", "Transform 2 entered")
              mqtt_safe_state2 = MQTT_Trigger_Dummy2.receivedCommand.toLong
              if (mqtt_safe_state2 < 999900) { // Value is not error

@kevin So far i’m lucky: Here i only see 1 or 2 values not from my sensors a week from a different source. So i’m very confident to say that there are nearly no interferences.

If it works with state it works with command. The only difference is the word “command” instead of “state”.

So take your existing Item and just replace the word state for command

Number MQTT_Trigger_Dummy       "[%.1f]"        {mqtt="<[openhabian:home/433toMQTT:command:default]", expire="60m, 999999"}

Okay the first part seems to work,
the rule gets triggered, but the MyItem2.recievedcommand is not working.
The logfile says ‘receivedCommand’ is not a member of ‘org.eclipse.smarthome.core.library.items.NumberItem’

Could it be, that receivedcommand is only available for say switch items?

Sorry to asking again simple questions, but i really want to try the alternative solution you proposed.

Its just receivedCommand. https://docs.openhab.org/configuration/rules-dsl.html#implicit-variables

To expand on that, the receivedCommand “belongs” to the rule that you refer to it within (which could be triggered by one of several Items or Groups). That’s part of what makes it useful, it isn’t associated with any particular Item.

Do you have access to the code of your 433MHz to MQTT gateway
I suggest that you change the payload to a json format eg:

155521: 15 says first sensorboard, voltage with 5521mV
110459: 11 says first sensorboard, humidity with 45.9%
130618: 13 says first sensorboard, temperature with 21,8 Degree

{ sensor:15, value:5521 }
{ sensor:11, value:45.9 }
{ sensor:13, value:21.8 }
and so on

Then you can subscribe to the topic and do a JSONPATH transform on the inbount mqtt subscription for each item. No rules…

Ok so I just hab a look at the openMQTTGateway wiki and some user reviews in other forums. I knew I saw that before and I couldn’t remember why I didn’t choose that solution.
You could have chosen a better solution. RFLink works very well and publishes information with sensor name and values. I process it though node-red and into OH via MQTT. openMQTT doesn’t review very well with users…

If you want to stick with your receiver the I recommend the following solution: Node-Red!
Get a node subscribing to you 433 gateway
Process the info in a function node and publish out on MQTT to different items on OH
For example the payload 155521 could get transformed by node-red into:
topic: Sensor/Voltage payload:5521

You just need your OH item to subscribe to Sensor/Voltage and off you go…
If you need help with node-red, I am available

No rules in OH. Async processing in node-red. Automatic updating of value in OH.

1 Like

@vzorglub Thank you for your feedback.
So i looked into RFLink and no, i will not buy another microcontroller just to get serial input which then has to be transfered by my esp8266.

The Node Red approach looks promising, but then then i said to myself:
Why not use the advantage of open source sw?
So what i did was take the OpenMQTTGateway and added a simple function in the RFSend Path.
Also added defines for my sensors like minimum value, maxvalue, and sensorinformation and mqtt topic to
transfer the data to.

My new function first checks if the recieved RF Value is one of my sensor values, if so
the value is transformed in one easy line and then send with the corresponding mqtt topic.

If the recieved value was not from one of my sensorboards then the default is the old handling of the message in OpenMQTTGateway style.

As i enabled OTA Updates for my gateway it is a simple compile and push (okay with pw for a little bit of security).

So i got rid of the neccessarity of using the rules, cause even with the great help of rikosak the outcome was that the problem itself is the shortcoming of OpenMQTTGateway in combination with the rule trigger problem.
The recieve command made it a little bit better, but only if i use one or two of my 8 sensor boards. With 8 sensorboards the usage of the rules is complicated, slow and errorprone.
I have to admit that i tried to “heal” the problem at the end of the data chain and not really touched the real issue.

So i say thank you to all the people who helped me in my search for enlightment:
@rikosak, @rossko57, @Josar, @Kevin and last but not least @vzorglub

In the long run i will try to adapt the RFLink to my NodeMcu with sending MQTT Data directly or at least Json conform data, because i like the approach of understand a lot more proctols than only RCSwitch. But this will be a side project. But if i get it working, i will post it here in this forum.

For future reference i will post later my code changes to the OpenMQTTGateway.

So here are the changes:
Inside of ZFGatewayRF.ino

boolean RFtoMQTT(){
.. original code here till
   if (!isAduplicate(MQTTvalue) && MQTTvalue!=0) {// conditions to avoid duplications of RF -->MQTT
   //  after the above if i added the following:
   if (DecideMQTTTopic(MQTTvalue)) return true; // Check for known MQTT Sensor Topic, if not known, do the standard
  .. old code of the function
}

//And my new function looks like this, given here example for one sensor!
boolean DecideMQTTTopic(unsigned long MQTTvalue_raw) {
  boolean result = false; 
  String value = "";
  if((start_sensor1_voltage < MQTTvalue_raw) and (MQTTvalue_raw < end_sensor1_voltage)) {
    // Voltage First Sensor found
     value = String(MQTTvalue_raw - start_sensor1_voltage);
     result = client.publish(topic_Sensor1_volt,(char *)value.c_str()); 
     return result;
  }
  if((start_sensor1_temp < MQTTvalue_raw) and (MQTTvalue_raw < end_sensor1_temp)) {
    // Temperature First Sensor found
     float calc_temp = (MQTTvalue_raw - start_sensor1_temp-sensor1_temp_offset)/10;
     value = String(calc_temp); // 130400 is equal 0.0 degree, and 130000 is equal -40.0 degree
     result = client.publish(topic_Sensor1_temp,(char *)value.c_str()); 
     return result;
  }
  if((start_sensor1_hum < MQTTvalue_raw) and (MQTTvalue_raw < end_sensor1_hum)) {
    // Humidity First Sensor found
     float calc_temp = (MQTTvalue_raw - start_sensor1_hum) / 10;
     value = String(calc_temp);
     result = client.publish(topic_Sensor1_hum,(char *)value.c_str()); 
     return result;
  }
}

//Also inside the config_RF.h i added the following, again example for one sensorboard

/*-------------------MQTT Topics and mapping to RF Sensor ----------------------*/
#define start_sensor1_voltage  150000
#define end_sensor1_voltage    159999
#define topic_Sensor1_volt     "sensor/bath/voltage"

#define start_sensor1_temp     130000
#define end_sensor1_temp       139999
#define sensor1_temp_offset    400
#define topic_Sensor1_temp     "sensor/bath/dht/temperature"

#define start_sensor1_hum      110000
#define end_sensor1_hum        119999
#define topic_Sensor1_hum     "sensor/bath/dht/humidity"

So, for me the adaption was rather easy and through the OTA Update also doable for adding later more sensors.
Just a sidenote: with now 8 sensorboards running i have not a single missed sensorvalue through to fast sending :slight_smile:

After some time the curiosity of NodeRed came up again and i tried the “conversion” via NodeRed and
i have to say: It was even easier. So if someone had no coding background then the NodeRed way will
be much easier for them.
So a Thumbs Up @vzorglub, great advice!