Event access management Power App with external barcode scanning for passes

I had a request from a customer who is running a 10-day event where attendees are permitted in certain areas. There will be in excess of 500 attendees who will all be issued passes that will indicate which area they are permitted in and the pass could include a QR code. Each of the entrances to the different areas will be staffed where passes will be checked. The different areas have capacity limits due to fire, Health & Safety and COVID19 reasons. The event is away from their normal infrastructure so they can’t rely on the normal access control systems we’ve become familiar with. Due to this, the customer felt a more automated approach to access management would be beneficial. They also run similar events throughout the year so any investment would be reusable. While I’d have preferred to break open the microcontroller toolbox and built some #IoT based pass readers but the customer wanted to use the Power Platform and their existing Office 365 investments.

Power App event entry control kiosk. Prototype #1.
Power App event entry control kiosk. Prototype #1.

I started off with my usual design-first approach, sketching out some wireframes and mapping the customer’s requirements back to wireframes and building out personas, user journies and the solution architecture. Part of my wireframes led me to want to verify the barcode capabilities and reassure myself with the approach. I’ve built a number of solutions that have used both the old web barcode scanner and the more modern barcode scanner. While those solutions were a great success I never felt 100% satisfied with the scanner capabilities. I often found it hard to scan barcodes or would have to scan them multiple times increasing the overall time to complete a task. This is where my caution originated particularly creating a contact-free event access management solution to reliably handle such high footfall.

Barcode scanning capability comparrison

One of the advantages of the web barcode scanner control is that it worked on desktop and mobile and it is visible on the screen which made it very obvious to an end-user to scan something. The control is obsolete because of poor performance, and the mobile Barcode scanner control replaces this control.

The mobile barcode scanner control is limited to Android and iOS and requires activation to enable the camera to start scanning.

There are some tricks to activate scanning but this can make editing and use between desktop and mobile hard, particularly if you fall down the trap of activating scanning via the OnVisible action of a screen. At this point, you will lose the ability to edit the screen and instead get a warning about the control only working on Android and iOS.

Error when using the Mobile Barcode Scanner in the browser or editor.

Another option is to use a barcode scanner. This obviously isn’t a native control to Power Apps as it is effectively just a keyboard but there are lots of different styles of barcode scanners out there so these should be considered too.

Hardware barcode scanner comparrision

So after building out a proof of concept using the mobile barcode scanner and after numerous failed attempts to read a QR code, it was obvious this wasn’t going to be a solution I could rely on. So I decided to take a different approach. I knew barcode scanners are seen as a keyboard when connected to a device. So I switched out the mobile barcode scanner control with a simple text field. I was able to process any entered text using the OnChange action with a text input control. I knew this was going to be something I could try with a barcode reader so I decided to buy a couple of units to test with. I could have just used a cheapo barcode reader gun but I wanted something that would be similar to those used in the final access control entry point solution.

One is similar to a checkout barcode reader. It’s a Lenvii E688 wired USB barcode scanner. It has a really helpful LED that is activated with nearby motion. It scans incredibly well and has an adjustable beep to acknowledge each scan. I tested this on my #Windows11 machine and on my iPad and iPhone with the help of one of those USB to appropriate device dongle adapter thingy-mac-things.

The other, an Alacrity Bluetooth barcode scanner is a handheld Bluetooth and wired reader. It too has an LED and has the longest range of the two when reading bar codes. It also comes with a base that allows the reader to be docked for continuous scanning and powered where LED is on continuously scanning. The dock makes for a great pass barcode reader. Another benefit to this barcode reader is that it connects via Bluetooth and therefore allows for the barcode reader to be placed in a more accessible location without being prohibited by cable length. The barcode reader can also be removed from the dock and used in wireless handheld mode should that be needed.

The event access management and entry conrol app

I built a single app that could be used for the different tasks required to manage the attendees and passes for the event. The solution includes attendee registration and allocation of passes at the start of the event, attendee and pass management throughout the event, tools for Fire, Health & Safety marshalls such as capacity tracking and muster point registers and entry control pass scanning. I won’t go into detail on the full solution but will instead concentrate on the entry control features.

Entry control

The key part for the entry control task was that it should be fast, contact-free and act as a companion to support the person staffing the entrance. There is no fancy airlock doors or barrier system preventing someone from entering nor is there likely going to be any rule breakers storming in when not permitted. The entry control part of the app will speed up whether someone is permitted in that area and provides clear visual aids to the entrance staff.

PowerApp Entry Point screen.
Pass permitted to enter.
Pass is not allowed to enter.

Rather than place two devices at each entry point to handle people entering and exiting, I built the app to support it from a single entry point device. If you have scanned in successfully and entered, then scan again when leaving it will acknowledge you have left the area and remove you from the current capacity headcount for that area.

