Skip to content

Toilet visits by gender, from one door counter ​

The question: How many people used the Level 4 toilets today, and how many of them were women and how many men?

What it costs: one people counter on the shared corridor door and one motion (PIR) sensor inside one of the two toilets. Nothing is worn, nobody is filmed, and no sensor needs to know who anyone is.

You needExampleWhere it goes
A line-crossing people counterMinew MSR01-BOver the corridor door that leads to both toilets, so everyone going to either side crosses it once
A PIR (motion) sensorMOKO S01PInside the women's toilet, on the ceiling or high on the wall, pointing at the area just inside the door. Not over a cubicle
Optional: a second PIRMOKO S01P, Aqara P1Inside the men's toilet. It turns the estimate into a cross-check (see Make it better)
A gateway that hears bothany Bluetooth gatewayAnywhere in range. The counter's place comes from the counter's own zone, not the gateway's

Why it works ​

The counter knows how many went in, but not where. The PIR knows someone went into the women's side, but not how many. Put together:

  • Everyone = the counter's entries
  • Women = the PIR's visits
  • Men = everyone − women
One counter on the shared corridor, one PIR in the women's toilet A floor plan. The corridor from the lift lobby leads through one door to a small hallway, and from the hallway to the women's toilet on the left and the men's toilet on the right. A line-crossing people counter is mounted over the corridor door, so everyone going to either toilet crosses it once. A PIR is on the ceiling inside the women's toilet, pointing at the area just inside its door. On the right, the arithmetic: everyone is the counter's entries, women is the PIR's visits, men is everyone minus women. Example: 120 entries, 52 women visits, so 68 men. THE FLOORCorridor from the lift lobbypeople walk inToilet hallwayshared by both sidesPeople counterover the door · e.g. MSR01-BWomen's toiletPIRceiling, facing the doorMen's toiletno sensor needed(optional 2nd PIR = a cross-check)THE ARITHMETICEveryonesum of the counter's entries120WomenPIR visits (one per 3 min max)− 52Meneveryone − women68Every error lands on Men:check it is never negative.
The counter knows how many went in; the PIR knows that someone went into the women's side. Men is what is left over, so any miscount of either sensor shows up there.

That subtraction is the whole trick. Any building where several rooms share one entrance can be split the same way: one counter at the shared door, one presence sensor in all but one of the rooms behind it.

1. Put the sensors in the right zones ​

  1. Devices → Devices, register both sensors (or let them auto-register).
  2. Give the counter the zone it guards, for example Toilet Hallway, and the PIR the zone it is in, L4 Female Toilet. A counter with no location writes nothing to the Entry / Exit report; the Devices page shows why.
  3. Name them for what they do: Count Sensor – Hallway to Toilet, PIR – L4 Female Toilet. The names appear in the rule and in the report.
  4. Walk through the door once and wave under the PIR. On the device's View panel the latest reading should show Entries (last report) going to 1 and Occupied going to 1.

2. Make a data table ​

System → Data tables → New table: see Data tables.

FieldValue
NameToilet entries
DescriptionOne row per corridor crossing (counter) and one per women's toilet visit (PIR). Men = entries − women.
Keep rows for365 days, if you want a year-on-year comparison
Columnsevent (text) · gender (text) · entry_total (number)

3. Two rules fill it ​

Rules → Add Rule, twice. Both use the check Sensor reading (any field) (how that works).

Rule A — corridor entry. Watches the counter.

SettingValue
Conditionfield entry Changes (any change)
Repeat at most every30 sec (the shortest)
ActionAdd a row to a data table → Toilet entries: event = hallway, entry_total = {{entry}}

Rule B — women's toilet visit. Watches the PIR.

SettingValue
Conditionfield occupied Becomes (changes to) 1
Repeat at most every3 min (see the PIR fires more than once)
ActionAdd a row to a data table → Toilet entries: event = toilet, gender = female

The counter reports entries since its last report (1 when one person walks in, 0 on the reports in between), so storing the reading and adding the rows up gives the day's total.

