In the previous post we created our own custom command in Speech Studio to turn music on and off using the Azure Percept.
In this post, we’ll take this further by delving into the world of Home Automation.
We’ll go through how to connect our command up to an Azure Function via the Command’s WebHook. From the Azure Function, we’ll connect to an Azure IoT Hub. We can then invoke a Direct Method on a Connected Raspberry Pi. This Direct Method will instruct the Raspberry Pi to turn on and off a Desk Lamp using a Relay.
Previously - A Recap of Custom Commands
Custom Commands allow us to create a command set that the Azure Percept can react to. In the previous post, we created a custom command that allowed the Percept to react to a command to turn music on or off.
Custom Commands are primarily comprised of a set of example sentences and a completion operation. In the previous post our completion operation was to simply respond to the user in voice that the music was turned on or off.
We made good use of Parameters so we could have a single command turn the music both on and off again.
What we’ll be doing
The following diagram gives us an overview of the major component parts of the solution:
We have the Azure Percept Audio in the top left. This of course is connected to the Carrier Board which I’ve not shown here.
Azure Percept makes use of the Speech Service to process spoken word detected through the Percept Audio SoM.
Making use of a Webhook, the Speech Service then triggers an Azure Function using HTTP.
This Azure function takes any parameters passed by the Speech Service and then connects to an Azure IoT Hub using a Service Policy.
The IoT Hub has a Device registered to it which in my case is a Raspberry Pi running .NET 5 and C#9.
The Azure Function invokes a Direct Method on the Raspberry Pi through the IoT Hub when it’s triggered, passing in any parameters which have been passed in from the Speech Service.
The Pi then actions the Direct Method and sets a GPIO pin connected to a relay which turns the mains power on to a Desk Lamp.
Creating an Azure Function App
Once a command has been recognised by the Percept we can configure a done action.
In the previous post we configured this “Done” action as a spoken response to the user. However, we can also configure the command to call a webhook before then returning the result of that webhook back to the user.
Before we can configure the webhook however, we need the address for the webhook to call into.
For this we're going to use an Azure Function. Azure Functions are a serverless compute offering which allows us to host and run our code without needing to worry about all the typical architecture around a traditional compute resource like a virtual machine.
On top of this, Azure Functions are super cheap to run, which is great for our use case.
We'll use the Azure Function to receive the Web Endpoint call from our Speech Command, process it and call into the Azure IoT Hub.
Hitting the blue create button, we’re taken to the first page of the Create Function App process:
Here we can choose our Subscription, Resource group and give our Function a unique Name. We can leave the Publish type as “Code”, set the Runtime Stack to “.NET”, the Version to “3.1” and the region to either “West US” or “West Europe” to match that of our Percept Resources.
We can leave the options on the remaining tags as their default, we we can just hit the “Review + Create” button. Check the options you’ve selected before hitting the blue “Create” button:
The Function App will then begin creating and complete some time later:
Once the Function has finished creating, we can navigate to our new Azure Function by hitting the blue “Go to resource” button:
Creating an Azure Function using VS Code
We’ll now use VS Code to create our Azure Function. It's also possible to complete most of these actions in the Portal, but I find that VS Code offers a great experience for creating Azure Functions.
Before we do this, we need to create a directory for our Azure Function to live in, so go ahead and find a nice location for your azure function. We can then open this folder in VS Code, either by right clicking in empty space and clicking “Open with VS Code”, or opening VS Code and opening the folder directly:
You will need to sign in to Azure if you haven’t already.
Once you’re signed in to Azure, all of your resources will be listed in the left pain when you click the Azure Icon:
Next we need to create our Azure Function. We can do that from the VS Code Tool Palette by pressing ctrl+shift+p, then typing Azure Function in the search box:
We can then select the first item in the list “Azure Functions: Create Function“.
We’ll then see the following prompt: “The select folder is not a function project. Create new project?”
We will then be prompted for which language we’d like to use:
We’ll choose “C#”. Next we’ll be asked which .NET runtime we want to use:
We’ll select “.NET Core 3 LTS”. We’ll then have a choice of Trigger for the Function:
We’ll select “HTTP trigger”. We’ll then have a chance to name our Function:
We’ll choose “PerceptTrigger” for our Trigger. Next, we can give our function a namespace:
We’ll use “Percept.Function“.
Finally we can choose the type of Authentication we want to use for our function:
We’ll choose “Function“, which will allow us to pass a token to the function to authenticate.
The Function will then be created:
With that, the basics of our function has been created:
Adding the Azure IoT Hub SDK
Next, as we’re going to be interacting with an IoT Hub, we need to add the IoT Hub SDK.
We can do this from the terminal. Pressing ” ctrl+shift+’ ” (Control + Shift + Apostrophe), will launch the terminal:
We can install the IoT Hub SDK by running:
dotnet add package Microsoft.Azure.Devices
Building the Azure Function Code
Replace the contents of the PerceptTrigger.cs file with the following block of code:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.Devices;
namespace PerceptIoT.Function
{
public static class PerceptTrigger
{
private static ServiceClient serviceClient;
// Connection string for your IoT Hub
private static string connectionString = System.Environment.GetEnvironmentVariable("IotHubConnectionString");
// Device ID for Raspberry Pi
private static string deviceID = System.Environment.GetEnvironmentVariable("DeviceID");
[FunctionName("PerceptTrigger")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation(requestBody);
dynamic data = JsonConvert.DeserializeObject(requestBody);
log.LogInformation($"The State was: {data.state} ");
string responseMessage = $"This HTTP triggered function executed successfully. The State was {data.state}";
serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
await InvokeMethodAsync(Convert.ToString(data.state));
serviceClient.Dispose();
return new OkObjectResult(responseMessage);
}
// Invoke the direct method on the device, passing the payload
private static async Task InvokeMethodAsync(string state)
{
var methodInvocation = new CloudToDeviceMethod("ControlLight")
{
ResponseTimeout = TimeSpan.FromSeconds(30),
};
methodInvocation.SetPayloadJson("{\"state\": \"" + state + "\"}");
// Invoke the direct method asynchronously and get the response from the simulated device.
var response = await serviceClient.InvokeDeviceMethodAsync(deviceID, methodInvocation);
Console.WriteLine($"\nResponse status: {response.Status}, payload:\n\t{response.GetPayloadAsJson()}");
}
}
}
Remember to change the “PerceptTrigger” references in the file to whatever you chose for your Function name.
Next we need to add a local debug setting for our IoT Hub Connection string. Replace the contents of your local.settings.json file with the following:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"IotHubConnectionString": "ENTER YOUR IOT HUB SERVICE LEVEL ACCESS POLICY CONNECTION STRING",
"DeviceID": "ENTER YOUR RASPBERRY PI DEVICE ID"
}
}
Deploying the Function App
We’re now ready to deploy our Function. Using the Azure Tools Extension, in the “Functions” section, if you expand the subscription you created your Function App within, then right click we’ll be given a set of options:
If we select the “Deploy to Function App” option, we can begin deploying our new Azure Function.
We’ll be asked to confirm if we want to deploy the Function App:
Hitting “Deploy” will begin the process of deploying the Function:
Once the process is complete, our new Azure Function will appear in the functions list:
Adding an IoT Device to the IoT Hub
As we’ll be deploying code to a Raspberry Pi which will connect to our IoT Hub, and in turn allow the Azure Function to invoke a Direct Method.
Navigating to the Overview Page of our IoT Hub, we can click the IoT Devices Item:
We’ll then be shown the list of IoT Devices we currently have registered to our IoT Hub:
We can add a new IoT Device by hitting the “+ New” item in the toolbar:
We can name our device “devicecontrol”, leave all the options at their defaults and hit the blue “Save” button:
We’ll then see our new device listed in the Device Registry. You may need to hit the “Refresh” button in the toolbar.
Adding an IoT Hub Shared Access Policy
We now need a way for our Azure Function to connect to our Percept IoT Hub. IoT Hub has the concept of Shared Access Policies to control access to devices and services connecting to and interacting with IoT Hub.
If we return to the overview page of our IoT Hub, we can add a new Shared Access Policy for our Function App to connect to:
We’ll now be shown all of the existing Built-In Shared Access Policies for our IoT Hub:
Our Function will need a policy with “Service Connect” access. We could use the built in “Service” policy, but I prefer to create a new policy for services to use.
If we click the “+ Add shared access policy” in the toolbar, we can add our own policy:
We can name our Shared Access Policy whatever makes sense, I’ve chose “perceptfunctionpolicy” here.
We can then select the “Service Connect” Permission and hit the blue “Add” button to create the Policy.
With the Policy created, it will appear in the list of Shared Access Policies:
If we click on our new Shared Access Policy, we can grab the Primary Connection string we need to allow our Azure Function to connect to the IoT Hub:
Adding a Function App Key
Now that we’ve grabbed our Shared Access Policy, we can add this along with the IoT Device ID of the Raspberry Pi IoT Device we added to the Function Keys for our Azure Function.
Azure Function Function Keys are a way for us to store secrets that our Function can use. This allows us to store our secrets, like IoT Hub Connection Strings, outside of our code, keeping them safe from prying eyes.
Onwards from this, we can also store variables that change the way our code works or configure it to connect with certain parameters.
If we navigate to the overview page of our Function App:
We can navigate to our list of Azure Functions by clicking the “Functions” menu item on the left:
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
We can then click the Function Keys menu item so we can add our required information:
We can add a new Function Key by pressing the “+ New function key” button at the top of the page:
We can add a Function Key for the Service Shared Access Policy Connection String we added earlier and press the blue “OK” button.
We can repeat that for our IoT Device ID:
Our new Function Keys should now be shown in the list:
Finding the Azure Function URL
We’ll be invoking our function using an HTTP trigger. As such, we’ll need the Azure Function URL.
If we return to the overview page of our function:
We can grab the Azure Function URL by hitting the “Get Function URL” button:
We can press the Copy button to the right of the URL.
Keep this URL safe somewhere for now as we’ll need it when we create our Web Endpoint next.
Adding a Web Endpoint to the Custom Command
We can now return to our Custom Command project. The easiest way to do this is via Percept Studio:
We can navigate to Speech and click on the Commands tab:
I’ve gone ahead and created a new Custom Command for this example, but you can absolutely use the PlayMusic-speech project we created in theprevious post.
Clicking on our custom command will take us to the Speech Project:
I’ve created a new Command named “TurnLightOnOff” with the following Example Sentences:
Turn the light {OnOff}
Turn the lights {OnOff}
Turn the lamp {OnOff}
Turn {OnOff} the light
Turn {OnOff} the lights
Turn {OnOff} the lamp
Lights {OnOff}
Lamp {OnOff}
Switch {OnOff} the light
Switch {OnOff} the lights
Switch {OnOff} the lamp
Switch the light {OnOff}
Switch the lights {OnOff}
Switch the lamp {OnOff}
What we need to do now is to create a new “Web endpoint” for our command to call use when it’s executed:
Clicking on the “Web endpoints” menu item on the left will take us to the Web Endpoints page:
We can now click on the “+ New web endpoint” button at the top of the centre panel to add a new endpoint:
We’ll name our Endpoint “LightControl” and hit the blue “Create” button:
We can now paste in our Function URL from the previous step into the “URL” text box. We can cut off the section beginning “?code=…” as we’ll be passing that in as a query parameter.
We need to set the “Method” option to “POST” here, as we’ll be passing the value of our “OnOff” parameter to our Azure Function in the body of the request.
We can now add the authentication code we cut from the end of the Function URL as a query parameter:
We can hit the “+ Add a query Parameter” button at the bottom of the right hand panel:
We enter “code” as the “Key” and we can paste in the Authentication Code in the “Value” box.
Remember to remove the “?code=” part in front of the Authentication code, so it’s just the random collection to letters and numbers.
We can save the parameter with the blue “Save” button.
Using the new Web Endpoint
We can now make use of our new Web Endpoint within our TurnLightOnOff Custom Command.
If we navigate to our TurnLightOnOff Custom command and to the “Done” section:
Make sure to remove any existing actions if you’re reusing anything from a previous post.
We can add an action for our Web Endpoint by hitting the “+ Add an action” button at the bottom of the right hand pane:
Selecting the “Call web endpoint” option will show the Call Web Endpoint dialog:
We can select our new “LightControl” Web Endpoint from the “Endpoint” dropdown.
Next we need to pass in the value for our “OnOff” paramater so that the Azure Function can pass this to the Raspberry Pi via the IoT Hub and a Direct Method. If we replace the “Body content (JSON)” section with the following:
{
"state": "{OnOff}"
}
We now need to feedback a spoken response to the user once the Web Endpoint has been called. If we hit the “On Success (Required)” tab at the top:
We can select the “Send speech response” option from the “Action to execute” dropdown:
We can return the following response:
The light has been turned {OnOff}
We can then repeat this for the “On Failure (Required)” tab:
Where we can enter the following response in the “Simple Response Editor”:
Failed to turn the light {OnOff}
We can now save our Done Action by hitting the blue “Save” button:
Finally, we can hit the “Save” button, followed by the “Train” button and finally the Publish Button:
We can then return to Azure Percept Studio and make sure our custom Command is assigned to our Percept:
Select your Custom Command and hit the “Assign” button in the toolbar:
Select your IoT Hub and Percept Device and hit the blue “Save” button to Deploy to your Device:
Raspberry Pi Code
Next we’ll get the Raspberry Pi set up ready to connect to the IoT Hub and receive the Direct Method Invocation from our Azure Function.
The first thing you’ll need to do is get your Raspberry Pi set up to run .NET 5. I’ve created a post around on how to that:
Once you’ve got the Pi Setup, we can create the project. I’d do this either in your home directory, or if you’ve set up a SAMBA share, then that directory will be best.
We create a new .NET 5 console application with:
dotnet new console -o device_code
cd device_code
We can now add the nuget packages for both GPIO Control and Azure IoT Hub Client:
Next paste the following code over your Program.cs file:
using System;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Device.Gpio;
using Microsoft.Azure.Devices.Client;
namespace device_code
{
class Program
{
static string DeviceConnectionString = "ENTER YOU DEVICE CONNECTION STRING";
static int lightPin = 32;
GpioController controller;
static async Task Main(string[] args)
{
GpioController controller = new GpioController(PinNumberingScheme.Board);
controller.OpenPin(lightPin, PinMode.Output);
controller.Write(lightPin, PinValue.High);
DeviceClient Client = DeviceClient.CreateFromConnectionString(DeviceConnectionString, Microsoft.Azure.Devices.Client.TransportType.Mqtt);
await Client.SetMethodHandlerAsync("ControlLight", (MethodRequest methodRequest, object userContext) => {
Console.WriteLine("IoT Hub invoked the 'ControlLight' method.");
Console.WriteLine("Payload:");
Console.WriteLine(methodRequest.DataAsJson);
dynamic data = JsonConvert.DeserializeObject(methodRequest.DataAsJson);
if (data.state == "on")
{
controller.Write(lightPin, PinValue.Low);
}
else
{
controller.Write(lightPin, PinValue.High);
}
var responseMessage = "{\"response\": \"OK\"}";
return Task.FromResult(new MethodResponse(Encoding.ASCII.GetBytes(responseMessage), 200));
}, null);
while (true)
{
}
}
}
}
We now need to replace the placeholder for the IoT Device Connection String with the one from the device we created earlier.
If we return to the portal, to our IoT Hub IoT Device Registry Page and to the Device Details page for our “devicecontrol” device:
We can copy the Primary Connection string and then paste that into the Program.cs file where we have “ENTER YOU DEVICE CONNECTION STRING”.
Raspberry Pi Circuit
The hardware side of this solution centres around a Raspberry Pi. We make use of a Relay to turn the mains supply to a desk lamp on and off.
DISCLAIMER
As a word of warning. The mains relay part of solution should only be attempted if you are experienced in handling mains voltages, as this can be very dangerous if the correct safety precautions aren’t followed.
Needless to say, I can’t take any responsibility for damage or harm as a result of the following instructions!
With that out of the way, the following is the circuit diagram for the Raspberry Pi, Relay and Lamp:
The Raspberry Pi is connected as follows:
Pi Pin Number
Function
Relay Pin Label
Colour
2
5V
VCC
Red
20
GND
GND
Black
32
Relay Control (GPIO 12)
IN1
Green
I’ve actually enclosed my whole circuit (aside from the Pi), in a patress to keep the mains side sealed away:
I’m using an Elegoo 4 way Relay unit… You can find this at Amazon here: https://amzn.to/2UGX6pT
Testing the System
With all of these parts hooked together, you should be in a position to test turning the light on and off!
First we need to run the software on the Raspberry Pi.
From the directory you created the “device_code” project, run the code with:
dotnet run
Once the code is running, you can try turning the light on and off using your Percept.
The Raspberry Pi terminal window should feedback the instructions it receives:
If everything has gone according to plan, you should now have a working system!
My Plans
I'd love to take this project further and look at controlling more devices around my home. I'd also like to perhaps replace the Raspberry Pi with a far smaller device... Perhaps an ESP32 or a Wilderness Labs Meadow. I could then dot these around the house and control my home with the Percept.
I'd also like to improve the feedback of the system, where currently I'm only sending a one way command, with no feedback from the Pi as to whether it actually carried out the instruction.
My Thoughts
I found the process of adding a Web Endpoint really easy to achieve, and worked really well. To begin with I was a little confused with the speech response to the called Web Endpoint, but it made sense once I'd set it up.
Event though it's super powerful, It would be awesome if Speech Studio could let us perhaps connect directly to other Azure Services, rather than having to roll our wrapper every time. Perhaps the facility to connect directly to IoT Hub maybe?
Obviously, using an Azure Function in the Consumption mode means that it can go to sleep if it's not used. This leads to a fair delay (around 20-30 seconds at times), before the function actually responds to our command hitting the web endpoint... I guess using a different pricing tier would help here. This coupled with the apparent wake delay of the Percept itself can lead to the first wake up taking some time to complete.
After that though, it works really well, with only a very slight delay between saying the command at the light turning on or off.
Overall, the whole platform works really well, and with the addition of Web Endpoints and Azure Functions, we're able to reach out to any part of Azure we like.
Updated Jul 08, 2021
Version 1.0
No CommentsBe the first to comment
Share
"}},"component({\"componentId\":\"custom.widget.MicrosoftFooter\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[\"board:IoTBlog\",\"message:2528048\"],\"name\":\"BlogMessagePage\",\"props\":{},\"url\":\"https://techcommunity.microsoft.com\"}}})":{"__typename":"ComponentRenderResult","html":""}},"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageCoverImage\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageCoverImage-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeTitle\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeTitle-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTimeToRead\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTimeToRead-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserRank\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserRank-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageCustomFields\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageCustomFields-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRevision\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRevision-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/QueryHandler\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageReplyButton\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageReplyButton-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageAuthorBio\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/ranks/UserRankLabel\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserRegistrationDate\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserRegistrationDate-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeDescription\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"components/tags/TagView/TagViewChip\"]})":[{"__ref":"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1737115705000"}],"cachedText({\"lastModified\":\"1737115705000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1737115705000"}]},"CachedAsset:pages-1737540114235":{"__typename":"CachedAsset","id":"pages-1737540114235","value":[{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"UserBlogPermissions.Page","type":"COMMUNITY","urlPath":"/c/user-blog-permissions/page","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730142000000,"localOverride":null,"page":{"id":"AllEvents","type":"CUSTOM","urlPath":"/Events","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730142000000,"localOverride":null,"page":{"id":"CommunityHub.Page","type":"CUSTOM","urlPath":"/Directory","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730142000000,"localOverride":null,"page":{"id":"AllBlogs.Page","type":"CUSTOM","urlPath":"/blogs","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737540114235,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Deleted","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"MMM dd yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":"en","possibleValues":["en-US"]}},"deleted":false},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"Category:category:IoT":{"__typename":"Category","id":"category:IoT","entityType":"CATEGORY","displayId":"IoT","nodeType":"category","depth":3,"title":"Internet of Things (IoT)","shortTitle":"Internet of Things (IoT)","parent":{"__ref":"Category:category:solutions"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","displayId":"top","nodeType":"category","depth":0,"title":"Top","entityType":"CATEGORY","shortTitle":"Top"},"Category:category:communities":{"__typename":"Category","id":"category:communities","displayId":"communities","nodeType":"category","depth":1,"parent":{"__ref":"Category:category:top"},"title":"Communities","entityType":"CATEGORY","shortTitle":"Communities"},"Category:category:solutions":{"__typename":"Category","id":"category:solutions","displayId":"solutions","nodeType":"category","depth":2,"parent":{"__ref":"Category:category:communities"},"title":"Topics","entityType":"CATEGORY","shortTitle":"Topics"},"Blog:board:IoTBlog":{"__typename":"Blog","id":"board:IoTBlog","entityType":"BLOG","displayId":"IoTBlog","nodeType":"board","depth":4,"conversationStyle":"BLOG","title":"Internet of Things Blog","description":"","avatar":null,"profileSettings":{"__typename":"ProfileSettings","language":null},"parent":{"__ref":"Category:category:IoT"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:gxcuf89792"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:communities"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:solutions"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:IoT"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"boardPolicies":{"__typename":"BoardPolicies","canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}}},"shortTitle":"Internet of Things Blog","repliesProperties":{"__typename":"RepliesProperties","sortOrder":"REVERSE_PUBLISH_TIME","repliesFormat":"threaded"},"tagProperties":{"__typename":"TagNodeProperties","tagsEnabled":{"__typename":"PolicyResult","failureReason":null}},"requireTags":true,"tagType":"PRESET_ONLY"},"Rank:rank:5":{"__typename":"Rank","id":"rank:5","position":6,"name":"MVP","color":"0069D4","icon":null,"rankStyle":"FILLED"},"User:user:94921":{"__typename":"User","id":"user:94921","uid":94921,"login":"Peter Gallagher","deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS05NDkyMS0yMTY5ODFpQUIxNUI0RkE1QUI5NEQ2RA"},"rank":{"__ref":"Rank:rank:5"},"email":"","messagesCount":8,"biography":null,"topicsCount":5,"kudosReceivedCount":12,"kudosGivenCount":11,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":null,"registrationTime":"2017-11-14T08:47:31.287-08:00","confirmEmailStatus":null},"followersCount":null,"solutionsCount":0},"BlogTopicMessage:message:2528048":{"__typename":"BlogTopicMessage","uid":2528048,"subject":"Azure Percept Audio - Home Automation with Azure Functions, Azure IoT Hub and Raspberry Pi","id":"message:2528048","revisionNum":5,"repliesCount":0,"author":{"__ref":"User:user:94921"},"depth":0,"hasGivenKudo":false,"board":{"__ref":"Blog:board:IoTBlog"},"conversation":{"__ref":"Conversation:conversation:2528048"},"messagePolicies":{"__typename":"MessagePolicies","canPublishArticleOnEdit":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","args":[]}},"canModerateSpamMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","args":[]}}},"contentWorkflow":{"__typename":"ContentWorkflow","state":"PUBLISH","scheduledPublishTime":null,"scheduledTimezone":null,"userContext":{"__typename":"MessageWorkflowContext","canSubmitForReview":null,"canEdit":false,"canRecall":null,"canSubmitForPublication":null,"canReturnToAuthor":null,"canPublish":null,"canReturnToReview":null,"canSchedule":null},"shortScheduledTimezone":null},"readOnly":false,"editFrozen":false,"moderationData":{"__ref":"ModerationData:moderation_data:2528048"},"teaser":"
\n
\n
Pete shows us how we can control a desk lamp from an Azure Percept DK
","body":"
In the previous post we created our own custom command in Speech Studio to turn music on and off using the Azure Percept.
\n
\n\n
\n
In this post, we’ll take this further by delving into the world of Home Automation.
\n
\n
We’ll go through how to connect our command up to an Azure Function via the Command’s WebHook. From the Azure Function, we’ll connect to an Azure IoT Hub. We can then invoke a Direct Method on a Connected Raspberry Pi. This Direct Method will instruct the Raspberry Pi to turn on and off a Desk Lamp using a Relay.
\n
\n
Previously - A Recap of Custom Commands
\n
\n
Custom Commands allow us to create a command set that the Azure Percept can react to. In the previous post, we created a custom command that allowed the Percept to react to a command to turn music on or off.
\n
\n
Custom Commands are primarily comprised of a set of example sentences and a completion operation. In the previous post our completion operation was to simply respond to the user in voice that the music was turned on or off.
\n
\n
We made good use of Parameters so we could have a single command turn the music both on and off again.
\n
\n
What we’ll be doing
\n
\n
The following diagram gives us an overview of the major component parts of the solution:
\n
\n
\n
\n
We have the Azure Percept Audio in the top left. This of course is connected to the Carrier Board which I’ve not shown here.
\n
\n
Azure Percept makes use of the Speech Service to process spoken word detected through the Percept Audio SoM.
\n
\n
Making use of a Webhook, the Speech Service then triggers an Azure Function using HTTP.
\n
\n
This Azure function takes any parameters passed by the Speech Service and then connects to an Azure IoT Hub using a Service Policy.
\n
\n
The IoT Hub has a Device registered to it which in my case is a Raspberry Pi running .NET 5 and C#9.
\n
\n
The Azure Function invokes a Direct Method on the Raspberry Pi through the IoT Hub when it’s triggered, passing in any parameters which have been passed in from the Speech Service.
\n
\n
The Pi then actions the Direct Method and sets a GPIO pin connected to a relay which turns the mains power on to a Desk Lamp.
\n
\n
Creating an Azure Function App
\n
\n
Once a command has been recognised by the Percept we can configure a done action.
\n
\n
In the previous post we configured this “Done” action as a spoken response to the user. However, we can also configure the command to call a webhook before then returning the result of that webhook back to the user.
\n
\n
Before we can configure the webhook however, we need the address for the webhook to call into.
\n
\n
For this we're going to use an Azure Function. Azure Functions are a serverless compute offering which allows us to host and run our code without needing to worry about all the typical architecture around a traditional compute resource like a virtual machine.
\n
\n
On top of this, Azure Functions are super cheap to run, which is great for our use case.
\n
\n
We'll use the Azure Function to receive the Web Endpoint call from our Speech Command, process it and call into the Azure IoT Hub.
Hitting the blue create button, we’re taken to the first page of the Create Function App process:
\n
\n
\n
\n
\n
Here we can choose our Subscription, Resource group and give our Function a unique Name. We can leave the Publish type as “Code”, set the Runtime Stack to “.NET”, the Version to “3.1” and the region to either “West US” or “West Europe” to match that of our Percept Resources.
\n
\n
We can leave the options on the remaining tags as their default, we we can just hit the “Review + Create” button. Check the options you’ve selected before hitting the blue “Create” button:
\n
\n
\n
\n
The Function App will then begin creating and complete some time later:
\n
\n
\n
\n
Once the Function has finished creating, we can navigate to our new Azure Function by hitting the blue “Go to resource” button:
\n
\n
\n
\n
Creating an Azure Function using VS Code
\n
\n
We’ll now use VS Code to create our Azure Function. It's also possible to complete most of these actions in the Portal, but I find that VS Code offers a great experience for creating Azure Functions.
\n
\n
Before we do this, we need to create a directory for our Azure Function to live in, so go ahead and find a nice location for your azure function. We can then open this folder in VS Code, either by right clicking in empty space and clicking “Open with VS Code”, or opening VS Code and opening the folder directly:
You will need to sign in to Azure if you haven’t already.
\n
\n
Once you’re signed in to Azure, all of your resources will be listed in the left pain when you click the Azure Icon:
\n
\n
\n
\n
Next we need to create our Azure Function. We can do that from the VS Code Tool Palette by pressing ctrl+shift+p, then typing Azure Function in the search box:
\n
\n
\n
\n
We can then select the first item in the list “Azure Functions: Create Function“.
\n
\n
We’ll then see the following prompt: “The select folder is not a function project. Create new project?”
\n
\n
\n
\n
We will then be prompted for which language we’d like to use:
\n
\n
\n
\n
We’ll choose “C#”. Next we’ll be asked which .NET runtime we want to use:
\n
\n
\n
\n
We’ll select “.NET Core 3 LTS”. We’ll then have a choice of Trigger for the Function:
\n
\n
\n
\n
We’ll select “HTTP trigger”. We’ll then have a chance to name our Function:
\n
\n
\n
\n
We’ll choose “PerceptTrigger” for our Trigger. Next, we can give our function a namespace:
\n
\n
\n
\n
We’ll use “Percept.Function“.
\n
\n
Finally we can choose the type of Authentication we want to use for our function:
\n
\n
\n
\n
We’ll choose “Function“, which will allow us to pass a token to the function to authenticate.
\n
\n
The Function will then be created:
\n
\n
\n
\n
With that, the basics of our function has been created:
\n
\n
\n
\n
Adding the Azure IoT Hub SDK
\n
\n
Next, as we’re going to be interacting with an IoT Hub, we need to add the IoT Hub SDK.
\n
\n
We can do this from the terminal. Pressing ” ctrl+shift+’ ” (Control + Shift + Apostrophe), will launch the terminal:
\n
\n
\n
\n
We can install the IoT Hub SDK by running:
\n
\n
dotnet add package Microsoft.Azure.Devices
\n
\n
\n
\n
\n
Building the Azure Function Code
\n
\n
Replace the contents of the PerceptTrigger.cs file with the following block of code:
\n
\n
using System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.WebJobs;\nusing Microsoft.Azure.WebJobs.Extensions.Http;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Newtonsoft.Json;\nusing Microsoft.Azure.Devices;\n\nnamespace PerceptIoT.Function\n{\n public static class PerceptTrigger\n {\n\n private static ServiceClient serviceClient;\n \n // Connection string for your IoT Hub\n private static string connectionString = System.Environment.GetEnvironmentVariable(\"IotHubConnectionString\");\n // Device ID for Raspberry Pi\n private static string deviceID = System.Environment.GetEnvironmentVariable(\"DeviceID\");\n\n [FunctionName(\"PerceptTrigger\")]\n public static async Task<IActionResult> Run(\n [HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\", Route = null)] HttpRequest req,\n ILogger log)\n {\n log.LogInformation(\"C# HTTP trigger function processed a request.\");\n\n string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n log.LogInformation(requestBody);\n\n dynamic data = JsonConvert.DeserializeObject(requestBody);\n\n log.LogInformation($\"The State was: {data.state} \");\n \n string responseMessage = $\"This HTTP triggered function executed successfully. The State was {data.state}\";\n\n serviceClient = ServiceClient.CreateFromConnectionString(connectionString);\n\n await InvokeMethodAsync(Convert.ToString(data.state));\n\n serviceClient.Dispose();\n\n return new OkObjectResult(responseMessage);\n }\n\n // Invoke the direct method on the device, passing the payload\n private static async Task InvokeMethodAsync(string state)\n {\n var methodInvocation = new CloudToDeviceMethod(\"ControlLight\")\n {\n ResponseTimeout = TimeSpan.FromSeconds(30),\n };\n\n methodInvocation.SetPayloadJson(\"{\\\"state\\\": \\\"\" + state + \"\\\"}\");\n\n // Invoke the direct method asynchronously and get the response from the simulated device.\n var response = await serviceClient.InvokeDeviceMethodAsync(deviceID, methodInvocation);\n\n Console.WriteLine($\"\\nResponse status: {response.Status}, payload:\\n\\t{response.GetPayloadAsJson()}\");\n }\n }\n}
\n
\n
\n
Remember to change the “PerceptTrigger” references in the file to whatever you chose for your Function name.
\n
\n
Next we need to add a local debug setting for our IoT Hub Connection string. Replace the contents of your local.settings.json file with the following:
\n
\n
{\n \"IsEncrypted\": false,\n \"Values\": {\n \"AzureWebJobsStorage\": \"\",\n \"FUNCTIONS_WORKER_RUNTIME\": \"dotnet\",\n \"IotHubConnectionString\": \"ENTER YOUR IOT HUB SERVICE LEVEL ACCESS POLICY CONNECTION STRING\",\n \"DeviceID\": \"ENTER YOUR RASPBERRY PI DEVICE ID\"\n }\n}
\n
\n
\n
Deploying the Function App
\n
\n
We’re now ready to deploy our Function. Using the Azure Tools Extension, in the “Functions” section, if you expand the subscription you created your Function App within, then right click we’ll be given a set of options:
\n
\n
\n
\n
If we select the “Deploy to Function App” option, we can begin deploying our new Azure Function.
\n
\n
We’ll be asked to confirm if we want to deploy the Function App:
\n
\n
\n
Hitting “Deploy” will begin the process of deploying the Function:
\n
\n
\n
\n
Once the process is complete, our new Azure Function will appear in the functions list:
\n
\n
\n
\n
\n
Adding an IoT Device to the IoT Hub
\n
\n
As we’ll be deploying code to a Raspberry Pi which will connect to our IoT Hub, and in turn allow the Azure Function to invoke a Direct Method.
Navigating to the Overview Page of our IoT Hub, we can click the IoT Devices Item:
\n
\n
\n
\n
We’ll then be shown the list of IoT Devices we currently have registered to our IoT Hub:
\n
\n
\n
\n
We can add a new IoT Device by hitting the “+ New” item in the toolbar:
\n
\n
\n
\n
We can name our device “devicecontrol”, leave all the options at their defaults and hit the blue “Save” button:
\n
\n
\n
\n
We’ll then see our new device listed in the Device Registry. You may need to hit the “Refresh” button in the toolbar.
\n
\n
Adding an IoT Hub Shared Access Policy
\n
\n
We now need a way for our Azure Function to connect to our Percept IoT Hub. IoT Hub has the concept of Shared Access Policies to control access to devices and services connecting to and interacting with IoT Hub.
\n
\n
If we return to the overview page of our IoT Hub, we can add a new Shared Access Policy for our Function App to connect to:
\n
\n
\n
\n
We’ll now be shown all of the existing Built-In Shared Access Policies for our IoT Hub:
\n
\n
\n
\n
Our Function will need a policy with “Service Connect” access. We could use the built in “Service” policy, but I prefer to create a new policy for services to use.
\n
\n
If we click the “+ Add shared access policy” in the toolbar, we can add our own policy:
\n
\n
\n
\n
We can name our Shared Access Policy whatever makes sense, I’ve chose “perceptfunctionpolicy” here.
\n
\n
We can then select the “Service Connect” Permission and hit the blue “Add” button to create the Policy.
\n
\n
With the Policy created, it will appear in the list of Shared Access Policies:
\n
\n
\n
\n
If we click on our new Shared Access Policy, we can grab the Primary Connection string we need to allow our Azure Function to connect to the IoT Hub:
\n
\n
\n
\n
Adding a Function App Key
\n
\n
Now that we’ve grabbed our Shared Access Policy, we can add this along with the IoT Device ID of the Raspberry Pi IoT Device we added to the Function Keys for our Azure Function.
\n
\n
Azure Function Function Keys are a way for us to store secrets that our Function can use. This allows us to store our secrets, like IoT Hub Connection Strings, outside of our code, keeping them safe from prying eyes.
\n
\n
Onwards from this, we can also store variables that change the way our code works or configure it to connect with certain parameters.
\n
\n
If we navigate to the overview page of our Function App:
\n
\n
\n
\n
We can navigate to our list of Azure Functions by clicking the “Functions” menu item on the left:
\n
\n
\n
\n
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
\n
\n
\n
\n
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
\n
\n
\n
\n
We can then click the Function Keys menu item so we can add our required information:
\n
\n
\n
\n
We can add a new Function Key by pressing the “+ New function key” button at the top of the page:
\n
\n
\n
\n
We can add a Function Key for the Service Shared Access Policy Connection String we added earlier and press the blue “OK” button.
\n
\n
We can repeat that for our IoT Device ID:
\n
\n
\n
\n
Our new Function Keys should now be shown in the list:
\n
\n
\n
\n
Finding the Azure Function URL
\n
\n
We’ll be invoking our function using an HTTP trigger. As such, we’ll need the Azure Function URL.
\n
\n
If we return to the overview page of our function:
\n
\n
\n
\n
We can grab the Azure Function URL by hitting the “Get Function URL” button:
\n
\n
\n
\n
We can press the Copy button to the right of the URL.
\n
\n
Keep this URL safe somewhere for now as we’ll need it when we create our Web Endpoint next.
\n
\n
Adding a Web Endpoint to the Custom Command
\n
\n
We can now return to our Custom Command project. The easiest way to do this is via Percept Studio:
We can navigate to Speech and click on the Commands tab:
\n
\n
\n
I’ve gone ahead and created a new Custom Command for this example, but you can absolutely use the PlayMusic-speech project we created in theprevious post.
\n
\n
Clicking on our custom command will take us to the Speech Project:
\n
\n
\n
\n
\n
\n
I’ve created a new Command named “TurnLightOnOff” with the following Example Sentences:
\n
\n
Turn the light {OnOff}\nTurn the lights {OnOff}\nTurn the lamp {OnOff}\nTurn {OnOff} the light\nTurn {OnOff} the lights\nTurn {OnOff} the lamp\nLights {OnOff}\nLamp {OnOff}\nSwitch {OnOff} the light\nSwitch {OnOff} the lights\nSwitch {OnOff} the lamp\nSwitch the light {OnOff}\nSwitch the lights {OnOff}\nSwitch the lamp {OnOff}
\n
\n
\n
What we need to do now is to create a new “Web endpoint” for our command to call use when it’s executed:
\n
\n
\n
\n
\n
Clicking on the “Web endpoints” menu item on the left will take us to the Web Endpoints page:
\n
\n
\n
\n
\n
We can now click on the “+ New web endpoint” button at the top of the centre panel to add a new endpoint:
\n
\n
\n
\nWe’ll name our Endpoint “LightControl” and hit the blue “Create” button:
\n
\n
\n
\nWe can now paste in our Function URL from the previous step into the “URL” text box. We can cut off the section beginning “?code=…” as we’ll be passing that in as a query parameter.
\n
\n
\n
\n
\n
\n
We need to set the “Method” option to “POST” here, as we’ll be passing the value of our “OnOff” parameter to our Azure Function in the body of the request.
\n
\n
We can now add the authentication code we cut from the end of the Function URL as a query parameter:
\n
\n
\n
\n
\n
We can hit the “+ Add a query Parameter” button at the bottom of the right hand panel:
\n
\n
\n
\n
\n
\n
We enter “code” as the “Key” and we can paste in the Authentication Code in the “Value” box.
\n
\n
Remember to remove the “?code=” part in front of the Authentication code, so it’s just the random collection to letters and numbers.
\n
\n
We can save the parameter with the blue “Save” button.
\n
\n
\n
\n
Using the new Web Endpoint
\n
\n
\n
\n
We can now make use of our new Web Endpoint within our TurnLightOnOff Custom Command.
\n
\n
If we navigate to our TurnLightOnOff Custom command and to the “Done” section:
\n
\n
\n
\n
Make sure to remove any existing actions if you’re reusing anything from a previous post.
\n
\n
We can add an action for our Web Endpoint by hitting the “+ Add an action” button at the bottom of the right hand pane:
\n
\n
\n
\n
Selecting the “Call web endpoint” option will show the Call Web Endpoint dialog:
\n
\n
\n
\n
We can select our new “LightControl” Web Endpoint from the “Endpoint” dropdown.
\n
\n
Next we need to pass in the value for our “OnOff” paramater so that the Azure Function can pass this to the Raspberry Pi via the IoT Hub and a Direct Method. If we replace the “Body content (JSON)” section with the following:
\n
{\n \"state\": \"{OnOff}\"\n}
\n
\n
\n
We now need to feedback a spoken response to the user once the Web Endpoint has been called. If we hit the “On Success (Required)” tab at the top:
\n
\n
\n
\n
We can select the “Send speech response” option from the “Action to execute” dropdown:
\n
\n
\n
\n
We can return the following response:
\n
The light has been turned {OnOff}
\n
\n
We can then repeat this for the “On Failure (Required)” tab:
\n
\n
\n
\n
Where we can enter the following response in the “Simple Response Editor”:
\n
Failed to turn the light {OnOff}
\n
\n
We can now save our Done Action by hitting the blue “Save” button:
\n
\n
\n
Finally, we can hit the “Save” button, followed by the “Train” button and finally the Publish Button:
\n
\n
\n
We can then return to Azure Percept Studio and make sure our custom Command is assigned to our Percept:
\n
\n
\n
\n
Select your Custom Command and hit the “Assign” button in the toolbar:
\n
\n\n
\n
\n
Select your IoT Hub and Percept Device and hit the blue “Save” button to Deploy to your Device:
\n
\n
\n
\n
Raspberry Pi Code
\n
\n
Next we’ll get the Raspberry Pi set up ready to connect to the IoT Hub and receive the Direct Method Invocation from our Azure Function.
\n
\n
The first thing you’ll need to do is get your Raspberry Pi set up to run .NET 5. I’ve created a post around on how to that:
Once you’ve got the Pi Setup, we can create the project. I’d do this either in your home directory, or if you’ve set up a SAMBA share, then that directory will be best.
\n
\n
We create a new .NET 5 console application with:
\n
\n
dotnet new console -o device_code\ncd device_code
\n
\n
\n
We can now add the nuget packages for both GPIO Control and Azure IoT Hub Client:
We now need to replace the placeholder for the IoT Device Connection String with the one from the device we created earlier.
\n
\n
If we return to the portal, to our IoT Hub IoT Device Registry Page and to the Device Details page for our “devicecontrol” device:
\n
\n
\n
\n
We can copy the Primary Connection string and then paste that into the Program.cs file where we have “ENTER YOU DEVICE CONNECTION STRING”.
\n
\n
Raspberry Pi Circuit
\n
\n
The hardware side of this solution centres around a Raspberry Pi. We make use of a Relay to turn the mains supply to a desk lamp on and off.
\n
\n
DISCLAIMER
As a word of warning. The mains relay part of solution should only be attempted if you are experienced in handling mains voltages, as this can be very dangerous if the correct safety precautions aren’t followed.
Needless to say, I can’t take any responsibility for damage or harm as a result of the following instructions!
\n
\n
\n
With that out of the way, the following is the circuit diagram for the Raspberry Pi, Relay and Lamp:
\n
\n
\n
\n
The Raspberry Pi is connected as follows:
\n
\n
\n\n
\n
Pi Pin Number
\n
Function
\n
Relay Pin Label
\n
Colour
\n
\n
\n
2
\n
5V
\n
VCC
\n
Red
\n
\n
\n
20
\n
GND
\n
GND
\n
Black
\n
\n
\n
32
\n
Relay Control (GPIO 12)
\n
IN1
\n
Green
\n
\n\n
\n
\n
I’ve actually enclosed my whole circuit (aside from the Pi), in a patress to keep the mains side sealed away:
\n
\n
\n
\n
I’m using an Elegoo 4 way Relay unit… You can find this at Amazon here: https://amzn.to/2UGX6pT
\n
\n
Testing the System
\n
\n
With all of these parts hooked together, you should be in a position to test turning the light on and off!
\n
First we need to run the software on the Raspberry Pi.
\n
\n
From the directory you created the “device_code” project, run the code with:
\n
\n
dotnet run
\n
\n
\n
Once the code is running, you can try turning the light on and off using your Percept.
\n
\n
The Raspberry Pi terminal window should feedback the instructions it receives:
\n
\n
\n
\n
If everything has gone according to plan, you should now have a working system!
\n
\n\n
\n
My Plans
\n
\n
I'd love to take this project further and look at controlling more devices around my home. I'd also like to perhaps replace the Raspberry Pi with a far smaller device... Perhaps an ESP32 or a Wilderness Labs Meadow. I could then dot these around the house and control my home with the Percept.
\n
\n
I'd also like to improve the feedback of the system, where currently I'm only sending a one way command, with no feedback from the Pi as to whether it actually carried out the instruction.
\n
\n
My Thoughts
\n
\n
I found the process of adding a Web Endpoint really easy to achieve, and worked really well. To begin with I was a little confused with the speech response to the called Web Endpoint, but it made sense once I'd set it up.
\n
\n
Event though it's super powerful, It would be awesome if Speech Studio could let us perhaps connect directly to other Azure Services, rather than having to roll our wrapper every time. Perhaps the facility to connect directly to IoT Hub maybe?
\n
\n
Obviously, using an Azure Function in the Consumption mode means that it can go to sleep if it's not used. This leads to a fair delay (around 20-30 seconds at times), before the function actually responds to our command hitting the web endpoint... I guess using a different pricing tier would help here. This coupled with the apparent wake delay of the Percept itself can lead to the first wake up taking some time to complete.
\n
\n
After that though, it works really well, with only a very slight delay between saying the command at the light turning on or off.
\n
\n
Overall, the whole platform works really well, and with the addition of Web Endpoints and Azure Functions, we're able to reach out to any part of Azure we like.
\n
\n
","body@stringLength":"63763","rawBody":"
In the previous post we created our own custom command in Speech Studio to turn music on and off using the Azure Percept.
\n
\n\n
\n
In this post, we’ll take this further by delving into the world of Home Automation.
\n
\n
We’ll go through how to connect our command up to an Azure Function via the Command’s WebHook. From the Azure Function, we’ll connect to an Azure IoT Hub. We can then invoke a Direct Method on a Connected Raspberry Pi. This Direct Method will instruct the Raspberry Pi to turn on and off a Desk Lamp using a Relay.
\n
\n
Previously - A Recap of Custom Commands
\n
\n
Custom Commands allow us to create a command set that the Azure Percept can react to. In the previous post, we created a custom command that allowed the Percept to react to a command to turn music on or off.
\n
\n
Custom Commands are primarily comprised of a set of example sentences and a completion operation. In the previous post our completion operation was to simply respond to the user in voice that the music was turned on or off.
\n
\n
We made good use of Parameters so we could have a single command turn the music both on and off again.
\n
\n
What we’ll be doing
\n
\n
The following diagram gives us an overview of the major component parts of the solution:
\n
\n
\n
\n
We have the Azure Percept Audio in the top left. This of course is connected to the Carrier Board which I’ve not shown here.
\n
\n
Azure Percept makes use of the Speech Service to process spoken word detected through the Percept Audio SoM.
\n
\n
Making use of a Webhook, the Speech Service then triggers an Azure Function using HTTP.
\n
\n
This Azure function takes any parameters passed by the Speech Service and then connects to an Azure IoT Hub using a Service Policy.
\n
\n
The IoT Hub has a Device registered to it which in my case is a Raspberry Pi running .NET 5 and C#9.
\n
\n
The Azure Function invokes a Direct Method on the Raspberry Pi through the IoT Hub when it’s triggered, passing in any parameters which have been passed in from the Speech Service.
\n
\n
The Pi then actions the Direct Method and sets a GPIO pin connected to a relay which turns the mains power on to a Desk Lamp.
\n
\n
Creating an Azure Function App
\n
\n
Once a command has been recognised by the Percept we can configure a done action.
\n
\n
In the previous post we configured this “Done” action as a spoken response to the user. However, we can also configure the command to call a webhook before then returning the result of that webhook back to the user.
\n
\n
Before we can configure the webhook however, we need the address for the webhook to call into.
\n
\n
For this we're going to use an Azure Function. Azure Functions are a serverless compute offering which allows us to host and run our code without needing to worry about all the typical architecture around a traditional compute resource like a virtual machine.
\n
\n
On top of this, Azure Functions are super cheap to run, which is great for our use case.
\n
\n
We'll use the Azure Function to receive the Web Endpoint call from our Speech Command, process it and call into the Azure IoT Hub.
Hitting the blue create button, we’re taken to the first page of the Create Function App process:
\n
\n
\n
\n
\n
Here we can choose our Subscription, Resource group and give our Function a unique Name. We can leave the Publish type as “Code”, set the Runtime Stack to “.NET”, the Version to “3.1” and the region to either “West US” or “West Europe” to match that of our Percept Resources.
\n
\n
We can leave the options on the remaining tags as their default, we we can just hit the “Review + Create” button. Check the options you’ve selected before hitting the blue “Create” button:
\n
\n
\n
\n
The Function App will then begin creating and complete some time later:
\n
\n
\n
\n
Once the Function has finished creating, we can navigate to our new Azure Function by hitting the blue “Go to resource” button:
\n
\n
\n
\n
Creating an Azure Function using VS Code
\n
\n
We’ll now use VS Code to create our Azure Function. It's also possible to complete most of these actions in the Portal, but I find that VS Code offers a great experience for creating Azure Functions.
\n
\n
Before we do this, we need to create a directory for our Azure Function to live in, so go ahead and find a nice location for your azure function. We can then open this folder in VS Code, either by right clicking in empty space and clicking “Open with VS Code”, or opening VS Code and opening the folder directly:
You will need to sign in to Azure if you haven’t already.
\n
\n
Once you’re signed in to Azure, all of your resources will be listed in the left pain when you click the Azure Icon:
\n
\n
\n
\n
Next we need to create our Azure Function. We can do that from the VS Code Tool Palette by pressing ctrl+shift+p, then typing Azure Function in the search box:
\n
\n
\n
\n
We can then select the first item in the list “Azure Functions: Create Function“.
\n
\n
We’ll then see the following prompt: “The select folder is not a function project. Create new project?”
\n
\n
\n
\n
We will then be prompted for which language we’d like to use:
\n
\n
\n
\n
We’ll choose “C#”. Next we’ll be asked which .NET runtime we want to use:
\n
\n
\n
\n
We’ll select “.NET Core 3 LTS”. We’ll then have a choice of Trigger for the Function:
\n
\n
\n
\n
We’ll select “HTTP trigger”. We’ll then have a chance to name our Function:
\n
\n
\n
\n
We’ll choose “PerceptTrigger” for our Trigger. Next, we can give our function a namespace:
\n
\n
\n
\n
We’ll use “Percept.Function“.
\n
\n
Finally we can choose the type of Authentication we want to use for our function:
\n
\n
\n
\n
We’ll choose “Function“, which will allow us to pass a token to the function to authenticate.
\n
\n
The Function will then be created:
\n
\n
\n
\n
With that, the basics of our function has been created:
\n
\n
\n
\n
Adding the Azure IoT Hub SDK
\n
\n
Next, as we’re going to be interacting with an IoT Hub, we need to add the IoT Hub SDK.
\n
\n
We can do this from the terminal. Pressing ” ctrl+shift+’ ” (Control + Shift + Apostrophe), will launch the terminal:
\n
\n
\n
\n
We can install the IoT Hub SDK by running:
\n
\ndotnet add package Microsoft.Azure.Devices\n
\n
\n
\n
\n
Building the Azure Function Code
\n
\n
Replace the contents of the PerceptTrigger.cs file with the following block of code:
\n
\nusing System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.WebJobs;\nusing Microsoft.Azure.WebJobs.Extensions.Http;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Newtonsoft.Json;\nusing Microsoft.Azure.Devices;\n\nnamespace PerceptIoT.Function\n{\n public static class PerceptTrigger\n {\n\n private static ServiceClient serviceClient;\n \n // Connection string for your IoT Hub\n private static string connectionString = System.Environment.GetEnvironmentVariable(\"IotHubConnectionString\");\n // Device ID for Raspberry Pi\n private static string deviceID = System.Environment.GetEnvironmentVariable(\"DeviceID\");\n\n [FunctionName(\"PerceptTrigger\")]\n public static async Task<IActionResult> Run(\n [HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\", Route = null)] HttpRequest req,\n ILogger log)\n {\n log.LogInformation(\"C# HTTP trigger function processed a request.\");\n\n string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n log.LogInformation(requestBody);\n\n dynamic data = JsonConvert.DeserializeObject(requestBody);\n\n log.LogInformation($\"The State was: {data.state} \");\n \n string responseMessage = $\"This HTTP triggered function executed successfully. The State was {data.state}\";\n\n serviceClient = ServiceClient.CreateFromConnectionString(connectionString);\n\n await InvokeMethodAsync(Convert.ToString(data.state));\n\n serviceClient.Dispose();\n\n return new OkObjectResult(responseMessage);\n }\n\n // Invoke the direct method on the device, passing the payload\n private static async Task InvokeMethodAsync(string state)\n {\n var methodInvocation = new CloudToDeviceMethod(\"ControlLight\")\n {\n ResponseTimeout = TimeSpan.FromSeconds(30),\n };\n\n methodInvocation.SetPayloadJson(\"{\\\"state\\\": \\\"\" + state + \"\\\"}\");\n\n // Invoke the direct method asynchronously and get the response from the simulated device.\n var response = await serviceClient.InvokeDeviceMethodAsync(deviceID, methodInvocation);\n\n Console.WriteLine($\"\\nResponse status: {response.Status}, payload:\\n\\t{response.GetPayloadAsJson()}\");\n }\n }\n}\n
\n
\n
Remember to change the “PerceptTrigger” references in the file to whatever you chose for your Function name.
\n
\n
Next we need to add a local debug setting for our IoT Hub Connection string. Replace the contents of your local.settings.json file with the following:
\n
\n{\n \"IsEncrypted\": false,\n \"Values\": {\n \"AzureWebJobsStorage\": \"\",\n \"FUNCTIONS_WORKER_RUNTIME\": \"dotnet\",\n \"IotHubConnectionString\": \"ENTER YOUR IOT HUB SERVICE LEVEL ACCESS POLICY CONNECTION STRING\",\n \"DeviceID\": \"ENTER YOUR RASPBERRY PI DEVICE ID\"\n }\n}\n
\n
\n
Deploying the Function App
\n
\n
We’re now ready to deploy our Function. Using the Azure Tools Extension, in the “Functions” section, if you expand the subscription you created your Function App within, then right click we’ll be given a set of options:
\n
\n
\n
\n
If we select the “Deploy to Function App” option, we can begin deploying our new Azure Function.
\n
\n
We’ll be asked to confirm if we want to deploy the Function App:
\n
\n
\n
Hitting “Deploy” will begin the process of deploying the Function:
\n
\n
\n
\n
Once the process is complete, our new Azure Function will appear in the functions list:
\n
\n
\n
\n
\n
Adding an IoT Device to the IoT Hub
\n
\n
As we’ll be deploying code to a Raspberry Pi which will connect to our IoT Hub, and in turn allow the Azure Function to invoke a Direct Method.
Navigating to the Overview Page of our IoT Hub, we can click the IoT Devices Item:
\n
\n
\n
\n
We’ll then be shown the list of IoT Devices we currently have registered to our IoT Hub:
\n
\n
\n
\n
We can add a new IoT Device by hitting the “+ New” item in the toolbar:
\n
\n
\n
\n
We can name our device “devicecontrol”, leave all the options at their defaults and hit the blue “Save” button:
\n
\n
\n
\n
We’ll then see our new device listed in the Device Registry. You may need to hit the “Refresh” button in the toolbar.
\n
\n
Adding an IoT Hub Shared Access Policy
\n
\n
We now need a way for our Azure Function to connect to our Percept IoT Hub. IoT Hub has the concept of Shared Access Policies to control access to devices and services connecting to and interacting with IoT Hub.
\n
\n
If we return to the overview page of our IoT Hub, we can add a new Shared Access Policy for our Function App to connect to:
\n
\n
\n
\n
We’ll now be shown all of the existing Built-In Shared Access Policies for our IoT Hub:
\n
\n
\n
\n
Our Function will need a policy with “Service Connect” access. We could use the built in “Service” policy, but I prefer to create a new policy for services to use.
\n
\n
If we click the “+ Add shared access policy” in the toolbar, we can add our own policy:
\n
\n
\n
\n
We can name our Shared Access Policy whatever makes sense, I’ve chose “perceptfunctionpolicy” here.
\n
\n
We can then select the “Service Connect” Permission and hit the blue “Add” button to create the Policy.
\n
\n
With the Policy created, it will appear in the list of Shared Access Policies:
\n
\n
\n
\n
If we click on our new Shared Access Policy, we can grab the Primary Connection string we need to allow our Azure Function to connect to the IoT Hub:
\n
\n
\n
\n
Adding a Function App Key
\n
\n
Now that we’ve grabbed our Shared Access Policy, we can add this along with the IoT Device ID of the Raspberry Pi IoT Device we added to the Function Keys for our Azure Function.
\n
\n
Azure Function Function Keys are a way for us to store secrets that our Function can use. This allows us to store our secrets, like IoT Hub Connection Strings, outside of our code, keeping them safe from prying eyes.
\n
\n
Onwards from this, we can also store variables that change the way our code works or configure it to connect with certain parameters.
\n
\n
If we navigate to the overview page of our Function App:
\n
\n
\n
\n
We can navigate to our list of Azure Functions by clicking the “Functions” menu item on the left:
\n
\n
\n
\n
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
\n
\n
\n
\n
We’ll now see the Azure Function we created from VS Code, clicking on this will take us to the details page:
\n
\n
\n
\n
We can then click the Function Keys menu item so we can add our required information:
\n
\n
\n
\n
We can add a new Function Key by pressing the “+ New function key” button at the top of the page:
\n
\n
\n
\n
We can add a Function Key for the Service Shared Access Policy Connection String we added earlier and press the blue “OK” button.
\n
\n
We can repeat that for our IoT Device ID:
\n
\n
\n
\n
Our new Function Keys should now be shown in the list:
\n
\n
\n
\n
Finding the Azure Function URL
\n
\n
We’ll be invoking our function using an HTTP trigger. As such, we’ll need the Azure Function URL.
\n
\n
If we return to the overview page of our function:
\n
\n
\n
\n
We can grab the Azure Function URL by hitting the “Get Function URL” button:
\n
\n
\n
\n
We can press the Copy button to the right of the URL.
\n
\n
Keep this URL safe somewhere for now as we’ll need it when we create our Web Endpoint next.
\n
\n
Adding a Web Endpoint to the Custom Command
\n
\n
We can now return to our Custom Command project. The easiest way to do this is via Percept Studio:
We can navigate to Speech and click on the Commands tab:
\n
\n
\n
I’ve gone ahead and created a new Custom Command for this example, but you can absolutely use the PlayMusic-speech project we created in theprevious post.
\n
\n
Clicking on our custom command will take us to the Speech Project:
\n
\n
\n
\n
\n
\n
I’ve created a new Command named “TurnLightOnOff” with the following Example Sentences:
\n
\nTurn the light {OnOff}\nTurn the lights {OnOff}\nTurn the lamp {OnOff}\nTurn {OnOff} the light\nTurn {OnOff} the lights\nTurn {OnOff} the lamp\nLights {OnOff}\nLamp {OnOff}\nSwitch {OnOff} the light\nSwitch {OnOff} the lights\nSwitch {OnOff} the lamp\nSwitch the light {OnOff}\nSwitch the lights {OnOff}\nSwitch the lamp {OnOff}\n
\n
\n
What we need to do now is to create a new “Web endpoint” for our command to call use when it’s executed:
\n
\n
\n
\n
\n
Clicking on the “Web endpoints” menu item on the left will take us to the Web Endpoints page:
\n
\n
\n
\n
\n
We can now click on the “+ New web endpoint” button at the top of the centre panel to add a new endpoint:
\n
\n
\n
\nWe’ll name our Endpoint “LightControl” and hit the blue “Create” button:
\n
\n
\n
\nWe can now paste in our Function URL from the previous step into the “URL” text box. We can cut off the section beginning “?code=…” as we’ll be passing that in as a query parameter.
\n
\n
\n
\n
\n
\n
We need to set the “Method” option to “POST” here, as we’ll be passing the value of our “OnOff” parameter to our Azure Function in the body of the request.
\n
\n
We can now add the authentication code we cut from the end of the Function URL as a query parameter:
\n
\n
\n
\n
\n
We can hit the “+ Add a query Parameter” button at the bottom of the right hand panel:
\n
\n
\n
\n
\n
\n
We enter “code” as the “Key” and we can paste in the Authentication Code in the “Value” box.
\n
\n
Remember to remove the “?code=” part in front of the Authentication code, so it’s just the random collection to letters and numbers.
\n
\n
We can save the parameter with the blue “Save” button.
\n
\n
\n
\n
Using the new Web Endpoint
\n
\n
\n
\n
We can now make use of our new Web Endpoint within our TurnLightOnOff Custom Command.
\n
\n
If we navigate to our TurnLightOnOff Custom command and to the “Done” section:
\n
\n
\n
\n
Make sure to remove any existing actions if you’re reusing anything from a previous post.
\n
\n
We can add an action for our Web Endpoint by hitting the “+ Add an action” button at the bottom of the right hand pane:
\n
\n
\n
\n
Selecting the “Call web endpoint” option will show the Call Web Endpoint dialog:
\n
\n
\n
\n
We can select our new “LightControl” Web Endpoint from the “Endpoint” dropdown.
\n
\n
Next we need to pass in the value for our “OnOff” paramater so that the Azure Function can pass this to the Raspberry Pi via the IoT Hub and a Direct Method. If we replace the “Body content (JSON)” section with the following:
\n{\n \"state\": \"{OnOff}\"\n}\n
\n
\n
We now need to feedback a spoken response to the user once the Web Endpoint has been called. If we hit the “On Success (Required)” tab at the top:
\n
\n
\n
\n
We can select the “Send speech response” option from the “Action to execute” dropdown:
\n
\n
\n
\n
We can return the following response:
\nThe light has been turned {OnOff}\n
\n
We can then repeat this for the “On Failure (Required)” tab:
\n
\n
\n
\n
Where we can enter the following response in the “Simple Response Editor”:
\nFailed to turn the light {OnOff}\n
\n
We can now save our Done Action by hitting the blue “Save” button:
\n
\n
\n
Finally, we can hit the “Save” button, followed by the “Train” button and finally the Publish Button:
\n
\n
\n
We can then return to Azure Percept Studio and make sure our custom Command is assigned to our Percept:
\n
\n
\n
\n
Select your Custom Command and hit the “Assign” button in the toolbar:
\n
\n\n
\n
\n
Select your IoT Hub and Percept Device and hit the blue “Save” button to Deploy to your Device:
\n
\n
\n
\n
Raspberry Pi Code
\n
\n
Next we’ll get the Raspberry Pi set up ready to connect to the IoT Hub and receive the Direct Method Invocation from our Azure Function.
\n
\n
The first thing you’ll need to do is get your Raspberry Pi set up to run .NET 5. I’ve created a post around on how to that:
Once you’ve got the Pi Setup, we can create the project. I’d do this either in your home directory, or if you’ve set up a SAMBA share, then that directory will be best.
\n
\n
We create a new .NET 5 console application with:
\n
\ndotnet new console -o device_code\ncd device_code\n
\n
\n
We can now add the nuget packages for both GPIO Control and Azure IoT Hub Client:
We now need to replace the placeholder for the IoT Device Connection String with the one from the device we created earlier.
\n
\n
If we return to the portal, to our IoT Hub IoT Device Registry Page and to the Device Details page for our “devicecontrol” device:
\n
\n
\n
\n
We can copy the Primary Connection string and then paste that into the Program.cs file where we have “ENTER YOU DEVICE CONNECTION STRING”.
\n
\n
Raspberry Pi Circuit
\n
\n
The hardware side of this solution centres around a Raspberry Pi. We make use of a Relay to turn the mains supply to a desk lamp on and off.
\n
\n
DISCLAIMER
As a word of warning. The mains relay part of solution should only be attempted if you are experienced in handling mains voltages, as this can be very dangerous if the correct safety precautions aren’t followed.
Needless to say, I can’t take any responsibility for damage or harm as a result of the following instructions!
\n
\n
\n
With that out of the way, the following is the circuit diagram for the Raspberry Pi, Relay and Lamp:
\n
\n
\n
\n
The Raspberry Pi is connected as follows:
\n
\n
\n\n
\n
Pi Pin Number
\n
Function
\n
Relay Pin Label
\n
Colour
\n
\n
\n
2
\n
5V
\n
VCC
\n
Red
\n
\n
\n
20
\n
GND
\n
GND
\n
Black
\n
\n
\n
32
\n
Relay Control (GPIO 12)
\n
IN1
\n
Green
\n
\n\n
\n
\n
I’ve actually enclosed my whole circuit (aside from the Pi), in a patress to keep the mains side sealed away:
\n
\n
\n
\n
I’m using an Elegoo 4 way Relay unit… You can find this at Amazon here: https://amzn.to/2UGX6pT
\n
\n
Testing the System
\n
\n
With all of these parts hooked together, you should be in a position to test turning the light on and off!
\n
First we need to run the software on the Raspberry Pi.
\n
\n
From the directory you created the “device_code” project, run the code with:
\n
\ndotnet run\n
\n
\n
Once the code is running, you can try turning the light on and off using your Percept.
\n
\n
The Raspberry Pi terminal window should feedback the instructions it receives:
\n
\n
\n
\n
If everything has gone according to plan, you should now have a working system!
\n
\n\n
\n
My Plans
\n
\n
I'd love to take this project further and look at controlling more devices around my home. I'd also like to perhaps replace the Raspberry Pi with a far smaller device... Perhaps an ESP32 or a Wilderness Labs Meadow. I could then dot these around the house and control my home with the Percept.
\n
\n
I'd also like to improve the feedback of the system, where currently I'm only sending a one way command, with no feedback from the Pi as to whether it actually carried out the instruction.
\n
\n
My Thoughts
\n
\n
I found the process of adding a Web Endpoint really easy to achieve, and worked really well. To begin with I was a little confused with the speech response to the called Web Endpoint, but it made sense once I'd set it up.
\n
\n
Event though it's super powerful, It would be awesome if Speech Studio could let us perhaps connect directly to other Azure Services, rather than having to roll our wrapper every time. Perhaps the facility to connect directly to IoT Hub maybe?
\n
\n
Obviously, using an Azure Function in the Consumption mode means that it can go to sleep if it's not used. This leads to a fair delay (around 20-30 seconds at times), before the function actually responds to our command hitting the web endpoint... I guess using a different pricing tier would help here. This coupled with the apparent wake delay of the Percept itself can lead to the first wake up taking some time to complete.
\n
\n
After that though, it works really well, with only a very slight delay between saying the command at the light turning on or off.
\n
\n
Overall, the whole platform works really well, and with the addition of Web Endpoints and Azure Functions, we're able to reach out to any part of Azure we like.
Pete shows us how we can control a desk lamp from an Azure Percept DK
","introduction":"","coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""},"currentRevision":{"__ref":"Revision:revision:2528048_5"},"latestVersion":{"__typename":"FriendlyVersion","major":"1","minor":"0"},"metrics":{"__typename":"MessageMetrics","views":10012},"visibilityScope":"PUBLIC","canonicalUrl":null,"seoTitle":null,"seoDescription":null,"placeholder":false,"originalMessageForPlaceholder":null,"contributors":{"__typename":"UserConnection","edges":[]},"nonCoAuthorContributors":{"__typename":"UserConnection","edges":[]},"coAuthors":{"__typename":"UserConnection","edges":[]},"blogMessagePolicies":{"__typename":"BlogMessagePolicies","canDoAuthoringActionsOnBlog":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","key":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","args":[]}}},"archivalData":null,"replies":{"__typename":"MessageConnection","edges":[],"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"customFields":[],"revisions({\"constraints\":{\"isPublished\":{\"eq\":true}},\"first\":1})":{"__typename":"RevisionConnection","totalCount":5}},"Conversation:conversation:2528048":{"__typename":"Conversation","id":"conversation:2528048","solved":false,"topic":{"__ref":"BlogTopicMessage:message:2528048"},"lastPostingActivityTime":"2021-07-08T14:33:13.630-07:00","lastPostTime":"2021-07-08T14:33:13.630-07:00","unreadReplyCount":0,"isSubscribed":false},"ModerationData:moderation_data:2528048":{"__typename":"ModerationData","id":"moderation_data:2528048","status":"APPROVED","rejectReason":null,"isReportedAbuse":false,"rejectUser":null,"rejectTime":null,"rejectActorType":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4MWlENjY4NURFMDEyQ0E1MjNG?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4MWlENjY4NURFMDEyQ0E1MjNG?revision=5","title":"Percept-Audio-Home-Automation-Featured-Image-1536x746","associationType":"TEASER","width":1536,"height":746,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4Mmk0MkNDNTNBQzRDNDIyMTY5?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4Mmk0MkNDNTNBQzRDNDIyMTY5?revision=5","title":"PerceptIoT","associationType":"BODY","width":1521,"height":991,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4M2lDNEJEQjk5MTEyQUI0NkY2?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4M2lDNEJEQjk5MTEyQUI0NkY2?revision=5","title":"image-80","associationType":"BODY","width":703,"height":459,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4NGkzMUVGMjVDNTczRkYxNkJB?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4NGkzMUVGMjVDNTczRkYxNkJB?revision=5","title":"image-81-1024x975","associationType":"BODY","width":1024,"height":975,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4OGlGRTE3MzY2QjdGNjFDNTlC?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI4OGlGRTE3MzY2QjdGNjFDNTlC?revision=5","title":"image-82","associationType":"BODY","width":1522,"height":1377,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5MGk3QTE1OTFFRjAzOURCMTAx?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5MGk3QTE1OTFFRjAzOURCMTAx?revision=5","title":"image-84","associationType":"BODY","width":1258,"height":631,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5MWlDQ0Y2MzUzRkE3RDg1MEI1?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5MWlDQ0Y2MzUzRkE3RDg1MEI1?revision=5","title":"image-85","associationType":"BODY","width":3238,"height":1591,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5M2k3RjlBMjY3MzlGNjk2MzIy?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5M2k3RjlBMjY3MzlGNjk2MzIy?revision=5","title":"image-88","associationType":"BODY","width":664,"height":514,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NGk1QzQ5Njc2RDU1REFFMEFE?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NGk1QzQ5Njc2RDU1REFFMEFE?revision=5","title":"image-86","associationType":"BODY","width":1235,"height":360,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NWk3MjMwRkFCMURDOEQ2NUEx?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NWk3MjMwRkFCMURDOEQ2NUEx?revision=5","title":"image-87","associationType":"BODY","width":1922,"height":1824,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NmkyNDBGNERGMTI5MkUzQUZE?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5NmkyNDBGNERGMTI5MkUzQUZE?revision=5","title":"image-89","associationType":"BODY","width":1033,"height":523,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5N2k0NEQyQTFEQ0QxQTVEMEU1?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5N2k0NEQyQTFEQ0QxQTVEMEU1?revision=5","title":"image-90","associationType":"BODY","width":617,"height":180,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5OGkyRTI4MzYyMEIzNzk2NjEy?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5OGkyRTI4MzYyMEIzNzk2NjEy?revision=5","title":"image-91","associationType":"BODY","width":1003,"height":411,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5OWlEQzgwOENBMkMyODg3NDA4?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDI5OWlEQzgwOENBMkMyODg3NDA4?revision=5","title":"image-92","associationType":"BODY","width":977,"height":248,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwMGk5MkRDRUZEQ0ZERjY4Mjkw?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwMGk5MkRDRUZEQ0ZERjY4Mjkw?revision=5","title":"image-93","associationType":"BODY","width":954,"height":660,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwMmlFOEM1Qzc1Mjg1NkQ3RUJG?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwMmlFOEM1Qzc1Mjg1NkQ3RUJG?revision=5","title":"image-94","associationType":"BODY","width":947,"height":205,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwM2k3MjkxRTM2MUUzNEZCM0E2?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwM2k3MjkxRTM2MUUzNEZCM0E2?revision=5","title":"image-95","associationType":"BODY","width":931,"height":203,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNGkxNzQ4MzU0NkU5MjQwNzUy?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNGkxNzQ4MzU0NkU5MjQwNzUy?revision=5","title":"image-96","associationType":"BODY","width":951,"height":267,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNWlFQTIxOEEwM0VDQjIwRkM4?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNWlFQTIxOEEwM0VDQjIwRkM4?revision=5","title":"image-97","associationType":"BODY","width":695,"height":144,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNmkxQUNGMkRFMDhBOUFFMDYw?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwNmkxQUNGMkRFMDhBOUFFMDYw?revision=5","title":"image-98","associationType":"BODY","width":2180,"height":1196,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwN2lGMjA2NEFDNjdEOEM0Q0U1?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwN2lGMjA2NEFDNjdEOEM0Q0U1?revision=5","title":"image-99","associationType":"BODY","width":893,"height":340,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwOWkyMEYzQjg3MUFEQTQ3ODZC?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMwOWkyMEYzQjg3MUFEQTQ3ODZC?revision=5","title":"image-100","associationType":"BODY","width":2386,"height":489,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxMmk0Mzg1MzY3NTFGQTU0RDM0?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxMmk0Mzg1MzY3NTFGQTU0RDM0?revision=5","title":"image-102","associationType":"BODY","width":1744,"height":826,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxM2lCQ0VEMkI0QUE3NEEzMUNC?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxM2lCQ0VEMkI0QUE3NEEzMUNC?revision=5","title":"image-103","associationType":"BODY","width":835,"height":198,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxNWk3RDg2RjFDMDMxNjQyRTIy?revision=5\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yNTI4MDQ4LTI5NDMxNWk3RDg2RjFDMDMxNjQyRTIy?revision=5","title":"image-104","associationType":"BODY","width":715,"height":126,"altText":null},"Revision:revision:2528048_5":{"__typename":"Revision","id":"revision:2528048_5","lastEditTime":"2021-07-08T14:33:13.630-07:00"},"CachedAsset:theme:customTheme1-1737540113726":{"__typename":"CachedAsset","id":"theme:customTheme1-1737540113726","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["default"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"favicon-1730836283320.png","imageLastModified":"1730836286415","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"favicon-1730836271365.png","imageLastModified":"1730836274203","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1300px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_BROWSER","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"3px","borderRadius":"3px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"16px","paddingXHero":"60px","fontStyle":"NORMAL","fontWeight":"700","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-200)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-200)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"LIGHT","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.16)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.12)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-link-color)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","forumColor":"#4099E2","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#148563","blogColor":"#1CBAA0","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#4C6B90","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#FF8000","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#D13A1F","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#333333","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#717171","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0069D4","secondary":"#333333","bodyText":"#333333","bodyBg":"#FFFFFF","info":"#409AE2","success":"#41C5AE","warning":"#FCC844","danger":"#BC341B","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#D3F5A4","#243A5E"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Segoe UI","fontStyle":"NORMAL","fontWeight":"400","h1FontSize":"34px","h2FontSize":"32px","h3FontSize":"28px","h4FontSize":"24px","h5FontSize":"20px","h6FontSize":"16px","lineHeight":"1.3","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":"","imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"40px","defaultMessageHeaderMarginBottom":"20px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"40px","specialMessageHeaderMarginBottom":"20px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Segoe UI","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.5","fontSizeBase":"16px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"14px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[{"source":"SERVER","name":"Segoe UI","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"},{"style":"NORMAL","weight":"300","__typename":"FontStyleData"},{"style":"NORMAL","weight":"600","__typename":"FontStyleData"},{"style":"NORMAL","weight":"700","__typename":"FontStyleData"},{"style":"ITALIC","weight":"400","__typename":"FontStyleData"}],"assetNames":["SegoeUI-normal-400.woff2","SegoeUI-normal-300.woff2","SegoeUI-normal-600.woff2","SegoeUI-normal-700.woff2","SegoeUI-italic-400.woff2"],"__typename":"CustomFont"},{"source":"SERVER","name":"MWF Fluent Icons","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"}],"assetNames":["MWFFluentIcons-normal-400.woff2"],"__typename":"CustomFont"}],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1737115705000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1737115705000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:quilt:o365.prod:pages/blogs/BlogMessagePage:board:IoTBlog-1737540111973":{"__typename":"CachedAsset","id":"quilt:o365.prod:pages/blogs/BlogMessagePage:board:IoTBlog-1737540111973","value":{"id":"BlogMessagePage","container":{"id":"Common","headerProps":{"backgroundImageProps":null,"backgroundColor":null,"addComponents":null,"removeComponents":["community.widget.bannerWidget"],"componentOrder":null,"__typename":"QuiltContainerSectionProps"},"headerComponentProps":{"community.widget.breadcrumbWidget":{"disableLastCrumbForDesktop":false}},"footerProps":null,"footerComponentProps":null,"items":[{"id":"blog-article","layout":"ONE_COLUMN","bgColor":null,"showTitle":null,"showDescription":null,"textPosition":null,"textColor":null,"sectionEditLevel":"LOCKED","bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"OneColumnQuiltSection","columnMap":{"main":[{"id":"blogs.widget.blogArticleWidget","className":"lia-blog-container","props":null,"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"}},{"id":"section-1729184836777","layout":"MAIN_SIDE","bgColor":"transparent","showTitle":false,"showDescription":false,"textPosition":"CENTER","textColor":"var(--lia-bs-body-color)","sectionEditLevel":null,"bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"MainSideQuiltSection","columnMap":{"main":[],"side":[{"id":"custom.widget.Social_Sharing","className":null,"props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":true,"title":"Share","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"MainSideSectionColumns"}}],"__typename":"QuiltContainer"},"__typename":"Quilt","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-pages/blogs/BlogMessagePage-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-pages/blogs/BlogMessagePage-1737115705000","value":{"title":"{contextMessageSubject} | {communityTitle}","errorMissing":"This blog post cannot be found","name":"Blog Message Page","section.blog-article.title":"Blog Post","archivedMessageTitle":"This Content Has Been Archived","section.section-1729184836777.title":"","section.section-1729184836777.description":"","section.CncIde.title":"Blog Post","section.tifEmD.description":"","section.tifEmD.title":""},"localOverride":false},"CachedAsset:quiltWrapper:o365.prod:Common:1737540056874":{"__typename":"CachedAsset","id":"quiltWrapper:o365.prod:Common:1737540056874","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"community.widget.navbarWidget","props":{"showUserName":true,"showRegisterLink":true,"useIconLanguagePicker":true,"useLabelLanguagePicker":true,"className":"QuiltComponent_lia-component-edit-mode__0nCcm","links":{"sideLinks":[],"mainLinks":[{"children":[],"linkType":"INTERNAL","id":"gxcuf89792","params":{},"routeName":"CommunityPage"},{"children":[],"linkType":"EXTERNAL","id":"external-link","url":"/Directory","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft365","params":{"categoryId":"microsoft365"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-teams","params":{"categoryId":"MicrosoftTeams"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows","params":{"categoryId":"Windows"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-securityand-compliance","params":{"categoryId":"MicrosoftSecurityandCompliance"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"outlook","params":{"categoryId":"Outlook"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"planner","params":{"categoryId":"Planner"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows-server","params":{"categoryId":"Windows-Server"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"azure","params":{"categoryId":"Azure"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"exchange","params":{"categoryId":"Exchange"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-endpoint-manager","params":{"categoryId":"microsoft-endpoint-manager"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"s-q-l-server","params":{"categoryId":"SQL-Server"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-2","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities","url":"/","target":"BLANK"},{"children":[{"linkType":"INTERNAL","id":"education-sector","params":{"categoryId":"EducationSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"a-i","params":{"categoryId":"AI"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"i-t-ops-talk","params":{"categoryId":"ITOpsTalk"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"partner-community","params":{"categoryId":"PartnerCommunity"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-mechanics","params":{"categoryId":"MicrosoftMechanics"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"healthcare-and-life-sciences","params":{"categoryId":"HealthcareAndLifeSciences"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"public-sector","params":{"categoryId":"PublicSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"io-t","params":{"categoryId":"IoT"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"driving-adoption","params":{"categoryId":"DrivingAdoption"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"s-m-b","params":{"categoryId":"SMB"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"startupsat-microsoft","params":{"categoryId":"StartupsatMicrosoft"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-1","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities-1","url":"/","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external","url":"/Blogs","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external-1","url":"/Events","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft-learn-1","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-learn-blog","params":{"boardId":"MicrosoftLearnBlog","categoryId":"MicrosoftLearn"},"routeName":"BlogBoardPage"},{"linkType":"EXTERNAL","id":"external-10","url":"https://learningroomdirectory.microsoft.com/","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-3","url":"https://docs.microsoft.com/learn/dynamics365/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-4","url":"https://docs.microsoft.com/learn/m365/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-5","url":"https://docs.microsoft.com/learn/topics/sci/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-6","url":"https://docs.microsoft.com/learn/powerplatform/?wt.mc_id=techcom_header-webpage-powerplatform","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-7","url":"https://docs.microsoft.com/learn/github/?wt.mc_id=techcom_header-webpage-github","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-8","url":"https://docs.microsoft.com/learn/teams/?wt.mc_id=techcom_header-webpage-teams","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-9","url":"https://docs.microsoft.com/learn/dotnet/?wt.mc_id=techcom_header-webpage-dotnet","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-2","url":"https://docs.microsoft.com/learn/azure/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"}],"linkType":"INTERNAL","id":"microsoft-learn","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"community-info-center","params":{"categoryId":"Community-Info-Center"},"routeName":"CategoryPage"}]},"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","controllerHighlightColor":"hsla(30, 100%, 50%)","linkFontWeight":"400","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkBoxShadowHover":"none","linkFontSize":"14px","backgroundOpacity":0.8,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","hamburgerColor":"var(--lia-nav-controller-icon-color)","linkTextBorderBottom":"none","brandLogoHeight":"30px","linkBgHoverColor":"transparent","linkLetterSpacing":"normal","collapseMenuDividerOpacity":0.16,"dropdownPaddingBottom":"15px","paddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"1px solid var(--lia-bs-border-color)","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","collapseMenuDividerBg":"var(--lia-nav-link-color)","linkColor":"var(--lia-bs-body-color)","linkJustifyContent":"flex-start","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","controllerTextColor":"var(--lia-nav-controller-icon-color)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-body-color)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid var(--lia-bs-body-color)","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","linkPaddingX":"10px","linkPaddingY":"5px","paddingTop":"15px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkBgColor":"transparent","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkDropdownPaddingY":"9px","controllerIconColor":"var(--lia-bs-body-color)","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"var(--lia-bs-body-color)"},"showSearchIcon":false,"languagePickerStyle":"iconAndLabel"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"transparent","linkHighlightColor":"var(--lia-bs-primary)","visualEffects":{"showBottomBorder":true},"linkTextColor":"var(--lia-bs-gray-700)"},"__typename":"QuiltComponent"},{"id":"custom.widget.HeroBanner","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"usePageWidth":false,"useBackground":false,"cMax_items":3,"title":"","lazyLoad":false,"widgetChooser":"custom.widget.HeroBanner"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.MicrosoftFooter","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1737115705000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:component:custom.widget.HeroBanner-en-1737540190338":{"__typename":"CachedAsset","id":"component:custom.widget.HeroBanner-en-1737540190338","value":{"component":{"id":"custom.widget.HeroBanner","template":{"id":"HeroBanner","markupLanguage":"REACT","style":null,"texts":{"searchPlaceholderText":"Search this community","followActionText":"Follow","unfollowActionText":"Following","searchOnHoverText":"Please enter your search term(s) and then press return key to complete a search."},"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":null,"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.HeroBanner","form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":null,"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"__typename":"Component","localOverride":false},"globalCss":null,"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"}},"localOverride":false},"CachedAsset:component:custom.widget.Social_Sharing-en-1737540190338":{"__typename":"CachedAsset","id":"component:custom.widget.Social_Sharing-en-1737540190338","value":{"component":{"id":"custom.widget.Social_Sharing","template":{"id":"Social_Sharing","markupLanguage":"HANDLEBARS","style":".social-share {\n .sharing-options {\n position: relative;\n margin: 0;\n padding: 0;\n line-height: 10px;\n display: flex;\n justify-content: left;\n gap: 5px;\n list-style-type: none;\n li {\n text-align: left;\n a {\n min-width: 30px;\n min-height: 30px;\n display: block;\n padding: 1px;\n .social-share-linkedin {\n img {\n background-color: rgb(0, 119, 181);\n }\n }\n .social-share-facebook {\n img {\n background-color: rgb(59, 89, 152);\n }\n }\n .social-share-x {\n img {\n background-color: rgb(0, 0, 0);\n }\n }\n .social-share-rss {\n img {\n background-color: rgb(0, 0, 0);\n }\n }\n .social-share-reddit {\n img {\n background-color: rgb(255, 69, 0);\n }\n }\n .social-share-email {\n img {\n background-color: rgb(132, 132, 132);\n }\n }\n }\n a {\n img {\n height: 2rem;\n }\n }\n }\n }\n}\n","texts":null,"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"Adds buttons to share to various social media websites","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Social_Sharing","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"Adds buttons to share to various social media websites","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":{"css":".custom_widget_Social_Sharing_social-share_c7xxz_1 {\n .custom_widget_Social_Sharing_sharing-options_c7xxz_2 {\n position: relative;\n margin: 0;\n padding: 0;\n line-height: 0.625rem;\n display: flex;\n justify-content: left;\n gap: 0.3125rem;\n list-style-type: none;\n li {\n text-align: left;\n a {\n min-width: 1.875rem;\n min-height: 1.875rem;\n display: block;\n padding: 0.0625rem;\n .custom_widget_Social_Sharing_social-share-linkedin_c7xxz_18 {\n img {\n background-color: rgb(0, 119, 181);\n }\n }\n .custom_widget_Social_Sharing_social-share-facebook_c7xxz_23 {\n img {\n background-color: rgb(59, 89, 152);\n }\n }\n .custom_widget_Social_Sharing_social-share-x_c7xxz_28 {\n img {\n background-color: rgb(0, 0, 0);\n }\n }\n .custom_widget_Social_Sharing_social-share-rss_c7xxz_33 {\n img {\n background-color: rgb(0, 0, 0);\n }\n }\n .custom_widget_Social_Sharing_social-share-reddit_c7xxz_38 {\n img {\n background-color: rgb(255, 69, 0);\n }\n }\n .custom_widget_Social_Sharing_social-share-email_c7xxz_43 {\n img {\n background-color: rgb(132, 132, 132);\n }\n }\n }\n a {\n img {\n height: 2rem;\n }\n }\n }\n }\n}\n","tokens":{"social-share":"custom_widget_Social_Sharing_social-share_c7xxz_1","sharing-options":"custom_widget_Social_Sharing_sharing-options_c7xxz_2","social-share-linkedin":"custom_widget_Social_Sharing_social-share-linkedin_c7xxz_18","social-share-facebook":"custom_widget_Social_Sharing_social-share-facebook_c7xxz_23","social-share-x":"custom_widget_Social_Sharing_social-share-x_c7xxz_28","social-share-rss":"custom_widget_Social_Sharing_social-share-rss_c7xxz_33","social-share-reddit":"custom_widget_Social_Sharing_social-share-reddit_c7xxz_38","social-share-email":"custom_widget_Social_Sharing_social-share-email_c7xxz_43"}},"form":null},"localOverride":false},"CachedAsset:component:custom.widget.MicrosoftFooter-en-1737540190338":{"__typename":"CachedAsset","id":"component:custom.widget.MicrosoftFooter-en-1737540190338","value":{"component":{"id":"custom.widget.MicrosoftFooter","template":{"id":"MicrosoftFooter","markupLanguage":"HANDLEBARS","style":".context-uhf {\n min-width: 280px;\n font-size: 15px;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.c-uhff-link {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.c-uhff {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.c-uhff-nav {\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n .c-heading-4 {\n color: #616161;\n word-break: break-word;\n font-size: 15px;\n line-height: 20px;\n padding: 36px 0 4px;\n font-weight: 600;\n }\n .c-uhff-nav-row {\n .c-uhff-nav-group {\n display: block;\n float: left;\n min-height: 1px;\n vertical-align: text-top;\n padding: 0 12px;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.c-list.f-bare {\n font-size: 11px;\n line-height: 16px;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 8px 0;\n margin: 0;\n }\n }\n }\n }\n}\n.c-uhff-base {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 30px 5% 16px;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.c-uhff-ccpa {\n font-size: 11px;\n line-height: 16px;\n float: left;\n margin: 3px 0;\n }\n a.c-uhff-ccpa:hover {\n text-decoration: underline;\n }\n ul.c-list {\n font-size: 11px;\n line-height: 16px;\n float: right;\n margin: 3px 0;\n color: #616161;\n li {\n padding: 0 24px 4px 0;\n display: inline-block;\n }\n }\n .c-list.f-bare {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 30px 24px 16px;\n }\n}\n","texts":{"New tab":"What's New","New 1":"Surface Laptop Studio 2","New 2":"Surface Laptop Go 3","New 3":"Surface Pro 9","New 4":"Surface Laptop 5","New 5":"Surface Studio 2+","New 6":"Copilot in Windows","New 7":"Microsoft 365","New 8":"Windows 11 apps","Store tab":"Microsoft Store","Store 1":"Account Profile","Store 2":"Download Center","Store 3":"Microsoft Store Support","Store 4":"Returns","Store 5":"Order tracking","Store 6":"Certified Refurbished","Store 7":"Microsoft Store Promise","Store 8":"Flexible Payments","Education tab":"Education","Edu 1":"Microsoft in education","Edu 2":"Devices for education","Edu 3":"Microsoft Teams for Education","Edu 4":"Microsoft 365 Education","Edu 5":"How to buy for your school","Edu 6":"Educator Training and development","Edu 7":"Deals for students and parents","Edu 8":"Azure for students","Business tab":"Business","Bus 1":"Microsoft Cloud","Bus 2":"Microsoft Security","Bus 3":"Dynamics 365","Bus 4":"Microsoft 365","Bus 5":"Microsoft Power Platform","Bus 6":"Microsoft Teams","Bus 7":"Microsoft Industry","Bus 8":"Small Business","Developer tab":"Developer & IT","Dev 1":"Azure","Dev 2":"Developer Center","Dev 3":"Documentation","Dev 4":"Microsoft Learn","Dev 5":"Microsoft Tech Community","Dev 6":"Azure Marketplace","Dev 7":"AppSource","Dev 8":"Visual Studio","Company tab":"Company","Com 1":"Careers","Com 2":"About Microsoft","Com 3":"Company News","Com 4":"Privacy at Microsoft","Com 5":"Investors","Com 6":"Diversity and inclusion","Com 7":"Accessiblity","Com 8":"Sustainibility"},"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.MicrosoftFooter","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":{"css":".custom_widget_MicrosoftFooter_context-uhf_f95yq_1 {\n min-width: 17.5rem;\n font-size: 0.9375rem;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-link_f95yq_12 {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff_f95yq_12 {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.custom_widget_MicrosoftFooter_c-uhff-nav_f95yq_35 {\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n .custom_widget_MicrosoftFooter_c-heading-4_f95yq_49 {\n color: #616161;\n word-break: break-word;\n font-size: 0.9375rem;\n line-height: 1.25rem;\n padding: 2.25rem 0 0.25rem;\n font-weight: 600;\n }\n .custom_widget_MicrosoftFooter_c-uhff-nav-row_f95yq_57 {\n .custom_widget_MicrosoftFooter_c-uhff-nav-group_f95yq_58 {\n display: block;\n float: left;\n min-height: 0.0625rem;\n vertical-align: text-top;\n padding: 0 0.75rem;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.custom_widget_MicrosoftFooter_c-list_f95yq_78.custom_widget_MicrosoftFooter_f-bare_f95yq_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 0.5rem 0;\n margin: 0;\n }\n }\n }\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff-base_f95yq_94 {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 1.875rem 5% 1rem;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_f95yq_107 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: left;\n margin: 0.1875rem 0;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_f95yq_107:hover {\n text-decoration: underline;\n }\n ul.custom_widget_MicrosoftFooter_c-list_f95yq_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: right;\n margin: 0.1875rem 0;\n color: #616161;\n li {\n padding: 0 1.5rem 0.25rem 0;\n display: inline-block;\n }\n }\n .custom_widget_MicrosoftFooter_c-list_f95yq_78.custom_widget_MicrosoftFooter_f-bare_f95yq_78 {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 1.875rem 1.5rem 1rem;\n }\n}\n","tokens":{"context-uhf":"custom_widget_MicrosoftFooter_context-uhf_f95yq_1","c-uhff-link":"custom_widget_MicrosoftFooter_c-uhff-link_f95yq_12","c-uhff":"custom_widget_MicrosoftFooter_c-uhff_f95yq_12","c-uhff-nav":"custom_widget_MicrosoftFooter_c-uhff-nav_f95yq_35","c-heading-4":"custom_widget_MicrosoftFooter_c-heading-4_f95yq_49","c-uhff-nav-row":"custom_widget_MicrosoftFooter_c-uhff-nav-row_f95yq_57","c-uhff-nav-group":"custom_widget_MicrosoftFooter_c-uhff-nav-group_f95yq_58","c-list":"custom_widget_MicrosoftFooter_c-list_f95yq_78","f-bare":"custom_widget_MicrosoftFooter_f-bare_f95yq_78","c-uhff-base":"custom_widget_MicrosoftFooter_c-uhff-base_f95yq_94","c-uhff-ccpa":"custom_widget_MicrosoftFooter_c-uhff-ccpa_f95yq_107"}},"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1737115705000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBanner-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBanner-1737115705000","value":{"messageMarkedAsSpam":"This post has been marked as spam","messageMarkedAsSpam@board:TKB":"This article has been marked as spam","messageMarkedAsSpam@board:BLOG":"This post has been marked as spam","messageMarkedAsSpam@board:FORUM":"This discussion has been marked as spam","messageMarkedAsSpam@board:OCCASION":"This event has been marked as spam","messageMarkedAsSpam@board:IDEA":"This idea has been marked as spam","manageSpam":"Manage Spam","messageMarkedAsAbuse":"This post has been marked as abuse","messageMarkedAsAbuse@board:TKB":"This article has been marked as abuse","messageMarkedAsAbuse@board:BLOG":"This post has been marked as abuse","messageMarkedAsAbuse@board:FORUM":"This discussion has been marked as abuse","messageMarkedAsAbuse@board:OCCASION":"This event has been marked as abuse","messageMarkedAsAbuse@board:IDEA":"This idea has been marked as abuse","preModCommentAuthorText":"This comment will be published as soon as it is approved","preModCommentModeratorText":"This comment is awaiting moderation","messageMarkedAsOther":"This post has been rejected due to other reasons","messageMarkedAsOther@board:TKB":"This article has been rejected due to other reasons","messageMarkedAsOther@board:BLOG":"This post has been rejected due to other reasons","messageMarkedAsOther@board:FORUM":"This discussion has been rejected due to other reasons","messageMarkedAsOther@board:OCCASION":"This event has been rejected due to other reasons","messageMarkedAsOther@board:IDEA":"This idea has been rejected due to other reasons","messageArchived":"This post was archived on {date}","relatedUrl":"View Related Content","relatedContentText":"Showing related content","archivedContentLink":"View Archived Content"},"localOverride":false},"Category:category:Exchange":{"__typename":"Category","id":"category:Exchange","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Planner":{"__typename":"Category","id":"category:Planner","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Outlook":{"__typename":"Category","id":"category:Outlook","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Community-Info-Center":{"__typename":"Category","id":"category:Community-Info-Center","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:EducationSector":{"__typename":"Category","id":"category:EducationSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:DrivingAdoption":{"__typename":"Category","id":"category:DrivingAdoption","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Azure":{"__typename":"Category","id":"category:Azure","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows-Server":{"__typename":"Category","id":"category:Windows-Server","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:SQL-Server":{"__typename":"Category","id":"category:SQL-Server","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftTeams":{"__typename":"Category","id":"category:MicrosoftTeams","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PublicSector":{"__typename":"Category","id":"category:PublicSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft365":{"__typename":"Category","id":"category:microsoft365","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:HealthcareAndLifeSciences":{"__typename":"Category","id":"category:HealthcareAndLifeSciences","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:SMB":{"__typename":"Category","id":"category:SMB","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:ITOpsTalk":{"__typename":"Category","id":"category:ITOpsTalk","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft-endpoint-manager":{"__typename":"Category","id":"category:microsoft-endpoint-manager","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftSecurityandCompliance":{"__typename":"Category","id":"category:MicrosoftSecurityandCompliance","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftLearn":{"__typename":"Category","id":"category:MicrosoftLearn","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Blog:board:MicrosoftLearnBlog":{"__typename":"Blog","id":"board:MicrosoftLearnBlog","blogPolicies":{"__typename":"BlogPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:AI":{"__typename":"Category","id":"category:AI","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftMechanics":{"__typename":"Category","id":"category:MicrosoftMechanics","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:StartupsatMicrosoft":{"__typename":"Category","id":"category:StartupsatMicrosoft","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PartnerCommunity":{"__typename":"Category","id":"category:PartnerCommunity","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows":{"__typename":"Category","id":"category:Windows","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"QueryVariables:TopicReplyList:message:2528048:5":{"__typename":"QueryVariables","id":"TopicReplyList:message:2528048:5","value":{"id":"message:2528048","first":10,"sorts":{"postTime":{"direction":"DESC"}},"repliesFirst":3,"repliesFirstDepthThree":1,"repliesSorts":{"postTime":{"direction":"DESC"}},"useAvatar":true,"useAuthorLogin":true,"useAuthorRank":true,"useBody":true,"useKudosCount":true,"useTimeToRead":false,"useMedia":false,"useReadOnlyIcon":false,"useRepliesCount":true,"useSearchSnippet":false,"useAcceptedSolutionButton":false,"useSolvedBadge":false,"useAttachments":false,"attachmentsFirst":5,"useTags":true,"useNodeAncestors":false,"useUserHoverCard":true,"useNodeHoverCard":false,"useModerationStatus":true,"usePreviewSubjectModal":false,"useMessageStatus":true}},"ROOT_MUTATION":{"__typename":"Mutation"},"CachedAsset:text:en_US-components/community/Navbar-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1737115705000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","gxcuf89792":"Tech Community","external-1":"Events","s-m-b":"Small and Medium Businesses","windows-server":"Windows Server","education-sector":"Education Sector","driving-adoption":"Driving Adoption","microsoft-learn":"Microsoft Learn","s-q-l-server":"SQL Server","partner-community":"Microsoft Partner Community","microsoft365":"Microsoft 365","external-9":".NET","external-8":"Teams","external-7":"Github","products-services":"Products","external-6":"Power Platform","communities-1":"Topics","external-5":"Microsoft Security","planner":"Planner","external-4":"Microsoft 365","external-3":"Dynamics 365","azure":"Azure","healthcare-and-life-sciences":"Healthcare and Life Sciences","external-2":"Azure","microsoft-mechanics":"Microsoft Mechanics","microsoft-learn-1":"Community","external-10":"Learning Room Directory","microsoft-learn-blog":"Blog","windows":"Windows","i-t-ops-talk":"ITOps Talk","external-link-1":"View All","microsoft-securityand-compliance":"Microsoft Security","public-sector":"Public Sector","community-info-center":"Lounge","external-link-2":"View All","microsoft-teams":"Microsoft Teams","external":"Blogs","microsoft-endpoint-manager":"Microsoft Intune and Configuration Manager","startupsat-microsoft":"Startups at Microsoft","exchange":"Exchange","a-i":"AI and Machine Learning","io-t":"Internet of Things (IoT)","outlook":"Outlook","external-link":"Community Hubs","communities":"Products"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1737115705000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1737115705000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1737115705000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1737115705000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1737115705000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewStandard-1737115705000","value":{"anonymous":"Anonymous","author":"{messageAuthorLogin}","authorBy":"{messageAuthorLogin}","board":"{messageBoardTitle}","replyToUser":" to {parentAuthor}","showMoreReplies":"Show More","replyText":"Reply","repliesText":"Replies","markedAsSolved":"Marked as Solved","movedMessagePlaceholder.BLOG":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.TKB":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.FORUM":"{count, plural, =0 {This reply has been} other {These replies have been} }","movedMessagePlaceholder.IDEA":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.OCCASION":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholderUrlText":"moved.","messageStatus":"Status: ","statusChanged":"Status changed: {previousStatus} to {currentStatus}","statusAdded":"Status added: {status}","statusRemoved":"Status removed: {status}","labelExpand":"expand replies","labelCollapse":"collapse replies","unhelpfulReason.reason1":"Content is outdated","unhelpfulReason.reason2":"Article is missing information","unhelpfulReason.reason3":"Content is for a different Product","unhelpfulReason.reason4":"Doesn't match what I was searching for"},"localOverride":false},"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/ThreadedReplyList-1737115705000","value":{"title":"{count, plural, one{# Reply} other{# Replies}}","title@board:BLOG":"{count, plural, one{# Comment} other{# Comments}}","title@board:TKB":"{count, plural, one{# Comment} other{# Comments}}","title@board:IDEA":"{count, plural, one{# Comment} other{# Comments}}","title@board:OCCASION":"{count, plural, one{# Comment} other{# Comments}}","noRepliesTitle":"No Replies","noRepliesTitle@board:BLOG":"No Comments","noRepliesTitle@board:TKB":"No Comments","noRepliesTitle@board:IDEA":"No Comments","noRepliesTitle@board:OCCASION":"No Comments","noRepliesDescription":"Be the first to reply","noRepliesDescription@board:BLOG":"Be the first to comment","noRepliesDescription@board:TKB":"Be the first to comment","noRepliesDescription@board:IDEA":"Be the first to comment","noRepliesDescription@board:OCCASION":"Be the first to comment","messageReadOnlyAlert:BLOG":"Comments have been turned off for this post","messageReadOnlyAlert:TKB":"Comments have been turned off for this article","messageReadOnlyAlert:IDEA":"Comments have been turned off for this idea","messageReadOnlyAlert:FORUM":"Replies have been turned off for this discussion","messageReadOnlyAlert:OCCASION":"Comments have been turned off for this event"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyCallToAction-1737115705000","value":{"leaveReply":"Leave a reply...","leaveReply@board:BLOG@message:root":"Leave a comment...","leaveReply@board:TKB@message:root":"Leave a comment...","leaveReply@board:IDEA@message:root":"Leave a comment...","leaveReply@board:OCCASION@message:root":"Leave a comment...","repliesTurnedOff.FORUM":"Replies are turned off for this topic","repliesTurnedOff.BLOG":"Comments are turned off for this topic","repliesTurnedOff.TKB":"Comments are turned off for this topic","repliesTurnedOff.IDEA":"Comments are turned off for this topic","repliesTurnedOff.OCCASION":"Comments are turned off for this topic","infoText":"Stop poking me!"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1737115705000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1737115705000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCoverImage-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCoverImage-1737115705000","value":{"coverImageTitle":"Cover Image"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeTitle-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeTitle-1737115705000","value":{"nodeTitle":"{nodeTitle, select, community {Community} other {{nodeTitle}}} "},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTimeToRead-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTimeToRead-1737115705000","value":{"minReadText":"{min} MIN READ"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1737115705000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1737115705000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserRank-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserRank-1737115705000","value":{"rankName":"{rankName}","userRank":"Author rank {rankName}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1737115705000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1737115705000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCustomFields-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCustomFields-1737115705000","value":{"CustomField.default.label":"Value of {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRevision-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRevision-1737115705000","value":{"lastUpdatedDatePublished":"{publishCount, plural, one{Published} other{Updated}} {date}","lastUpdatedDateDraft":"Created {date}","version":"Version {major}.{minor}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1737115705000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyButton-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyButton-1737115705000","value":{"repliesCount":"{count}","title":"Reply","title@board:BLOG@message:root":"Comment","title@board:TKB@message:root":"Comment","title@board:IDEA@message:root":"Comment","title@board:OCCASION@message:root":"Comment"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageAuthorBio-1737115705000","value":{"sendMessage":"Send Message","actionMessage":"Follow this blog board to get notified when there's new activity","coAuthor":"CO-PUBLISHER","contributor":"CONTRIBUTOR","userProfile":"View Profile","iconlink":"Go to {name} {type}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1737115705000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/ranks/UserRankLabel-1737115705000","value":{"altTitle":"Icon for {rankName} rank"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserRegistrationDate-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserRegistrationDate-1737115705000","value":{"noPrefix":"{date}","withPrefix":"Joined {date}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeAvatar-1737115705000","value":{"altTitle":"Node avatar for {nodeTitle}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeDescription-1737115705000","value":{"description":"{description}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagView/TagViewChip-1737115705000","value":{"tagLabelName":"Tag name {tagName}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1737115705000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1737115705000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false}}}},"page":"/blogs/BlogMessagePage/BlogMessagePage","query":{"boardId":"iotblog","messageSubject":"azure-percept-audio---home-automation-with-azure-functions-azure-iot-hub-and-ras","messageId":"2528048"},"buildId":"_FASV5DDw52YaqfBDLqsB","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"o365","openTelemetryServiceVersion":"24.11.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/customComponent/CustomComponent/CustomComponent.tsx","./components/blogs/BlogArticleWidget/BlogArticleWidget.tsx","./components/external/components/ExternalComponent.tsx","./components/messages/MessageView/MessageViewStandard/MessageViewStandard.tsx","./components/messages/ThreadedReplyList/ThreadedReplyList.tsx","../shared/client/components/common/List/UnwrappedList/UnwrappedList.tsx","./components/tags/TagView/TagView.tsx","./components/tags/TagView/TagViewChip/TagViewChip.tsx"],"appGip":true,"scriptLoader":[{"id":"analytics","src":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/pagescripts/1729284608000/analytics.js?page.id=BlogMessagePage&entity.id=board%3Aiotblog&entity.id=message%3A2528048","strategy":"afterInteractive"}]}