PAGES

29

Mar 16

Nuget Packages in ASP.NET Core 1.0



Dependencies are NuGet packages in ASP.NET Core 1.0, which we still can add to our project from the Package Manager Console or the NuGet Dialog, just like in previous versions.

However, ASP.NET Core 1.0 introduces the project.json file, which among other things, contains a list of all the NuGet packages that the project depends on, and allow us to add or remove dependencies directly from the file.

Let’s see a simple example.

Adding packages from the project.json file

Imagine we want to add some logging functionality to our application and we decide to install the log4net library for this purpose.

To do this, we just need to open the project.json file, which should be located in the root of the project, and add a new entry to the dependencies node. This new entry should specify the name and version of the package.

  "dependencies": {
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
        "Microsoft.AspNet.Mvc": "6.0.0-beta3",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta3",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta3",
        "log4net": "2.0.3"
    }

One of the coolest things about this is that Visual Studio provides IntelliSense to help us to select the NuGet package that we want to install.

1

Once the package entry has been added, all we need to do is to save the file, and the package will automatically be added to the project as a reference.

2

We can either select a specific version of the package, or not specify any, in this case, we will always get the latest version.

  "dependencies": {
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
        "Microsoft.AspNet.Mvc": "6.0.0-beta3",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta3",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta3",
        "log4net": ""
    }

And this is all we need to do. Keep in mind that this also works the other way around: if we want to delete a package from our project, remove the package entry from the project.json file.

Targeting multiple frameworks

As you have probably noticed, there are two different sections under the project references. These sections represent the different runtimes which the new ASP.NET is able to run on.

ASP.NET 5.0 is the full .NET CLR and ASP.NET Core 5.0 is the cloud-optimized Core CLR.

4

Adding a dependency to target only one of these runtimes is fairly easy too. The frameworks node of the project.json file contains a node for each of the runtimes: the node aspnet50 correspond to the full .NET CLR and the aspnetcore50 to the Core CLR.

If we only want to add the log4net package to the Core CLR, we just need to add a new dependency node under aspnetcore50, and then create a new package entry, just like we did before.

"frameworks": {
        "aspnet50": { },
        "aspnetcore50": {
            "dependencies": {
                "log4net": "2.0.3"
            }
        }
    }

After saving the file, we should be able to see that the dependency was only added to the Core CLR runtime.

6

Final Note

As we have seen, managing dependencies has become easier with ASP.NET Core 1.0. I like this new approach of adding and removing dependencies by editing a json file. It seems much simpler and cleaner than the approaches offered in previous versions of ASP.NET.

It also removes the need for using Visual Studio. The only tool we need is a regular text editor from which we can update the project.json file.

0 comments , permalink


23

Mar 16

Bower Packages in ASP.NET Core 1.0



Bower is a Node.js tool to manage front-end dependencies. It’s a package manager just like NuGet, but for front-end libraries. With this tool, we can add things like jQuery, Angular or Bootstrap to our project.

In this post, I will explain how to use Bower to manage front-end dependencies in our ASP.NET Core 1.0 project.

Installing Node.js

To install Bower, we need to have Node.js installed on our machine. Visual Studio 2015 installs Node.js by default, so you may already probably have it on your computer. If not, you can download and install it from here.

To verify that Node.js is installed correctly, open the Command Prompt (or Powershell) and type the following command:

> Node

The output should indicate that we just opened the interactive node.js shell, from which we can start executing JavaScript code directly.

0

If for any reason, we get a _”node is not recognized as an internal or an external command”_ , make sure Node is added to the Windows PATH environment variable.

Installing Bower

Now that Node is installed correctly in our system let’s proceed to install Bower. We are going to do this with the help of NPM, a package manager for Node. With this tool, we can install things like Gulp, Grunt or in our case, Bower.

To install Bower enter the following command:

> npm install g bower

The ‘g’ stands for ‘global’, this option installs the package globally so that we can run it from everywhere as a command.

Managing front-end packages

If everything went correctly, we should now have Bower installed on our machine. It’s time to take advantage of this awesome tool and start adding our favorites front-end libraries to our project.

There are two main options to manage Bower packages in an ASP.NET Core 1.0 project: from the bower.json file or from the Command Prompt.

The bower.json file is the Bower manifest file, from which we can track all the packages that are used by our project. This file is very similar to the project.json file that we use to manage NuGet packages and other dependencies.

We can add a bower.json file to our project very easily from Visual Studio. From the Solution Explorer, right-click on the project> Add> Bower JSON Configuration File

2

Now that the bower.json file is part of our project, let’s add the AngularJs library. To do this, create a new entry under the dependencies section of the bower.json file. This entry will contain the name and the version of the package we want to add.


{
    "name": "BowerApp.Properties",
    "private": true,
    "dependencies": {
        "angular": "1.3.15"
    },
    "exportsOverride": {
    }
}

Notice that Visual Studio provides Intellisense to help us to select among all the Bower packages available. By the way, you can find a list of all the Bower packages that are currently available here.

We now save the changes, and AngularJs should be added automatically to our project. But before we verify this fact we are going to add another package, however, this time we are going to do it from the Command Prompt.

Let’s add for example Font Awesome, a font and CSS toolkit for web applications. We can install this package just by entering the following command:

> bower install font-awesome –save

The new package should now be a dependency of our project. If we go back to our bower.json file we can see that a new entry for the Font Awesome package was added.

{
  "name": "BowerApp",
  "private": true,
  "dependencies": {
    "angular": "1.3.15",
    "font-awesome": "~4.3.0"
  },
  "exportsOverride": {}
}

What if we want to remove an existing dependency? We again have two options; we can either delete the entry for the package from the bower.json file or use the following command from the Command Prompt:

> bower uninstall angular

If what we want is to update the version of one of our dependencies, update the version number directly in the bower.json file, or from the Command Prompt:

> bower update angular

And this will update the package to the latest version available.

Personally I find editing the bower.json file a much easier approach than from the Command Prompt, but both methods are very simple and easy to use.

Viewing the list of Bower dependencies

The easiest way to know what dependencies are included in our project is by looking at the bower.json file. Whatever dependencies are included in this file will be the ones included in our project.

Even if the dependencies are not physically on our machine but are added to this file, they will be downloaded and installed automatically the first time the project is compiled.

This is a very useful feature because it removes the need of including the dependency files when checking in our code to the source control. We only need to check in the bower.json file that will already the list of project dependencies.

We can also view the Bower dependencies included in our project from the Solution Explorer. They are listed under Dependencies -> Bower

7

Or even from the Command Prompt just by typing in the following command:

> bower list

Finally, if what we want is to access the physical files of our Bower packages we should go to the bower-component folder, at the root of our project. This is the place where Bower dependencies are placed by default.

8

0 comments , permalink


14

Mar 16

Sometimes, Hue just need a quick REST



(Warning: This post contains terrible jokes about “Hue” sounding like “you”.  Prepare knee for slapping.)

Hue caught my eye as soon as Hue got here. Herein lies the epic of my trials and tribulations with Hue, my Friends.

Episode One: The One Where Hue get invited to the party

I grew up in theater, both on- and back-stage. From there, I gained a love for being able to set the mood to anything you can imagine just by tweaking the colors around you. It only makes sense then, that my apartment became my palate. I started decorating with light around 2010, before Hue was a glimmer – and I did it using RGB LED stage lighting fixtures. For those unfamiliar, stage lighting elements are generally controlled using a protocol called DMX512. I found a USB>DMX interface, and wrote an application to control the variety of styles of lights scattered around my apartment. I won’t go into too much detail about that here, because I already have a blog post about it over at Fervent Geek.

