-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathX10.py
229 lines (197 loc) · 5.46 KB
/
X10.py
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
import struct
import time
# Header Byte Types
addr = 0x04
func = 0x06
fullBright = 0x7e;
funccode = {
"All Off": 0x0,
"All On": 0x1,
"On": 0x2,
"Off": 0x3,
"Dim": 0x4,
"Bright": 0x5,
"All Off": 0x6,
"ExtCode": 0x7,
"HailReq": 0x8,
"HailAck": 0x9,
"Preset1": 0xA,
"Preset2": 0xB,
"ExtDataXfer": 0xC,
"StatusOn": 0xD,
"StatusOff": 0xE,
"StatusReq": 0xF
}
housecode = {
"A": 0x6,
"B": 0xE,
"C": 0x2,
"D": 0xA,
"E": 0x1,
"F": 0x9,
"G": 0x5,
"H": 0xD,
"I": 0x7,
"J": 0xF,
"K": 0x3,
"L": 0xB,
"M": 0x0,
"N": 0x8,
"O": 0x4,
"P": 0xC
}
unitcode = {
"1": 0x6,
"2": 0xE,
"3": 0x2,
"4": 0xA,
"5": 0x1,
"6": 0x9,
"7": 0x5,
"8": 0xD,
"9": 0x7,
"10": 0xF,
"11": 0x3,
"12": 0xB,
"13": 0x0,
"14": 0x8,
"15": 0x4,
"16": 0xC
}
# Given a byte string, calculate the checksum by adding all the
# bytes and then returning the bitwise AND with 0xFF.
#==============================================================
def X10_Checksum( s ):
sum = 0
for c in s:
sum = sum + ord(c)
return sum & 0xFF
# Send a string to the X10 CM11a module. The module replys with
# a chechsum. On a good checksum, we send an ACK. After the ACK,
# the module replys with a READY. Note, the ACK value is zero and
# the READY value is 0x55. Also note, it make take up to two
# seconds for the module to respond on some commands.
#==============================================================
def X10_Send( ser, s ):
ret = True # Init return code.
ser.flushInput()
ser.write( s )
c = ser.read( 1 )
cs = X10_Checksum( s ) # Compute checksum of the bytes.
if (len(c) == 1) and (ord(c) == cs): # Good Checksum
ser.write( chr(0x00) ) # Send ACK
c = ser.read(1) # Look for X10 ready.
if (len(c) == 1) and (ord(c) == 0x55):
ret = True # All Good
else:
print "Err: Missing X10 ready response."
ret = False
else:
print "Checksum Err / Len = %d" % len(c)
if len(c) == 1:
print "Checksum -> %x expecting %x" % (ord(c), cs)
ret = False
return ret # Return True on Good & False on Bad
#==============================================================
def X10_On( ser, h, u ):
ser.flushInput()
b = struct.pack( 'BB', addr, (h << 4 ) | (u & 0x0F) )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send first ON string.'
return False
b = struct.pack( 'BB', func, (h << 4 ) | funccode['On'] )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send second ON string.'
return False
return True # Everything must be OK.
#==============================================================
def X10_Off( ser, h, u ):
ser.flushInput()
b = struct.pack( 'BB', addr, (h << 4 ) | (u & 0x0F) )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send first OFF string.'
return False
b = struct.pack( 'BB', func, (h << 4 ) | funccode['Off'] )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send second OFF string.'
return False
return True # Everything must be OK.
#==============================================================
def X10_Bright( ser, h, u ):
ret = True
to = ser.timeout # Save timeout
ser.timeout = 5
ser.flushInput()
b = struct.pack( 'BB', addr, (h << 4 ) | (u & 0x0F) )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send first Bright string.'
ret = False
if ret == True:
b = struct.pack( 'BB', fullBright, (h << 4 ) | funccode['Bright'] )
#print "0x%x 0x%x" % struct.unpack('BB', b)
if X10_Send( ser, b ) == False:
print 'X10 Error send second Bright string.'
ret = False
ser.timeout = to # Restore timeout to orginal value.
return ret # True = OK / False = Error.
# Ask the CM11A for its status. In short order, the CM11A should
# respond with 14 bytes of status.
#==============================================================
def X10_Status( ser ):
to = ser.timeout # Save current timeout.
ser.timeout = 0.1 # Status bytes should be quick.
ret = False
ser.flushInput()
time.sleep( 0.1 )
ser.write( chr(0x8b) )
c = ser.read( 14 ) # The module should return 14 bytes of info.
if len(c) >= 13:
i = 0
for a in c:
print "%d : %s" % ( i, hex(ord(a)) )
i = i + 1
print 'X10 status OK.'
ret = True
else:
print 'X10 status is BAD.'
print 'X10 string len: ' + str(len(c))
i = 0
for a in c:
print "%d : %s" % ( i, hex(ord(a)) )
i = i + 1
ret = False
ser.write( chr(0x00) ) # Send an ACK.
ser.timeout = to # Restore timeout value.
return (ret, c)
# The CM11A X10 will NOT do anything until its clock is set.
# The following code just sets the clock to something so the
# interface can be used.
#==============================================================
def X10_SetClock( ser ):
# Since I don't use the clock in the CM11A this code just
# sets the clock to some junk so the module can start working.
s = b"\x9b\x32\x66\x07\xf4\x04\x60"
ser.flushInput()
time.sleep( 0.5 ) # Wait a bit after getting a 0xA5.
ser.flushInput()
ser.write( s )
print 'Reseting X10 clock.'
c = ser.read(1) # Readback checksum.
cs = X10_Checksum( s[1:] )
if (len(c) == 1) and (ord(c) == cs):
ser.write( chr(0x00) )
c = ser.read( 1 )
if (len(c) == 1) and (ord(c) == 0x55):
print 'X10 Clock set.'
else:
print 'X10 final 0x55 marker missing.'
else:
ser.write( chr(0x00) )
print 'Bad checksum from X10 interface.'
print 'X10 returned: ' + hex(ord(c))
print 'Expected Checksum: ' + hex(cs)