PlatSim_Genova/PlatformSimulator/bin/proxybusdriver.py
2026-01-30 16:38:33 +01:00

208 lines
6.8 KiB
Python

from __future__ import print_function
import proxybus
import time
import threading
import sys
import xml.etree.ElementTree as ET
import os
def normalize_tags(elem):
elem.tag = elem.tag.lower()
for attr, value in elem.attrib.items():
norm_attr = attr.lower()
if norm_attr != attr:
elem.set(norm_attr,value)
elem.attrib.pop(attr)
for child in elem:
normalize_tags(child)
def parse_and_get_normalized_root(xmlfile):
if os.path.exists(xmlfile):
tree = ET.parse(xmlfile)
root = tree.getroot()
normalize_tags(root)
else:
root = None
return root
debug = False
class ProxyBusDriver(object):
def __init__(self):
self.name= 'Abstract Bus Driver'
self.t= None
self.mutex = threading.Lock()
self.stopRequest= True
self.usclockperiod = pow(2,32) - 1
self.icdxmlfile = proxybus.__proxy_icdxmlfile__
self.version = proxybus.__proxy_version__
self.injectable_errors= ()
proxybus.setStartCallback(proxybus.__proxy_identifier__,self.start)
proxybus.setStopCallback(proxybus.__proxy_identifier__,self.stop)
proxybus.setSendCallback(proxybus.__proxy_identifier__,self.send)
proxybus.setUsClockPeriodCallback(proxybus.__proxy_identifier__,lambda : int(self.usclockperiod))
proxybus.setOnErrorInjectionListCallback(proxybus.__proxy_identifier__,lambda : (self.injectable_errors))
if sys.version_info.major < 3:
setattr(self,'timeclock',getattr(time,'clock'))
else:
setattr(self,'timeclock',getattr(time,'perf_counter'))
self.ticktime = self.getticktime()
self.overclock_factor = None
__del__ = lambda self: None
def start(self):
print (self.name, "start...",end='')
if not self.open_comm(): return False
print (self.name, "thread start...",end='')
self.clean()
if self.t is not None and self.t.is_alive():
self.raiseError('when running! thread id=%d'%self.t.ident,3)
else:
self.stopRequest= False
self.t= threading.Thread(name=self.name, target=self._backgroundLoop) #, args=(self,))
self.t.start()
print ('new thread id=', self.t.ident)
return self.t.is_alive()
def stop(self):
print (self.name, "stop...")
self.acquireLock()
self.stopRequest= True
self.releaseLock()
return True
def clean(self):
self.acquireLock()
if self.t is not None and self.t.is_alive():
print ('thread id=', self.t.ident, self.t.is_alive(),end='')
self.t.join(1.0)
if self.t.is_alive():
print ('busy')
self.raiseError("Unable to join python thread...",3)
else:
print ('Ok')
else:
print ('but no thread alive')
self.releaseLock()
def raiseError(self,msg,severiy):
proxybus.onBusError(proxybus.__proxy_identifier__,str(msg),int(severiy))
def forward_msg(self, m_id, m_data):
proxybus.onReceive(proxybus.__proxy_identifier__,m_id,m_data)
def set_log_auto(self, m_auto):
proxybus.onSetBusLogAuto(proxybus.__proxy_identifier__,m_auto)
def log_rx(self, m_id, data ):
proxybus.onBusLog(proxybus.__proxy_identifier__,m_id,False,data)
def log_tx(self, m_id, data ):
proxybus.onBusLog(proxybus.__proxy_identifier__,m_id,True,data)
def acquireLock(self):
ret =False
if self.mutex:
ret= self.mutex.acquire(False)
return ret
def releaseLock(self):
if self.mutex:
try:
self.mutex.release()
except threading.ThreadError:
print("already unlocked...")
def getticktime(self):
"""!
@brief return average time ( sec ) for os tick time
@param self : The object pointer
"""
total=0
for i in range(10):
start=time.time()
time.sleep(0.001)
total += time.time() - start
return total/10
def sleep(self,sec,inaccuracy=None):
"""!
@brief perform a more precise sleep based on inaccuracy due to os tick time or inaccuracy passed as argument
@param self : The object pointer
@param inaccuracy : the amount of time to reach by using open loop cpu time
"""
begin=self.timeclock()
end=begin + sec
s=sec - self.ticktime if inaccuracy is None else inaccuracy
time.sleep(s if(s>0) else 0)
while self.timeclock() < end:
continue
return self.timeclock()-begin
def setNotifyOverClock(self,factor):
"""!
@brief set the parameter to calculate the overclock time and notify the when the extra time
of the loop iteration is greater
@param self : The object pointer
@param factor : floating: with range [0:1] used to calculate the extra iteration time
None: reset to default (no check is performed)
"""
if factor is not None and ( factor > 0 and factor <= 1 ):
self.overclock_factor = factor
else:
self.overclock_factor = None
def setLogTimeTagStringClbk(self,callback):
proxybus.setLogTimeTagStringCallback(proxybus.__proxy_identifier__,callback)
def _backgroundLoop(self):
"""!
@brief it is the thread function that implement the open loop with period time based on usclockperiod
"""
sleep_time = (self.usclockperiod/1000000.0)
over = None if self.overclock_factor is None else sleep_time * self.overclock_factor
#print self.usclockperiod,sleep_time
while True:
begin=self.timeclock()
if self.acquireLock():
try:
self.iteration()
except:
self.raiseError(sys.exc_info(),3)
print (self.name, 'error, thread id=', self.t.ident, 'exiting',sys.exc_info())
break
finally:
self.releaseLock()
if self.stopRequest: break
end = self.timeclock()
if debug is True : print (end - begin)
dif = sleep_time - (end - begin)
if dif > 0 : self.sleep(dif)
else:
if over is not None and abs(dif) > over:
s="Bus Overclock {} {}".format(over * 100,abs(dif))
print(s)
self.raiseError(s,2)
proxybus.onClock(proxybus.__proxy_identifier__)
print ('closing connection....')
self.close_comm()
def send(self, m_id, m_data, m_err):
return False
def open_comm(self):
return False
def close_comm(self):
pass
def iteration(self):
pass