Once Hue was released, I was immediately suckered in and started acquiring additional colorful lighting apparatuses – this time communicating using Hue’s own protocols rather than DMX. Sadly, this meant that I had two completely independent applications controlling the lights in my apartment – not the greatest scenario. To add to the complexity, everything in my apartment is automated. The lights turn on white when I need to wake up, green when I need to finish breakfast, red when I need to be out the door, off during the day, back on white in the evening, blue when I need to go to bed, and off when I should be in bed. Configuring that setup on multiple independent platforms was a pain. Changing it for holidays where I didn’t want that schedule to occur was untenable. Something would have to be done. But first, Hue had some expanding to do.

Episode Two: The One Where Hue Learn a New Language

About a year ago, I was able to take on a project to decorate the game room at Clarity’s office. Given my penchant for light-decorated rooms, it was only natural for me to select some Hue lighting to allow the room to take on a festive slant. Once it was in place, it was simple enough to set the lighting schemes using the mobile app on my personal phone to set the scene. However, I began getting inquiries from other people that were interested in writing custom applications to control the lights in various creative ways.

Hue has a great API available that allows some pretty advanced control – but there’s an application registration and authentication process that adds a bit of a barrier to entry. To make it as simple as possible for people to use the lights in their applications, I wrote a REST wrapper for the Hue API that exposed POST and GET web interfaces to allow control of the lights using ridiculously simple web requests. Anyone in the office could now get the state of all the lights, and set the lights to any color they wanted – with next to no effort.

Episode Three: The One where Hue Plays Nicely with Others

This wrapper application wasn’t just useful at the office. By running the same bridging application for the Hue network at home, and creating a new type of lighting fixture within my DMX lighting control application that set the state of lights using web requests, I was able to add the Hue lights into the same application that controls the DMX lights – bringing all the lighting in my apartment back under a single point of control. Finally.

To further expand the capabilities, I extended the DMX control application itself (not just the Hue bits) to expose the same interface for requesting and setting the state of the DMX lights that it controls. Now, the Hue lights and the DMX lights can all be controlled using the same URL formats (just hitting different URLS, one hosted by the Hue Bridge application, and one hosted by the DMX control application). This opens the doors for some pretty fancy web-based control applications that integrate multiple types of lights, across multiple locations. I haven’t written a UI for that yet, but it’s on my to-do list.

Episode Four: The One Where Hue Get a Job

I discussed in a previous post an application I wrote to track the state of conference rooms. Hue lights were a natural fit to be an indicator of the status of conference rooms for people waiting outside, and a means for notifying the participants inside. I already had a Hue API wrapper written for the lights in the game room, so all I had to do was allow the application to run multiple instances against different Hue networks (since they’re too far apart to connect to each other), and I could use the same simple web interface from the Conference Companion to set the lights to indicate all sorts of things for the conference rooms.

Episode Five: The One Where Hue’re Forgetful

When native Hue bulbs (as opposed to Friends of Hue) lose power, they always default to bright white when power is restored. When you have a bunch of Hue bulbs in a room in the office that’s on a motion sensor, this is really annoying, as I keep finding them white when they’re supposed to be festive. Unfortunately, this is not something that Phillips plans to change, according to Steve. So what’s a developer to do? Find a workaround, of course!

I already had the Bridge application running that had the ability to query for the state of lights. One of the properties that you can get is ‘Reachable’ – ie can the Hue network reach the bulb. Presumably, if a bulb is unreachable, it has lost power. So, I just set up a periodic poll of the system to track when bulbs go from reachable to un-reachable. When they do lose connection, I store the previous state they were in, and once the bulb becomes reachable once again, set the state of the bulb to what it was before it became un-reachable. Additionally, if the bridge application receives a request to change the color of a bulb while it is unreachable, it will save that color and set the bulb to it once it’s reachable again. Since the core color recovery is not dependent on an internal ‘scene’ that the bulb should be (but rather the observed state before power loss), if another person changes the color of the lights, the color that they recover to will be whatever the other person set it to be.

So there’s where we find ourselves.  Hue continues to provide lots of opportunities for interesting projects – the limit is only what you can come up with to use it for (well, and budget).  Don’t be surprised if Hue come up again…

0 comments , permalink


9

Mar 16

Dependency injection in ASP.NET Core 1.0



Dependency injection is at the heart of ASP.NET Core 1.0 Much has been written about it since last year, but in this article I would like to provide a simple example of how to use dependency injection to inject a service in an ASP.NET Core 1.0 Controller.

To achieve this, we will create an ASP.NET Core 1.0 application that displays the weather forecast. This application will be able to use two different services: WeatherService, which uses WeatherNet to provide real weather forecast, and WeatherService2, which as you will see later, is not a very reliable forecast provider.

Later in the article, I will demonstrate how easy it is to modify our application and switch between these two services.

Creating the service

The first thing we need to do is to create an interface that our services can implement. This interface will only have one method, which will provide the weather forecast based on a location.

public interface IWeatherService
{
    string GetWeather(string city, string country);
}

Once we have the interface, we create a new class that will contain the service implementation. This service we will retrieve and return the weather forecast using WeatherNet, based on the city and country parameters.

public class WeatherService :IWeatherService
{

    public string GetWeather(string city, string country)
    {
        var wClient = new WeatherNet.Clients.CurrentWeather();
        var weather = wClient.GetByCityName(city, country)
                      .Item.Description;
        
        return string.Format(
           "WeatherService {0} in {1} ({2})",
            weather, city, country);
    }
}

Now, we add the WeatherService2 implementation in a new class. This service will not retrieve the weather using any third party. Instead, it will make the assumption that there is heavy snow everywhere. A little bit scary, right? ;)

public class WeatherService2 : IWeatherService
{

    public string GetWeather(string city, string country)
    {
        var weather = "Heavy Snow";
        
        return string.Format(
           "WeatherService2 {0} in {1} ({2})",
            weather, city, country);
    }
}

In our sample application, I put the three classes in three different files under a Service folder created in the root folder.

1

Injecting the service into the controller

It’s time to inject the service to our Controller. To do this, we create a Controller constructor, which is going to take an IWeatherService implementation as a parameter. We also create a private field so that it’s available to the rest of the methods of the Controller.

IWeatherService _weatherService;
public HomeController(IWeatherService weatherService)
{
     _weatherService = weatherService;
}
 

Now we want to use the injected service in the Index method of our Controller to return the weather forecast. To keep it simple, the parameters will be hard coded in this method.

[HttpGet("/")]
public string Index()
{
    return _weatherService.GetWeather("Miami", "US");
}

Registering the service

Now let’s do some magic and use the new dependency injection feature that comes with ASP.NET Core 1.0.

In the Startup.cs file we have a ConfigureService method, which we need to add the following line to register our service in the application:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddInstance(new WeatherService());
}

This line means that every time our app needs an instance of IWeatherService, the WeatherService implementation will be used.

Notice that we have used the AddInstance method to register our service, this is going to provide the same service instance for each HTTP request that uses the service. However, in some cases we may want to create a new instance every time that the service is used. In this case, we can use something like the AddTransient method, which will provide a new instance of the service every time it’s needed:

services.AddTransient<IWeatherService>(x=> new WeatherService());

Running the application!

