Public Class CM17A 'header and footer for every message Private Const HeaderCode = "1101010110101010" Private Const FooterCode = "10101101" 'device group 1-8 or 9-16? Private Const FirstGroupCode = "000" Private Const SecondGroupCode = "100" 'logical commands that can be sent Public Const CommandOn = "On" Public Const CommandOff = "Off" Public Const CommandBright = "Bright" Public Const CommandDim = "Dim" 'logical houses Public Const HouseA = "A" Public Const HouseB = "B" Public Const HouseC = "C" Public Const HouseD = "D" Public Const HouseE = "E" Public Const HouseF = "F" Public Const HouseG = "G" Public Const HouseH = "H" Public Const HouseI = "I" Public Const HouseJ = "J" Public Const HouseK = "K" Public Const HouseL = "L" Public Const HouseM = "M" Public Const HouseN = "N" Public Const HouseO = "O" Public Const HouseP = "P" 'literal codes for each house Dim Houses() As String = {"01100", "01110", "01000", "01010", "10000", "10010", "10100", "10110", "11100", "11110", "11000", "11010", "00000", "00010", "00100", "00110"} 'description of any error Public LastError As Microsoft.VisualBasic.ErrObject 'for communication with device Private CP As System.IO.Ports.SerialPort Public Sub New(ByVal nPort As Integer) If CP Is Nothing Then CP = New System.IO.Ports.SerialPort End If 'set variables: port, 9600, N, 8, 1, timeout CP.PortName = "COM" + nPort.ToString CP.BaudRate = 9600 CP.DataBits = 8 CP.StopBits = IO.Ports.StopBits.One CP.Parity = IO.Ports.Parity.None CP.WriteTimeout = 1000 End Sub Public Function SendCommand(ByVal strHouse As String, ByVal nDevice As Integer, ByVal strX10Cmd As String) As Boolean Dim bResult As Boolean = True Dim strError As String = "" 'construct 2-byte command to send to CM17A device 'see ftp://ftp.x10.com/pub/manuals/cm17a_protocol.txt for protocol details Dim strCmd As String 'header strCmd = HeaderCode '1st byte of command is house code + group code strCmd += Houses(Asc(strHouse) - Asc(HouseA)) If nDevice <= 8 Then strCmd += FirstGroupCode Else strCmd += SecondGroupCode End If '2nd Byte of command is more complicated 'thanks to Adam Davis - http://www.ubasics.com/adam/electronics/cm17.shtml for breaking it down 'bit 1 If strX10Cmd = CommandDim Or strX10Cmd = CommandBright Then strCmd = strCmd + "1" Else strCmd = strCmd + "0" End If 'bit 2 Select Case nDevice Case 1 To 4, 9 To 12 strCmd += "0" Case Else strCmd += "1" End Select 'bit 3 If strX10Cmd = CommandOff Then strCmd += "1" Else strCmd += "0" End If 'bit 4 If (nDevice Mod 2 = 0) Or (strX10Cmd = CommandDim) Then strCmd += "1" Else strCmd += "0" End If 'bit 5 If strX10Cmd = CommandDim Or strX10Cmd = CommandBright Then strCmd += "1" Else Select Case nDevice Case 1, 2, 5, 6, 9, 10, 13, 14 strCmd += "0" Case Else strCmd += "1" End Select End If 'bits 6-8 strCmd += "000" 'footer strCmd += FooterCode 'send command to serial port 'open and prep Try CP.Open() CP.DiscardInBuffer() CP.DiscardOutBuffer() Catch Ex As Exception bResult = False LastError = Err() End Try If CP.IsOpen Then Dim nDelay As Integer = 30 'milliseconds Dim nBit As Integer = 0 'send reset/no power CP.DtrEnable = False CP.RtsEnable = False System.Threading.Thread.Sleep(nDelay) 'send power CP.DtrEnable = True CP.RtsEnable = True System.Threading.Thread.Sleep(nDelay) For nBit = 0 To strCmd.Length - 1 'either dtr or rts must be true at any given time to maintain power to unit, 'thus true is always set before false If Convert.ToInt32(strCmd.Substring(nBit, 1)) = 0 Then 'send 0 CP.DtrEnable = True CP.RtsEnable = False Else 'send 1 CP.RtsEnable = True CP.DtrEnable = False End If System.Threading.Thread.Sleep(nDelay) 'reset for next bit CP.RtsEnable = True CP.DtrEnable = True System.Threading.Thread.Sleep(nDelay) Next End If If CP.IsOpen Then CP.Close() Return bResult End Function End Class