Mapping actions of the FP1 presence sensor onto OH items

I have set up the Aqara FP1 presence sensor in zigbee2mqtt, which gives me the following MQTT topics:

Presencesensor1
availability = {"state":"online"}
device_temperature = 21
power_outage_count = 8
motion_sensitivity = high
monitoring_mode = undirected
approach_distance = medium
update-state = idle
update-installed_version = 58
update-latest_version = 58
presence_event = leave
linkquality = 116
action = region_1_unoccupied
presence = false

The one I’m interested in here is the action topic. I am wondering what’s the best way of mapping the actions reported there into openHAB. The topic has quite a number of possible values but these are very clearly structured: the first part signifies the region that triggered the action (in the example above region_1_ stands for region 1 (which is certain area in my kitchen). After that comes the action, which can be “enter”, “leave”, “occupied”, “unoccupied”. You get the idea.

Now I want to create one item in OH for each region and the state of that item would then change based on the actions reported via MQTT. The crux is that I need to map multiple items onto a single MQTT topic and I see multiple ways of doing it but can’t see which one is worth embarking on.

Option 1

Create multiple channels in the FP1 thing, i.e. one for each region. I believe channels can be configured to ignore values in the topic that don’t start with a certain string. The values that are not ignored could then be transformed, either with a RegEx or, give that there are only a few possible values, with a simple map.

Option 2

Create only one channel but link it to multiple items instead (and use transformations similar to option 1). The OH UI seems to be somewhat more user-friendly for this option as it provides different mapping options. At the thing level, I’d have to figure out how to do it).

Option 3

Create one channel and link it to one item, which then triggers a rule that updates the state for each region-item. This option seems easiest for me to implement (I’ve worked a lot with rules but almost not at all with transformations). On the other hand, using rules for this feels like a waste of resources and potentially slower than translations.

Option 0 (not really an option)

I believe there are also ways of doing this already at the level of zigbee2mqtt, which I think also allows to split such a topic into multiple topics. OH would then see a different action topic for each region and the setup would be straight forwards, but I’d prefer not to dig into that and keep my logic in OH.

So, is there any reason to avoid any of these options right away? Is there a best one?

option 1 is probably the simplest. You use regex to select only the region that matches that particular channel, e.g. channel name: “region1”, stateTransformation: REGEX:region_1.*, on="region_1_occupied", off="region_1_unoccupied", and so on.

1 Like

yes, I realized that option 2 doesn’t actually work properly because the items linked to the same channel wont retain their previous value and instead switch to NULL as soon as one of the other items is updated, e.g. when the mqtt topic changes to region_1_occupied to region_2_enter the region 2 item will be updated to “enter” but the region 1 item will switch to NULL., which is not what we want. Maybe it can be avoided, but option 1 makes more sense. I simply used REGEX:region_1_(\w+) in the advanced channel configuration like so:

Now I just need to figure out whether there is a way of getting the history of stares when the states are strings or whether I need to add another transformation at the item level to transform the string states to numbers, which will then be available historically in the “Analyze” link…

What are the different possible values? enter/occupied/unoccupied/exit ?

Do you need to differentiate between enter vs occupied and exit vs unoccupied? If not, you could just have it as a contact item, which will be persisted as 0/1 (I think).

The possible values are

“enter”, “leave”, “occupied”, “unoccupied”

For the time being, I need to preserve all because it is rather tricky to calibrate the FP1, so I need to monitor when the different states are triggered.

I’ve created a transform map like this

unoccupied=0
enter=1
occupied=2
leave=3

and set the item as number, but the transformation fails:

2024-01-15 10:18:27.351 [WARN ] [al.profiles.MapTransformationProfile] - Could not transform state 'enter' with function 'FP1_states.map' and format '%s'

Could you paste the channel and item definitions?