We now run our application and observe how, as expected, the sky is clear in Miami. This seems right to me, and means that our WeatherService implementation was used.

2

If, for any reason, we want to use WeatherService2, we just need to modify the ConfigureServices method.

public void ConfigureServices(IServiceCollection services)
{
      services.AddMvc();
      services.AddInstance(new WeatherService2());
}

Let’s run our application again, and voilà. Heavy snow in Miami, which means that this time our application used the WeatherService2 implementation.

3

0 comments , permalink


29

Feb 16

PowerShell Skype Trusted Pool Creator



In one of my previous posts, I shared a PowerShell tool to wrap the management of Skype Trusted Applications within a Windows Forms GUI, provided via a PowerShell script. In it, I alluded to another tool I’d written that wraps the process of creating Trusted Application Pools and Applications – well here it is!

This is another full Windows Forms application, embedded within a PowerShell scriptlet. You can create Trusted Application Pools (selecting the registrar from a dropdown), add servers to any Pool you’ve created, create Trusted Applications assigned to any pool, and add initial Trusted Endpoints to and Pool. All these actions can be done via script fairly easily, this just abstracts away a lot of the lookups that often need to happen for syntax and related server information.

EndpointCreator

Like the other scriptlet, loading the commands can be done either by opening Skype PowerShell and launching the scriptlet manually, or creating a new Skype PowerShell shortcut that loads both the Skype or Lync scriptlets into PowerShell as well as the application scriptlet. You can do this my adding &’{filePath.ps1}’ to the end of the default Skype for Business PowerShell shortcut target path.

And the script:

# Set up the form
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = “Clarity Connect Lync Application Creator”
$objForm.Size = New-Object System.Drawing.Size(820,230)
$objForm.StartPosition = “CenterScreen”
$registrars = Invoke-Expression ‘Get-CsPool | Where-Object {$_.Services –match “Registrar:”} | Select-Object Fqdn’ #identity has name info
$sites = Invoke-Expression “Get-CsSite | Select-Object SiteId”
$trustedAppPools = Invoke-Expression “Get-CsTrustedApplicationPool | Select-Object PoolFqdn”
$trustedApps = Invoke-Expression “Get-CsTrustedApplication | Select-Object ApplicationId”
$endpoints = Invoke-Expression “get-cstrustedapplicationendpoint | Select-Object SipAddress”
# Set up Create Pool area ==============================================================
$poolLabel = New-Object System.Windows.Forms.Label
$poolLabel.Location = New-Object System.Drawing.Size(0,0)
$poolLabel.Size = New-Object System.Drawing.Size(200,20)
$poolLabel.Text = “Create Pool”
$objForm.Controls.Add($poolLabel)
$poolFqdn = New-Object System.Windows.Forms.TextBox
$poolFqdn.Location = New-Object System.Drawing.Size(20,20)
$poolFqdn.Size = New-Object System.Drawing.Size(200,30)
$poolFqdn.Text = “Pool FQDN”
$objForm.Controls.Add($poolFqdn)
$poolRegistrar = New-Object System.Windows.Forms.ComboBox
$poolRegistrar.Location = New-Object System.Drawing.Size(240,20)
$poolRegistrar.Size = New-Object System.Drawing.Size(200,30)
[void] $poolRegistrar.Items.Clear()
foreach ($registrar in $registrars)
  {
    [void] $poolRegistrar.Items.Add($registrar.Fqdn)
  }
$objForm.Controls.Add($poolRegistrar)
$poolServerFqdn = New-Object System.Windows.Forms.TextBox
$poolServerFqdn.Location = New-Object System.Drawing.Size(460,20)
$poolServerFqdn.Size = New-Object System.Drawing.Size(200,30)
$poolServerFqdn.Text = “Server FQDN”
$objForm.Controls.Add($poolServerFqdn)
$poolCreate = New-Object System.Windows.Forms.Button
$poolCreate.Location = New-Object System.Drawing.Size(700,20)
$poolCreate.Size = New-Object System.Drawing.Size(80,20)
$poolCreate.Text = “Create Pool”
$objForm.Controls.Add($poolCreate)
$poolCreate.add_Click(
  {
    $poolLocalFqdn = $poolFqdn.Text
    $poolLocalRegistrar = $poolRegistrar.Text
    $poolRegistrarSiteData = Invoke-Expression “Get-CsPool -Identity $poolLocalRegistrar | Select-Object Site”
    $poolRegistrarSite = $poolRegistrarSiteData.Site
    $poolLocalSiteData = Invoke-Expression “Get-CsSite -Identity `”$poolRegistrarSite`” | Select-Object SiteId”
    $poolLocalSite = $poolLocalSiteData.SiteId
    $poolLocalServerFqdn = $poolServerFqdn.Text
    $items = Invoke-Expression “New-CsTrustedApplicationPool -Identity $poolLocalFqdn -Registrar $poolLocalRegistrar -Site $poolLocalSite -ComputerFqdn $poolLocalServerFqdn”
    $trustedAppPools = Invoke-Expression “Get-CsTrustedApplicationPool | Select-Object PoolFqdn”
    [void] $serverFqdn.Items.Clear()
    foreach ($trustedAppPool in $trustedAppPools)
      {
        [void] $serverFqdn.Items.Add($trustedAppPool.PoolFqdn)
      }
    [void] $appPool.Items.Clear()
    foreach ($trustedAppPool in $trustedAppPools)
      {
        [void] $appPool.Items.Add($trustedAppPool.PoolFqdn)
      }
  })
# Set up Add Pool Server area ==============================================================
$serverLabel = New-Object System.Windows.Forms.Label
$serverLabel.Location = New-Object System.Drawing.Size(0,50)
$serverLabel.Size = New-Object System.Drawing.Size(200,20)
$serverLabel.Text = “Add Server to Pool”
$objForm.Controls.Add($serverLabel)
$serverPool = New-Object System.Windows.Forms.ComboBox
$serverPool.Location = New-Object System.Drawing.Size(20,70)
$serverPool.Size = New-Object System.Drawing.Size(200,30)
[void] $serverPool.Items.Clear()
foreach ($trustedAppPool in $trustedAppPools)
  {
    [void] $serverPool.Items.Add($trustedAppPool.PoolFqdn)
  }
$objForm.Controls.Add($serverPool)
$serverFqdn = New-Object System.Windows.Forms.TextBox
$serverFqdn.Location = New-Object System.Drawing.Size(240,70)
$serverFqdn.Size = New-Object System.Drawing.Size(200,30)
$serverFqdn.Text = “Server FQDN”
$objForm.Controls.Add($serverFqdn)
$serverCreate = New-Object System.Windows.Forms.Button
$serverCreate.Location = New-Object System.Drawing.Size(700,70)
$serverCreate.Size = New-Object System.Drawing.Size(80,20)
$serverCreate.Text = “Add Server”
$objForm.Controls.Add($serverCreate)
$serverCreate.add_Click(
  {
    $serverLocalPool = $serverPool.Text
    $serverLocalFqdn = $serverFqdn.Text
    $items = Invoke-Expression “New-CsTrustedApplicationComputer -Identity $serverLocalFqdn -Pool $serverLocalPool”
  })
