Help - Search - Members - Calendar
Full Version: Diy Web Based Ajax Universal Remote
Lumenlab > Community Interests > Mad Science
computercowboy
DOWNLOAD EXAMPLE SOURCE CODE HERE: http://theater.computercowboy.com/Control/

I got my USB-UIRT on Saturday and wasted no time putting together a web based software that I can run on any computer on the internet. For now I have a monitor and mouse behind my couch but I will be buying a touch screen soon. I did the whole thing in .net and it works very well. I have attached a component diagram and a screen shot of the interface. Most of the time was spent collecting the graphics/icons, that and training all the IR codes. I wrote about 2,000 lines of code to make it all work.

Components controlled
Click to view attachment

Interface
Click to view attachment

I am having trouble getting receive events working over RS232 from the projector. I can send commands just fine. Projector control is a mixture of IR for toggle commands and RS232 for specific settings like aspect ratio. The source switching is beautiful and it allows me to change audio, video, aspect ratio and overscan in one click. To do that with the remotes required 4 different remotes and muliple button pushes on one of them. The channel macros are nice also. I mad a list of my favorite channels as number enums.

CODE
/// <summary>
    /// A list of Channels
    /// </summary>
    public enum Channel
    {
        Discovery=776,
        FOX=708,
        NFL=777,
        ABC=710,
        NBC=713,
        CBS=706,
        AandE=771,
        HBO=750,
        ESPN=772,
        ESPN2=778,
        NESN=733,
        TNT=764,
    }


The string for a channel can be sent from the JavaScript links on the page via AJAX and then parsed using the following code.

CODE
/// <summary>
        /// Takes a channel name and sends the commands to change to that channel
        /// </summary>
        /// <param name="strChannel">Channel Name</param>
        [AjaxPro.AjaxMethod]
        public static void ChannelCommmand(string strChannel)
        {
            Controller uirt = new Controller();
            // make str into enum type
            Channel channel = (Channel)Enum.Parse(typeof(Channel), strChannel);

            // get the channel # via cast
            int channelNumber = (int)channel;

            // pop it into a char array
            char[] digits = channelNumber.ToString().ToCharArray();

            // loop through each char of the channel
            foreach (char digit in digits)
            {
                // get the index of the number in the static array
                int codeIndex = Convert.ToInt32(digit.ToString());

                // transmit the propper code using the index
                uirt.Transmit(ControlCodes.SA8300HD.Number[codeIndex]);
            }

            // transmit an accept code for immediate results
            uirt.Transmit(ControlCodes.SA8300HD.Button_Select);
        }



I am excited to get an X10 firecracker to control the lights in the living room and around the house. I would rather get RadioRA but it is just too expesive at the moment. The RS232 for RadioRA costs ~$700 and the x10 Firecracker cost ~$40. I guess I will just have to wait for my raise / bonus to get RadioRA. Anyway the X10 firecracker is apparently really easy to control via RS232 which is super easy to do in .NET, check out how easy it is to send a command to the InFocus projector

CODE
            SerialPort sp5000 = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);

            // Open the sp5000 for communications
            sp5000.Open();

            sp5000.Write(ControlCodes.InfocusSP5000.RS232.OverscanOff);

            sp5000.Close();


Part of the solution I have right now has some sample code for the firecracker based on .NET 1.1, I am going to use the enums and such from it but I will probably just use the SerialPort class from .NET 2.0 as I have done with the SP5000.

Doing this project makes me want all my devices to have RS232 control.

Other thoughts:
The web app runs off my main media server / router computer on Windows Server 2003. I have a HTPC running XP pro and I want to be able to send it generic commands for power dvd like play pause etc. I am trying to figure out exactly how to do this. One thought I had is a windows service or web service on the XP machine to receive the commands and invoke/marshall them on the xp client machine. The other thought is some sort of hardware / software solution like make some custom serial to ps2 cable and send commands directly to the ps2 port. I don't know if option 2 is possible or pratical but I am thinking that option 1 is better. The problem with option one is I don't know how to marshal a generic command like 'Play' from .net. I found an article on code project about controlling specific apps like windows media player but I want it to be a generic command almost as if a keyboard button had been pressed on the client machine. Any ideas?
infinityPlusOne
That's wicked.

Now, whats the URL so I can change the channels on you? Muwhahaha!
computercowboy
QUOTE (infinityPlusOne @ Sep 6 2007, 12:21 PM) *
That's wicked.

Now, whats the URL so I can change the channels on you? Muwhahaha!

password protected boss, if you download you can configure the password in the web.config file
Natural Newbie
Now thats what I call useful programming! Your catching up to the way bill gates lives, hehe.
computercowboy
Ordered the x10 Firecracker on Friday with enough lighting modules to control the living room. I should have that all set in a couple hours after receiving it.
computercowboy
Updated FireCracker code for .NET 2.0

