|
2 | 2 | import struct
|
3 | 3 | from serial import Serial
|
4 | 4 |
|
| 5 | +END_COMMAND = '\r\n' |
| 6 | + |
5 | 7 | # command types
|
6 |
| -POINT_TO_MULTIPOINT = '\\05' |
| 8 | +POINT_TO_MULTIPOINT = '~\\05' |
7 | 9 |
|
8 | 10 | # Applications
|
9 | 11 | APP_LIGHTING = '38'
|
10 | 12 |
|
11 | 13 | # Routing buffer
|
12 | 14 | ROUTING_NONE = '00'
|
13 | 15 |
|
14 |
| - |
| 16 | +LIGHT_ON = '79' |
| 17 | +LIGHT_OFF = '01' |
15 | 18 | # light on
|
16 | 19 | #\0538007964 (GA 100)
|
17 | 20 |
|
|
21 | 24 | # set to level
|
22 | 25 | #\053800rr64FF (GA 100, to level 100%/0xff)
|
23 | 26 |
|
| 27 | +RAMP_RATES = { |
| 28 | + '02': 0, |
| 29 | + '0A': 4, |
| 30 | + '12': 8, |
| 31 | + '1A': 12, |
| 32 | + '22': 20, |
| 33 | + '2A': 30, |
| 34 | + '32': 40, |
| 35 | + '3A': 60, |
| 36 | + '42': 90, |
| 37 | + '4A': 120, |
| 38 | + '52': 180, |
| 39 | + '5A': 300, |
| 40 | + '62': 420, |
| 41 | + '6A': 600, |
| 42 | + '72': 900, |
| 43 | + '7A': 1020 |
| 44 | +} |
| 45 | + |
| 46 | + |
24 | 47 | def duration_to_ramp_rate(seconds):
|
25 | 48 | if seconds == 0:
|
26 | 49 | return '02'
|
@@ -56,15 +79,41 @@ def duration_to_ramp_rate(seconds):
|
56 | 79 | return '7A'
|
57 | 80 | raise OutOfRangeException, 'That duration is too long'
|
58 | 81 |
|
| 82 | +def ramp_rate_to_duration(rate): |
| 83 | + assert len(rate) == 2, "Ramp rate must be two characters." |
| 84 | + rate = rate.upper() |
| 85 | + return RAMP_RATES[rate] |
| 86 | + |
| 87 | +def cbus_checksum(input): |
| 88 | + "Calculates the checksum of a C-Bus command string." |
| 89 | + if input[0] == '\\': |
| 90 | + input = input[1:] |
| 91 | + |
| 92 | + input = input.decode('base16') |
| 93 | + c = 0 |
| 94 | + for x in input: |
| 95 | + c += ord(x) |
| 96 | + |
| 97 | + return ((c % 256) ^ 256) + 1 |
59 | 98 |
|
60 | 99 | class CBusPCISerial(object):
|
61 | 100 | def __init__(self, device):
|
62 | 101 | self.s = Serial(device, 9600)
|
63 | 102 | self.reset()
|
64 | 103 |
|
65 | 104 | def reset(self):
|
66 |
| - # reset the PCI |
67 |
| - self.s.write('~') |
| 105 | + # reset the PCI, enable MMI reports so we know when buttons are pressed. |
| 106 | + # (mmi is actually disabled, 59g vs 79g |
| 107 | + self.write('~~~\r\nA3210038g\r\nA3420002g\r\nA3300059g\r\n') |
68 | 108 |
|
| 109 | + def write(self, msg): |
| 110 | + print "Message = %r" % msg |
| 111 | + self.s.write(msg) |
69 | 112 |
|
70 |
| - |
| 113 | + def lighting_group_on(self, group_id): |
| 114 | + # TODO: Implement checksumming |
| 115 | + self.write(POINT_TO_MULTIPOINT + APP_LIGHTING + ROUTING_NONE + LIGHT_ON + ('%02X' % group_id) + 'g' + END_COMMAND) |
| 116 | + |
| 117 | + def lighting_group_off(self, group_id): |
| 118 | + # TODO: Implement checksumming |
| 119 | + self.write(POINT_TO_MULTIPOINT + APP_LIGHTING + ROUTING_NONE + LIGHT_OFF + ('%02X' % group_id) + 'g' + END_COMMAND) |
0 commit comments