# Set up Create Application area ==============================================================
$appLabel = New-Object System.Windows.Forms.Label
$appLabel.Location = New-Object System.Drawing.Size(0,100)
$appLabel.Size = New-Object System.Drawing.Size(200,20)
$appLabel.Text = “Create Application”
$objForm.Controls.Add($appLabel)
$appName = New-Object System.Windows.Forms.TextBox
$appName.Location = New-Object System.Drawing.Size(20,120)
$appName.Size = New-Object System.Drawing.Size(200,30)
$appName.Text = “clarityconnect”
$objForm.Controls.Add($appName)
$appPool = New-Object System.Windows.Forms.ComboBox
$appPool.Location = New-Object System.Drawing.Size(240,120)
$appPool.Size = New-Object System.Drawing.Size(200,30)
[void] $appPool.Items.Clear()
foreach ($trustedAppPool in $trustedAppPools)
  {
    [void] $appPool.Items.Add($trustedAppPool.PoolFqdn)
  }
$objForm.Controls.Add($appPool)
$appPort = New-Object System.Windows.Forms.TextBox
$appPort.Location = New-Object System.Drawing.Size(460,120)
$appPort.Size = New-Object System.Drawing.Size(100,30)
$appPort.Text = “10022″
$objForm.Controls.Add($appPort)
$appCreate = New-Object System.Windows.Forms.Button
$appCreate.Location = New-Object System.Drawing.Size(700,120)
$appCreate.Size = New-Object System.Drawing.Size(80,20)
$appCreate.Text = “Create App”
$objForm.Controls.Add($appCreate)
$appCreate.add_Click(
  {
    $appLocalName = $appName.Text
    $appLocalPool = $appPool.Text
    $appLocalPort = $appPort.Text
    $items = Invoke-Expression “New-CsTrustedApplication -ApplicationId $appLocalName -TrustedApplicationPoolFqdn $appLocalPool -Port $appLocalPort”
    $appTopo = Invoke-Expression “Enable-CsTopology”
    $trustedApps = Invoke-Expression “Get-CsTrustedApplication | Select-Object ApplicationId”
    [void] $endpointApplication.Items.Clear()
    foreach ($trustedApp in $trustedApps)
      {
        [void] $endpointApplication.Items.Add($trustedApp.ApplicationId)
      }
  })
# Set up Create Application Endpoint area ==============================================================
$endpointLabel = New-Object System.Windows.Forms.Label
$endpointLabel.Location = New-Object System.Drawing.Size(0,150)
$endpointLabel.Size = New-Object System.Drawing.Size(200,20)
$endpointLabel.Text = “Create Endpoint”
$objForm.Controls.Add($endpointLabel)
$endpointApplication = New-Object System.Windows.Forms.ComboBox
$endpointApplication.Location = New-Object System.Drawing.Size(20,170)
$endpointApplication.Size = New-Object System.Drawing.Size(200,30)
[void] $endpointApplication.Items.Clear()
foreach ($trustedApp in $trustedApps)
  {
    [void] $endpointApplication.Items.Add($trustedApp.ApplicationId)
  }
$objForm.Controls.Add($endpointApplication)
$endpointSip = New-Object System.Windows.Forms.TextBox
$endpointSip.Location = New-Object System.Drawing.Size(240,170)
$endpointSip.Size = New-Object System.Drawing.Size(200,30)
$endpointSip.Text = “sip:clarityconnect@domain.com”
$objForm.Controls.Add($endpointSip)
$endpointDisplayName = New-Object System.Windows.Forms.TextBox
$endpointDisplayName.Location = New-Object System.Drawing.Size(460,170)
$endpointDisplayName.Size = New-Object System.Drawing.Size(100,30)
$endpointDisplayName.Text = “Clarity Connect”
$objForm.Controls.Add($endpointDisplayName)
$endpointCreate = New-Object System.Windows.Forms.Button
$endpointCreate.Location = New-Object System.Drawing.Size(700,170)
$endpointCreate.Size = New-Object System.Drawing.Size(100,20)
$endpointCreate.Text = “Create Endpoint”
$objForm.Controls.Add($endpointCreate)
$endpointCreate.add_Click(
  {
    $endpointapplicationId = $endpointApplication.SelectedItem
    $endpointapplicationData = Invoke-Expression “Get-CsTrustedApplication -Filter *$endpointapplicationId | Select-Object TrustedApplicationPoolFqdn”
    $endpointPool = $endpointapplicationData.TrustedApplicationPoolFqdn
    $endpointLocalDisplay = $endpointDisplayName.Text
    $endpointLocalSip = $endpointSip.Text
    $items = Invoke-Expression “New-CsTrustedApplicationEndpoint -ApplicationId $endpointapplicationId -TrustedApplicationPoolFqdn $endpointPool -SipAddress $endpointLocalSip -DisplayName `”$endpointLocalDisplay`”"
    $endpoints = Invoke-Expression “get-cstrustedapplicationendpoint | Select-Object SipAddress”
    $endpointSip.Text = “sip:clarityconnect@domain.com”
    $endpointDisplayName.Text = “Clarity Connect”
  })
# Activate the form
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

Comments Off , permalink


22

Feb 16

PowerShell Skype Application Endpoint Manager



There’s an interesting limitation placed on Lync and Skype Trusted Application Endpoints, where only one incoming PSTN number can be assigned per endpoint. While there are various ways to work around this with custom applications, in a standard environment, this may mean that you have a lot of endpoints to manage for a given application.

In addition to that, if you work in an environment that has a lot of trusted applications configured (for example, if you work for a company that does UCMA development…), chances are good that you’ve got tens or hundreds of Trusted Applications floating around.

Managing all those applications and endpoints is done through the brilliance of PowerShell Commandlets. While managing them through PowerShell works wonderfully, sometimes you just want a glance-able interface where you can make quick manual changes without searching or scanning through lists and lists of shell results.

Did you know that you can create a full Windows Forms application using Powershell? No? Now you do! To help manage all the endpoints that were configured for applications, I made a Windows Forms application inside a powershell script that wraps the powershell commands to create and maintain endpoints within a more user-friendly interface. I have another similar application that’s used for creating Trusted Application Pools and their Applications, which I’ll include in a future post.

EndpointManager

Loading the commands can be done either by opening Skype PowerShell and launching the scriptlet manually, or creating a new Skype PowerShell shortcut that loads both the Skype or Lync scriptlets into PowerShell as well as the application scriptlet.  You can do this my adding &’{filePath.ps1}’ to the end of the default Skype for Business PowerShell shortcut target path.

The script itself:

