source: powerbar/npm4000.py@ 127

Last change on this file since 127 was 75, checked in by Rick van der Zwet, 15 years ago

Status hack

  • Property svn:executable set to *
File size: 8.3 KB
RevLine 
[75]1#!/usr/bin/env python
[65]2# NPM 4000 powerbar managment script, to be used instead of the windows
3# application.
[75]4#
[65]5# XXX: Not all features are ported yet (like amp monitoring)
6# XXX: Some dirty poking around with hex representations and numeric representations of ports
[75]7# XXX: Make proper classes for use
8# XXX: Documentation
9#
[65]10# Licence: BSD
11# Version: $Id: npm4000.py 750 2009-09-27 14:34:55Z rick $
12# Rick van der Zwet <info@rickvanderzwet.nl>
[75]13
[65]14import socket, time
15import getopt, sys
16
17MAX_BUFFER = 100
18MAX_PORTS = 24
19
20# XOR all the 8bit values to get a checksum
21def checksum(s):
22 crc = 0
23 for p in range(0, len(s),2):
24 crc ^= int(s[p:p+2], 16)
25 return "%02X" % crc
26
27inet_addr = '192.168.0.178'
28inet_port = 4001
29
30passwd = 0x12345678
31addr_code = 0xFFFF
32
33verbose = False
34
35cmd2code = { 'login' : (0x5507, 1),
36 'portOn' : (0xB204, 2),
37 'portOff' : (0xC204, 2),
38 'allPortsOff' : (0xC103, 6),
39 'allPortsOn' : (0xB104, 15),
40 'status' : (0xD103, 2),
41 'knownError' : (0xFFFF, 1),
42 }
43
44# Socket used troughout the code
45s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46
47def getCode(type):
48 return(cmd2code[type][0])
49
50def getTimeout(type):
51 return(cmd2code[type][1])
52
53def dprint(msg):
54 if verbose:
55 print time.strftime('[%Y-%m-%d %H:%M:%S]'), msg
56
57def getPortNumber(name):
58 port_char = name[0]
59 port_number = int(name[1])
60 number = -1
61 if port_char == 'A':
62 number = port_number
63 elif port_char == 'B':
64 number = port_number + 8
65 elif port_char == 'C':
66 number = port_number + 16
67 else:
68 raise ValueError, "Port %s not defined" % name
69
70 return(number)
71
72def getPortName(number):
73 name = "U3"
74 if number <= 8:
75 name = "A%i" % number
76 elif number <= 16:
77 name = "B%i" % (number - 8)
78 elif number <= 24:
79 name = "C%i" % (number - 16)
80 else:
81 raise ValueError, "Port %i not defined" % number
82 return(name)
83
84def getPortHex(number):
85 return(int(getPortName(number),16))
86
87def generateCommand(type,arg=None):
88 if arg == None:
89 command = "%04X%04X" % (getCode(type), addr_code)
90 else:
91 command = "%04X%04X%02X" % (getCode(type), addr_code, arg)
92 command += checksum(command)
93 return (command)
94
95
96def sendCommand(type, arg=None):
97 cmd = generateCommand(type,arg)
98 timeout = getTimeout(type)
99 dprint('Send: ' + cmd + ' (%s)' % (type))
100 s.send(cmd)
101 s.settimeout(timeout)
102 try:
103 retval = s.recv(MAX_BUFFER)
104 dprint('Recv: ' + retval)
105 except socket.timeout:
106 retval = None
107 print 'Recv: ERR timeout (wrong command, bad connection)'
108 #XXX: XOR Checking for data correctness
109 return(retval)
110
111def doCommand(type, arg=None):
112 sendCommand('login', passwd)
113 retval = sendCommand(type, arg)
114 #XXX: Check if command returned succesfull D128FF
115 return(retval)
116
117
118def getPortState(port, raw_status):
119 """Port configuration is put into 24 bits, every port has one bit
120 representing the statewith a awkward order:
121 A8,A7,A6,A5,A4,A3,A2,A1,B8,..,B1,C8,..,C1"""
122 # Portion of retval we are interested in
123 ports_state = int(raw_status[8:14],16)
124 port_bit_location = -1
125 if port <= 8:
126 port_bit_location = (1 << 15 << port)
127 elif port <= 16:
128 port_bit_location = (1 << 7 << (port - 8))
129 elif port <= 24:
130 port_bit_location = (1 << (port - 16 - 1))
131
132 if port_bit_location & ports_state:
133 return True
134 else:
135 return False
136
[75]137def getPortStatus(i):
[65]138 raw_status = doCommand('status')
[75]139 print "Port %02i [%s]:" % (i, getPortName(i)),
140 if getPortState(i,raw_status):
141 print "1"
142 else:
143 print "0"
[65]144 return(retval)
145
[75]146def getStatusAll():
[65]147 raw_status= doCommand('status')
148 for i in range(1,25):
149 print "Port %02i [%s]:" % (i, getPortName(i)),
150 if getPortState(i,raw_status):
151 print "1"
152 else:
153 print "0"
154
155def togglePort(port):
[75]156 if getPortState(port):
[65]157 doCommand('portOff',port)
158 else:
159 doCommand('portOn', port)
160
161
162def runTest():
163 print "TEST: Start will all port Offline"
164 doCommand('allPortsOff')
165
166 print "TEST: All On and Off again, in mass execution"
167 doCommand('allPortsOn',0x01)
168 doCommand('allPortsOff')
169
170 print "TEST: Enable and disable ports one by one"
171 for i in range(1,25):
172 print getPortName(i)
173 doCommand('portOn', getPortHex(i))
174 doCommand('portOff', getPortHex(i))
175
176 print "TEST: Send known error"
177 doCommand('knownError')
178
179
180def usage():
181 print """
182Usage %s arguments
183Version: $Id: npm4000.py 750 2009-09-27 14:34:55Z rick $
184
185Arguments:
186 [-h|--help] Reading right know
187 [-v|--verbose] Print extra communication output
[74]188 --host= IP adress of FQDN hostname [%s]
189 --port= Port to connect to [%s]
190 --password= Password to use in hex notation [0x1234568]
[65]191 --addresscode= Internal device number in hex notation [0xFFFF]
192 [-s|--status] Current port configuration
193 [-t <port>|--toggle=<port>] Toggle port(s)
194 [-o <port>|--on=<port>] Turn on port(s)
195 [-f <port>|--off=<port>] Turn off port(s)
196
197Note: <port> has different notations:
198 Numeric value of port 1,2,3,4,5,..
199 Actual value of port A1,..,A8,B1,..,B8,C1,..,C8
200 All ports all
[74]201 """ % (sys.argv[0], inet_addr, inet_port)
[65]202
203def main():
204 global verbose, addr_code, inet_addr, inet_port, passwd, s
205 try:
206 opts, args = getopt.getopt(sys.argv[1:],
[75]207 "hf:s:t:o:v", ["help","verbose","host=", "port=", "password=", "addresscode=","toggle=","off=", "on=", "status="])
[65]208 except getopt.GetoptError, err:
209 # print help information and exit:
210 print str(err) # will print something like "option -a not recognized"
211 usage()
212 sys.exit(2)
213
214 opt_port = None
215 opt_action = None
216 for o, a in opts:
217 if o in ("-v", "--verbose"):
218 verbose = True
219 elif o in ("-h", "--help"):
220 usage()
221 sys.exit()
222 elif o in ("--addresscode"):
223 addr_code = int(a,16)
224 elif o in ("--host"):
225 inet_addr = a
226 elif o in ("--password"):
227 passwd = int(a,16)
228 elif o in ("--port"):
229 inet_port = a
230 elif o in ("-s", "--status"):
[75]231 opt_action = "status"
232 opt_port = a
[65]233 elif o in ("-t","--toggle"):
234 opt_action = "toggle"
235 opt_port = a
236 elif o in ("-f","--off"):
237 opt_action = "off"
238 opt_port = a
239 elif o in ("-o","--on"):
240 opt_action = "on"
241 opt_port = a
242 else:
243 assert False, "unhandled option"
244
[75]245 if (opt_port == None or opt_action == None):
[65]246 usage()
247 sys.exit(2)
248
249 dprint ('action: ' + opt_action + ' port: ' + opt_port)
250
[75]251 s.connect((inet_addr, inet_port))
252
253 # Status needs real integers, hack
254 if opt_action == "status":
255 if opt_port == "all":
256 getStatusAll()
257 else:
258 print "XXX: Implement"
259 sys.exit(0)
260
[65]261 # Resolve port to proper number
262 if opt_port == "all":
263 None # Blank resolution, as it is done elsewhere
264 elif opt_port[0] in ("A","B","C"):
265 opt_port = int(opt_port,16)
266 dprint('Hexcode of port: %i' % opt_port)
267 else:
268 # Dirty hack to have conversion and checking at the same time
269 opt_port = getPortHex(int(opt_port))
270 dprint('Hexcode of port: %i' % opt_port)
271
272 if opt_action == "toggle":
273 if opt_port == "all":
274 for i in range(1,25):
275 togglePort(getPortHex(i))
276 else:
277 togglePort(opt_port)
278 elif opt_action == "on":
279 if opt_port == "all":
280 doCommand("allPortsOn",0x01)
281 else:
282 doCommand("portOn", opt_port)
283 elif opt_action == "off":
284 if opt_port == "all":
285 doCommand("allPortsOff");
286 else:
287 doCommand("portOn", opt_port)
288
[75]289
[65]290if __name__ == "__main__":
291 main()
Note: See TracBrowser for help on using the repository browser.