<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coding Bandit</title>
	<atom:link href="https://codingbandit.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://codingbandit.com/blog</link>
	<description></description>
	<lastBuildDate>Sat, 04 Sep 2021 14:47:19 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.3.6</generator>
	<item>
		<title>A step back into normalcy – DevIntersection Spring 2021</title>
		<link>https://codingbandit.com/blog/2021/09/04/a-step-back-into-normalcy-devintersection-spring-2021/</link>
				<comments>https://codingbandit.com/blog/2021/09/04/a-step-back-into-normalcy-devintersection-spring-2021/#respond</comments>
				<pubDate>Sat, 04 Sep 2021 14:47:17 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=360</guid>
				<description><![CDATA[2021 DevIntersection review and being comfortable attending a conference during COVID.]]></description>
								<content:encoded><![CDATA[
<p>Earlier this year, I ventured on to my favorite travel site and booked flight tickets for the first time in almost two years. It didn&#8217;t feel real, and I lacked confidence that the trip would even happen, given the COVID-19 pandemic. The event I was traveling to was the spring <a href="https://www.devintersection.com">DevIntersection</a> conference in Orlando, FL, between June 8<sup>th</sup> and 10<sup>th</sup>, 2021.</p>



<p>As the days crept on, I prepared my talks and IoT devices, pulled out my travel laptop, and dusted it off. Windows then proceeded to install updates over the next 12 hours. A few days before my flight, reality set in that this trip was going to happen. My anxiety was pretty high with fear of unknowns such as how will we all be safe, keep a distance, how many people will be there, how often will surfaces be cleaned, among many other concerns. Upon arrival, all of my concerns subsided as there were mask mandates, social distancing, and a superb Disney cast keeping on top of sanitizing rooms and common areas. The DevIntersection group planned this event perfectly, and I could then redirect my focus to the event&#8217;s purpose, learning about technology.</p>



<p>My learning goals were to attend sessions on security, infrastructure, and Infrastructure as Code topics. A few sessions that stood out to me were the following:</p>



<ul><li>Azure Sentinel, by Chris Givens. In this session, I learned about Azure Sentinel and how it works alongside built-in machine learning to identify changes in user behavior patterns. I also enjoyed experiencing the Sentinel user interface that generates graph visualizations as an intuitive method of investigating the root cause of security incidents.&nbsp; (image from: <a href="https://docs.microsoft.com/en-us/azure/sentinel/overview">What is Azure Sentinel? | Microsoft Docs</a>)</li></ul>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2021/09/sentineldevint-1024x382.png" alt="Sentinel User Interface displaying a graph representation of security incidents." class="wp-image-361" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/09/sentineldevint-1024x382.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2021/09/sentineldevint-300x112.png 300w, https://codingbandit.com/blog/wp-content/uploads/2021/09/sentineldevint-768x286.png 768w, https://codingbandit.com/blog/wp-content/uploads/2021/09/sentineldevint.png 1430w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Sentinel User Interface</figcaption></figure>



<ul><li>Master your Terraform deployments with Azure DevOps, by Jim Counts. This session was my first introduction to Terraform. I learned about syntax, variables, the <a href="https://docs.microsoft.com/en-us/azure/developer/terraform/overview">Terraform Azure provider</a>, and testing strategies when it comes to authoring Terraform for deployments in Azure. After this session, I feel I have the information and confidence to begin authoring my own Terraform deployments in Azure, check them into source control, and leverage them in Azure DevOps pipelines.</li><li>Running AKS in production, by Dan Patrick. This session brought real-world experiences and lessons learned to the forefront. The content covered infrastructure, networking, security, and DevOps. The candid nature of Dan explaining some of the problems encountered on projects could save others a lot of headaches and time. I like how the abstract for the session reads: &#8220;Our pain, your gain.&#8221; Dan provided guidance on best practices for deployments, Azure DevOps and Terraform deployments, and securing AKS. I enjoyed the conversation back and forth between Dan and his colleague Jim Counts who was also in the audience for this presentation – many more experiences were unearthed as part of those conversations. There were so many valuable points and recommended guidance presented in this session. I would love to see its content made available as a series of documentation written as a reference.</li></ul>



<p>My sessions for this event were IoT-focused. I presented on four IoT topics and participated in a closing panel discussion on the final day of the conference. My sessions were:</p>



<ul><li>Introduction to Azure Sphere. In this session, I explained the reasoning behind the Azure Sphere platform. I described the <a href="https://www.microsoft.com/en-us/research/uploads/prod/2020/11/Seven-Properties-of-Highly-Secured-Devices-2nd-Edition-R1.pdf">seven properties of a highly secured IoT device</a> and how the Azure Sphere platform satisfies those properties. I explained how to claim a device, obtain proper certificate authentication, and add a device to an enrollment group. I then reviewed a simple C program used to define a product for a device group. This program was then cloud-deployed to the Azure Sphere that I had on my desk.</li><li>Living on the Edge. In this session, I reviewed the different types of IoT Edge devices and IoT Edge gateways. We walked through defining an IoT Edge device in IoT Hub. Using a Raspberry Pi 4 device, we used apt-get, and a trusted Microsoft feed to complete the installation and configuration of the Pi 4 device. We then walked through creating an IoT Edge module in C#, building and uploading the module to the Azure Container registry. In IoT Hub, we configured the module to be deployed to the IoT Edge device we registered: the Raspberry Pi 4 device.</li><li>Using Azure IoT Central to form a basis for your IoT Solutions. In this session, I reviewed the Software as a Service (Saas) offering of IoT Central. I listed out some pros and cons of having this type of solution. While it is closed source and hides much of the underlying IoT infrastructure resources, such as Stream Analytics, IoT Hub, Device Provisioning Service (DPS), and Time Series Insights. I demonstrated multiple ways of extending IoT Central to benefit from its SaaS web portal interface, customizability, dashboarding, and analytics – and still enable more complicated scenarios and downstream processing, consistent with more mature IoT solutions. I demonstrated Continuous Data Export to a service bus queue and triggered a Power Automate flow when an alert (rule) is activated based on the data ingested.</li><li>IoT State of the Union. In this session, we reviewed the Azure Internet of Things Platform. We covered the products and services expected in IoT solution architectures today and their roles in the overall solution. We covered concepts relating to IoT Hub/DPS and when it makes sense to kick start a solution using IoT Central. We also covered some of the new features surrounding Azure Digital Twins. We discussed multiple areas where Device Twin Definition Language (DTDL) is used, including device twins, module twins, and device capability models (IoT Plug &amp; Play).</li><li>Closing panel. I had the opportunity to discuss the impacts of COVID-19 on technology careers with our host, Jeff Fritz, and friends Sara Faatz and Sam Basu. We talked about how various companies and employees adjusted and overcame obstacles related to such drastic changes in the work environment. We also discussed how DevIntersection is leading the pack when it comes to returning to in-person learning. Hybrid or online learning is valuable, but in-person learning provides the additional benefit of hallway conversations and connections with others.</li></ul>



<p>As I reflect on the spring 2021 edition of DevIntersection, I am motivated to attend the fall DevIntersection event in December (7<sup>th</sup>-9<sup>th</sup>, 2021). This event was comfortable and very well-done. I am looking forward to adding more in-person learning opportunities in my steps to getting back to normalcy.</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2021/09/04/a-step-back-into-normalcy-devintersection-spring-2021/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>How a Microsoft Learn Challenge helped me pass the AI-102 certification exam</title>
		<link>https://codingbandit.com/blog/2021/05/30/how-a-microsoft-learn-challenge-helped-me-pass-the-ai-102-certification-exam/</link>
				<comments>https://codingbandit.com/blog/2021/05/30/how-a-microsoft-learn-challenge-helped-me-pass-the-ai-102-certification-exam/#respond</comments>
				<pubDate>Mon, 31 May 2021 00:25:31 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Certification]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Training]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=350</guid>
				<description><![CDATA[How a Microsoft Learn Challenge helped me pass the AI-102 certification exam.]]></description>
								<content:encoded><![CDATA[Earlier this month, I was given the opportunity to participate in the MVP Global Cloud Skills Challenge. Who&nbsp; doesn&#8217;t like a challenge, right? I decided to focus on the Data and AI challenge because I want to keep my Azure AI skills up-to-date in this fast-paced technology field. These skills are essential to me, as I spend most of my work days in the data and machine learning world, and pull in AI technologies as needed on various projects.

<!-- /wp:paragraph --><!-- wp:paragraph -->

<!-- wp:image {"id":355,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img class="wp-image-355" src="https://codingbandit.com/blog/wp-content/uploads/2021/05/challengeacceptedkey_wide.jpg" alt="Take the Challenge key on a keyboard" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/05/challengeacceptedkey_wide.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2021/05/challengeacceptedkey_wide-300x167.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2021/05/challengeacceptedkey_wide-768x428.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Take the challenge</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->

The Data and AI challenge was for a limited time; therefore, it wasn&#8217;t something I could put off and procrastinate. As I worked through the learning path, I enjoyed the completeness of the content and the analogies presented to understand rather complicated topics. &nbsp;The visuals and the knowledge checks gave me the confidence that I was interpreting the concepts correctly. The hands-on exercises allowed me to get acquainted with updated user interfaces, new features and increase my comfort level with the cloud shell.

<!-- /wp:paragraph -->

<!-- wp:paragraph -->

Not going to lie, it was very motivating to see the leader board fill up with people that had already completed the challenge, I wanted to see my name there as well. I ended up completing all 42 modules in this challenge in about a week. I absolutely love that there were <a href="https://en.wikipedia.org/wiki/42_(number)" target="_blank" rel="noreferrer noopener">42</a> modules in this challenge <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" />

<!-- /wp:paragraph -->

<!-- wp:image {"id":351,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img class="wp-image-351" src="https://codingbandit.com/blog/wp-content/uploads/2021/05/leaderboard.png" alt="MVP leader board" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/05/leaderboard.png 990w, https://codingbandit.com/blog/wp-content/uploads/2021/05/leaderboard-300x265.png 300w, https://codingbandit.com/blog/wp-content/uploads/2021/05/leaderboard-768x679.png 768w" sizes="(max-width: 990px) 100vw, 990px" />

<figcaption>Data and AI Challenge Leaderboard</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->

Part of the challenge included learning more about digital accessibility. As a dyslexic person, I enjoyed seeing the focus Microsoft is putting on this area. One of the things that I am incredibly uncomfortable with is taking timed exams. However, after completing four modules centering around accessibility, I decided that I could attempt a certification exam, and if necessary, Microsoft would provide accommodations for my dyslexia. I reviewed <a href="https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE4MbYD" target="_blank" rel="noreferrer noopener">the skills outline for exam AI-102: Designing and Implementing a Microsoft Azure AI Solution</a> and discovered that this exam&#8217;s requirements were covered in the Data and AI Cloud Skills Challenge that I had just completed. I promptly scheduled the exam for the following week before I could chicken out.

<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":352,"width":300,"height":401,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img class="wp-image-352" src="https://codingbandit.com/blog/wp-content/uploads/2021/05/chickenscared.png" alt="Scared cartoon chicken" width="300" height="401" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/05/chickenscared.png 600w, https://codingbandit.com/blog/wp-content/uploads/2021/05/chickenscared-225x300.png 225w" sizes="(max-width: 300px) 100vw, 300px" />

<figcaption>Chicken</figcaption></figure>
</div>
<!-- /wp:image -->

<!-- wp:paragraph -->

In the few days I had before taking the exam, I revisited some of the learning modules and augmented this knowledge with reading some documentation. Exam day arrived and even though I was confident in the topics that would be covered in the exam, I was extremely anxious about the process of taking the test. After about the first 15 minutes, I started to relax &#8211; I ended up with plenty of time to review the questions twice. Upon completion of the exam &#8211; the testing software immediately informed me that I had passed. I am now a <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-engineer/" target="_blank" rel="noreferrer noopener">Microsoft Certified AI Engineer Associate</a>.

<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":353,"width":300,"height":300,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img class="wp-image-353" src="https://codingbandit.com/blog/wp-content/uploads/2021/05/azure-ai-engineer.png" alt="Microsoft Certified Azure AI Engineer Associate" width="300" height="300" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/05/azure-ai-engineer.png 600w, https://codingbandit.com/blog/wp-content/uploads/2021/05/azure-ai-engineer-300x300.png 300w, https://codingbandit.com/blog/wp-content/uploads/2021/05/azure-ai-engineer-150x150.png 150w" sizes="(max-width: 300px) 100vw, 300px" />

<figcaption>Microsoft Certified Azure AI Engineer Associate</figcaption></figure>
</div>
<!-- /wp:image -->

<!-- wp:paragraph -->

Obtaining this certification paved the way for another opportunity. I have been preparing class content and delivering training on Microsoft technologies on a regular basis for the past couple of years. With the confirmation of my training experience, I was able to enroll as a <a href="https://docs.microsoft.com/en-us/learn/certifications/mct-certification" target="_blank" rel="noreferrer noopener">Microsoft Certified Trainer</a> &#8211; a &#8220;one day&#8221; goal that I had set for myself years ago &#8211; that &#8220;one day&#8221; ended up being May 13th, 2021.

<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":354,"width":300,"height":300,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img class="wp-image-354" src="https://codingbandit.com/blog/wp-content/uploads/2021/05/MCT-Microsoft_Certified_Trainer.png" alt="Microsoft Certified Trainer 2021-2022" width="300" height="300" srcset="https://codingbandit.com/blog/wp-content/uploads/2021/05/MCT-Microsoft_Certified_Trainer.png 600w, https://codingbandit.com/blog/wp-content/uploads/2021/05/MCT-Microsoft_Certified_Trainer-300x300.png 300w, https://codingbandit.com/blog/wp-content/uploads/2021/05/MCT-Microsoft_Certified_Trainer-150x150.png 150w" sizes="(max-width: 300px) 100vw, 300px" />

<figcaption>Microsoft Certified Trainer 2021-2022</figcaption></figure>
</div>
<!-- /wp:image -->

<!-- wp:paragraph -->

I nominate you, dear reader &#8211; to follow the same path as I did to take the AI-102 exam &#8211; here is a link to a collection of modules that I used in order to prepare: <a href="https://docs.microsoft.com/en-us/users/codingbandit/collections/mppgagdow78zq8?WT.mc_id=AI-MVP-5003966" target="_blank" rel="noreferrer noopener">AI-102 Exam Prep Learning Collection</a>. Happy Learning !!

<!-- /wp:paragraph -->

<!-- wp:paragraph -->

#TheMVPChallenge

<!-- /wp:paragraph -->]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2021/05/30/how-a-microsoft-learn-challenge-helped-me-pass-the-ai-102-certification-exam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Controlling an LED from the cloud using a C# Azure IoT Edge module on the Raspberry Pi</title>
		<link>https://codingbandit.com/blog/2020/12/01/controlling-an-led-from-the-cloud-using-a-c-azure-iot-edge-module-on-the-raspberry-pi/</link>
				<comments>https://codingbandit.com/blog/2020/12/01/controlling-an-led-from-the-cloud-using-a-c-azure-iot-edge-module-on-the-raspberry-pi/#respond</comments>
				<pubDate>Tue, 01 Dec 2020 07:03:32 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Raspberry Pi]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=320</guid>
				<description><![CDATA[This post expects that you have created an Azure IoT Edge device and have it registered with an existing IoT Hub (free or standard...]]></description>
								<content:encoded><![CDATA[
<blockquote class="wp-block-quote"><p>This post expects that you have created an Azure IoT Edge device and have it registered with an existing IoT Hub (free or standard tier). If you need some help with this, see this <a rel="noreferrer noopener" href="https://codingbandit.com/blog/2020/10/10/setting-up-a-pi-4-as-an-azure-edge-device/" target="_blank">blog post</a>.</p></blockquote>



<p>This article is part of <a href="https://www.csadvent.christmas/" target="_blank" rel="noreferrer noopener">The Fourth Annual C# Advent Calendar</a> initiative by <a href="https://twitter.com/mgroves" target="_blank" rel="noreferrer noopener">Matthew D. Groves</a>. You&#8217;ll find other helpful articles and tutorials published daily by community members and experts there, so make sure to check it out every day.</p>



<p>Azure IoT Edge modules are deployed to devices as Docker containers. In this article we will create an Azure IoT Edge module to control an LED that is connected to the Raspberry Pi.</p>



<h2>Wiring</h2>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_fritzing.jpg" alt="Wiring diagram" class="wp-image-326" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_fritzing.jpg 514w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_fritzing-300x219.jpg 300w" sizes="(max-width: 514px) 100vw, 514px" /></figure>



<p>In this diagram, we will connect the Raspberry PI GPIO7 pin to a 100 ohm resistor. Connect the other end of the resistor to the the cathode (+ve, long leg) of the LED. The anode of the LED (-ve, short leg) will be connected to the Raspberry PI ground (GND).</p>



<h2>Create a Container Registry </h2>



<p>Login to the Azure Portal and navigate to the resource group that contains your IoT Hub. From the top toolbar, select the <strong>+ Add </strong>button.</p>



<p>In the Marketplace search box, search for <strong>Container Registry</strong>, and select it from the search results. Select <strong>Create</strong> on the resource overview screen.</p>



<p>In the <strong>Create container registry</strong> form, give the registry a globally unique name and ensure it is located in the appropriate region. You can select the Basic SKU. Select the <strong>Review + create</strong> button, then after validation passes, select <strong>Create</strong>.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_createcontainerregistry-1024x702.jpg" alt="Create container registry form" class="wp-image-322" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_createcontainerregistry-1024x702.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_createcontainerregistry-300x206.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_createcontainerregistry-768x527.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_createcontainerregistry.jpg 1257w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Navigate to the container registry resource once it&#8217;s deployed. From the left menu, select <strong>Access keys</strong>, then enable the <strong>Admin user</strong> switch. Make note of the <strong>Login server</strong>, <strong>Username</strong> and <strong>password</strong> values.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_repositoryadmin-1024x389.jpg" alt="Container registry Access Keys" class="wp-image-323" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_repositoryadmin-1024x389.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_repositoryadmin-300x114.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_repositoryadmin-768x292.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_repositoryadmin.jpg 1245w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2>Creating the Azure IoT Edge Module</h2>



<p>You have the choice to create the Azure IoT Edge module using Visual Studio or Visual Studio Code. In this case, I will be using Visual Studio Code. The pre-requisites needed are the following:</p>



<ul><li><a rel="noreferrer noopener" href="https://code.visualstudio.com/" target="_blank">Visual Studio Code</a></li><li><a href="https://dotnet.microsoft.com/download/dotnet-core/3.1" target="_blank" rel="noreferrer noopener">.Net Core 3.1 SDK</a></li><li><a rel="noreferrer noopener" href="https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp" target="_blank">C# for Visual Studio Code extension</a></li><li><a rel="noreferrer noopener" href="https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools" target="_blank">Azure IoT Tools for Visual Studio Code extension</a></li><li><a rel="noreferrer noopener" href="https://hub.docker.com/editions/community/docker-ce-desktop-windows/" target="_blank">Docker Desktop Community</a></li></ul>



<p>Create a folder where you would like the project to be created. Then open Visual Studio Code.</p>



<p>We will use the command palette to scaffold the project. Use CTRL+SHIFT+P to open the palette. First, login to Azure using the <strong>Azure: Sign in</strong> command. Next, execute the following command: <strong>Azure IoT Edge: New IoT Edge solution</strong>. In executing this command, you will be prompted for the following:</p>



<ul><li>Folder where you&#8217;d like the solution created</li><li>The solution name</li><li>The module template (select C#)</li><li>The module name (LightControl)</li><li>The Docker image repository with the module name (registryloginserver.azurecr.io/lightcontrol)</li></ul>



<p>Once the solution has been scaffolded, open the <strong>.env</strong> file, and add the <strong>CONTAINER_REGISTRY_USERNAME</strong> and <strong>CONTAINER_REGISTRY_PASSWORD </strong>values with those that you recorded from the Access keys section of the container registry.</p>



<p>Open a Terminal window (Powershell), and change directory into the modules/LightControl folder. Execute the following command to add GPIO support to our module:</p>



<pre class="wp-block-code"><code>dotnet add System.Device.GPIO</code></pre>



<p>Open the <strong>modules\LightControl\Program.cs </strong>file and replace it with the following code listing (commented inline):</p>



<pre class="wp-block-code"><code>namespace LightControl
{
    using System;   
    using System.Runtime.Loader;    
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.Devices.Client.Transport.Mqtt;
    using System.Device.Gpio;

    class Program
    {
        static int ledpin = 7; //GPIO 7
        static GpioController controller;

        static void Main(string&#91;] args)
        {
            Init().Wait();

            // Wait until the app unloads or is cancelled
            var cts = new CancellationTokenSource();
            AssemblyLoadContext.Default.Unloading += (ctx) =&gt; cts.Cancel();
            Console.CancelKeyPress += (sender, cpe) =&gt; cts.Cancel();
            WhenCancelled(cts.Token).Wait();
        }

        /// &lt;summary&gt;
        /// Handles cleanup operations when app is cancelled or unloads
        /// &lt;/summary&gt;
        public static Task WhenCancelled(CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource&lt;bool&gt;();
            cancellationToken.Register(s =&gt; ((TaskCompletionSource&lt;bool&gt;)s).SetResult(true), tcs);
            return tcs.Task;
        }

        /// &lt;summary&gt;
        /// Initializes the ModuleClient and sets up the callback to receive
        /// direct method calls from the IoT Hub
        /// &lt;/summary&gt;
        static async Task Init()
        {
            MqttTransportSettings mqttSetting = new MqttTransportSettings(TransportType.Mqtt_Tcp_Only);
            ITransportSettings&#91;] settings = { mqttSetting };

            // Open a connection to the Edge runtime
            ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
            await ioTHubModuleClient.OpenAsync();
            Console.WriteLine("IoT Hub module client initialized.");
         
            //setup direct method handler 
            await ioTHubModuleClient.SetMethodDefaultHandlerAsync(DirectMethodCalled, ioTHubModuleClient);
            controller = new GpioController();
            controller.OpenPin(ledpin, PinMode.Output);
            Console.WriteLine("Initialized GPIO and listening for direct method call");

        }
        private static Task&lt;MethodResponse&gt; DirectMethodCalled(MethodRequest methodRequest, object userContext)
        {
            var data = Encoding.UTF8.GetString(methodRequest.Data);
            Console.WriteLine(data);
                      
           string result = "{\"result\":\"Executed direct method: " + methodRequest.Name + "\"}";

           switch(methodRequest.Name) {
               case "ON":
                    // Turn on the LED                    
                    controller.Write(ledpin, PinValue.High);
                    Console.WriteLine("LED SHOULD BE ON NOW");
                    break;
               case "OFF":
                    // Turn off the LED
                    controller.Write(ledpin, PinValue.Low);
                    Console.WriteLine("LED SHOULD BE OFF NOW");
                    break;
               default:
                    Console.WriteLine("Unknown method");
                    break;                   
           }
           //Acknowledge the receipt of the direct method call
           return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200));
           
        }

    }
}</code></pre>



<p>Next, open the <strong>modules\LightControl\Dockerfile.arm32v7</strong> file. Replace ONLY the first line of the file with the following (this will allow us to build the Linux based container on Windows):</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env</code></pre>



<h2>Build and push the LightControl module</h2>



<p>Open the Command Palette once again, and execute the <strong>Azure IoT Edge: Build and Push IoT Edge Module Image</strong>. This command will publish our build to our Azure Container Registry. You can expect the following prompts:</p>



<ul><li>Select module config file (select the modules\LightControl\module.json file)</li><li>Select Platform (select arm32v7)</li></ul>



<p>Once the build has completed. Locate in the output the line that starts with <strong>Successfully tagged</strong>. Record the tag value. It should look something similar to: <strong>yourcontainerregistry.azurecr.io/lightcontrol:0.0.1-arm32v7</strong></p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_successfullytagged-1024x358.jpg" alt="Build output" class="wp-image-327" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_successfullytagged-1024x358.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_successfullytagged-300x105.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_successfullytagged-768x268.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_successfullytagged.jpg 1411w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2>Add the module to be deployed to the Edge device</h2>



<p>In the Azure Portal, navigate to your IoT Hub. From the left menu, select <strong>IoT Edge</strong> located in the <strong>Automatic Device Management</strong> section. From there, select your edge device from the list. Select<strong> Set modules</strong> from the top toolbar menu.</p>



<p>On the <strong>Set modules</strong> on device page, fill out the<strong> Container Registry Credentials</strong> section at the top of the form with the values you recorded when creating the registry.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-1024x131.jpg" alt="The Container Registry Credentials section" class="wp-image-325" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-1024x131.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-300x39.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-768x99.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-1536x197.jpg 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/11/csadvent_modulerepositorycreds-2048x263.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>In the <strong>IoT Edge Modules</strong> section, expand the <strong>+ Add</strong> drop down and select <strong>IoT Edge Module</strong>.</p>



<p>Enter <strong>LightControl </strong>as the Module Name, and with the <strong>Module Settings</strong> tab selected, paste the tag value that you recorded earlier (similar to <strong>yourcontainerregistry.azurecr.io/lightcontrol:0.0.1-arm32v7</strong>). </p>



<p>Select the <strong>Container Create Options</strong> tab, and paste the following JSON. This will allow the Docker container we deploy access to the GPIO pins.</p>



<pre class="wp-block-code"><code>{
    "HostConfig": {
        "Privileged": true
    }
}</code></pre>



<p>Select the <strong>Add</strong> button, to add this module to the list.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_modulesettings.jpg" alt="Module settings tab" class="wp-image-328" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_modulesettings.jpg 1017w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_modulesettings-300x230.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_modulesettings-768x588.jpg 768w" sizes="(max-width: 1017px) 100vw, 1017px" /></figure>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_containercreateoptions-1024x964.jpg" alt="Container Create Options" class="wp-image-329" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_containercreateoptions-1024x964.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_containercreateoptions-300x283.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_containercreateoptions-768x723.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_containercreateoptions.jpg 1049w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>You should now be back on the <strong>Set modules on device </strong>screen. Select <strong>Review + create</strong>, then <strong>Create</strong> once validation has passed.  This will return you to the <strong>Edge Device</strong> screen. Give the deployment a minute or two to reach your device, then select the <strong>Refresh</strong> button from the top toolbar. You should see<strong> LightControl</strong> listed as a module and reported by the device. Stay on this screen &#8211; we&#8217;ll be needing it momentarily.</p>



<h2>Control the LED with a Direct Method call</h2>



<p>Open a command prompt, and SSH into your Edge device. Once logged in execute the following command:</p>



<pre class="wp-block-code"><code>sudo iotedge logs -f LightControl</code></pre>



<p>This command will show the console output of our module. Keep this window visible while you return to the Azure Portal Edge Device Screen. From the Modules list, select the<strong> LightControl</strong> module. This will open the <strong>Details</strong> screen for our LightControl Edge module. From the top toolbar, select the <strong>Direct method</strong> item.</p>



<p>On the Direct method form, for Method Name, you can enter the value <strong>ON</strong> or <strong>OFF</strong>. In the Payload field, you can optionally send additional information to the module direct method handler. Invoke the method by selecting the Invoke Method button from the top toolbar.</p>



<p>In my example, I called the method <strong>ON</strong> and passed in the payload JSON of: <strong>{ &#8220;Initiator&#8221;: &#8220;CSAdvent&#8221; }</strong></p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_invokedirectmethod.jpg" alt="Invoke direct method" class="wp-image-330" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_invokedirectmethod.jpg 875w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_invokedirectmethod-297x300.jpg 297w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_invokedirectmethod-768x777.jpg 768w" sizes="(max-width: 875px) 100vw, 875px" /></figure>



<p>Once invoked, you should see your LED turn on! Not only that, but looking in your SSH window, you will see the console output that the light should be on.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_consoleoutput.jpg" alt="Console output showing the light is on." class="wp-image-331" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_consoleoutput.jpg 581w, https://codingbandit.com/blog/wp-content/uploads/2020/12/csadvent_consoleoutput-300x46.jpg 300w" sizes="(max-width: 581px) 100vw, 581px" /></figure>



<p>Feel free to invoke the <strong>OFF</strong> method and watch the LED and the console output.</p>



<h2>Wrapping up!</h2>



<p>I hope that this article helps demonstrate how to control GPIO pins from an Azure IoT Edge module. Enjoy the rest of the C# Advent series!</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2020/12/01/controlling-an-led-from-the-cloud-using-a-c-azure-iot-edge-module-on-the-raspberry-pi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Setting up a Pi 4 as an Azure Edge Device</title>
		<link>https://codingbandit.com/blog/2020/10/10/setting-up-a-pi-4-as-an-azure-edge-device/</link>
				<comments>https://codingbandit.com/blog/2020/10/10/setting-up-a-pi-4-as-an-azure-edge-device/#respond</comments>
				<pubDate>Sat, 10 Oct 2020 23:04:24 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Raspberry Pi]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=285</guid>
				<description><![CDATA[Preamble: I started writing this blog post based on a Twitch stream that I had back in March 2020. A lot has happened since...]]></description>
								<content:encoded><![CDATA[
<p>Preamble: I started writing this blog post based on a Twitch stream that I had back in March 2020. A lot has happened since then as we all know. That being said, I am so happy to finally get back to finishing this one out!</p>



<p>I have been chomping at the bit to get myself a Pi 4 device. Of course I went with the 4 GB version. I landed on buying a <a rel="noreferrer noopener" href="https://smile.amazon.com/gp/product/B07VFCB192/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&amp;psc=1" target="_blank">Vilros starter kit on Amazon</a>. I like that you can get (pretty much) everything you need in a single box.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros-1024x799.png" alt="Vilros Pi 4 Kit" class="wp-image-286" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros-1024x799.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros-300x234.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros-768x599.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros-1536x1198.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/03/vilros.png 1620w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Vilros Pi 4 Kit</figcaption></figure>



<p>The first thing I wanted to do is to make this thing into an Azure Edge device, so that I can easily deploy container-based applications remotely from IoT Hub and to act as a device gateway in my home (among other things).</p>



<h2>Imaging the Operating System</h2>



<p>I decided to use Raspbian Buster as the OS even though it is considered a <a rel="noreferrer noopener" href="https://docs.microsoft.com/en-us/azure/iot-edge/support" target="_blank">tier 2 operating system</a>. You can obtain the Raspbian Buster image from the <a rel="noreferrer noopener" href="https://www.raspberrypi.org/downloads/raspbian/" target="_blank">Raspberry Pi website</a>. I am running Windows, so I downloaded the Zip file for<strong> Raspbian Buster with desktop</strong> item. Please note, that for some reason, I needed to download this at least twice, because the file was corrupting somehow in transit [this was not an issue in October 2020]. Also, using <a rel="noreferrer noopener" href="https://www.7-zip.org/" target="_blank">7-Zip</a> is recommended as the unzip utility over the built-in Windows zip file extractor.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-1024x1018.png" alt="Raspbian Buster with desktop download." class="wp-image-287" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-1024x1018.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-300x298.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-150x150.png 150w, https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-768x763.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload-1536x1527.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/03/raspbianbusterdownload.png 1682w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Raspbian Buster with desktop download.</figcaption></figure>



<p>With the zip file extracted, I inserted the micro-SD card into my card reader and flashed the operating system image on it using the <a rel="noreferrer noopener" href="https://www.balena.io/etcher/" target="_blank">Balena Etche</a>r tool.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/03/balenaetchertool.png" alt="Balena Etcher Tool" class="wp-image-289" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/03/balenaetchertool.png 796w, https://codingbandit.com/blog/wp-content/uploads/2020/03/balenaetchertool-300x180.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/03/balenaetchertool-768x461.png 768w" sizes="(max-width: 796px) 100vw, 796px" /><figcaption>Balena Etcher Tool</figcaption></figure>



<p>While the OS is being imaged, cancel out of any Windows drive popups that surface.</p>



<h2>Configuring Raspbian Buster</h2>



<p>Insert the micro-sd card into the Raspberry Pi. Then connect a screen, mouse, keyboard, and network cable. Power on the device and wait for it to boot up.</p>



<p>On the welcome screen, be sure to note the IP address of the device &#8211; and continue setting up the Pi using your desired settings. It is equally important to remember the password you enter for the <strong>pi</strong> user.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image2-1024x768.jpg" alt="Raspberry Pi Buster Welcome Screen" class="wp-image-311" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image2-1024x768.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image2-300x225.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image2-768x576.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image2.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Raspberry Pi Buster Welcome Screen</figcaption></figure>



<p>Ensure that you allow for the Operating System to check for and install any necessary updates.</p>



<p>Next, we&#8217;ll enable SSH on the device. This is optional &#8211; but I find it much easier to work on my large monitors vs. the small screen that I have on my Pi. From the Pi menu, select <strong>Preferences</strong>, then <strong>Raspberry Pi Configuration</strong>.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image1-1024x768.jpg" alt="Raspberry Pi Configuration Menu" class="wp-image-312" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image1-1024x768.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image1-300x225.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image1-768x576.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image1.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Raspberry Pi Configuration Menu</figcaption></figure>



<p>Select the <strong>Interfaces</strong> tab, then ensure you enable <strong>SSH</strong>, and select <strong>OK</strong>. You may also enable all interfaces that you require for your project at this time. I&#8217;ve also enabled <strong>Camera</strong>, <strong>SPI</strong>, <strong>I2C</strong>, <strong>Serial Port</strong>, <strong>1-Wire</strong> and <strong>Remote GPIO</strong> [mainly because I&#8217;m not sure all of what I want to do with it yet <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ]. Reboot the device so that the new settings take effect.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image0-1024x768.jpg" alt="Raspberry Pi Configuration Screen" class="wp-image-313" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image0-1024x768.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image0-300x225.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image0-768x576.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/thumbnail_image0.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Raspberry Pi Configuration Screen</figcaption></figure>



<h2>Install Azure IoT Edge</h2>



<p>Next, you can either open the Terminal directly on your pi device, or SSH into it from the machine of your choice.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1024x60.jpg" alt="Raspberry Pi Terminal Icon" class="wp-image-315" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1024x60.jpg 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-300x18.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-768x45.jpg 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Raspberry Pi Terminal Icon</figcaption></figure>



<p>For SSH, enter the command <strong>ssh pi@ipaddressofpi</strong> and when prompted, type <strong>yes</strong> to continue connecting.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1.png" alt="" class="wp-image-293" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1.png 979w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1-300x157.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal-1-768x402.png 768w" sizes="(max-width: 979px) 100vw, 979px" /><figcaption>SSH Window</figcaption></figure>



<p>First thing we need to do is install an earlier version of OpenSSL that is compatible with Azure IoT Edge. Install this package by executing the following:</p>



<pre class="wp-block-code"><code>sudo apt-get install libssl1.0.2</code></pre>



<p>We&#8217;ll need to register the Microsoft Key and software repository feed in order to obtain the software necessary to run Azure IoT Edge. Execute the following command to retrieve the list of products from the feed, and copy the downloaded list to the apt sources on the device. The last two commands in the series will install the Microsoft GPG public key as a trusted source.</p>



<pre class="wp-block-code"><code>curl https://packages.microsoft.com/config/debian/stretch/multiarch/prod.list > ./microsoft-prod.list

sudo cp ./microsoft-prod.list /etc/apt/sources.list.d/

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg

sudo cp ./microsoft.gpg /etc/apt/trusted.gpg.d/</code></pre>



<p>Now that we&#8217;ve added (and trusted) the Microsoft package feed. Let&#8217;s update our device&#8217;s package list.</p>



<pre class="wp-block-code"><code>sudo apt-get update</code></pre>



<p>Next, we&#8217;ll install the Moby engine and its associated CLI so that we can deploy, control, and run our Docker containers. Moby and the CLI are available as a single package in Microsoft package feed. Install this package by executing the following two commands:</p>



<pre class="wp-block-code"><code>sudo apt-get install moby-engine</code></pre>



<p>Now for the moment we&#8217;ve all been waiting for! Let&#8217;s install the most recent iotedge package.</p>



<pre class="wp-block-code"><code>sudo apt-get install iotedge</code></pre>



<p>Woohoo! We&#8217;ve made it! We&#8217;ve installed Azure IoT Edge on the Pi. We now need to give it a home. Keep your terminal window open while we switch gears to provisioning the device to an IoT Hub !</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal2.png" alt="SSH Window showing installation of the iotedge package" class="wp-image-295" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal2.png 979w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal2-300x274.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/terminal2-768x701.png 768w" sizes="(max-width: 979px) 100vw, 979px" /><figcaption>Installing the iotedge package</figcaption></figure>



<h2>Provision the Edge Device with an IoT Hub</h2>



<p>Log in to the <a rel="noreferrer noopener" href="https://portal.azure.com" target="_blank">Azure Portal</a> and choose to <strong>+ Create a resource</strong>. Search for <strong>IoT Hub</strong> and create the resource &#8211; choose either the <strong>Free </strong>tier or <strong>Standard</strong> tier. </p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/iothubprov-765x1024.png" alt="" class="wp-image-297" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/iothubprov-765x1024.png 765w, https://codingbandit.com/blog/wp-content/uploads/2020/10/iothubprov-224x300.png 224w, https://codingbandit.com/blog/wp-content/uploads/2020/10/iothubprov-768x1028.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/iothubprov.png 806w" sizes="(max-width: 765px) 100vw, 765px" /><figcaption>Provisioning the IoT Hub</figcaption></figure>



<p>Once provisioned. Open the IoT Hub resource you just created, and select <strong>IoT Edge</strong> from the left menu (beneath Automatic Device Management). </p>



<p>On the IoT Edge screen, select <strong>+ Add an IoT Edge device</strong> from the top toolbar. Give the device a name in the <strong>Device ID</strong> field. For authentication, we&#8217;ll just keep it simple and use a Symmetric key. Press the <strong>Save</strong> button to complete the device creation step.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/createedgedevice.png" alt="Creating an IoT Edge Device" class="wp-image-298" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/createedgedevice.png 923w, https://codingbandit.com/blog/wp-content/uploads/2020/10/createedgedevice-282x300.png 282w, https://codingbandit.com/blog/wp-content/uploads/2020/10/createedgedevice-768x817.png 768w" sizes="(max-width: 923px) 100vw, 923px" /><figcaption>Creating an IoT Edge Device</figcaption></figure>



<p>The device is now listed on the IoT Edge screen. Select the device you just created from the table.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgelisted.png" alt="IoT Edge Device List" class="wp-image-299" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgelisted.png 496w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgelisted-268x300.png 268w" sizes="(max-width: 496px) 100vw, 496px" /><figcaption>IoT Edge Device List</figcaption></figure>



<p>On the device screen, copy the Primary Connection String value, and paste it into a text editor. This is the connection string we will use to configure our IoT Edge module on the Pi.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-1024x517.png" alt="IoT Edge Device Primary Connection String" class="wp-image-300" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-1024x517.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-300x151.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-768x388.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-1536x775.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgedeviceprimaryconnectionstring-2048x1033.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>IoT Edge Device Primary Connection String</figcaption></figure>



<p>While we&#8217;re still on the device screen, select the <strong>Set Modules</strong> item from the top toolbar. It makes sense to have some type of module installed that will send telemetry from our device up to the IoT Hub to verify connectivity.</p>



<p>In the <strong>IoT Edge Modules</strong> section of the <strong>Set Modules</strong> screen, expand the +<strong> Add</strong> toolbar item, and select the <strong>+ Marketplace Module</strong> item.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/addmarketplacemodulemenu-1024x796.png" alt="Add Marketplace Module" class="wp-image-301" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/addmarketplacemodulemenu-1024x796.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/addmarketplacemodulemenu-300x233.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/addmarketplacemodulemenu-768x597.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/addmarketplacemodulemenu.png 1388w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Add Marketplace Module</figcaption></figure>



<p>In the search box for the marketplace, search for <strong>Simulated</strong>, and select to install the <strong>Simulated Temperature Sensor</strong> IoT Edge module.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgemarketplacesearch.png" alt="Marketplace Search" class="wp-image-302" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgemarketplacesearch.png 706w, https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgemarketplacesearch-300x183.png 300w" sizes="(max-width: 706px) 100vw, 706px" /><figcaption>Marketplace Search</figcaption></figure>



<p>Select the <strong>Review + create</strong> button to validate. Once validation has succeeded, select the <strong>Create</strong> button to persist the configuration.</p>



<p>Return to the terminal window for the final piece of the puzzle. We need to configure our Pi with the device connection string that we obtained from the IoT Hub.</p>



<p>Execute the following command to edit the configuration of our IoT Edge module:</p>



<pre class="wp-block-code"><code>sudo nano /etc/iotedge/config.yaml</code></pre>



<p>Use your arrow keys to navigate down the document until you see the <strong>&lt;ADD DEVICE CONNECTION STRING HERE&gt;</strong> text. Replace that text with the connection string you copied for your device in the IoT Hub earlier. (CTRL+X to exit, choose y to save and enter to confirm the same file name).</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgenanoconfig.png" alt="Configuring the IoT Edge Module with the Device Connection String" class="wp-image-303" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgenanoconfig.png 683w, https://codingbandit.com/blog/wp-content/uploads/2020/10/iotedgenanoconfig-300x152.png 300w" sizes="(max-width: 683px) 100vw, 683px" /><figcaption>Configuring the IoT Edge Module with the Device Connection String</figcaption></figure>



<p>Restart the IoT Edge module by executing the following command:</p>



<pre class="wp-block-code"><code>sudo systemctl restart iotedge</code></pre>



<p>Give the module a couple of minutes to restart, and view the logs of the IoT Edge Daemon by executing the following (when finished use CTRL+C to exit the command):</p>



<pre class="wp-block-code"><code>systemctl status iotedge</code></pre>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgeruntimerunning.png" alt="Edge runtime is running" class="wp-image-304" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/edgeruntimerunning.png 920w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgeruntimerunning-300x111.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/edgeruntimerunning-768x283.png 768w" sizes="(max-width: 920px) 100vw, 920px" /><figcaption>Edge runtime is running</figcaption></figure>



<p>Verify the success of the remote deployment of the <strong>SimulatedTemperatureSensor</strong> module onto the device by executing the following command:</p>



<pre class="wp-block-code"><code>sudo iotedge list</code></pre>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/simulatedtempondevice-1024x106.png" alt="Simulated Temperature Module on the Device" class="wp-image-305" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/simulatedtempondevice-1024x106.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulatedtempondevice-300x31.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulatedtempondevice-768x79.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulatedtempondevice.png 1465w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Simulated Temperature Module on the Device</figcaption></figure>



<p>You can view the output of the telemetry being sent by the <strong>SimulatedTemperatureSensor </strong>module by executing the following command:</p>



<pre class="wp-block-code"><code>sudo iotedge logs -f SimulatedTemperatureSensor</code></pre>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry-1024x374.png" alt="Simulated Device Telemetry" class="wp-image-306" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry-1024x374.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry-300x110.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry-768x280.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry-1536x561.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/10/simulateddevicetelemetry.png 1671w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Simulated Device Telemetry</figcaption></figure>



<p>Returning to the <strong>Azure Portal</strong>, refresh your Edge Device screen and you should see the <strong>IoT Edge runtime</strong> responding successfully. The <strong>SimulatedTemperatureSensor</strong> module should also have reported in from the device to the IoT Hub as well. </p>



<p>In the Azure Portal, you can view statistics of incoming messages into your IoT Hub resource on its Overview screen.</p>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview-1024x759.png" alt="IoT Hub Usage" class="wp-image-308" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview-1024x759.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview-300x222.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview-768x569.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview-1536x1138.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/10/hubusageoverview.png 1964w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>IoT Hub Usage</figcaption></figure>



<p>You can monitor incoming telemetry at the IoT Hub level by opening an instance of the <a href="https://shell.azure.com" target="_blank" rel="noreferrer noopener">Azure cloud shell</a>, and run the following Azure CLI commands:</p>



<pre class="wp-block-code"><code>az extension add --name azure-iot

az iot hub monitor-events --device-id {YourDeviceId} --hub-name {YourIoTHubName}</code></pre>



<figure class="wp-block-image size-large"><img src="https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-1024x405.png" alt="Incoming Telemetry Cloud Shell" class="wp-image-309" srcset="https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-1024x405.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-300x119.png 300w, https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-768x304.png 768w, https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-1536x608.png 1536w, https://codingbandit.com/blog/wp-content/uploads/2020/10/incomingtelemetrycloudshell-2048x810.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Incoming Telemetry Cloud Shell</figcaption></figure>



<h2>Conclusion</h2>



<p>Welcome to the beginning of your IoT Edge journey! I hope this blog post helps you get started !</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2020/10/10/setting-up-a-pi-4-as-an-azure-edge-device/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Machine Learning on Windows : Installing tooling and setting up an environment</title>
		<link>https://codingbandit.com/blog/2019/12/20/machine-learning-on-windows-installing-tooling-and-setting-up-an-environment/</link>
				<comments>https://codingbandit.com/blog/2019/12/20/machine-learning-on-windows-installing-tooling-and-setting-up-an-environment/#comments</comments>
				<pubDate>Fri, 20 Dec 2019 18:58:29 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[anaconda]]></category>
		<category><![CDATA[jupyter]]></category>
		<category><![CDATA[machine learning]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=244</guid>
				<description><![CDATA[I have recently started studying a fantastic Machine Learning Book named Hands-On Machine Learning with Scikit-Learn, Keras &#38; TensorFlow (2nd Edition). I am only...]]></description>
								<content:encoded><![CDATA[
<p>I have recently started studying a fantastic Machine Learning Book named Hands-On Machine Learning with Scikit-Learn, Keras &amp; TensorFlow (2nd Edition). I am only on the second chapter, but even so &#8211; this book has been well worth the purchase price.</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><a href="https://www.amazon.com/Hands-Machine-Learning-Scikit-Learn-TensorFlow-dp-1492032646/dp/1492032646/ref=mt_paperback?_encoding=UTF8&amp;me=&amp;qid=" target="_blank" rel="noreferrer noopener"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/homlslkt_book_cover.jpg" alt="Hands-On Machine Learning with Scikit-Learn, Keras &amp; Tensorflow " class="wp-image-247" width="263" height="347"/></a><figcaption>Hands-On Machine Learning with Scikit-Learn, Keras &amp; Tensorflow Book Cover</figcaption></figure></div>



<p>There&#8217;s only one aspect that made it slightly more difficult to get started &#8211; all of the intro material in the first chapter assumes you are running on a Linux machine. I am a Windows user &#8211; so I needed to seek out an alternate way to get my learning started with my platform of choice.</p>



<h2>Step 1 &#8211; Install Python 3 and pip</h2>



<p>This one, I need to go off of memory because I already had Python and pip installed on my machine &#8211; so forgive me if I forget something. You need to <a aria-label="download the latest release of Python 3 for Windows (opens in a new tab)" href="https://www.python.org/downloads/windows/" target="_blank" rel="noreferrer noopener">download the latest release of Python 3 for Windows</a>. Press the link for the latest version (typically near the top of the screen) &#8211; and that will bring you to the download page for that version. Scroll towards the bottom of the page and there will be a list of files. Keep it simple and download and run the <strong>Windows x86-64 executable installer</strong>. <em>Ensure you add Python to your PATH environment variable (available as an option in the installer &#8211; mine is in C:\Users\myuser\AppData\local\Programs\Python\Python38)</em></p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/pythoninstaller.png" alt="Pyton Installer Window" class="wp-image-248" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/pythoninstaller.png 997w, https://codingbandit.com/blog/wp-content/uploads/2019/12/pythoninstaller-300x185.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/pythoninstaller-768x473.png 768w" sizes="(max-width: 997px) 100vw, 997px" /><figcaption>Python Installer</figcaption></figure>



<p>Next you&#8217;ll need to download the get-pip.py script. You can get the <a aria-label="raw script directly from GitHub (opens in a new tab)" href="https://raw.githubusercontent.com/pypa/get-pip/master/get-pip.py" target="_blank" rel="noreferrer noopener">raw script directly from GitHub.</a> (Right click the previous link, select save target as.. and save get-pip.py to your desktop). Because we already have Python installed, it&#8217;s just a matter of double-clicking on the script and letting it do its thing (a console window will open and close when it is finished). Now we need to ensure that we add pip to our path environment variable. It is located in your Python installation location in the Scripts folder &#8211; in my case it is in <em>C:\Users\myusername\AppData\Local\Programs\Python\Python38\Scripts</em>.</p>



<p>Verify the paths are entered correctly by opening a command prompt and executing the pip command.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/pipcmdwindow.png" alt="Command Window with pip command executed" class="wp-image-251" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/pipcmdwindow.png 979w, https://codingbandit.com/blog/wp-content/uploads/2019/12/pipcmdwindow-300x280.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/pipcmdwindow-768x716.png 768w" sizes="(max-width: 979px) 100vw, 979px" /><figcaption>Command Window with pip command executed</figcaption></figure>



<h2>Step 2 &#8211; Download and Install Anaconda</h2>



<p>The next item that will be needed is a tool called Anaconda. Download and run the <a aria-label="Anaconda Distribution Windows Installer for Python 3 (opens in a new tab)" href="https://www.anaconda.com/distribution/" target="_blank" rel="noreferrer noopener">Anaconda Distribution Windows Installer for Python 3</a>. When running the installer, when you get to the installation options, be sure to uncheck both checkboxes (do not add anaconda to the path, and do not make it the default python installation for the system as we have already downloaded and installed Python).</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstalloptions.png" alt="Anaconda Installation Options" class="wp-image-252" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstalloptions.png 499w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstalloptions-300x233.png 300w" sizes="(max-width: 499px) 100vw, 499px" /><figcaption>Anaconda Installation Options</figcaption></figure>



<p>This installation is not a speedy one, so use patience and wait for it to complete.</p>



<h2>Step 3 &#8211; Begin a project by creating an environment</h2>



<p>After the installation has completed. In the Start Menu, you should now have application called <em>Anaconda Navigator</em>. Start this application (and be ready for console windows popping up and disappearing, it&#8217;s a normal thing). In the application, select <em>Environments</em> from the left menu, and in the Environments List pane, press the <em>Create</em> button to create a new workspace/environment.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentmenu-1024x540.png" alt="Anaconda Navigator Create Environment Menu" class="wp-image-253" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentmenu-1024x540.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentmenu-300x158.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentmenu-768x405.png 768w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentmenu.png 2044w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Anaconda Navigator Create Environment Menu</figcaption></figure>



<p>In the Create Environment form, give your environment a name, select the proper Python version, then press the<em> Create</em> button.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentform.png" alt="Anaconda Create Environment Form" class="wp-image-254" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentform.png 960w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentform-300x166.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondacreateenvironmentform-768x424.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><figcaption>Anaconda Create Environment Form</figcaption></figure>



<h2>Step 4 &#8211; Install the required packages for your project </h2>



<p>In order to follow along with the second chapter in this book, I needed to install some package dependencies into my environment. In the Environment List, ensure that you have the environment that you just created selected from the list. In the third pane, it shows you the packages that are already installed and available for use.  </p>



<p>The additional packages required for this chapter are: <strong>jupyter</strong>, <strong>matplotlib</strong>, <strong>numpy</strong>, <strong>pandas</strong>, <strong>scipy</strong>, and <strong>sklearn</strong> (**<em>search for <strong>scikit-learn</strong> instead of sklearn&nbsp;**</em>). Install these packages in your environment from the packages pane (third pane) by selecting <em>All</em> from the drop-down filter, and searching for each package individually. You do not need to install them one at a time, search for one, check the box, search for the next, check the box, and so on. After you have searched and checked each one &#8211; press the <em>Apply&nbsp;</em>button and wait for the packages to install.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstallpackages-1024x479.png" alt="Anaconda Install Packages" class="wp-image-255" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstallpackages-1024x479.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstallpackages-300x140.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondainstallpackages-768x359.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Anaconda Install Packages</figcaption></figure>



<h2>Step 5 &#8211; Open the Environment using Jupyter Notebooks</h2>



<p>In the Environments list (middle pane) &#8211; ensure your environment is selected and press the play button, this will display a context menu where you will select Open with Jupyter Notebook. This will automatically fire up the Jupyter server and a web browser will display showing you the Jupyter web interface. </p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondaopenenvironmentwithjupyter-1024x567.png" alt="Anaconda Open Environment with Jupyter Notebook" class="wp-image-266" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondaopenenvironmentwithjupyter-1024x567.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondaopenenvironmentwithjupyter-300x166.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondaopenenvironmentwithjupyter-768x426.png 768w, https://codingbandit.com/blog/wp-content/uploads/2019/12/anacondaopenenvironmentwithjupyter.png 1489w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Anaconda Open Environment with Jupyter Notebook</figcaption></figure>



<p>In the upper right of the Jupyter web interface, there is a New button, press this button and under the Notebook section, select Python3.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyternewnotebookmenu-1024x335.png" alt="Jupyter Web Interface Create New Python 3 Notebook" class="wp-image-256" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyternewnotebookmenu-1024x335.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyternewnotebookmenu-300x98.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyternewnotebookmenu-768x252.png 768w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyternewnotebookmenu.png 1334w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Jupyter Web Interface Create New Python 3 Notebook</figcaption></figure>



<p>Now you are off to the races to continue with the guidance presented in Chapter 2 &#8211; have fun!</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterhelloworld-1024x226.png" alt="Jupyter Notebook executing Hello World" class="wp-image-257" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterhelloworld-1024x226.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterhelloworld-300x66.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterhelloworld-768x169.png 768w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterhelloworld.png 1170w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Jupyter Notebook executing Hello World</figcaption></figure>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterchapter2notebook-1024x815.png" alt="Sampling of the Chapter 2 Jupyter Notebook" class="wp-image-259" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterchapter2notebook-1024x815.png 1024w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterchapter2notebook-300x239.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterchapter2notebook-768x611.png 768w, https://codingbandit.com/blog/wp-content/uploads/2019/12/jupyterchapter2notebook.png 1163w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Sampling of the Chapter 2 Jupyter Notebook</figcaption></figure>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2019/12/20/machine-learning-on-windows-installing-tooling-and-setting-up-an-environment/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
							</item>
		<item>
		<title>Creating a basic Stream Deck Emulator with Node.js</title>
		<link>https://codingbandit.com/blog/2019/01/20/creating-a-basic-stream-deck-emulator-with-node-js/</link>
				<comments>https://codingbandit.com/blog/2019/01/20/creating-a-basic-stream-deck-emulator-with-node-js/#respond</comments>
				<pubDate>Mon, 21 Jan 2019 01:26:31 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Node]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Stream Deck]]></category>
		<category><![CDATA[websockets]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=232</guid>
				<description><![CDATA[Stream Deck is a handy gadget targeted primarily to people who stream online. It allows you to automate tasks in 3rd party tools like...]]></description>
								<content:encoded><![CDATA[
<p><a aria-label="Stream Deck is a handy gadget targeted primarily to people who stream online. It allows you to automate tasks in 3rd party tools like OBS, Streamlabs, Mixer and more. It also allows you to open various executable programs on your computer, making it not only valuable to streamers, but also a great overall productivity tool. Stre (opens in a new tab)" href="https://www.elgato.com/en/gaming/stream-deck" target="_blank" rel="noreferrer noopener">Stream Deck</a> is a handy gadget targeted primarily to people who stream online. It allows you to automate tasks in 3rd party tools like OBS, Streamlabs, Mixer and more. It also allows you to open various executable programs on your computer, making it not only valuable to streamers, but also a great overall productivity tool. Elgato, the creator of Stream Deck, has recently <a aria-label="Stream Deck is a handy gadget targeted primarily to people who stream online. It allows you to automate tasks in 3rd party tools like OBS, Streamlabs, Mixer and more. It also allows you to open various executable programs on your computer, making it not only valuable to streamers, but also a great overall productivity tool. Elgato, the creator of Stream Deck, has recently released an SDK allowing developers to extend the platform with their own custom plugins. (opens in a new tab)" href="https://developer.elgato.com/documentation/stream-deck/sdk/overview/" target="_blank" rel="noreferrer noopener">released an SDK</a> allowing developers to extend the platform with their own custom plugins.</p>



<p>While building the<a aria-label="While building the .NET Core library for Stream Deck along with Jeff Fritz' Twitch Stream (opens in a new tab)" href="https://github.com/FritzAndFriends/StreamDeckToolkit" target="_blank" rel="noreferrer noopener"> .NET Core library</a> for Stream Deck plugins along with <a aria-label="While building the .NET Core library for Stream Deck plugins along with Jeff Fritz' Twitch Stream, it became evident that we can't expect all contributors to have physical hardware to be able to code for this project. (opens in a new tab)" href="https://www.twitch.tv/csharpfritz" target="_blank" rel="noreferrer noopener">Jeff Fritz&#8217; Twitch Stream</a>, it became evident that we can&#8217;t expect all contributors to have physical hardware to be able to code for this project.</p>



<p>I took it upon myself to complete a simple solution to this problem. What is nice is that all communication between the Stream Deck and its plugins are all via web sockets, so standing up an emulator is just a matter of setting up a server. I decided to stand up this emulator in Node.js due to its simplicity and terseness.</p>



<h2>Obtaining the Source Code</h2>



<p>All code is available through <a aria-label="The initial code is available through GitHub and is hosted alongside the .NET Core library project. (opens in a new tab)" href="https://github.com/FritzAndFriends/StreamDeckEmulator" target="_blank" rel="noreferrer noopener">GitHub</a> and is hosted alongside the .NET Core library project. Initially (which hopefully by the time you read this has matured somewhat) &#8211; I&#8217;ve implemented an application that will emulate the Stream Deck hardware by initiating a web socket server, then firing up the plugin executable. It also listens for user interaction to send a message from the server to the plugin. I will walk you through the &#8220;original&#8221; version of this code here.</p>



<h2>Configuration</h2>



<p>Configuration for this Node application is available in the config.js file. This file contains settings for the folder path to the plugin code, the name of the manifest file, as well as the name of the plugin. It also contains websocket server settings including device id (which is a made up hardware id assigned to our Stream Deck emulator), and the port on which the plugin will communicate with the server.</p>



<pre class="wp-block-code"><code>// config.js listing
let config = {};
config.executable = {
    path: "C:\\SourceCode\\Fritz\\StreamDeckToolkit\\src\\SamplePlugin\\bin\\Debug\\netcoreapp2.2\\win10-x64",
    manifest: "manifest.json",
    exe: "SamplePlugin.exe"
};
config.server = {
    deviceId : '55F16B35884A859CCE4FFA1FC8D3DE5B',
    port : 3000
}

module.exports = config;</code></pre>



<h2>Websocket Server Code</h2>



<p>Next is the websocket server code, located in server.js. This file is responsible for creating the websocket server listening on the configured port. It will also listen for commands from the main program (index.js) to know when to send the keyUp event across a connected socket, emulating a button press. Originally the keyUp event is the only event implemented in this code, adding others would just be a matter of adding cases to the switch statement.</p>



<pre class="wp-block-code"><code>// server.js listing
const config = require('./config');
var manifest = require(config.executable.path +'\\'+ config.executable.manifest);

const WebSocket = require('ws');
const server = new WebSocket.Server({ port: config.server.port});
let _socket; 

server.on('connection', (socket) => {
    _socket = socket;
    _socket.on('message',(msg)=> {
        console.log("\n"+ msg);
    });
});

// Message from index.js
process.on('message', (msg) => {
    switch(msg) {
        case 'button':
            var json = {
                "action": manifest.Actions[0].UUID,
                "event": "keyUp",
                "context": '',
                "device": config.deviceId,
                "payload": {
                    "settings": {},
                    "coordinates": {
                        "column": 3, 
                        "row": 1
                    },
                    "state": 0,
                    "userDesiredState": 1,
                    "isInMultiAction": false
                }
            };
            _socket.send(JSON.stringify(json));
            break;
        default:
            console.log('\nUnknown Index message: '+ msg);
            break;
    }
});</code></pre>



<h2>The main application</h2>



<p>Finally, the main application, available in index.js. This application is responsible for starting up the websocket server, as well as initiating the plugin via the command line using the appropriate command-line parameters. This code also listens for user input, in the case of the original code, we are only listening for the character b to be pressed by the user in order to initiate the keyUp event. By pressing b, the application sends a message to the server application telling it to execute the socket message associated with &#8216;button&#8217;.</p>



<pre class="wp-block-code"><code>// index.js
const config = require('./config');
const { fork } = require('child_process');
var rlSync = require('readline-sync');
var exec = require('child_process').execFile;
var manifest = require(config.executable.path +'\\'+ config.executable.manifest);

const forked = fork('server.js');
forked.send('&lt;status>Web Socket Server Started....');

// Registration Stuff
var info = {
    'application': {
      'language': 'en', 
      'platform': 'windows', 
      'version': '4.0.0'
    }, 
    'devices': [
      {
        'id': config.server.deviceId, 
        'size': {
          'columns': 5, 
          'rows': 3
        }, 
        'type': 0
      }
    ]
  };

var registrationParams = ['-port', config.server.port, '-pluginUUID', manifest.Actions[0].UUID,'-registerEvent','registerEvent','-info', JSON.stringify(info)];
exec(config.executable.exe, registrationParams, { cwd: config.executable.path }, (err, data) => {
    if(err){
        console.log(`ERROR: ${err}`);
    } else {
        console.log(`DATA: ${data}`);
    }
} );

// Type b at any time to send a KeyUp event to the plugin
promptUser();

function promptUser() {
    var cmd = rlSync.question("Enter 'b' to simulate a button press ");
    switch(cmd) {
        case 'b':
            forked.send('button');
            break;
        default:
            break;
    }
    promptUser();
}</code></pre>



<h2>Running the emulator</h2>



<p>The first thing you need to do is to <a aria-label='The first thing you need to do is to pull down the code, ensure your configuration is pointed to the correct path, running "npm install", then "node .".&nbsp; (opens in a new tab)' href="https://github.com/FritzAndFriends/StreamDeckEmulator" target="_blank" rel="noreferrer noopener">pull down the code</a>, and ensuring your configuration is pointed to the correct path.</p>



<p>Then, install the dependencies using:</p>



<pre class="wp-block-code"><code>npm install</code></pre>



<p>And run the application using:</p>



<pre class="wp-block-code"><code>node .</code></pre>



<p>In this case, I am using a debug version of the Sample Plugin available from the StreamDeckToolkit, it has a debugger break that will fire when the plugin is initiated. Select &#8220;StreamDeckToolKit&#8221; to initiate the debugger in the plugin code.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/01/attachDebugger.png" alt="Attach Debugger" class="wp-image-235" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/01/attachDebugger.png 427w, https://codingbandit.com/blog/wp-content/uploads/2019/01/attachDebugger-300x293.png 300w" sizes="(max-width: 427px) 100vw, 427px" /><figcaption>Attach Debugger</figcaption></figure>



<p>It will break on a line that says Debugger.Launch() , just press the continue button in Visual Studio.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/01/image.png" alt="Stream Deck Emulator Registration" class="wp-image-236" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/01/image.png 846w, https://codingbandit.com/blog/wp-content/uploads/2019/01/image-300x70.png 300w, https://codingbandit.com/blog/wp-content/uploads/2019/01/image-768x178.png 768w" sizes="(max-width: 846px) 100vw, 846px" /><figcaption>Stream Deck Emulator Registration</figcaption></figure>



<p>On the console of the Node application &#8211; you&#8217;ll see a couple things.</p>



<p>#1 &#8211; The prompt for the user to press &#8216;b&#8217; to initiate the button press (this will seem out of order with the server messages being output, but rest assured, the user can press &#8216;b&#8217; at any time to initiate the button press).</p>



<p>#2 &#8211; The registration message that is received from the plugin is output.</p>



<p>Once the user enters b &lt;enter> &#8211; the magic starts &#8211; it initates the keyUp event in the plugin, and the plugin responds with commands for the Stream Deck (Emulator). Developers can now inspect the messages obtained from the plugin in the console of the Node application.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2019/01/image-1.png" alt="Stream Deck Plugin Events Received Upon Button Press" class="wp-image-238" srcset="https://codingbandit.com/blog/wp-content/uploads/2019/01/image-1.png 645w, https://codingbandit.com/blog/wp-content/uploads/2019/01/image-1-300x151.png 300w" sizes="(max-width: 645px) 100vw, 645px" /><figcaption>Stream Deck Plugin Events Received Upon Button Press</figcaption></figure>



<h2>To finish off&#8230;</h2>



<p>This blog post gives an overview of the beginnings of the Stream Deck Emulator project &#8211; I&#8217;m certain it will grow from here &#8211; but this gives us a starting point to ease plugin development for the Stream Deck hardware.</p>



<p></p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2019/01/20/creating-a-basic-stream-deck-emulator-with-node-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Azure Sphere MT3620 &#8211; Painless I2C with the Grove Shield library</title>
		<link>https://codingbandit.com/blog/2018/11/13/azure-sphere-mt3620-painless-i2c-with-the-grove-shield-library/</link>
				<comments>https://codingbandit.com/blog/2018/11/13/azure-sphere-mt3620-painless-i2c-with-the-grove-shield-library/#comments</comments>
				<pubDate>Tue, 13 Nov 2018 21:13:07 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Azure Sphere]]></category>
		<category><![CDATA[GPIO]]></category>
		<category><![CDATA[I2C]]></category>
		<category><![CDATA[MT3620]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=209</guid>
				<description><![CDATA[Read I2C temperature and humidity values with the press of a button using Azure Sphere.]]></description>
								<content:encoded><![CDATA[
<p></p>



<p>When first diving in to explore the <a aria-label="When first diving in to explore the Azure Sphere MCU, I was a bit dismayed that I2C and ADC are all currently unsupported. My spirits were then lifted when I discovered that the Grove Shield for the Azure Sphere MT3620 removes that barrier! (opens in a new tab)" href="https://codingbandit.com/blog/2018/11/07/unboxing-the-azure-sphere-mt3620-development-kit/" target="_blank" rel="noreferrer noopener">Azure Sphere MCU</a>, I was a bit dismayed that I2C and ADC are currently unsupported. My spirits were then lifted when I discovered that the <a aria-label="When first diving in to explore the Azure Sphere MCU, I was a bit dismayed that I2C and ADC are all currently unsupported. My spirits were then lifted when I discovered that the Grove Shield for the Azure Sphere MT3620 removes that barrier! (opens in a new tab)" href="https://www.seeedstudio.com/Grove-Starter-Kit-for-Azure-Sphere-MT3620-Development-Kit-p-3150.html" target="_blank" rel="noreferrer noopener">Grove Shield for the Azure Sphere MT3620 </a>removes that barrier!</p>



<h2>The MT3620 Grove Shield</h2>



<p>When I first purchased my Azure Sphere, I also added the <a aria-label="When I first purchased my Azure Sphere, I also added the Azure Sphere Grove Starter Kit. I have had a lot of good experiences with Seeed Grove kits in the past, so picking this one up was only logical. It provides the shield that sits atop of the Azure Sphere and exposes plug and play options for GPIO, Analog, and UART peripherals. The starter kit also shipped with a series of popular sensors so that you can get started designing your devices without having to breadboard or solder anything. There are tons of affordable Grove sensors available, each with accompanying schematics and source libraries for various hardware platforms. (opens in a new tab)" href="https://www.seeedstudio.com/Grove-Starter-Kit-for-Azure-Sphere-MT3620-Development-Kit-p-3150.html" target="_blank" rel="noreferrer noopener">Azure Sphere Grove Starter Kit</a>. I have had a lot of good experiences with Seeed Grove kits in the past, so picking this one up was only logical. It provides the shield that sits atop of the Azure Sphere and exposes plug and play options for GPIO, Analog, and UART peripherals. The starter kit also shipped with a series of popular sensors so that you can get started designing your devices without having to breadboard or solder anything. There are tons of affordable <a aria-label="When I first purchased my Azure Sphere, I also added the Azure Sphere Grove Starter Kit. I have had a lot of good experiences with Seeed Grove kits in the past, so picking this one up was only logical. It provides the shield that sits atop of the Azure Sphere and exposes plug and play options for GPIO, Analog, and UART peripherals. The starter kit also shipped with a series of popular sensors so that you can get started designing your devices without having to breadboard or solder anything. There are tons of affordable Grove sensors available,&nbsp;&#10; (opens in a new tab)" href="http://wiki.seeedstudio.com/Grove_System/" target="_blank" rel="noreferrer noopener">Grove sensors</a> available, each with accompanying schematics and source libraries for various hardware platforms.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/mt3620_shield.jpg" alt="MT3620 Grove Shield" class="wp-image-214" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/mt3620_shield.jpg 800w, https://codingbandit.com/blog/wp-content/uploads/2018/11/mt3620_shield-300x225.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/mt3620_shield-768x576.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption>MT3620 Grove Shield</figcaption></figure>



<h2>The MT3620 Grove Shield Library</h2>



<p>Seeed Studio has provided <a aria-label="Seeed Studio has provided full C source code to their library that interfaces with the Azure Sphere board. (opens in a new tab)" href="https://github.com/Seeed-Studio/MT3620_Grove_Shield" target="_blank" rel="noreferrer noopener">full C source code to their library</a> that interfaces with the Azure Sphere board. In the same repository, they&#8217;ve also included <a aria-label="Seeed Studio has provided full C source code to their library that interfaces with the Azure Sphere board. In the same repository, they've also included code samples for each of the Grove sensors included in the starter kit. (opens in a new tab)" href="https://github.com/Seeed-Studio/MT3620_Grove_Shield/tree/master/Samples" target="_blank" rel="noreferrer noopener">code samples</a> for each of the Grove sensors provided in the starter kit.</p>



<h2>Creating an app that reads temperature and humidity at the press of a button</h2>



<h4>Prepping the hardware</h4>



<p>In this project, we&#8217;ll be using two groves that come from the starter kit &#8211; the <a aria-label="In this project, we'll be using two groves that come from the starter kit - the Grove - Blue LED Button and the Grove - Temperature and Humidity Sensor (SHT31) (opens in a new tab)" href="https://www.seeedstudio.com/Grove-Blue-LED-Button-p-3104.html" target="_blank" rel="noreferrer noopener">Grove &#8211; Blue LED Button</a> and the <a aria-label="In this project, we'll be using two groves that come from the starter kit - the Grove - Blue LED Button and the Grove - Temperature and Humidity Sensor (SHT31) (opens in a new tab)" href="https://www.seeedstudio.com/Grove-Temperature-Humidity-Sensor-SHT3-p-2655.html" target="_blank" rel="noreferrer noopener">Grove &#8211; Temperature and Humidity Sensor (SHT31).</a></p>



<p>Plug the Temperature/Humidity sensor into one of the I2C ports, and the button into the GPIO0 slot (this ultimately ends up using GPIO0 and GPIO1).</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/hardwaresetup.jpg" alt="Hardware Setup" class="wp-image-215" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/hardwaresetup.jpg 800w, https://codingbandit.com/blog/wp-content/uploads/2018/11/hardwaresetup-300x225.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/hardwaresetup-768x576.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption>Hardware Setup</figcaption></figure>



<h4>Setting up the Visual Studio project</h4>



<p>The first step to any development is to clone the <a aria-label="The first step to any development is to clone the MT3620 Shield Library repository. Remember where you cloned this repository - we'll be needing it shortly! (opens in a new tab)" href="https://github.com/Seeed-Studio/MT3620_Grove_Shield" target="_blank" rel="noreferrer noopener">MT3620 Shield Library repository</a>. <strong>Remember where you cloned this repository &#8211; we&#8217;ll be needing it shortly!</strong></p>



<p>Once cloned, open Visual Studio 2017, and create a new project using the &#8216;Blank Application for MT3620 RDB (Azure Sphere)&#8217; template (located in Other Languages -&gt; Visual C++ -&gt; Cross Platform -&gt; Azure Sphere). I have named mine &#8216;OnDemandTemperatureAndHumidity&#8217;.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/createproject.png" alt="Create Blank Azure Sphere Project" class="wp-image-210" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/createproject.png 941w, https://codingbandit.com/blog/wp-content/uploads/2018/11/createproject-300x208.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/createproject-768x533.png 768w" sizes="(max-width: 941px) 100vw, 941px" /><figcaption>Create Blank Azure Sphere Project</figcaption></figure>



<p>Once the project has been generated, we need to add the cloned MT3620 Shield Library project to the solution. Do so by right-clicking the solution in solution explorer, and select &#8216;Add existing project&#8217;, then find the &#8216;MT3620_Grove_Shield_Library.vcxproj&#8217; that is located in the MT3620_Grove_Shield_Library folder of the cloned repository.</p>



<p>Next, add a project reference to the Grove Shield Library project that we just added. Do so by right-clicking on your &#8216;OnDemandTemperatureAndHumidity&#8217; project, and select &#8216;Add&#8217; -&gt; &#8216;Reference&#8217;, then select &#8216;Projects&#8217; -&gt; &#8216;Solution&#8217; in the left-hand treeview, and place a checkmark next to the MT3620_Grove_Shield_Library item.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/addprojectreference.png" alt="Add reference to the MT3620_Grove_Shield_Library" class="wp-image-211" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/addprojectreference.png 1178w, https://codingbandit.com/blog/wp-content/uploads/2018/11/addprojectreference-300x207.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/addprojectreference-768x531.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/addprojectreference-1024x708.png 1024w" sizes="(max-width: 1178px) 100vw, 1178px" /><figcaption>Add reference to the MT3620_Grove_Shield_Library</figcaption></figure>



<p>Now we need to add the location of the MT3620_Grove_Shield_Library to the include directories of the project. To do so, right click on the &#8216;OnDemandTemperatureAndHumidity&#8217; project and select &#8216;Properties&#8217;. Then in the left-hand treeview, expand &#8216;Configuration Properties&#8217; -&gt; &#8216;C/C++&#8217; -&gt; &#8216;General&#8217;. In the &#8216;Additional Include Directories&#8217; field, add the path to the MT3620_Grove_Shield_Library folder (it contains the &#8216;Grove.h&#8217; file). My field value (will vary based on where you cloned the library), now looks similar to this:</p>



<pre class="wp-block-code"><code>C:\SourceCode\AzureSphere\MT3620_Grove_Shield\MT3620_Grove_Shield_Library;%(AdditionalIncludeDirectories)</code></pre>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/additionalincludes.png" alt="Add MT3620 path to 'Additional Include Directories' field" class="wp-image-212" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/additionalincludes.png 1289w, https://codingbandit.com/blog/wp-content/uploads/2018/11/additionalincludes-300x195.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/additionalincludes-768x499.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/additionalincludes-1024x665.png 1024w" sizes="(max-width: 1289px) 100vw, 1289px" /><figcaption>Add MT3620 path to &#8216;Additional Include Directories&#8217; field</figcaption></figure>



<h4>Bring on the Source Code!</h4>



<p>In order to gain access to the functionality of the shield, we will need to add some capabilities to the app manifest of the project. In the root of the OnDemandTemperatureAndHumidity project, open &#8216;app_manifest.json&#8217; and modify the Capabilities property to the following:</p>



<pre class="wp-block-code"><code>  "Capabilities": {
    "AllowedConnections": [],
    "Gpio": [ 8, 9, 10, 15, 16, 17, 18, 19, 20, 12, 13, 0, 1, 4, 5, 57, 58, 11, 14, 48 ],
    "Uart": [ "ISU0", "ISU3" ],
    "WifiConfig": false
  }</code></pre>



<p>Next, in the Source Files folder, modify your main.c file with the following listing (my code additions are numbered, and commented inline):</p>



<pre class="wp-block-code"><code>#include &lt;signal.h>
#include &lt;stdbool.h>
#include &lt;stdlib.h>
#include &lt;string.h>
#include &lt;time.h>

#include "applibs_versions.h"
#include &lt;applibs/log.h>

#include "mt3620_rdb.h"

// 1. include the Grove, Grove LED Button, and Grove Temp Humidity Headers from the MT3620_Grove_Shield_Libary
#include "Grove.h"
#include "Sensors/GroveLEDButton.h"
#include "Sensors/GroveTempHumiSHT31.h"

static volatile sig_atomic_t terminationRequested = false;

static void TerminationHandler(int signalNumber)
{
	terminationRequested = true;
}

int main(int argc, char *argv[])
{
	// 2. define variables for button and initial state
	static GPIO_Value_Type buttonState, lastButtonState;
	void *ledButton = GroveLEDButton_Init(1, 0);
	lastButtonState = GroveLEDButton_GetBtnState(ledButton);

	// 3. initialize i2c feed with baud rate and temp humidity sensor
	int i2cFeed;
	GroveShield_Initialize(&amp;i2cFeed, 115200);
	void* tempHumiditySensor = GroveTempHumiSHT31_Open(i2cFeed);

	struct sigaction action;
	memset(&amp;action, 0, sizeof(struct sigaction));
	action.sa_handler = TerminationHandler;
	sigaction(SIGTERM, &amp;action, NULL);

	// FYI - loop is every 1000 nanoseconds
	const struct timespec sleepTime = { 0, 1000 };
	while (!terminationRequested) {

		// 4. determine button state and if it has changed, toggle LED accordingly
		buttonState = GroveLEDButton_GetBtnState(ledButton);
		if (buttonState != lastButtonState) {
			if (buttonState == 0) {
				GroveLEDButton_LedOn(ledButton);
				Log_Debug("Button pressed.\n");
				// 5. take a temperature and humidity reading every time button is pressed
				GroveTempHumiSHT31_Read(tempHumiditySensor);
				float temperature = GroveTempHumiSHT31_GetTemperature(tempHumiditySensor);
				float humidity = GroveTempHumiSHT31_GetHumidity(tempHumiditySensor);
				Log_Debug("Temperature: %.1fC\n", temperature);
				Log_Debug("Humidity: %.1f\%c\n", humidity, 0x25);
			}
			else {
				GroveLEDButton_LedOff(ledButton);
				Log_Debug("Button released.\n");
			}
		}
		lastButtonState = buttonState;

		nanosleep(&amp;sleepTime, NULL);
	}
	return 0;
}

</code></pre>



<p>Build and run your project on your device &#8211; every time you press the button, the LED will light up, and the debug output will indicate the current temperature and humidity. The resulting output will look similar to the following:</p>



<pre class="wp-block-code"><code>Remote debugging from host 192.168.35.1
Button pressed.
Temperature: 22.4C
Humidity: 40.2%
Button released.
Button pressed.
Temperature: 22.3C
Humidity: 43.3%
Button released.
Button pressed.
Temperature: 22.3C
Humidity: 42.9%
Button released.
Button pressed.
Temperature: 22.3C
Humidity: 41.9%
Button released.
Button pressed.
Temperature: 22.3C
Humidity: 41.3%
Button released.</code></pre>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="640" height="480" src="https://www.youtube.com/embed/9a7-3e0bPdU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption>I2C with Azure Sphere and MT3620 Grove Shield</figcaption></figure>



<h2>Conclusion</h2>



<p>The Azure Sphere Grove Starter kit greatly simplifies creating a proof of concept on the platform. What is especially nice is that the libraries provided by Seeed Studio have all the source code available on GitHub. This makes it easy to start creating code to interface with additional Groves, or if you are adventurous, creating your own custom Groves adhering to the interface.</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2018/11/13/azure-sphere-mt3620-painless-i2c-with-the-grove-shield-library/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
							</item>
		<item>
		<title>Setting up Firebase Push Notifications in an existing NativeScript Angular application</title>
		<link>https://codingbandit.com/blog/2018/11/12/setting-up-firebase-push-notifications-in-an-existing-nativescript-angular-application/</link>
				<comments>https://codingbandit.com/blog/2018/11/12/setting-up-firebase-push-notifications-in-an-existing-nativescript-angular-application/#respond</comments>
				<pubDate>Mon, 12 Nov 2018 21:02:42 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Firebase]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[NativeScript]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=182</guid>
				<description><![CDATA[Incorporate Firebase Cloud Messaging in an existing NativeScript application.]]></description>
								<content:encoded><![CDATA[
<p>When researching the implementation of Firebase Push Notifications, I came across many articles and snippets that were pretty dated or contained a lot of extraneous information. I felt it warranted to write a quick and simple, right-to-the-point article.</p>



<h2>Adding the NativeScript Firebase Plugin</h2>



<p>This step is a pretty simple one. If you have not already done so in your application, add the nativescript firebase plugin by executing the following command:</p>



<pre class="wp-block-code"><code>tns plugin add nativescript-push-notifications</code></pre>



<p>Also ensure that you have the plugin setup in your project <a href="https://github.com/EddyVerbruggen/nativescript-plugin-firebase">as specified on the plugin GitHub page</a>.</p>



<h2>Cloud messaging setup</h2>



<p>Verify in your project root folder that the file &#8216;firebase.nativescript.json&#8217; that the messaging property is set to true.</p>



<pre class="wp-block-code"><code>...
"messaging": true,
...</code></pre>



<h2>Setting up iOS for messaging</h2>



<p>With Firebase being a Google offering, they made it very painless to incorporate messaging for Android &#8211; we&#8217;ve already done everything that we needed to do to get it to run there. We will have to perform additional steps for iOS.</p>



<h4>Enable push notifications in Xcode</h4>



<p>Using Xcode, in the &#8216;/platforms/ios/&#8217; folder, open your &#8216;*.xcworkspace&#8217; file. Select the project in the left hand treeview, them select the &#8216;Capabilities&#8217; tab. Scroll down until you find &#8216;Push Notifications&#8217;, and toggle it to the &#8216;On&#8217; position.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/turnonpush.png" alt="iOS Turn On Push Notifications" class="wp-image-190" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/turnonpush.png 1025w, https://codingbandit.com/blog/wp-content/uploads/2018/11/turnonpush-300x112.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/turnonpush-768x286.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/turnonpush-1024x382.png 1024w" sizes="(max-width: 1025px) 100vw, 1025px" /><figcaption>iOS Turn On Push Notifications</figcaption></figure>



<p>This will create an entitlements file located in &#8216;/platforms/ios/&lt;project&gt;/&lt;project.entitlements&#8217; &#8211; this file will need to be copied (or merged) to &#8216;/App_Resources/iOS/&lt;project&gt;.entitlements&#8217;. This will allow the entitlements to be copied over every time you remove and re-add the iOS platform.</p>



<h4>Enable background notifications</h4>



<p>In order to be able to receive notifications when the app is closed, you&#8217;ll need to enable background notifications. Open &#8216;/App_Resources/iOS/Info.plist&#8217; and add this key:</p>



<pre class="wp-block-code"><code>&lt;key>UIBackgroundModes&lt;/key>
&lt;array>
  &lt;string>remote-notification&lt;/string>
&lt;/array></code></pre>



<h4>Generate an APNS authentication key</h4>



<p>Go to &#8216;https://developer.apple.com&#8217; and log in with your Apple developer account. Select &#8216;Certificates, Identifiers &amp; Profiles&#8217;. Then, on the left hand menu, select &#8216;All&#8217; underneath the &#8216;Keys&#8217; section and click the &#8216;+&#8217; button to add a key. Give the key a description, ensure you check the APNs checkbox, then click the &#8216;Continue&#8217; button, then the &#8216;Confirm&#8217; button to generate the key. Finally, download the key, we will be using it momentarily.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/genapnsauthkey.png" alt="Generate APNs Authentication Key" class="wp-image-191" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/genapnsauthkey.png 1266w, https://codingbandit.com/blog/wp-content/uploads/2018/11/genapnsauthkey-300x218.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/genapnsauthkey-768x557.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/genapnsauthkey-1024x743.png 1024w" sizes="(max-width: 1266px) 100vw, 1266px" /><figcaption>Generate APNs Authentication Key</figcaption></figure>



<h4>Verify your application has Push Notifications as configurable</h4>



<p>In the Apple developer site, select your App ID and ensure that Push Notifications are set to &#8216;Configurable&#8217;. If it&#8217;s not, simply edit the form, and check the &#8216;Push Notifications&#8217; checkbox.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/pushconfigurable.png" alt="Push Notifications Configurable" class="wp-image-192" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/pushconfigurable.png 1323w, https://codingbandit.com/blog/wp-content/uploads/2018/11/pushconfigurable-300x137.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/pushconfigurable-768x351.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/pushconfigurable-1024x468.png 1024w" sizes="(max-width: 1323px) 100vw, 1323px" /><figcaption>Push Notifications Configurable</figcaption></figure>



<p>If you&#8217;ve made a change, you will need to re-generate your <a aria-label="If you've made a change, you will need to re-generate your development provisioning profile. (opens in a new tab)" href="https://docs.nativescript.org/sidekick/user-guide/code-signing/code-signing-for-ios/create-development-provisioning" target="_blank" rel="noreferrer noopener">development provisioning profile</a>.</p>



<h4>Add iOS Authentication key to Firebase</h4>



<p>Log into your Firebase console, and next to &#8216;Project Overview&#8217; click the cog button and select &#8216;Project Settings&#8217;. Select the &#8216;Cloud Messaging&#8217; tab, then scroll down to the iOS app configuration section, and click the &#8216;Upload&#8217; button.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/iosappconfig.png" alt="APNs Authentication Key Configuration" class="wp-image-193" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/iosappconfig.png 1711w, https://codingbandit.com/blog/wp-content/uploads/2018/11/iosappconfig-300x105.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/iosappconfig-768x268.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/iosappconfig-1024x357.png 1024w" sizes="(max-width: 1711px) 100vw, 1711px" /><figcaption>APNs Authentication Key Configuration</figcaption></figure>



<p>You will now be presented with a form, upload the APNs authentication key that you generated earlier. Enter a 10 character Key ID (these 10 characters are the suffix to the key file that you downloaded) &#8211; and fill out your Team ID &#8211; this is located in the Apple Developer Console under Membership.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/teamid.png" alt="iOS Developer Team ID" class="wp-image-194" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/teamid.png 1381w, https://codingbandit.com/blog/wp-content/uploads/2018/11/teamid-300x136.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/teamid-768x347.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/teamid-1024x463.png 1024w" sizes="(max-width: 1381px) 100vw, 1381px" /><figcaption>iOS Developer Team ID</figcaption></figure>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/uploadapnsauthkey-1.png" alt="Uploading APNs Authentication Key Form" class="wp-image-197" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/uploadapnsauthkey-1.png 647w, https://codingbandit.com/blog/wp-content/uploads/2018/11/uploadapnsauthkey-1-300x255.png 300w" sizes="(max-width: 647px) 100vw, 647px" /><figcaption>Uploading APNs Authentication Key Form</figcaption></figure>



<h2>Add notification handling code</h2>



<p>Open &#8216;/src/app/app.component.ts&#8217; and in your ngOnInit handler within the firebase.init call, add the following code (firebase.init method included here for clarity):</p>



<pre class="wp-block-code"><code>firebase.init({
    showNotifications: true,
    showNotificationsWhenInForeground: true
  });</code></pre>



<h2>Send a test notification</h2>



<p>Ensure you have your application running on actual device(s). <strong>I was only able to receive them when the apps were running on the device, disconnected from any computer.</strong></p>



<p>In your firebase console, in the left hand menu, in the &#8216;Grow&#8217; section &#8211; select &#8216;Cloud Messaging&#8217;. You can then author a message, select which app(s) to send the message to, and finally review the message prior to publishing.</p>



<ul class="wp-block-gallery columns-3 is-cropped"><li class="blocks-gallery-item"><figure><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/push1.png" alt="Author Push Notification" data-id="200" data-link="https://codingbandit.com/blog/?attachment_id=200" class="wp-image-200" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/push1.png 1239w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push1-300x140.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push1-768x360.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push1-1024x479.png 1024w" sizes="(max-width: 1239px) 100vw, 1239px" /><figcaption>Author Push Notification</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/push2.png" alt="Set Push Notification Recipients" data-id="201" data-link="https://codingbandit.com/blog/?attachment_id=201" class="wp-image-201" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/push2.png 1145w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push2-300x167.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push2-768x427.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push2-1024x570.png 1024w" sizes="(max-width: 1145px) 100vw, 1145px" /><figcaption>Set Push Notification Recipients</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/push3.png" alt="Review and Publish Push Notification" data-id="202" data-link="https://codingbandit.com/blog/?attachment_id=202" class="wp-image-202" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/push3.png 845w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push3-300x173.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/push3-768x443.png 768w" sizes="(max-width: 845px) 100vw, 845px" /><figcaption>Review and Publish Push Notification</figcaption></figure></li></ul>



<p>Once published, you will receive notifications on the devices you&#8217;ve selected.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/android_pushnotification.jpg" alt="Android Push Notification" class="wp-image-203" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/android_pushnotification.jpg 450w, https://codingbandit.com/blog/wp-content/uploads/2018/11/android_pushnotification-169x300.jpg 169w" sizes="(max-width: 450px) 100vw, 450px" /><figcaption>Android Push Notification</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/ios_pushnotification.jpg" alt="iOS Push Notification" class="wp-image-204" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/ios_pushnotification.jpg 338w, https://codingbandit.com/blog/wp-content/uploads/2018/11/ios_pushnotification-169x300.jpg 169w" sizes="(max-width: 338px) 100vw, 338px" /><figcaption>iOS Push Notification</figcaption></figure></div>



<p>That&#8217;s all there is to it, hopefully this will help someone cut to the chase and implement Push Notifications in their NativeScript application.</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2018/11/12/setting-up-firebase-push-notifications-in-an-existing-nativescript-angular-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Unboxing the Azure Sphere MT3620 Development Kit</title>
		<link>https://codingbandit.com/blog/2018/11/07/unboxing-the-azure-sphere-mt3620-development-kit/</link>
				<comments>https://codingbandit.com/blog/2018/11/07/unboxing-the-azure-sphere-mt3620-development-kit/#respond</comments>
				<pubDate>Wed, 07 Nov 2018 20:32:03 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Sphere]]></category>
		<category><![CDATA[IoT]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=167</guid>
				<description><![CDATA[Join me as I unbox the Azure Sphere MT3620 Development Kit, set it up, press a button, and blink an LED !]]></description>
								<content:encoded><![CDATA[
<p>While doing some IoT writing, I became increasingly curious about the new MCU on the block &#8211; Azure Sphere. It is being touted as being very powerful and as the most secure board available in the market today. It also boasts a lifetime of fully managed patches and security updates.</p>



<p>Note: Azure Sphere needs to be linked to Azure Active Directory (AAD) &#8211; I have one through my personal business&#8217; Office 365 subscription. There are <a aria-label="Note: Azure Sphere needs to be linked to Azure Active Directory (AAD) - I have one through my personal business' Office 365 subscription. There are multiple ways of creating an AAD instance through this guidance. (opens in a new tab)" href="https://docs.microsoft.com/en-us/azure-sphere/install/azure-directory-account" target="_blank" rel="noreferrer noopener">multiple ways of creating an AAD instance through this guidance</a>.</p>



<h2>Procuring the dev kit</h2>



<p>I <a aria-label="I ordered my dev kit, and received it a couple of weeks later. (opens in a new tab)" href="https://aka.ms/azurespheredevkits" target="_blank" rel="noreferrer noopener">ordered my dev kit</a> and received it a few weeks later &#8211; I also added the <a aria-label="I ordered my dev kit, and received it a few weeks later - I also added the Grove starter kit for it so that I could easily start tinkering with it immediately. (opens in a new tab)" href="https://www.seeedstudio.com/Grove-Starter-Kit-for-Azure-Sphere-MT3620-Development-Kit-p-3150.html" target="_blank" rel="noreferrer noopener">Grove starter kit</a> so that I could start tinkering with my new board immediately.</p>



<ul class="wp-block-gallery columns-2 is-cropped"><li class="blocks-gallery-item"><figure><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/closedboxes.jpg" alt="Azure Sphere with Grove Kit Closed Boxes" data-id="169" data-link="https://codingbandit.com/blog/?attachment_id=169" class="wp-image-169" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/closedboxes.jpg 800w, https://codingbandit.com/blog/wp-content/uploads/2018/11/closedboxes-300x151.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/closedboxes-768x386.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption>Azure Sphere with Grove Kit Closed Boxes</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/openboxes.jpg" alt="Azure Sphere with Grove Kit Open Boxes" data-id="170" data-link="https://codingbandit.com/blog/?attachment_id=170" class="wp-image-170" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/openboxes.jpg 800w, https://codingbandit.com/blog/wp-content/uploads/2018/11/openboxes-300x185.jpg 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/openboxes-768x473.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption>Azure Sphere with Grove Kit Open Boxes</figcaption></figure></li></ul>



<h2>Download and install the SDK</h2>



<p>In order to develop for the Azure Sphere, you&#8217;ll need to<a aria-label="In order to develop for the Azure Sphere, you'll need to download the SDK - at the time of this writing it is currently in preview. (opens in a new tab)" href="http://aka.ms/AzureSphereSDKDownload" target="_blank" rel="noreferrer noopener"> download and install the SDK</a> &#8211; at the time of this writing it is currently in preview.</p>



<h2>Claiming the device</h2>



<p>Hook up the Sphere to your PC using the USB cable that was included in the box. Open the Azure Sphere Developer Command Prompt and log in with your Microsoft account:</p>



<pre class="wp-block-code"><code>azshpere login</code></pre>



<p>This will open a familiar browser login screen to authenticate your account. You may be shown a message indicating that there are no Azure Sphere Tenants found under the selected AAD user &#8211; this is expected. If you need to create a tenant, execute a command to create one (replace the name argument with the name of your choosing, I named mine &#8216;TrilliumSphere&#8217;) &#8211; you will be prompted to authenticate once more:</p>



<pre class="wp-block-code"><code>azsphere tenant create --name TrilliumSphere</code></pre>



<p>Then claim the device using the following command:</p>



<pre class="wp-block-code"><code>azsphere device claim</code></pre>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/createtenantclaimdevice.png" alt="Create Tenant and Claim Device" class="wp-image-173" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/createtenantclaimdevice.png 979w, https://codingbandit.com/blog/wp-content/uploads/2018/11/createtenantclaimdevice-300x157.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/createtenantclaimdevice-768x402.png 768w" sizes="(max-width: 979px) 100vw, 979px" /><figcaption>Create Tenant and Claim Device</figcaption></figure>



<h2>Performing initial setup</h2>



<p>Configure the device to utilize your Wi-Fi by issuing the following command:</p>



<pre class="wp-block-code"><code>azsphere device wifi add --ssid &lt;YOURSSID> --key &lt;YOURKEY></code></pre>



<p>When the device first boots, or connects to Wi-Fi, it will automatically seek out and install any updates. These updates should not be interrupted. Check the status of any updates by issuing the following command:</p>



<pre class="wp-block-code"><code>azsphere device show-ota-status</code></pre>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/wifiandupdatestatus.png" alt="Add WiFi and Device Update Status" class="wp-image-174" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/wifiandupdatestatus.png 674w, https://codingbandit.com/blog/wp-content/uploads/2018/11/wifiandupdatestatus-300x103.png 300w" sizes="(max-width: 674px) 100vw, 674px" /><figcaption>Add WiFi and Device Update Status</figcaption></figure>



<h2>HelloWorld MCU Edition == Blink</h2>



<p>The default Hello World program for a microcontroller is to blink an LED. I followed the <a aria-label="The default Hello World program for a microcontroller is to blink an LED. I followed the following walkthrough to perform just that! (opens in a new tab)" href="https://docs.microsoft.com/en-us/azure-sphere/quickstarts/qs-blink-application" target="_blank" rel="noreferrer noopener">following walkthrough</a> to perform just that!</p>



<p>By default, the Sphere ships to you in a locked state, meaning you can&#8217;t load or debug programs from a PC. Execute the following command to unlock the device:</p>



<pre class="wp-block-code"><code>azsphere device prep-debug</code></pre>



<p>You will then see output similar to the following:</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/unlockdevicefordebugging.png" alt="Unlock Sphere for Debugging" class="wp-image-175" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/unlockdevicefordebugging.png 962w, https://codingbandit.com/blog/wp-content/uploads/2018/11/unlockdevicefordebugging-300x105.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/unlockdevicefordebugging-768x270.png 768w" sizes="(max-width: 962px) 100vw, 962px" /><figcaption>Unlock Sphere for Debugging</figcaption></figure>



<p>As indicated in the console window &#8211; when a device is unlocked, it will not receive over-the-air updates. To lock a device for production (and to start receiving updates once more) you would execute the following command:</p>



<pre class="wp-block-code"><code>azsphere device prep-field</code></pre>



<p>In order to run the blink sample, keep the device in the unlocked/debug mode. Ensure that you are running the latest build of Visual Studio 2017 &#8211; at the time of this writing it is v.15.8.9 &#8211; this will save you a whole lot of headaches!!!</p>



<p> Open Visual Studio, create a new project &#8211; then select the &#8216;Blink Sample for MT3620 RDB (Azure Sphere)&#8217; template (on my machine this is located under Other Languages -&gt; Visual C++ -&gt; Cross Platform -&gt; Azure Sphere).</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/newmt3620blinkproject.png" alt="New MT3620 Blink Sample Project" class="wp-image-176" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/newmt3620blinkproject.png 941w, https://codingbandit.com/blog/wp-content/uploads/2018/11/newmt3620blinkproject-300x208.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/newmt3620blinkproject-768x533.png 768w" sizes="(max-width: 941px) 100vw, 941px" /><figcaption>New MT3620 Blink Sample Project</figcaption></figure>



<p>Build and run the project &#8211; then press the &#8216;A&#8217; button to change the speed of the blinking on LED 1.</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="640" height="480" src="https://www.youtube.com/embed/TFAGufsj_ZE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption>Azure Sphere MT3620 Blink Sample Project</figcaption></figure>



<p>Sample Source file listing is as follows (copied from template) Source Files\main.c :</p>



<pre class="wp-block-code"><code>#include &lt;errno.h>
#include &lt;signal.h>
#include &lt;stdbool.h>
#include &lt;stdlib.h>
#include &lt;string.h>
#include &lt;time.h>
#include &lt;unistd.h>

// applibs_versions.h defines the API struct versions to use for applibs APIs.
#include "applibs_versions.h"
#include "epoll_timerfd_utilities.h"

#include &lt;applibs/gpio.h>
#include &lt;applibs/log.h>

#include "mt3620_rdb.h"

// This sample C application for the MT3620 Reference Development Board (Azure Sphere)
// blinks an LED.
// The blink rate can be changed through a button press.
//
// It uses the API for the following Azure Sphere application libraries:
// - gpio (digital input for button)
// - log (messages shown in Visual Studio's Device Output window during debugging)

// File descriptors - initialized to invalid value
static int gpioButtonFd = -1;
static int gpioButtonTimerFd = -1;
static int gpioLedFd = -1;
static int gpioLedTimerFd = -1;
static int epollFd = -1;

// Button state variables
static GPIO_Value_Type buttonState = GPIO_Value_High;
static GPIO_Value_Type ledState = GPIO_Value_High;

// Blink interval variables
static const int numBlinkIntervals = 3;
static const struct timespec blinkIntervals[] = {{0, 125000000}, {0, 250000000}, {0, 500000000}};
static int blinkIntervalIndex = 0;

// Termination state
static volatile sig_atomic_t terminationRequired = false;

/// &lt;summary>
///     Signal handler for termination requests. This handler must be async-signal-safe.
/// &lt;/summary>
static void TerminationHandler(int signalNumber)
{
    // Don't use Log_Debug here, as it is not guaranteed to be async signal safe
    terminationRequired = true;
}

/// &lt;summary>
///     Handle LED timer event: blink LED.
/// &lt;/summary>
static void LedTimerEventHandler()
{
    if (ConsumeTimerFdEvent(gpioLedTimerFd) != 0) {
        terminationRequired = true;
        return;
    }

    // The blink interval has elapsed, so toggle the LED state
    // The LED is active-low so GPIO_Value_Low is on and GPIO_Value_High is off
    ledState = (ledState == GPIO_Value_Low ? GPIO_Value_High : GPIO_Value_Low);
    int result = GPIO_SetValue(gpioLedFd, ledState);
    if (result != 0) {
        Log_Debug("ERROR: Could not set LED output value: %s (%d).\n", strerror(errno), errno);
        terminationRequired = true;
    }
}

/// &lt;summary>
///     Handle button timer event: if the button is pressed, change the LED blink rate.
/// &lt;/summary>
static void ButtonTimerEventHandler()
{
    if (ConsumeTimerFdEvent(gpioButtonTimerFd) != 0) {
        terminationRequired = true;
        return;
    }

    // Check for a button press
    GPIO_Value_Type newButtonState;
    int result = GPIO_GetValue(gpioButtonFd, &amp;newButtonState);
    if (result != 0) {
        Log_Debug("ERROR: Could not read button GPIO: %s (%d).\n", strerror(errno), errno);
        terminationRequired = true;
        return;
    }

    // If the button has just been pressed, change the LED blink interval
    // The button has GPIO_Value_Low when pressed and GPIO_Value_High when released
    if (newButtonState != buttonState) {
        if (newButtonState == GPIO_Value_Low) {
            blinkIntervalIndex = (blinkIntervalIndex + 1) % numBlinkIntervals;
            if (SetTimerFdInterval(gpioLedTimerFd, &amp;blinkIntervals[blinkIntervalIndex]) != 0) {
                terminationRequired = true;
            }
        }
        buttonState = newButtonState;
    }
}

/// &lt;summary>
///     Set up SIGTERM termination handler, initialize peripherals, and set up event handlers.
/// &lt;/summary>
/// &lt;returns>0 on success, or -1 on failure&lt;/returns>
static int InitPeripheralsAndHandlers(void)
{
    struct sigaction action;
    memset(&amp;action, 0, sizeof(struct sigaction));
    action.sa_handler = TerminationHandler;
    sigaction(SIGTERM, &amp;action, NULL);

    epollFd = CreateEpollFd();
    if (epollFd &lt; 0) {
        return -1;
    }

    // Open button GPIO as input, and set up a timer to poll it
    Log_Debug("Opening MT3620_RDB_BUTTON_A as input\n");
    gpioButtonFd = GPIO_OpenAsInput(MT3620_RDB_BUTTON_A);
    if (gpioButtonFd &lt; 0) {
        Log_Debug("ERROR: Could not open button GPIO: %s (%d).\n", strerror(errno), errno);
        return -1;
    }
    struct timespec buttonPressCheckPeriod = {0, 1000000};
    gpioButtonTimerFd = CreateTimerFdAndAddToEpoll(epollFd, &amp;buttonPressCheckPeriod,
                                                   &amp;ButtonTimerEventHandler, EPOLLIN);
    if (gpioButtonTimerFd &lt; 0) {
        return -1;
    }

    // Open LED GPIO, set as output with value GPIO_Value_High (off), and set up a timer to poll it
    Log_Debug("Opening MT3620_RDB_LED1_RED\n");
    gpioLedFd = GPIO_OpenAsOutput(MT3620_RDB_LED1_RED, GPIO_OutputMode_PushPull, GPIO_Value_High);
    if (gpioLedFd &lt; 0) {
        Log_Debug("ERROR: Could not open LED GPIO: %s (%d).\n", strerror(errno), errno);
        return -1;
    }
    gpioLedTimerFd = CreateTimerFdAndAddToEpoll(epollFd, &amp;blinkIntervals[blinkIntervalIndex],
                                                &amp;LedTimerEventHandler, EPOLLIN);
    if (gpioLedTimerFd &lt; 0) {
        return -1;
    }

    return 0;
}

/// &lt;summary>
///     Close peripherals and handlers.
/// &lt;/summary>
static void ClosePeripheralsAndHandlers(void)
{
    // Leave the LED off
    if (gpioLedFd >= 0) {
        GPIO_SetValue(gpioLedFd, GPIO_Value_High);
    }

    Log_Debug("Closing file descriptors\n");
    CloseFdAndPrintError(gpioLedTimerFd, "LedTimer");
    CloseFdAndPrintError(gpioLedFd, "GpioLed");
    CloseFdAndPrintError(gpioButtonTimerFd, "ButtonTimer");
    CloseFdAndPrintError(gpioButtonFd, "GpioButton");
    CloseFdAndPrintError(epollFd, "Epoll");
}

/// &lt;summary>
///     Main entry point for this application.
/// &lt;/summary>
int main(int argc, char *argv[])
{
    Log_Debug("Blink application starting\n");
    if (InitPeripheralsAndHandlers() != 0) {
        terminationRequired = true;
    }

    // Use epoll to wait for events and trigger handlers, until an error or SIGTERM happens
    while (!terminationRequired) {
        if (WaitForEventAndCallHandler(epollFd) != 0) {
            terminationRequired = true;
        }
    }

    ClosePeripheralsAndHandlers();
    Log_Debug("Application exiting\n");
    return 0;
}
</code></pre>



<h2>First impressions</h2>



<p>My first impressions with this device has overall been positive. It was easy to add it to the domain and claim it &#8211; though I did have to disconnect and reconnect it in order for the tenant creation command to see it. In Visual Studio &#8211; I was getting an application error when opening the project, and if I tried to build the project, it would fail but not give any errors in the error pane. After updating Visual Studio &#8211; the project started working fine!</p>



<p>I guess it&#8217;s time to brush up on my C programming!!!</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2018/11/07/unboxing-the-azure-sphere-mt3620-development-kit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Importing iCal (*.ics) Feed into the UI for NativeScript Calendar Component</title>
		<link>https://codingbandit.com/blog/2018/11/06/importing-ical-ics-feed-into-the-ui-for-nativescript-calendar-component/</link>
				<comments>https://codingbandit.com/blog/2018/11/06/importing-ical-ics-feed-into-the-ui-for-nativescript-calendar-component/#comments</comments>
				<pubDate>Tue, 06 Nov 2018 18:41:14 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[Calendar]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[NativeScript]]></category>
		<category><![CDATA[TypeScript]]></category>
		<category><![CDATA[UI for NativeScript]]></category>

		<guid isPermaLink="false">https://codingbandit.com/blog/?p=152</guid>
				<description><![CDATA[Learn how to import an existing iCal feed and display events in a UI for NativeScript Calendar.]]></description>
								<content:encoded><![CDATA[
<p>I encountered a requirement while implementing a mobile application recently where I needed to display events in a mobile application that are published on a Google Calendar. I could have gone the route of using a WebView and embedding it that way, but I wanted the users to experience the richness and beauty of using a fully native application.</p>



<p>I decided to utilize the UI for NativeScript from Progress Software, a professional grade component library that is available free of charge. Included in this offering is a Calendar component that satisfies my need for a better user experience.</p>



<p><strong>Note:</strong> this is expecting that you already have the module importing the UI for NativeScript Calendar and ListView components. It is also importing only basic iCal data, no recurrence rule parsing is taking place. This article also doesn&#8217;t step you through creating a NativeScript application from scratch, it shows you how to add the functionality into an existing module. In this case, I have created an application module called Calendar, and I have already setup the module, routes, etc.</p>



<h2>Obtain the calendar feed</h2>



<p>The first thing that you will need is the public or private feed for the Google Calendar that you&#8217;d like to have imported to have displayed in the NativeScript Calendar component. To do this, open your Google Calendar page, on the upper-right hand corner of the page, click on cog icon and select &#8216;Settings&#8217;.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendar11062018-1.png" alt="Google Calendar Settings" class="wp-image-154" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendar11062018-1.png 447w, https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendar11062018-1-300x45.png 300w" sizes="(max-width: 447px) 100vw, 447px" /><figcaption>Google Calendar Settings</figcaption></figure>



<p>Next, ensure you select the correct calendar to edit the settings for. Then scroll toward the bottom of the settings window, and find the iCal address. You can choose a public link (for published calendars) or the private link for private/unpublished calendars. In my case, the calendar is not public, so I am making a note of the private iCal address.</p>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendarsettings1162018-1.png" alt="iCal Addresses" class="wp-image-156" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendarsettings1162018-1.png 1311w, https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendarsettings1162018-1-300x198.png 300w, https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendarsettings1162018-1-768x507.png 768w, https://codingbandit.com/blog/wp-content/uploads/2018/11/gcalendarsettings1162018-1-1024x676.png 1024w" sizes="(max-width: 1311px) 100vw, 1311px" /><figcaption>iCal Addresses</figcaption></figure>



<h2>Establishing a model</h2>



<p>In order to populate the Calendar component, it requires data to adhere to the <a href="https://docs.telerik.com/devtools/nativescript-ui/api/classes/calendarevent.html">C</a><a href="https://docs.telerik.com/devtools/nativescript-ui/api/classes/calendarevent.html" target="_blank" rel="noreferrer noopener">alendar</a><a href="https://docs.telerik.com/devtools/nativescript-ui/api/classes/calendarevent.html">Event</a> model established in the API. This model includes the following properties:</p>



<ul><li>endDate</li><li>eventColor</li><li>isAllDay</li><li>startDate</li><li>title</li></ul>



<p>This is a great model for a base calendar, however, I need a little more information captured in my events, so I created a new class that extends the CalendarEvent model &#8211; adding to it a couple more properties. Here is a listing of my app/models/calendar-event-extended.ts file:</p>



<pre class="wp-block-code"><code>import { CalendarEvent } from "nativescript-ui-calendar";
import { Color } from "tns-core-modules/color/color";

export class CalendarEventExtended extends CalendarEvent {
    description: string;
    location: string;
    constructor() {
        const maxDate = new Date(8640000000000000);
        const minDate = new Date(-8640000000000000);
        super("None", minDate, maxDate, false, new Color(200, 188, 26, 214));
        this.description = "";
        this.location = "";
    }
}</code></pre>



<h2>Creating a service class</h2>



<p>I have my project setup to have service classes to retrieve data from Firebase Firestore or any other external data source. This is where I will put my class that is responsible for pulling, parsing and transforming the iCal data into the CalendarEventExtended structure. Here is a listing of my services/calendar-service.ts file:</p>



<pre class="wp-block-code"><code>import * as moment from "moment";
import { getString } from "tns-core-modules/http";
import traceModule = require("tns-core-modules/trace");
import { CalendarEventExtended } from "../models/calendar-event-extended";

export class CalendarService {
     private _icsUrl: string = "";
     constructor(icsUrl: string) {
         this._icsUrl = icsUrl;
     }
     getCalendarEventsPromise(): Promise&lt;Array&lt;CalendarEventExtended>> {
         return new Promise&lt;Array&lt;CalendarEventExtended>>((resolve, reject) => {
            getString(this._icsUrl).then((content) => {
                const calEvents = new Array&lt;CalendarEventExtended>();
                const lines = content.split("\n");
                let entry = new CalendarEventExtended();
                lines.forEach((itm) => {
                    if (itm.indexOf("BEGIN:VEVENT") === 0) {
                        entry = new CalendarEventExtended();
                    } else if (itm.indexOf("DTSTART") === 0) {
                        if (itm.indexOf("VALUE=DATE") >= 0) {
                            entry.isAllDay = true;
                            entry.startDate = this._getDateOnlyFromIcalString(itm);
                        } else {
                            entry.startDate = this._getDateTimeFromIcalString(itm);
                        }
                    } else if (itm.indexOf("DTEND") === 0) {
                        entry.endDate = (itm.indexOf("VALUE=DATE") >= 0) ?
                                    this._getDateOnlyFromIcalString(itm) :
                                    this._getDateTimeFromIcalString(itm);
                    } else if (itm.indexOf("SUMMARY") === 0) {
                        entry.title = this._getTextFromIcalString(itm);
                    } else if (itm.indexOf("DESCRIPTION") === 0) {
                        entry.description = this._getTextFromIcalString(itm);
                    } else if (itm.indexOf("LOCATION") === 0) {
                        entry.location = this._getTextFromIcalString(itm);
                    } else if (itm.indexOf("END:VEVENT") === 0) {
                        calEvents.push(entry);
                    }
                });
                resolve(calEvents);
             }, (err) => {
                 traceModule.error(err);
                 reject(err);
             });
         });
     }
     private _getDateTimeFromIcalString(str: string): Date {
        const dteNum = str.split(":")[1];
        const m = moment(dteNum, "YYYYMMDDTHHmmssZ");

        return m.toDate();
     }
     private _getDateOnlyFromIcalString(str: string): Date {
         const dteNum = str.split(":")[1];
         const m = moment(dteNum, "YYYYMMDD");

         return m.toDate();
     }
     private _getTextFromIcalString(str: string): string {
        const idx = str.indexOf(":");

        return str.substr(idx + 1).replace("\\", "");
     }
}
</code></pre>



<p>From the code above, you can see that I am pulling the iCal data from a url and parsing its content. This is only providing basic parsing, I don&#8217;t have logic in there to deal with recurrence rules, so this will work in the basic calendar usage case. I am also utilizing the trace module for logging functionality, so if you are not using that &#8211; it can be removed. The getCalendarEventsPromise function returns just that, a promise that it will retrieve, parse, and transform the calendar data into an array of CalendarEventExtended objects.</p>



<h2>Establishing a View Model</h2>



<p>In this application, what I needed to do is display the calendar with events, then when a date is selected, to list the events for that date in a list below the calendar (I am also using the ListView component from UI from NativeScript). This View Model is also responsible for setting styles for the calendar, most of which I retained as the defaults. You will notice that I am importing another service, application-service &#8211; this is where I have set things like the iCal url as well as the color palette for the application. The listing for view-models/calendar-view-model.ts is as follows:</p>



<pre class="wp-block-code"><code>import { Observable } from "data/observable";
import { ObservableArray } from "data/observable-array";
import * as Moment from "moment";
import * as MomentRange from "moment-range";

import { CalendarDayViewStyle, CalendarEventsViewMode, CalendarMonthNamesViewStyle, CalendarMonthViewStyle, CalendarSelectionEventData, CalendarSelectionMode, CalendarTransitionMode, CalendarViewMode, CalendarWeekViewStyle, CalendarYearViewStyle, DayCellStyle, SelectionShape } from "nativescript-ui-calendar";
import { CalendarEventExtended } from "../models/calendar-event-extended";
import { applicationService } from "../services/application-service";

const moment = MomentRange.extendMoment(Moment);

export class CalendarViewModel extends Observable {
    private _calendarEvents: ObservableArray&lt;CalendarEventExtended> = new ObservableArray&lt;CalendarEventExtended>();
        private _calendarEventsFiltered: ObservableArray&lt;CalendarEventExtended> = new ObservableArray&lt;CalendarEventExtended>();
    private _selectedDate: Date = new Date();

    constructor() {
        super();
    }

    get selectedDate(): Date {
        return this._selectedDate;
    }

    set selectedDate(dte: Date) {
        this._selectedDate = dte;
    }

    get calendarEvents(): ObservableArray&lt;CalendarEventExtended> {
        return this._calendarEvents;
    }

    get calendarEventsFiltered(): ObservableArray&lt;CalendarEventExtended> {
        return this._calendarEventsFiltered;
    }

    updateCalendarEventsFiltered(events: Array&lt;CalendarEventExtended>) {
        this.calendarEventsFiltered.length = 0;
        if (events &amp;&amp; events.length) {
            for (const ce of events) {
                this.calendarEventsFiltered.push(ce);
            }
        }
    }

    updateCalendarEvents(list: Array&lt;CalendarEventExtended>) {
        this.calendarEvents.length = 0;
        if (list &amp;&amp; list.length) {
            for (const ce of list) {
                this.calendarEvents.push(ce);
            }
        }
    }

    onDateSelected(args: CalendarSelectionEventData) {
        this.calendarEventsFiltered.length = 0;
        if (args.date) {
            const filtered = this.calendarEvents.filter((itm, idx, calendarEvents) => {
                const range = moment().range(moment(itm.startDate).startOf("day"), moment(itm.endDate).endOf("day"));

                return range.contains(args.date);
            });
            this.updateCalendarEventsFiltered(filtered);
        }
    }

    get selectionMode() {
        return CalendarSelectionMode.Single;
    }

    get viewMode() {
        return CalendarViewMode.Month;
    }

    get transitionMode() {
        return CalendarTransitionMode.Slide;
    }

    get eventsViewMode() {
        return CalendarEventsViewMode.None;
    }

    get monthViewStyle(): CalendarMonthViewStyle {
        const monthViewStyle = new CalendarMonthViewStyle();
        monthViewStyle.backgroundColor = applicationService.iconsTextColorHex;
        monthViewStyle.showTitle = true;
        monthViewStyle.showWeekNumbers = false;
        monthViewStyle.showDayNames = true;
        monthViewStyle.selectionShape = SelectionShape.None;

        const todayCellStyle = new DayCellStyle();
        todayCellStyle.cellBackgroundColor = applicationService.primaryColorHex;
        todayCellStyle.cellBorderWidth = 2;
        todayCellStyle.cellBorderColor = applicationService.primaryColorHex;
        monthViewStyle.todayCellStyle = todayCellStyle;

        const dayCellStyle = new DayCellStyle();
        dayCellStyle.eventTextSize = 4;              monthViewStyle.dayCellStyle = dayCellStyle;

        const weekendCellStyle = new DayCellStyle();
             weekendCellStyle.cellBackgroundColor = applicationService.extraLightPrimaryColorHex;
               monthViewStyle.weekendCellStyle = weekendCellStyle;

        const selectedCellStyle = new DayCellStyle();
               selectedCellStyle.cellBackgroundColor = applicationService.accentColorHex;
        monthViewStyle.selectedDayCellStyle = selectedCellStyle;

        return monthViewStyle;

    }

    get weekViewStyle(): CalendarWeekViewStyle {
        const weekViewStyle = new CalendarWeekViewStyle();
                              

        return weekViewStyle;
    }

    get yearViewStyle(): CalendarYearViewStyle {
        const yearViewStyle = new CalendarYearViewStyle();

        return yearViewStyle;

    }

    get dayViewStyle(): CalendarDayViewStyle {
        const dayViewStyle = new CalendarDayViewStyle();
          
         return dayViewStyle;
    }

    get monthNamesViewStyle(): CalendarMonthNamesViewStyle {
        const monthNamesViewStyle = new CalendarMonthNamesViewStyle();
        return monthNamesViewStyle;
    }
}
</code></pre>



<p>From the code above, you can see that I am using <a href="https://www.npmjs.com/package/moment" target="_blank" rel="noreferrer noopener">MomentJS</a> and the extensions available in <a href="https://www.npmjs.com/package/moment-range" target="_blank" rel="noreferrer noopener">Moment-Range</a> packages &#8211; both are available via npm. You can also see that I&#8217;ve created an event onDateSelected that will filter events by the date selected &#8211; these will be displayed in the ListView.</p>



<h2>Date Formatting Display Pipe</h2>



<p>In my list view, I also wanted to format the dates and times in a specific format, as such I created a simple DateTimeFormatter pipe to transform my data to the desired format. This formatter must be in your @NgModule declaration in order to use it. The source code for the pipes/dateTimeFormatter.ts is as follows:</p>



<pre class="wp-block-code"><code>import { Pipe, PipeTransform } from "@angular/core";
import * as moment from "moment";

@Pipe({
    name: "sgDateTimeFormatter",
    pure: true
})

export class DateTimeFormatter implements PipeTransform {
    transform(dte: Date): string {
        return moment(dte).format("MM/DD/YYYY h:mm A");
    }
}</code></pre>



<h2>Finally &#8211; the view!</h2>



<p>The component code for my application Calendar module utilizes another <a href="https://github.com/bradmartin/nativescript-cardview">plug-in</a> for displaying the events list as a series of cards. I am also using the <a href="https://github.com/NativeScript/template-drawer-navigation-ng">angular drawer navigation template</a> as the basis of my application. My component source file listing is as follows (app/calendar/calendar.component.ts):</p>



<pre class="wp-block-code"><code>import { AfterViewInit, Component,  OnInit } from "@angular/core";
import * as app from "application";
import { registerElement } from "nativescript-angular/element-registry";
import { CardView } from "nativescript-cardview";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import { applicationService } from "../services/application-service";
import { CalendarService } from "../services/calendar-service";
import { CalendarViewModel } from "../view-models/calendar-view-model";

registerElement("CardView", () => CardView);

@Component({
    selector: "Calendar",
    moduleId: module.id,
    templateUrl: "./calendar.component.html"
})
export class CalendarComponent implements OnInit, AfterViewInit {
    vm: CalendarViewModel = new CalendarViewModel();
    constructor() {
        // Use the component constructor to inject providers.
    }

    ngOnInit(): void {
        // Init your component properties here.
    }

    ngAfterViewInit(): void {
        const svc = new CalendarService(applicationService.calendarUrl);
        svc.getCalendarEventsPromise().then((result) => {
            this.vm.updateCalendarEvents(result);
        });
    }

    onDrawerButtonTap(): void {
        const sideDrawer = &lt;RadSideDrawer>app.getRootView();
        sideDrawer.showDrawer();
    }
}
</code></pre>



<p>From the code above, you can see that it utilizes the service that was created to pull back data and populate the view model. </p>



<p>The view listing is as follows (calendar.component.html):</p>



<pre class="wp-block-code"><code>&lt;ActionBar class="action-bar">
    &lt;!-- 
    Use the NavigationButton as a side-drawer button in Android
    because ActionItems are shown on the right side of the ActionBar
    -->
    &lt;NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()">&lt;/NavigationButton>
    &lt;!-- 
    Use the ActionItem for IOS with position set to left. Using the
    NavigationButton as a side-drawer button in iOS is not possible,
    because its function is to always navigate back in the application.
    -->
    &lt;ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()"
        ios.position="left">
    &lt;/ActionItem>
    &lt;Label class="action-bar-title" text="Calendar">&lt;/Label>
&lt;/ActionBar>

&lt;GridLayout rows="2*,*" columns="*" class="page page-content">
    &lt;RadCalendar [eventSource]="vm.calendarEvents"
        [monthViewStyle] = "vm.monthViewStyle" [weekViewStyle]="vm.weekViewStyle"
        [monthNamesViewStyle] = "vm.monthNamesViewStyle" [yearViewStyle]="vm.yearViewStyle"
        [dayViewStyle]="vm.dayViewStyle" [transitionMode]="vm.transitionMode"
        [selectionMode]="vm.selectionMode" [eventsViewMode]="vm.eventsViewMode" 
        [selectedDate]="vm.defaultDate"
        (dateSelected)="vm.onDateSelected($event)"
        row="0" col="0">
    &lt;/RadCalendar>
    &lt;RadListView [items]="vm.calendarEventsFiltered" row="1" col="0">
        &lt;ng-template tkListItemTemplate let-item="item">
            &lt;CardView class="cardStyle" elevation="10" radius="1">
                &lt;StackLayout orientation="vertical">
                    &lt;Label class="primary-header" [text]="item.title">&lt;/Label>
                    &lt;StackLayout class="list-item-divider">&lt;/StackLayout>
                    &lt;Label class="secondary-header" [text]="item.description">&lt;/Label>
                    &lt;StackLayout margin="5" *ngIf="!item.isAllDay">
                        &lt;Label text="Start Date: {{item.startDate | sgDateTimeFormatter}}">&lt;/Label>
                        &lt;Label text="End Date: {{item.endDate | sgDateTimeFormatter}}">&lt;/Label>
                    &lt;/StackLayout>
                    &lt;StackLayout margin="5" *ngIf="item.isAllDay">
                        &lt;Label text="Date: {{item.startDate | sgDateTimeFormatter}}">&lt;/Label>
                    &lt;/StackLayout>
                  
                &lt;/StackLayout>
            &lt;/CardView>
        &lt;/ng-template>
    &lt;/RadListView>
&lt;/GridLayout></code></pre>



<p>Here is what the resulting code looks like on a device:</p>



<figure class="wp-block-image"><img alt=""/></figure>



<figure class="wp-block-image"><img src="https://codingbandit.com/blog/wp-content/uploads/2018/11/finalcalendar1162018-1.png" alt="UI for NativeScript Calendar" class="wp-image-160" srcset="https://codingbandit.com/blog/wp-content/uploads/2018/11/finalcalendar1162018-1.png 614w, https://codingbandit.com/blog/wp-content/uploads/2018/11/finalcalendar1162018-1-178x300.png 178w, https://codingbandit.com/blog/wp-content/uploads/2018/11/finalcalendar1162018-1-609x1024.png 609w" sizes="(max-width: 614px) 100vw, 614px" /><figcaption>UI for NativeScript Calendar</figcaption></figure>



<h2>Wrap-up</h2>



<p>One of the nice things about NativeScript is its flexibility. I like that I am easily able to extend it using JavaScript and leverage many of the helper libraries available on NPM to get me where I need to go. This is just a simple example of how you can provide an in-application native experience to your users while still using information you&#8217;ve already got published on the web.</p>
]]></content:encoded>
							<wfw:commentRss>https://codingbandit.com/blog/2018/11/06/importing-ical-ics-feed-into-the-ui-for-nativescript-calendar-component/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
							</item>
	</channel>
</rss>