[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = “Clarity Connect Lync Endpoint Manager”
$objForm.Size = New-Object System.Drawing.Size(1190,500)
$objForm.StartPosition = “CenterScreen”
# Set up the application list ==============================================================
$applicationsList = New-Object System.Windows.Forms.Listbox
$applicationsList.Location = New-Object System.Drawing.Size(20,20)
$applicationsList.Size = New-Object System.Drawing.Size(300,400)
$applications = Invoke-Expression “Get-CsTrustedApplication | Select-Object ApplicationId”
[void] $applicationsList.Items.Clear()
[void] $applicationsList.Items.Add(“All”)
foreach ($application in $applications)
  {
      [void] $applicationsList.Items.Add($application.ApplicationId)
  }
$objForm.Controls.Add($applicationsList)
$applicationsList.add_Click(
  {
    $applicationId = $applicationsList.SelectedItem
    $endpointDetails.Text = “”
    $teluriUri.Text = “”
    $displayName.Text = “”
    $teluriSet.Enabled = $False
    $displayNameSet.Enabled = $False
    $endpointList.Items.Clear()
    if($applicationId -eq “All”) {
      $items = Invoke-Expression “Get-CsTrustedApplicationEndpoint | Select-Object SipAddress”
      if ($items –ne $Null)
      {
        foreach ($item in $items)
        {
          [void] $endpointList.Items.Add($item.SipAddress)
        }
        $endpointCreate.Enabled = $False
      }
    }
    else
    {
      if ($applicationId –ne $Null)
      {
        $items = Invoke-Expression “Get-CsTrustedApplicationEndpoint -ApplicationId $applicationId | Select-Object SipAddress”
        if ($items –ne $Null)
        {
          foreach ($item in $items)
          {
            [void] $endpointList.Items.Add($item.SipAddress)
          }
          $endpointCreate.Enabled = $True
        }
      }
    }
  })
# Set up the endpoint box ==============================================================
$endpointList = New-Object System.Windows.Forms.Listbox
$endpointList.Location = New-Object System.Drawing.Size(340,20)
$endpointList.Size = New-Object System.Drawing.Size(300,400)
[void] $endpointList.Items.Clear()
$objForm.Controls.Add($endpointList)
$endpointList.Add_Click(
  {
    $endpointSip = $endpointList.SelectedItem
    if($endpointSip -ne $null)
    {
      $endpointDetails.Text = Invoke-Expression “(Get-CsTrustedApplicationEndpoint -Identity $endpointSip | Format-List | Out-String).Trim()”
      $endpointData = Invoke-Expression “Get-CsTrustedApplicationEndpoint -Identity $endpointSip | Select-Object LineUri, DisplayName”
      $teluriUri.Text = $endpointData.LineUri
      $displayName.Text = $endpointData.DisplayName
      $teluriSet.Enabled = $True
      $displayNameSet.Enabled = $True
    }
  })
# Set up the endpoint details box ==============================================================
$endpointDetails = New-Object System.Windows.Forms.TextBox
$endpointDetails.Location = New-Object System.Drawing.Size(660,20)
$endpointDetails.Size = New-Object System.Drawing.Size(500,200)
$endpointDetails.Multiline = $True
$endpointDetails.Wordwrap = $True
$endpointDetails.ReadOnly = $True
$objForm.Controls.Add($endpointDetails)
# Set up Assign Tel URI area ==============================================================
$teluriLabel = New-Object System.Windows.Forms.Label
$teluriLabel.Location = New-Object System.Drawing.Size(660,230)
$teluriLabel.Size = New-Object System.Drawing.Size(200,20)
$teluriLabel.Text = “Assign Tel URI”
$objForm.Controls.Add($teluriLabel)
$teluriUri = New-Object System.Windows.Forms.TextBox
$teluriUri.Location = New-Object System.Drawing.Size(660,250)
$teluriUri.Size = New-Object System.Drawing.Size(200,30)
$teluriUri.Text = “”
$objForm.Controls.Add($teluriUri)
$teluriSet = New-Object System.Windows.Forms.Button
$teluriSet.Location = New-Object System.Drawing.Size(880,250)
$teluriSet.Size = New-Object System.Drawing.Size(120,20)
$teluriSet.Text = “Set Tel URI”
$teluriSet.Enabled = $False
$objForm.Controls.Add($teluriSet)
$teluriSet.add_Click(
  {
    $items = Invoke-Expression ‘Set-CsTrustedApplicationEndpoint -Identity $endpointSip -LineUri $teluriUri.Text’
    $endpointDetails.Text = Invoke-Expression “(Get-CsTrustedApplicationEndpoint -Identity $endpointSip | Format-List | Out-String).Trim()”
  })
# Set up Assign Display Name area ==============================================================
$displayNameLabel = New-Object System.Windows.Forms.Label
$displayNameLabel.Location = New-Object System.Drawing.Size(660,280)
$displayNameLabel.Size = New-Object System.Drawing.Size(200,20)
$displayNameLabel.Text = “Assign Display Name”
$objForm.Controls.Add($displayNameLabel)
$displayName = New-Object System.Windows.Forms.TextBox
$displayName.Location = New-Object System.Drawing.Size(660,300)
$displayName.Size = New-Object System.Drawing.Size(200,30)
$displayName.Text = “”
$objForm.Controls.Add($displayName)
$displayNameSet = New-Object System.Windows.Forms.Button
$displayNameSet.Location = New-Object System.Drawing.Size(880,300)
$displayNameSet.Size = New-Object System.Drawing.Size(120,20)
$displayNameSet.Text = “Set DisplayName”
$displayNameSet.Enabled = $False
$objForm.Controls.Add($displayNameSet)
$displayNameSet.add_Click(
  {
    $items = Invoke-Expression ‘Set-CsTrustedApplicationEndpoint -Identity $endpointSip -DisplayName $displayName.Text’
    $endpointDetails.Text = Invoke-Expression “(Get-CsTrustedApplicationEndpoint -Identity $endpointSip | Format-List | Out-String).Trim()”
  })
# Set up Create Application Endpoint area ==============================================================
$endpointLabel = New-Object System.Windows.Forms.Label
$endpointLabel.Location = New-Object System.Drawing.Size(20,420)
$endpointLabel.Size = New-Object System.Drawing.Size(200,20)
$endpointLabel.Text = “Add Endpoint to Application”
$objForm.Controls.Add($endpointLabel)
$endpointSipUri = New-Object System.Windows.Forms.TextBox
$endpointSipUri.Location = New-Object System.Drawing.Size(20,440)
$endpointSipUri.Size = New-Object System.Drawing.Size(200,30)
$endpointSipUri.Text = “sip:clarityconnect@domain.com”
$objForm.Controls.Add($endpointSipUri)
$endpointDisplayName = New-Object System.Windows.Forms.TextBox
$endpointDisplayName.Location = New-Object System.Drawing.Size(240,440)
$endpointDisplayName.Size = New-Object System.Drawing.Size(200,30)
$endpointDisplayName.Text = “Clarity Connect”
$objForm.Controls.Add($endpointDisplayName)
$endpointCreate = New-Object System.Windows.Forms.Button
$endpointCreate.Location = New-Object System.Drawing.Size(460,440)
$endpointCreate.Size = New-Object System.Drawing.Size(100,20)
$endpointCreate.Text = “Create Endpoint”
$endpointCreate.Enabled = $False
$objForm.Controls.Add($endpointCreate)
$endpointCreate.add_Click(
  {
  if($applicationId -ne “All”) {
      $applicationId = $applicationsList.SelectedItem
      $applicationData = Invoke-Expression “Get-CsTrustedApplication -Filter *$applicationId | Select-Object TrustedApplicationPoolFqdn”
      $poolFqdn = $applicationData.TrustedApplicationPoolFqdn
      $display = $endpointDisplayName.Text
      $sip = $endpointSipUri.Text
      $invoked = Invoke-Expression “New-CsTrustedApplicationEndpoint -ApplicationId $applicationId -TrustedApplicationPoolFqdn $poolFqdn -SipAddress $sip -DisplayName `”$display`”"
      $items = Invoke-Expression “Get-CsTrustedApplicationEndpoint -ApplicationId $applicationId | Select-Object SipAddress”
      [void] $endpointList.Items.Clear()
      if ($items –ne $Null)
      {
        foreach ($item in $items)
        {
          [void] $endpointList.Items.Add($item.SipAddress)
        }
      }
      $endpointDisplayName.Text = “Clarity Connect”
      $endpointSipUri.Text = “sip:clarityconnect@domain.com”
    }
  })
# Activate the form
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

Comments Off , permalink


1

Feb 16

Clarity Conference Companion



Meetings. An ever-present tenant of the average office workday that can be simultaneously a source of extraordinarily useful discussions and fuel for distressingly Dilbertesque tediousness.
As you may know, I’m a fan of efficiency, especially when it involves creating ways to have interactions with inanimate objects. The restrooms in our office are already internet-connected – so why not conference rooms? Once you have a seed of an idea like that, it’s hard for it to not run rampant. Which then gave rise to…

The Clarity Conference Companion

Part 1: Getting the Data

EWS, or Exchange Web Services, is an API that Microsoft Exchange exposes that allows you to query mailboxes, calendars, and other objects hosted by Exchange. In general, if you want to get calendar events for a mailbox, you can perform a FindAppointments request using the ExchangeService with the appropriate filters. However, for that to work, you need to have permissions granted on that account (like your own account, or someone whose calendar you manage). While this is perfect for the normal use scenario, I needed to be able to look at the availability of all the conference room accounts – which I do not have permissions to see.

Enter, the Scheduler. When you’re setting up a new meeting, the Scheduler tab can display a basic set of information for each person on the meeting to help you determine the best time to schedule so that everyone can make it. Importantly, you do not need to have permissions on any of the other mailboxes in order to see the data. By requesting from the ExchangeService GetUserAvailability and specifying a FreeBusyViewType of Detailed, I can get back from mailboxes I don’t have explicit access to all their appointments, as well as the Subjects – which generally maps to the person who organized the meeting.

Spin up a quick console application that uses EWS to grab the schedule for each room, and bam. Data acquired.

Part 2: Setting Status

Our office is heavily invested in Skype for Business, and we use it extensively for both communication and presence. Additionally, each desk has a Busylight, which is a physical representation of each person’s presence state to help real-world passers-by know who’s available to talk and who’s not.

A good first step in this application was to add in the ability to see, from outside the room, what the room’s “Presence” state is at the moment. Since I already had the calendar schedule for the room, it was a relatively trivial task to trigger “something” when a meeting was starting soon (so you don’t go into a room for an ad-hoc meeting, only to find it booked minutes later), currently in progress, or if the room was free.

But what should that “something” be, exactly?

The most obvious thing was to allow people in the office to be able to see the status using their Skype for Business client. Step one was to spin up a UCMA Platform in my application – there are tons of other posts about that, so I won’t wax on about it. Once our system administrator enabled all the room accounts for Skype, I had my UCMA platform register UserEndpoints for each room. Then, when one of those events occurred that should cause ‘something’ to happen, I updated the appropriate UserEndpoint with the new state of the room (green if available, red if booked, yellow if it will be in use shortly), as well as a tag of the current user (if applicable).  If you find that resource accounts are not showing presence, try logging out of and back into your Skype client – I found that was necessary for accounts that had never been logged into using an actual Skype client.

So that covered people sitting at their desks, but what about people wandering through the office looking for an empty room? Enter: Phillips Hue.

I placed a Hue light outside the conference room, and got that hooked up so it could be updated via a simple web request. Adding a bit to my ‘something’ method, I instruct the Hue light to update to the appropriate color at the same time I update the Skype endpoint’s presence state. Then, just like the Busylights we have at desks, we now had a real-world indicator of the state of the room sitting right outside the door.
2016-01-29 12.26.26

Whether virtual or physical, we had status. But now that the basics are down, what else could we do to add value?

Part 3: Notifications

Keeping track of when a meeting in a conference room is getting close to ending can be a real problem. It’s very easy to become embroiled in a discussion and completely forget what time it is, until the next people that have the room reserved are bashing down the door – or a 15 minute standup has escalated to an hour-long dialog. If only there were a way to subtly tell the people in the room that they should start wrapping up their meeting (without derailing a critical discussion…

Once again, Enter: Phillips Hue.

Placing another Hue light inside the room, I had my application set this light using notifications that would be useful to those actually in the meeting room. If the room is available, it’s green. Meeting starting soon? Flip it to yellow to give anyone having an impromptu meeting a heads up that something’s happening soon. It’s turned off while a meeting is in progress, but turns yellow when there are 5 minutes left in the scheduled meeting to remind those inside to start wrapping up. When a meeting is over, it will flash red if another meeting is scheduled immediately afterward, or to green if the room is available and extending the meeting won’t impact anyone else.

It’s a small thing, but giving people in the room a subtle heads up to start wrapping up their meeting has gotten more positive feedback than anything else.

2016-01-29 12.29.052016-01-29 13.34.59

Part 4: Interaction

It’s a simple “fact”: if you have a UserEndpoint that you’re publishing presence for, you should give it a personality too. And so the full Conference Companion was born.

I added logic that would allow each conference room to accept IMs, and respond about the availability of the room based on the request.

If you send a generic IM, it tells if you if it is currently available and the schedule for the rest of the day – including when it’s next occupied. If it’s not available, it tells you when it’s free, and also suggests other rooms that show as available at the moment.

If you include a time in your IM, it tells you about the room’s availability today at that particular time – as well as everything else previously mentioned. If you include a duration (like 30 minutes or 1 hour), it’ll tell you if the room will be free for the duration of your requested meeting – either now or at the time specified, if you did so.

Interaction

Joining the restrooms, Clarity’s conference rooms gained a little bit of intelligence.  What’s next?

1 comment , permalink


9

Sep 15

K2 Check Box List Control and WCF services



There are multiple approaches to implementing multi-value fields in K2 SmartForms. Using the Check Box List control is a very powerful one. This post demonstrates how to use this control with a WCF service to load and save data.

First, we will populate a Check Box List with all the possible values that users will be able to select. Then, we will process and save the selection made by the user. Last, will be to load different selections to the control depending on the user.

For this demo, I have created a new CheckBoxListExample view and added a Check Box List control.

1

Populating the Control

For data populating purposes, the Check Box List is not much different from other K2 controls. The only thing we need to do is define a data-source along with a Key and a Display property.

Let’s then create a service method that we can use as data-source.

The following method will return a list of data objects. Each of them will be a color that will have both, a Key, and a Name property.

public List GetAllColors()
{
     var colors = new List();

     colors.Add(new ListData { Key = "B", Name = "Blue" });
     colors.Add(new ListData { Key = "R", Name = "Red" });
     colors.Add(new ListData { Key = "Y", Name = "Yellow" });
     colors.Add(new ListData { Key = "G", Name = "Green" });
     colors.Add(new ListData { Key = "O", Name = "Orange" });

     return colors;
}

After publishing the service, we add our method to a Smart Object, making sure that the Key and Name properties of our colors are mapped correctly.

2

Now is time to use the new method as data-source for our Check Box List control.

Let’s open the Configure Data Source dialog (Control Properties -> Data Source section -> Type) and let K2 know that we want to use the new method as data-source. We also want the Key property to be the value of the items, and the Name property to be the text displayed.

3

After saving the changes and running the view, we can see how the control is populated with the values coming from the service method that we created.

4

Sending Selected Data

The control is now filled with real data, what enables users to make selections. The next natural step is to store these selections to a more persistent storage system, like a database.

Here is where things get a little tricky, but only a little.  The Check Box List control sends the list of selected values in XML format.

As an example, the XML sent when the colors Blue (B) and Green (G) are selected looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<collection>
   <object parentid="d7058dc8-e2af-4ebc-85dc-87d918e7585b" parenttype="Object">
      <fields>
         <field name="Key">
            <value>B</value>
         </field>
         <field name="Key">
            <value>G</value>
         </field>
      </fields>
   </object>
</collection>

The “value” nodes are the ones containing the Key property of the selected options. So we will need to create a method in our service that processes this XML and extract these values.

We can do this in many different ways, but a very simple approach is to use the XmlTextReader class to retrieve these values and put them into something more manageable, like a list of strings. Later, we could use this list to store the values in the database.

The following method will process the selected options taking the mentioned approach.

public void SaveUserColors(string userName, string colorsXML)
{
      var selection = new List<string>();
      using (XmlTextReader tr = new XmlTextReader(new StringReader(colorsXML)))
      {
          bool canRead = tr.Read();
          while (canRead)
          {
             if (tr.Name == "value")
             {
                 canRead = tr.Read();
                 if (!string.IsNullOrEmpty(tr.Value) && !selection.Contains(tr.Value))
                 {
                     selection.Add(tr.Value);
                 }
             }
             else
             {
                 canRead = tr.Read();
             }
          }
     }

     SaveUserColorsToDb(userName, selection);

 }

Let’s add now the method to the Smart Object.

5

Once the Smart Object is deployed is time to call the new method from the view. For this purpose, I have created a Drop-Down List control, to display the different users in our application, and a Save button that will trigger the saving functionality.

6

A new action to call the Smart Object method will need to be set on the “Clicked”  button rule.

7

In this call, we need to pass the Check Box List control, along with the Users Drop-Down, as arguments.

8

After saving the changes and running the view, we can make now a color selection, specify a user in the Drop-Down and send this data to the service by clicking on the Save button. Our service method should take care of processing this data.

9

Setting User’s Selection

So far we have seen how to populate the Check Box List control and send the colors selected to the service so that they can be stored in a database. Let’s see now how we can set a particular set of options in our control.

To do this, we need to pass a semi-colon separated list with the values of the colors we desire to set in the control. For example, if we want to set Blue and Green in the control, we will need to pass the string “B;G;”.

Knowing this, let’s create a service method that returns a different list of colors,  in the required format, depending on the user specified.

public string GetColorsByUser(string userName)
{
    var sb = new StringBuilder();

    if (userName == "mdelarosa")
    {
          sb.Append(string.Format("{0};", "B"));
          sb.Append(string.Format("{0};", "G"));
    }
    else
    {
          sb.Append(string.Format("{0};", "Y"));
    }

    return sb.ToString();
 }

Let’s now add the method to the Smart Object.

10

And let’s make some changes to the UI.  Our view will now have a Populate User Colors button that will set the Check Box List control, to the colors chosen by the user specified in the Drop-Down.

11

We now call the new Smart Object method from the ‘Clicked’ button rule and pass the user in the parameter.

13

Finally, we assign to the Check Box List the list of colors returned

14

After saving the changes and running the view, we can see how the colors set in the control change depending on the user selected.

15

16

229 comments , permalink


3

Sep 15

Our Summer with Parse



Intro
We have been using Parse as the backend platform for a Web site and iOS app for a few months now and wanted to share some of our feedback (Pros, Cons, and Gotchas) on a few of the functional areas. My team’s primary focus of the project was the integration of the Website with Parse using the JavaScript SDK.

Data
Parse offers a noSQL database with a web-based UI, called the Data Browser, to support management of the classes and the associated data.
Each record by default is assigned the following fields: objectId (to serve as the row’s unique identifier), createdAt (to capture the date/time of initial creation), updatedAt (to capture the date/time of when the record was last updated), and ACL (to control the read/write permissions for that particular record).

Pros:
• Parse supports more complex data types such as GeoPoint (for storing the latitude and longitude of a particular location), Array, File (for file storage within Parse), Pointer (the typical Foreign Key relationship) and Relation (to store a one to many relationship).
• Parse can easily extract all of your data. You initiate a request in the Parse Dashboard and Parse emails you a zip file of JSON files – one file per table. I would usually then copy the content of the files into an online JSON viewer to visualize the data better, e.g. http://jsonviewer.stack.hu
Cons:
• The Data Browser only allows you to view one class at a time, although it does support easy navigation to other classes if there is a Pointer or Relation on the class. Coming from a SQL Server background I was used to writing queries in Management Studio and seeing multiple results in one window that were sorted by one or more specified columns. This particular project was not as complex as some of my past projects, so navigating between classes and noting the objectIds wasn’t too painful.
Gotchas:
• The ability to update values directly in the Parse Dashboard Data Browser is a blessing and a curse. It makes direct inserts and updates quick to execute without having to write query statements, but since changes are committed immediately there is no way to rollback. Use caution when updating a value, deleting a row, or deleting a column since it cannot be undone/rolled back.
• If an object is failing to save without an intuitive message, double check the Class Level Permissions for the object which is an Advanced setting under the Security option. This caught us once because even though the row-level permission was correct, the Write / Update permission at the class level was disabled for some reason and we were unable to update a record. The error message we recevied wasn’t too informative.
Security / Edit Class Level Permissions
Advanced Settings
Cloud Code
Parse supports running code in the Parse Cloud, which they host as Cloud Code. The Cloud function can be invoked from the client SDKs and through the REST API. Parse also supports integration with third parties via the Cloud Code. In our implementation we overwrote the beforeSave and afterSave methods for certain objects in order to take another action when a record was being inserted/updated. We also integrated with Stripe as a payment mechanism.

Pros:
• The Cloud Code is very easy to deploy to the server via a command line.
• The Parse Dashboard supports viewing the actual file contents of the deployed Cloud Code. Normally, tracking of build versions or files’ modified dates is the only way to infer what version of the code was running on the server. By seeing the actual code, you can confirm if functionality was actually deployed or if it somehow got missed.
• The integration with Stripe was easy to implement with the Cloud Code.
Cons:
• Logging functionality is present but not as robust as other implementations I have used on .NET projects such as log4net’s ability to log to a rolling file or database for better auditability and monitoring.
Gotchas:
• The beforeSave and afterSave methods were helpful when writing code to affect other tables. Occasionally there was a gotcha in that the original record that was being inserted/updated did not have permission to update a record in the other table due to ACL permissions. Luckily you can overwrite that restriction with the useMasterKey call which allows the code to execute under the master user account instead of the user initiating the request.
useMasterKey sample call

Config
Parse supports configuration values at the app level. In our implementation we used a handful of config values to manage variables that could change.

Pros:
• The Parse Dashboard has an interface which makes it easy to add and update configuration parameters. A config parameter can be any of Parse’s supported data types:
Config Parameter Types
• The config value is available by the system on the next read and is retrieved by a simple get() call.
Retrieving a config value
API Console
The API Console is a great built-in feature to allow you to easily test API calls. No real Pros/Cons come to mind, but just make sure you are using the correct action for what you are trying to execute.
API Console
Analytics
Parse provides a mechanism to monitor the real-time health of your system in a visual way. For our particular project we just grazed the surface of its capabilities by using the Parse.Analytics.track call to track client-side errors, but we will be looking into this more as our project moves to Production to analyze things such as API Requests, Slow Queries, etc.
Analytics example
Gotchas:
• The track method is expecting string values for the keys. In our case we were receiving numeric error codes and tried to pass them to the track method as-is in the array, but it was generating an error on the client-side which we noticed by having the Developer Tools / Console window open. To get around it we had to force the error.code value to a string first:
Analytics call
User Management
Parse automatically handles many of the capabilities necessary for user account management. Actions such as signing up, logging in, resetting a forgotten password, and even integration with Facebook are all built-in. With our implementation we added a requirement for a user’s password to be at least 6 characters via client-side validation.

Misc. Feature
Clone App – this feature was great to have when we started on Phase 2 but did not want to recreate the whole backend from scratch. We were able to clone our main environment to use as a base for our next version effortlessly.
Clone App
Summary
Overall we have enjoyed our summer developing with Parse and are looking forward to exploring even more what Parse has to offer. Functionality such as Background Jobs and more advanced Analytics are just a few of the areas we will be looking into for Phase 2. Check out their expansive Documentation on their site for more information.

10 comments , permalink


20

Jul 15

Restroom Monitor Mark II



Have you ever found yourself in need of answering nature’s secondary call, walking across the office to heed it, only to find that all the stalls are in use? <sarcasm>Being situated at the far end of the office, this was a very serious issue</sarcasm> – or at least I could pretend it was to give myself enough of an excuse to do something about it. If only there was a way to know, before ever leaving your desk, if your call would be able to be answered in peace or not.

The concept is simple – determine the state of a restroom and put it somewhere that it can be checked before heading over. A similar system was installed many years ago using wireless, battery-powered magnetic switches updating a website – but the very obvious boxes were vandalized and required frequent maintenance. My objective was to make something completely invisible (and that wouldn’t make people uncomfortable – as restroom tracking could easily do) and impervious to all but the most malicious sabotage – while providing a seamless way to check the state.

The restrooms in question are private rooms (not just stalls), with their own door and deadbolt – the door is always closed, and the occupancy is determined by the position of the deadbolt, which also has a red/green flag on the front of the door. One of the main concerns about this project was doing it in such a way that it wouldn’t make anyone uncomfortable – which would rapidly kill the project – invasion of privacy lawsuits can be expensive. A wide variety of methods of determining state were considered and discarded:

  • Motion sensor – too much like a camera and bad for long visits, tough to get a definitive state
  • Infrared sensor – too much like a camera and visible
  • Red/green color sensor looking at flag – too much like a camera
  • Magnetic switch or door hinge rotation sensor – can’t tell if the door is locked or not
  • Deadbolt induction sensor – too fragile
  • Switch connected to a Bluetooth dongle to communicate – sitting inside a metal door frame could have connectivity issues and the battery would have to be replaced

I eventually settled on a deadbolt switch designed specifically for commercial installation, wired through the door frame to above the dropped ceiling (isn’t drilling holes in the office walls fun?). The switch sits inside the deadbolt pocket (so is not visible), is designed for industrial usage (so won’t break with repeated use), and is wired so that connectivity is perfect and there are no batteries (so requires no maintenance). The switch I used was this deadbolt pocket switch.

DeadboltPocketSwitch

Once you have a way to determine the state of the restroom, the next step is to be able to read the state and send it somewhere. After working with a couple different microcontrollers, I decided to use the Spark Core because of the on-board WiFi and extremely easy development/deployment process. After working with it, I could not recommend it highly enough. After using the phone application to connect it to wifi and tie it to your account, you update the microcontroller by coding the application on their web IDE, then pushing the automatically verified and compiled code to the device over the public internet. It’s one step short of pure magic – and a drastic and welcome change from the microcontrollers I’ve worked with in the past. All that aside, it’s a simple task to have the Core receive input from the switch when it changes, then POST notifications when it receives a changed state from the switch over WiFi to a listening service endpoint. The microcontroller is wired into power from a standard mains to USB power supply – again, removing any dependency on battery maintenance.

I did experiment with using USB battery packs to see what kind of battery life I could get – and ran into an interesting behavior.  The battery packs that automatically turn on do so by monitoring the current dropped across the power pins.  They also automatically turn off when too low a draw is detected – assuming that nothing is actually using the power.  To conserve power draw, I disabled the WiFi on the microcontroller when not actively transmitting a changed switch state.  While this did save energy, it also made the power draw low enough (<10 mA) that the battery pack automatically turned itself off thinking that nothing was plugged in.  To get around this, I wired up a transistor circuit to put a 50 millisecond draw across the power pins (through a resistor) every 7 seconds (suggested by this article).  This was effective in keeping the device on – but the biggest battery pack I could find (20,000 mAh) only lasted about a week.  In the interest of a platform requiring zero maintenance, I instead decided to hook up a USB wall wart power supply and wire that in rather than relying on battery power.

SparkCore

The two grey wires go through the wall, down the frame, and to the two door switches (via Molex connectors for easier maintenance), the lower black cable is power from a USB wall wart, and the upper black cable goes to the indicator lights – more on that later)

On the other side of the POST request, I have a Windows Service running on a server, which is self-hosting both an HTTP endpoint for the microcontroller to call with switch state changes, as well as a Skype for Business platform and user endpoints representing each restroom. Since everyone at Clarity is on our internal IM client all day (Lync/Skype for Business), it’s logical that we’d look there for the state of the restrooms. Since Skype for Business endpoints already have a presence state associated with them that shows red/green, it’s an absolutely perfect fit to have endpoints for each restroom that can be Available or Busy, according to the status of the switch on the physical room. Welcome to the internet of things (or places)!

S4BRestroomStatus

So that’s all nice and dandy!  Indicators on our computers getting the state of the restroom – that seems good enough.  Yea, I wasn’t happy with “good enough” either – it just wasn’t quite over-the-top enough yet.  Clearly, more was needed.

I printed 3D models of toilets (can I just say how much I love the previous 6 words?) on the office 3D printer (MakerBot 2) using clear plastic filament, and embedded LED lights into the back of them (hot glue to the rescue). Since the microcontroller already knows the state of the switches and is able to put out a very convenient 5 volt current that can drive the LEDs, it was a simple task to wire up the translucent toilets to lit LEDs indicating their respective state – functioning as remote physical indicators for the rooms that could be glanced at before heading down the hallway to the doors themselves.  As a side note, I used an Ethernet cable to go from the microcontroller to the RGB LEDs – 3 power sinks per light plus one shared voltage source needed 7 wires to run to the models, and Ethernet cables are a very convenient 8 strands, and are easily available in an office.  I wired up female connectors from Ethernet ‘extension’ cable to both ends, so that the light is easy to disconnect and can use standard Ethernet cables of whatever length is needed to run the distance without having to re-solder the pins.  In the picture above, it’s the upper black wire that I said I would mention later.

RestroomStatusIndicators

Next, since the Skype for Business endpoints that were showing the presence for the restrooms already support IM very easily (and were coming in to an application that I controlled), why not allow the restroom endpoints to have conversations? I added the ability for the endpoints to respond to inquiries about usage for the day with some basic statistics (from the aforementioned state change data), suggest places for lunch (randomized, suggesting 3 different cuisines from a database of over 50 places in the immediate vicinity), and tell jokes (all of them awful – from a database collection of several thousand).

Some people seem to have a thing about using a restroom when the seat still carries warmth from the last occupant. To accommodate those folks, I added in a ‘cool-down’ period, based on how long it eas occupied. Y’know, because it was absolutely necessary.

RestroomConversation

Finally, since data was getting sent to the service anyway with each switch change, I set up a database that the historical changes could be written to. This way, we can compile all sorts of utterly useless statistics about restroom usage, preference between the two, peak times of day, etc. What better information is there to offer at quarterly meetings?

RestroomGraph

And with that, the Pooper Snooper Mark II (er… Restroom Monitor) was born. 

41 comments , permalink