Xcom_Test_Loop_Program.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ##########################################################################################################################################
  4. # Python-File Information #
  5. ##########################################################################################################################################
  6. #
  7. # File: Xcom_Test_Program.py
  8. # Author: Tobias Müller
  9. # Date: 2017.08.09
  10. #
  11. ##########################################################################################################################################
  12. # Requirements #
  13. ##########################################################################################################################################
  14. import sys
  15. import signal
  16. import socket
  17. import os
  18. import time
  19. import ptvsd as debug
  20. import serial as UART
  21. import pigpio as GPIO
  22. from Xcom_API import Xcom_API
  23. ##########################################################################################################################################
  24. # Class Definition & Description #
  25. ##########################################################################################################################################
  26. # This program demonstrate the functionality of the Xcom_API-class. It sends permanently a request for a known object_id and display the
  27. # answer from the Xtender-System. To use this program a Raspberry Pi with a Raspicomm extender module and a RS232-bridge called
  28. # Xcom-232i is required.
  29. ##########################################################################################################################################
  30. # Program Information #
  31. ##########################################################################################################################################
  32. PROG_NAME = 'Xcom_Test_Program'
  33. PROG_VERSION = 'v1.0'
  34. ##########################################################################################################################################
  35. # Debug server-Settings #
  36. ##########################################################################################################################################
  37. debug.enable_attach(secret='Debug')
  38. ##########################################################################################################################################
  39. # GPIO-Server-Setting #
  40. ##########################################################################################################################################
  41. # LED-Ports
  42. LED1 = 18
  43. LED2 = 27
  44. # Detect GPIO-HOST
  45. Hostname = socket.gethostname()
  46. # GPIO-State-Variable
  47. GPIO_ENABLE = False
  48. # GPIO-ERROR_Variable
  49. GPIO_ERR = False
  50. ##########################################################################################################################################
  51. # COM-Port-Setting #
  52. ##########################################################################################################################################
  53. # COM-Parameter-Variable
  54. COM_PARA = {'Port' : '/dev/ttyAMA0',
  55. 'Baudrate' : 115200,
  56. 'Bytesize' : UART.EIGHTBITS,
  57. 'Parity' : UART.PARITY_EVEN,
  58. 'Stopbits' : UART.STOPBITS_ONE,
  59. 'Timeout' : 2,
  60. 'XON_XOFF' : False,
  61. 'RTS_CTS' : False,
  62. 'DSR_DTR' : False}
  63. # COM-State-Variable
  64. COM_ENABLE = False
  65. # COM-ERROR-Variable
  66. COM_ERR = False
  67. COM_TIME_ERR = False
  68. ##########################################################################################################################################
  69. # Global Variable #
  70. ##########################################################################################################################################
  71. object_set = False
  72. port = ''
  73. baudrate = ''
  74. crc = False
  75. source = ''
  76. destination = ''
  77. ##########################################################################################################################################
  78. # Functions #
  79. ##########################################################################################################################################
  80. # exit Programm
  81. def exit():
  82. sys.exit(0)
  83. #print header
  84. def header():
  85. # Use Global-Variable
  86. global port
  87. global baudrate
  88. global object_set
  89. global PROG_NAME
  90. global PROG_VERSION
  91. global COM_ENABLE
  92. global GPIO_ENABLE
  93. global destination
  94. global crc
  95. global source
  96. # clear terminal
  97. os.system('cls' if os.name == 'nt' else 'clear')
  98. #print Header
  99. print('#' *120)
  100. print('#' *120)
  101. print('##',' ' *114,'##')
  102. print('## Welcome to {} version: {}. This program demonstrate the functionality of the {}-class. ##'.format(PROG_NAME, PROG_VERSION[1:],Xcom_API.get_prog_name()))
  103. print('## It sends permanently a request for a known object_id and display it.',' ' *42,'##')
  104. print('##',' ' *114,'##')
  105. print('## COM-Port: {}{}destination-addr.: {}{}Version Xcom_API: {} ##'.format(port,' '*(26-len(port)),destination,' '*(24-len(destination)),Xcom_API.get_prog_version()[1:]))
  106. print('## Baudrate: {}{}source-addr.: {}{}Object of Xcom_API set: {}{} ##'.format(baudrate,' '*(26-len(baudrate)),source,' '*(29-len(source)),object_set,' '*(object_set)))
  107. print('## COM enable: {}{}CRC-Check enable: {}{}GPIO enable: {}{} ##'.format(COM_ENABLE,' '*(19+COM_ENABLE),crc,' '*(20+crc),GPIO_ENABLE,' '*(GPIO_ENABLE)))
  108. print('##',' ' *114,'##')
  109. print('#' *120)
  110. print('#' *120,'\n')
  111. # setup
  112. def setup():
  113. # Use Global-Variable
  114. global COM_PARA
  115. global port
  116. global baudrate
  117. global destination
  118. global crc
  119. global source
  120. # get COM-Port
  121. if len(sys.argv) >= 2:
  122. port = sys.argv[1]
  123. COM_PARA['Port'] = port
  124. header()
  125. else:
  126. while True:
  127. Buffer = input('Do you want to use COM-Port: /dev/ttyAMA0? (yes/no): ')
  128. if Buffer == 'yes' or Buffer == 'y':
  129. port = COM_PARA['Port']
  130. header()
  131. break
  132. elif Buffer == 'no' or Buffer == 'n':
  133. port = input('Enter a COM-Port: ')
  134. COM_PARA['Port'] = port
  135. header()
  136. break
  137. else:
  138. print('What do you mean?\n')
  139. # get baudrate
  140. if len(sys.argv) >= 3 and (sys.argv[2] == '115200' or sys.argv[2] == '38400'):
  141. baudrate = sys.argv[2]
  142. COM_PARA['Baudrate'] = int(baudrate)
  143. header()
  144. else:
  145. while True:
  146. Buffer = input('Do you want to use a Baudrate of: 115200? (yes/no): ')
  147. if Buffer == 'yes' or Buffer == 'y':
  148. baudrate = str(COM_PARA['Baudrate'])
  149. header()
  150. break
  151. elif Buffer == 'no' or Buffer == 'n':
  152. while True:
  153. baudrate = input('Enter a Baudrate (115200 or 38400): ')
  154. if baudrate == '115200' or baudrate == '38400':
  155. COM_PARA['Baudrate'] = int(baudrate)
  156. header()
  157. break
  158. else:
  159. print('baudrate: {}, is not supported.'.format(baudrate))
  160. break
  161. else:
  162. print('What do you mean?\n')
  163. # get destination-address
  164. if len(sys.argv) >= 4:
  165. destination = sys.argv[3]
  166. header()
  167. else:
  168. while True:
  169. Buffer = input('Do you want to use the destination-address: 101? (yes/no): ')
  170. if Buffer == 'yes' or Buffer == 'y':
  171. destination = str(101)
  172. header()
  173. break
  174. elif Buffer == 'no' or Buffer == 'n':
  175. while True:
  176. destination = input('Enter a destination-address: ')
  177. try:
  178. if isinstance(int(destination),int):
  179. header()
  180. break
  181. except ValueError:
  182. print('destination-address: {}, is not an integer.'.format(destination))
  183. break
  184. else:
  185. print('What do you mean?\n')
  186. # get source-address
  187. if len(sys.argv) >= 5:
  188. source = sys.argv[4]
  189. header()
  190. else:
  191. while True:
  192. Buffer = input('Do you want to use the source-address: 1? (yes/no): ')
  193. if Buffer == 'yes' or Buffer == 'y':
  194. source = str(1)
  195. header()
  196. break
  197. elif Buffer == 'no' or Buffer == 'n':
  198. while True:
  199. source = input('Enter a source-address: ')
  200. try:
  201. if isinstance(int(source),int):
  202. header()
  203. break
  204. except ValueError:
  205. print('source-address: {}, is not an integer.'.format(source))
  206. break
  207. else:
  208. print('What do you mean?\n')
  209. # get crc check state
  210. if len(sys.argv) == 6 and (sys.argv[5] == 'False' or sys.argv[5] == 'True' or sys.argv[5] == '1' or sys.argv[5] == '0'):
  211. if sys.argv[5] == 'True' or sys.argv[5] == '1':
  212. crc = True
  213. else:
  214. crc = False
  215. header()
  216. else:
  217. while True:
  218. Buffer = input('Do you want to activate CRC-Check? (yes/no): ')
  219. if Buffer == 'yes' or Buffer == 'y':
  220. crc = True
  221. header()
  222. break
  223. elif Buffer == 'no' or Buffer == 'n':
  224. crc = False
  225. header()
  226. break
  227. else:
  228. print('What do you mean?\n')
  229. # open GPIOs
  230. def open_gpios(LED1,LED2,Hostname):
  231. # Use Global-Variable
  232. global GPIO_ERR
  233. global GPIO_ENABLE
  234. # Try Function
  235. try:
  236. # Enable GPIO-Server
  237. LED_Handle = GPIO.pi(Hostname)
  238. # GPIO-Mode
  239. LED_Handle.set_mode(LED1, GPIO.OUTPUT)
  240. LED_Handle.set_mode(LED2, GPIO.OUTPUT)
  241. # GPIO-Start-State
  242. LED_Handle.write(LED1, GPIO.LOW)
  243. LED_Handle.write(LED2, GPIO.LOW)
  244. GPIO_ENABLE = True
  245. # print completed task
  246. print('GPIOs on \"{}\" are configured.'.format(Hostname))
  247. # return LED-Handle
  248. return LED_Handle
  249. # Handle Errors
  250. except AttributeError:
  251. print('There is no connection to the \"{}\" possible.\nEnsure that the Deamon-Host-Process\"pigpiod\" has started with root privileges on the Raspberry Pi to connect to the GPIOs.'.format(Hostname))
  252. GPIO_ERR = True
  253. exit()
  254. # close GPIOs
  255. def close_gpios(LED_Handle,Hostname,LED1,LED2):
  256. # Use Global-Variable
  257. global GPIO_ERR
  258. global GPIO_ENABLE
  259. # Try Function
  260. try:
  261. # Reset GPIOs
  262. LED_Handle.clear_bank_1(1<<LED1)
  263. LED_Handle.clear_bank_1(1<<LED2)
  264. # close GPIO-Server
  265. LED_Handle.stop()
  266. GPIO_ENABLE = False
  267. # print completed task
  268. print('GPIOs closed.')
  269. except AttributeError:
  270. print('There is no connection to the \"{}\" possible.\n GPIOs can not be closed safely.'.format(Hostname))
  271. GPIO_ERR = True
  272. exit()
  273. # open COM-Port
  274. def open_com_port(LED_Handle,LED1,COM_PARA):
  275. # Use Global-Variable
  276. global COM_ENABLE
  277. global COM_ERR
  278. # Try Function
  279. try:
  280. # open COM-Port
  281. COM_Handle = UART.Serial(port = COM_PARA['Port'],
  282. baudrate = COM_PARA['Baudrate'],
  283. bytesize = COM_PARA['Bytesize'],
  284. parity = COM_PARA['Parity'],
  285. stopbits = COM_PARA['Stopbits'],
  286. timeout = COM_PARA['Timeout'],
  287. xonxoff = COM_PARA['XON_XOFF'],
  288. rtscts = COM_PARA['RTS_CTS'],
  289. dsrdtr = COM_PARA['DSR_DTR'])
  290. COM_ENABLE = True
  291. # LED1 on
  292. LED_Handle.write(LED1, GPIO.HIGH)
  293. # print completed task
  294. print('COM-Port: \"{}\", is opened.'.format(COM_Handle.port))
  295. # return COM_Handle
  296. return COM_Handle
  297. # Handle Errors
  298. except UART.SerialException:
  299. print('COM-Port: \"{}\", can not be opened. Make sure it is available and not used by other programs.'.format(COM_PARA['Port']))
  300. COM_ERR = True
  301. exit()
  302. except ValueError:
  303. print('COM-Port-Parameters are out of spezifications.')
  304. COM_ERR = True
  305. exit()
  306. except TypeError:
  307. print('Baudrate: {}, is not supported.'.format(COM_PARA['Baudrate']))
  308. COM_ERR = True
  309. exit()
  310. # close COM-Port
  311. def close_com_port(COM_Handle,LED_Handle,LED1):
  312. # Use Global-Variable
  313. global COM_ENABLE
  314. global COM_ERR
  315. # Try Function
  316. try:
  317. # save Port-Name
  318. port = COM_Handle.port
  319. # close COM-Port
  320. COM_Handle.close()
  321. COM_ENABLE = False
  322. # LED1 off
  323. LED_Handle.write(LED1, GPIO.LOW)
  324. # print completed task
  325. print('COM-Port: \"{}\", is closed.'.format(port))
  326. # Handle Errors
  327. except UART.SerialException:
  328. print('COM-Port: \"{}\", can not be closed.'.format(port))
  329. COM_ERR = True
  330. exit()
  331. # write to COM-Port
  332. def com_wite(LED_Handle,LED2,COM_Handle,BUFFER):
  333. # LED2 on
  334. LED_Handle.write(LED2, GPIO.HIGH)
  335. # sent Byte-Frame
  336. COM_Handle.write(BUFFER)
  337. # LED2 off
  338. LED_Handle.write(LED2, GPIO.LOW)
  339. # read from COM-Port
  340. def com_read(LED_Handle,LED2,COM_Handle):
  341. # LED2 on
  342. LED_Handle.write(LED2, GPIO.HIGH)
  343. # read Byteframe
  344. BUFFER = COM_Handle.read(30)
  345. # LED2 off
  346. LED_Handle.write(LED2, GPIO.LOW)
  347. # return Buffer
  348. return BUFFER
  349. # Create object of class Xcom_API
  350. def create_obj_of_class(destination,source,crc):
  351. # Use Global-Variable
  352. global object_set
  353. #Try Function
  354. try:
  355. # Create an object of class Xcom_API
  356. OBJ_Handle = Xcom_API(crc=crc,destination=int(destination),source=int(source))
  357. object_set = True
  358. return OBJ_Handle
  359. # Handle Errors
  360. except:
  361. print('Destination- and/or source-address are not supported.')
  362. exit()
  363. ##########################################################################################################################################
  364. # Main-Program #
  365. ##########################################################################################################################################
  366. # Try Main-Function
  367. try:
  368. # print Header
  369. header()
  370. # run setup if to check arguments an create an object of the class Xcom_API
  371. setup()
  372. # Configure GPIOs and COM-Port and object of class
  373. LED_Handle = open_gpios(LED1,LED2,Hostname)
  374. header()
  375. COM_Handle = open_com_port(LED_Handle,LED1,COM_PARA)
  376. header()
  377. OBJ_Handle = create_obj_of_class(destination,source,crc)
  378. header()
  379. #Ask for Object_ID create Frame for request
  380. while True:
  381. try:
  382. header()
  383. print('Known Parameter-Numbers (object_id):')
  384. print(' maximum current of ac source = 1107\n battery charge current = 1138\n smart boost allowed = 1126')
  385. print(' inverter allowed = 1124\n type of detection of grid loss = 1552\n charger allowed = 1125')
  386. print(' charger uses only power from ac = 1646\n ac output voltage = 1286\n inverter frequency = 1112')
  387. print(' transfer relay allowed = 1128\n limitation of the power boost = 1607\n remote entry active = 1545')
  388. print('\nKnown Information-Numbers (object_id):')
  389. print(' battery voltage = 3000\n battery charge current = 3005\n battery temperature = 3001')
  390. print(' battery voltage ripple = 3006\n state of charge = 3007\n number of battery elements = 3050')
  391. print(' input voltage = 3011\n input current = 3012\n input frequency = 3084')
  392. print(' input power = 3138\n output voltage = 3021\n output current = 3022')
  393. print(' output frequency = 3085\n output power = 3139\n operating state = 3028')
  394. print(' boost active = 3019\n state of inverter = 3049\n state of transfer relay = 3020')
  395. print(' state of output relay = 3030\n state of aux relay 1 = 3031\n state of aux relay 2 = 3032')
  396. print(' state of ground relay = 3074\n state of neutral transfer relay = 3075\n state of remote entry = 3086')
  397. Buffer = int(input('\nType in an object_id: '))
  398. Buffer = OBJ_Handle.get_read_frame(Buffer)
  399. header()
  400. break
  401. except:
  402. while True:
  403. Buffer = input('\nobject_id unknown, do you want to try it again (yes/no): ')
  404. if Buffer == 'yes' or Buffer == 'y':
  405. header()
  406. break
  407. elif Buffer == 'no' or Buffer =='n':
  408. header()
  409. exit()
  410. else:
  411. print('\nWhat do you mean?')
  412. # main while loop:
  413. while True:
  414. # send Byteframe
  415. com_wite(LED_Handle,LED2,COM_Handle,Buffer)
  416. # read from COM-Port
  417. Buffer2 = com_read(LED_Handle,LED2,COM_Handle)
  418. # get data from frame print value
  419. Buffer2 = OBJ_Handle.get_data_from_frame(Buffer2)
  420. if not Buffer2[0]:
  421. print('Answer from xtender:',Buffer2[1])
  422. else:
  423. print('Answer from xtender:',OBJ_Handle.get_text_from_error_id(Buffer2[1]))
  424. # Handle Errors
  425. except KeyboardInterrupt:
  426. if signal.SIGINT:
  427. print('\n\nProgram closed with Strg+c.')
  428. # Exit program safely.
  429. finally:
  430. print('\nExit Program.')
  431. if (('COM_Handle' in locals() and COM_Handle and COM_ENABLE and not COM_ERR) or
  432. ('LED_Handle' in locals() and LED_Handle and GPIO_ENABLE and not GPIO_ERR)):
  433. print('\nCleanup work:')
  434. if 'COM_Handle' in locals() and COM_Handle and COM_ENABLE and not COM_ERR:
  435. close_com_port(COM_Handle,LED_Handle,LED1)
  436. if 'LED_Handle' in locals() and LED_Handle and GPIO_ENABLE and not GPIO_ERR:
  437. close_gpios(LED_Handle,Hostname,LED1,LED2)