@ -170,8 +170,8 @@ def UACKeyListCheck(inRequest, inRoleKeyList):
# Update user access
# Update user access
def UACUpdate ( inGSettings , inADLoginStr , inADStr = " " , inADIsDefaultBool = True , inURLList = [ ] , inCPAllowKeyList = [ ] , inRoleHierarchyAllowedDict = { } ) :
def UACUpdate ( inGSettings , inADLoginStr , inADStr = " " , inADIsDefaultBool = True , inURLList = [ ] , inCPAllowKeyList = [ ] , inRoleHierarchyAllowedDict = { } ) :
lUserTurple = ( inADStr . upper ( ) , inADLoginStr . upper ( ) ) # Create turple key for inGSettings["Server "]["AccessUsers"]["RuleDomainUserDict"]
lUserTurple = ( inADStr . upper ( ) , inADLoginStr . upper ( ) ) # Create turple key for inGSettings["Server Dict "]["AccessUsers"]["RuleDomainUserDict"]
if inURLList == [ ] and lUserTurple not in inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] : # Backward compatibility if user is not exist
if inURLList == [ ] and lUserTurple not in inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] : # Backward compatibility if user is not exist
inURLList = [
inURLList = [
{
{
" Method " : " GET " ,
" Method " : " GET " ,
@ -189,8 +189,8 @@ def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inU
}
}
]
]
# Check RoleHierarchyAllowedDict in gSettings for the old role hierarchy - include in result.
# Check RoleHierarchyAllowedDict in gSettings for the old role hierarchy - include in result.
if lUserTurple in inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] and " RoleHierarchyAllowedDict " in inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] [ lUserTurple ] :
if lUserTurple in inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] and " RoleHierarchyAllowedDict " in inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] [ lUserTurple ] :
lRoleHierarchyAllowedOLDDict = inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] [ lUserTurple ] [ " RoleHierarchyAllowedDict " ]
lRoleHierarchyAllowedOLDDict = inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] [ lUserTurple ] [ " RoleHierarchyAllowedDict " ]
Server . __ComplexDictMerge2to1__ ( in1Dict = inRoleHierarchyAllowedDict , in2Dict = lRoleHierarchyAllowedOLDDict ) # Merge dict 2 into dict 1
Server . __ComplexDictMerge2to1__ ( in1Dict = inRoleHierarchyAllowedDict , in2Dict = lRoleHierarchyAllowedOLDDict ) # Merge dict 2 into dict 1
# Create Access item
# Create Access item
@ -199,16 +199,16 @@ def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inU
" RoleHierarchyAllowedDict " : inRoleHierarchyAllowedDict
" RoleHierarchyAllowedDict " : inRoleHierarchyAllowedDict
}
}
# Case add domain + user
# Case add domain + user
inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] . update ( { ( inADStr . upper ( ) , inADLoginStr . upper ( ) ) : lRuleDomainUserDict } )
inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] . update ( { ( inADStr . upper ( ) , inADLoginStr . upper ( ) ) : lRuleDomainUserDict } )
if inADIsDefaultBool :
if inADIsDefaultBool :
# Case add default domain + user
# Case add default domain + user
inGSettings [ " Server " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] . update ( { ( " " , inADLoginStr . upper ( ) ) : lRuleDomainUserDict } )
inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " RuleDomainUserDict " ] . update ( { ( " " , inADLoginStr . upper ( ) ) : lRuleDomainUserDict } )
# Add supertoken for the all access (it is need for the robot communication without human)
# Add supertoken for the all access (it is need for the robot communication without human)
def UACSuperTokenUpdate ( inGSettings , inSuperTokenStr ) :
def UACSuperTokenUpdate ( inGSettings , inSuperTokenStr ) :
lLoginStr = " SUPERTOKEN "
lLoginStr = " SUPERTOKEN "
UACUpdate ( inGSettings = inGSettings , inADLoginStr = lLoginStr )
UACUpdate ( inGSettings = inGSettings , inADLoginStr = lLoginStr )
inGSettings [ " Server " ] [ " AccessUsers " ] [ " AuthTokensDict " ] . update (
inGSettings [ " Server Dict " ] [ " AccessUsers " ] [ " AuthTokensDict " ] . update (
{ inSuperTokenStr : { " User " : lLoginStr , " Domain " : " " , " TokenDatetime " : datetime . datetime . now ( ) , " FlagDoNotExpire " : True } }
{ inSuperTokenStr : { " User " : lLoginStr , " Domain " : " " , " TokenDatetime " : datetime . datetime . now ( ) , " FlagDoNotExpire " : True } }
)
)
@ -216,6 +216,63 @@ def UACSuperTokenUpdate(inGSettings, inSuperTokenStr):
# OrchestratorWeb defs
# OrchestratorWeb defs
# # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # #
# Connect URL to DEF
# "inMethodStr":"GET|POST",
# "inURLStr": "/index", #URL of the request
# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase",
# "inContentTypeStr": "", #HTTP Content-type
# "inDef": None #Function with str result
def WebURLConnectDef ( inGSettings , inMethodStr , inURLStr , inMatchTypeStr , inDef , inContentTypeStr = " application/octet-stream " ) :
lURLItemDict = {
" Method " : inMethodStr . upper ( ) ,
" URL " : inURLStr , # URL of the request
" MatchType " : inMatchTypeStr , # "BeginWith|Contains|Equal|EqualCase",
# "ResponseFilePath": "", #Absolute or relative path
#"ResponseFolderPath": "C:\Abs\Archive\scopeSrcUL\OpenRPA\Orchestrator\Settings",
# Absolute or relative path
" ResponseContentType " : inContentTypeStr , #HTTP Content-type
" ResponseDefRequestGlobal " : inDef #Function with str result
}
inGSettings [ " ServerDict " ] [ " URLList " ] . append ( lURLItemDict )
# Connect URL to Folder
# "inMethodStr":"GET|POST",
# "inURLStr": "/Folder/", #URL of the request
# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase",
# "inFolderPathStr": "", #Absolute or relative path
def WebURLConnectFolder ( inGSettings , inMethodStr , inURLStr , inMatchTypeStr , inFolderPathStr ) :
# Check if last symbol is "/" - append if not exist
lFolderPathStr = os . path . abspath ( inFolderPathStr )
if lFolderPathStr [ - 1 ] != " / " : lFolderPathStr + = " / "
# Prepare URLItem
lURLItemDict = {
" Method " : inMethodStr . upper ( ) ,
" URL " : inURLStr , # URL of the request
" MatchType " : inMatchTypeStr , # "BeginWith|Contains|Equal|EqualCase",
# "ResponseFilePath": "", #Absolute or relative path
" ResponseFolderPath " : lFolderPathStr , # Absolute or relative path
" ResponseContentType " : " application/octet-stream " , #HTTP Content-type
#"ResponseDefRequestGlobal": inDef #Function with str result
}
inGSettings [ " ServerDict " ] [ " URLList " ] . append ( lURLItemDict )
# Connect URL to File
# "inMethodStr":"GET|POST",
# "inURLStr": "/index", #URL of the request
# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase",
# "inFolderPathStr": "", #Absolute or relative path
def WebURLConnectFile ( inGSettings , inMethodStr , inURLStr , inMatchTypeStr , inFilePathStr , inContentTypeStr = " application/octet-stream " ) :
lURLItemDict = {
" Method " : inMethodStr . upper ( ) ,
" URL " : inURLStr , # URL of the request
" MatchType " : inMatchTypeStr , # "BeginWith|Contains|Equal|EqualCase",
" ResponseFilePath " : os . path . abspath ( inFilePathStr ) , #Absolute or relative path
#"ResponseFolderPath": os.path.abspath(inFilePathStr), # Absolute or relative path
" ResponseContentType " : inContentTypeStr , #HTTP Content-type
#"ResponseDefRequestGlobal": inDef #Function with str result
}
inGSettings [ " ServerDict " ] [ " URLList " ] . append ( lURLItemDict )
# Add control panel HTML, JSON generator or JS when page init
# Add control panel HTML, JSON generator or JS when page init
def WebCPUpdate ( inGSettings , inCPKeyStr , inHTMLRenderDef = None , inJSONGeneratorDef = None , inJSInitGeneratorDef = None ) :
def WebCPUpdate ( inGSettings , inCPKeyStr , inHTMLRenderDef = None , inJSONGeneratorDef = None , inJSInitGeneratorDef = None ) :
# Create Struct if the re is current key
# Create Struct if the re is current key
@ -409,45 +466,71 @@ def SchedulerActivityTimeAddWeekly(inGSettings, inTimeHHMMStr="23:55:", inWeekda
# RDPSession
# RDPSession
# # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # #
# Create new RDPSession in RobotRDPActive
# Create some RDP template dict to use it when connect/reconnect
def RDPSessionConnect ( inGSettings , inRDPSessionKeyStr , inHostStr , inPortStr , inLoginStr , inPasswordStr ) :
def RDPTemplateCreate ( inLoginStr , inPasswordStr , inHostStr = " 127.0.0.1 " , inPortInt = 3389 , inWidthPXInt = 1680 , inHeightPXInt = 1050 ,
inUseBothMonitorBool = False , inDepthBitInt = 32 , inSharedDriveList = [ " c " ] ) :
lRDPTemplateDict = { # Init the configuration item
" Host " : inHostStr , # Host address, example "77.77.22.22"
" Port " : str ( inPortInt ) , # RDP Port, example "3389"
" Login " : inLoginStr , # Login, example "test"
" Password " : inPasswordStr , # Password, example "test"
" Screen " : {
" Width " : inWidthPXInt , # Width of the remote desktop in pixels, example 1680
" Height " : inHeightPXInt , # Height of the remote desktop in pixels, example 1050
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example
" FlagUseAllMonitors " : inUseBothMonitorBool , # True or False, example False
" DepthBit " : str ( inDepthBitInt ) # "32" or "24" or "16" or "15", example "32"
} ,
" SharedDriveList " : inSharedDriveList , # List of the Root sesion hard drives, example ["c"]
###### Will updated in program ############
" SessionHex " : " 77777sdfsdf77777dsfdfsf77777777 " , # Hex is created when robot runs, example ""
" SessionIsWindowExistBool " : False ,
# Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False
" SessionIsWindowResponsibleBool " : False ,
# Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False
" SessionIsIgnoredBool " : False # Flag to ignore RDP window False - dont ignore, True - ignore, example False
}
return lRDPTemplateDict
# Search dublicates in GSettings RDPlist TODO!
# Return list if dublicates
def RDPSessionDublicatesResolve ( inGSettings ) :
pass
#for lItemKeyStr in inGSettings["RobotRDPActive"]["RDPList"]:
# lItemDict = inGSettings["RobotRDPActive"]["RDPList"][lItemKeyStr]
# Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if key is exists
# 2 way of the use
# Var 1: inGSettings, inRDPSessionKeyStr, inRDPTemplateDict
# Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr
def RDPSessionConnect ( inGSettings , inRDPSessionKeyStr , inRDPTemplateDict = None , inHostStr = None , inPortStr = None , inLoginStr = None , inPasswordStr = None ) :
# Check thread
# Check thread
if not Core . IsProcessorThread ( inGSettings = inGSettings ) :
if not Core . IsProcessorThread ( inGSettings = inGSettings ) :
if inGSettings [ " Logger " ] : inGSettings [ " Logger " ] . warning ( f " RDP def was called not from processor queue - activity will be append in the processor queue. " )
if inGSettings [ " Logger " ] : inGSettings [ " Logger " ] . warning ( f " RDP def was called not from processor queue - activity will be append in the processor queue. " )
lResult = {
lResult = {
" Def " : RDPSessionConnect , # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
" Def " : RDPSessionConnect , # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
" ArgList " : [ ] , # Args list
" ArgList " : [ ] , # Args list
" ArgDict " : { " inRDPSessionKeyStr " : inRDPSessionKeyStr , " inHostStr " : inHostStr , " inPortStr " : inPortStr ,
" ArgDict " : { " inRDPSessionKeyStr " : inRDPSessionKeyStr , " in RDPTemplateDict" : inRDPTemplateDict , " in HostStr" : inHostStr , " inPortStr " : inPortStr ,
" inLoginStr " : inLoginStr , " inPasswordStr " : inPasswordStr , } , # Args dictionary
" inLoginStr " : inLoginStr , " inPasswordStr " : inPasswordStr }, # Args dictionary
" ArgGSettings " : " inGSettings " , # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgGSettings " : " inGSettings " , # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgLogger " : None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgLogger " : None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
}
}
inGSettings [ " ProcessorDict " ] [ " ActivityList " ] . append ( lResult )
inGSettings [ " ProcessorDict " ] [ " ActivityList " ] . append ( lResult )
else : # In processor - do execution
else : # In processor - do execution
# ATTENTION - dont connect if RDP session is exist
# Var 1 - if RDPTemplateDict is input
lRDPConfigurationItem = inRDPTemplateDict
# Var 2 - backward compatibility
if lRDPConfigurationItem is None :
lRDPConfigurationItem = RDPTemplateCreate ( inLoginStr = inLoginStr , inPasswordStr = inPasswordStr ,
inHostStr = inHostStr , inPortInt = int ( inPortStr ) ) # ATTENTION - dont connect if RDP session is exist
# Start the connect
if inRDPSessionKeyStr not in inGSettings [ " RobotRDPActive " ] [ " RDPList " ] :
if inRDPSessionKeyStr not in inGSettings [ " RobotRDPActive " ] [ " RDPList " ] :
lRDPConfigurationItem = { # Init the configuration item
" Host " : inHostStr , # Host address, example "77.77.22.22"
" Port " : inPortStr , # RDP Port, example "3389"
" Login " : inLoginStr , # Login, example "test"
" Password " : inPasswordStr , # Password, example "test"
" Screen " : {
" Width " : 1680 , # Width of the remote desktop in pixels, example 1680
" Height " : 1050 , # Height of the remote desktop in pixels, example 1050
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example
" FlagUseAllMonitors " : False , # True or False, example False
" DepthBit " : " 32 " # "32" or "24" or "16" or "15", example "32"
} ,
" SharedDriveList " : [ " c " ] , # List of the Root sesion hard drives, example ["c"]
###### Will updated in program ############
" SessionHex " : " 77777sdfsdf77777dsfdfsf77777777 " , # Hex is created when robot runs, example ""
" SessionIsWindowExistBool " : False , # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False
" SessionIsWindowResponsibleBool " : False , # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False
" SessionIsIgnoredBool " : False # Flag to ignore RDP window False - dont ignore, True - ignore, example False
}
inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ] = lRDPConfigurationItem # Add item in RDPList
inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ] = lRDPConfigurationItem # Add item in RDPList
Connector . Session ( lRDPConfigurationItem ) # Create the RDP session
Connector . Session ( lRDPConfigurationItem ) # Create the RDP session
Connector . SystemRDPWarningClickOk ( ) # Click all warning messages
Connector . SystemRDPWarningClickOk ( ) # Click all warning messages
else :
if inGSettings [ " Logger " ] : inGSettings [ " Logger " ] . warning ( f " RDP session was not created because it is alredy exists in the RDPList. Use RDPSessionReconnect if you want to update RDP configuration. " )
return True
return True
# Disconnect the RDP session
# Disconnect the RDP session
@ -476,14 +559,14 @@ def RDPSessionDisconnect(inGSettings, inRDPSessionKeyStr, inBreakTriggerProcessW
return True
return True
# RDP Session reconnect
# RDP Session reconnect
def RDPSessionReconnect ( inGSettings , inRDPSessionKeyStr ):
def RDPSessionReconnect ( inGSettings , inRDPSessionKeyStr , inRDPTemplateDict = None ):
# Check thread
# Check thread
if not Core . IsProcessorThread ( inGSettings = inGSettings ) :
if not Core . IsProcessorThread ( inGSettings = inGSettings ) :
if inGSettings [ " Logger " ] : inGSettings [ " Logger " ] . warning ( f " RDP def was called not from processor queue - activity will be append in the processor queue. " )
if inGSettings [ " Logger " ] : inGSettings [ " Logger " ] . warning ( f " RDP def was called not from processor queue - activity will be append in the processor queue. " )
lResult = {
lResult = {
" Def " : RDPSessionReconnect , # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
" Def " : RDPSessionReconnect , # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
" ArgList " : [ ] , # Args list
" ArgList " : [ ] , # Args list
" ArgDict " : { " inRDPSessionKeyStr " : inRDPSessionKeyStr } , # Args dictionary
" ArgDict " : { " inRDPSessionKeyStr " : inRDPSessionKeyStr , " inRDPTemplateDict " : inRDPTemplateDict } , # Args dictionary
" ArgGSettings " : " inGSettings " , # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgGSettings " : " inGSettings " , # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgLogger " : None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
" ArgLogger " : None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
}
}
@ -491,6 +574,8 @@ def RDPSessionReconnect(inGSettings, inRDPSessionKeyStr):
else :
else :
lRDPConfigurationItem = inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ]
lRDPConfigurationItem = inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ]
RDPSessionDisconnect ( inRDPSessionKeyStr = inRDPSessionKeyStr ) # Disconnect the RDP
RDPSessionDisconnect ( inRDPSessionKeyStr = inRDPSessionKeyStr ) # Disconnect the RDP
# Replace Configuration item if inRDPTemplateDict exists
if inRDPTemplateDict is not None : lRDPConfigurationItem = inRDPTemplateDict
# Add item in RDPList
# Add item in RDPList
inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ] = lRDPConfigurationItem
inGSettings [ " RobotRDPActive " ] [ " RDPList " ] [ inRDPSessionKeyStr ] = lRDPConfigurationItem
# Create the RDP session
# Create the RDP session
@ -748,7 +833,7 @@ def Orchestrator(inGSettings):
lDaemonLoopSeconds = gSettingsDict [ " SchedulerDict " ] [ " CheckIntervalSecFloat " ]
lDaemonLoopSeconds = gSettingsDict [ " SchedulerDict " ] [ " CheckIntervalSecFloat " ]
lDaemonActivityLogDict = { } #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonActivityLogDict = { } #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonLastDateTime = datetime . datetime . now ( )
lDaemonLastDateTime = datetime . datetime . now ( )
gSettingsDict [ " Server " ] [ " WorkingDirectoryPathStr " ] = os . getcwd ( ) # Set working directory in g settings
gSettingsDict [ " Server Dict " ] [ " WorkingDirectoryPathStr " ] = os . getcwd ( ) # Set working directory in g settings
# Init SettingsUpdate defs from file list (after RDP restore)
# Init SettingsUpdate defs from file list (after RDP restore)
lSettingsUpdateFilePathList = gSettingsDict . get ( " OrchestratorStart " , { } ) . get ( " DefSettingsUpdatePathList " , [ ] )
lSettingsUpdateFilePathList = gSettingsDict . get ( " OrchestratorStart " , { } ) . get ( " DefSettingsUpdatePathList " , [ ] )
@ -858,25 +943,6 @@ def Orchestrator(inGSettings):
lThread = threading . Thread ( target = Processor . ActivityListExecute , kwargs = { " inGSettings " : inGSettings , " inActivityList " : lItem [ " ActivityList " ] } )
lThread = threading . Thread ( target = Processor . ActivityListExecute , kwargs = { " inGSettings " : inGSettings , " inActivityList " : lItem [ " ActivityList " ] } )
lThread . start ( )
lThread . start ( )
lIterationLastDateTime = datetime . datetime . now ( ) # Set the new datetime for the new processor activity
lIterationLastDateTime = datetime . datetime . now ( ) # Set the new datetime for the new processor activity
#######################################################################
#Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#######################################################################
if " TimeHH:MMStart " in lItem and " TimeHH:MMStop " in lItem and " ActivityIntervalSeconds " in lItem :
#Сформировать временной штамп, относительно которого надо будет проверять время
#часовой пояс пока не учитываем
lActivityDateTime = datetime . datetime . strptime ( lItem [ " TimeHH:MMStart " ] , " % H: % M " )
lActivityDateTime = lActivityDateTime . replace ( year = lCurrentDateTime . year , month = lCurrentDateTime . month , day = lCurrentDateTime . day )
lActivityTimeEndDateTime = datetime . datetime . strptime ( lItem [ " TimeHH:MMStop " ] , " % H: % M " )
lActivityTimeEndDateTime = lActivityTimeEndDateTime . replace ( year = lCurrentDateTime . year , month = lCurrentDateTime . month , day = lCurrentDateTime . day )
#Убедиться в том, что время наступило
if (
lCurrentDateTime < lActivityTimeEndDateTime and
lCurrentDateTime > = lActivityDateTime and
( lGUID , lActivityDateTime ) not in lDaemonActivityLogDict ) :
#Запись в массив отработанных активностей
lDaemonActivityLogDict [ ( lGUID , lActivityDateTime ) ] = { " ActivityStartDateTime " : lCurrentDateTime , " ActivityEndDateTime " : lActivityTimeEndDateTime }
#Запуск циклической процедуры
Timer . activityLoopStart ( lItem [ " ActivityIntervalSeconds " ] , lActivityTimeEndDateTime , lItem [ " Activity " ] )
except Exception as e :
except Exception as e :
if lL : lL . exception ( f " Scheduler: Exception has been catched in Scheduler module when activity time item was initialising. ActivityTimeItem is { lItem } " )
if lL : lL . exception ( f " Scheduler: Exception has been catched in Scheduler module when activity time item was initialising. ActivityTimeItem is { lItem } " )
lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity
lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity