Iphone as a Universe Controller: Part 1

Why have a universal remote control when you can have a universe controller? I was fortunate enough to get to beta test some of ioBridge's forthcoming hardware. Their hardware lets you connect just about anything to the internet. The possibilites with these things are just about limitless. I am convinced I can control just about anything in my house with this little board and my iPhone. The company has a number of premade "smart boards." The modules also have input/output pins so you can get any of your microcontroller projects online. I wanted to put together a few simple progects based on their smart boards. I got a x10, light sensor, and a servo smart board. I made a little gizmo with each one. In this write up I'm going to talk about the gizmo I made with their servo smart board.  In my next post I'm going to demonstrate how to control you home lights. Then I will post about how the ioBridge module can be used to lock your computer and update your twitter feed automatically when you leave the office. 

I have a dog that stays home alone while I am at school. I thought it would be nice to be able to check up on my dog Cooper during the day, and even better if I could give him a delicious doggie treat. With the ioBridge module, a servo smart board, and some random parts around the house I was able to put together a dog watching, treat giver that is all controlled with my iPhone over the internet. The whole project took about an hour and because of iobridge's simple internet interface no programing was required. 

Here is a video (youtube link) of the finished project. Below the video are my detailed instruction about the project.


Finished project in action

Here's what I used:
ioBridge I/O module
ioBridge servo smart board
servo
old CD spindle case
cardboard scrap
large syringe plunger
scrap wood
webcam (just used for visual confirmation that treat was delievered)

ioBridge servo smart board

I started by cutting a hole in the top of the old CD case for the axel of the servo to fit through. With some scrap wood I mounted the servo above the case.

Old CD spindle case with servo attached to top. The windows in the side are for loading the dispenser with treats


I cut the plunger to a length about a quarter of an inch shorter then the interior of the old cd case. After super gluing the servo's detachable wheel to the top of the plunger I glued square cardboard scrap to half of the plunger at 45 degree angles. I made some triagnles out of wood and used them to keep each of the fins seperated by 45 degrees. While the glue dried I cut a pie shaped wedge in the board that was the same size as the wedges created by gluing the cardboard at 45 degree angles around the plunger. 

Syringe plunger with cardboard fins attached at 45 degree angles

Bottom platform with hole cut for treat to drop through


Once the glue dried I attached the plunger to the servo and connected the servo to the ioBridge I/O modeule via the servo smart board.

View of bottom of housing with plunger assembly attached to servo

Assembled device

I followed the simple ioBridge instructions for getting their board online for the first time. Using the ioBridge web interface it was simple to create a widget that controlled the servo. At the end of the widget wizard it automatically saved the buttons that controlled the position of the servo in my ioBridge dashboard (the dashboard is your home page once you log into the ioBridge website). The wizard also outputs javascript incase you want to embed the controls in your own page as I did. 

Screen shot of widget builder 

With all the javascript their site gave me it was no time before I had a webpage that I could access from my iPhone. I could have just pasted the javascript they gave me into notepad and saved it as an html and had controls that would control my device, but I wanted a little something more. I optimized it to be viewed on my iPhone and embedded a feed from a streaming webcam I placed over Cooper's kennel. Now I could see what my dog is up to when I'm away. I saved the website to my iPhone's home screen, and in less than an hour and a half from starting the project I had a web app on my phone from which I could view my dog and give him delicious, steak flavored treats. 



Icon on iPhone home screen and then view of the web app I created using the ioBridge generated javascript. The picture of my dog is from a streaming webcam.



How to do somthing(call JavaScript code) after AnimationExtender completed

Many engineers use AjaxControlToolkit AnimationExtender to achieve the animation process. It encapsulates JavaScript library to achieve.
Now there is a scenario: When the AnimationExtender is completed, how can we do some JavaScript? For example:

