Laurent Ellerbach

Ce blog est principalement destiné à publier des informations relatives à Microsoft, à ses technologies, aux outils Visual Studio et à ses versions Express notamment Visual Basic

September, 2011

  • 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

Page 1 of 1 (6 items)