Why Changes and not Greater than 0. Changes is an edge: it is checked the moment the reading changes, on every packet. Greater than 0 is a level, and a level rule on one sensor is checked at most once a minute, so a second entry inside that minute is never seen. Changes also fires when the reading drops back to 0, which writes a row with entry_total 0. Those rows add nothing to the sum; leave them. To be sure the figure is right, compare a day with Reports → Entry / Exit for the same counter: the two totals should match.

4. The report ​

Reports → Custom Reports → New Report, Source Table Toilet entries (the builder).

StepSet
Metric 1sum Entry total, call it Everyone
Metric 2count Records, only where Gender equals female, call it Women
Calculated columnMen = metric 1 minus metric 2
Calculated columnWomen % = metric 2 as % of metric 1
Group byDate (a daily table) or Hour (the busy hours)
ChartBar

Save it. It stays in the Custom Reports list: press ▶, pick the dates, and Export CSV for a spreadsheet. (Custom reports cannot be emailed on a schedule yet; System › Schedule Report covers the built-in reports only.)

Reading it honestly ​

These are visits, not people. Someone who goes in twice is two. A cleaner going in and out counts too: if cleaners wear badges, the Toilet Hygiene app already knows when they are inside, and their cleans are listed there.

The counter counts crossings in the "in" direction. Mount it the way round the vendor marks as in, and check on a quiet day that entries and exits come close (Reports → Entry / Exit). A big, steady gap means the counter is mounted backwards, is too high, or the door is often propped open.

The PIR fires more than once per visit ​

A PIR says "occupied" when it sees movement and "empty" after its hold-off time. Someone who sits still in a cubicle for longer than the hold-off makes the PIR go empty and then occupied again when they move, and each of those is a new Becomes 1. In our own office the women's PIR fired three or four times within five minutes for one visit, which made "women" almost as large as "everyone" and "men" close to zero.

Repeat at most every is the fix: one row per 3 minutes at most. The price is that two women arriving within 3 minutes of each other are one row. Pick the interval for your toilet:

ToiletRepeat at most every
Small, one or two cubicles3–5 min
Large, busy at lunch1–2 min, and accept some double counting

Check it the first week. If Men ever comes out negative for an hour, the PIR is overcounting: lengthen the interval.

Men is whatever is left over ​

Every error lands on Men: a missed PIR trigger adds a man, a double trigger takes one away, and a cleaner or a visit to a store room off the same corridor is counted as a man. That is why the next step is worth it.

Make it better ​

A PIR in the men's toilet too. Add Rule C, the same as Rule B with gender = male, watching the men's PIR. Now the report has three figures:

  • Women = rows where gender is female
  • Men = rows where gender is male
  • Not accounted for = everyone − women − men (calculated column twice: Everyone minus Women, then that minus Men, as a second report or in the CSV)

Not accounted for near zero means both PIRs are counting well. A large positive number means a PIR is missing visits; a negative one means one is double counting. Without that check, you would never know.

One rule, any number of toilets. Write the rule on a label (for example Toilet PIR) instead of one device, store gender as text you fix per rule, and add toilet = {{zone_uid}} as a zone column. A new toilet then needs only its sensor labelled.

Feed Toilet Hygiene. Give each toilet its gender on its settings in the Toilet Hygiene app, and the counter's visits drive the dirty score and the Busy-hour auto clean there. This report is the extra layer: who used it, not only how many.

Or ask OAIA. In the assistant, type: "Count women and men for the Level 4 toilets. The hallway counter is 'Count Sensor – Hallway to Toilet' and there is a PIR in the female toilet." It proposes this table, both rules and the report, and builds them when you press Apply. See OAIA.

Questions and problems ​

No hallway rows. Check the counter has a location and zone on the Devices page, and that Rules shows Rule A's Fired count going up. A rule watching a field the sensor does not send never fires: the field is entry, not entry_delta.

Rows, but Entry total is empty. The action wrote {{value}} or a name into the number column on a rule whose first condition is not entry. Use {{entry}}.

The numbers on this report and on Entry / Exit differ by a few. The data table started when the rule was saved; Entry / Exit has counted since the counter was registered. Also, both reports cut days on your organisation's clock, but a rule switched off for a while leaves a gap only in the data table.

Last updated:

Omaya platform documentation