<asp:ImageButton ID="ib1" ImageUrl="~/images/AJAX.gif" OnClientClick="return false;"  Height="100px" Width="100px" runat="server" />
<ajaxToolkit:AnimationExtender id="OpenAnimation" runat="server" BehaviorID="AnimationBehavior"  TargetControlID="ib1" >
   <Animations>
        <OnClick>
           <Sequence>
           <EnableAction Enabled="false" />              
           <Pulse Duration=".1" />
           <Parallel AnimationTarget="ib1" Duration=".3" Fps="30">
             <FadeOut />
               <Scale ScaleFactor="5" Unit="px" Center="true"  ScaleFont="true" FontUnit="pt" />
           </Parallel>              
           <StyleAction Attribute="postbackurl" Value="~/Default.aspx"/>
         </Sequence>
        </OnClick>
     </Animations>
</ajaxToolkit:AnimationExtender>



With the above sample, it will do Animation after you click the imagebutton. But now, we want to make it redirect to a new page after clicking the imagebutton and completing the Animation. If you define imagebutton OnClick event, it will not be triggered because OnClientClick returns false. If you remove out OnClientClick="return false;", it will do postback directly when you click the button, rather than waiting the completion of animation. Maybe we can call some client event, which will be triggered after AnimationExtender is completed. But the problem is AnimationBehavior hasn't any client event about onCompleted.

Actually, I'd like to make a way to achieve it: we can build an Animation object to contact with the AnimationBehavior, receive the Animation instance from it and declare OnEnd client event of Animation object.


<script type="text/javascript">

     function pageLoad() {
         var animation =$find('AnimationBehavior')._onClick.get_animation();
         animation.add_ended(onend);
     }
     function onend() {
         window.location.href = "../../../Default.aspx";
    
     }

</script>


Now, after you click the imagebutton, it will do the Animation. After anything is completed, it will go to the new page.

Build a Combobox in ASP.Net

As we all known, DropDownList in ASP.Net is totally different from Combobox in WinForm. However, sometimes, we hope we are able to input some words in DropDownList in ASP.Net, and the related item will be hightlighten so that we can get the functionality of Combobox in WinForm.


Fortunately, AjaxControlToolkit provides ListSearch control for us to achieve this(http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ListSearch/ListSearch.aspx). But we have to build two controls to populate the functionality and type the key words above the select control.


It's still different from Combobox in Winform. We hope we can type the words inside DropDownList and the related item will be returned in the list as the below pic.
How can we achieve that?
I rebuild the whole select control with HTML code and Css so that I can input text inside select control.


Default.aspx:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>combobox</title>
    <link href="ListSearch.css" rel="stylesheet" type="text/css" />
</head>

<script type="text/javascript">
    var dropShow = false
    var currentID
    function dropdown(el) {
        if (dropShow) {
            dropFadeOut()
        } else {
            currentID = el
            el.style.visibility = "visible"
            dropFadeIn()
        }
    }
    function dropFadeIn() {//select box fade in
        if (currentID.filters.alpha.opacity < 100) {
            currentID.filters.alpha.opacity += 20
            fadeTimer = setTimeout("dropFadeIn()", 50)
        } else {
            dropShow = true
            clearTimeout(fadeTimer)
        }
    }
    function dropFadeOut() {//select box fade out
        if (currentID.filters.alpha.opacity > 0) {
            clearTimeout(fadeTimer)
            currentID.filters.alpha.opacity -= 20
            fadeTimer = setTimeout("dropFadeOut()", 50)
        } else {
            dropShow = false
            currentID.style.visibility = "hidden"
        }
    }
    function dropdownHide() {
        if (dropShow) {
            dropFadeOut()
            dropShow = false
        }
    }
    function hiLight(el) {//highlight place
        if (dropShow) {
            for (i = 0; i < el.parentElement.childNodes.length; i++) {
                el.parentElement.childNodes(i).className = "link_record0"
            }
            el.className = "link_record1"
        }
    }
    function CheckMe(el) {//replace with the selected item
        document.all.text1.value = el.innerText

    }
    document.onclick = dropdownHide


    function listsearch() {
        if (dropShow) {

        } else {
            currentID = value1
            value1.style.visibility = "visible"
            dropFadeIn()
        }
        var word = document.all.text1.value;
        var l;
        var childsnum = value1.childNodes.length;
        for (l = 0; l < childsnum; l++) {
            var s = value1.childNodes[l].innerText;

            if (s.substring(0, word.length) == word)
                hiLight(value1.childNodes[l]);

        }

    }
