Now that we have our development environment setup, let's take a look at the code. I first changed the way the the X10 library is created ("Firecracker.cs"). I decided to take advantage of the "Singleton Design Pattern" (http://www.c-sharpcorner.com/Code/2003/Jan/SingletonPattern.asp). Essentially this allows us to have ONLY a single instance of our class created. This instance then will be used by all calling applications. The main reason for this is because the library relates to the single serial port instance. If we had more than one application trying to access the Serial port, it would definitely throw an exception. So now we limit that access to a single point in the code and a single class, so if more than one caller needs to use the resource, they will have to sit and wait for it to be freed.
Here is the rewrite of the class initialization. Notice that it does in fact use the Singleton Pattern and that we have moved the serial port initialization to use the new library.
#region Singleton pattern to avoid more than
once instance of the class
private Firecracker() {
}
Communications.Rs232 comm=null;
private Firecracker(int commPort) {
comm = new Communications.Rs232();
comm.Port=commPort;
comm.BaudRate=9600;
comm.DataBit=8;
comm.StopBit=Communications.Rs232.DataStopBit.StopBit_1;
comm.Parity=Communications.Rs232.DataParity.Parity_None;
comm.Timeout=1000;
this.CommPort = commPort;
}
privatestaticvolatile Firecracker instance=null;
publicstatic Firecracker GetInstance(int CommPort) {
//Double-Check Lock singletone
if(instance==null)
{
lock(typeof(Firecracker))
{
if(instance==null)
{
instance = new Firecracker(CommPort);
}
}
}
return instance;
}
#endregion
The next major rewrite of code is the method named "SendCommand". Here is the new implementation. Notice that the Serial Communication IO uses the new library and not Vallelunga's library. You will find this new implementation much more stable than the previous build.
publicbool SendCommand(char houseCode, int deviceCode, Commands 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.ToString()) {
case "TurnOn":
binaryCmd += GetBinaryCommandCode(deviceCode,
BinaryCommandCodes.TurnOnIndex);
break;
case "TurnOff":
binaryCmd += GetBinaryCommandCode(deviceCode,
BinaryCommandCodes.TurnOffIndex);
break;
case "MakeBrighter":
binaryCmd += MakeBrighterCommandCode;
break;
case "MakeDimmer":
binaryCmd += MakeDimmerCommandCode;
break;
}
int delay = 30;
binaryCmd += FooterCode;
comm.Open();
comm.Dtr=false;
comm.Rts=false;
System.Threading.Thread.Sleep(delay);
comm.Dtr=true;
comm.Rts=true;
System.Threading.Thread.Sleep(delay);
for(int bit=0;bit<binaryCmd.Length;bit++) {
if (Convert.ToInt32(binaryCmd.Substring(bit, 1)) == 0) {
comm.Dtr=true;
comm.Rts=false;
} else {
comm.Rts=true;
comm.Dtr=false;
}
System.Threading.Thread.Sleep(delay);
comm.Rts=true;
comm.Dtr=true;
System.Threading.Thread.Sleep(delay);
}
//comm.Write(b);
comm.Close();
returntrue;
}
First this code gathers the necessary bits to send to the serial port in the "binaryCmd" variable. This is of course based on the house code, device code, and the command that you chose to send. The loop may seem strange to you. This is where we actually send the command to the serial port itself. We need to loop over each bit that we gathered and set the state of the DTR (data set ready) and RTS (request to send) lines. For more information on the Firecracker (CM17A) Communications Specification see the "7A programming protocol.txt" document (http://www.mscorlib.com/7A%20programming%20protocol.txt).