Wednesday, July 01, 2009

It's now easier than ever to evaluate Padarn, our ASP.NET Web Server for Windows CE.  We now have available an Evaluation Kit that comes with:

  • A 600MHz fanless Windows CE 6.0 device
  • 13 hands-on labs with full source code
  • A full sample Padarn web site with source code
  • Fully-functional Padarn evaluation binaries

The kit is being offered at an introductory price of $300.00, and if that isn't enough to convince you, we'll even credit that against any purchase of Padarn you make.

For more information, see the Padarn web site.

7/1/2009 4:06:15 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Monday, June 29, 2009

The latest version of our Padarn Mobile Server supports VirtualPathProviders.  This means that now it is easy to create REST Web Services that run on your Windows CE or Windows Mobile device.  Download the latest hands-on lab "HOL P303 - Using VirtualPathProviders in Padarn to provide REST Web Services" from the web site here.

6/29/2009 1:31:39 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Wednesday, May 13, 2009

We've been doing a ton of internal work lately on our Padarn ASP.NET Web Server for Windows CE - both on features as well as just the general stuff you have to do to have a product.  Part of this work was to create a series of hands-on labs to demonstrate how to use Padarn effectively.  The PDFs (a dozen in all so far), along with the latest Developer's Guide are available for public viewing on the Padarn Downloads page.

5/13/2009 7:47:53 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Thursday, May 29, 2008

We're just about to release a new version of Padarn, out ASP.NET Web Server for Windows CE.  This version brings SSL support as well as Basic and Digest authentication.  Another part of this release was trying to keep the footprint reasonably small.  Here's a screen shot of all of the assemblies needed for the entire engine implementation:

padarnfootprint.PNG

So yes, we have an ASP.NET web server with SSL and authentication support and it's just 305KB - and half of that is for SSL alone.

 

5/29/2008 12:26:56 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Monday, January 21, 2008
A customer asked us to integrate a new camera with Padarn recently (the D-Link DCS-900) to try to do a similar thing that I had done in my PTZ camera demo.  Well this camera was a little different and a whole lot easier to get "streaming" data from.  I ended up writing a small wrapper class that takes the MJPG data coming from the camera, parses it into in-memory Image classes, and then those are available for use.

Once I had that I figured it would be interesting to serve up a Padarn page that did nothing but return the latest frame data from that camera - after all the camera doesn't support PTZ and just a button that takes a picture didn't seem terribly new or informative. 

The problem was that the version of Padarn I was using (1.0.5020) didn't support writing a stream of bytes to the Response.  Well as of 1.0.5030 Padarn now supports WriteBytes (and a few other things like CacheBehavior) and I created a page that dynamically loads the images into an on-page IFrame and allows you to adjust the refresh rate dynamically without ever having to send a full page request in again.

I can see that this could be useful for dynamic updates to a page for something like a control system gauge or for animating building automation status items.

Check out the new sample here.

The code for the DCS-900 looks like this (notice that the ICamera interface changed a little, so the PTZ camera also had to be altered.  I simply stubbed out the new methods).

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using OpenNETCF.Peripherals.Camera;

namespace OpenNETCF.Peripherals
{
  public class DCS900 : ICamera
  {
    private Image m_lastImage = null;
    private volatile bool m_stopThread = true;
    Thread m_grabberThread;
    private IPAddress m_ip;

    public DCS900()
    {
    }

    public void Initialize(IPAddress ipAddress, string userName, string password)
    {
        m_ip = ipAddress;
    }

    public bool SupportsPanTilt
    {
        get { return false; }
    }

    private int FindFrameBoundary(byte[] data, int offset, int maxLength)
    {
        byte[] frameDelimiter = Encoding.ASCII.GetBytes("--video boundary--");
        int n = 0;
        bool match;

        for (; offset < maxLength; offset++)
        {
            match = true;
            if (data[offset] == frameDelimiter[n])
            {
                match &= true;
                n++;
                if (n >= frameDelimiter.Length)
                {
                    // we've found the header
                    return offset + 1;
                }
            }
            else
            {
                match = false;
                n = 0;
            }
        }

        return -1;
    }

    private Image ImageFromFrameData(byte[] data, int frameLength)
    {
        int start = 50;

        // find the data start - it will be between 50 and 54 bytes in from the frame start
        while (data[start] != 0xFF)
        {
            start++;
            if (start > 54) return null;
            if (data[start + 1] == 0xD9) break;
        }

        try
        {
            using (MemoryStream stream = new MemoryStream(data, start, frameLength - start))
            {
                Image image = new Bitmap(stream);
                stream.Close();
                return image;
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }

        return null;
    }

    public void Start()
    {
        m_grabberThread = new Thread(GrabberThreadProc);
        m_grabberThread.IsBackground = true;
        m_grabberThread.Start();
    }

    public void Stop()
    {
        m_stopThread = true;
    }

    public bool IsRunning
    {
        get { return !m_stopThread; }
    }

    private void GrabberThreadProc()
    {
        lock (m_grabberThread)
        {
            m_stopThread = false;

            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Connect(new IPEndPoint(m_ip, 80));

            string header = "GET /VIDEO.CGI HTTP/1.0\r\nUser-Agent: user\r\nAuthorization: Basic YWRtaW46REVVU1Q=\r\n\r\n";
            byte[] data = Encoding.ASCII.GetBytes(header);
            byte[] image = new byte[32768]; // 32k buffer is more than adequate for this camera

            s.Send(data);

            data = new byte[2048];

            int offsetStart = 0;
            int offsetEnd = 0;
            int ptr = 0;

            int length = s.Receive(data);

            do
            {
                offsetStart = FindFrameBoundary(data, 0, length);
            } while (offsetStart < 0);

            while (!m_stopThread)
            {
                offsetEnd = FindFrameBoundary(data, offsetStart, length);

                while (offsetEnd < 0)
                {
                    int copyLength = length - offsetStart;
                    Buffer.BlockCopy(data, offsetStart, image, ptr, copyLength);
                    offsetStart = 0;
                    ptr += copyLength;

                    length = s.Receive(data);
                    offsetEnd = FindFrameBoundary(data, offsetStart, length);
                }

                if (ptr > 50)
                {
                    Buffer.BlockCopy(data, offsetStart, image, ptr, offsetEnd - 18);
                    ptr += offsetEnd - 18;

                    m_lastImage = ImageFromFrameData(image, ptr);

                }
                offsetStart = offsetEnd;
                ptr = 0;

                Thread.Sleep(200);
            }

            s.Close();
        }
    }

    public Image GetImage()
    {
        return m_lastImage;
    }

    public void Pan(PanDirection direction)
    {
        throw new NotSupportedException();
    }

    public void Tilt(TiltDirection direction)
    {
        throw new NotSupportedException();
    }
  }
}


1/21/2008 7:56:46 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, December 13, 2007
Today we rolled out an update to Padarn: version 1.0.5010.

"So what's new," you ask? 

  1. We added support for the Page.Request.Browser property.  On the surface it seemed quite simple, but the implementation was actually quite a challenge.
  2. We fixed a bug that Page.Request.Headers always came back null
  3. We updated the SampleSite demo including:
    1. Updates and additions to the OpenNETCF.Web.Html namespace
    2. A new Camera Demo page that controls a camera in our "server closet"
    3. A page showing hosting the WMP control service media off of Padarn
    4. A page that shows client browser capability detection
The docs and live page are updated - you can reach them both from here:  www.opennetcf.com/padarn.ocf


We are also now offering Padarn free of charge for academic use.  Contact us for details.

12/13/2007 7:26:16 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  |