I can’t seem to find an explanation of what the default %s state formatted means and what alternatives are available. I suspect it means “string” (which would mean it’s not the source of my error, but I’m not sure.

Channels:

channels:
  - id: FP1_action_raw
    channelTypeUID: mqtt:string
    label: FP1 last action
    description: ""
    configuration:
      stateTopic: zigbee2mqtt/Presencesensor1/action
  - id: FP1_region1
    channelTypeUID: mqtt:string
    label: Kitchen counter FP1
    description: ""
    configuration:
      stateTopic: zigbee2mqtt/Presencesensor1/action
      transformationPattern: REGEX:region_1_(\w+)
  - id: FP1_region2
    channelTypeUID: mqtt:string
    label: Kitchen table FP1
    description: ""
    configuration:
      stateTopic: zigbee2mqtt/Presencesensor1/action
      transformationPattern: REGEX:region_2_(\w+)

And here is one of the items with the attempted transformation:

oh, and here is the item itself:

Can you set this logger to DEBUG: org.openhab.transform.map.internal.profiles.MapTransformationProfile

How do I do that? I assume I need to modify a file in openhab3/userdata/etc/ but which one?

I tried reproducing your case and I had problems too.
What solved it was changing the regex pattern to: region_1_(.*) for some reason, it doesn’t like using \w+

Wow, thanks for all the work!

Unfortunately, changing the regex to region_1_(.*) didn’t solve it for me. It would have surprised me since that transformation (from mqtt-topic value to channel value) works fine. It is the next transformation that fails:

2024-01-15 11:42:26.448 [WARN ] [al.profiles.MapTransformationProfile] - Could not transform state 'enter' with function 'FP1_states.map' and format '%s'

Did you have the file FP1_states.map located in <CONF>/transform/ folder ?

To change the logger config, go to Karaf console, and type

log:set debug org.openhab.transform.map.internal.profiles.MapTransformationProfile

When you’re done, type:

log:set default org.openhab.transform.map.internal.profiles.MapTransformationProfile

EDIT: However, looking at the source code, you probably won’t get much more details because the exception is masked :frowning:

yes, it’s in the same folder as the de.map and en.map files that seem to be included by default. However, while those files show up in the UI, the one I created doesn’t:

Safari-2024-01-15 at 11.57.24@2x

But there is no error that it cant find the file, so I assume that it is reading it w/o problems.

Hmm… pardon me, that \w+ indeed worked. I fell victim of not escaping the backslash (I entered mine in code editor - yours is fine because it’s entered on the web ui)

Anyhow, I can now get mine to work fine with \w+ pattern too.

Have you tried renaming the file (and updating the file reference in the profile settings)?
I am suspecting that the file somehow didn’t get loaded properly by the file watcher (for some reason - if this was the case, then it’s a bug). By renaming, hopefully the file watcher would notice it and load it.

I’m still working on figuring out the console. Had to find out the default password for the openhab user on the docker image (answer is here).

But this sounds more promising:

You mean just rename it to something else?

What file reference in what profile settings?

Edit: I think I found the problem:

>ll
drwxr-xr-x 15 9001 9001 4096 Dec 22  2021 ../
-rw-------  1 root root   41 Jan 15 10:15 FP1_states.map
-rw-------  1 9001 9001   38 Dec 13  2020 de.map
-rw-------  1 9001 9001   38 Dec 13  2020 en.map
-rw-------  1 9001 9001  282 Dec 13  2020 readme.txt

Yes just rename it to e.g. occupancy_states.map

This one - see where it says FP1_states.map - change that to match the new name

Alternatively try restarting openhab - that should reload the map files too.

Bingo!
I wish the error message included the actual problem instead of just sugar coating it with a generic “sorry it didn’t work”.

1 Like

OK, I got it to work. The problem was the file permission:

chowned it to 9001:9001 and now it works.

Thanks for all your help!

Oh, of course. Didn’t realize that was called a profile.

That I don’t understand. It can’t be an alternative to changing the file name in the profile, cause how would it know that the file is now called something else, so do you mean this is an alternative to renaming? In that case, could you explain what exactly your diagnosis was? Are you saying that openhab may simply have missed that this file exists and wouldn’t even find it when provided its name and that restarting OH or renaming the file would trigger it to see that file? I’m asking this because it seems to be an important mechanism to be aware of when troubleshooting OH, i.e. that files need to be somehow picked up by OH in order for it to access them, cause it can’t see them based on the path alone, or something?

Yes I meant alternative to renaming. But given the actual problem, that wouldn’t have helped.

No, I thought that for some reason when you created the file, openhab didn’t “notice” that this file existed, so it wouldn’t load it. And because it wasn’t loaded, it wouldn’t have found it when you’re referring to it in your transformation. This is because I have read in some cases the file watcher failed when symlinks are involved.

As we now know, that wasn’t the case, but it’s kinda related, i.e. openhab couldn’t load the file due to permissions.