11import time , json , os , logging , requests , base64
22from datetime import datetime
3- from random import randint , uniform
3+ from random import randint , uniform , choices
44
55from cumulocityAPI import C8Y_BASE , C8Y_TENANT , C8Y_USER , C8Y_PASSWORD , CumulocityAPI
66from oeeAPI import OeeAPI , ProfileCreateMode
@@ -34,6 +34,16 @@ def try_event(probability: float):
3434 '''
3535 return uniform (0.0 , 1.0 ) <= probability
3636
37+ def get_random_status (statusses , durations , probabilites ):
38+ '''returns a random status and duration of the given lists of status, durations and probabilites.
39+ '''
40+ if len (statusses ) != len (probabilites ) or len (durations ) != len (probabilites ):
41+ log .info (
42+ "Length of statusses, duration and probabilites does not match. Set status to up" )
43+ return "up" , 0
44+ choice = choices ([i for i in range (len (probabilites ))], probabilites )[0 ]
45+ return statusses [choice ], durations [choice ]
46+
3747cumulocityAPI = CumulocityAPI ()
3848oeeAPI = OeeAPI ()
3949
@@ -60,8 +70,10 @@ def __calculate_next_run(self) -> int:
6070 return time .time () + randint (self .min_interval_in_seconds , self .max_interval_in_seconds )
6171
6272 def __reschedule_and_run (self ):
63- self .next_run = self .__calculate_next_run ()
64- self .run_block (self )
73+ duration = self .run_block (self )
74+ duration = duration .pop () or 0 # Why is duration a set?
75+ self .next_run = self .__calculate_next_run () + duration
76+ log .debug (f"Reschedule next run and wait for additional { duration } seconds. Next run is at { time .strftime ('%Y-%m-%d %H:%M:%S' , time .localtime (self .next_run ))} " )
6577
6678 def tick (self ):
6779 if (time .time () - self .next_run ) > 0 :
@@ -133,14 +145,13 @@ def __on_availability_event(self, event_definition, task):
133145
134146 event = self .__type_fragment (event_definition )
135147
136- status_up_probability = event_definition .get ("statusUpProbability" ) or 0.5
137-
138- if try_event (status_up_probability ):
139- event .update ({'status' : 'up' })
140- self .machine_up = True
141- else :
142- event .update ({'status' : 'down' })
143- self .machine_up = False
148+ statusses = event_definition .get ("status" ) or ["up" ]
149+ probabilities = event_definition .get ("probabilities" ) or [0.5 ]
150+ durations = event_definition .get ("durations" ) or [0 ]
151+ status , duration = get_random_status (
152+ statusses , durations , probabilities )
153+ self .machine_up = (status == "up" )
154+ event .update ({'status' : status })
144155
145156 event .update (self .__get_production_info ())
146157 self .__send_event (event )
@@ -150,6 +161,8 @@ def __on_availability_event(self, event_definition, task):
150161 if self .__is_whole_piece_available ():
151162 self .__force_production_event ()
152163
164+ return duration
165+
153166 def __force_production_event (self ):
154167 for event_definition in self .model ["events" ]:
155168 event_type = event_definition .get ("type" )
@@ -358,6 +371,7 @@ def load(filename):
358371if CREATE_PROFILES .lower () == "true" :
359372 [oeeAPI .create_and_activate_profile (id , ProfileCreateMode .CREATE_IF_NOT_EXISTS )
360373 for id in oeeAPI .get_simulator_external_ids ()]
374+ os .system ("python profile_generator.py -cat" )
361375
362376while True :
363377 for simulator in simulators :
0 commit comments