Monday, May 28, 2012

Resetting local Ports and Devices from .NET

Currently, I am working on C# applications that communicate with several external devices connected via USB ports. In rare cases the ports just stop working correctly, so we needed a programmatic approach to reset them. Doing this by using C# is not trivial. The solution we implemented uses the following components:
-          C#’s SerialPort class
-          WMI (Windows Management Instrumentation)
-          P/Invoke with calls to the Windows Setup API

Accessing a port using C#
Using a certain port with C# is rather simple. The .NET framework provides the SerialPort class as a wrapper to the underlying Win32 port API. You can simply create a new instance of the class by providing the name of an existing port. On the instance object you have methods to open or close the port or to read and write data from its underlying stream. It also provides events to notify any listeners when data or errors were received. Here is a small example on how to open a port by first checking if the given port name exists in the operating system:

public SerialPort OpenPort(string portName)
{
    if (!IsPortAvailable(portName))
    {
        return null;
    }

    var port = new SerialPort(portName);

    try
    {
        port.Open();
    }
    catch (UnauthorizedAccessException) { ... }
    catch (IOException) { ... }
    catch (ArgumentException) { ... }
}

private bool IsPortAvailable(string portName)
{
    // Retrieve the list of ports currently mounted by
    // the operating system (sorted by name)
    string[] ports = SerialPort.GetPortNames();
    if (ports != null && ports.Length > 0)
    {
        return ports.Where(new Func<string, bool>((s) =>
        {
            return s.Equals(portName,
                            StringComparison.InvariantCultureIgnoreCase);
        })).Count() == 1;
    }
    return false;
}

In rare cases the Open method of the port threw an IO Exception in our applications. This situation was not reproducible but also not acceptable. We noticed that after deactivating the port in the device manager and reactivating it, everything was working fine again. So we searched for a solution to do exactly the same thing from code.

Enable/Disable Devices
First of all a function or set of functions was needed to disable and enable a certain port. This can not directly be done from C# and needs some P/Invoke calls to the Win32 API. Luckily others had similar problems and so I found a very good solution at http://www.eggheadcafe.com/community/csharp/2/10315145/enabledisable-comm-port-by-programming.aspx. It uses the device installation functions from the Win32 Setup API. All you need is to retrieve the class GUID for the device set and the instance Id for the specific device you want to disable or enable. Just have a look at the link for the code or download the accompanying code for this blog post.

Retrieving the Ports Instance Id
Last thing to do is to acquire the correct instance Id for our port. We need a method that takes in the port name and retrieves the corresponding instance Id. For the exact definition of an instance Id in windows terms have a look at http://msdn.microsoft.com/en-us/library/windows/hardware/ff541224(v=vs.85).aspx. In our case we’d like to use the Plug ‘n’ Play device Id that can also be seen in the properties window of a device inside the device manager. For this purpose we are going to use WMI. If you need information about WMI have a look at http://msdn.microsoft.com/en-us/library/windows/desktop/aa394582(v=vs.85).aspx. WMI provides the Win32_SerialPort class that can be used to iterate over all mounted ports of the operating system. Two properties of the Win32_SerialPort class are important for us: The DeviceID property which represents the port name and the PNPDeviceID which gives the Plug ‘n’ Play instance Id. Notice while this works perfectly for Plug 'n' Play devices it may not work for other kinds of devices.

ManagementObjectSearcher searcher =
    new ManagementObjectSearcher("select * from Win32_SerialPort");
foreach (ManagementObject port in searcher.Get())
{
    if (port["DeviceID"].ToString().Equals(portName))
    {
        instanceId = port["PNPDeviceID"].ToString();
        break;
    }
}

If we found the appropriate instance Id we can use it together with the Win32 Setup API to retrieve a device info set and the corresponding device info data. If a device info for the instance Id was found we can use its class GUID and the instance Id to disable and enable the device. The following method is used to reset a port with a given instance Id:

