Making group rules/scripts for FlowerCare/Miflora sensors in OH3

I have several Xiaomi FlowerCare/Miflora sensors. These are small plant sensors that use Bluetooth for communication and I use miflora-mqtt-daemon on external Raspberry pi to send the data via MQTT to my fresh install of OH3.
Recently, the daemon has been updated to support Homie 3 convention (even if the README still says that it supports only v.2.0.5), so the sensors get auto-detected - brilliant.

I am trying to do everything the new OH3 GUI way, so once OH detected the sensors, I created Equipment for each of them, with points/items for all their channels (luminosity, temperature, soil moisture, fertility (actually conductance) and battery level).

Now I want to make a rule that will warn me if some of the plants are getting dry. For this, I believe I need several steps that I am not certain how to do:

  • add minimal soil moisture for each plant (since plants have different requirements)
    • should I add a new Point to the Equipment I created for each sensor’s Thing?
  • group either the sensor Things, the sensor Equipments, or only the “moisture” Points
    • which one is it and how should I do it (in the GUI)?
  • write a rule 'to warn me about dry plants:
    • triggered when a sensor receives an update
    • it should compare the received moisture level with the minimal value and issue a warning if it is below
    • I want one rule for all the sensors (hence the group in the previous step), but do not know how to do it
    • I would prefer the new ECMAScript, but any solution is welcome

“None of the above”
The semantic model tends to get in the way of a clear view of openHAB’s real workings, which revolve around Items. With a few exceptions, you’ll use Items for display and controls in the UI, you’ll use Items for triggering, evaluating, and action in rules.

What you’re looking for here is to Group a bunch of sensors into a logical association of similar functions (nothing to do with physical locations of thesemantic model, or the technical pathways of the Things hierarchy).

And a Group, as it happens, is just another Item. You’d create it outside of the semantic model, and assign other Items as members to it.

Sounds like the right idea, rather like a thermostat you’ll want a closely associated ‘setpoint’ type of value to use as a target or threshold.

Search for design patterns involving Member of Group triggers and evaluation, and Associated Items to find related Items. The notes may not be in the rule language you want to use, but it is the principles that you are interested in.

I have now made it work - it turned out to be easy, once I knew what to do.

I started as planned and made Equipments out of the auto-discovered Things, with all Channels added as Points.
The Points’ names were left at the default, which is <Equipment-name>_<channel>; in particular, the moisture Points are named <Equipment-name>_moisture.
Then I added a new Point <Equipment-name>_moisture_min of type Number to each of the Equipments, to represent the minimal required soil moisture, and set appropriate values for all the plants. (For this, I created a page with sliders and set the values there.)
Next, I added a new Item of type Group and added all the *_moisture_min items into the group.

Finally, I created a rule that triggers when any member of the group changes value, with the following DSL script as the only action:

val sensMoisture = newState as Number

// src: https://community.openhab.org/t/rules-dsl-get-item-from-string-name/48279
val minMoistItem = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name + "_min") as GenericItem
if (minMoistItem.state == NULL) {
  logWarn("plants", minMoistItem.name + " is missing a value")
  return
}
val minMoisture = minMoistItem.state as Number
// -> removing '_moisture' from the calling item gives the equipment name
val plantEquip = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.replace("_moisture", "")) as GenericItem

if (sensMoisture.floatValue < minMoisture.floatValue) {
  logInfo("Notification", "Plant '" + plantEquip.label + "' needs watering!")
}

In my actual implementation, I also send a message to my mobile, by sending a command to a special messaging item, as described in this design pattern.

2 Likes