mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-20 01:13:58 +00:00
175 lines
6.7 KiB
Python
175 lines
6.7 KiB
Python
|
|
|
|
|
|
# Connection Manager
|
|
|
|
# This module is informed by the several state machines in case of good connection.
|
|
# It calculates an overall ConnectionLevel.
|
|
# This ConnectionLevel is provided to the state machines, so that each state machine
|
|
# has the possiblity to decide whether it needs to do something or just stays silent.
|
|
#
|
|
# The basic rule is, that a good connection on higher layer (e.g. TCP) implicitely
|
|
# confirms the good connection on lower layer (e.g. Modem presence). This means,
|
|
# the lower-layer state machine can stay silent as long as the upper layers are working
|
|
# fine.
|
|
|
|
from configmodule import getConfigValue, getConfigValueBool
|
|
import sys # For exit_on_session_end hack
|
|
|
|
CONNLEVEL_100_APPL_RUNNING = 100
|
|
CONNLEVEL_80_TCP_RUNNING = 80
|
|
CONNLEVEL_50_SDP_DONE = 50
|
|
CONNLEVEL_20_TWO_MODEMS_FOUND = 20
|
|
CONNLEVEL_15_SLAC_ONGOING = 15
|
|
CONNLEVEL_10_ONE_MODEM_FOUND = 10
|
|
CONNLEVEL_5_ETH_LINK_PRESENT = 5
|
|
|
|
CONNMGR_CYCLES_PER_SECOND = 33 # 33 cycles for one second, is 30ms call cycle
|
|
CONNMGR_TIMER_MAX = (5*33) # 5 seconds until an OkReport is forgotten.
|
|
CONNMGR_TIMER_MAX_10s = (10*33) # 10 seconds until an OkReport is forgotten.
|
|
CONNMGR_TIMER_MAX_15s = (15*33) # 15 seconds until an OkReport is forgotten.
|
|
CONNMGR_TIMER_MAX_20s = (20*33) # 20 seconds until an OkReport is forgotten.
|
|
|
|
|
|
class connMgr():
|
|
def getConnectionLevel(self):
|
|
return self.ConnectionLevel
|
|
|
|
def printDebugInfos(self):
|
|
s = "[CONNMGR] " + str(self.timerEthLink) + " " \
|
|
+ str(self.timerModemLocal) + " " \
|
|
+ str(self.timerModemRemote) + " " \
|
|
+ str(self.timerSlac) + " " \
|
|
+ str(self.timerSDP) + " " \
|
|
+ str(self.timerTCP) + " " \
|
|
+ str(self.timerAppl) + " " \
|
|
+ " --> " + str(self.ConnectionLevel)
|
|
self.addToTrace(s)
|
|
|
|
|
|
def __init__(self, callbackAddToTrace, callbackShowStatus):
|
|
self.timerEthLink = 0
|
|
self.timerModemLocal = 0
|
|
self.timerModemRemote = 0
|
|
self.timerSlac = 0
|
|
self.timerSDP = 0
|
|
self.timerTCP = 0
|
|
self.timerAppl = 0
|
|
self.ConnectionLevel = 0
|
|
self.ConnectionLevelOld = 0
|
|
self.cycles = 0
|
|
self.addToTrace = callbackAddToTrace
|
|
|
|
def mainfunction(self):
|
|
# shortcut: we do not check the ethernet link, instead, we assume it is just always present.
|
|
self.timerEthLink = 10
|
|
# count all the timers down
|
|
if (self.timerEthLink>0):
|
|
self.timerEthLink-=1
|
|
if (self.timerModemLocal>0):
|
|
self.timerModemLocal-=1
|
|
if (self.timerModemRemote>0):
|
|
self.timerModemRemote-=1
|
|
if (self.timerSlac>0):
|
|
self.timerSlac-=1
|
|
if (self.timerSDP>0):
|
|
self.timerSDP-=1
|
|
if (self.timerTCP>0):
|
|
self.timerTCP-=1
|
|
if (self.timerAppl>0):
|
|
self.timerAppl-=1
|
|
# Based on the timers, calculate the connectionLevel.
|
|
if (self.timerAppl>0):
|
|
self.ConnectionLevel=CONNLEVEL_100_APPL_RUNNING
|
|
else:
|
|
if (self.timerTCP>0):
|
|
self.ConnectionLevel=CONNLEVEL_80_TCP_RUNNING
|
|
else:
|
|
if (self.timerSDP>0):
|
|
self.ConnectionLevel=CONNLEVEL_50_SDP_DONE
|
|
else:
|
|
if (self.timerModemRemote>0):
|
|
self.ConnectionLevel=CONNLEVEL_20_TWO_MODEMS_FOUND
|
|
else:
|
|
if (self.timerSlac>0):
|
|
self.ConnectionLevel=CONNLEVEL_15_SLAC_ONGOING
|
|
else:
|
|
if (self.timerModemLocal>0):
|
|
self.ConnectionLevel=CONNLEVEL_10_ONE_MODEM_FOUND
|
|
else:
|
|
if (self.timerEthLink>0):
|
|
self.ConnectionLevel=CONNLEVEL_5_ETH_LINK_PRESENT
|
|
else:
|
|
self.ConnectionLevel=0
|
|
if (self.ConnectionLevelOld!=self.ConnectionLevel):
|
|
self.addToTrace("[CONNMGR] ConnectionLevel changed from " + str(self.ConnectionLevelOld) + " to " + str(self.ConnectionLevel))
|
|
if ((self.ConnectionLevelOld==100) and (self.ConnectionLevel<100)):
|
|
# We had a charging session, and now it is gone.
|
|
# Depending on configuration option, we may end the script here.
|
|
if getConfigValueBool("exit_on_session_end"):
|
|
# TODO: This is a hack. Do this in fsmPev instead?
|
|
self.addToTrace("[CONNMGR] Terminating the application.")
|
|
sys.exit(0)
|
|
|
|
self.ConnectionLevelOld = self.ConnectionLevel
|
|
if ((self.cycles % 33)==0):
|
|
# once per second
|
|
self.printDebugInfos()
|
|
self.cycles+=1
|
|
|
|
def ModemFinderOk(self, numberOfFoundModems):
|
|
if (numberOfFoundModems>=1):
|
|
self.timerModemLocal = CONNMGR_TIMER_MAX
|
|
if (numberOfFoundModems>=2):
|
|
self.timerModemRemote = CONNMGR_TIMER_MAX_10s # 10s for the slac sequence, to avoid too fast timeout
|
|
|
|
def SlacOk(self):
|
|
# The SetKey was sent to the local modem. This leads to restart of the
|
|
# local modem, and potenially also for the remote modem. If both modems are up,
|
|
# they need additional time to pair. We need to be patient during this process. */
|
|
self.timerSlac = CONNMGR_TIMER_MAX_20s
|
|
|
|
def SdpOk(self):
|
|
self.timerSDP = CONNMGR_TIMER_MAX
|
|
|
|
def TcpOk(self):
|
|
self.timerTCP = CONNMGR_TIMER_MAX_10s
|
|
|
|
def ApplOk(self, time_in_seconds=10):
|
|
# The application confirmed to have communication. It can decide, based on its state,
|
|
# how long the confirmation shall hold. Default is ten seconds.
|
|
self.timerAppl = time_in_seconds * CONNMGR_CYCLES_PER_SECOND
|
|
|
|
|
|
def testCallbackAddToTrace(s):
|
|
print("callbackAddToTrace: " + s)
|
|
|
|
def testCallbackShowStatus(s):
|
|
print("callbackShowStatus: " + s)
|
|
|
|
if __name__ == "__main__":
|
|
print("Testing ConnectionManager...")
|
|
cm = connMgr(testCallbackAddToTrace, testCallbackShowStatus)
|
|
print("connection level " + str(cm.getConnectionLevel()))
|
|
cm.mainfunction()
|
|
print("connection level " + str(cm.getConnectionLevel()))
|
|
cm.SlacOk()
|
|
cm.mainfunction()
|
|
print("connection level " + str(cm.getConnectionLevel()))
|
|
for i in range(1000):
|
|
cm.mainfunction()
|
|
cm.ModemFinderOk(1)
|
|
for i in range(1000):
|
|
cm.mainfunction()
|
|
cm.ModemFinderOk(2)
|
|
for i in range(1000):
|
|
cm.mainfunction()
|
|
cm.SdpOk()
|
|
for i in range(1000):
|
|
cm.mainfunction()
|
|
cm.TcpOk()
|
|
for i in range(1000):
|
|
cm.mainfunction()
|
|
cm.ApplOk()
|
|
for i in range(1000):
|
|
cm.mainfunction()
|