I upgraded the code for communicating with the firecracker that I got from some website to work better in .NET 2.0, mainly I just changed it so that it uses the new SerialPort class in .NET 2.0
CODE
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace X10
{
    public class FireCracker
    {
        // Serial Port used to send commands
        private SerialPort sp;

        /// <summary>
        /// Init FireCracker
        /// </summary>
        /// <param name="ComPort">The COM Port to use to send Commands</param>
        public FireCracker(int ComPort)
        {
            // set up the Com Port
            sp = new SerialPort("COM" + ComPort.ToString(), 9600, Parity.None, 8, StopBits.One);
        }

        #region Methods

        /// <summary>
        /// Send a command to the X10 device with the supplied house code, device code, and command.
        /// </summary>
        /// <param name="houseCode">The house code of the device you wish to control.</param>
        /// <param name="deviceCode">The numeric id of the device you wish to control.</param>
        /// <param name="cmd">The command you wish to give this device. TurnOn, TurnOff, Brighten, Dim.</param>
        /// <returns>True when the SendCommand operation is complete</returns>
        public bool SendCommand(char houseCode, int deviceCode, X10DeviceCommand cmd)
        {

            // Send to the mCommPort serial port a binary stream consisting of the house code
            // device code, and any additional binary data that helps execute the desired command.;
            string binaryCmd = HeaderCode + GetBinaryHouseCode(houseCode) + GetBinaryGroupCode(deviceCode);

            switch (cmd)
            {
                case X10DeviceCommand.TurnOn:
                    binaryCmd += GetBinaryCommandCode(deviceCode, BinaryCommandCodes.TurnOnIndex);
                    break;
                case X10DeviceCommand.TurnOff:
                    binaryCmd += GetBinaryCommandCode(deviceCode, BinaryCommandCodes.TurnOffIndex);
                    break;
                case X10DeviceCommand.MakeBrighter:
                    binaryCmd += MakeBrighterCommandCode;
                    break;
                case X10DeviceCommand.MakeDimmer:
                    binaryCmd += MakeDimmerCommandCode;
                    break;
            }

            binaryCmd += FooterCode;

            // Open the port up
            sp.Open();
            sp.DtrEnable = false;
            sp.RtsEnable = false;
            System.Threading.Thread.Sleep(DELAY);
            sp.DtrEnable = true;
            sp.RtsEnable = true;
            System.Threading.Thread.Sleep(DELAY);
            for (int bit = 0; bit < binaryCmd.Length; bit++)
            {
                if (Convert.ToInt32(binaryCmd.Substring(bit, 1)) == 0)
                {
                    sp.DtrEnable = true;
                    sp.RtsEnable = false;
                }
                else
                {
                    sp.DtrEnable = false;
                    sp.RtsEnable = true;
                }
                System.Threading.Thread.Sleep(DELAY);
                sp.RtsEnable = true;
                sp.DtrEnable = true;
                System.Threading.Thread.Sleep(DELAY);
            }

            // Close Port
            sp.Close();
            return true;
        }

        /// <summary>
        /// Determine the binary group code from the device code
        /// </summary>
        private string GetBinaryGroupCode(int deviceCode)
        {
            return (deviceCode > 8 ? SecondGroupCode : FirstGroupCode);
        }


        /// <summary>
        /// Convert a house code (A-P) to its binary representation
        /// </summary>
        private string GetBinaryHouseCode(char houseCode)
        {
            houseCode = Convert.ToChar(houseCode.ToString().ToLower());
            return mBinaryHouseCode[houseCode - Convert.ToInt32('a')];
        }


        /// <summary>
        /// Convert a device code + command code index to its binary representation
        /// </summary>
        private string GetBinaryCommandCode(int deviceCode, BinaryCommandCodes codeIndex)
        {
            return mBinaryCommandCode[deviceCode - 1, Convert.ToInt32(codeIndex)];
        }

        #endregion

        #region BinaryCodes

        private const int DELAY = 30; // The delay between sending bits, in milliseconds
        private const string HeaderCode = "1101010110101010"; // Header (never changes);
        private const string FooterCode = "10101101"; // Footer (never changes);
        private const string MakeBrighterCommandCode = "10001000"; // Brightens last device, if applicable;
        private const string MakeDimmerCommandCode = "10011000"; // Dims last device, if applicable;
        private const string FirstGroupCode = "0000"; // Applies to devices 1-8;
        private const string SecondGroupCode = "0100"; // Applies to devices 9-16;

        // y value in mBinaryCommandCode(x,y) array.
        private enum BinaryCommandCodes
        {
            TurnOnIndex = 0,
            TurnOffIndex = 1
        }

        // House codes A-P in binary.
        private string[] mBinaryHouseCode =        { "0110", "0111", "0100", "0101", "1000", "1001", "1010", "1011", "1110", "1111", "1100", "1101", "0000", "0001", "0010", "0011" };

        // Pattern: { { Dev Code 1, On } { Deve Code 1, Off }, { Dev Code 2, On } { Dev Code 2, Off }, ... }
        // Bit layout: "0ac0b000" where bits
        // a = 1-4/9-12 vs. 5-9/13-16
        // b = 1-2/5-6/9-10/13-14 vs. 3-4/7-8/11-12/15-16
        // c = on vs. off
        private string[,] mBinaryCommandCode =     { { "00000000", "00100000" }, { "00010000", "00110000" }, { "00001000", "00101000" }, { "00011000", "00111000" }, { "01000000", "01100000" }, { "01010000", "01110000" }, { "01001000", "01101000" }, { "01011000", "01111000" }, { "00000000", "00100000" }, { "00010000", "00110000" }, { "00001000", "00101000" }, { "00011000", "00111000" }, { "01000000", "01100000" }, { "01010000", "01110000" }, { "01001000", "01101000" }, { "01011000", "01111000" } };

        #endregion

    }

    /// <summary>
    /// Commands that may be sent to SendCommand().
    /// </summary>
    public enum X10DeviceCommand
    {
        TurnOn = 0,
        TurnOff = 1,
        MakeBrighter = 2,
        MakeDimmer = 3
    }
}
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.