Appearance
Occupancy: which number is which
Omaya shows "how many people are here" in several places, and they do not all count the same thing. This page is the one to read before you act on any of them.
The short version: a zone's occupancy comes from whichever sensor actually covers it, and every screen tells you which one it used. If it says tags, the number counts only people carrying something — it is a floor, not a headcount.
The four sources
Every zone reports its count from one of four places. Omaya picks the best one available, in this order.
| Source | What it counts | Where it comes from | Freshness |
|---|---|---|---|
radar | Everyone in the room, carrying something or not | A calibrated position radar (Minew MSR01-A) in that room | Live frames, up to 10 minutes old |
sensor | Everyone the sensor can see | A fixed counting sensor — a radar whose live feed has gone quiet, a ToF counter, or a count pushed in through the API | The newest reading in the last 10 minutes |
doors | Everyone through the door | The net of counters on the space's own doorways, where it says every one of them is counted | Rebuilt every five minutes, reset daily |
tags | Only people carrying a BLE tag or badge | Distinct tags seen in the zone within the window (10 minutes by default) | The selected window |
Read the badge, not just the number
On Zone Occupancy each card carries a small radar, sensor or doors badge when the count includes everyone. No badge means it is a tag count. GET /api/v1/occupancy returns the same thing as a source field, and the assistant says it in words.
Why tags zero does not mean empty
A zone with no radar and no counting sensor can only see people who carry a tag. A meeting room full of visitors with nothing in their pockets reads 0. That is not a bug and it is not a broken sensor — the platform is telling you truthfully that it saw no tagged person.
Anywhere Omaya can tell the difference, it says so: the utilisation report marks tag-counted zones, the seat-planning table has a confidence column, and the AI assistant is instructed to say "no tagged person seen" rather than "empty".
If you need a real headcount in a room, it needs a radar or a counting sensor. No amount of configuration turns a tag count into one.
Right now versus over time
These are two different questions and they use two different stores.
count how full the room is now; ask count_max whether it was ever too small; ask the mean how hard it worked. A room that peaked at eleven and is now empty reports count = 2 and count_max = 11 for that hour — neither figure is wrong, and reading one as the other is the single most common mistake on these reports. Right now — the Zone Occupancy page, the dashboard tile, GET /api/v1/occupancy. The fused number described above, cached for 30 seconds. Poll no faster than that.
Over time — every report, and GET /api/v1/occupancy/{zone}/history. These read the hourly people-count report, where each hour holds four figures:
| Field | Meaning |
|---|---|
count | The last reading of that hour |
count_max | The peak — the most people seen at once during the hour |
count_sum / count_samples | Together, the hour's mean |
Reports use count_max for "how busy did it get" and the mean for "how busy was it typically". count alone is only the final sample and is rarely what you want — if a room emptied at ten to the hour, count is 0 while count_max is 12.
One hour can hold two rows
A zone with both a radar and BLE tags gets one row per source per hour — sensor and gateway. The history endpoint returns both so you can see them apart. Screens that show a single number prefer the sensor row, because it counts everyone.
Capacity, and what "busy" means
Capacity is one number per zone. Set it under Spaces → Zones, or on a meeting room under Apps → Meeting Room — they are the same field and writing either updates the other.
With a capacity set, every zone gets a status:
| Status | Meaning |
|---|---|
empty | Nobody there |
normal | Below half of capacity |
busy | Half of capacity or more |
over | At or above capacity |
Without a capacity, a zone can only ever be empty or normal, the percent-of-capacity columns stay blank, the zone.occupancy.status webhook can never fire busy or over, and seat planning cannot tell you whether a venue is short. Setting capacities is the single highest-value piece of configuration in the platform.
Doorway counts are not the zone's occupancy
A doorway counter (Minew MSR01-B) counts people crossing, and which way. It is a real headcount at a line. What it is not is a count of who is inside the zone, so Omaya shows entries and exits beside the occupancy figure and never as it:
26 in · 51 out today (drift)In-minus-out is a legitimate way to get occupancy, and plenty of buildings run on it — but it only holds when every way in and out is counted, and when the net figure is re-zeroed at a time the space is known to be empty. Neither is something Omaya can check for you, so it does not present the difference as the answer.
Where the smaller direction falls below 60 % of the larger, Omaya flags it drift. That is nearly always partial coverage rather than a faulty sensor: one lab door read 32 in / 94 out in a day because the way people arrived has no counter on it. Entries and exits themselves are honest; their difference, in a space you have not fully instrumented, is not.
When the doors are all counted
A venue can say so: Space → Venue → "Every way in and out of this venue is counted." Omaya then nets its counters and publishes the result as the venue's occupancy with source: doors, ahead of the sum of its zones and behind an external system reporting the whole building.
Two checks still apply, and either one falls the venue back to its zone sum: more people recorded leaving than arriving (impossible with full coverage, so it means an uncounted way in), and counters that have gone quiet during opening hours.
A single room can do it too
A zone has the same tick: Space → Zone → "Every door of this room is counted." It needs one more thing that a whole floor does not, because a door between two rooms is an entrance to one and an exit from the other: each counter says which side faces in, on the device itself. A street or lobby door faces into the room from nowhere counted; an internal door faces into one room and out of its neighbour, and the same crossings then move people between the two instead of inventing them in both.
A counted room that has a counter with no side set is a room whose number is missing that door — so the nightly audit says so rather than letting it drift.
What the audit checks
Coverage is a claim nothing can verify when it is made. What Omaya can do is watch the numbers the claim produces, nightly, and say when they stop being consistent with it:
- A counter in a counted room that was never told which side faces in.
- Two counters mapped to the same pair of spaces — usually one door with two units on it, counting everyone twice.
- A full day with far more arrivals than departures. With every door counted that cannot happen, so there is a way out nobody is watching. This is the half the live check cannot judge, because a morning looks the same.
- A room counted by both its doors and a sensor, disagreeing. One of them is wrong, and having both is free evidence about which.
Findings arrive as configuration alerts on the counter concerned, in the same place as every other device problem.
Venues
A venue's headline number is normally the sum of its zones. If a building-wide source — typically a badge or access-control system pushing to POST /api/v1/occupancy/readings — has reported within the last 10 minutes, that becomes the venue number instead and is marked source: external, because a badge system sees the whole building while the zone sensors only see the rooms they cover.
Timezones
Report buckets are stored in UTC. Every screen converts to your organisation's timezone before showing or grouping them, so "Thursday 10:00" on a report means 10:00 where you are. If you query the API directly you get UTC timestamps and the conversion is yours to do.
Things that surprise people
A radar sees through glass. A meeting room with glass walls will count people in the corridor until its counting area is calibrated. That is what the calibration panel on the device page is for — it tells the radar where the walls are. An uncalibrated radar in a glass room reports numbers that are real detections but the wrong room.
A radar's live feed goes quiet between bursts. An idle radar sends its "nobody here" frames in bursts with gaps of several minutes. The source may flip between radar and sensor during those gaps; the number does not change.
Tag counts are per window. A tag seen once in a 10-minute window counts for the whole window. Widen the window and you count more people who merely passed through.
Zones can overlap in real life but not in the count. A person is counted in one zone at a time — the zone the platform decided they were in. Two zones drawn over the same floor space will not both count them.
Where each screen gets its number
| Screen | Source | Notes |
|---|---|---|
| Dashboard "Right Now" tile | Fused | Same as Zone Occupancy |
| Zone Occupancy | Fused, with source badge | Also shows door traffic and 24-hour history |
| Right Now page | Fused | Says "people · radar" or "sensors" |
| Space Utilisation | Hourly report, sensor row preferred | Occupied = an hour whose peak was 1 or more |
| Room Usage Map | Radar positions only | Rooms without a calibrated radar do not appear |
| Meeting Room app | Radar snapshot | Drives the mini-map and no-show release |
GET /api/v1/occupancy | Fused | Carries source, tags, as_of |
| AI assistant | Fused | Instructed to caveat tag-counted zones |