The video demonstrates scanning pass to gain entry and then scanning again when leaving.

The thing with the barcode reader approach is that it requires a text input to place the scanned barcode text into. In a kiosk-based solution, this isn’t great as end-users can “play” so I set about making hiding the control from the screen. First I made the control hidden but that prevented any input from the barcode reader. I then tried changing all the controls colours to match the background. While this made the text input mostly hidden I was still left with a flashing text cursor that I couldn’t hide. Finally, I set the width and height of the control to 0.

Text Input is hidden by setting the width and height as 0.

There is one problem though. You must use SetFocus(TextInput) to place the text cursor into the text box. This resulted in the ability to scan barcodes while not showing anything on the screen.

Use SetFocus to allow scanned barcodes to be entered but the textbox to remain hidden.

I hope this inspires you to think differently when approaching a project that could leverage barcode scanning in Power Apps but also inspires others to use barcode scanning as they create a really efficient solution for capturing data 💖. I’ll try to share some more pictures and updates as the solution progresses, particularly of the implemented access management solution and barcode readers.

Bonus: I ordered a tablet holder which arrived just before I published this post so I thought I could show some early pictures of the reader and tablet together to test how this could work for the event. I think it looks great 🤩

Barcode reader attached to stand with tablet.
Barcode reader and tablet together on stand.

Can you IoT an Airwick air freshener?

This project is one that makes me feel on top of the world but also possibly one of my most craziest IoT projects. I am fascinated with IoT and the point where software interacts with my physical world for example in the simplest form, a sensor programmed to turn a light bulb on when there is motion. I get huge joy from tinkering and exploring how things work but the real satisfaction comes from combining connected sensors, data, automation and machine learning and of course learning myself. This project was no exception.

We’ve all most likely been into a public restroom somewhere and had the automatic air freshener trigger and possibly even make us jump out of our skin when it does. These units typically run on a schedule and spray some kind of air freshener into the room. Some are even a little smarter and trigger when there is motion in the room. Well I have a number of air fresheners like these in the house and sure they’re not necessary but I like them and they smell nice. What I don’t like is how they continue to work when I’m not in the room and even not in the house. This is entirely wasteful and not very smart. And well my house is smart so get with the programme! The other problem is if you’re like me and find it hard to sleep sometimes the noise of them spraying throughout the night is annoying and likely lead to me saying to myself was trying to get to sleep “I wonder if I can make these things smart“. I’ve likely fallen asleep as this stage and forgotten about the crazy idea, but clearly this one time I didn’t, so here I am writing about how to IoT Airwick air fresheners. Let’s consider a smart air freshener and how it would work if it wasn’t triggered by a manually.

Motion. Rooms can be busy so triggering with each motion event would as wasteful as it spraying every 15 minutes now. But we could use motion in combination with when the air freshener last sprayed to ensure it only sprays every 30 minutes for example.

Alarm state. If my house alarm is armed then that is a good sign I’m not home so the air fresheners shouldn’t work. This could also prevent them from working when in night mode but there is, of course, one the exception to that, the bathroom!

Room based triggers. In the living room, if the TV is on or the sofa is occupied then the room is in-use. In the office, if my workstation is unlocked then I am likely working and the room is in-use. If my toilet is flushed and the bath or shower is in-use then that is a great indication the bathroom is in use. And yes, I’ve IoT’ed my toilet! Then there are exceptions like if I’m having a bath I probably don’t want it to be triggered as it would mess with my Zen.

Spray interval. The unit provides some control over the frequency the air freshener sprays but this is limited to 9, 18 and 36-minute intervals. Why these intervals I don’t know but I’m sure Airwick have their reason. It would be useful to replicate this and allow longer intervals between sprays.

Sensors. Throughout my house, I have a large collection of sensors and in a truly connected world, these should be considered too. For example, when the alarm is unarmed after a trip away the air fresheners could be sprayed to create a welcoming smell. If windows are open then I’d rather have the fresh air than the air freshener so don’t have them spray.

Voice. In an inclusive world, voice assistants are increasingly used to perform tasks that ordinarily might have been out of reach for some people.

So considering all of the above I decided to accept the challenge and IoT’ed my air fresheners. But with all these crazy ideas – I wasn’t going to compromise on the aesthetics. The look and feel could not be compromised. Let me walk you through it.


Airwick Air Freshener

The Airwick air freshener device is pretty discrete. It contains a can of the air freshener of your choosing and two AA batteries. Behind the scenes, there is a 3v motor which when powered, powers gearing that creates sufficient force to push down the nozzle on the can of air freshener. Notice the red plunger gear is only two-thirds round. This prevents the gearing from forcing the aerosol can to spray continuously and it runs out of gear. When the motor is no longer powered the gearing reverses from the return force of the nozzle of the can of compressed air freshener.