public static bool TryResetPortByInstanceId(string instanceId)
{
    SafeDeviceInfoSetHandle diSetHandle = null;
    if (!String.IsNullOrEmpty(instanceId))
    {
        try
        {
            Guid[] guidArray = GetGuidFromName("Ports");

            //Get the handle to a device information set for all
            //devices matching classGuid that are present on the
            //system.
            diSetHandle = NativeMethods.SetupDiGetClassDevs(
                ref guidArray[0],
                null,
                IntPtr.Zero,
                SetupDiGetClassDevsFlags.DeviceInterface);

            //Get the device information data for each matching device.
            DeviceInfoData[] diData = GetDeviceInfoData(diSetHandle);

            //Try to find the object with the same instance Id.
            foreach (var infoData in diData)
            {
                var instanceIds =
                        GetInstanceIdsFromClassGuid(infoData.ClassGuid);
                foreach (var id in instanceIds)
                {
                    if (id.Equals(instanceId))
                    {
                        //disable port
                        SetDeviceEnabled(infoData.ClassGuid, id, false);
                        //wait some milliseconds
                        Thread.Sleep(200);
                        //enable port
                        SetDeviceEnabled(infoData.ClassGuid, id, true);
                        return true;
                    }
                }
            }
        }
        catch (Exception)
        {
            return false;
        }
        finally
        {
            if (diSetHandle != null)
            {
                if (diSetHandle.IsClosed == false)
                {
                    diSetHandle.Close();
                }
                diSetHandle.Dispose();
            }
        }
    }
    return false;
}

With the code set up so far we can now easily reset a port in case we’re getting an IO Exception while trying to open the port. We just have to call the method inside our exception handler and try to open the port again. That solved our initial problem. Be aware that it may take some time to disable and re-enable the port. It may be a good idea to do it inside a separate thread if you’re working inside an application using a GUI.


Download the sample code file: PortHelper.cs

Monday, May 21, 2012

Conference Papers .NET Day Franken

Lately I had the great pleasure to speak at the german community conference .NET Day Franken. I was talking about HTML 5 Canvas and its posibilities to display native animations, visual effects and even 3D in the browser. It was a lot of fun for me and I'd like to provide the presentation as well as the demos here for download. Please feel free to contact me if you have any questions regarding the provided material.

Downloads: Presentation | Demos

Thursday, May 17, 2012

Video Manipulation with HTML 5 Canvas

No doubt that the HTML 5 Canvas is currently one of the most popular HTML 5 elements. Its pixel manipulation and drawing APIs provide a broad range of possibilities to create interactive content natively integrated into the web browser. In this blog post I’m going to show you how to implement a simple video filter application using the Canvas Image API and a little bit of JavaScript. Don’t be afraid, it won’t hurt.

The reason why the Canvas element is so popular is its native integration into the web browser. No plugin needed to display animated graphics or interactive content. I guess everyone knows that there are platforms that don’t support Flash or Silverlight, but still provide web access. This is where Canvas comes into play. For sure, it’s not nearly matured like Flash and there are no advanced development environments but it seems very promising and is just at its beginning.

Canvas Image API.
Let’s do some theory first in order to understand what we’re doing later. The Image API provides the following three JavaScript functions:


-          drawImage(Image, dx, dy)
-          drawImage(Image, dx, dy, dw, dh)
-          drawImage(Image, sx, sy, sw, sh, dx, dy, dw, dh)
The first and second functions are very simple. They provide the ability to draw an image at the given position (dx, dy) with the given size (dw, dh). Nothing extraordinary so far. The third function enables you to cut off a piece of the image and place that piece right onto the canvas. The parameters starting with ‘s’ can be used to determine a region in the source image. With the ‘d’ parameters the region can be placed anywhere in the current canvas. For the video sample we will only use the first function. I’m going to demonstrate the use of the third function in a future blog post.

Another functionality provided by the Image API is the ImageData object. This object represents the current content of the Canvas and has only one property, the data property. The data property is a single dimensional array containing all the pixel values of the current image. There are four bytes in the array per pixel in the following order:


So this is exactly what we need to manipulate image or in this case video data. A single frame of a video is nothing else but an image.
There’s one additional hint I’d like to give here. Pay attention when manipulating the image data object while you’re in the development process. For security reasons it is not allowed to get the image data of the canvas when you run a local HTML file. You will receive a DOM Security Exception and your page will not be displayed. Sometimes you won’t see the exception (depends on the browser you are using) and just wonder why you don’t see anything. To avoid this problem start the web site from inside a local web server.

Manipulating the Video.
We’ll have a very simple setting for our web app. We’re just going to display a video and according to a selected filter display the result of the filter operation next to the original. Here is the HTML Body for this setting:

