server.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import time
  2. import os
  3. import pcipywrap
  4. import json
  5. import BaseHTTPServer
  6. import sys
  7. from optparse import OptionParser
  8. class PcilibServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  9. def __init__(s, pcilib, *args):
  10. s.pcilib = pcilib
  11. BaseHTTPServer.BaseHTTPRequestHandler.__init__(s, *args)
  12. def do_HEAD(s):
  13. s.send_response(200)
  14. s.send_header('content-type', 'application/json')
  15. s.end_headers()
  16. def do_GET(s):
  17. length = int(s.headers['Content-Length'])
  18. #deserialize input data
  19. data = json.loads(s.rfile.read(length).decode('utf-8'))
  20. if 'command' in data:
  21. command = data['command']
  22. if(command == 'help'):
  23. s.help(data)
  24. #elif(command == 'open'):
  25. # #check required arguments
  26. # if not 'device' in data:
  27. # s.error('message doesnt contains "device" field, '
  28. # 'which is required for "open" command', data)
  29. # return
  30. # #parse command arguments and convert them to string
  31. # device = str(data.get('device', None))
  32. # model = data.get('model', None)
  33. # if not model is None:
  34. # model = str(model)
  35. #
  36. # try:
  37. # s.openPcilibInstance(device, model)
  38. # except Exception as e:
  39. # s.error(str(e), data)
  40. # return
  41. #
  42. # #Success! Create and send reply
  43. # s.send_response(200)
  44. # s.send_header('content-type', 'application/json')
  45. # s.end_headers()
  46. # out = dict()
  47. # out['status'] = 'ok'
  48. # s.wrapMessageAndSend(out, data)
  49. elif(command == 'get_registers_list'):
  50. #parse command arguments and convert them to string
  51. bank = data.get('bank', None)
  52. if not bank is None:
  53. bank = str(bank)
  54. registers = dict()
  55. try:
  56. registers = s.pcilib.get_registers_list(bank)
  57. except Exception as e:
  58. s.error(str(e), data)
  59. return
  60. #Success! Create and send reply
  61. s.send_response(200)
  62. s.send_header('content-type', 'application/json')
  63. s.end_headers()
  64. out = dict()
  65. out['status'] = 'ok'
  66. out['registers'] = registers
  67. s.wrapMessageAndSend(out, data)
  68. elif(command == 'get_register_info'):
  69. #check required arguments
  70. if not 'reg' in data:
  71. s.error('message doesnt contains "reg" field, '
  72. 'which is required for "get_register_info" command', data)
  73. return
  74. #parse command arguments and convert them to string
  75. reg = str(data.get('reg', None))
  76. bank = data.get('bank', None)
  77. if not bank is None:
  78. bank = str(bank)
  79. register = dict()
  80. try:
  81. register = s.pcilib.get_register_info(reg, bank)
  82. except Exception as e:
  83. s.error(str(e), data)
  84. return
  85. #Success! Create and send reply
  86. s.send_response(200)
  87. s.send_header('content-type', 'application/json')
  88. s.end_headers()
  89. out = dict()
  90. out['status'] = 'ok'
  91. out['register'] = register
  92. s.wrapMessageAndSend(out, data)
  93. elif(command == 'get_property_list'):
  94. #parse command arguments and convert them to string
  95. branch = data.get('branch', None)
  96. if not branch is None:
  97. branch = str(branch)
  98. properties = dict()
  99. try:
  100. properties = s.pcilib.get_property_list(branch)
  101. except Exception as e:
  102. s.error(str(e), data)
  103. return
  104. #Success! Create and send reply
  105. s.send_response(200)
  106. s.send_header('content-type', 'application/json')
  107. s.end_headers()
  108. out = dict()
  109. out['status'] = 'ok'
  110. out['properties'] = properties
  111. s.wrapMessageAndSend(out, data)
  112. elif(command == 'read_register'):
  113. #check required arguments
  114. if not 'reg' in data:
  115. s.error('message doesnt contains "reg" field, '
  116. 'which is required for "read_register" command', data)
  117. return
  118. #parse command arguments and convert them to string
  119. reg = str(data.get('reg', None))
  120. bank = data.get('bank', None)
  121. if not bank is None:
  122. bank = str(bank)
  123. value = 0
  124. try:
  125. value = s.pcilib.read_register(reg, bank)
  126. except Exception as e:
  127. s.error(str(e), data)
  128. return
  129. #Success! Create and send reply
  130. s.send_response(200)
  131. s.send_header('content-type', 'application/json')
  132. s.end_headers()
  133. out = dict()
  134. out['status'] = 'ok'
  135. out['value'] = value
  136. s.wrapMessageAndSend(out, data)
  137. elif(command == 'write_register'):
  138. #check required arguments
  139. if not 'reg' in data:
  140. s.error('message doesnt contains "reg" field, '
  141. 'which is required for "write_register" command', data)
  142. return
  143. if not 'value' in data:
  144. s.error('message doesnt contains "value" field, '
  145. 'which is required for "write_register" command', data)
  146. return
  147. #parse command arguments and convert them to string
  148. reg = str(data.get('reg', None))
  149. value = str(data.get('value', None))
  150. bank = data.get('bank', None)
  151. if not bank is None:
  152. bank = str(bank)
  153. try:
  154. s.pcilib.write_register(value, reg, bank)
  155. except Exception as e:
  156. s.error(str(e), data)
  157. return
  158. #Success! Create and send reply
  159. s.send_response(200)
  160. s.send_header('content-type', 'application/json')
  161. s.end_headers()
  162. out = dict()
  163. out['status'] = 'ok'
  164. s.wrapMessageAndSend(out, data)
  165. elif(command == 'get_property'):
  166. #check required arguments
  167. if not 'prop' in data:
  168. s.error('message doesnt contains "prop" field, '
  169. 'which is required for "get_property" command', data)
  170. return
  171. #parse command arguments and convert them to string
  172. prop = str(data.get('prop', None))
  173. value = 0
  174. try:
  175. value = s.pcilib.get_property(prop)
  176. except Exception as e:
  177. s.error(str(e), data)
  178. return
  179. #Success! Create and send reply
  180. s.send_response(200)
  181. s.send_header('content-type', 'application/json')
  182. s.end_headers()
  183. out = dict()
  184. out['status'] = 'ok'
  185. out['value'] = value
  186. s.wrapMessageAndSend(out, data)
  187. elif(command == 'set_property'):
  188. #check required arguments
  189. if not 'prop' in data:
  190. s.error('message doesnt contains "prop" field, '
  191. 'which is required for "set_property" command', data)
  192. return
  193. if not 'value' in data:
  194. s.error('message doesnt contains "value" field, '
  195. 'which is required for "set_property" command', data)
  196. return
  197. #parse command arguments and convert them to string
  198. prop = str(data.get('prop', None))
  199. value = str(data.get('value', None))
  200. try:
  201. s.pcilib.set_property(value, prop)
  202. except Exception as e:
  203. s.error(str(e), data)
  204. return
  205. #Success! Create and send reply
  206. s.send_response(200)
  207. s.send_header('content-type', 'application/json')
  208. s.end_headers()
  209. out = dict()
  210. out['status'] = 'ok'
  211. s.wrapMessageAndSend(out, data)
  212. else:
  213. s.error('command "' + command + '" undefined', data)
  214. return
  215. else:
  216. s.error('message doesnt contains "command" field, which is required', data)
  217. return
  218. #print str(s.headers['content-type'])
  219. #print post_data['some']
  220. """open device context """
  221. def openPcilibInstance(s, device, model):
  222. s.pcilib = pcipywrap.create_pcilib_instance(device, model)
  223. """Send help message"""
  224. def help(s, received_message = None):
  225. s.send_response(200)
  226. s.send_header('content-type', 'application/json')
  227. s.end_headers()
  228. usage = str('Usage:\n'
  229. ' Server receive commands via http GET with json packet.\n'
  230. ' content-type should have value "application/json"\n'
  231. ' Server could handle only commands. to set command, you\n'
  232. ' should specify field "command" in packet with command name\n'
  233. ' List of commands:\n'
  234. '\n'
  235. ' command: help - Get help. This will return usage\n'
  236. '\n'
  237. ' command: open - Opens context of device. It will be reopened if already open.\n'
  238. ' required fields\n'
  239. ' device: - path to the device file [/dev/fpga0]\n'
  240. ' optional fields\n'
  241. ' model: - specifies the model of hardware, autodetected if doesnt exists\n'
  242. '\n'
  243. ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n'
  244. ' optional fields\n'
  245. ' bank: - if set, only register within the specified bank will be returned\n'
  246. '\n'
  247. ' command: get_register_info - Returns the information about the specified register.\n'
  248. ' required fields\n'
  249. ' reg: - the name of the register\n'
  250. ' optional fields\n'
  251. ' bank: - if set, only register within the specified bank will be returned\n'
  252. '\n'
  253. ' command: get_property_list - Returns the list of properties available under the specified path.\n'
  254. ' optional fields\n'
  255. ' branch: - Path. If not set, will return the top-level properties\n'
  256. '\n'
  257. ' command: read_register - Reads the specified register.\n'
  258. ' required fields\n'
  259. ' reg: - the name of the register\n'
  260. ' optional fields\n'
  261. ' bank: - if set, only register within the specified bank will be processed\n'
  262. '\n'
  263. ' command: write_register - Writes to specified register.\n'
  264. ' required fields\n'
  265. ' reg: - the name of the register\n'
  266. ' value: - the register value to write. Should be int, float or string (with number)\n'
  267. ' optional fields\n'
  268. ' bank: - if set, only register within the specified bank will be processed\n'
  269. '\n'
  270. ' command: get_property - Reads / computes the property value.\n'
  271. ' required fields\n'
  272. ' prop: - full name including path\n'
  273. '\n'
  274. ' command: set_property - Writes the property value or executes the code associated with property.\n'
  275. ' required fields\n'
  276. ' prop: - full name including path\n'
  277. ' value: - the property value to write. Should be int, float or string (with number)\n'
  278. '\n')
  279. out = {'status': 'ok', 'usage' : usage}
  280. s.wrapMessageAndSend(out, received_message)
  281. """Send error message with text description"""
  282. def error(s, info, received_message = None):
  283. s.send_response(400)
  284. s.send_header('content-type', 'application/json')
  285. s.end_headers()
  286. out = dict()
  287. out['status'] = 'error'
  288. out['description'] = info
  289. out['note'] = 'send {"command" : "help"} to get help'
  290. s.wrapMessageAndSend(out, received_message)
  291. def wrapMessageAndSend(s, message, received_message = None):
  292. if not received_message is None:
  293. message['received_message'] = received_message
  294. s.wfile.write(json.dumps(message))
  295. if __name__ == '__main__':
  296. #parce command line options
  297. parser = OptionParser()
  298. parser.add_option("-p", "--port", action="store",
  299. type="int", dest="port", default=9000,
  300. help="Set server port (9000)")
  301. parser.add_option("-d", "--device", action="store",
  302. type="string", dest="device", default=str('/dev/fpga0'),
  303. help="FPGA device (/dev/fpga0)")
  304. parser.add_option("-m", "--model", action="store",
  305. type="string", dest="model", default=None,
  306. help="Memory model (autodetected)")
  307. opts = parser.parse_args()[0]
  308. HOST_NAME = ''
  309. PORT_NUMBER = opts.port
  310. MODEL = opts.model
  311. DEVICE = opts.device
  312. #Set enviroment variables, if it not setted already
  313. if not 'APP_PATH' in os.environ:
  314. APP_PATH = ''
  315. file_dir = os.path.dirname(os.path.abspath(__file__))
  316. APP_PATH = str(os.path.abspath(file_dir + '/../..'))
  317. os.environ["APP_PATH"] = APP_PATH
  318. if not 'PCILIB_MODEL_DIR' in os.environ:
  319. os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml"
  320. if not 'LD_LIBRARY_PATH' in os.environ:
  321. os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib"
  322. #redirect logs to exeption
  323. pcipywrap.__redirect_logs_to_exeption()
  324. #start server
  325. pcilib_server = BaseHTTPServer.HTTPServer
  326. #pass Pcipywrap to to server handler
  327. lib = pcipywrap.Pcipywrap(DEVICE, MODEL)
  328. def handler(*args):
  329. PcilibServerHandler(lib, *args)
  330. httpd = pcilib_server((HOST_NAME, PORT_NUMBER), handler)
  331. print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
  332. try:
  333. httpd.serve_forever()
  334. except KeyboardInterrupt:
  335. pass
  336. httpd.server_close()
  337. print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)