Coverage for pyilper/pilbox.py: 86%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/python3
2# -*- coding: utf-8 -*-
3# pyILPER 1.2.1 for Linux
4#
5# An emulator for virtual HP-IL devices for the PIL-Box
6# derived from ILPER 1.4.5 for Windows
7# Copyright (c) 2008-2013 Jean-Francois Garnier
8# C++ version (c) 2013 Christoph Gießelink
9# Python Version (c) 2015 Joachim Siebold
10#
11# This program is free software; you can redistribute it and/or
12# modify it under the terms of the GNU General Public License
13# as published by the Free Software Foundation; either version 2
14# of the License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24#
25# PIL-Box object class ---------------------------------------------
26#
27# Initial version derived from ILPER 1.43
28#
29# Changelog
30#
31# 09.02.2014 improvements and changes of ILPER 1.45
32# - send RFC to virtual devices after each cmd frame
33# - high byte detection
34#
35# 07.06.2014 jsi
36# - introduce configurable baudrate support
37# 06.10.2015 jsi:
38# - class statement syntax update
39# 16.10.2015 jsi:
40# - removed SSRQ, CSRQ approach
41# - introduced COFI switch to get real IDY frames from the loop (requires firmware 1.6)
42# 29.11.2015 jsi:
43# - removed activity timer
44# 30.11.2015 jsi:
45# - introduced idyframe option
46# 03.02.2015 jsi
47# - set frame timeout to 50 msec
48# 07.02.2015 jsi
49# - set pilbox call removed
50# 22.02.2016 cg
51# - send the cmd and not the RFC frame back to the PIL-Box
52# 22.03.2016 cg
53# - send acknowledge for high byte only at a 9600 baud connection
54# 26.04.2016 jsi
55# - auto baudrate support, code taken from cgi
56# 09.05.2016 jsi
57# - reenable baud rate setting in addition to auto baud support
58# 11.07.2016 jsi
59# - autobaud detection rewritten, hint by cg
60# - move constants to pilcore.py
61# 13.10.2016 jsi
62# - remove unregister function
63# - store tab name if device is registered
64# 30.10.2016 jsi
65# - getDevices added (removed by mistake)
66# 07.10.2017 jsi
67# - refactoring: moved process(), sendFrame() and device list handling code to
68# thread object
69#
70# PIL-Box Commands
71#
72COFF= 0x497 # initialize in controller off mode
73TDIS= 0x494 # disconnect
74COFI= 0x495 # switch PIL-Box to transmit real IDY frames
76from .pilrs232 import Rs232Error, cls_rs232
77from .pilcore import *
79class PilBoxError(Exception):
80 def __init__(self,msg,add_msg=None):
81 self.msg=msg
82 if add_msg is None:
83 self.add_msg=""
84 else:
85 self.add_msg= add_msg
88class cls_pilbox:
90 def __init__(self,ttydevice,baudrate,idyframe):
91 self.__baudrate__= baudrate # baudrate of connection or 0 for autodetect
92 self.__idyframe__= idyframe # switch box to send idy frames
93 self.__tty__= cls_rs232() # serial device object
94 self.__ttydevice__=ttydevice # serial port name
96#
97# get connection speed
98#
99 def getBaudRate(self):
100 return(self.__baudrate__)
101#
102# send command to PIL-Box, check return value
103#
104 def __sendCmd__(self,cmdfrm,tmout):
105 hbyt,lbyt= disassemble_frame(cmdfrm)
106 try:
107 self.write(lbyt,hbyt)
108 bytrx= self.__tty__.rcv(tmout)
109 except Rs232Error as e:
110 raise PilBoxError("PIL-Box command error:", e.value)
111 if bytrx is None:
112 raise PilBoxError("PIL-Box command error: timeout","")
113 try:
114 if ((ord(bytrx) & 0x3F) != (cmdfrm & 0x3F)):
115 raise PilBoxError("PIL-Box command error: illegal retval","")
116 except TypeError:
117 raise PilBoxError("PIL-Box command error: illegal retval","")
119#
120# Connect to PIL-Box in controller off mode
121#
122 def open(self):
123#
124# open serial device, no autobaud mode
125#
126 if self.__baudrate__ > 0:
127 try:
128 self.__tty__.open(self.__ttydevice__, self.__baudrate__)
129 except Rs232Error as e:
130 raise PilBoxError("Cannot connect to PIL-Box", e.value)
131 self.__sendCmd__(COFF,TMOUTCMD)
133 else:
134#
135# open serial device, detect baud rate, use predefined baudrates in
136# BAUDRATES list in reverse order
137#
138 success= False
139 errmsg=""
140 for i in range(len(BAUDRATES)-1,0,-1):
141#
142# open device at the beginning of the loop, if error throw exception and exit
143#
144 baudrate= BAUDRATES[i][1]
145 if i== len(BAUDRATES)-1:
146 try:
147 self.__tty__.open(self.__ttydevice__, baudrate)
148 except Rs232Error as e:
149 raise PilBoxError("Cannot connect to PIL-Box", e.value)
150#
151# otherwise reset device and use next baudrate
152#
153 else:
154 try:
155 self.__tty__.flushInput()
156 self.__tty__.setBaudrate(baudrate)
157 except Rs232Error as e:
158 raise PilBoxError("Cannot connect to PIL-Box", e.value)
159#
160# initialize PIL-Box with current baud rates
161#
162 try:
163 self.__sendCmd__(COFF,TMOUTCMD)
164 success= True
165 self.__baudrate__=baudrate
166 break
167 except PilBoxError as e:
168 errmsg=e.msg
169#
170# no success with any baud rate, throw exception and exit
171#
172 if not success:
173 self.__tty__.close()
174 raise PilBoxError("Cannot connect to PIL-Box", errmsg)
176 if self.__idyframe__:
177 self.__sendCmd__(COFI,TMOUTCMD)
179#
180# Disconnect PIL-Box
181#
182 def close(self):
183 try:
184 self.__sendCmd__(TDIS,TMOUTCMD)
185 finally:
186 self.__tty__.close()
187#
188# Read byte from PIL-Box
189#
190 def read(self):
191 try:
192 bytrx= self.__tty__.rcv(TMOUTFRM)
193 except Rs232Error as e:
194 raise PilBoxError("PIL-Box read frame error", e.value)
195 return bytrx
196#
197# Send one or two bytes to the PIL-Box
198#
199 def write(self,lbyt,hbyt=None):
200 if hbyt is None:
201 buf=bytearray([lbyt])
202 else:
203 buf=bytearray([hbyt,lbyt])
204 try:
205 self.__tty__.snd(buf)
206 except Rs232Error as e:
207 raise PilBoxError("PIL-Box send frame error", e.value)