Laurent Ellerbach

Internet of Things, IoT, Arduino, Netduino, Galileo, Spark.IO, NETMF, .NET Microframework and other embedded gadgets :-)

  • Laurent Ellerbach

    Securing web server with login and password on .NET Microframework

    • 1 Comments

    If you want to expose your .NET Microframework web server on the Internet you better have to make sure it is protected. Even if you keep the URL secret, it will not stay secret Sourire it’s not a good way to protect it! A better way if you have to expose it is to use a login and a password. Still not the best way but reasonably ok. To add more security, use https on your board. But if you are using a netduino board like me, the https web server is a big too big and will not fit. So I’ve decided to use login/password.

    the good news is that you already have classes to be able to implement a login and password very easily. First read this post to understand how to implement a web server. In the main function ProcessClientGetRequest, just add at the beginning of the function the following code:

    string strResp = "<HTML><BODY>netduino sprinkler<p>";
    bool IsSecured = false;
    if (request.Credentials != null)
    { // Parse and Decode string.
        Debug.Print("User Name : " + request.Credentials.UserName);
        Debug.Print("Password : " + request.Credentials.Password);
        // if the username and password are right, then we are authenticated
        if (request.Credentials.UserName == MyLogin && 
    request.Credentials.Password == MyPassword) { IsSecured = true; } } //if not secured display an error message. And return the function if (!IsSecured) { strResp += "<p>Authentication required<p>Invalid login or password"; response.StatusCode = (int)HttpStatusCode.Unauthorized; response.Headers.Add("WWW-Authenticate: Basic realm=\"netduino sprinkler\""); strResp += "</BODY></HTML>"; byte[] messageBody = Encoding.UTF8.GetBytes(strResp); response.ContentType = "text/html"; response.OutputStream.Write(messageBody, 0, messageBody.Length); return; }

    The IsSecured boolean is there to check if the login and password are valid. by default it is set at false. Then the request.Credentials contains the login credentials. If they are not null, you can just check if they are the right ones. UserName contains the user name and guess what, Password contains the password. Not rocket science there Sourire just compare them with the one you want to use. By default the authentication type is basic. So login and password are send in clear mode. Not the most secure but unfortunately like most of the internet protocol still use for mail like POP and other protocols like that. Again, to get more protection, use https if you can on your board.

    .NET Micro framework web server object also support Windows Live authentication. As I’m doing this code in a plane from Moscow to Dubai, quite hard to test it!

    request.Credentials.AuthenticationType = AuthenticationType.Basic;
    request.Credentials.AuthenticationType = AuthenticationType.WindowsLive;

    Those are the 2 modes. If I have the opmportunity, I’ll test the Windows Live one. If anyone do the test, please let me know!

    The rest of the code is pretty straight forward, it’s just about displaying an error message with the HttpStutusCode as Unauthorized. And just return the function before the end. Very efficient to protect all site and all pages. The good news is that you will not have to authenticate to access all pages, it will be carry on from one page to another up to when you’ll close your browser and come back. I do not recommend to store any login/password on any of your pc, or device. Always type them!

    If you want to store somewhere the login and password, you can store it on the SD card of your board. If your board is store in a secure location in your house and not accessible, you may not need to crypt the login and password. And anyway if the person has access to your board controlling some equipment, it’s probably too late. But if you need, crypt it on the storing location.

    Here is a code example how to read this login and password from a file.

    if (Microsoft.SPOT.Hardware.SystemInfo.IsEmulator)
        strDefaultDir = "WINFS";
    else
        strDefaultDir = "SD";
    
    FileStream fileToRead = null;
    try
    {
        fileToRead = new FileStream(strDefaultDir + "\\" 
    + strFileProgram, FileMode.Open, FileAccess.Read); long fileLength = fileToRead.Length; Debug.Print("File length " + fileLength); //file length has to be less than 1024 otherwise, it will raise an exception byte[] buf = new byte[fileLength]; string mySetupString = ""; // Reads the data. fileToRead.Read(buf, 0, (int)fileLength); // convert the read into a string mySetupString = new String(Encoding.UTF8.GetChars(buf)); int mps = mySetupString.IndexOf(ParamSeparator); MyLogin = mySetupString.Substring(0, mps); MyPassword = mySetupString.Substring(mps + 1, mySetupString.Length - mps-1); fileToRead.Close(); } catch (Exception e) { if (fileToRead != null) { fileToRead.Close(); } //throw e; Debug.Print(e.Message); }

    strFileProgram contain the file name in which you ware storing the login and password. And ParamSeparator is a char containing a separator character between the login and password stored. So it’s a character that you will not allow to use in a login or password. So use a character like return. As it can’t be used in a login and password.

    The first couple of lines are to identify if we are running in the emulator or not. In the emulator storing access is by default in the WINFS directory. And on the netduino board in SD. Then the code is very similar to what I’ve already shown in this article. The login and password will have to be stored in a global string of the http server class. As explain in the mentioned article, you can also save those data quite easily using the same file. And you can also build a simple page to allow the user (usually you) to change this login and password. In my case I’m not doing it as I’m the only user. And if I need to change it, I can do it directly on the SD card. Of course, use a long login and a complex and long password. At least 10 character, a majuscule, a miniscule, a numeric and a non alphanumeric character. And you can consider you may be ok. But again, it’s not the most secure solution. So if you have to expose directly your board to the internet and you’ll need to access it thru the web sever, make sure you are not piloting any critical part of your house or resources.

    As always, any feedback welcome.

  • Laurent Ellerbach

    Using a light transistor sensor and a led to create a detector

    • 1 Comments

    I will give a session in French during the next French TechDays on .NET Microframework. And I’m preparing couple of demos that almost anyone with limited knowledge in electronic and limited knowledge in programming. The idea is to show cool stuff you can do at home or a kid can do. Interested in coming to my session and more? You can register there.

    This session will be about doing demos and showing how you can very easily do hardware with a netduino board and .NET Microframework. It’s quite cool as you are very close to the hardware and no OS to do things you don’t want to be done Sourire.

    The coolest thing is that I get old electronic component from old PC. I get a light sensor from a very old hard drive and I will use it in my demo of course. This light sensor was used to count the number of turn the hard drive was doing and assert the speed to make sure it will go on the right speed. This simple sensor is one led and on transistor. And it looks like this:

    WP_000188

    It’s this small black thing. Looking at the schematic, it look like this:

    image

    So we have a common ground and the transistor is used like an switch. If it gets light, it will be open, if not, it will be closed. So we basically have to light the led and plug the transistor into a digital input to look at the state of the pin.

    As the led is working with about 2V and current should be about 0,02A, I will have to use a resistor. I remember an old rule: U = RxI. Where U is the voltage (in Volt), R is the resistor (in Ohm) and I is the current (in Amperes). I have 3.3V and 5V alimentation present on the board. I choose to use the 3.3V. So to get the resistor needed, I need to apply a simple math:

    R = (3,3 – 2)/0,02 = 65 Ohms

    Looking at couple of resistors I have, I found a 67 Ohms which will work. It’s anyway not really precise. So I plug the resistor into the 3.3V, add the 67 Ohms resistor, then the Led. The black cable on the ground. And I plugged the yellow one into the Digital IO 12 on my board.

    To have something cool, I’m using a led which I plugged also into a Digital IO, the number 0. And the same formula apply to calculate the resistor and the same resistor has to be used, the pin are 3.3V (5V tolerant).

    Now, the very simple code to see something happening is here:

    public static void Main()
    {
        InputPort Button;
        OutputPort LED;
    
        LED = new OutputPort(Pins.GPIO_PIN_D0, true);
        Button = new InputPort(Pins.GPIO_PIN_D12, false, Port.ResistorMode.PullUp);
        while (true)
        {
            LED.Write(Button.Read());
            Thread.Sleep(10);
        }
    }

    I create a Led as an OutputPort. And an InputPort for the transistor. And I do an infinite loop to check the status. And the led will reflect the status of the transistor.

    As I’m using the transistor as a switch with a high state (Port.ResistorMode.PullUp), I will have the value of True when the transistor won’t receive any light. So it mean that when I will have an object between the led (the one in front of the transistor) and the transistor, the value of the pin will be 1 and when the transistor will receive the light, it will be 0.

    Result is quite cool, I’ve done a detector with old component Sourire Back to my Lego city lighting project, I can use this to determine if a train is coming and blink a led for couple of seconds for example. And of course, I will not use the code as it is otherwise, it will only do this and nothing else! I’ll use interrupt ports to get the change of status of the port. But that’s for another post Sourire.

    More cool code and demos during my session in TechDays. And as always, don’t hesitate to give me your feedback. This time as it’s hardware, I was not able to do this into a plane. I had to do it with the board at home. Good news is I woke up early this morning so I had time to do it.

  • Laurent Ellerbach

    ASP.NET and .NET Microframework HTTP web server together (part 2/2)

    • 0 Comments

    In my previous post, I’ve explained how create a HTTP web server on a .NET Microframework Netduino board with no OS like Windows or Linux. And how to consume a kind of web service from this device from an ASP.NET application. The idea was to get setup data from the Netduino. Those data are a list of lights placed in my Lego city. And the ASP.NET application will allow to display the lights on a map and allow the user to click on a light. When clicking, the application will call the Netduino which will do the work of turning on or off the led. And that’s this part we will explain in this post.

    The function ProcessSwitch on the Netduino board is called when a URL like http://ipaddressnetduino/switch.aspx?id=0;lg=true is called. See previous post for more details on this function.

    Now the idea is to consume this in an ASP.NET page. First, we have to get the LegoLight object from the application storage. And that’s what we are doing in the first line of code of the Page_Load function. We will later detail the rest of the code.

    public partial class _Default : System.Web.UI.Page
    {
    
        public System.Collections.ArrayList myLegoLight;
        public ParamPage MyParamPage = new ParamPage();
    
        protected void Page_Load(object sender, EventArgs e)
        {
            myLegoLight = (System.Collections.ArrayList)Application.Get("LegoLight");
            int myID = -1;
            bool myLight = false;
            if (Request.Params.Count > 0)
            {
                //Is our paramater present?
                foreach(string mystr in Request.Params.AllKeys)
                {
                    if (mystr == MyParamPage.id)
                    {
                        myID = Convert.ToInt32(Request.Params.Get(MyParamPage.id));
                    }
                    if (mystr == MyParamPage.lg)
                    {
                        myLight = Convert.ToBoolean(Request.Params.Get(MyParamPage.lg));
                    }
                }
                if ((myID >= 0) && (myID < myLegoLight.Count))
                { 
                    ((LegoLight)myLegoLight[myID]).Light = myLight;
                }
            }
           
        }
    }

    There is also some code needed to display the lights on an image. I have done this code directly in the page.

    <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
        CodeBehind="Default.aspx.cs" Inherits="LegoCityWeb._Default" %>
    
    <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
    </asp:Content>
    
    <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    
    <script src="/Scripts/position.js" type="text/javascript"></script>
    
        <p>
      Click the lamp to switch on or off
        </p>
    <%
        int i = 0;
        string strResp = "";
        for (i=0; i<myLegoLight.Count; i++)
        {
            LegoCityWeb.LegoLight mLegoLight;
            mLegoLight = (LegoCityWeb.LegoLight)myLegoLight[i];
            strResp += "<span style='position:absolute;margin-left:" 
    + mLegoLight.PosX + "px; margin-top:" + mLegoLight.PosY
    + "px;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>"
    ; strResp += "<a href='/" + MyParamPage.pageDefault
    + MyParamPage.ParamStart + MyParamPage.id + MyParamPage.ParamEqual
    + i + MyParamPage.ParamSeparator + MyParamPage.lg + MyParamPage.ParamEqual
    + !mLegoLight.Light + "'>"; if (mLegoLight.Light) strResp += "<img alt='" + mLegoLight.Name
    + "' border=0 width=26 height=45 src='/lampon.png'>"; else strResp += "<img alt='" + mLegoLight.Name
    + "' border=0 width=26 height=45 src='/lampoff.png'>"; strResp += "</a></span>"; Response.Write(strResp); strResp = ""; } %> <img alt="" id="MyImage" src="/ville.jpg" /> </asp:Content>

    The first part of the code is the default code created by the template. It allow to have a nice menu, the logon part. Real code starts with the script section:

    <script src="/Scripts/position.js" type="text/javascript"></script>
    

    This script is the one I’ve developed and explain in this post to display an overlay image on an image with coordinates. There are 2 functions findLeft and findTop which returns the absolute positioning of an object from the left and top part of the page. This allow to overlay images on a page using span tags with a real positioning. Again, all this explain in the previous post.

    the for loop will go thru each LegoLight object. Each object has a position on the picture in pixel. The following code is creating the necessary code to position the picture:

    strResp += "<span style='position:absolute;margin-left:" 
    + mLegoLight.PosX + "px; margin-top:" + mLegoLight.PosY
    + "px;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>"
    ;

    The next line create a link which look like http://nameoftheserver/default.aspx?id=0&lg=true. So the main page will take params. those params allow to command the lights. That’s the second part of the code from the Page_Load function. And I’ll explain it just after.

    The rest of the client page display either an image of a light on or off depending of the status.

            if (mLegoLight.Light)
                strResp += "<img alt='" + mLegoLight.Name 
    + "' border=0 width=26 height=45 src='/lampon.png'>"; else strResp += "<img alt='" + mLegoLight.Name
    + "' border=0 width=26 height=45 src='/lampoff.png'>"; strResp += "</a></span>"; Response.Write(strResp); strResp = ""; } %> <img alt="" id="MyImage" src="/ville.jpg" />

    And finally add the main image on which all light objects will be displayed by overlay.

    So back to the page load code, when the main page is called, it can contains parameters. they are “id” and “lg”. The “id” one represents the id of a LegoLight object and the “lg” one the status of the light. Which can be on (true) or off (false).

    In order to get those params, I have done the following code:

    int myID = -1;
    bool myLight = false;
    if (Request.Params.Count > 0)
    {
        //Is our paramater present?
        foreach(string mystr in Request.Params.AllKeys)
        {
            if (mystr == MyParamPage.id)
            {
                myID = Convert.ToInt32(Request.Params.Get(MyParamPage.id));
            }
            if (mystr == MyParamPage.lg)
            {
                myLight = Convert.ToBoolean(Request.Params.Get(MyParamPage.lg));
            }
        }
        if ((myID >= 0) && (myID < myLegoLight.Count))
        { 
            ((LegoLight)myLegoLight[myID]).Light = myLight;
        }

    The Request object contains a class called Params. This class includes all parameters that are in the URL (thru a GET call) and/or thru a POST and in what the browser tells on you (your language, your OS, your IP, etc). So a nice foreach can go thru all this up to find the “id” one. And convert it to a real number as all params are just strings. And it will also find the “lg” one and concerts it to a bool.

    And if the ID is a valid number, it will switch on or off the light. If no value is present, the default value will apply and it will switch off the light. When calling the Light property of the LegoLight object, remember from my last post that it is calling the Netduino hardware thru a web page to actually physically switch the physical light on and off.

    Sol here is the end of the second part. To summarize, in those 2 articles, you’ve seen how to call a web page including parameters from a .Net Microframework Netduino board, getting parameters from this same board, displaying overlay images on it, and many things like that Sourire I hope you’ve enjoy it!

  • Laurent Ellerbach

    ASP.NET and .NET Microframework HTTP web server together (part 1/2)

    • 1 Comments

    I will show in this post how to call a web page from a .NET Microframework board which has implemented a HTTP Web Server and get results from it. The idea is to do a mix of previous posts. You are more and more to follow this blog so you may now be familiar with my implementation of a Web Server on a Netduino board. If not, read first the article which explain how to create such a web server on a board with no OS like Windows or Linux. And also how to create a dynamic management page like ASP.NET or Php or Java.

    When you’ll have read it, you’ll need also to read how to read a setup file in .NET Microframework. This is used to setup the board which will pilot led to light up my Lego city.

    Once you’ve done that, you’ll also need to read the post on how to display overlay images in HTML using Javascript. Yes, I know lots or reading before starting but I don’t want to go again thru all the code. I will only focus on the “new” parts.

    First let start with 2 web pages on the Netduino board. The first one allow to switch on and off one led. The code of the function looks like:

    private static void ProcessSwitch(HttpListenerContext context)
    {
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;
        // decode params
        string strParam = request.RawUrl;
        ParamPage MyParamPage = new ParamPage();
        bool bLight = false;
        int iID = -1;
        Param[] Params = decryptParam(strParam);
        if (Params != null)
            for (int i = 0; i < Params.Length; i++)
            {
                //find both params
                int j = Params[i].Name.ToLower().IndexOf(MyParamPage.id);
                if (j == 0)
                {
                    Convert.ToInt(Params[i].Value, out iID);
                }
                j = Params[i].Name.ToLower().IndexOf(MyParamPage.lg);
                if (j == 0)
                {
                    Convert.ToBool(Params[i].Value, out bLight);
                }
            }
        // if the ID value is valid, just light up the light :-)
        string strResp = strOK;
        if ((iID != -1) && (iID < myLegoLight.Count))
        {
            ((LegoLight)myLegoLight[iID]).Light = bLight;
        }
        else
        {
            strResp = strProblem;
        }
        
        strResp = OutPutStream(response, strResp);
    }

    In previous posts, I’ve explained how to handle parameters from a web query and transform them into real value. That’s what the first part of the code is doing.

    Please note that strOK = “OK” and strProblem = “Problem”. We will need this later on on the ASP.NET side.

    if ((iID != -1) && (iID < myLegoLight.Count))
    {
        ((LegoLight)myLegoLight[iID]).Light = bLight;
    }
    else
    {
        strResp = strProblem;
    }

    Those lines just validate that the ID of the light is in the range of ID. If yes, the OK status will be send out, if no, that the problem which will be sent out. The LegoLight structure contains information on the led, a name and coordinates on a picture. All that is explained in the previous post as a pre reading Sourire

    private static void ProcessLights(HttpListenerContext context)
    {
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;
        string strResp = "";
        LegoLight mLegoLight;
        ParamPage MyParamPage = new ParamPage();
        for (int i = 0; i < myLegoLight.Count; i++)
        {
            mLegoLight = (LegoLight)myLegoLight[i];
            strResp += mLegoLight.Name + ParamSeparator;
            strResp += mLegoLight.ID.ToString() + ParamSeparator;
            strResp += mLegoLight.Light.ToString() + ParamSeparator;
            strResp += mLegoLight.Network.ToString() + ParamSeparator;
            strResp += mLegoLight.PosX.ToString() + ParamSeparator;
            strResp += mLegoLight.PosY.ToString() + strEndFile;
            strResp = OutPutStream(response, strResp);
        }
    }

    The second function is also very simple, it does just “serialize” in the “old” way all the LegoLights objects and send them thru the output which is the web page. ParamSeparator = “&” and strEndFile = “\r”. So similar to what I’ve already explain in the post on how to read (and write) a setup file.

    Of course, when you do code on a very reach and fast platform, you can serialize those object in a nice way with XML and create the schema and all what is needed to look good, nice and reading by a human. Reality is I’m using an embedded platform where resources are expensive, almost no memory is available and it runs very slowly. Just think it’s a PC from the early 1980… And you’ll be close to the reality of what the Netduino can do.

    The output looks like: mairie&0&False&1&158&59 station&1&True&1&208&300 train&2&False&1&10&10 rue&3&False&1&700&550

    It does contain a “serialized” view of the LegoLight array. Now, the question is how to consume this? Answer is: thru an ASP.NET application Sourire

    So let’s go for the code to consume this. First step is to create an ASP.NET  application. I’ve used a simple default template which contains the code to create and manage users, a default page and an about page. So all what is needed to start. First step is to create the LegoLight object.

    public class LegoLight
     {
         private string myName = "";
         private int myPosX = 0;
         private int myPosY = 0;
         private byte myNetwork = 0;
         private bool myLight = false;
         private int myID;
    
         public int ID
         {
             get { return myID; }
             set { myID = value; }
         }
    
         public string Name
         {
             get { return myName; }
             set { myName = value; }
         }
         public int PosX
         {
             get { return myPosX; }
             set { myPosX = value; }
         }
         public int PosY
         {
             get { return myPosY; }
             set { myPosY = value; }
         }
         public byte Network
         {
             get { return myNetwork; }
             set { myNetwork = value; }
         }
         public bool Light
         {
             get { return myLight; }
             set { 
                 // do call the Netduino here :-)
                 // and change the status
    
                 //Create a web client object
                 string strUri = LegoCityWeb.Properties.Settings.Default.NetduinoURL;
                 ParamPage MyParamPage = new ParamPage();
                 strUri += MyParamPage.ParamStart + LegoCityWeb.Properties.Settings.Default.NetduinoID + MyParamPage.ParamEqual + myID;
                 strUri += MyParamPage.ParamSeparator + LegoCityWeb.Properties.Settings.Default.NetduinoLight + MyParamPage.ParamEqual + value;
                 //URL will look like http://ipaddressnetduino/switch.aspx?id=0;lg=true
                 Uri MyUri = new Uri(strUri);
                 string myResponse = GetStringFromURL(MyUri);
                 if (myResponse == LegoCityWeb.Properties.Settings.Default.NetduinoOK)
                     myLight = value;
              }
    
         }
         public string GetStringFromURL(Uri mUri)
         {
             WebClient instanceHTTP = new WebClient();
             const int MAX_BUFFER = 1024;
             string myResponse ="";
             Stream returnValue;     
             try
             {
                 //call the specific URI
                 returnValue = instanceHTTP.OpenRead(mUri);
                 // read the stream. This stream can't be seek, so get every byte "manually"
                 byte[] mybuff = new byte[MAX_BUFFER];
                 int i = 0;
                 int ret = -1;
                 do
                 {
                     ret = returnValue.ReadByte();
                     //if there is nothing to read return -1. Values goes from 0 to 255
                     if (ret > 0)
                     {
                         mybuff[i] = (byte)ret;
                     }
                     else
                     {
                         mybuff[i] = 0;
                     }
                     i++;
                 } while ((ret != -1) && (i < MAX_BUFFER));        
                 //returnValue.Read(mybuff, 0, (int)returnValue.Length);
                 myResponse = System.Text.Encoding.ASCII.GetString(mybuff, 0, i-1);
                 returnValue.Dispose();
             }
             catch(Exception ex)
             {                    
                 return myResponse;                       
             }
             //close the stream
             
             return myResponse;
         }
    
     }

    Nothing really complicated here, you’ll find very basic properties to get and set the ID, the name, the network, the position. Where it gets a bit more complicated it’s for the Light property. Well, remember that when you set the property to false, the idea is to switch off the light and when on true, to switch it to on. The idea is to call the first web method we’ve just write on the Netduino board. Remember, the URL to call looks like http://ipaddressnetduino/switch.aspx?id=0;lg=true

    In the code, I’m using application setting for the URL (NetduinoURL), the name of the paramaters (both for the ID NetduinoID and light status NetduinoLight). And I build the URL with the ID of the LegoLight object and the status of the light (so True or False, will also work with 1 and 0). When it’s done, I call a function called GetStringURL. This function has the only purpose to call the URI and return as a string the result. I’ll explain the function later on. In our case, back to the beginning of the article, this function will return “OK” if everything is correct of “Problem” if not. So I just test if it’s OK or not. And set the new light status if everything works fine.

    So now, let have a look at the GetStringURL function. It does take a URI as an argument and return a string.

    WebClient instanceHTTP = new WebClient();
    const int MAX_BUFFER = 2048;
    string myResponse ="";
    Stream returnValue;     
    First step is to create the variables we will need. We will call a web page, so we need to create a WebClient object. the MAX_BUFFER constant will be used to create a buffer that will contain what is returned by the Netduino. I have limited it to 2048 as it’s the maximum number of characters that will be send. On the Netduino, the original setup file will not exceed 1024 characters. But on the response stream, it will contains the ID and the light status as True and False rather than in text. So it will be a bit longer but there is no chance that the returned page will be larger than 2048.

    the myResponse will be used to put the response text and return it. And the stream object to get the stream from the WebClient object call.

    try
    {
        //call the specific URI
        returnValue = instanceHTTP.OpenRead(mUri);
        // read the stream. This stream can't be seek, so get every byte "manually"
        byte[] mybuff = new byte[MAX_BUFFER];
        int i = 0;
        int ret = -1;
        do
        {
            ret = returnValue.ReadByte();
            //if there is nothing to read return -1. Values goes from 0 to 255
            if (ret > 0)
            {
                mybuff[i] = (byte)ret;
            }
            else
            {
                mybuff[i] = 0;
            }
            i++;
        } while ((ret != -1) && (i < MAX_BUFFER));        

    The next part of the code open the URI and place the result in the stream returnValue. It’s a synchronous call but it will be quick as the Netduino will only return text. So no need here to do an asynchronous call which will be necessary if you have large amount of data to read.

    Now, the specificity with the stream we just get is that it is not seekable. So the only way I found to get the data is to pull every single char after the other. The function ReadByte allow this kind of read and return a byte (so a value between 0 and 255). It return –1 in case of problem. The “do while” loop if here to read the entire buffer. And of course, when you start manipulating stream, you better have to use a try catch section.

    So either when the buffer is full or when you’ve reach the end of the stream, the mybuff byte array will contain all the stream. Next step is to convert if to a string.

    myResponse = System.Text.Encoding.ASCII.GetString(mybuff, 0, i-1);

    That’s what this function is doing for you. In the same class, you find also a function to convert from string to a char array and more. And the conversion will be done only for the right amount of read data.

    So here it is for the LegoLigh object. A bit different that the one on the Netduino but only for the Light part. Which on the Netduino call hardware function to actually light up leds.

    Now it still does not answer the question on how to consume the “serialized” LegoLight array returned by the Netduino. For this, we will need also to read a stream and convert it to a string and “deserialize” the string to rehydrate the objects. The best place to do that is when the web application starts. It suppose that the Netduino is already started. If not, it’s just about adding a reinitialisation fonction which will basically call again the same code. It may be needed after a cold Netduino boot. It can also be checked by the main ASP.NET application on a regular basis like every day, week or hour. We’re not there for the moment.

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        LegoLight mLegoLight = new LegoLight();
        string strUri = LegoCityWeb.Properties.Settings.Default.NetduinoURLLight;
        ParamPage MyParamPage = new ParamPage();
        //URL will look like http://ipaddressnetduino/lights.aspx
        Uri MyUri = new Uri(strUri);
        string mySetupString = mLegoLight.GetStringFromURL(MyUri);
        int i = mySetupString.IndexOf(MyParamPage.EndFile);
        string mySubstring = "";
        string[] myParam;
        int j = 0;
        int inc = 0;
        try
        {
            char[] mSeparator = MyParamPage.ParamSeparator.ToCharArray();
            while ((i < mySetupString.Length) && (i != -1))
            {
                //split the substring in 3
                mySubstring = mySetupString.Substring(j, i - j);
                myParam = mySubstring.Split(mSeparator);
                mLegoLight = new LegoLight();
                mLegoLight.Name = myParam[0];
                int myint = 0;
                myint = Convert.ToInt32(myParam[1]);
                mLegoLight.ID = myint;
                mLegoLight.Light = Convert.ToBoolean(myParam[2]);
                //Convert.ToInt(myParam[1], out myint);
                myint = Convert.ToInt32(myParam[3]);
                mLegoLight.Network = (byte)myint;
                myint = Convert.ToInt32(myParam[4]);
                //Convert.ToInt(myParam[2], out myint);
                mLegoLight.PosX = myint;
                myint = Convert.ToInt32(myParam[5]);
                //Convert.ToInt(myParam[3], out myint);
                mLegoLight.PosY = myint;
                myLegoLight.Add(mLegoLight);
    
                //next string
                j = i + 1;
                if (j < mySetupString.Length)
                    i = mySetupString.IndexOf(MyParamPage.EndFile, j);
                else
                    i = -1;
                inc++;
            }
            Application.Add("LegoLight", myLegoLight);
        }
        catch
        { 
        
        }
    }

    The code will seat in the Application Start function. This is the first method called when the ASP.NET application starts. So the perfect moment to add those kind of initialization.

    Same as for the LegoLight object for the Light method, it starts with the creation of a URI and the call of the specific page which will return the serialized object. The deserialization is not too complex, it’s about splitting the string. First by finding the “\r” character and then the separators “&”. It’s quite artisanal but it’s perfectly working. Then a simple conversion for int and bool allow to populate the LegoLight object and add it to the Array. And finally, this array is stored into the Application storage to be used later.

    And that’s it for the first part of this article. In the second part, we will see how to call the method to change the light and display this in a nice and sweet ASP.NET page. As always, I’m coding in planes and also write articles in planes with no Internet connection. I don’t know why but I enjoy coding in planes with no way to find better code than the one I write. I’m just a marketing director writing code Sourire. And as always, feedback welcome. Thanks for one I already received, it motivates me to continue. And thanks also for being more and more to read this blog.

  • Laurent Ellerbach

    Creating dynamically a web page using .NET Micro framework

    • 0 Comments

    In a previous post, I’ve explain how to read a file using .NET Microframework, how to create a setup file and load it (and write it also), how to implement a web server using HTTP and managing dynamically web pages and parameters. This post will explain how to generate dynamically a page using files and code. So more or less the same idea but using all components this time.

    And the project is about lighting my Lego city. The idea is to be able to click on an image and a led will switch on or off in the Lego city. I’ll show in this post how to generate dynamically using files and code the page containing the overlay images from this post.

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;
    // decode params
    string strParam = request.RawUrl;
    ParamPage MyParamPage = new ParamPage();
    bool bLight = false;
    int iID= -1;
    Param[] Params = decryptParam(strParam);
    if (Params != null)
        for (int i = 0; i < Params.Length; i++)
        {
            //on cherche le paramètre strMonth
            int j = Params[i].Name.ToLower().IndexOf(MyParamPage.id);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out iID);
            }
            j = Params[i].Name.ToLower().IndexOf(MyParamPage.lg);
            if (j == 0)
            {
                Convert.ToBool(Params[i].Value, out bLight);
            }
        }

    This first part of the code is very similar to what I’ve explained in this post. The page parameters are analyzed, they are converted into real values. Here, each light has an id and a status. They can be on or off. Again, more information in some of my previous posts here.

    // if the ID value is valid, just light up the light :-)
    if ((iID != -1) && (iID < myLegoLight.Count))
    {
        ((LegoLight)myLegoLight[iID]).Light = bLight;
    }

    As it’s a web page and anyone can access it, there are a minimum of integrity to do Sourire I just check if the id is in the limit and load the object. More information on the LegoLight class here.

    string strResp = "<HTML><BODY>netduino Lego City<p>";
    
    // Print requested verb, URL and version.. Adds information from the request.
    strResp += "HTTP Method: " + request.HttpMethod + "<br> Requested URL: \"" + request.RawUrl +
        "<br> HTTP Version: " + request.ProtocolVersion + "\"<p>";
    strResp = OutPutStream(response, strResp);
    //send first part of the HTML File
    SendFile(response, strDefaultDir + "\\page1.ht");

    I create a string with the first part of the HTML page and for debug purpose, I add couple of information and send the string to the response object. Again, everything is explained there.

    The SendFile function is the one described in the post explaining how to read a file. Details here. strDefaultDir contains the directory where the file page1.ht is located. In the emulator it’s WINFS and in the netduino it’s SD. I change it “manually” depending on the environment I’m in. No real need to write code for this. Remember we are running an embedded application, no one will change it!! So things like this one can be written in the marble Sourire

    Page1.ht contains the following:

    <script langague="Javascript">
      // You don't need to worry about this
      function findTop(iobj) { ttop = 0; while (iobj) 
    { ttop += iobj.offsetTop; iobj = iobj.offsetParent; } return ttop; } function findLeft(iobj) { tleft = 0; while (iobj)
    { tleft += iobj.offsetLeft; iobj = iobj.offsetParent; } return tleft; } //This is all you need: //findTop(doucment.all.MyImage); </script> <p> Click the lamp to switch on or off </p>

    As expected, it’s just HTML code Sourire and if you want to understand what is the javascript in the page doing, read this post. By the way, I don’t like javascript, I truly prefer C/C++, C#, VB or even real Java (I say I prefer Java over javascript but it’s far far away from the 3 others Sourire).

    //build array of Span
    LegoLight mLegoLight;
    for (int i = 0; i < myLegoLight.Count; i++)
    {
        mLegoLight = (LegoLight)myLegoLight[i];
        strResp += "<span style='position:absolute;margin-left:" + mLegoLight.PosX +
    "px; margin-top:" + mLegoLight.PosY + "px;width:26px;height:45px;
    top:findTop(document.all.MyImage); left:findLeft(document.all.MyImage);'>"
    ; strResp += "<a href='/" + MyParamPage.pageDefault + ParamStart+ MyParamPage.id +
    ParamEqual + i + ParamSeparator + MyParamPage.lg + ParamEqual + !mLegoLight.Light + "'>"; strResp = OutPutStream(response, strResp); if (mLegoLight.Light) SendFile(response, strDefaultDir + "\\imgon.ht"); else SendFile(response, strDefaultDir + "\\imgoff.ht"); strResp += "</a></span>"; strResp = OutPutStream(response, strResp); }

    The next part of the code displays as a span over the main image all LegoLight object and depending if the state of the light is on or off send a different file. in one case it’s imgon.ht and in the other imgoff.ht. Both code are very similar:

    <img border=0 width=26 height=45 src="/WINFS/lampon.png">
    <img border=0 width=26 height=45 src="/WINFS/lampoff.png">

    Of course the /WINFS here reference the emulator path. In the reality it will be /SD as content will be in an SD card in the real word.

    And to finish, couple of lines:

    //send rest of the file
    SendFile(response, strDefaultDir + "\\page2.ht");
    
    strResp += "</BODY></HTML>";
    strResp = OutPutStream(response, strResp);

    They basically send the rest of the page. page2.ht just contains the image:

    <img alt="" src="/WINFS/ville.jpg" /></p>
    

    Again, here I’m using the emulator. In order to make it work, /WINFS need to be change to /SD to work on the Netduino.

    And you are done, here is a simple example that mix file and dynamic generated code to produce a web page in .NET Microframework Sourire Enjoy the beauty of the code Sourire

  • Laurent Ellerbach

    Dynamically watermark a picture in a ASP.NET page

    • 0 Comments

    In a previous post, I’ve explain how to use generic ASP.NET handlers to display a picture. The concept is easy to use and perfect to manipulate any kind of document you want to output in your web server. There equivalent of this in technologies like PHP or Java but it’s so easy to do using ASP.NET. In my previous post, I’ve used VB, so I’ll continue with VB Sourire Don’t worry, it’s as easy to do in C#!

    The overall code to watermark an image dynamically using the generic handler and the minimum manipulation code is here:

    <%@ WebHandler Language="VB" Class="Image" %>
    
    Imports System
    Imports System.Web
    Imports System.Net
    Imports System.IO
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    
    Public Class Image : Implements IHttpHandler
        
        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            context.Response.ContentType = "image/jpeg"
            context.Response.AddHeader("Cache-Control", "private,must-revalidate,post-check=1,pre-check=2,no-cache")
                    
            Dim instanceHTTP As New WebClient
            Dim MaCamera As New Camera
            Dim MyUri As New Uri("file://c:/Temp/image.jpg")
            Dim returnValue As Stream
            
            Try
                
                returnValue = instanceHTTP.OpenRead(MyUri)
                
                Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
                
                Dim MyText As String = Now.ToString("yyy-MM-dd HH-mm")
                Dim MyGraphics As Graphics = Graphics.FromImage(MyImage)
                Dim MyFont As Font = New Font(FontFamily.GenericSerif, 12)
                MyGraphics.DrawString(MyText, MyFont, Brushes.White, 100, 100)
                            
                MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
                MyGraphics.Dispose()
                MyImage.Dispose()
                
            Catch ex As Exception
                context.Response.Write("Error")
            End Try
            
        End Sub
     
        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property
    
    End Class
    

    I will not explain again what I’ve explain in the previous post on the way handlers are working. So I’ll just concentrate on the image manipulation and how to write text in an image dynamically.

    returnValue = instanceHTTP.OpenRead(MyUri)
    
    Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
    
    Dim MyText As String = Now.ToString("yyy-MM-dd HH-mm")
    Dim MyGraphics As Graphics = Graphics.FromImage(MyImage)
    Dim MyFont As Font = New Font(FontFamily.GenericSerif, 12)
    MyGraphics.DrawString(MyText, MyFont, Brushes.White, 100, 100)
                
    MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
    MyGraphics.Dispose()
    MyImage.Dispose()

    I first open a URI which contains an image. In my case a static image sitting on the hard drive but the idea here is to take it from a webcam for example. The URI is open as a stream and passed to an Image object.

    The idea here is to watermark the image with the date. So I create a simple string containing the date and time in a dedicated formatting. I like this formatting "yyy-MM-dd HH-mm" as it’s easy to sort especially with files. It does return a text like “2011-11-24 10-47”.

    Then I create a graphics object pointing on the image. This object is directly link to the image we have loaded and any modification made on the graphics object will impact the image. It’s the basic concept of pointers used here.

    In order to write text, you’ll have to choose a font. Again, nothing complicated here, choose your preferred font and the size. A good Serif and a 12 size will be enough in my example.

    And let the magic work using the DrawString method to draw in the graphics, so in the image your text. The 100 and 100 params are the X and Y starting point where to write the text. It starts on the upper left corner of the image. You can also use predefined points. But for the example, I keep it very simple.

    And as explain in the previous post, you just have to save your watermarked picture into the output stream and you’re done. Or almost done, don’t forget to dispose the graphics objects, better to do it especially if you want to scale up. The garbage collector will thank you Sourire

    Final result will look like that:

    image

    And of course, you can do more, much more using this handler. You can add shapes, transform the color schemas, apply filters, etc. .NET is full or very efficient graphics manipulations. so just use them! In my case I use it to tag pictures with date and time as in this example but also to control when I can access an image on some webcam. I do not expose them directly to the web. They are only accessible thru handlers like this. And only to specific persons (with a login and password) and on specific time. Maybe more in a next example!

    As always, feedback welcome Sourire The code and blog post written in a plane from Paris to Zagreb Sourire

  • Laurent Ellerbach

    Writing a generic ASP.NET handler to return an image and control the image

    • 1 Comments

    In one of my project, I want to integrate the picture from an IP camera to a web site. The idea is to be able to put a IP camera in my Lego room and see it for real. Especially to be able to control it. this project is linked to the one to light my Lego city. Instead of having the static image of the city, I want to be able to show the real time image. For this project, I’m using a netduino and .NET Microframework.

    Most IP camera do propose a simple URL where you can get the image. So it is very easy to integrate. But what if you want to control when to display the picture? Let say you don’t want to display the picture over night or just in small period of time? Or you want to dynamically add something to the picture like a layer? Well, IP camera are not smart enough to do it. So you’ll have to write some code.

    In ASP.NET you cant easily write a generic handler with the .ashx extension. that’s what I’ll do. And I’ll do it in VB.NET, that will change from my previous post that I did in C#. And no, I won’t do it in C++, php or Java Tire la langue. Yes, I do love VB too. Not only C#. As started developing a very long ago when the only thing you had on a PC was BASICA, the BASIC that was implemented in the IBM PC ROM. My father had a PC at home he was using for his own business.I was allow to use it but as I did not get any floppy disk, the only thing I was able to do was coding. And that’s at this time at 10 I started to code… in BASIC. and since then I never stopped coding Sourire 

    The simple code is the following one:

    <%@ WebHandler Language="VB" Class="Image" %>
    
    Imports System
    Imports System.Web
    Imports System.Net
    Imports System.IO
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    
    Public Class Image : Implements IHttpHandler
        
        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            context.Response.ContentType = "image/jpeg"
            context.Response.AddHeader("Cache-Control", 
    "private,must-revalidate,post-check=1,pre-check=2,no-cache") Dim instanceHTTP As New WebClient Dim MyUri As New Uri("http://yourcameraurl/image.jpg") Dim returnValue As Stream Try returnValue = instanceHTTP.OpenRead(MyUri) Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue) MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg) MyImage.Dispose() Catch ex As Exception context.Response.Write("Error") End Try End Sub Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class

    On top the page, you have to declare that it’s a WebHandler and implement IHttpHandler. When you’ve done that, add the ProcessRequest function as following:

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

    And also the read only property IsReusable. This function basically allow you to control if you want the ProcessRequest function to be reusable without executing the code or not. Here, the idea is to refresh the image each time the function is called so the property will return false.

    The ProcessRequest function gives you a HttpContext object. This object allow you to get many information like the brower type, the IP request address and more. But it also allow you to write in the response object. And that’s what interest us here as we want to send back an image.

    context.Response.ContentType = "image/jpeg"
    context.Response.AddHeader("Cache-Control", "private,must-revalidate,post-check=1,pre-check=2,no-cache")

    Those 2 just set the content type as an image so the browser will know how to interpret the content before having it at all. It does this interpretation automatically based on the extension of the file usually even if the type is not set. But here, it is mandatory to define as the extension of you file is .ASHX. And is it not interpreted as an image by any browser Sourire and the .ASHX can virtually return anything, it can be images, text, videos, PowerPoint, Excel file, Word docs, zip or whatever you want. So don’t forget this line! Still the browser (at least Internet Explorer Sourire) is smart enough to figure out that when you are in the “Error” returned in the stream is text and not a jpg…

    the second line is about adding a header. Here, I’m not really sure I do it correctly but I try to specify that the browser can’t cache the image as I want always a fresh image.

            Dim instanceHTTP As New WebClient
            Dim MyUri As New Uri("http://yourcameraurl/image.jpg")
            Dim returnValue As Stream

    The instanceHTTP variable will be used to download the image from the web cam. It’s a WebClient which allow to do this kind of operation. It can be done synchronously or asynchronously.

    The MyURI is used to create the URI that will be used to download the picture. So put in the string the address of your webcam. It is quite easy to find, just open your webcam in a browser, usually it display a page which includes the picture of your image. Right click on the image and you get the URL.

    Then we will need a stream object to put the image in and resend to the response object. that’s what returnValue is.

            Try
                returnValue = instanceHTTP.OpenRead(MyUri)
                
                Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
                            
                MyImage.Save(context.Response.OutputStream, 
    System.Drawing.Imaging.ImageFormat.Jpeg)MyImage.Dispose() Catch ex As Exception context.Response.Write("Error") End Try

    I know you are a good developer so I know when you are trying to access critical resources or resources that may not be present that you are using a try catch section. Good, you are a great developer Sourire. The fact is that trying to download a picture from a webcam may not work. The webcam may be down, your kids may have switch it off or your cat or your mother or whatever can happen.

    returnValue = instanceHTTP.OpenRead(MyUri)

    The 3 variables created previously are used in this line of code. It does open a stream (returnValue) from the WebClient (instanceHTTP) which has a URI (MyURI). That’s done, we are ready to download the picture from the camera.

    Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)

    So I create an Image object which I get from the camera thru the function FromStream. On this image, I can do whatever I want. Add text, change the size, colors or do any manipulation.

    MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)

    Here, I just save the image as a jpeg in the Response object. And I don’t forget to dispose the image as I don’t need it anymore.

    And that’s it! And you can image returning video or file you have created on the flight. Or pages or whatever you want. It is as simple to use handlers in ASP.NET. This implementation as it is as not really a usage. It is much simple to directly use the address of the camera. The only usage you can see is to secure your internal network and the access to the camera. By doing this you are impersonalizing the access to the camera. It is view as a black box from your web server.

    I’ll try to do couple of more post to show examples on how you can create thumbnails on the flight using this technic or maybe how you can restrict access regarding hours. I’m just a marketing guy with a technical background doing code in planes and enjoying it Sourire So any feedback on the code an those articles is welcome. And I see in my stats you are more and more to read them!

  • Laurent Ellerbach

    Read a setup file in .NET Microframework

    • 0 Comments

    In my previous post, I’ve explain how to read the content of a file in .NET Microframework. The idea now is to read a setup file. I want to store the position of the lamp icon I’d like to display on my Lego city map. More information on what I want to do in this post.

    First I’d like to explain the final structure of object I want to setup with my file. I have created a class which will contain a name, a position, the information if the light is on or not. The class is very simple, here is the code:

    public class LegoLight
    {
        private string myName = "";
        private int myPosX = 0;
        private int myPosY = 0;
        private byte myNetwork = 0;
        private bool myLight = false;
    
        public string Name
        {
            get { return myName; }
            set { myName = value; }
        }
        public int PosX
        {
            get { return myPosX; }
            set { myPosX = value; }
        }
        public int PosY
        {
            get { return myPosY; }
            set { myPosY = value; }
        }
        public byte Network
        {
            get { return myNetwork; }
            set { myNetwork = value; }
        }
        public bool Light
        {
            get { return myLight; }
            set { myLight = value; }
        }
    }

    Then I create an Array to store all the LegoLight objects. The good news with array is that you can easily add, remove, search in the array. The main problem is that the object you are adding are just objects. so you need a cast to force the kind of object you want to play with. But as you are the developer, you know what you’ve put in your array Sourire or if you don’t know, just guess Tire la langue

    static ArrayList myLegoLight = new ArrayList();

    I decided to create a simple setup file with the name, network and both position saved in the file. The concept of network is to be able to display all lights that are part of a network at the same time. The position is the position in pixel on the main image of the led to display. The name will be able to be displayed in the alt attribute of the file but also to be able to display the information on a regular page and not on the map. And I don’t save the state of the light, by default, it will be off.

    There is no serialization implemented in netduino so to store a save and read a file, you’ll have to do it manually. You have basically 2 options. First is to save the binary state of your object. That’s approximately what the serialize function is doing and the second is to do like the old ini files readable by a human. I will go for the second option just because I’m a human and it will be easiest for me to create the setup file. I can do it easily with notepad.

    So I have decided to use the following format: name(string);network(number in a string);PosX(number in a string); PosY(number in a string)\r

    As an example, it gives for one LegoLight object: mairie;1;158;59
    and for an array:

    mairie;1;158;59
    station;1;208;300
    train;1;10;10
    rue;1;700;550

    Now the challenge is to read a file like this. The code I wrote is the following (ParamSeparator = ‘;’, strDefaultDir and strFileSetup contains the path of the file and the name):

    LegoLight mLegoLight = new LegoLight();
    FileStream fileToRead = null;
    try
    {
        fileToRead = new FileStream(strDefaultDir+"\\"+strFileSetup, FileMode.Open, FileAccess.Read);
        long fileLength = fileToRead.Length;
        // Send HTTP headers. Content lenght is ser
        Debug.Print("File length " + fileLength);
        // Now loops sending all the data.
    
        //file length has to be less than 1024 otherwise, it will raise an exception
        byte[] buf = new byte[fileLength];
        string mySetupString="";
        
        // Reads the data.
        fileToRead.Read(buf, 0, (int)fileLength);
        // convert the read into a string
        mySetupString = new String(Encoding.UTF8.GetChars(buf));
        //find "\r"
        int i = mySetupString.IndexOf("\r");
        string mySubstring = "";
        string[] myParam;
        int j=0;
        while ((i < mySetupString.Length) && (i != -1))
        { 
            //split the substring in 3
            mySubstring = mySetupString.Substring(j, i - j);
            myParam = mySubstring.Split(ParamSeparator);
            mLegoLight = new LegoLight();
            mLegoLight.Name = myParam[0];
            int myint = 0;
            Convert.ToInt(myParam[1], out myint);
            mLegoLight.Network = (byte)myint;
            Convert.ToInt(myParam[2], out myint);
            mLegoLight.PosX = myint;
            Convert.ToInt(myParam[3], out myint);
            mLegoLight.PosY = myint;
            myLegoLight.Add(mLegoLight);
    
            //next string
            j = i+1;
            if (j < mySetupString.Length)
                i = mySetupString.IndexOf("\r", j);
            else
                i = -1;
            
        }
        fileToRead.Close();
    }
    catch (Exception e)
    {
        if (fileToRead != null)
        {
            fileToRead.Close();
        }
        throw e;
    }

    First, it create the LegoLight array and a file stream. Then, in a try catch, it starts to open and read the content of the file. See the previous post for most details on how to read a file on a SD. Please note here that the file as to be smaller than the max size of the buffer. For the netduino it is 1024. So the total length of the setup file has to be smaller than 1K. 1 LegoLight is about 35o so it allow to store about 30 objects. Which is quite enough for my needs. I did not test it in my code. I’m the only user of the solution and if I distribute it, I’ll have to do couple of additional check. But as we are in a try catch section, the code will just raise an exception and it will continue to work anyway.

    The second part is more interesting as it is where the parameters will be read and converted. First the buffer is converted into a string. the mySetupString now contains strings that’s has to be analyzed. I had 2 ways to do it there. The first one was to split the string using mySubstring.Split function with the "’\r’ and then for each object in the string, split it again finding the ‘;’. I did it for the first part in the “old way” with a simple while loop and finding the next occurrence of the ‘\r’. That is basically what the Split function is doing anyway to produce the array of strings.

    mySetupString = new String(Encoding.UTF8.GetChars(buf));
    //find "\r"
    int i = mySetupString.IndexOf("\r");
    string mySubstring = "";
    string[] myParam;
    int j=0;
    while ((i < mySetupString.Length) && (i != -1))
    { 
        //split the substring in 3
        mySubstring = mySetupString.Substring(j, i - j);
        myParam = mySubstring.Split(ParamSeparator);
        mLegoLight = new LegoLight();
        mLegoLight.Name = myParam[0];
        int myint = 0;
        Convert.ToInt(myParam[1], out myint);
         mLegoLight.Network = (byte)myint;
        Convert.ToInt(myParam[2], out myint);
        mLegoLight.PosX = myint;
        Convert.ToInt(myParam[3], out myint);
        mLegoLight.PosY = myint;
        myLegoLight.Add(mLegoLight);
    
        //next string
        j = i+1;
        if (j < mySetupString.Length)
            i = mySetupString.IndexOf("\r", j);
        else
            i = -1;
        
    }

    When a line of parameters like “station;1;208;300” is in the myParam string array, the first param contains “station”, the second one “1”, the third one “208” and the last one “300”. As the numbers are in a string format, they need to be converted into real numeric numbers. In a previous post, I’ve created couple of functions that allow an easy conversion, that’s the job of the Convert.ToInt function. The LegoLight object is then added to the array.

    This is an easy and cheap way in terms of memory print to read a setup file and restore the state of objects. For biggest objects or file, you’ll may have to store the binary representation of the data and read by chunk. that should be as efficient but use less memory print. And ob course, avoid XML format they are too big and too costly in foot print. Remember, you have very limited resources, you need to tune them and make sure you are using them very carefully.

    If you want to save your parameters, here is the code (in the previous code, ParamSeparator = ‘;’). Nothing really complicated, it just create a string with all the parameters, add the separators and finally saved them in a file.

    string strSer = "";
    LegoLight mLegoLight;
    for(int i=0; i<myLegoLight.Count; i++)
    {
        mLegoLight=(LegoLight)myLegoLight[i];
        strSer += mLegoLight.Name + ";" 
    + mLegoLight.Network.ToString() + ";"
    + mLegoLight.PosX.ToString() + ";"
    + mLegoLight.PosY.ToString() + '\r'; } File.WriteAllBytes(strDefaultDir + "\\" + strFileSetup, Encoding.UTF8.GetBytes(strSer));

    If you do it in your code, don’t forget the try catch section and make sure you do not exceed the capacity of the memory for string objects. Remember it is 1024 char in netduino. So the build string has to be smallest. If not, you’ll have to write the file by small write up to the end. You’ll need to open the file before the loop, and write each stream in the file each time and finally close the file. And again, don’t forget the try catch. You never know what can happen. And as you are designing an embedded system, it has to work and just work!

    So I hope I’ve shown you the basic method to read a setup file and save it. Nothing really complicated there. I’m just a marketing director writing code mainly in planes and testing back home Sourire

  • Laurent Ellerbach

    Reading file in .NET Microframework

    • 0 Comments

    For the one reading my articles, you know I’m developing in .NET Microframework an application to be able to switch on and off led in my Lego City. In the past post, I’ve explain how to setup a web server with HTTP, generate dynamic pages, handle parameters. And in the last one I show how to overlay 2 images and make the one on top clickable. In this article, I’ll explain how to read a file from the file system. I need this to be able to store images on an SD card for example and push them thru HTTP on the client. But I also want to have a setup file with the position of the led to display on the map.

    .NET Microframework offer basic IO with basic file system. It has to be a FAT format sitting on SD or equivalent. For the netduino, you have the netduino plus version which offers a SD card reader. And the basic IO are already implemented. So you can easily read and write a file. I have to admit I get couple of problems with SD card and have hard time to find one which was working all the time. Also, it looks like there is an hardware/firmware problem with SD card. But it’s about to be fixed. I never get too many problems to read the SD card but mainly to write on it. Here, my need is about reading and not writing.

    In the HTTP Server example, there is a good example of how to read a file and send it over HTTP. Here is the function (a bit modified from the original sample for my own purpose):

    static void SendFile(HttpListenerResponse response, string strFilePath)
     {
         FileStream fileToServe = null;
         try
         {
             fileToServe = new FileStream(strFilePath, FileMode.Open, FileAccess.Read);
             long fileLength = fileToServe.Length;
             // Once we know the file length, set the content length.
             //response.ContentLength64 = fileLength;
             // Send HTTP headers. Content lenght is ser
             Debug.Print("File length " + fileLength);
             // Now loops sending all the data.
    
             byte[] buf = new byte[BUFFER_SIZE];
             for (long bytesSent = 0; bytesSent < fileLength; )
             {
                 // Determines amount of data left.
                 long bytesToRead = fileLength - bytesSent;
                 bytesToRead = bytesToRead < BUFFER_SIZE ? bytesToRead : BUFFER_SIZE;
                 // Reads the data.
                 fileToServe.Read(buf, 0, (int)bytesToRead);
                 // Writes data to browser
                 response.OutputStream.Write(buf, 0, (int)bytesToRead);
    
                 System.Threading.Thread.Sleep(50);
                 // Updates bytes read.
                 bytesSent += bytesToRead;
             }
             fileToServe.Close();
         }
         catch (Exception e)
         {
             if (fileToServe != null)
             {
                 fileToServe.Close();
             }
             throw e;
         }
     }

    The function takes the HTTP response object and the file name of the file to send over HTTP.

    Then the code is quite simple. It first create a FileStream. And as it is well developed, you have a nice try catch Sourire. When you try to access files or resources, always use a try catch. You never know what can happen. You may have the user removing the support on where the file are like the SD card, the file may be corrupted, already access by another thread, etc.

    The file is open on readonly so if there is any other thread which want to access it also in read only, it is possible:

    fileToServe = new FileStream(strFilePath, FileMode.Open, FileAccess.Read);
    long fileLength = fileToServe.Length;

    The size of the file is stored into a variable. It will be necessary because the size of the memory in a netduino is very limited and you can’t open the file totally, put it in memory and send it as you’ll probably do a regular OS like Windows or Linux. Here, there is no operating system, no page file, and very very limited resources to only couple of kilo bytes. Yes, kilo bytes, not mega and far away giga!

    byte[] buf = new byte[BUFFER_SIZE];
    for (long bytesSent = 0; bytesSent < fileLength; )
    {
        // Determines amount of data left.
        long bytesToRead = fileLength - bytesSent;
        bytesToRead = bytesToRead < BUFFER_SIZE ? bytesToRead : BUFFER_SIZE;
        // Reads the data.
        fileToServe.Read(buf, 0, (int)bytesToRead);
        // Writes data to browser
        response.OutputStream.Write(buf, 0, (int)bytesToRead);
    
        System.Threading.Thread.Sleep(50);
        // Updates bytes read.
        bytesSent += bytesToRead;

    Reading the file will be done by slice. We are creating a buffer of the BUFFER_SIZE size. Here in netduino the maximum size is 1024. So the file will be read by slide of 1K and send over the response object. the loop is simple, it just read the file up to the end by slice of 1024 bytes.

    and to allow the system to do something else, it is paused couple of miliseconds. So be aware sending large file over HTTP in a netduino and any other .NET Microframework environment will require lot of loop like this and will take time.

    The rest of the code is just about closing the file. if you are sure your file will be less than 1K, you don’t need the loop, you’ll just need to create a buffer of the right size and read all.

    So we’ve seen the basic of reading a file in .NET Microframework. In a next post we will see how to use this to read a setup file.

  • Laurent Ellerbach

    Display overlay images in HTML and javascript with .NET Microframework

    • 1 Comments

    In my current project of lighting my Lego city, I’m working on a simple web interface that will allow thru a HTTP web page to display an image and small lamp icons on overlay. In my previous project on automate my sprinklers, I’ve implemented a HTTP web server in my netduino. It’s working like any Apache or IIS with kind of dynamic pages like ASP, php or Java. of course the implementation is much smaller and do cover only the very basic functions like GET request and sending file over.

    So as for the sprinkler project, I started with the HTTP Server example provided in the .NET Microframework SDK. I’ve removed what I did not need (same as for the Sprinkler project) and added couple of features like conversion, GET parameter management. Now I have the base, I was looking at a way to display images on overlap. my HTML bases are quite old, last time I did a page by hand was for the sprinkler project but not really with images. So of course, I remember the <img> tag and the map attribute to create an image that can bi clicked in multiple areas but that was not really what I wanted. I wanted multiple real images to be displayed on top of each other and having the ability to click on them.

    I rapidly found the <span> tag which allow to display anything on anyplace on top of HTML code. So it was looking perfect for my usage. The way to use it is to create an area and place HTML code inside with a position on the page. As an example:

    <span style='position:
    absolute;margin-left:158px; margin-top:59px; width:55px;
    height:44px; top:20px; left:50px;'><a href="/"><img border=0 width=55 height=44
    src="lampoff.png"></a></span>
    

    This span will be positioned in an absolute position on the page, starting from 158 pixels from the left side of the page and 59 from the top. Then you have to add another 20 pixels from the top and 50 from the left. The size of this span will be 55 pixels width and 44 pixels height. And it will contain an <a> tag with an image. The size of the image is 55 pixels width and 44 pixels height. the question you may ask is why is the span control taking 2 parameters for each position? one called margin-left + left and for vertical positioning margin-top + top. So good question Sourire the idea there is to allow to position first the span based on a control on the page and then offer the possibility to add an offset. the top/left is the first positioning and the margin-top/margin-left the second one. You want a real example? OK, so lets go with my final page which looks like this:

    image

    As you can see, I’ve positioned some lamps on the main image. And on top of the image there is some text. Imagine than in my code, I want to add more text before, of change the font size. It will change the position of the main picture. So the position of the lamp icons will change too. If I hard code the position of those lamp icons with absolute numbers, I’ll have to change all of them if I do a modification on the page.

    Now, If I can get dynamically the position of the main image and then use the possibility to use the margin to adjust the position on the main image, the only thing I have to care of is really the position on the picture. Well, the bad news there is that in HTML there is no other way than doing javascript to get a position of an object. So I had to code in javascript, 2 functions. 1 which will give me the absolute top position of the image and one for the left position. I have to admit I did not write javascript for such a long time… And I also have to admit, it’s not a language I like very much. No strong typing, no real way to debug correctly, no real language structure and less productivity than with languages like C#, VB, Java, C/C++. But I did it, and here is the result:

    <script langague="Javascript">
            // function to return the absolute Top and Left position
            function findTop(iobj) { ttop = 0; while (iobj) 
    { ttop += iobj.offsetTop; iobj = iobj.offsetParent; }
    return ttop; } function findLeft(iobj) { tleft = 0; while (iobj)
    { tleft += iobj.offsetLeft; iobj = iobj.offsetParent; }
    return tleft; } //to use it if the id of your image is MyImage //findTop(document.all.MyImage); </script>

    The function findTop will take the object you want the top position in argument. In HTML you can have imbricated objects so you have to take care of this to get the real position of an object. So I did a very simple recursive loop to sum the top position of all the parents objects up to the point there won’t be any object. And I simply return the sum of those positions. I did the exact same function for the left position. Now question is: how to use it? well, that’s very simple Sourire Taking the previous example, it will be:

    <span style='position:
    absolute;margin-left:158px; margin-top:59px; width:55px;
    height:44px; top:findTop(document.all.MyImage); 
    left:findLeft(document.all.MyImage);'><a href="/">
    <
    img border=0 width=55 height=44 src="lampoff.png"></a></span>

    So rather than have a number after the left and top attributes, I just call the functions. It assume that the name of the picture is MyImage. To give a name to an object, just use the id attribute:

    <img alt="Map of the city" id=MyImage src="ville.jpg" />
    

    and that’s it! the overall code for the page I generate automatically looks like:

    <HTML><BODY>netduino Lego City
    <p>HTTP Method: GET<br>
    Requested URL: "/default.aspx?id=0;lg=True<br>
    HTTP Version: 1.1"<p>
    <
    script langague="Javascript"> // You don't need to worry about this function findTop(iobj) { ttop = 0; while (iobj)
    { ttop += iobj.offsetTop; iobj = iobj.offsetParent; }
    return ttop; } function findLeft(iobj) { tleft = 0; while (iobj)
    { tleft += iobj.offsetLeft; iobj = iobj.offsetParent; }
    return tleft; } </script> <p> Click the lamp to switch on or off </p><span style='position:absolute;margin-left:158;
    margin-top:59;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>
    <
    a href='/default.aspx?id=0;lg=False'>
    <
    img border=0 width=26 height=45 src="/WINFS/lampon.png"></a></span>
    <
    span style='position:absolute;margin-left:208;
    margin-top:300;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>
    <
    a href='/default.aspx?id=1;lg=True'>
    <
    img border=0 width=26 height=45 src="/WINFS/lampoff.png"></a></span>
    <
    span style='position:absolute;margin-left:10;
    margin-top:10;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>
    <
    a href='/default.aspx?id=2;lg=True'>
    <
    img border=0 width=26 height=45 src="/WINFS/lampoff.png"></a></span>
    <
    span style='position:absolute;margin-left:700;
    margin-top:550;width:26px;height:45px; top:findTop(document.all.MyImage);
    left:findLeft(document.all.MyImage);'>
    <
    a href='/default.aspx?id=3;lg=True'>
    <
    img border=0 width=26 height=45 src="/WINFS/lampoff.png"></a></span>
    <
    img alt="" src="/WINFS/ville.jpg" /></p></BODY></HTML>

    The /WINFS/ path is due to the fact I was running this sample thru the emulator. If you run it on the netduino board, then the SD path is /SD/.

    So I have created all what I need to display an image, put some other pictures as overlap, have the possibility to click on them. Now the next step is about generating dynamically this page from the netduino which I did and I will post explanations in a next post. Of course, there is the possibility to do all this with CSS. It’s working exactly the same way. My need is very simple so I won’t use CSS there but maybe to make my page very sexy in the future. Enjoy this code and post written in a plane Rire

  • Laurent Ellerbach

    Lighting my Lego city using .NET Microframework

    • 5 Comments

    Now I have created a software to pilot sprinklers, I want to be able to pilot my Lego city and light it. I know my sprinkler project is not over as I still need to work on the hardware. I will do it over the winter and try to find someone to help me. This new project looks simpler for me as it will basically only be couple of led. So it can be directly plugged to the netduino board.

    I have quite a big Lego city as you can see in this picture with 2 trains, a modern city, an old city, an airport, couple of rail stations.

    For those who may not have guess, I’m a Lego fan, I have more than 650 official Lego sets from 1970+ to now. Not all are build, some are just used for spare parts to build other kind of constructions. And I have also hundreds of kilos of brick at home which allow me to build whatever I want. You can have a look at part of the collection here.

    Same as for the sprinkler project, the idea is to be able to switch some part on automatically, at night for example, and switch them on and off also manually. In order to reuse the work I’ve done, I will create a similar project with and http web server (like IIS or Apache running on Windows or Linux), dynamic pages (like ASP.NET, php or Java) with parameters. I’ve already develop a web server I will be able to reuse and the management for dynamic input.

    My idea this time is to be able to display a web page with pictures of the city and specific points on the pictures that will represent the light to switch on and off. clicking on them will change the color of the points and switch the light accordingly.

    In a longer term, I will try to pilot also the train lights and the rail switch. That will need a bit more electronic but is very easy to do in term of code. So probably that the code will exist before the electronic as for the sprinkler project. I will try also in this project to use the SD card to store the picture of the city and the points coordinate to be displayed. So a kind of setup file. I’ve already try to play with the SD card but with limited success. I don’t know from where the problem is coming from. I use couple of different cards and I always get errors but never the same. So I think the problem is coming from the hardware.

    So let see where this project will go Sourire

  • Laurent Ellerbach

    Creating and launching timer in .NET Microframework

    • 1 Comments

    In previous posts, I had the occasion to show how to implement a web server using HTTP and handling web request (in my example GET requests) with parameters URL like in a real Windows or Linux server running Internet Information Server (IIS) or Apache with a generated HTML page like for ASP.NET, PHP or Java. Of course in couple of Kilo bits of memory, you just can’t do the same as IIS or Apache. Of course, security is very limited, capacity to cache non existent and many functions does just not exist! But at least you can do what you want and you just can focus on creating web page by hands with real C# code using the standard HTML language Sourire for those of my age who have started to write web pages in 1993 or so remember that it’s not very complicated and notepad was your best friend. Youngest one using tools like Visual Studio, Eclipse or others just don’t know Clignement d'œil Ok, I’m probably a bit polemic there but they may be less comfortable doing it than people of my age or people who developed couple of ISAPI filters.

    So read first this post on the web server implementation, then how to setup the time and date, this one on how to generate a calendar then this one on how to create programs. All done? Good! now, we will create couple of timers to launch the sprinklers. the good news is that in .NET Microframework, there is all what you need to do that. the only thing you have to do is to add a line like that in your initialization phase. I’ve added it in the StartHttpServer function:

    Timer MyTimer = new Timer(new TimerCallback(ClockTimer_Tick), null, 30000, 30000);

    So we have created a Time object that will call a function ClockTimer_Tick every 30 seconds in 30 seconds. The ClockTimer_Tick function looks like:

    static void ClockTimer_Tick(object sender)
    {
        DateTime now = DateTime.Now;
        Debug.Print(now.ToString("MM/dd/yyyy hh:mm:ss"));
        //do we have a Sprinkler to open?
        for (int i = 0; i < SprinklerPrograms.Count; i++)
        { 
            SprinklerProgram MySpr = (SprinklerProgram)SprinklerPrograms[i];
            if ((now.Year == MySpr.DateTimeStart.Year) && (now.Month == MySpr.DateTimeStart.Month) && (now.Day == MySpr.DateTimeStart.Day)
                && (now.Hour == MySpr.DateTimeStart.Hour) && (now.Minute >= MySpr.DateTimeStart.Minute))
            { // this is the time to open a sprinkler
                Debug.Print("Sprinkling " + i + " date time " + now.ToString("MM/dd/yyyy hh:mm:ss"));
                Springlers[MySpr.SprinklerNumber].Manual = false;
                Springlers[MySpr.SprinklerNumber].Open = true;
                // it will close all sprinkler in the desired time of sprinkling. Timer will be called only once.
                Timer MyTime = new Timer(new TimerCallback(ClockStopSprinkler), null, (int)MySpr.Duration.Ticks/10000, 0);
                SprinklerPrograms.RemoveAt(i);
            }
        }
    }            
    

    It starts by creating a DateTime object that take the actual date time. It will be used to see if there are programs to launch. The loop just go thru all the programs. Programs are contained into an ArrayList SprinklerPrograms and contains objects that are SprinklerProgram. All this is describe in this post.

    So what it does is just testing if the program is the right year, right month, right day, right hour and if the minute to start is pasted. As the function is called every 30 seconds, a sprinkler will be started during the minute it was planned. To open the sprinkler, the Sprinkler function Open from the Sprinkler class is called. The code for the class looks like:

    static private OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
    public class Sprinkler
    {
        private bool MySpringlerisOpen = false;
        private int MySprinklerNumber;
        private bool MyManual = false;
    
        public Sprinkler(int SprNum)
        {
            MySprinklerNumber = SprNum;
            //need hardware here
        }
    
        // open or close a sprinkler
        public bool Open
        {
            get { return MySpringlerisOpen; }
            set
            {
                MySpringlerisOpen = value;
                //do harware here
                if (MySpringlerisOpen)
                    led.Write(true);
                else
                    led.Write(false);
            }
        }
        public bool Manual
        {   get { return MyManual; }
            set { MyManual = value; }
        }
            
    
        //read only property
        public int SprinklerNumber
        {
            get { return MySprinklerNumber; }
        }
    }

    This class does not include the real hardware work. It just light on the embedded led when a sprinkler is open and switch it of when closed. As there are multiple sprinklers sharing the same internal led, the led object as to be declare as a static object in the main class to be kept alive and shared by all the sprinklers.

    Here come the specific of the netduino. The internal led is an OutputPort and use a specific port. It can be found in the definition of the enum:

    public const Cpu.Pin ONBOARD_LED = 55;

    The sprinkler class contains the number of the sprinkler, if it is open and if it is a manual open or an automatic opening. The only way to create a sprinkler class is to give it a number. It is done as behind there will be some hardware initialization and all objects will need to be unique. When I’ll have done the hardware work, I’ll come back to post the necessary code Clignement d'œil

    So back to the launch of the program, the code will set the opening to manual and open it in the sprinkler:

    Springlers[MySpr.SprinklerNumber].Manual = false;
    Springlers[MySpr.SprinklerNumber].Open = true;
    // it will close all sprinkler in the desired time of sprinkling. Timer will be called only once.
    Timer MyTime = new Timer(new TimerCallback(ClockStopSprinkler), null, (int)MySpr.Duration.Ticks/10000, 0);
    SprinklerPrograms.RemoveAt(i);

    Then it will create a new timer that will be called after the duration specified to sprinkle. The Ticks member return a number of ticks. 10000 ticks represent 1 second. So the ClockStopSprinkler will be called after the right duration and only 1 time. The function is quite simple, it just reset all sprinklers to close. I’ve decided to do this as I feel it is much more secure. I just can’t run anyway 2 sprinklers at the same time as I don’t have enough water pressure to run more than once a time.

    static void ClockStopSprinkler(object sender)
    {
        Debug.Print("Stop sprinkling " + DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss"));
        //close all sprinklers if automatic mode
        for (int i = 0; i < NUMBER_SPRINKLERS; i++)
        {
            if (Springlers[i].Manual == false)
                Springlers[i].Open = false; 
        }
    }

    If the mode is manual, no reason to stop a sprinkler. The manual mode can be run in another page. I’ll describe this into a future post.

    So quite easy code here to open and close the sprinklers when needed. Just use simple timers! I hope you’ve also enjoyed this post. Coding makes you feel better Sourire and that’s just a marketing guy telling you this Clignement d'œil

  • Laurent Ellerbach

    Program a date time and duration for a sprinkler in .NET Microframework and netduino

    • 0 Comments

    In my previous posts, I’ve explained that I wanted to be able to program sprinklers in my garden day by day thru the Internet when I was not at home to save energy and water. No need to use a sprinkler when it has rained all night but need to use them when it has been very dry and sunny all day and no forecast for rain in the coming days. So I choose to use a netduio, it’s a system on chip simple board, using no OS so no Windows, no Linux, no DOS or any anything else than .NET Microframework (in one word and not Micro framework). I use C# to develop on it but it’s also possible since recently to use Visual Basic (VB.NET).

    So to summarize, after couple of post, I’ve created a web server to handle http requests like any Windows, Linux server running IIS, Apache or any other web server and being able to handle request in the URL like for ASP.NET, PHP or Java, see this post. I already manage to display a calendar. So now it’s time to add programs!

    As for the calendar, I start by decoding the URL, this time URL looks like program.aspx?year=2011;month=9;day=10;hour=21;minute=2;duration=20;spr=0

    There are 7 parameters. I pass to the URL the year, month, day, start hour, start minute and duration of the program on a specific sprinkler. I made it clear in the parameters to be understandable by a human Sourire In the production version and if I need to get more free space and to improve performance, I’ll reduce the length of the parameters name and URL name. I will save footprint but also time processing and bandwidth when generating the URL. As I did program with clean code, I just need to change couple of strings in a single class for the overall code. All is explained in a previous post.

    I have decided (that’s the chance to be the developer Clignement d'œil) to reset a program when I set the duration to 0. In this case, I just need to have a valid year, month and sprinkler number. So this code will do the job:

    if (intDuration == 0)
    {
        for (int i = 0; i < SprinklerPrograms.Count; i++)
        {
            // case the date already exist => update the hour, minute and duration for the given Sprinkler
            if ((intYear == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Year)
                && (intMonth == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Month)
                && (intDay == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Day)
                && (intSprinklerNumber == ((SprinklerProgram)SprinklerPrograms[i]).SprinklerNumber))
            {
    
                SprinklerPrograms.RemoveAt(i);
                strResp += "Deleting Sprinkler " + intSprinklerNumber + " for " + intYear + " " 
    + intMonth + " " + intDay + ". <br>"; strResp += "<a href='/" + MyParamPage.pageSprinkler + "'>Back to main page</a>"; strResp = OutPutStream(response, strResp); } } }
    As you can see, there a SprinklerPrograms variable. So what is this? It’s an array define like this:
    public static ArrayList SprinklerPrograms = new ArrayList()

    Good news with .NET Microframework is that like for the real .NET framework or even Java or PHP, there is a minimum to manage array and lists. This ArrayList is smart enough to take any object in the array, up to 1024 elements (that’s the limit of netduino platform). And there is function to add, remove, find specific objects.

    intYear == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Year

    I do test to see if there is an existing element with the same date (year, month, day) and sprinkler. And If I found one, I just remove it. If nothing if found, nothing will be done and no message display. In a normal usage, this page is called from other page. Of course, as it’s just a web page, it can be called by anyone with crappy elements in the URL. It’s just a choice as in a normal usage, it should not happen.

    I also cast an element of the ArrayList to a SprinklerProgam class. This class is created to store a single program for a sprinkler.

    public class SprinklerProgram
    {
        private DateTime myDateTimeStart;
        private TimeSpan myDuration;
        private int mySprinklerNumber;
    
        public SprinklerProgram(DateTime mDT, TimeSpan mTS, int mSN)
        {
            myDateTimeStart = mDT;
            myDuration = mTS;
            mySprinklerNumber = mSN;
        }
    
        public DateTime DateTimeStart
        {
            get { return myDateTimeStart; }
            set { myDateTimeStart = value; }
        }
        public TimeSpan Duration
        {
            get { return myDuration; }
            set { myDuration = value;  }
        }
    
        public int SprinklerNumber
        {
            get { return mySprinklerNumber; }
            set { mySprinklerNumber = value; }
        }
    
    }

    Nothing really complicated there, it’s just about storing the start date, time, duration and sprinkler number. And I do test the year, month, day and sprinkler with a casting.

    So next, the idea is to see if the date and time are valid, create a DateTime object and check if it is today or not. If it is today, only part of the time will be displayed as the idea is not to be able to program a past day. Then after couple of test, either there is a program existing for a sprinkler and it just need to be updated, either it has to be created.

    else if ((intYear > 1900) && (intMonth > 0) && (intMonth < 13) && (intHour >= 0) 
    && (intHour < 24) && (intMinute >= 0) && (intMinute < 60)) { MyDate = new DateTime(intYear, intMonth, intDay, intHour, intMinute, 0); bool TodayIsToday = false; if ((intYear == tmpNow.Year) && (intMonth == tmpNow.Month) && (intDay == tmpNow.Day)) TodayIsToday = true; // Is the program in the future or today! if ((MyDate >= tmpNow) || (TodayIsToday)) { bool updated = false; // is the duration the right one? with an existing sprinkler? if ((intDuration > 0) && (intDuration < 1440) && (intSprinklerNumber >= 0)
    && (intSprinklerNumber < NUMBER_SPRINKLERS)) { MySpanDuration = new TimeSpan(0, intDuration, 0); // is it a new program for a day a just an update (only 1 program per day available) for (int i = 0; i < SprinklerPrograms.Count; i++) { // case the date already exist => update the hour, minute and duration for the given Sprinkler if ((MyDate.Year == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Year) && (MyDate.Month == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Month) && (MyDate.Day == ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart.Day) && (intSprinklerNumber == ((SprinklerProgram)SprinklerPrograms[i]).SprinklerNumber) && (updated == false)) { ((SprinklerProgram)SprinklerPrograms[i]).DateTimeStart = MyDate; ((SprinklerProgram)SprinklerPrograms[i]).Duration = MySpanDuration; updated = true; strResp += "Updating Sprinkler " + intSprinklerNumber + " for "
    + MyDate.ToString("yyyy MMM d") + " to start at " + MyDate.ToString("HH:mm") + " and duration of "
    + MySpanDuration.Minutes + " minutes. <br>"; strResp = OutPutStream(response, strResp); } } // does not exist, then will need to create it if (updated == false) { SprinklerPrograms.Add(new SprinklerProgram(MyDate, MySpanDuration, intSprinklerNumber)); strResp += "Adding Sprinkler " + intSprinklerNumber + " for "
    + MyDate.ToString("yyyy MMM d") + " to start at " + MyDate.ToString("HH:mm") + " and duration of "
    + MySpanDuration.Minutes + " minutes. <br>"; updated = true; strResp = OutPutStream(response, strResp); } } if (updated == false) { //create a timeline to select hour and minutes strResp += "<br>Select your starting time.<br>"; strResp += "<table border=1>"; //in case it's Today, allow programation for the next hour int StartTime = 0; if (TodayIsToday) StartTime = intHour+1; strResp = OutPutStream(response, strResp); for (int i = StartTime; i < 24; i++) { for (int j = 0; j < 2; j++) { strResp += "<tr><td>"; DateTime tmpDateTime = new DateTime(intYear, intMonth, intDay, i, j * 30, 0); strResp += tmpDateTime.ToString("HH:mm"); strResp += "</td><td>"; strResp += "<a href='" + MyParamPage.pageProgram + ParamStart
    + MyParamPage.year + ParamEqual + tmpDateTime.Year + ParamSeparator + MyParamPage.month + ParamEqual
    + tmpDateTime.Month + ParamSeparator + MyParamPage.day + ParamEqual + tmpDateTime.Day + ParamSeparator
    + MyParamPage.hour + ParamEqual + i + ParamSeparator + MyParamPage.minute + ParamEqual + j * 15
    + ParamSeparator + MyParamPage.duration + ParamEqual + "20" + ParamSeparator + MyParamPage.spr
    + ParamEqual + intSprinklerNumber + "'>20 minutes</a>"; strResp += "</td>"; strResp = OutPutStream(response, strResp); strResp = "</tr>"; } } strResp += "</table>"; } else { // something has been updated so redirect to the main page strResp += "<a href='/" + MyParamPage.pageSprinkler + "'>Back to main page<a><br>"; strResp += "<a href='/" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year
    + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + intMonth + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinklerNumber + "'>Proram this month</a>"; strResp = OutPutStream(response, strResp); } } else { strResp += "Date must be in the future"; } }

    In the case, a new program has to be added, the code is really simple as we are using an ArrayList:

    SprinklerPrograms.Add(new SprinklerProgram(MyDate, MySpanDuration, intSprinklerNumber));

    Just use the Add member to add a new object. As explain, the only object that are added are SprinklerProgam. In the case, it has to be updated, it just search the list, compare the dates and update the information in the object for hour, minute and duration.

    And finally, if nothing has been update, it display a simple table containing the start hour and the duration. Here by default, it’s 20 minutes but it can of course be different. It’s hard coded here as an example. Best way is to use a constant of a variable that can be set in a different page.

    In case an update or an add has been done, it displays the ability to return to the main page or program another day. The smart thing with this code is that this page just point on itself. I mean by this that this page either display the list of hour and duration or either add, remove or update the information regarding a program. So it is quite efficient as many tests has already be done and are common anyway.

    And last but not least, when a date is not correct, or a time or anything else, it just display a gentle and simple message telling something is wrong. No real benefit here to do more detailed as it should not be displayed when clicking on the normal link. It may only happen when URL are type like this or called from another code or generated by another code.

    Now we have programs for sprinkler the question is how we will be able to launch those programs! See the answer in the next post Sourire and enjoy .NET Microframework! As for the last post, my code is far to be perfect, I’m just a marketing director writing code! Code is life Sourire

  • Laurent Ellerbach

    Displaying a calendar in a web page using .NET Microframework

    • 0 Comments

    As I want to program sprinklers I need to be able to select a date. In my previous posts, I’ve already explained how I’ve setup a Web Server using .NET Microframework, my netduino with Visual Studio using C# and all the magic of code Rire. My implementation allow me to pass parameters in a URL. And I want to create a page to display a calendar. Using PHP, Java or ASP.NET is so easy as you don’t have to do anything, just call a date time picker class, object, widget or whatever extension it can be. Here, there is just nothing Triste

    So all is to be done manually. and it’s not very easy as we will need to determine the number of day in a month, display them in a nice table, add links on the days to call another page. So quite a bit of work. And also the need to go back in the past HTML docs… Well, lets start somewhere Sourire I choose to start with a function to return the number of days in a month. I did not find it in the framework.

    static int NumberDaysPerMonth(int Month, int Year)
            {
                if ((Month <= 0) || (Month >= 13))
                    return 0;
                if ((Year % 4 == 0 && Year % 100 != 0) || Year % 400 == 0)
                {
                    int[] NbDays = new int[] {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    return NbDays[Month-1];
                } else {
                    int[] NbDays = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    return NbDays[Month-1];
            }

    Basically there are year with month of February that change every 4 years, with the exception of century years and every 400 years. In this case, you have 29 days, in all other cases only 28. The rest of the months stay constant. To be very efficient, I’ve just created tables of 12 elements representing each month, and I return the number of days. I’ll be very proud if my netduino board will be still used to pilot my sprinklers in the next century… but anyway, it’s always better to have as clean code as possible!

    In my previous post, you’ll find the first part of the code for this function. The first part analyze the URL and get the year and month of the sprinkler to program.

    So here is the second part of the code. Pretty long but I’ll explain all parts later on:

        string strResp = "<HTML><BODY>netduino sprinkler<p>";
    
        // Print requested verb, URL and version.. Adds information from the request.
        strResp += "HTTP Method: " + request.HttpMethod + "<br> Requested URL: \"" + request.RawUrl +
            "<br> HTTP Version: " + request.ProtocolVersion + "\"<p>";
        response.ContentType = "text/html";
        response.StatusCode = (int)HttpStatusCode.OK;
        if ((intMonth > 0) && (intMonth<13) && (intYear > 2009) && (intYear <2200))
        {
            //are we in the future?
            DateTime tmpDT = new DateTime(intYear, intMonth, 1);
            DateTime tmpNow = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            if (tmpDT >= tmpNow)
            {
    
                for (int i = 0; i < NUMBER_SPRINKLERS; i++)
                    if (i != intSprinkler)
                        strResp += "Calendar for <a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + intMonth + ParamSeparator + MyParamPage.spr + ParamEqual + i + "'>sprinkler " + i + "</a><br>";
                strResp = OutPutStream(response, strResp); 
                strResp += "Month: " + intMonth + "<br>";
                strResp += "Year: " + intYear + "<br>";
                // Display some previous and next.
                // is it the first month? (case 1rst of January of the year to program but in the future year so month =12 and 1 less year)
                if ((intMonth == 1) && (intYear > DateTime.Now.Year))
                    strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + (intYear - 1) + ParamSeparator + MyParamPage.month + ParamEqual + "12" + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp";
                else if ((intMonth > DateTime.Now.Month) && (intYear == DateTime.Now.Year)) // (other cases
                    strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth - 1) + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp";
                else if(intYear > DateTime.Now.Year)
                    strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth - 1) + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp";
                // next month //case december
                strResp = OutPutStream(response, strResp); 
                if (intMonth == 12)
                    strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + (intYear + 1) + ParamSeparator + MyParamPage.month + ParamEqual + "1" + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Next month</a>";
                else // (other cases
                    strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth + 1) + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Next month</a>";
                // display and build a calendar :)
                strResp += "<p>";
                strResp += "<table BORDER='1'><tr>";
                for (int i = 0; i < days.Length; i++)
                    strResp += "<td>" + days[i] + "</td>";
                strResp += "</tr><tr>";
                int NbDays = NumberDaysPerMonth(intMonth, intYear);
                DateTime dt = new DateTime(intYear, intMonth, 1);
                for (int i = 0; i < (int)dt.DayOfWeek; i++)
                    strResp += "<td></td>";
                strResp = OutPutStream(response, strResp); 
                for (int i = 1; i <= NbDays; i++)
                {
                    if ((intMonth == DateTime.Now.Month) && (intYear == DateTime.Now.Year) && (i < DateTime.Now.Day))
                    { // don't add a link to program a past day
                        strResp += "<td>" + i + "</td>";
                    }
                    else
                    {
                        strResp += "<td><a href='" + MyParamPage.pageProgram + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + intMonth + ParamSeparator + MyParamPage.day + ParamEqual + i + ParamSeparator + MyParamPage.hour + ParamEqual + DateTime.Now.Hour + ParamSeparator + MyParamPage.minute + ParamEqual + DateTime.Now.Minute + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>" + i + "</a></td>";
                    }
                    if ((i + (int)dt.DayOfWeek) % 7 == 0)
                        strResp += "</tr><tr>";
                    strResp = OutPutStream(response, strResp);
                }
                strResp += "</tr></table>";
            }
            else
            {
                strResp += "Not in the future, please select a valid month and year, <a href='calendar.aspx?Year=" + DateTime.Now.Year + ";Month=" + DateTime.Now.Month + ";Spr=" + intSprinkler + "'>click here</a> to go to the actual month";
            }
        }
        strResp += "</BODY></HTML>";
        strResp = OutPutStream(response, strResp);
    }

    The first line of code are here to create the HTML page, I use it also to show the URL and the parameters as a debugging point of view. No real rocket science there.

    Then I test if the date is in the future. I setup a maximum date for 2200. I think I can live perfectly up to this date Clignement d'œil and if needed, at this time, I’ll modify the code again Tire la langue. That said, this validation is not enough. We must know if we are in a future month or the actual or not.

    //are we in the future?
    DateTime tmpDT = new DateTime(intYear, intMonth, 1);
    DateTime tmpNow = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
    if (tmpDT >= tmpNow)

    Those 3 lines of code will give us the answer. If we are not in the future, no need to program a sprinkler. It’s quite necessary to do as the page can be called by almost anyone with almost any parameter. And the number of element is a table is limited to 1024. So no need to use unnecessary space in the memory. Embedded is about optimization. every single line of code has to have a usage. Otherwise, just remove it. If you can do something in 5 lines of code rather than 10, choose the 5 lines! And if 7 is the best compromise for speed/memory print, use the 7 lines. Resources are limited, don’t forget it. There are so limited that the strResp string value is limited to 1024 characters. And 1024 characters in HTML is reach very soon!

    I have to admit the first page I did I totally forget this limit. And guess what, first run with couple of HML worked perfectly and then it just raise an out of memory exception. And at this time, I just realize string were limited… That’s why in the code, you’ll find the following function and lines:

    private static string OutPutStream(HttpListenerResponse response, string strResponse)
            {
                byte[] messageBody = Encoding.UTF8.GetBytes(strResponse);
                response.OutputStream.Write(messageBody, 0, messageBody.Length);                 
                return "";
            }

    and the call is simple:

    strResp = OutPutStream(response, strResp);

    All what this function does is emptying the string and put it into the output stream to be displayed in the browser. As we are building our own page, it’s quite easy to know when the string will be close to 1024 characters and empty it. So you’ll see this line of code very regularly.

    The function return an empty string which I remap to the strResp string. All what the function does is convert the string into an array of bytes, and put it into the output stream and initialize again strResp to an empty string.

    I have N sprinklers to program and want to be able to change from a sprinkler to another. So the following line of code will create the right links:

    for (int i = 0; i < NUMBER_SPRINKLERS; i++)
                            if (i != intSprinkler)
                                strResp += "Calendar for <a href='" + MyParamPage.pageCalendar 
    + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month 
    + ParamEqual + intMonth + ParamSeparator + MyParamPage.spr + ParamEqual + i + "'>sprinkler " + i + "</a><br>";

    As you can see, the URL is build based on a class that returns string and couple of chars. All that is explain in a previous post.

    intYear and intMonth has been decoded from a URL like “calendar.aspx?year=2011;month=9;spr=0”. And the code generate URL like this Sourire

    Now, I want to add a “Previous” and “Next” month in my page. Again, usually using automatic component in a high level PHP, Java or ASP.NET on a Windows or Linux box is very easy. Everything is done automatically with high level framework. Here you have to do all the cases by hand. There is the case of the first month (January) where you’ll have to decrease for 1 year and change the month to 12 (December) to go on the previous month. There is the case of December where it’s the opposite to go on the next month. And as I want to allow only future current and future month, I need to make sure, I will not display any previous when it’s in the past.

    // Display some previous and next.
    // is it the first month? (case 1rst of January of the year to program but in the future year so month =12 and 1 less year)
    if ((intMonth == 1) && (intYear > DateTime.Now.Year))
        strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual + (intYear - 1) + ParamSeparator + MyParamPage.month + ParamEqual + "12" + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp";
    else if ((intMonth > DateTime.Now.Month) && (intYear == DateTime.Now.Year)) // (other cases
        strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual 
    + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth - 1) + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp"; else if(intYear > DateTime.Now.Year) strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual
    + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth - 1) + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinkler + "'>Previous month</a>&nbsp&nbsp&nbsp"; // next month //case december strResp = OutPutStream(response, strResp); if (intMonth == 12) strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual
    + (intYear + 1) + ParamSeparator + MyParamPage.month + ParamEqual + "1" + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinkler + "'>Next month</a>"; else // (other cases strResp += "<a href='" + MyParamPage.pageCalendar + ParamStart + MyParamPage.year + ParamEqual
    + intYear + ParamSeparator + MyParamPage.month + ParamEqual + (intMonth + 1) + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinkler + "'>Next month</a>";

    OK, we do have our “Previous” and Next” links now Sourire. Not rocket science code but efficient and easy to write. Let go for the calendar itself!

    // display and build a calendar :)
    strResp += "<p>";
    strResp += "<table BORDER='1'><tr>";
    for (int i = 0; i < days.Length; i++)
        strResp += "<td>" + days[i] + "</td>";
    strResp += "</tr><tr>";
    int NbDays = NumberDaysPerMonth(intMonth, intYear);
    DateTime dt = new DateTime(intYear, intMonth, 1);
    for (int i = 0; i < (int)dt.DayOfWeek; i++)
        strResp += "<td></td>";
    strResp = OutPutStream(response, strResp); 
    for (int i = 1; i <= NbDays; i++)
    {
        if ((intMonth == DateTime.Now.Month) && (intYear == DateTime.Now.Year) && (i < DateTime.Now.Day))
        { // don't add a link to program a past day
            strResp += "<td>" + i + "</td>";
        }
        else
        {
            strResp += "<td><a href='" + MyParamPage.pageProgram + ParamStart + MyParamPage.year 
    + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + intMonth + ParamSeparator
    + MyParamPage.day + ParamEqual + i + ParamSeparator + MyParamPage.hour + ParamEqual + DateTime.Now.Hour
    + ParamSeparator + MyParamPage.minute + ParamEqual + DateTime.Now.Minute + ParamSeparator
    + MyParamPage.spr + ParamEqual + intSprinkler + "'>" + i + "</a></td>"; } if ((i + (int)dt.DayOfWeek) % 7 == 0) strResp += "</tr><tr>"; strResp = OutPutStream(response, strResp); } strResp += "</tr></table>";

    In order to display a month, we will need 7 columns and as many row as necessary. We will only display the number of the day where it has to be. So the code starts with creating a table with a simple border.

    strResp += "<table BORDER='1'><tr>";
    for (int i = 0; i < days.Length; i++)
        strResp += "<td>" + days[i] + "</td>";
    strResp += "</tr><tr>";

    The days table is the following:

    static string[] days = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
    , "Friday", "Saturday" };

    Of course, you can get this from resources, make it localizable, etc. In my case, English will perfectly work for me and I need to use a minimum space in the netduino Sourire The DateTime class has an interesting feature as it gives you the day of the week you are.

    int NbDays = NumberDaysPerMonth(intMonth, intYear);
    DateTime dt = new DateTime(intYear, intMonth, 1);
    for (int i = 0; i < (int)dt.DayOfWeek; i++)
        strResp += "<td></td>";
    strResp = OutPutStream(response, strResp); 

    Used as in the example, it will give the first day of the month. And we know that we can fill the first values of the table with nothing as we are not at the first day. So as an example, if the first day is Monday, it will fill Sunday with nothing else than the <td></td>. DayOfWeek will be equal to 1. If it’s a Saturday, it will return 7 and the 6 first cells of the table will just be empty <td></td>. Now, we just can doo a loop up to the number of days in the month and don’t forget to add a <tr> tag after every Saturday Sourire

    for (int i = 1; i <= NbDays; i++)
    {
        if ((intMonth == DateTime.Now.Month) && (intYear == DateTime.Now.Year) && (i < DateTime.Now.Day))
        { // don't add a link to program a past day
            strResp += "<td>" + i + "</td>";
        }
        else
        {
            strResp += "<td><a href='" + MyParamPage.pageProgram + ParamStart + MyParamPage.year + ParamEqual + intYear + ParamSeparator + MyParamPage.month + ParamEqual + intMonth + ParamSeparator + MyParamPage.day + ParamEqual + i + ParamSeparator + MyParamPage.hour + ParamEqual + DateTime.Now.Hour + ParamSeparator + MyParamPage.minute + ParamEqual + DateTime.Now.Minute + ParamSeparator + MyParamPage.spr + ParamEqual + intSprinkler + "'>" + i + "</a></td>";
        }
        if ((i + (int)dt.DayOfWeek) % 7 == 0)
            strResp += "</tr><tr>";
        strResp = OutPutStream(response, strResp);
    }
    strResp += "</tr></table>";

    There is still a case here where we won’t add a link to program a past day when it’s the current month as we only allow program for future dates and not past dates. Of course, there will be an interesting case for the actual day but we will see that in a coming post. Pure HTML guys who want to validate the result code in a special HTML validator will tell me that I should add couple of more <td></td> to finalize the table. Fact is that it’s not really needed as all browsers interpret it correctly. Couple of lines of code less Sourire

    Rest of code is there just to empty the strResp buffer and output the stream in the response object. Final result looks like this (if we are the 7th of September 2011):

    netduino sprinkler 

    HTTP Method: GET
    Requested URL: "/calendar.aspx?year=2011;month=9;spr=0
    HTTP Version: 1.1"

    Calendar for sprinkler 1
    Calendar for sprinkler 2
    Month: 9
    Year: 2011
    Next month

    Sunday Monday Tuesday Wednesday Thursday Friday Saturday
    1 2 3
    4 5 6 7 8 9 10
    11 12 13 14 15 16 17
    18 19 20 21 22 23 24
    25 26 27 28 29 30

    And of course you can navigate with the “previous” (not here as it’s the current month) and “next” month links. When clicking on a day, it calls a page to program a sprinkler. We will see this in a next post.

    I hope you’ve enjoy this post. I did enjoy a lot creating this calendar. It’s so strange to do it by hand! As usual, feedback welcome, I’m just a marketing director doing code Sourire

  • Laurent Ellerbach

    Setup a time and date using .NET Microframework

    • 0 Comments

    In theory, .NET Microframework implement a class to get the time from a time server. It never worked for me using my netduino board. You’ll find more info on this board in my previous post. And also I’ve implemented a Web Server with the possibility to decrypt a parameter URL.

    netduino has no BIOS and no way when it’s off to keep a date and time. So each time you boot it, you have to setup the time and date yourself. Normally in order to do that, you can use the TimeService class.It looks like it’s not implemented on this board. The forum is very active and very useful. So as I needed the right time on my board and not in a very precise way (second and even minutes were ok), I get the idea of requesting a web page on my server that will return a date and time value.

    In terms of code on an IIS server, it’s very very very very simple:

    <%@ Page Title="Home Page" Language="C#" 
        CodeBehind="Default.aspx.cs" Inherits="DateHeure._Default" %><html><head></head>
    <body><% Response.Write(DateTime.Now.ToString("u")); %></body></html>
    Nothing else is needed! the “u” formatting return a date time like “2011/09/15 15:20:30Z”. So the return code from the server will be: <html><head></head><body>2011/09/15 15:20:30Z</body></html>

    On the client side on the netduino board, I needed to have an HTTP client and then decrypt the date and time. I found the HTTP Client in the sample and just simply it. So I’ve created a function that take a URL to request the page and return a date.

    public static DateTime ReadDateTime(string url)
     {
         // Create an HTTP Web request.
         HttpWebRequest request =
             HttpWebRequest.Create(url) as HttpWebRequest;
    
         // Set request.KeepAlive to use a persistent connection. 
         request.KeepAlive = true;
    
         // Get a response from the server.
         WebResponse resp = null;
         DateTime MyDateTime = DateTime.Now;
    
         try
         {
             resp = request.GetResponse();
         }
         catch (Exception e)
         {
             Debug.Print("Exception in HttpWebRequest.GetResponse(): " +
                 e.ToString());
         }
    
         // Get the network response stream to read the page data.
         if (resp != null)
         {
             Stream respStream = resp.GetResponseStream();
             string page = null;
             byte[] byteData = new byte[1024];
             char[] charData = new char[1024];
             int bytesRead = 0;
             Decoder UTF8decoder = System.Text.Encoding.UTF8.GetDecoder();
             int totalBytes = 0;
    
             // allow 5 seconds for reading the stream
             respStream.ReadTimeout = 5000;
    
             // If we know the content length, read exactly that amount of 
             // data; otherwise, read until there is nothing left to read.
             if (resp.ContentLength != -1)
             {
    
                 Thread.Sleep(500);
                 bytesRead =
                     respStream.Read(byteData, 0, byteData.Length);
                 if (bytesRead == 0)
                 {
                     return MyDateTime;
                 }
    
                 // Convert from bytes to chars, and add to the page 
                 // string.
                 int byteUsed, charUsed;
                 bool completed = false;
                 totalBytes += bytesRead;
                 UTF8decoder.Convert(byteData, 0, bytesRead, charData, 0,
                     bytesRead, true, out byteUsed, out charUsed,
                     out completed);
                 page = page + new String(charData, 0, charUsed);
    
                 // Display the page download status.
                 Debug.Print("Bytes Read Now: " + bytesRead +
                     " Total: " + totalBytes);
    
                 page = new String(
                     System.Text.Encoding.UTF8.GetChars(byteData));
             }
    
             // Display the page results.
             Debug.Print(page);
    
             // Close the response stream.  For Keep-Alive streams, the 
             // stream will remain open and will be pushed into the unused 
             // stream list.
             resp.Close();
             if (page.Length > 0)
             {
                 int start = page.IndexOf("<body>");
                 int end = page.IndexOf("</body>");
                 if ((start >= 0) && (end >= 0))
                 {
                     String strDateHeure = page.Substring(start + 6, end - start - 7);
                     if (strDateHeure.Length > 0)
                     {
                         int year = -1;
                         int month = -1;
                         int day = -1;
                         int hour = -1;
                         int minute = -1;
                         Convert.ToInt(strDateHeure.Substring(0, 4), out year);
                         Convert.ToInt(strDateHeure.Substring(5, 2), out month);
                         Convert.ToInt(strDateHeure.Substring(8, 2), out day);
                         Convert.ToInt(strDateHeure.Substring(11, 2), out hour);
                         Convert.ToInt(strDateHeure.Substring(14, 2), out minute);
                         if ((year != -1) && (month != -1) && (day != -1) && (hour != -1) && (minute != -1))
                             MyDateTime = new DateTime(year, month, day, hour, minute, 0);
                     }
                 }
             }
         }
    
         return MyDateTime;
     }
    First part of the code is the one form the sample. I’ve just modify the size of the buffer to fit with the max size in the netduino. Second part if the analyze of the return page. It does just keep what is between the <body> and </body> tags, remove the Z and basically convert the string to int using the convert class I’ve developed and expose in my previous post. I did not convert the second as I don’t need to be very precise. And of course, I’m checking if values are correct. I should have check also a range for year, month, day, hours and minutes. I did not and if something goes wrong I may get an exception when creating the DateTime class. I take the risk here.

    Now, I initialize the date and time when starting the HTTP server like this:

    DateTime TodayIs = new DateTime(2011, 8, 14, 10, 0, 0);
    Utility.SetLocalTime(TodayIs);
    Debug.Print(TodayIs.ToString());
    TodayIs = ReadDateTime(MyTimeServer);
    Utility.SetLocalTime(TodayIs);
    Debug.Print(TodayIs.ToString());

    MyTimeServer is a string with the URL of my date time page. Be careful as you’ll need a full URL including the name of the page. In my case the URL is http://www.ellerbach.net/DateHeure/default.aspx.

    By following the debug trace, you’ll see the date and time changing.

    It took about 1 hour to create this function and implement it in real Sourire I love this very cool netduino and .NET Microframework. The marketing guy doing development. Sourire

  • Laurent Ellerbach

    Implementing a simple HTTP server in .NET Microframework

    • 4 Comments

    To follow my previous posts, I’ve started to implement a simple HTTP server in my netduino using .NET Microfamework. I have to admit it was quite easy as there is a HTTP Server example in the samples. I was very impressed that with no OS so no Windows, no Linux, no Mac or any DOS or whatever OS, you can do high level code, create a Web Server in about 2 hours. I haven’t seen something comparable using Java, native C or other languages. There may be ways but here, all the framework is designed to be able to handle any kind of networking, there is even multithreading. I’ll use multithreading in a future post to show how to handle periodic calls.

    As I would not use all the functions, I’ve started to simplify the code and kept only what I needed.

    So I just kept couple of functions:

    • public static void StartHttpServer()
    • internal static void RunServer(string prefix)
    • static private string GetPathFromURL(string URL)
    • private static void ProcessClientGetRequest(HttpListenerContext context)
    • static void SendFileOverHTTP(HttpListenerResponse response, string strFilePath)
    • class PrefixKeeper

    I will not used any post method, so I removed it from the code. I removed also the certificate part because I won’t use HTTPS and removed the secure part as I won’t also use it. It needs to clean a bit the code but nothing really too complicated.

    I wanted to use parameter in the URL. So have requests like http://siteweb/page.ext?param1=value1;param2=value2

    In order to do that, I’ve created a very simple class which associate on parameter and one value. Nothing really to comment here, it’s a very classic class. I let the set and get properties in this class as it may be use in read and write. Both parameters and values are string.

    public class Param
            {
                private string myName = "";
                private string myValue = "";
    
                public string Name
                {
                    get { return myName; }
                    set { myName = value; }
                }
    
                public string Value
                {
                    get { return myValue; }
                    set { myValue = value; }
                }
    
                public Param()
                {
                    myName = "";
                    myValue = "";
                }
            }

    In the sample, there is nothing to decrypt such a URL. So I’ll need to function to decrypt the URL and return a table with parameters and the associated values.

    As I want to have clean code (or as clean as possible Sourire), I’ve defined 3 chars constant for the various separators.

    const char ParamSeparator = ';';
    const char ParamStart = '?';
    const char ParamEqual = '=';

    private static Param[] decryptParam(String Parameters)
    {
        Param[] retParams = null;
        int i = Parameters.IndexOf(ParamStart);
        int j = i;
        int k;
        if ( i> 0) 
        {
            //look at the number of = and ;
            
            while ((i < Parameters.Length) || (i == -1))
            {
                j = Parameters.IndexOf(ParamEqual, i);
                if (j > i)
                {
                    //first param!
                    if (retParams == null)
                    {
                        retParams = new Param[1];
                        retParams[0] = new Param();
                    }
                    else
                    {
                        Param[] rettempParams = new Param[retParams.Length+1];
                        retParams.CopyTo(rettempParams, 0);
                        rettempParams[rettempParams.Length-1] = new Param();
                        retParams = new Param[rettempParams.Length];
                        rettempParams.CopyTo(retParams, 0);
                    }
                    k = Parameters.IndexOf(ParamSeparator, j);
                    retParams[retParams.Length - 1].Name = Parameters.Substring(i + 1, j - i - 1);
                    //case'est la fin et il n'y a rien
                    if (k == j)
                    {
                        retParams[retParams.Length - 1].Value = "";
                    } // cas normal
                    else if (k > j)
                    {
                        retParams[retParams.Length - 1].Value = Parameters.Substring(j + 1, k - j - 1);
                    } //c'est la fin
                    else
                    {
                        retParams[retParams.Length - 1].Value = Parameters.Substring(j + 1, Parameters.Length - j - 1);
                    }
                    if (k > 0)
                        i = Parameters.IndexOf(ParamSeparator, k);
                    else
                        i = Parameters.Length;
                }
            }
        }
        return retParams;
    }

    The code here is not very complex. It looks first at the start parameter. Here, it’s the question mark (? ParamStart) then it finds the separator equal mark (= ParamEqual) and it finished by the separator (; ParamSeparator). Couple of cases if we are at the end for example as there is usually no separator.

    I’m not sure it’s the smartes way to do it but it’s working, it’s pretty robust and it’s been working with many various URL and cases. I’ve chosen to return a table as it’s easy to implement and easy to use. It’s pretty simple in .NET Microframework.

    You just has to be careful as depending on the platform you are using the size of the tables are limited. In the case of netduino, it’s a maximum 1024 elements. That’s also the limit size for strings. No impact here as we can consider (never consider anything in code Sourire) that a URL will be less than 1024 parameters as the string used will of course of a maximum of 1024 characters.

    In order to have clean code, I’ve also define couple of parameters and page names in a read only class.

    public class ParamPage {
        public string year { get { return "year"; } }
        public string month { get { return "month"; } }
        public string day { get { return "day"; } }
        public string hour { get { return "hour"; } }
        public string minute { get { return "minute"; } }
        public string duration { get { return "duration"; } }
        public string spr { get { return "spr"; } }
        public string pageProgram { get { return "program.aspx"; } }
        public string pageListPrgm { get { return "listprg.aspx"; } }
        public string pageCalendar { get { return "calendar.aspx"; } }
        public string pageSprinkler { get { return "sprinkler.aspx"; } }
    }

    It defines all my parameters, name of the pages I’ll use. So in code, I’ll use this class to make sure I’ll always use the right element and don’t mix up my parameters. It will also be the same name use for all pages when needed.

    As you’ve seen, the decrypt parameter function return a string value. In your code, you may want to convert it to int, float, bool or other numeric values. .NET Microframework does not provide any convert class as the full framework. So you’ll to do it by hand Sourire Not quite hard and you’ll be able to keep this class for other development.

    public class Convert
     {
         public static bool ToFloat(string s, out float result)
         {
             bool success = true;
             int decimalDiv = 0;
             result = 0;
             try
             {
                 for (int i = 0; i < s.Length; i++)
                 {
                     if (s[i] == '.' && decimalDiv == 0)
                         decimalDiv = 1;
                     else if (s[i] < '0' || s[i] > '9')
                         success = false;
                     else
                     {
                         result = result * 10;
                         decimalDiv = decimalDiv * 10;
                         result += (int)(s[i] - '0');
                     }
                 }
                 result = (float)result / decimalDiv;
             }
             catch
             {
                 success = false;
             }
             return success;
         }
    
         public static bool ToInt(string s, out int result)
         {
             bool success = true;
             result = 0;
             try
             {
                 for (int i = 0; i < s.Length; i++)
                 {
                         result = result * 10;
                         result += (int)(s[i] - '0');
                 }
             }
             catch
             {
                 success = false;
             }
             return success;
         }
    
         public static bool ToBool(string s, out bool result)
         { 
             bool success = true;
             result = false;
             try
             {
                 if ((s == "1") || (s.ToLower() == "true"))
                     result = true;
             }
             catch
             {
                 success = false;
             }
             return success;
         }
     
     }

    The code is very simple too. I’ve prefer to handle in the class a try catch and return a success value. I feel more comfortable coding like that but if you want to make it more simpler and faster, just don’t use a try catch and handle it in a higher level. The conversion for int will return funky numbers if you don’t have only decimal in the string and same for float. I’m not looking first if all are numeric if the min and max values are correct. It’s just fast and easy way to convert.

    For the bool conversion, I’ve decided to only validate the true which can be represented as 1 or true. Anything else will just be false. So here false is anything but true.

    Now to use the decrypt function and associate couple of values, here is a complete example. with the request.RawUrl you can get the URL so a string like calendar.aspx?year=2011;month=9;spr=0

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;
    // decode params
    string strParam = request.RawUrl;
    ParamPage MyParamPage = new ParamPage();
    int intMonth = -1;
    int intYear = -1;
    int intSprinkler = -1;
    Param[] Params = decryptParam(strParam);

    Here you’ll get Params as a table of 3 elements. First couple will be year and 2011, second month and 9 and third spr and 0. All as strings. Now you’ll have to convert those string into values and then use them in your code.

    if (Params !=null)
        for (int i = 0; i < Params.Length; i++)
        {
            //on cherche le paramètre strMonth
            int j = Params[i].Name.ToLower().IndexOf(MyParamPage.month);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intMonth);
            }
            j = Params[i].Name.ToLower().IndexOf(MyParamPage.year);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intYear);
            }
            j = Params[i].Name.ToLower().IndexOf(MyParamPage.spr);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intSprinkler);
            }
        }

    At the end, you’ll get intMonth = 9, intYear = 2011 and intSprinkler = 0.

    Last but not least, to call a function with a name and parameters you’ll need to do it in the private static void ProcessClientGetRequest(HttpListenerContext context) function from the sample.

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;
    
    ParamPage MyParamPage = new ParamPage();
    
    string strFilePath = GetPathFromURL(request.RawUrl);
    
    string strCalendar = "\\" + MyParamPage.pageCalendar;
    // if page calendar.aspx
     if (strFilePath.Length >= strCalendar.Length)
     {
         if (strFilePath.Substring(0, strCalendar.Length).ToLower() == strCalendar)
         {
             ProcessCalendar(context);
             return;
         }
     }

    So basically, the idea is to see if the name of the page is the one used at the beginning of the URL string. If yes, it calls a specific function and gives it the context object. From there, you can use the previous code to decode your URL and analyze your parameters.

    So to summarize, with couple of more functions, you are now able to pass parameters un a URL and decrypt them. For me, that’s what I wanted to do as it’s very easy to use to generate URL but also call specific URL in code. If you have better way to do all of this, just let me know, I’m just a marketing guy doing code Sourire

  • Laurent Ellerbach

    netduino board: geek tool for .NET Microframework

    • 0 Comments

    In the past, long time ago, I’ve been a developer. I loved to develop low level code like drivers. And I love embedded and robots and all those stuff. So I have a natural attraction for .NET Microframework. Of course I know it was existing but I never really touch it. And discussing with Pierre Cauchois, he told me he bought a netduino board and automate his cooler!

    I had a look at it and just figure that was exactly what I needed to start my automation sprinkler project! So I bought the netduino plus version with the micro sd card reader and the network connection. So 50€ later and couple of days I’ve received this gadget Sourire

    What I love with netduino is that it’s an open source design, really simple and efficient, the community is really active and it has all what I needed in terms of IO. And of course, I’ll be able to reuse my .NET C# skills. OK, last time I’ve coded in C# was 1 year ago to automate my CANON EOS and be able to control it. But after 2 hours of code, C# skills come back very fast Sourire And good news with .NET Microframework is that the number of class is quite small! so it’s very easy to understand, very efficient classes and pretty much all what you need.

    So I’ve started by downloading and installing all the SDK (I’m using Visual Studio Ultimate but it’s working with express versions). and downloaded the first example to make the embedded led blinking. And é minutes later, it was working Sourire At this time I was an happy geek Rire

    So I started to look at other samples that are available and played with the HHTPServer one. And decided to derive from this project to build my own pages and program my sprinklers. On the other side, I’ve done quite a bit retro engineering on my sprinklers (Gardena model). they are bi stable electro valve using 9V small impulsions. So I know I have to use 2 digital output to pilot open and close for each sprinkler. And I’ll first concentrate and the soft and then on the hardware. By the way, the hardware question is still open, so if anyone want help, I’ll appreciate it.

    When searching if someone already did this, I found Mike Linnen  who has done an amazing integration with Windows Azure and Windows Phone 7. check it, it’s really cool!

    In the next post, I’ll go thru couple of lines of code!

  • Laurent Ellerbach

    Re opening this blog

    • 0 Comments

    I’m re opening this blog. It’s been too long since I’ve posted anything on this blog.

    And as I’m developing a bit again, I’ve decided to share it more broadly. Well, that may be a bit specific as I’m developing on .NET Microframework but it may interest couple of people. My main goal is to be able to control my sprinklers at home over the Internet. For the moment, the only thing I can do is to select a program for a duration and a specific period on them. So when it’s raining or it’s too warm and I’m far away, I can’t adjust or make it adjust itself automatically.

    So I bought a netduino plus http://www.netduino.com/netduinoplus/specs.htm and started to develop a web interface on it and an hardware interface Sourire So I’ll post about this story.

    I love to be a marketing director doing dev. Dev is like sport, it’s good for your health Sourire

  • Laurent Ellerbach

    MSDN et formation

    • 0 Comments

    CIF, DIF, APR… Vous connaissez ? Et si je vous dis Congé individuel de formation, Droit individuel à la formation, Action préparatoire au recrutement ???

    La formation est un des points noirs de la satisfaction des développeurs (Etude ANIF 2007 sur le moral des informaticiens).

    Pour vous permettre de prendre en main votre formation, d’être pro-actif, nous avons réalisé un dossier sur MSDN sur le sujet. Les principaux dispositifs pour les salariés et les demandeurs d’emploi sont donc présentés, avec des liens utiles pour aller plus loin : http://msdn2.microsoft.com/fr-fr/bb980893.aspx

  • Laurent Ellerbach

    MSDN France vous souhaite un Joyeux Noël

    • 1 Comments

    Je profite d'une pause dans le marathon infernal de ces fêtes de fin d'année pour pointer une super vidéo où l'équipe de MSDN France vous souhaite une bonne année :


    Video: Joyeux Noël aux développeurs de la part d'MSDN

    A ne pas rater :-) Surtout le vrai Père Noël :-) Philippe a raté sa carrière. Il aurait dû faire acteur :-)

    Je vous laisse retourner à vos dindes, poissons, crustacés, fois gras et autres bûches.

  • Laurent Ellerbach

    IIS rattrape Apache comme serveur Web

    • 2 Comments

    Ca faisait déjà un moment qu’IIS progressait et cela continue. La source est l’étude Netcraft qui fait référence depuis plus de 10 ans sur le marché des serveurs Web.

    “This continues the strong gains seen last month, a rate of over 5% monthly growth, with MySpace, Microsoft Live.com, and Google's Blogger each gained over 1 million sites this month. Benefitting from the gains at MySpace and Microsoft Live, Microsoft-IIS now hosts over 50 million sites.”

    Le graphique est d’ailleurs intéressant à suivre : Market Share for Top Servers Across All Domains August 1995 - October 2007clip_image002

    Source : http://news.netcraft.com/archives/2007/10/11/october_2007_web_server_survey.html

  • Laurent Ellerbach

    Pour les étudiants : des Webcasts sur les carrières dans l'informatique

    • 1 Comments

    Sur le site Etudiants, qui a été dernièrement un peu relooké, nous lançons une nouvelle initiative d’échanges en live sur le net entre les étudiants et les employés de Microsoft pour les aider à mieux connaître les métiers des nouvelles technologies.

    Pour commencer cette série de rencontre live, Jérémy Fain, tout jeune responsable des partenariats avec les éditeurs de logiciels émergents, aura la chance de partager sa jeune expérience et de répondre aux  questions des étudiants  le mercredi 24 octobre à 18h.

    clip_image001

    Retrouvez  le programme des rencontres live avec les employés de Microsoft et les enregistrements des anciens webcasts sur le site Etudiants !

  • Laurent Ellerbach

    Apprendre .NET avec la Saga .NET

    • 2 Comments

    Mieux que Dalas, la Saga .NET, réalisée par Pascal Belaud, va vous permettre de vous mettre à .NET. C’est un cursus de cours de 10 épisodes complets avec des vidéos, les codes sources associés et de quoi refaire les exercices.

    Ce que j’aime particulièrement chez Pascal, c’est sa pédagogie, les explications qu’il donne sont toujours claires et les exemples parlent bien.

    image

    La série sera complétée par d’autres épisodes si nous en avons la demande. Aussi, n’hésitez pas à réagir en m’envoyant un mail ou dans les commentaires.

    Ca se passe ici : http://www.microsoft.com/france/vision/saga-dot-net/

  • Laurent Ellerbach

    Frogz : elle arrive le 8 octobre

    • 1 Comments

    Ca se passe sur http://www.frogz.fr

    J'adore :-)

    Il faut vraiment aller voir !

  • Laurent Ellerbach

    Fréquence MSDN, vous connaissez ?

    • 2 Comments

    C'est un nouveau concept que nous lançons. Une émission de radio diffusée en live avec roundtalbe (donc plutôt de la TV avec vision 360° du plateau) à partir du 10 octobre.

    L'objectif est de pouvoir revenir sur l'actialité des quelques semaines passées, décortiquer des annonces et aussi répondre à vos questions en direct. Vous pourrez en effet poser des questions en direct.

    Nous vous réservons également quelques surprises et un peu de fun :-)

    Nous avons prévu 1 heure pour la première émission. Si le concept plait, alors on remettra ça avec d'autres émissions.

    Pour s'inscrire, c'est là que ça passe :

    http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032354930&Culture=fr-FR

Page 2 of 6 (126 items) 12345»