<body>
    <p>
        <select id="filterFunctionSelector">
            <option value="None">None</option>
            <option value="Invert">Color Inversion</option>
            <option value="Edge">Edge Detection</option>
            <option value="Blur">Blur</option>
        </select>
    </p>
    <video id="sourcevid" autoplay="true" loop="true">
        <source src="BigBuckBunny_640x360.mp4" type="video/mp4"/>
        <source src="BigBuckBunny_640x360.ogv" type="video/ogg"/>
    </video>
    <canvas width="640" height="360" id="outputCanvas"></canvas>
    <canvas width="640" height="360" id="sourceCanvas" style="visibility:
hidden"></canvas>
</body>

Notice that I used the new HTML 5 Video element. It’s great because you just need to provide the several video formats and the browser uses the first one it can display. No more nasty object or embed tags. For the demo I used an extract from the big buck bunny video at www.bigbuckbunny.org.
I defined two Canvas elements whereas the source Canvas will not be displayed on the web site. It just takes the current video frame and serves as source for manipulating the image data object. You could also draw directly to the output Canvas but by using an intermediate canvas that is not visible, you save some CPU power while there is no video filter selected.
Let’s have a look at the JavaScript code for displaying the manipulated video:
var destCanvasCtx = document.getElementById('outputCanvas').getContext('2d');
var sourceCanvasCtx = document.getElementById('sourceCanvas').getContext('2d');
var video = document.getElementById('sourcevid'); 

function drawFrame() {
    destCanvasCtx.clearRect(0, 0, destCanvasCtx.canvas.width,
  destCanvasCtx.canvas.height);    sourceCanvasCtx.drawImage(video, 0, 0); 

    var select = document.getElementById("filterFunctionSelector");
    var value = select.value; 

    if (value == 'None')
        return; 

    var input = sourceCanvasCtx.getImageData(0, 0, sourceCanvasCtx.canvas.width,
sourceCanvasCtx.canvas.height);
    var output = destCanvasCtx.createImageData(destCanvasCtx.canvas.width,
destCanvasCtx.canvas.height);
               

    if (value == 'Invert')
        invertColor(input, output);
    else if (value == 'Edge')
        edgeDetection(input, output);
    else if (value == 'Blur') {
        destCanvasCtx.drawImage(video, 0, 0);
        blur(destCanvasCtx, 10);
        return;
    }
    destCanvasCtx.putImageData(output, 0, 0);
}
setInterval(drawFrame, 40);

This is not as bad as it looks. Believe me! First we’re getting a reference to the canvas elements and the displayed video. We then define a function that will be called every 40 milliseconds. This is a little bit more than the 23 frames per second the video has. So we have enough time to apply the filter and draw the result to the output canvas.
Let’s take a closer look at the drawFrame function. First we clear the output canvas and draw the current video frame to the intermediate canvas. Notice the drawImage function. By using the getImageData function from the source canvas we get the pixel data of the current frame. The createImageData function creates an empty pixel array from the output canvas. According to the currently selected filter function, we pass both ImageData objects to the appropriate function. As an example I will show you the invertColor function here:
function invertColor(input, output) {
    var inputData = input.data;
    var outputData = output.data; 

    for (var i = 0; i < inputData.length; i += 4) {
        outputData[i] = 255 - inputData[i];
        outputData[i + 1] = 255 - inputData[i + 1];
        outputData[i + 2] = 255 - inputData[i + 2];
        outputData[i + 3] = 255;
    }
}


The function is very easy. It just iterates over the input pixel data and sets the manipulated values to the output array. When the function returns to the drawFrame function, the output array contains the complete image frame and can be drawn to the output canvas by using the putImageData function. Here is an image of the result in the browser with the applied edge detection filter:

Just one more hint: Applying image filters with software rendering has mostly not a good performance. For color inversion and edge detection it was no problem. But there is a blurring filter too. First I tried to implement a real blurring filter but it turned out to be very slow in the several browsers. After searching the web I found that others had the same problem. You can find a very elegant solution here: http://www.flother.com/blog/2010/image-blur-html5-canvas/. The approach is to just draw several copies of the current image whereas each copy is offset one pixel around the original one and is displayed with some opacity. So it’s not a real filter algorithm but it gives the impression of a blurred image and provides the needed speed for a video.

Summary
The Canvas element is very powerful and it is exciting to see all the possibilities lying within it. As I mentioned at the beginning of this post it has just started and there is still a lot of work to do when it comes to browser support and appropriate development environments. Just give it a try and find out for yourself if Canvas has something to offer for you.