Gearing and the plunger from inside an Airwick air freshener.

The build

This was quick to build out and I had a working air freshener activated through my NodeMcu in about 15 minutes.

The components connected for testing.

I planned to use a smaller ESP32 dev board but for this prototype, I’ve opted to use the standard board for ease of access. I made a few alterations to the plastic insert in order for me to place the components inside.

All the components to make an IoT Air Freshener packed away inside.

I also planned to use larger batteries but will need to 3d print a housing for that so for this prototype I housed the battery discretely on the back for ease of access and space reasons.

The battery is discretely located on the back for the prototype.


In order to operate my air freshener automatically, I need something that I can programmatically control from Home Assistant. To provide me with the compute for this IoT project I turned to my trusted and favourite ESP32 NodeMcu board flashed with ESPHome. The ESP32 NodeMcu is powered from a battery and is connected to a relay. This relay allows a circuit to open and closes which then activates the motor and gearing inside the air freshener.

Fritzing wiring diagram.
Fritzing wiring diagram

In 10 lines of configuration, I was able to create a switch that operates that relay and that’s it. It is as simple as that. To turn the switch on and off you need an interface. ESPHome provides the ability to do this through a web UI, MQTT or in my case through integration with Home Assistant. In fact, Home Assistant auto-discovers ESPHome devices so the switch I defined in my configuration is immediately available to use.

To preserve the battery I decided to use the deep sleep and MQTT component in ESPHome. This allows me to wake the device, check the state of a MQTT topic. It then either triggers the air freshener or goes back to sleep depending on the state of that MQTT topic and save battery power.

Home Assistant

The brain of my house Home Assistant handles all the integration with ESPHome, other sensors and the home automation logic.

ESPHome air freshener switch integrated with Home Assistant

I won’t go through all of the different automations I have created to work with my new-fangled smart IoT air fresheners but instead, I’ll show you an example that in part is the most applicable for an air freshener. My bathroom air freshener. That particular air freshener is triggered when my IoT toilet is flushed and as automations go is the coolest toilet air freshener automation you will likely to ever see!

For me, the data is as much fun to play with and analyse as the tinkering with all the hardware. To provide me with additional data points that I can study, I added a counter that increments each time the unit is sprayed and a date sensor to store when the air freshener was last replaced.

To preserve battery life the ESP board goes into a deep sleep and wakes every few minutes to check if it needs to trigger the air freshener. This is achieved using an MQTT topic. I created an MQTT switch that is enabled when a binary sensor is on. This switch triggers the air freshener to spray and is reset before ESPHome sends the device to sleep again.

Alexa – beast-mode level five-thousand!!!

We all know there can be those moments when a little fresh air is most welcome. For those situations, I’ll leave you with this.

Alexa, it’s stinky.

This uses a custom component for Home Assistant called alexa_media_player. An Alexa routine is created to listen for that sentence which then set the brightness level of a virtual light created in Home Assistant to a particular level. Then an automation in Home Assistant is triggered. It checks which room Alexa was used in and then activates the air freshener a few times in that room.

One thing I have noticed with Alexa routines is that I’ve always had to keep the wake sentences short and not complex in order for them to be picked up by Alexa. For example, for this I started with “Alexa, it is stinky in here” but her response would be “Sorry, I don’t know that one”. Instead, I simplified the wake sentence to “Alexa, it’s stinky and “Alexa, it smells”. This could be taken a step further and a routine could be used to activate all the air fresheners like “Alexa, freshen up the house” for those moments when you have someone special coming over!

Screenshot of my it is stinky routine in the Alexa app.

Closing thoughts

This really could not have been made any easier and that is down to two great projects Home Assistant and ESPHome. I strongly recommend that if you haven’t explored Home Assistant, ESPHome or ESP32 NodeMcu for tinkering you give them a try.

From this picture, it is impossible to tell that this Airwick air freshener has been IoT’d.

I started by saying I would not compromise on the look and feel of the unit and hopefully the above demonstrates this. There are other benefits to this madness. My friends won’t freak out from the sound of the air freshener spraying nor think I think they smell! The air freshener will last longer and because I converted the batteries I can recharge them. I’ll be able to work out when the spray needs replacing from the data. Oh and I’ll be able to get off to sleep without hearing that clicking noise and troubling myself with such crazy ideas like this. For now at least!

So while I’ve made a few jokes in this article and had lots of fun along the way, the point I want you to take away is that ideas can become reality. Crazy to you might not be crazy to someone else. Let your mind run away and be creative. The growth and learning opportunities are endless.

I 💕 my Home Assistant

Gist extension for VS Code