</script>

<body text="#000000">
    <form id="form1" runat="server">
    <table>
        <tr>
            <td>
                <div class="link_box" onselectstart="return false" style="width: 98%;">
                    <div class="link_head" onclick="dropdown(value1)">
                        <table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0">
                            <tr>
                                <td>
                                    <div class="link_text">
                                        <nobr><input id="text1" type="text" onkeyup="listsearch()"></input></nobr>
                                    </div>
                                </td>
                                <td align="right" width="22">
                                    <div onmouseup="this.className='link_arrow0'" class="link_arrow0" onmousedown="this.className='link_arrow1'"
                                        onkeypress="this.className='link_arrow0'">
                                        6</div>
                                </td>
                            </tr>
                        </table>
                    </div>
                    <div class="link_value" id="value1" style="width: 500px; height: 300px">
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                attach</label></div>
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                bea</label></div>
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                free</label></div>
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                jump</label></div>
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                lumb</label></div>
                        <div class="link_record0" onmouseover="hiLight(this)" onclick="CheckMe(this);document.all.form1.city.value=this.innerText">
                            <label>
                                luppy</label></div>
                    </div>
                </div>
            </td>
            <td>
                <input type="hidden" value="Please Select" name="city">
                <input type="submit" value="ok">
            </td>
        </tr>
    </table>
    </form>
</body>
</html>


ListSearch.css:

BODY {
FONT: 12px
}
TD {
FONT: 12px
}
DIV {
FONT: 12px
}
LABEL {
PADDING-RIGHT: 0px; PADDING-LEFT: 4px; PADDING-BOTTOM: 0px; PADDING-TOP: 3px; HEIGHT: 19px
}
.link_box {
CURSOR: default; TEXT-ALIGN: left;
}
.link_head {
BORDER-RIGHT: 2px inset; BORDER-TOP: 2px inset; BORDER-LEFT: 2px inset; WIDTH: 100%;
BORDER-BOTTOM: 2px inset; HEIGHT: 23px
}
.link_text {
PADDING-LEFT: 2px; BACKGROUND: #fff
}
.link_arrow0 {
BORDER-RIGHT: 2px outset; BORDER-TOP: 2px outset; BACKGROUND: buttonface;
FONT: 14px marlett; BORDER-LEFT: 2px outset; WIDTH: 22px;
BORDER-BOTTOM: 2px outset; HEIGHT: 19px; TEXT-ALIGN: center
}
.link_arrow1 {
BORDER-RIGHT: buttonshadow 1px solid; PADDING-RIGHT: 0px;
BORDER-TOP: buttonshadow 1px solid; PADDING-LEFT: 2px;
BACKGROUND: buttonface; PADDING-BOTTOM: 0px; FONT: 14px marlett;
BORDER-LEFT: buttonshadow 1px solid; WIDTH: 22px; PADDING-TOP: 2px;
BORDER-BOTTOM: buttonshadow 1px solid; HEIGHT: 19px; TEXT-ALIGN: center
}
.link_value {
BORDER-RIGHT: 1px solid; BORDER-TOP: 1px solid; FILTER: alpha(opacity:0);
VISIBILITY: hidden; OVERFLOW-X: hidden; OVERFLOW: auto; BORDER-LEFT: 1px solid;
BORDER-BOTTOM: 1px solid; POSITION: absolute
}
.link_record0 {
BORDER-TOP: #eee 1px solid; PADDING-LEFT: 2px; BACKGROUND: #fff;
WIDTH: 100%; COLOR: #000; HEIGHT: 20px
}
.link_record1 {
BORDER-TOP: #047 1px solid; PADDING-LEFT: 2px; BACKGROUND: #058;
WIDTH: 100%; COLOR: #fe0; HEIGHT: 20px
}


The sample is based on native code. I plan to build it by ASP.Net Ajax ScriptControl model in the future.