Or Making Your Office 365 Meeting Rooms Accessible or How Wheelchair Users Can Find The Best Meeting Rooms In Your Organization etc. – there are many different titles I can think of for this blog post. They are all to do with setting useful properties against your meeting rooms so that your users can find the best rooms.
As of the time of writing (updated July 2020), “Outlook Places” service exposes a client-side UX only in Outlook on the web (OWA) with Outlook for Windows and Mac due by end of August 2020. Given Microsoft’s previous behaviour of flighting Exchange Online features for one client initially before rolling them out to other clients, this is likely to hit Outlook mobile etc. at some point after that. Therefore I recommend that you update all your room properties now using the PowerShell cmdlet Set-Place so that your users are able to find meeting rooms and other resources upon the functionality appearing in their client.
The Exchange Online Management Shell cmdlet Set-Place allows you to configure properties such as if the room is accessible for wheelchair users (hence the title of this blog post), or what AV equipment it holds or indeed how many people the room can hold (comfortably!). As this information, especially in a large organization, is probably known by many different people and requires the input of these different users to maintain a master list, this blog post will look at the process of creating this list and then importing it back into Exchange Online when updated.
Creating A Master Room Metadata List
From Exchange Online Management Shell run the following:
Get-Mailbox -RecipientTypeDetails RoomMailbox -ResultSize Unlimited | Get-Place | Export-CSV OrganizationRooms.csv -NoClobber -NoTypeInformation
Open the file, here called OrganizationRooms.csv in Excel. I removed the Type, ResourceDelegates, IsManaged, BookingType and Localities columns and the last five columns (SpaceType, CustomSpaceType, Desks, IsValid, and ObjectState) from this file and then save it as an Excel file to OneDrive for Business or SharePoint Online and shared it with the relevant facilities management and other interested parties (don’t share it as a CSV file, as multiple users cannot edit a csv file in real time). We wait for this information to be updated. If you wish you could lock out cells from being edited such as Identity and maybe DisplayName so that future updating of existing rooms is easy to do.
Specifically we are looking at information such as location (physical street/city address, building name [for campus type organizations], floor label and GeoCoordinates), AV equipment (such as audio, video, display devices and room phone number), accessibility for wheelchair users, and miscellaneous tags (in the form of a comma separated list such as “Conference Room”,Lecture,“Tiered Seating”) that users could use in their room search. There are tools to generate geo-coordinates from addresses that you can find online (including Google Maps) and they are required as latitude;longitude;altitude (where altitude is optional) – for example “-50.9876;10.1234;100” (and if you have a non-English server you need to ensure the format is correct, for example it might need a comma and not a decimal place, such as “-50,9876;10,1234;100” if you had a French language server – which means this value needs quoting as it has commas inside the value).
Updating Room Metadata in Exchange Online
To upload the new data, save the shared Excel spreadsheet as a CSV file again and run the following Exchange Online Management Shell script. Note that the following script works where the object is created in Exchange Online/M365 and not synced from Active Directory (hybrid). For hybrid see the code further down the page:
# Update conference rooms based on info in OrganizationRooms.csv
Connect-ExchangeOnline -UserPrincipalName exoadmin@tenant.onmicrosoft.com
$rooms = Import-Csv -Path OrganizationRooms.csv
foreach ($room in $rooms) {
$currentRoom = $room.identity
Write-Host "Updating"$room.DisplayName
if ($room.street -eq $null) { $room.street = "" }
if ($room.city -eq $null ) { $room.city = "" }
if ($room.state -eq $null ) { $room.state = "" }
if ($room.postalcode -eq $null) { $room.postalcode = "" }
if ($room.CountryOrRegion -eq $null) { $room.CountryOrRegion = "" }
if ($room.GeoCoordinates -like "*;*") { $room.GeoCoordinates = "" } # Looks to see if value is formatted properly, latitude;longitude or latitude;longitude;altitude
if ($room.phone -eq $null) { $room.phone = "" }
if ($room.capacity -eq [int]$room.capacity) { $room.capacity = [int]$room.capacity } # needs to be a number, does not work with null like most of the other values here
if ($room.building -eq $null) { $room.building = "" }
if ($room.Label -eq $null) { $room.label = "" }
if ($room.AudioDeviceName -eq $null) { $room.AudioDeviceName = "" }
if ($room.VideoDeviceName -eq $null) { $room.VideoDeviceName = "" }
if ($room.DisplayDeviceName -eq $null) { $room.DisplayDeviceName = "" }
if ($room.IsWheelChairAccessible -eq $null) { $room.IsWheelChairAccessible = $false }
if ($room.Floor -eq $false) { $room.Floor = "" } # looks to see if contains no number, not null like most of the other values here
if ($room.FloorLabel -eq $null) { $room.FloorLabel = "" }
if ($room.FloorLabel -eq "" -and $room.Floor -ne "") {$room.FloorLabel = $room.Floor} # Copy the Floor number to FloorLabel if this value is blank
if ($room.tags -eq $null) { $room.tags = "" }
$addressParams = @{
Street = $room.street
City = $room.city
State = $room.state
PostalCode = $room.postalcode
CountryOrRegion = $room.CountryOrRegion
}
$geoParams = @{
GeoCoordinates = $room.GeoCoordinates
}
$capacityParams = @{
Capacity = $room.capacity
}
$contactParams = @{
Phone = $room.Phone
Building = $room.building
Label = $room.label
}
$deviceParams = @{
AudioDeviceName = $room.AudioDeviceName
VideoDeviceName = $room.VideoDeviceName
DisplayDeviceName = $room.DisplayDeviceName
}
$accessibilityParams = @{
IsWheelChairAccessible = [bool]$room.IsWheelChairAccessible
}
$floorParams = @{
Floor = $room.Floor
FloorLabel = $room.FloorLabel
Tags = $room.Tags
}
Set-Place $currentRoom @addressParams
if ($room.GeoCoordinates -like "*;*") {
Write-Host " Geo..."
Set-Place $currentRoom @geoParams # Only set Geo if there is a valid value to set. Errors if try to set anything else
}
if ($room.capacity -is [int]) {
Write-Host " Capacity..."
Set-Place $currentRoom @capacityParams # only set capacity if the value is a number or it errors
}
Write-Host " Contact..."
Set-Place $currentRoom @contactParams
Write-Host " Device..."
Set-Place $currentRoom @deviceParams
Write-Host " Accessibility..."
Set-Place $currentRoom @accessibilityParams
Write-Host " Floor..."
Set-Place $currentRoom @floorParams
# Add room to City/Building distribution group (RoomList objects). Need these made beforehand (New-DistributionList "buildingname" -alias "cityname-buildingname" -RoomList)
Add-DistributionGroupMember $room.building -Member $room.identity -ErrorAction SilentlyContinue
}
In the above code I have not included attributes from Get-Place that I cannot write back such as IsManaged, BookingType and Localities – I am interested though in knowing what they are used for as they are undocumented, though Localities is the RoomList that the room belongs to?
There are a few other properties that are useful to set related to this information in the CSV file – for example, as you know the City you could provide the TimeZone as an additional column and set the room mailbox to the correct TimeZone otherwise it defaults to “Pacific Standard Time”. See this post on how to get a list of all the timezone values. This code can be used to import a value per room from the CSV file or update all the rooms to a single value such as “GMT Standard Time” as shown.
Working Times (start and end) can be set here as well. This is important if you have the ScheduleOnlyDuringWorkHours Calendar Processing property set.
$rooms = Import-Csv -Path OrganizationRooms.csv
foreach ($room in $rooms) {
if ($room.timezone -eq $null) { $room.timezone = "GMT Standard Time" }
Set-MailboxRegionalConfiguration $room.identity -TimeZone $room.timezone
Set-MailboxCalendarConfiguration $room.identity -WorkingHoursTimeZone $room.timezone -WorkingHoursStartTime 8:00 -WorkingHoursEndTime 18:00
}
If you get back the error “Encountered an internal server error.” then this is because you are trying to update an AADConnect synced object when your directories are in hybrid mode. The correct script to run is further down this page.
The above code just replaces the current values in Exchange Online with the values in the spreadsheet, so the spreadsheet becomes your master.
Note that values with spaces need to be quoted in the CSV – such as tags and various display names. Also it is worth being aware that with conference bridges and Teams meetings, room “capacity” is not always as important as it might sound – a room with a capacity of 3 people will work fine if everyone is remote! Booking multiple rooms for a single meeting is also planned.
Hybrid
If the room object is synced from on-premises Active Directory then you can still use Set-Place to update the object in the cloud, you just cannot set the City, CountryOrRegion, GeoCoordinates, Phone, PostalCode, State, and Street attributes. The way to set these properties is Set-User and that needed to be run against the source of the object (that is on your management Exchange Server on-premises against Active Directory).
The cmdlet to run instead of the above in Exchange Online uses Set-Place as shown:
$OrganizationRooms = Import-Csv .\OrganizationRooms.csv
ForEach ($Room in $OrganizationRooms) {
[Boolean]$IsWheelChairAccessible = [System.Convert]::ToBoolean($Room.IsWheelChairAccessible)
Set-Place $Room.DisplayName -Capacity $Room.Capacity -Building $Room.Building -Label $Room.Label -AudioDeviceName $Room.AudioDeviceName -VideoDeviceName $Room.VideoDeviceName -DisplayDeviceName $Room.DisplayDeviceName -IsWheelChairAccessible $IsWheelChairAccessible -FloorLabel $Room.FloorLabel -Tags $Room.Tags
}
And the code to run on-premises uses Set-User as shown:
$OrganizationRooms = Import-Csv .\OrganizationRooms.csv
ForEach ($Room in $OrganizationRooms) {
Set-User $Room.Identity -Street $Room.Street -City $Room.City -State $Room.State -PostalCode $Room.PostalCode -CountryOrRegion $Room.CountryOrRegion -GeoCoordinates $Room.GeoCoordinates -Phone $Room.Phone
}
Set-Place can be viewed at https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/set-place?view=exchange-ps
Exchange Server
All rooms and resources that you manage via the steps in the blog post need to be Exchange Online resources. If the mailbox is still on Exchange Server and not moved to Exchange Online in a hybrid scenario, you are not able query and set the information in Get-Place or Set-Place
But that does not mean you cannot get ready for the day that you move those resources (rooms) to Exchange Online. On Exchange Server you can run the following Exchange Management Shell PowerShell and get a csv file with exactly the same columns as above. Get the spreadsheet filled in as mentioned above and then when you move the room to Exchange Online and update Set-Place and Set-User, the room will be found and updated.
Set-ADServerSettings -ViewEntireForest $true
Get-Mailbox -RecipientTypeDetails RoomMailbox -ResultSize Unlimited | Select Identity,DisplayName,Street,City,State,PostalCode,CountryOrRegion,GeoCoordinates,IsManaged,BookingType,ResourceDelegates,Phone,Capacity,Building,Label,AudioDeviceName,VideoDeviceName,DisplayDeviceName,IsWheelChairAccessible,Floor,FloorLabel,Tags,Localities,SpaceType,CustomSpaceType,IsValid,ObjectState | Export-CSV OrganizationRooms-OnPremises.csv -NoClobber -NoTypeInformation
User Room Search Experience
This blog post was originally written in July 2020, but the end-user experience has changed since then. As I updated this in Dec 2023 I see that the “Room Finder” option distinguishes between Buildings and Cities rather than asking the user to choose a “city or room list” and now asks the user to search by building and lists all the cities. The “buildings” are the room lists (special Distribution Groups that contain resource mailboxes) and the “city” is the City property from Get/Set-Place cmdlet.
To view and search for rooms based on these settings you need to wait 24-48 hours from using Set-Place before the property is visible in Outlook, OWA or Teams. You then create a new event in the calendar and click “Search for a room or location>Browse with Room Finder” (in OWA or new Outlook) or “Room Finder” in Outlook or “Add location” in Teams.
The suggested rooms listed are those you have used or attended meetings at recently, but if you click in the “Building” search box (OWA or Outlook) you can either enter a city or room list name (I suggest naming your room lists after buildings) and click the City or Room List name:
This allows the “Filters” option to become available, where you can filter for capacity (rooms larger than) or properties such as audio/video or accessible rooms.
Once you have set the features you need, click Apply and select the room you need for the meeting. Being able to book multiple rooms for a single meeting is also possible – imagine booking a meeting where people attend remotely but the remote location is another office.
Note that as of September 2022, the Outlook/OWA search for “Floor” will instead query the FloorLabel property and not the Floor property. Floor is a number, but FloorLabel a string, so searching for “Ground” or “Penthouse” or 2 or 6 etc. will now be possible when it used to only work for numeric floor numbers. So ensure that FloorLabel is correctly updated on all your rooms.
Call To Action
Its quite easy to generate a list of all the rooms and their current settings (see above) as a spreadsheet. Its more work to update that list, but if you have a list then you can start. Rooms don’t often change their status regarding accessibility etc. but if you start cataloguing your rooms now or add this work to an Exchange Server migration project, then your users will benefit as the functionality appears in the client the users use.
If you don’t update your places metadata, then clients will be unable to successfully find meeting rooms.
Leave a Reply