source: powerbar/npm4000.py@ 73

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

NPM4000 managment script taken from the old 'data' repository

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