Gist is a big part of my workflow. I’ve always been on the lookout for a desktop tool. Well, it turns out I was looking in the wrong place. A few days I discovered two VS Code extensions Gist and GitHub Gist Explorer. They both really great extensions and so far I’m really enjoying having Gist at my fingertips in VS Code.

GitHub Gist Explorer

Once you have installed the extension you will need to grab yourself an access token for GitHub – you can get a personal access token by going to settings and then accessing Developer Settings. Make sure you just give the token access to Gists.

GitHub Gist Explorer seems to be my favourite so far. Having the explorer available in the side pain really helps and the command bar paste and save from clipboard features are really great!

How do I use Gist

The majority of my use if private where I have created secret Gists. I have a number of markdown Gists which I have named Gistsmarks which I use as bookmarks to jump to a collection of Gists like boilerplates for my blog articles.

Any code I share on my blog is shared as a Gist. This allows me to embed the code in the article with a nice editor and provides me with version control too. When I started using Gists I painstakingly went through all my posts and converted any previous code blocks into Gists. Oh, and when I reference code I use the highlighted line(s) URL which is a cool trick too.

Highlighting code in a Gist with the URL

I also use Gist to share code and snippets with friends and customers (when it is appropriate of course). I also have runbook like Gists to quickly reference which provide basic lines of PowerShell to perform tasks and run common commands against Microsoft Teams in Office 365 for example. I also have a markdown file for each of my demo environments where I hold information about different personas I have created, areas where I have built out certain functionality and a basic changelog.

While I’m on the topic of VS Code extensions I think I will write another post and share my favourites VS Code extensions.

Hopefully, you got the Gist of things! See what I did there….I’ll get my coat.

Switch between modern SharePoint homepages using PnP PowerShell

This featured in Episode 44 of the SharePoint Dev Weekly podcast.

I’ve been working on a modern intranet project amongst over projects for the last 12-months. This has been more about the transformation of content and business processes, rethinking information architecture and reimagining a modern intranet than it has been about custom development.

I’ve been working on a modern intranet project amongst over projects for the last 12-months. This has been more about the transformation of content and business processes, rethinking information architecture and reimagining a modern intranet than it has been about custom development.

We’ve recently been testing variations in the design of a homepage with different audiences. This side-by-side comparison has allowed end-user feedback, performance and accessibility testing. The same approach has also been useful for previewing and testing the capabilities of new features (like the new Yammer web part). The challenge comes when you need to promote or switch over one of these variations as the new site homepage. The homepage is the page users are directed to when first navigating to a site or clicking on the site logo. It is like as important as the index.html or default.aspx page existence to a website. Note that these variations of the homepage permit testing of content and not site configuration. To test navigation, theme or similar we have separate sites and environments for this purpose.

To solve the problem switching the homepage from an existing page whilst preserving the home.aspx page name I’ve leveraged the SharePoint Pnp cmdlets to create a script that will rename or remove the current homepage (and can remove it through a toggle) and then rename an existing page to make it the new homepage.

Set-SPNewHomePage script demonstration
Demonstration of the Set-SPNewHomePage script in action.

Use my PnP PowerShell script to replace the home.aspx page

Alternative methods

Change the default homepage through SharePoint

Site Owners can use the out-of-the-box make homepage action to make any page the default homepage or welcome page. This is available from the toolbar in the site pages library. But this keeps the page name and means the default page is /sitepages/randompagename.aspx instead of the standard /sitepages/home.aspx that all sites have. From my perspective this is not great. Certainly, intranet-like sites should follow some basic content management principles. Call in a touch on the OCD side but consistently having a standard homepage is one of these for me.

Screenshot of setting a new homepage in the site pages library.
Screenshot of setting a new homepage in the site pages library.

Change the welcome page site property through Site Settings or PowerShell

Previously you could use the classic settings page (typically exposed by the publishing feature) or by browsing to /_layouts/15/AreaWelcomePage.aspx to make changes to the welcome page. This method no longer works and throws an error.

As with the make homepage action describe earlier this changes the default homepage to the use the page name you have provided and means the site won’t be available if users have bookmarked the site with the page name (/sitepages/home.aspx) in the URL.

Screenshot of the welcome page site settings page.
Screenshot of the welcome page site settings page.

What is my point? To this day can I still memory recall core settings pages. With these, you can quickly review or makes changes to settings pages rather than using the UI to navigate to them. This includes those that may no longer be exposed in the UI. Whilst my memory serves me well I don’t recommend this approach as these pages and settings are gradually being replaced with alternatives or removed by the SharePoint and Office 365 engineering team for a reason.

Instead, you can also use Pnp PowerShell to change the site welcome page property. I’ve provided an example script below.

As simple as my script is, it is the approach worth learning the most. I hope you find this article useful and as with all Pnp development effort. Sharing is caring!