# Script to automatically Schedule trains
#
# Author: Bill Fitch, copyright 2020
# Part of the JMRI distribution
# Description:
# We scan the operations:trains table and get a list of the trains that need to be scheduled
# in SchedulerMaster init we set up a listener which triggers every minute
# in the appropriate minute in the listener we append the train to the trains_to_be_scheduled
# in SchedulerMaster handle we process trains_to_be_scheduled by running run_trains(trains_to_be_scheduled)
# run_trains sets up a thread which moves the train, and removed the train from the trains_to_be_scheduled list
from javax.swing import JFrame, JPanel, JButton, BoxLayout, Box, JComponent, BorderFactory, JLabel, JTextField
from java.awt import GridLayout
from java.awt import Color, Font
from java.awt import Dimension, FlowLayout
from java.beans import PropertyChangeEvent
from java.awt.event import FocusAdapter, ActionListener
from javax.swing import SwingWorker, SwingUtilities
import os
import copy
import jmri
import java
import time
from org.python.core.util import StringUtil
from threading import Thread
from collections import Counter
# from javax.swing import JFrame
# from java.awt.event import WindowAdapter
from java.util.concurrent import CountDownLatch
CreateSchedulerPanel = jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/SchedulerPanel.py')
execfile(CreateSchedulerPanel)
CreateRoutesPanel = jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/RoutesPanel.py')
execfile(CreateRoutesPanel)
CreateEditRoutePanel = jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/EditRoutePanel.py')
execfile(CreateEditRoutePanel)
CreateEditRoutePanel = jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/Timetable.py')
execfile(CreateEditRoutePanel)
try:
basestring
except NameError:
basestring = str
if "list" in globals() and type(globals()["list"]).__name__ != "type":
# print(" Detected shadowed 'list' type: ", type(globals()["list"])) # list is being used in JMRI. This enables us to use list in Jython
del globals()["list"]
CreateEditRoutePanel = jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/DisplayMqttTimetable.py')
execfile(CreateEditRoutePanel)
trains_to_be_scheduled = []
run_train_dict = {}
scheduled = {}
RunTrain_instance = {}
tListener = None
class SchedulerMaster(jmri.jmrit.automat.AbstractAutomaton):
def __init__(self):
global scheduling_in_operation_gbl
self.logLevel = 0
self.frame = None
self.f = None
scheduling_in_operation_gbl = False
self.od = OptionDialog()
def exit(self): # called explicitly when scheduler thread is killed to stop multiple frames being visible
try:
self.frame.setVisible(False)
self.f.setVisible(False)
if "timetable_frame_gbl" in globals():
timetable_frame_gbl.setVisible(False)
except:
pass
def setup(self):
global schedule_trains_hourly
global schedule_trains_glb
global scheduling_in_operation_gbl
# schedule trains initially
# schedule_trains_glb = False
scheduling_in_operation_gbl = "False"
self.stop_schedule_trains_master() #don't really need this.
# print "scheduling_in_operation_gbl 6 start setup", scheduling_in_operation_gbl
# self.ToggleSchedulingtrains_action(None) # Toggle schedule_trains_glb
# print "scheduling_in_operation_gbl 6a", scheduling_in_operation_gbl
if 'schedule_trains_hourly' not in globals():
schedule_trains_hourly = False
#run before setting up Schedule Master
if self.logLevel > 0: print "starting SchedulerMaster setup"
self.scheduler_master_sensor = sensors.getSensor("startSchedulerSensor")
self.scheduler_view_scheduled_trains = sensors.getSensor("viewScheduledSensor")
self.scheduler_edit_routes = sensors.getSensor("editRoutesSensor")
self.scheduler_show_clock_sensor = sensors.getSensor("showClockSensor")
self.timetable_sensor = sensors.getSensor("timetableSensor")
self.departure_time_sensor = sensors.getSensor("departureTimeSensor")
self.help_sensor = sensors.getSensor("helpSensor")
if self.logLevel > 0: print "finished SchedulerMaster setup"
if self.logLevel > 0: print "returned from setup"
# print "scheduling_in_operation_gbl 7 end setup", scheduling_in_operation_gbl
return True
def init(self):
global run_local_timetable_gbl
# print "scheduling_in_operation_gbl 7 - init", scheduling_in_operation_gbl
if "run_timetable_gbl" not in globals():
run_local_timetable_gbl = False
self.train_scheduler_setup = False
# print "scheduling_in_operation_gbl 7 - init end", scheduling_in_operation_gbl
if self.logLevel > 0: print "returned from init"
showing_clock = False
showing_trains = False
def handle(self):
# print "start handle 0"
global schedule_trains_hourly
global schedule_trains_glb
global run_local_timetable_gbl
global station_name_list_gbl
global station_name_list_mqtt_gbl
global group_location_gbl
global timetable_triggered_gbl
if self.logLevel > 0: print "start handle"
# print "start handle"
# print "scheduling_in_operation_gbl 7 handle", scheduling_in_operation_gbl
self.button_sensors_to_watch = [self.scheduler_master_sensor, self.scheduler_view_scheduled_trains, \
self.scheduler_edit_routes, \
self.scheduler_show_clock_sensor, self.timetable_sensor, \
self.departure_time_sensor, self.help_sensor]
button_sensors_to_watch_JavaList = java.util.Arrays.asList(self.button_sensors_to_watch)
self.waitSensorState(button_sensors_to_watch_JavaList, ACTIVE)
# print "Z"
if self.departure_time_sensor.getKnownState() == ACTIVE:
self.set_departure_trains()
# print "ZZ"
self.departure_time_sensor.setKnownState(INACTIVE)
# print "Y"
if self.timetable_sensor.getKnownState() == ACTIVE:
title = ""
# if "station_name_list_gbl" not in globals():
# station_name_list_gbl = ""
# print "b"
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
my_scheduled_route_list = [train.getRoute() for train in train_list]
if None in my_scheduled_route_list:
OptionDialog().displayMessage("check scheduled routes are entered correctly\ncannot proceed with timetable")
else:
# print "my_scheduled_route_list", my_scheduled_route_list
# print "c"
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
# print "d"
station_list = []
for route in my_scheduled_route_list:
route_locations_list = route.getLocationsBySequenceList()
# print "route", route.getName(), "route_locations_list", route_locations_list
station_list1 = [str(route_location.getName()) for route_location in route_locations_list \
if ".py" not in route_location.getName()]
# print "e" , "station_list1", station_list1
for x in station_list1:
if x not in station_list:
station_list.append(x)
station_list.sort()
# print "station_list", station_list
repeat = True
while repeat:
# get station_group list
platform_list = []
station_group_list = []
station_group_list.append("All Stations")
station_group_location_list = []
PlatformPanel = MyTableModel7()
for location_name in station_list:
LocationManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
location = LocationManager.getLocationByName(location_name)
platform = PlatformPanel.get_location_platform(location)
station_group = PlatformPanel.get_location_station_group(location)
if station_group.strip() is not None and station_group.strip() is not "":
if station_group.strip() not in station_group_list:
station_group_list.append(station_group.strip())
# print "type station_group", type(station_group.strip())
station_group_location_list.append([station_group.strip(), location_name])
station_group_location_list.append(["All Stations", location_name])
if self.logLevel > 0: print "station list", station_list
msg = "timetables can be shown locally on this computer or\n" + \
"on remote computers/tablets communicating by mqtt\n\n" + \
"scheduler needs to be on and clock running"
opt0 = "Cancel"
if run_local_timetable_gbl == True:
opt1 = "hide local timetable"
else:
opt1 = "show local timetable"
opt4 = "set platforms and station groups"
opt2 = "select station for local timetable"
opt3 = "mqtt timetables"
if 'timetable_triggered_gbl' not in globals():
reply = OptionDialog().customQuestionMessage4str(msg, title, opt0, opt4, opt2, opt3)
else:
reply = OptionDialog().customQuestionMessage5str(msg, title, opt0, opt1, opt4, opt2, opt3)
# print "reply", reply
if self.logLevel > 0: print "timetable_sensor active"
if reply == OptionDialog().CLOSED_OPTION or reply == opt0:
repeat = False
elif reply == opt1:
if run_local_timetable_gbl == True:
run_local_timetable_gbl = False
else:
run_local_timetable_gbl = True
elif reply == opt4:
gui7 = CreateAndShowGUI7()
# Create a latch that waits for CreateAndShowGUI7 frame to be closed
# In CreateAndShowGUI7 the latch is decremented whe the frame is closed
global latch
latch = CountDownLatch(1)
# Wait until the frame is closed
latch.await()
reply = True
elif reply == opt2:
repeat1 = True
select_from_stations = True
while repeat1 == True:
if "station_name_list_gbl" not in globals():
station_name_list_gbl = ""
list_items_no_trains = self.get_scheduled_routes("no_train")
list_items_with_trains = self.get_scheduled_routes("with_train")
if select_from_stations:
title = "select station(s) for timetable - only stations on scheduled routes are shown"
options = ["Cancel", "Select from Station Groups", "Show Timetable"]
result = OptionDialog().MultipleListOptions(station_list, title, options, preferred_size = "default")
else:
title = "select station_group for timetable"
options = ["Cancel", "Select from Stations", "Show Timetable"]
result = OptionDialog().ListOptions(station_group_list, title, options, preferred_size = "default")
option = result[1]
if option == "Cancel" or self.od.CLOSED_OPTION == True:
run_local_timetable_gbl = False
self.timetable_sensor.setKnownState(INACTIVE)
repeat1 = False
elif option == "Show Timetable":
if select_from_stations:
station_name_list_gbl = result[0]
# get group_station_name
if len(station_name_list_gbl) == 1:
group_location_gbl = station_name_list_gbl[0] # the first and only station station1
else:
group_location_gbl = self.get_group_station_name(station_name_list_gbl)
else:
group_location_gbl = result[0]
# get station list
station_name_list = []
for l in station_group_location_list:
if l[0] == group_location_gbl:
station_name_list.append(l[1])
station_name_list_gbl = station_name_list
run_local_timetable_gbl = True
self.ensure_conditions_for_timetable_to_show_are_met()
repeat1 = True
else:
if select_from_stations == True:
select_from_stations = False
else:
select_from_stations = True
repeat1 = True
repeat = True
elif reply == opt3:
repeat = True
while repeat:
title = "MQTT timetables"
msg = "timetables can be shown on remote computers/tablets communicating by mqtt\n\n" + \
"scheduler needs to be on and clock running"
opt0 = "Cancel"
opt1 = "Generate mqtt timetable"
opt2 = "View/delete mqtt timetables"
opt3 = "Display mqtt timetables"
reply = OptionDialog().customQuestionMessage4str(msg, title, opt0, opt1, opt2, opt3)
if self.od.CLOSED_OPTION == True or reply == opt0:
repeat = False
elif reply == opt1:
select_from_stations = True
if "station_name_list_gbl" not in globals():
station_name_list_gbl = ""
list_items_no_trains = self.get_scheduled_routes("no_train")
list_items_with_trains = self.get_scheduled_routes("with_train")
if select_from_stations:
title = "select station(s) for timetable - only stations on scheduled routes are shown"
options = ["Cancel", "Select from Station Groups", "Generate Timetable"]
result = OptionDialog().MultipleListOptions(station_list, title, options, preferred_size = "default")
else:
title = "select station_group for timetable"
options = ["Cancel", "Select from Stations", "Generate Timetable"]
result = OptionDialog().ListOptions(station_group_list, title, options, preferred_size = "default")
option = result[1]
if option == "Cancel" or self.od.CLOSED_OPTION == True:
run_local_timetable_gbl = False
self.timetable_sensor.setKnownState(INACTIVE)
repeat = False
elif option == "Generate Timetable":
if select_from_stations:
station_name_list_mqtt_gbl = result[0]
# get group_station_name
if len(station_name_list_gbl) == 1:
group_location_mqtt_gbl = station_name_list_gbl[0] # the first and only station station1
else:
group_location_mqtt_gbl = self.get_group_station_name(station_name_list_mqtt_gbl)
print "group_location_mqtt_gbl", group_location_mqtt_gbl
else:
group_location_mqtt_gbl = result[0]
# print "group_location_mqtt_gbl", group_location_mqtt_gbl
# get station list
station_name_list = []
for l in station_group_location_list:
if l[0] == group_location_mqtt_gbl:
station_name_list.append(l[1])
station_name_list_mqtt_gbl = station_name_list
# print "station_name_list_mqtt_gbl", station_name_list_mqtt_gbl
# get emblem
title = "Display Train Operator Emblem?"
emblem_list = ["GB (British Rail)", "Germany (DB)", "No Emblem"]
options = ["Cancel", "Generate Timetable"]
result = self.od.ListOptions(emblem_list, title, options, preferred_size = "default")
# print "result", result
train_operator_emblem = result[0]
option1 = result[1]
if option1 == "Cancel" or self.od.CLOSED_OPTION == True:
# run_local_timetable_gbl = False
self.timetable_sensor.setKnownState(INACTIVE)
else:
self.generate_node_red_code(station_name_list_mqtt_gbl, group_location_mqtt_gbl, train_operator_emblem)
self.write_list2([train_operator_emblem])
repeat = True
else:
if select_from_stations == True:
select_from_stations = False
else:
select_from_stations = True
repeat = True
elif reply == opt2: # view/delete mqtt timetables
msg = "The generated timetables are saved in the following directory \n" +\
"Delete any that are not required"
OptionDialog().displayMessage(msg)
self.view_delete_mqtt_timetables()
repeat = True
elif reply == opt3: # display mqtt timetables
msg = "Will attempt to display all generated timetables in default browser \n" +\
"If Node Red is installed the timetables will be displayed \n" + \
"If MQTT is set up in jmri and mosquitto is running the timetables will work \n" +\
" when the scheduler is running"
OptionDialog().displayMessage(msg)
dmt = DisplayMqttTimetable()
repeat = True
repeat = True
self.timetable_sensor.setKnownState(INACTIVE)
if self.scheduler_master_sensor.getKnownState() == ACTIVE: # pause processing if we turn the sensor off
if self.logLevel > 0: print("checking valid operations trains")
if self.logLevel > 0: print "train_scheduler_setup",self.train_scheduler_setup
# # check whether can/want to schedule trains every hour
# schedule_trains_hourly = self.check_whether_schedule_trains_every_hour()
# print "scheduling_in_operation_gbl 8", scheduling_in_operation_gbl
self.set_default_scheduling_values()
# print "scheduling_in_operation_gbl 70", scheduling_in_operation_gbl
self.set_period_trains_will_run_frame()
# print "scheduling_in_operation_gbl 71", scheduling_in_operation_gbl
self.show_analog_clock() # show the analog clock
# set time to midnight
if self.logLevel > 0: print "set minute time listener"
global minute_time_listener_setup
if "minute_time_listener_setup" not in globals():
minute_time_listener_setup = False
if minute_time_listener_setup == False:
self.setup_minute_time_listener_to_schedule_trains() # only do this first time setup
self.train_scheduler_setup = True
self.scheduler_master_sensor.setKnownState(INACTIVE)
if self.scheduler_view_scheduled_trains.getKnownState() == ACTIVE:
self.show_operations_trains()
self.scheduler_view_scheduled_trains.setKnownState(INACTIVE)
if self.scheduler_edit_routes.getKnownState() == ACTIVE:
self.show_routes()
self.scheduler_edit_routes.setKnownState(INACTIVE)
if self.scheduler_show_clock_sensor.getKnownState() == ACTIVE:
self.show_analog_clock()
self.scheduler_show_clock_sensor.setKnownState(INACTIVE)
if self.help_sensor.getKnownState() == ACTIVE:
self.display_help()
self.help_sensor.setKnownState(INACTIVE)
self.waitMsec(500)
if self.logLevel > 0: print "end handle"
# print "scheduling_in_operation_gbl 7 handle end", scheduling_in_operation_gbl
# print "F"
return True
def mqtt_timetable_directory(self):
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "mqtt_timetables"
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def view_delete_mqtt_timetables(self):
dir = self.mqtt_timetable_directory()
j = JFileChooser(dir);
j.setAcceptAllFileFilterUsed(False)
filter = FileNameExtensionFilter("json files json", ["json"])
j.addChoosableFileFilter(filter);
j.setDialogTitle("Delete not wanted mqtt timetables");
ret = j.showDialog(None, "Delete");
if ret == JFileChooser.APPROVE_OPTION:
file = j.getSelectedFile()
if file == "" or file == None:
return
if file.exists():
os.remove(file.getAbsolutePath())
# print("File " + file.getName() + " has been deleted successfully.")
else:
print("The selected file does not exist.")
else:
print("File selection cancelled.")
return
def get_group_station_name(self, station_name_list_gbl):
# print "station_name_list_gbl", station_name_list_gbl
concatenated_names = " ".join(station_name_list_gbl) # [station1,station2]
print "concatenated_names", concatenated_names
station_groups = []
for station_name in station_name_list_gbl:
LocationManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
location = LocationManager.getLocationByName(station_name)
station_group = MyTableModel7().get_location_station_group(location)
print "station_name", station_name, "station_group", station_group.replace(" ", "*")
if station_group != "" and station_group != " ":
station_groups.append(station_group)
# print "appending station_groups", station_groups
counter = Counter(station_groups)
print "counter", counter
print "counter.most_common(1)", counter.most_common(1)
most_common_item = " "
if counter.most_common() != []:
most_common_item = counter.most_common(1)[0][0]
print "most_common_item", most_common_item
if most_common_item != " ":
group_location_gbl = most_common_item.strip() # need an option to rename this
else:
group_location_gbl = concatenated_names
print "group_location_gbl", group_location_gbl
return group_location_gbl
def ensure_conditions_for_timetable_to_show_are_met(self):
global scheduling_in_operation_gbl
global timebase
global start_hour_gbl, end_hour_gbl
if "timebase" not in globals():
timebase = jmri.InstanceManager.getDefault(jmri.Timebase)
if "start_hour_gbl" not in globals():
start_hour_gbl = None
if start_hour_gbl == None: # check if Start Scheduler has been run
sm = SchedulerMaster() # if not set up everything which would have been run
sm.set_default_scheduling_values()
# sm.set_period_trains_will_run_frame()
# sm.show_analog_clock() # show the analog clock
sm.setup_minute_time_listener_to_schedule_trains()
sm.train_scheduler_setup = True
if timebase.getRun() == False:
# get the current time without using timebase
date = jmri.implementation.DefaultClockControl().getTime()
calendar = java.util.Calendar.getInstance()
calendar.setTime(date)
minute = calendar.get(calendar.MINUTE)
# Manually create and trigger a PropertyChangeEvent
# have to call it twice to get the timetable to display
event = PropertyChangeEvent("TimeSource", "time",(minute - 2) % 60, (minute - 1) % 60)
TimeListener().propertyChange(event) # Directly call the listener's method
event = PropertyChangeEvent("TimeSource", "time", (minute - 1) % 60, minute)
TimeListener().propertyChange(event)
else:
# print "should be OK to show timetable"
pass
def generate_node_red_code(self, station_name_list, station_name, train_operator_emblem):
node_red_template_path = \
jmri.util.FileUtil.getExternalFilename('program:jython/DispatcherSystem/timetable_template/node_red_flow.json"')
# read the file into a string
#check if file is present
if os.path.isfile(node_red_template_path):
#open text file in read mode
text_file = open(node_red_template_path, "r")
#read whole file to a string
data = text_file.read()
#close file
text_file.close()
# create a unique reference for the websocketout node
import uuid
id = str(uuid.uuid1())
# change the file to work with station_name
# websocket names cannot have spaces in them
# so where we need to replace spaces we have My_Station$ instead of MyStation
new_data = (data.replace('My_Station$_ref', id) \
.replace('My_Station$', station_name.replace(" ","-")) \
.replace("My_Station_List", str(station_name_list)) \
.replace("My_Station", station_name) \
.replace("My_Emblem", train_operator_emblem))
# 'My_Station$' for url without spaces
# "My_Station" for title
# "My_Station_List" for list of stations to include
# store the modified file to a file in the user directory
new_node_red_template_directory = jmri.util.FileUtil.getExternalFilename('preference:dispatcher/mqtt_timetables/')
#create the folder if it does not exist
if not os.path.exists(new_node_red_template_directory):
os.makedirs(new_node_red_template_directory)
file_path = new_node_red_template_directory + java.io.File.separator + station_name + ".json"
f = open(file_path, "w")
f.write(new_data)
f.close()
else:
OptionDialog().displayMessage(file_path + "does not exist, reinstall latest JMRI")
msg = "node red file for '" + station_name + "' is in " + file_path + "\n" + \
"import the file into a node_red instance on computer on same network \n" + \
"and edit as illustrated in the help, and open indicated web page on tablet/laptop \n" + \
"e.g. http://localhost:1880/" + station_name.replace(" ", "-") + ", where localhost should be replaced by network address \n" + \
"of computer hosting node_red instance\n\n" + \
"Note any spaces in the station name have been replaced by hyphens in the web address\n\n" + \
"ALSO ensure an MQTT Connection is set up in preferences, as detailed in help."
OptionDialog().displayMessage(msg)
def set_departure_trains(self):
# allow running of scheduled routes to set journey times and wait times,
# which allow durations and departure times to be set up
# print "set departure trains"
global wait_time_gbl
global scheduled
global scheduling_margin_gbl
global set_departure_trains_gbl
global CreateAndShowGUI5_glb
set_departure_trains_gbl = True
self.set_default_scheduling_values()
msg = "Set Departure Times"
opt1 = "set wait time in stations"
opt2 = "run train on route to set journey times"
opt3 = "set departure times manually"
reply = OptionDialog().customQuestionMessage3str(msg, "", opt1, opt2, opt3)
if reply == opt1:
memory = memories.getMemory("IM:" + "DS_wait_time")
# print "memory", type(memory)
if memory is None or memory.getValue() == "":
memory = memories.provideMemory("IM:" + "DS_wait_time")
memory.setValue(3)
title = "wait time at station"
msg = "set wait time at all stations"
default_value = str(memory.getValue())
wait_time = OptionDialog().input(msg, title, default_value)
# memory = memories.getMemory("IM:" + "DS_wait_time")
if memory is not None:
memory.setValue(wait_time)
# print "wait_time", wait_time
return
elif reply == opt2:
list_items_no_trains = self.get_scheduled_routes("no_train")
# print "list_items_no_trains", list_items_no_trains
list_items_with_trains = self.get_scheduled_routes("with_train")
# print "list_items_with_trains", list_items_with_trains
list_items_starting_from_occupied_blocks = self.get_routes_starting_from_occupied_blocks()
# print "list_items_starting_from_occupied_blocks", list_items_starting_from_occupied_blocks
show_trains_in_occupied_blocks = True
repeat = True
while repeat:
if show_trains_in_occupied_blocks:
title = "Select Route to Record Journey Times: Showing routes from occupied blocks"
options = ["Cancel", "Run Route", "Show all scheduled routes"]
reply1 = OptionDialog().ListOptions(list_items_starting_from_occupied_blocks, title, options, preferred_size = "default")
else:
title = "Select Route to Record Journey Times: Showing scheduled routes"
options = ["Cancel", "Run Route", "Show routes starting from occupied blocks"]
reply1 = OptionDialog().ListOptions(list_items_no_trains, title, options, preferred_size = "default")
my_list = reply1[0]
route_name = str(my_list)
option = str(reply1[1])
if OptionDialog().CLOSED_OPTION == True or option == "Cancel":
# print "cancelling"
return
elif option == "Run Route":
# print "Run Route"
train_array = [trn for [rte, trn] in list_items_with_trains if str(rte) == route_name]
if len(train_array) == 0:
OptionDialog().displayMessage("Selected route is not on the scheduled list - try again")
return
else:
train = train_array[0]
set_departure_times = True
param_scheduled_start = "00:00"
journey_time_row_displayed = True
if "CreateAndShowGUI5_glb" in globals():
if CreateAndShowGUI5_glb != None:
CreateAndShowGUI5_glb.frame.dispose()
CreateAndShowGUI5_glb = CreateAndShowGUI5(None, route_name, param_scheduled_start, journey_time_row_displayed = journey_time_row_displayed)
title = "Run Train"
msg = "Last time to cancel"
opt1 = "Cancel"
opt2 = "Run Train"
reply = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
if reply == JOptionPane.CANCEL_OPTION or reply == opt1:
CreateAndShowGUI5_glb.frame.dispose()
return
OptionDialog().displayMessageNonModal("Run Train along route " + str(route_name) + " now","Check train is in required station
Then click to run route")
# print "Ended non modal, wait for non modal"
self.waitForNonModal()
# print "finished wait for non modal"
if self.logLevel > 0: print "running train %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", train.getDescription(), train.getName()
# running_train = RunTrain(train, g.g_stopping, set_departure_times)
route = train.getRoute()
routeName = route.getName()
station_from, station_to = self.get_first_and_last_station(route) # starting from beginning of route
if self.logLevel > 0: print "station_from", station_from, "station_to", station_to
start_block = blocks.getBlock(station_from)
if self.logLevel > 0: "start_block",start_block, "station_to", station_to
train_name = start_block.getValue()
no_repetitions = 0
delay_val = 0
# print "%%%%%%%%%%%%%%train_name%%%%%%%%%%%%%%", train_name
if train_name is None:
OptionDialog().displayMessage("No train is in the start position \n\n(maybe it has not been set up so the system recognises it)\npress setup train - register the train - and try again")
return
else:
# print "train_name is not none"
pass
if "stopping" in train.getDescription():
if self.logLevel > 0: print "A"
run_train = RunRoute(route, g.g_stopping, station_from, station_to, no_repetitions, train_name, \
set_departure_times = True)
run_train.setName("running_route_" + routeName)
instanceList.append(run_train)
run_train.start()
else:
if self.logLevel > 0: print "B"
run_train = RunRoute(route, g.g_express, station_from, station_to, no_repetitions, train_name, \
set_departure_times = True)
run_train.setName("running_route_" + routeName)
instanceList.append(run_train)
run_train.start()
repeat = False
else:
if show_trains_in_occupied_blocks == True:
show_trains_in_occupied_blocks = False
else:
show_trains_in_occupied_blocks = True
repeat = True
return
elif reply == opt3:
list_items_no_trains = self.get_scheduled_routes("no_train")
# print "list_items_no_trains", list_items_no_trains
list_items_with_trains = self.get_scheduled_routes("with_train")
# print "list_items_with_trains", list_items_with_trains
list_items_all_routes = self.get_all_routes()
# print "list_items_all_routes", list_items_all_routes
show_all_routes = True
repeat = True
while repeat:
if show_all_routes:
title = "Select Route to Record Journey Times: Showing all routes"
options = ["Cancel", "Set Departure Times", "Show scheduled routes"]
reply1 = OptionDialog().ListOptions(list_items_all_routes, title, options, preferred_size = "default")
else:
title = "Select Route to Record Journey Times: Showing scheduled routes"
options = ["Cancel", "Set Departure Times", "Show all routes"]
reply1 = OptionDialog().ListOptions(list_items_no_trains, title, options, preferred_size = "default")
my_list = reply1[0]
option = reply1[1]
route_name = str(my_list)
option = str(option)
if OptionDialog().CLOSED_OPTION == True or option == "Cancel":
# print "cancelling"
return
elif option == "Set Departure Times":
param_scheduled_start = "00:00"
journey_time_row_displayed = True
if "CreateAndShowGUI5_glb" not in globals():
CreateAndShowGUI5_glb = CreateAndShowGUI5(None, route_name, param_scheduled_start, journey_time_row_displayed = journey_time_row_displayed)
else:
CreateAndShowGUI5_glb.frame.dispose()
CreateAndShowGUI5_glb = CreateAndShowGUI5(None, route_name, param_scheduled_start, journey_time_row_displayed = journey_time_row_displayed)
repeat = False
else:
if show_all_routes == True:
show_all_routes = False
else:
show_all_routes = True
repeat = True
return
def get_first_and_last_station(self, route):
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
for routelocation in route.getLocationsBySequenceList() \
if ".py" not in routelocation.getName()]
if self.logLevel > 0: print "routelocationsSequenceNumber_list", routelocationsSequenceNumber_list
first_routelocation = [routelocation \
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
][0]
last_routelocation = [routelocation \
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
][-1]
if self.logLevel > 0: print "routelocation", routelocation
return [str(first_routelocation), str(last_routelocation)] # row number starts from 0
def waitForNonModal(self):
Jdialog_closed = sensors.getSensor("Jdialog_closed")
Jdialog_closed.setKnownState(INACTIVE)
btn = [Jdialog_closed]
btn_to_watch = java.util.Arrays.asList(btn)
# print "waiting for button" , Jdialog_closed.getKnownState()
self.waitSensorState(btn_to_watch, ACTIVE)
def get_scheduled_routes(self, option):
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
if option == "with_train":
my_list = [[train.getRoute().getName() if train is not None else "" , train] for train in train_list if train.getRoute() is not None]
else:
my_list = [train.getRoute().getName() if train is not None else "" for train in train_list if train.getRoute() is not None]
return sorted(my_list)
def get_routes_starting_from_occupied_blocks(self):
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
route_list = RouteManager.getRoutesByNameList()
my_list = [route.getName() for route in route_list if blocks.getBlock(route.getLocationsBySequenceList()[0].getName()).getSensor().getState() == ACTIVE ]
return sorted(my_list)
def get_all_routes(self):
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
route_list = RouteManager.getRoutesByNameList()
my_list = [route.getName() for route in route_list ]
return sorted(my_list)
def start_and_end_time_scheduling(self):
if self.logLevel > 0: print "start_and_end_time_scheduling"
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
start_time_hour = 23
end_time_hour = 0
for train in train_list:
train_hour = int(train.getDepartureTimeHour())
if train_hour < start_time_hour:
start_time_hour = train_hour
else:
pass
if train_hour > end_time_hour:
end_time_hour = train_hour
else:
pass
# print "[start_time_hour, end_time_hour]", [start_time_hour, end_time_hour]
if self.logLevel > 0: print "start_and_end_time_scheduling end"
return [start_time_hour, end_time_hour]
def set_period_trains_will_run_frame(self):
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl
if self.frame == None:
# print "frame is None"
self.frame = jmri.util.JmriJFrame('Schedule Trains');
panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
self.frame.add(panel)
row0 = JPanel()
row0.setLayout(BoxLayout(row0, BoxLayout.X_AXIS))
txt = JTextField(140)
txt.setMaximumSize( txt.getPreferredSize() );
txt.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.red),
txt.getBorder()));
label_panel_location = JLabel()
# btnpanelLocation = JButton("Set Panel Location", actionPerformed = btnpanelLocation_action)
btnpanelLocation = JButton("Set Panel Location")
row0.add(Box.createVerticalGlue())
row0.add(Box.createRigidArea(Dimension(20, 0)))
row0.add(btnpanelLocation)
row0.add(Box.createRigidArea(Dimension(20, 0)))
row0.add(label_panel_location)
row0.add(Box.createRigidArea(Dimension(20, 0)))
rowTitle_22 = JPanel()
rowTitle_22.setLayout(BoxLayout(rowTitle_22, BoxLayout.X_AXIS))
rowTitle_23 = JPanel()
rowTitle_23.setLayout(BoxLayout(rowTitle_23, BoxLayout.X_AXIS))
rowStage1Title_1 = JLabel("Sets Up System to run hourly trains ")
rowStage1Title_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
# get_start_filename()
# get_backup_filename()
# rowStage1Title_1 = JLabel(" Modifies: " + start_filename + " Creates backup: " + backup_filename)
# rowStage1Title_1.add(Box.createHorizontalGlue());
# rowStage1Title_1.setAlignmentX(rowStage1Title_1.LEFT_ALIGNMENT)
# rowStage1Title_2 = JLabel("Run Scheduled Trains")
# rowStage1Title_3 = JLabel(" Read Help to see how system works") #start_filename + "_icons"
rowTitle_22.add(Box.createVerticalGlue())
rowTitle_22.add(Box.createRigidArea(Dimension(20, 0)))
rowTitle_22.add(rowStage1Title_1)
# rowTitle_22.add(Box.createRigidArea(Dimension(20, 0)))
# rowTitle_22.add(rowStage1Title_2)
# rowTitle_22.add(Box.createVerticalGlue())
# rowTitle_22.add(Box.createRigidArea(Dimension(20, 0)))
# rowTitle_22.add(JLabel(""))
# rowTitle_23.add(rowStage1Title_3)
rowTitle_33 = JPanel()
rowTitle_33.setLayout(BoxLayout(rowTitle_33, BoxLayout.X_AXIS))
rowTitle_33.add(Box.createVerticalGlue())
rowTitle_33.add(Box.createRigidArea(Dimension(30, 0)))
rowTitle_33.add(rowStage1Title_1)
# buttons
rowStage1Button = JPanel()
rowStage1Button.setLayout(BoxLayout(rowStage1Button, BoxLayout.X_AXIS))
global rowrowStage4Button_4, rowAStage1Button_1, rowBStage1Button_1, rowCStage1Button_1, rowDStage1Button_1, rowEStage1Button_1, rowFStage1Button_1
rowAStage1Button = JPanel()
rowAStage1Button.setLayout(BoxLayout(rowAStage1Button, BoxLayout.X_AXIS))
rowBStage1Button = JPanel()
rowBStage1Button.setLayout(BoxLayout(rowBStage1Button, BoxLayout.X_AXIS))
rowCStage1Button = JPanel()
rowCStage1Button.setLayout(BoxLayout(rowCStage1Button, BoxLayout.X_AXIS))
rowDStage1Button = JPanel()
rowDStage1Button.setLayout(BoxLayout(rowDStage1Button, BoxLayout.X_AXIS))
rowEStage1Button = JPanel()
rowEStage1Button.setLayout(BoxLayout(rowEStage1Button, BoxLayout.X_AXIS))
rowFStage1Button = JPanel()
rowFStage1Button.setLayout(BoxLayout(rowFStage1Button, BoxLayout.X_AXIS))
rowrowStage1Button_1 = JLabel("Change parameters to run trains")
rowrowStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowrowStage1Button_1.add(Box.createHorizontalGlue());
rowrowStage1Button_1.setAlignmentX(rowrowStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "start hour: " + str(start_hour_gbl)
rowAStage1Button_1 = JLabel(stringToDisplay)
rowAStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowAStage1Button_1.add(Box.createHorizontalGlue());
rowAStage1Button_1.setAlignmentX(rowAStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "end hour: " + str(end_hour_gbl)
rowBStage1Button_1 = JLabel(stringToDisplay)
rowBStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowBStage1Button_1.add(Box.createHorizontalGlue());
rowBStage1Button_1.setAlignmentX(rowBStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "fast clock (when scheduling trains): x " + str(fast_clock_rate)
rowCStage1Button_1 = JLabel(stringToDisplay)
rowCStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowCStage1Button_1.add(Box.createHorizontalGlue());
rowCStage1Button_1.setAlignmentX(rowCStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "fast clock (outside running times): x " + str(speed_not_operational_gbl)
rowDStage1Button_1 = JLabel(stringToDisplay)
rowDStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowDStage1Button_1.add(Box.createHorizontalGlue());
rowDStage1Button_1.setAlignmentX(rowDStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "scheduling margin: " + str(scheduling_margin_gbl) + " fast mins"
rowEStage1Button_1 = JLabel(stringToDisplay)
rowEStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowEStage1Button_1.add(Box.createHorizontalGlue());
rowEStage1Button_1.setAlignmentX(rowEStage1Button_1.LEFT_ALIGNMENT)
stringToDisplay = "scheduling in operation: " + str(scheduling_in_operation_gbl)
rowFStage1Button_1 = JLabel(stringToDisplay)
rowFStage1Button_1.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowFStage1Button_1.add(Box.createHorizontalGlue());
rowFStage1Button_1.setAlignmentX(rowFStage1Button_1.LEFT_ALIGNMENT)
rowStage1Button_1 = JButton("Initialisation", actionPerformed = self.setup_schedule_parameters_panel)
stage1Button = rowStage1Button_1
rowStage2Button = JPanel()
rowStage2Button.setLayout(BoxLayout(rowStage2Button, BoxLayout.X_AXIS))
rowrowStage2Button_2 = JLabel("Set Clock to Session Start")
rowrowStage2Button_2.setFont(rowTitle_22.getFont().deriveFont(Font.BOLD, 13));
rowrowStage2Button_2.add(Box.createHorizontalGlue());
rowrowStage2Button_2.setAlignmentX(rowrowStage2Button_2.LEFT_ALIGNMENT)
rowStage2Button_2 = JButton("Set Time ", actionPerformed = self.SetTime_action)
stage2Button = rowStage2Button_2
rowStage3Button = JPanel()
rowStage3Button.setLayout(BoxLayout(rowStage3Button, BoxLayout.X_AXIS))
rowrowStage3Button_3 = JLabel("Stop/Start Scheduling Trains")
rowrowStage3Button_3.setFont(rowTitle_33.getFont().deriveFont(Font.BOLD, 13));
rowrowStage3Button_3.add(Box.createHorizontalGlue());
rowrowStage3Button_3.setAlignmentX(rowrowStage3Button_3.LEFT_ALIGNMENT)
rowStage3Button_3 = JButton("Schedule ", actionPerformed = self.ToggleSchedulingtrains_action)
stage3Button = rowStage3Button_3
rowStage4Button = JPanel()
rowStage4Button.setLayout(BoxLayout(rowStage4Button, BoxLayout.X_AXIS))
rowrowStage4Button_4 = JLabel("Stop/Start Clock")
rowrowStage4Button_4.setFont(rowTitle_33.getFont().deriveFont(Font.BOLD, 13));
rowrowStage4Button_4.add(Box.createHorizontalGlue());
rowrowStage4Button_4.setAlignmentX(rowrowStage4Button_4.LEFT_ALIGNMENT)
rowStage4Button_4 = JButton("Stop/Start", actionPerformed = self.StopStartClock_action)
stage4Button = rowStage4Button_4
rowStage5Button = JPanel()
rowStage5Button.setLayout(BoxLayout(rowStage5Button, BoxLayout.X_AXIS))
rowrowStage5Button_5 = JLabel("Initialise time, start scheduler, start time
Stop scheduler, stop time")
rowrowStage5Button_5.setFont(rowTitle_33.getFont().deriveFont(Font.BOLD, 13));
rowrowStage5Button_5.add(Box.createHorizontalGlue());
rowrowStage5Button_5.setAlignmentX(rowrowStage5Button_5.LEFT_ALIGNMENT)
rowStage5Button_5 = JButton("Initialise", actionPerformed = self.StopStartScheduler_action)
stage5Button = rowStage5Button_5
rowStage6Button = JPanel()
rowStage6Button.setLayout(BoxLayout(rowStage6Button, BoxLayout.X_AXIS))
rowrowStage6Button_6 = JLabel("Start scheduler, start time
Stop scheduler, stop time")
rowrowStage6Button_6.setFont(rowTitle_33.getFont().deriveFont(Font.BOLD, 13));
rowrowStage6Button_6.add(Box.createHorizontalGlue());
rowrowStage6Button_6.setAlignmentX(rowrowStage6Button_6.LEFT_ALIGNMENT)
rowStage6Button_6 = JButton(" Run ", actionPerformed = self.Running_StopStartScheduler_action)
stage6Button = rowStage6Button_6
rowStage1Button.add(Box.createVerticalGlue())
rowStage1Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage1Button.add(rowStage1Button_1)
rowStage1Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage1Button.add(rowrowStage1Button_1)
rowAStage1Button.add(Box.createVerticalGlue())
rowAStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowAStage1Button.add(rowAStage1Button_1)
rowBStage1Button.add(Box.createVerticalGlue())
rowBStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowBStage1Button.add(rowBStage1Button_1)
rowCStage1Button.add(Box.createVerticalGlue())
rowCStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowCStage1Button.add(rowCStage1Button_1)
rowDStage1Button.add(Box.createVerticalGlue())
rowDStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowDStage1Button.add(rowDStage1Button_1)
rowEStage1Button.add(Box.createVerticalGlue())
rowEStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowEStage1Button.add(rowEStage1Button_1)
rowFStage1Button.add(Box.createVerticalGlue())
rowFStage1Button.add(Box.createRigidArea(Dimension(120, 0)))
rowFStage1Button.add(rowFStage1Button_1)
rowStage2Button.add(Box.createVerticalGlue())
rowStage2Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage2Button.add(rowStage2Button_2)
rowStage2Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage2Button.add(rowrowStage2Button_2)
rowStage3Button.add(Box.createVerticalGlue())
rowStage3Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage3Button.add(rowStage3Button_3)
rowStage3Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage3Button.add(rowrowStage3Button_3)
rowStage4Button.add(Box.createVerticalGlue())
rowStage4Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage4Button.add(rowStage4Button_4)
rowStage4Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage4Button.add(rowrowStage4Button_4)
rowStage5Button.add(Box.createVerticalGlue())
rowStage5Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage5Button.add(rowStage5Button_5)
rowStage5Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage5Button.add(rowrowStage5Button_5)
rowStage6Button.add(Box.createVerticalGlue())
rowStage6Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage6Button.add(rowStage6Button_6)
rowStage6Button.add(Box.createRigidArea(Dimension(20, 0)))
rowStage6Button.add(rowrowStage6Button_6)
#Title
# panel.add(self.leftJustify(rowTitle_2))
panel.add(self.leftJustify(rowTitle_22))
panel.add(self._create_separator_row())
#stage1
panel.add(self.leftJustify(rowStage1Button))
panel.add(self.leftJustify(rowAStage1Button))
panel.add(self.leftJustify(rowBStage1Button))
panel.add(self.leftJustify(rowCStage1Button))
panel.add(self.leftJustify(rowDStage1Button))
panel.add(self.leftJustify(rowEStage1Button))
panel.add(self._create_separator_row())
#stage2
panel.add(self.leftJustify(rowStage2Button))
# panel.add(self.leftJustify(rowStage2Separator))
panel.add(self.leftJustify(rowStage3Button))
panel.add(self.leftJustify(rowFStage1Button))
panel.add(self.leftJustify(rowStage4Button))
panel.add(self._create_separator_row())
panel.add(self.leftJustify(rowStage5Button))
panel.add(self._create_separator_row())
panel.add(self.leftJustify(rowStage6Button))
panel.add(self._create_separator_row())
self.frame.pack()
self.frame.setVisible(True)
self.frame.setSize(450, 400)
self.frame.setLocation(10,10)
def _create_separator_row(self):
"""Creates and returns a new separator panel object."""
separatorPanel = JPanel()
separatorPanel.setLayout(BoxLayout(separatorPanel, BoxLayout.X_AXIS))
separatorLabel = JLabel("*******************************************************************")
separatorLabel.add(Box.createHorizontalGlue())
separatorLabel.setAlignmentX(separatorLabel.LEFT_ALIGNMENT)
separatorPanel.add(Box.createVerticalGlue())
separatorPanel.add(Box.createRigidArea(Dimension(20, 0)))
separatorPanel.add(separatorLabel)
separatorPanel.add(Box.createRigidArea(Dimension(20, 0)))
separatorPanel.add(JLabel("")) # Empty label for spacing
return self.leftJustify(separatorPanel)
def leftJustify(self, panel):
b = Box.createHorizontalBox()
b.add( panel )
b.add( Box.createHorizontalGlue() )
# (Note that you could throw a lot more components
# and struts and glue in here.)
return b
# self.close_this_panel(event)
#
# self.run_trains()
def close_this_panel(self, event):
if self.logLevel > 0: print "closing panel"
comp = event.getSource()
win = SwingUtilities.getWindowAncestor(comp);
win.dispose()
def SetTime_action(self, event):
global fast_clock_running_at_operational_speed
global timebase
# timebase needs to be running to set rate and time
timebase.setRun(True)
timebase.userSetRate(float(speed_not_operational_gbl))
# set clock to beginning of session
self.set_timebase_start_hour(int(start_hour_gbl)-1, 55)
# self.set_timebase_start_hour(0, 0)
# set timebase to stop
timebase.setRun(False)
if "rowrowStage4Button_4" in globals():
if timebase.getRun():
state = "Started"
else:
state = "Stopped"
stringToDisplay = "Stop/Start Clock: " + state
rowrowStage4Button_4.setText(stringToDisplay) # Update the label
def ToggleSchedulingtrains_action(self, event):
global schedule_trains_glb
global scheduling_in_operation_gbl
global rowFStage1Button_1
# schedule_trains_glb = False
if self.logLevel > 0: print "ToggleSchedulingtrains_action", "scheduling_in_operation_gbl", scheduling_in_operation_gbl
#stop Scheduler
if 'scheduling_in_operation_gbl' not in globals():
scheduling_in_operation_gbl = "True"
# print "scheduling_in_operation_gbl 8", scheduling_in_operation_gbl
if scheduling_in_operation_gbl == "False":
self.start_schedule_trains_master()
scheduling_in_operation_gbl = "True"
else:
self.stop_schedule_trains_master()
scheduling_in_operation_gbl = "False"
# print "scheduling_in_operation_gbl 0", scheduling_in_operation_gbl
stringToDisplay = "scheduling in operation: " + str(scheduling_in_operation_gbl)
if 'rowFStage1Button_1' in globals():
rowFStage1Button_1.setText(stringToDisplay) # Update the label
if self.logLevel > 0: print "ToggleSchedulingtrains_action end", "scheduling_in_operation_gbl", scheduling_in_operation_gbl
def StopStartClock_action(self, event):
self.swap_timebase_state_run_stop()
def StopStartScheduler_action(self, event):
if scheduling_in_operation_gbl == "False": # start scheduler
self.ToggleSchedulingtrains_action(event)
# if timebase.getRun() == True: # set time
self.SetTime_action(event) # sets time and sets timebase to stop
# if timebase.getRun() == False:
self.swap_timebase_state_run_stop() # start timebase
else:
# stop scheduler (was running)
self.ToggleSchedulingtrains_action(event)
# leave time at same time as before
# stop timebase
self.set_timebase_state_stop()
def Running_StopStartScheduler_action(self, event):
if scheduling_in_operation_gbl == "False": # start scheduler
self.ToggleSchedulingtrains_action(event)
if timebase.getRun() == False:
self.swap_timebase_state_run_stop() # start timebase
else:
# stop scheduler (was running)
self.ToggleSchedulingtrains_action(event)
# leave time at same time as before
# stop timebase
self.set_timebase_state_stop()
def swap_timebase_state_run_stop(self):
global timebase
global tListener
global fast_clock_rate
global rowrowStage4Button_4
if timebase.getRun() == True:
timebase.removeMinuteChangeListener(tListener)
timebase.setRun(False)
# print "fast_clock_rate", fast_clock_rate
else:
timebase.setRun(True)
if tListener is None:
tListener = TimeListener()
timebase.addMinuteChangeListener(tListener)
if "rowrowStage4Button_4" in globals():
if timebase.getRun():
state = "Started"
else:
state = "Stopped"
stringToDisplay = "Stop/Start Clock: " + state
rowrowStage4Button_4.setText(stringToDisplay) # Update the label
else:
# print '"rowrowStage4Button_4" not in globals()'
pass
def set_timebase_state_stop(self):
global timebase
global tListener
global fast_clock_rate
global rowrowStage4Button_4
timebase.removeMinuteChangeListener(tListener)
timebase.setRun(False)
if "rowrowStage4Button_4" in globals():
state = "Stopped"
stringToDisplay = "Stop/Start Clock: " + state
rowrowStage4Button_4.setText(stringToDisplay) # Update the label
else:
# print '"rowrowStage4Button_4" not in globals()'
pass
def start_schedule_trains_master(self):
global instanceList
global rowFStage1Button_1
# start scheduler
if self.logLevel > 0: print "setup values for running"
schedule_trains_master = ScheduleTrains()
schedule_trains_master.setName('Schedule Trains Master')
list_existing_schedule_trains = [iL.getName() for iL in instanceList if iL.getName() == 'Schedule Trains Master']
# print "list_existing_schedule_trains", list_existing_schedule_trains
if list_existing_schedule_trains == []:
# print "appending instance list"
instanceList.append(schedule_trains_master)
if schedule_trains_master.setup():
# print "setting name"
schedule_trains_master.setName('Schedule Trains Master')
schedule_trains_master.start()
scheduling_in_operation_gbl = "False"
# print "scheduling_in_operation_gbl 2", scheduling_in_operation_gbl
stringToDisplay = "scheduling in operation: " + str(scheduling_in_operation_gbl)
if 'rowFStage1Button_1' in globals():
rowFStage1Button_1.setText(stringToDisplay) # Update the label
if self.logLevel > 0: print "end setup values for running"
def stop_schedule_trains_master(self):
global instanceList
#stop all threads even if there are duplications
summary = jmri.jmrit.automat.AutomatSummary.instance()
automatsList = java.util.concurrent.CopyOnWriteArrayList()
schedule_trains_master = ScheduleTrains()
for automat in summary.getAutomats():
automatsList.add(automat)
# print "automatsList", automatsList
for automat in automatsList:
# print "automat", automat
if "ScheduleTrains" in str(automat): automat.stop()
# print automat, "stopped"
# print "automatsList2", automatsList
# print "end stop_all_threads"
instanceList = [iL for iL in instanceList if str(iL.getName()) != 'Schedule Trains Master']
def set_default_scheduling_values(self):
# self.show_analog_clock() # show the analog clock
# print "set_default_scheduling_hourly_values"
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl
# read parameters
scheduling_in_operation_gbl1 = False # change of logic do not set scheduling_in_operation_gbl here
[start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl1] = self.read_list()
if self.logLevel > 0: print "read list" , [start_hour_gbl, end_hour_gbl, speed_not_operational_gbl]
if start_hour_gbl == "":
start_hour_gbl = "04"
end_hour_gbl = "22"
fast_clock_rate = "10"
speed_not_operational_gbl = "100"
scheduling_margin_gbl = "3"
scheduling_in_operation_gbl = "False"
# print "1scheduling_in_operation_gbl", scheduling_in_operation_gbl
self.write_list([start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl])
# print "fast_clock_rate in set_default_scheduling_values", fast_clock_rate
def setup_schedule_parameters_panel(self, event):
"""Creates and displays a panel for setting the scheduler parameters."""
# read parameters
[self.start_hour, self.end_hour, fast_clock_rate, self.speed_not_operational, \
self.scheduling_margin, self.scheduling_in_operation] = self.read_list()
if self.logLevel > 0: print "read list" , [self.start_hour, self.end_hour, self.speed_not_operational]
if self.start_hour == "":
self.start_hour = "04"
self.end_hour = "22"
fast_clock_rate = "10"
self.speed_not_operational = "100"
self.scheduling_margin = "10"
self.scheduling_in_operation = "False"
# Create and set up the window.
self.params_frame = JFrame("Set Schedule Parameters") #NOI18N
self.params_frame.setPreferredSize(Dimension(550, 250))
# Create and set up the panel using a simple grid layout.
self.params_panel = JPanel(GridLayout(0, 2, 10, 5)) # hgap, vgap
self.params_panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)) # top, left, bottom, right
# Add the widgets to the panel.
self.add_schedule_parameter_widgets()
# Set the panel to be the content pane of the window.
self.params_frame.setContentPane(self.params_panel)
# Display the window.
self.params_frame.pack()
self.params_frame.setVisible(True)
class FieldValidator(FocusAdapter, ActionListener):
"""
A listener that validates a text field when focus is lost or Enter is pressed.
If validation fails, it reverts the field to its previous value.
"""
def __init__(self, validation_function, field):
self.validation_function = validation_function
self.field = field
self.old_value = None
def focusGained(self, event):
"""Store the current value when the field gains focus."""
self.old_value = self.field.getText()
def _validate_and_revert(self):
"""Helper method to run validation and revert on failure."""
if not self.validation_function(self.field):
# The validation function already shows the error message.
# Now, revert the text field to the last known good value.
self.field.setText(self.old_value)
def focusLost(self, event):
"""Validate when focus is lost."""
self._validate_and_revert()
def actionPerformed(self, event):
"""Validate when Enter is pressed."""
self._validate_and_revert()
def add_schedule_parameter_widgets(self):
"""Adds labels, fields, and buttons to the parameters panel."""
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl
# --- Create Widgets ---
start_hour_label = JLabel("Start Hour (0-23):") #NOI18N
self.start_hour_field = JTextField(4)
end_hour_label = JLabel("End Hour (0-23):") #NOI18N
self.end_hour_field = JTextField(4)
fast_clock_label = JLabel("Fast Clock Rate (Running Period):") #NOI18N
self.fast_clock_field = JTextField(4)
fast_clock_off_label = JLabel("Fast Clock Rate (Non Running Period) (1-100):") #NOI18N
self.fast_clock_off_field = JTextField(4)
margin_label = JLabel("Scheduling Margin (Fast Mins, 0-20):") #NOI18N
self.margin_field = JTextField(4)
save_button = JButton("Save") #NOI18N
cancel_button = JButton("Cancel") #NOI18N
# --- Pre-fill fields with existing values ---
# This assumes the values are stored as attributes of your class.
# If they are globals, you would reference them directly.
self.start_hour_field.setText(str(self.start_hour))
self.end_hour_field.setText(str(self.end_hour))
self.fast_clock_field.setText(str(fast_clock_rate))
self.fast_clock_off_field.setText(str(self.speed_not_operational))
self.margin_field.setText(str(self.scheduling_margin))
# --- Add Listeners for real-time validation (on focus loss or Enter key) ---
start_hour_validator = self.FieldValidator(self.validate_start_hour, self.start_hour_field)
self.start_hour_field.addFocusListener(start_hour_validator)
self.start_hour_field.addActionListener(start_hour_validator)
end_hour_validator = self.FieldValidator(self.validate_end_hour, self.end_hour_field)
self.end_hour_field.addFocusListener(end_hour_validator)
self.end_hour_field.addActionListener(end_hour_validator)
fast_clock_validator = self.FieldValidator(self.validate_fast_clock_rate, self.fast_clock_field)
self.fast_clock_field.addFocusListener(fast_clock_validator)
self.fast_clock_field.addActionListener(fast_clock_validator)
fast_clock_off_validator = self.FieldValidator(self.validate_fast_clock_off_rate, self.fast_clock_off_field)
self.fast_clock_off_field.addFocusListener(fast_clock_off_validator)
self.fast_clock_off_field.addActionListener(fast_clock_off_validator)
margin_validator = self.FieldValidator(self.validate_margin, self.margin_field)
self.margin_field.addFocusListener(margin_validator)
self.margin_field.addActionListener(margin_validator)
# --- Add Action Listeners ---
save_button.actionPerformed = self.save_schedule_parameters_action
cancel_button.actionPerformed = self.cancel_schedule_parameters_action
# --- Add Widgets to Panel in Order, wrapping fields to control size ---
self.params_panel.add(start_hour_label)
field_panel1 = JPanel(FlowLayout(FlowLayout.LEFT, 10, 0))
field_panel1.add(self.start_hour_field)
self.params_panel.add(field_panel1)
self.params_panel.add(end_hour_label)
field_panel2 = JPanel(FlowLayout(FlowLayout.LEFT, 10, 0))
field_panel2.add(self.end_hour_field)
self.params_panel.add(field_panel2)
self.params_panel.add(fast_clock_label)
field_panel3 = JPanel(FlowLayout(FlowLayout.LEFT, 10, 0))
field_panel3.add(self.fast_clock_field)
self.params_panel.add(field_panel3)
self.params_panel.add(fast_clock_off_label)
field_panel4 = JPanel(FlowLayout(FlowLayout.LEFT, 10, 0))
field_panel4.add(self.fast_clock_off_field)
self.params_panel.add(field_panel4)
self.params_panel.add(margin_label)
field_panel5 = JPanel(FlowLayout(FlowLayout.LEFT, 10, 0))
field_panel5.add(self.margin_field)
self.params_panel.add(field_panel5)
# --- Add Buttons ---
# Create a panel to hold both buttons, so they can be centered together.
button_panel = JPanel(FlowLayout(FlowLayout.CENTER, 10, 5)) # hgap=10, vgap=5
button_panel.add(save_button)
button_panel.add(cancel_button)
# Add an empty label to the first column of the last row to push the button panel to the right.
self.params_panel.add(JLabel(""))
self.params_panel.add(button_panel)
def save_schedule_parameters_action(self, event):
"""Saves the parameters back to the class and closes the window."""
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl
# --- Run all validations one last time before saving ---
if not self.validate_start_hour(self.start_hour_field): return
if not self.validate_end_hour(self.end_hour_field): return
if not self.validate_fast_clock_rate(self.fast_clock_field): return
if not self.validate_fast_clock_off_rate(self.fast_clock_off_field): return
if not self.validate_margin(self.margin_field): return
# All validation passed, now save the values.
self.start_hour = int(self.start_hour_field.getText())
self.end_hour = int(self.end_hour_field.getText())
fast_clock_rate = int(self.fast_clock_field.getText())
self.speed_not_operational = int(self.fast_clock_off_field.getText())
self.scheduling_margin = int(self.margin_field.getText())
items = [str(item) for item in [self.start_hour,self.end_hour, fast_clock_rate, \
self.speed_not_operational, \
self.scheduling_margin, scheduling_in_operation_gbl]]
if self.logLevel > 0: print "items to write", items
self.write_list(items)
# store in globals
start_hour_gbl = self.start_hour
end_hour_gbl = self.end_hour
speed_not_operational_gbl = self.speed_not_operational
scheduling_margin_gbl = self.scheduling_margin
# update the jlabel texts
stringToDisplay = "start hour: " + str(start_hour_gbl)
rowAStage1Button_1.setText(stringToDisplay) # Update the label
stringToDisplay = "end hour: " + str(end_hour_gbl)
rowBStage1Button_1.setText(stringToDisplay) # Update the label
stringToDisplay = "fast clock (when scheduling trains): x " + str(fast_clock_rate)
rowCStage1Button_1.setText(stringToDisplay) # Update the label
stringToDisplay = "fast clock (outside running times): x " + str(speed_not_operational_gbl)
rowDStage1Button_1.setText(stringToDisplay) # Update the label
stringToDisplay = "scheduling margin: " + str(scheduling_margin_gbl) + " fast mins"
rowEStage1Button_1.setText(stringToDisplay) # Update the label
print
"Scheduler parameters saved."
# Close the window after saving.
self.params_frame.dispose()
def cancel_schedule_parameters_action(self, event):
"""Closes the window without saving."""
self.params_frame.dispose()
# --- Validation Methods ---
def validate_start_hour(self, field):
"""Validates the Start Hour field."""
try:
value = int(field.getText())
if not (0 <= value <= 23):
OptionDialog().displayMessage("Start Hour must be between 0 and 23.")
return False
except ValueError:
OptionDialog().displayMessage("Start Hour must be a valid number.")
return False
return True
def validate_end_hour(self, field):
"""Validates the End Hour field."""
try:
value = int(field.getText())
if not (0 <= value <= 23):
OptionDialog().displayMessage("End Hour must be between 0 and 23.")
return False
except ValueError:
OptionDialog().displayMessage("End Hour must be a valid number.")
return False
return True
def validate_fast_clock_rate(self, field):
"""Validates the Fast Clock Rate (Running) field."""
try:
value = int(field.getText())
if value <= 0:
OptionDialog().displayMessage("Fast Clock Rate (Running) must be a positive number.")
return False
except ValueError:
OptionDialog().displayMessage("Fast Clock Rate (Running) must be a valid number.")
return False
return True
def validate_fast_clock_off_rate(self, field):
"""Validates the Fast Clock Rate (Outside Hours) field."""
try:
value = int(field.getText())
if not (1 <= value <= 100):
OptionDialog().displayMessage("Fast Clock Rate (Outside Hours) must be between 1 and 100.")
return False
except ValueError:
OptionDialog().displayMessage("Fast Clock Rate (Outside Hours) must be a valid number.")
return False
return True
def validate_margin(self, field):
"""Validates the Scheduling Margin field."""
try:
value = int(field.getText())
if not (0 <= value <= 20):
OptionDialog().displayMessage("Scheduling Margin must be between 0 and 20.")
return False
except ValueError:
OptionDialog().displayMessage("Scheduling Margin must be a valid number.")
return False
return True
def directory(self):
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "hourlySchedule"
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def write_list(self, a_list):
# store list in binary file so 'wb' mode
file = self.directory() + "hourlySchedule.txt"
if self.logLevel > 0: print "hourlySchedule" , a_list
if self.logLevel > 0: print "file" , file
with open(file, 'wb') as fp:
if self.logLevel > 0: print "a_list", a_list
i = 0
for items in a_list:
if self.logLevel > 0: print "items", items
fp.write('%s' %items)
if i < 5 : fp.write(",")
i+=1
# for item in items:
# if self.logLevel > 0: print "item", item
# fp.write('%s' %item)
# if i < 3 : fp.write(",")
# i+=1
# fp.write('\n')
# Read list to memory
def read_list(self):
# for reading also binary mode is important
file = self.directory() + "hourlySchedule.txt"
n_list = []
try:
with open(file, 'rb') as fp:
for line in fp:
# print "line", line
# x = line[:-1]
# print x
y = line.split(",")
if self.logLevel > 0: print "y" , y
n_list = y
return n_list
except:
return ["", "", "", "", "", ""]
def directory2(self):
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "train_operators_emblem"
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def write_list2(self, a_list):
# store list in binary file so 'wb' mode
file = self.directory2() + "train_operator_emblem.txt"
if self.logLevel > 0: print "train_operator_emblem" , a_list
if self.logLevel > 0: print "file" , file
with open(file, 'wb') as fp:
if self.logLevel > 0: print "a_list", a_list
i = 0
for items in a_list:
if self.logLevel > 0: print "items", items
fp.write('%s' %items)
if i < 5 : fp.write(",")
i+=1
# Read list to memory
def read_list2(self):
# for reading also binary mode is important
file = self.directory2() + "train_operator_emblem.txt"
n_list = []
try:
with open(file, 'rb') as fp:
for line in fp:
# print "line", line
# x = line[:-1]
# print x
y = line.split(",")
if self.logLevel > 0: print "y" , y
n_list = y
return n_list
except:
return ["", "", "", "", "", ""]
def is_time_format(self, input):
try:
time.strptime(input, '%H:%M')
return True
except IndexError:
if self.logLevel > 0: print "a"
except ValueError:
return False
def setup_minute_time_listener_to_schedule_trains(self):
global tListener
global timebase
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
scheduling_margin_gbl, scheduling_in_operation_gbl
global schedule_trains_hourly
global minute_time_listener_setup
if self.logLevel > 0: print "Setting up Time Scheduler"
timebase = jmri.InstanceManager.getDefault(jmri.Timebase)
# set up timebase and start at midnight
if self.logLevel > 0: print "******************************************set timebase hour"
self.set_default_scheduling_values()
self.set_timebase_start_hour(int(start_hour_gbl)-1, 45)
self.set_timebase_start_hour(12, 0)
#
# attach a listener to the timebase.
tListener = TimeListener()
# to set the rate, the timebase needs to be running
mystate = timebase.getRun()
if timebase.getRun() == False:
self.swap_timebase_state_run_stop()
timebase.userSetRate(float(fast_clock_rate))
desired_state = False
if False != timebase.getRun():
self.swap_timebase_state_run_stop()
minute_time_listener_setup = True
self.init = True
def set_timebase_start_hour(self, hour, minute):
from java.util import Date
global timebase
mystate = timebase.getRun()
if mystate == False:
self.swap_timebase_state_run_stop()
timebase = jmri.InstanceManager.getDefault(jmri.Timebase)
date = Date(2020,10,21) #any date really
date.setHours(hour)
date.setMinutes(minute)
timebase.userSetTime(date) ## set to 00:00 21/10/2020 (want the time to be 00:00)
if mystate != timebase.getRun():
self.swap_timebase_state_run_stop()
def train_scheduler(self):
#reset fast clock
self.reset_clock()
#go through operations:trains and get the train starting now
def reset_clock(self):
pass
f = None
def display_help(self):
ref = "html.scripthelp.DispatcherSystem.DispatcherSystem"
jmri.util.HelpUtil.displayHelpRef(ref)
def show_analog_clock(self):
if self.f == None:
self.f = jmri.jmrit.analogclock.AnalogClockFrame()
self.f.setSize(300, 200)
self.f.setLocationRelativeTo(None)
if self.frame != None:
self.f.setLocation(self.frame.getX() + self.frame.getWidth(), self.frame.getY());
self.f.setVisible(True)
def set_time_to_beginning_of_hourly_train_working(self):
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, scheduling_margin_gbl, scheduling_in_operation_gbl
# start_hour_gbl is the start of hourly working
start_hour = int(start_hour_gbl)
if self.logLevel > 0: print "start_hour", start_hour
self.set_timebase_start_hour(start_hour -1, 55)
def show_routes(self):
# a = jmri.jmrit.operations.routes.RoutesTableAction()
# a.actionPerformed(None)
CreateAndShowGUI6(self)
def show_operations_trains(self):
global CreateAndShowGUI4_frame
# delete any previous frames
if "CreateAndShowGUI4_frame" in globals():
CreateAndShowGUI4_frame.setVisible(False)
else:
# print "not in globals"
pass
# show dispatcher system form
CreateAndShowGUI4(self)
def get_train_list(self):
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
return train_list
from java.util.concurrent import TimeUnit
class TimeListener(java.beans.PropertyChangeListener):
# This is called every minute since it has been attached as timebase.addMinuteChangeListener(tListener)
def __init__(self):
# global timetable_gbl
self.logLevel = 0
if self.logLevel > 0: print "set up TimeListener"
self.prev_time = 0
if self.logLevel > 0: print "end TimeListener"
def propertyChange(self, event):
global fast_clock_running_at_operational_speed
if 'fast_clock_running_at_at_operational_speed' not in globals():
fast_clock_running_at_operational_speed = True
global minutes_old2, minutes_old3
global schedule_trains_hourly
global timetable_gbl, run_local_timetable_gbl
global fast_clock_rate
global send_mqtt_messages_gbl
if 'minutes_old3' not in globals():
minutes_old3 = 0
# print "a"
minutes_old = int(event.getOldValue())
# print "b"
minutes = int(event.getNewValue())
# print "c", minutes
if self.logLevel > 0: print "property change", "minutes", minutes,
if 'minutes_old2' not in globals():
minutes_old2 = minutes_old
if self.logLevel > 0: print "before: minutes_old3", minutes_old3
if self.logLevel > 0: print "minutes_old", minutes_old, "minutes", minutes, "minutes_old2", minutes_old2, \
"(minutes_old - minutes_old2)", (minutes_old - minutes_old2), \
"(minutes_old - minutes_old2) % 60 == 1", (minutes_old - minutes_old2) % 60 == -1
# if self.logLevel > 0: print "property change", event.newValue
if (minutes_old - minutes_old2) % 60 != 0:
# when we set the fast clock in the event timer it triggers a new event at the same time
# we then get into a recursion. This ignores the second call at the same time
if self.logLevel > 0: print "two events are triggered with the same minutes"
else:
if self.logLevel > 0: print "timeListener: normal Operation"
if self.logLevel > 0: print "minutes_old", minutes_old, "minutes", minutes, "minutes_old2", minutes_old2, \
"(minutes - minutes_old2) % 60 ", (minutes - minutes_old2) % 60
# print "y", minutes, type(minutes), int(minutes)
if int(minutes) % 10 == 0: # only check every 10 minutes to prevent problens at non_operational_speeds
# don't just check at 0 minutes in case train us started not on the hour
if self.logLevel > 0: print "minutes", int(minutes), "int(minutes) % 10", int(minutes) % 10, "minutes", minutes
# print "e"
minutes_old2 = minutes
# print "set fast clock rate"
self.set_fast_clock_rate() # sets global fast_clock_at_operational_speed
self.process_operations_trains(event) # scheduled trains
send_mqtt_messages_gbl = True
if 'send_mqtt_messages_gbl' not in globals():
send_mqtt_messages_gbl = False
if 'run_local_timetable_gbl' not in globals():
run_local_timetable_gbl = False
# print "send_mqtt_messages_gbl", send_mqtt_messages_gbl
if run_local_timetable_gbl or send_mqtt_messages_gbl:
# do not display more frequently than 5 secs
# print "f1", fast_clock_rate
fcr = int(str(fast_clock_rate))
x = (5.0 / 60.0)
# print "x", x, "fcr", fcr, "x*fcr", x * fcr
no_fast_minutes = int(x * fcr)
if no_fast_minutes == 0: no_fast_minutes = 1
if minutes % no_fast_minutes == 0:
Trigger_Timetable(minutes)
else:
# print "HIDING TIMETABLE WINDOW"
# print "run_timetable_gbl", run_timetable_gbl, "send_mqtt_messages_gbl", send_mqtt_messages_gbl
if 'timetable_gbl' in globals():
# timetable_gbl = None
if timetable_gbl != None:
timetable_gbl.hideWindow()
minutes_old2 = minutes # use minutes_old2 to prevent recursion
minutes_old3 = minutes_old
if self.logLevel > 0: print "after: minutes_old3", minutes_old3
if self.logLevel > 0: print "end property change" ; print ""
def stop(self):
tListener.cancel()
def set_fast_clock_rate(self):
# set the fast clock rate
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, scheduling_margin_gbl, scheduling_in_operation_gbl
global schedule_trains_hourly
global timebase
global fast_clock_running_at_operational_speed
# if self.logLevel > 0: print "TimeListener: change",event.propertyName, "from", event.oldValue, "to", event.newValue
if self.logLevel > 0: print "set_fast_clock_rate: 1"
if self.speed_not_operational_gbl__is_defined():
if self.logLevel > 0: print "set_fast_clock_rate: 2", speed_not_operational_gbl
# if schedule_trains_hourly:
if True:
hour = int(timebase.getTime().getHours())
minutes = int(timebase.getTime().getMinutes())
rate = timebase.userGetRate()
if self.logLevel > 0: print "set_fast_clock_rate:", "schedule_trains_hourly", schedule_trains_hourly
fast_clock_during_non_operational_times = speed_not_operational_gbl
if self.logLevel > 0: print "fast clock during non operational_times", fast_clock_during_non_operational_times
if self.logLevel > 0: print "hour", hour, "start_hour_gbl", start_hour_gbl, "end_hour_gbl", end_hour_gbl, \
"fast_clock_rate", fast_clock_rate, "speed_not_operational_gbl", speed_not_operational_gbl, \
"hour >= start_hour_gbl and hour <= end_hour_gbl", hour >= int(start_hour_gbl) and hour <= int(end_hour_gbl)
if hour >= int(start_hour_gbl) and hour <= int(end_hour_gbl):
# or hour == int(start_hour_gbl - 1) % 24 and minutes == 59:
if rate != fast_clock_rate: # check to stop recursion error
timebase.userSetRate(float(fast_clock_rate))
fast_clock_running_at_operational_speed = True
if self.logLevel > 0: print "set_fast_clock_rate:", "fast_clock_rate slow", fast_clock_rate
pass
else:
if self.logLevel > 0: print "fast_clock_during_non_operational_times", fast_clock_during_non_operational_times
fcr = fast_clock_during_non_operational_times
if fcr > 100 : fcr = 100 # set to maximum
if rate != fcr:
timebase.userSetRate(float(fcr))
fast_clock_running_at_operational_speed = False
if self.logLevel > 0: print "set_fast_clock_rate:", "fcr", fcr
else:
print "speed_not_operational_gbl__is_defined()", False
def process_operations_trains(self, event ):
global timebase
global schedule_trains_hourly
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, scheduling_margin_gbl, scheduling_in_operation_gbl
global scheduled
global trains_to_be_scheduled
if self.logLevel > 0: print " ****** in process_operations_trains"
if self.logLevel > 0: print "A1"
if 'schedule_trains_hourly' not in globals():
schedule_trains_hourly = False
if self.logLevel > 0: print "in process_operations_trains", "schedule_trains_hourly", schedule_trains_hourly
hour = int(timebase.getTime().getHours())
if self.logLevel > 1: print "type hour" , type(hour)
minutes = event.newValue
if self.logLevel > 1: print "type minutes", type(minutes)
self.curr_time = minutes + hour * 60
if self.logLevel > 1: print "curr_time", self.curr_time
self.prev_time = self.curr_time -1
if self.logLevel > 1: print "prev_time", self.prev_time
# only schedule within stat_hour and end_hour
if int(start_hour_gbl) <= hour <= int(end_hour_gbl):
pass # need to process trains
else:
if self.logLevel > 0: print "returning in process_operational_trains"
return # outside operational time
if self.logLevel > 0: print "A2"
if self.logLevel > 1: print "TimeListener: process_operations_trains"
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
train_list = [train for train in train_list if "skip" not in train.getComment()] # exclude trains marked as 'don't schedule' in Scheduled trains table
if self.logLevel > 0: print "train_list",train_list
#if self.logLevel > 1: print "prev_time", self.prev_time, "curr_time", self.curr_time
if self.logLevel > 0: print "a3"
for train in train_list:
if self.logLevel > 1: print "*******************"
if self.logLevel > 1: print ("train list: departure time: ", str(train.getDepartureTime()), str(train.getName()))
if self.logLevel > 1: print "prev_time", self.prev_time, "curr_time", self.curr_time, "train.getDepartTimeMinutes()", train.getDepartTimeMinutes()
#get the train that is triggered in the current minute
if event == None:
if self.logLevel > 0: print "event is none , returning"
return
if self.logLevel > 0: print "A4"
# schedule the train taking account of the repeat command
# trains_to_start = []
if self.logLevel > 0: print "train_list", train_list, "trains_to_be_scheduled", trains_to_be_scheduled
for train in train_list:
comment = train.getComment()
repeat_command = self.find_between(comment, "[repeat-", "-repeat]")
if self.logLevel > -1: print "train", train, "repeat_command", repeat_command
max = int(minutes)
min = (int(minutes) - 1)
mid = int(train.getDepartTimeMinutes())
if repeat_command == "Once":
if max == 0:
min += 1; mid += 1; max += 1
print "hour", hour, "minutes", minutes, "mid", mid, "min", min, "max", max, "train.getDepartTimeMinutes()", train.getDepartTimeMinutes()
min1 = hour - 1
mid1 = int(train.getDepartureTimeHour())
max1 = hour
if max1 == 0: # ensure mid lies between min amd max (ensure we don't have 1 < 0 <= 0)
min1 += 1; mid1 += 1; max1 += 1
print "min1", min1, "mid1", mid1, "max1", max1, "(min1) < (mid1) <= (max1)", (min1) < (mid1) <= (max1)
if (min % 60 < (mid % 60) <= max % 60) and \
((min1) < (mid1) <= (max1)):
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
elif repeat_command == "Repeat every 20 mins":
if max % 20 == 0:
min += 1; mid += 1; max += 1 # ensure mid lies between min amd max (ensure we don't have 59 < 0 <= 0)
if (min % 20 < (mid % 20) <= max % 20):
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
elif repeat_command == "Repeat every 30 mins":
if max % 30 == 0:
min += 1; mid += 1; max += 1
if (min % 30 < (mid % 30) <= max % 30):
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
elif repeat_command == "Repeat every Hour":
if self.logLevel > 0: print "min", min, "max", max, "mid", mid
if max == 0:
min += 1; mid += 1; max += 1
if self.logLevel > 0: print "min", min, "max", max, "mid", mid
if (min < (mid % 60) <= max):
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
elif repeat_command == "Repeat every 2 Hours":
if max == 0:
min += 1; mid += 1; max += 1
min1 = hour - 1
mid1 = int(train.getDepartureTimeHour())
max1 = hour
if max1 % 2 == 0: # ensure mid lies between min amd max (ensure we don't have 1 < 0 <= 0)
min1 += 1; mid1 += 1; max1 += 1
if (min < (mid % 60) <= max) and \
((min1 % 2) < (mid1 % 2) <= (max1 % 2)):
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
else:
if self.logLevel > 0: print "incorrect repeat command", repeat_command
# assume set to once
if self.prev_time < int(train.getDepartTimeMinutes()) <= self.curr_time and \
"skip" not in train.getDescription(): # if skip in description of scheduled Train do not run the train
if train not in trains_to_be_scheduled:
trains_to_be_scheduled.append(train)
scheduled[train] = False
if self.logLevel > 0: print "trains_to_be_scheduled", trains_to_be_scheduled
if self.logLevel > 0: print "Time listener: trains_to_be_scheduled", trains_to_be_scheduled
if self.logLevel > 0: print "scheduled", scheduled
if self.logLevel > 0: print "trains_to_be_scheduled", trains_to_be_scheduled
def speed_not_operational_gbl__is_defined(self):
global start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, scheduling_margin_gbl, scheduling_in_operation_gbl
try:
speed_not_operational_gbl
except NameError:
if self.logLevel > 0: print("well, it WASN'T defined after all!")
return False
else:
if self.logLevel > 0: print("sure, it was defined.")
return True
def find_between(self, s, first, last):
try:
start = s.index(first) + len(first)
end = s.index(last, start)
return s[start:end]
except IndexError:
if self.logLevel > 0: print "D"
except ValueError:
return ""
class Trigger_Timetable:
def __init__(self, minutes):
global timetable_triggered_gbl
global print_count
timetable_triggered_gbl = True
if minutes == None: return
self.run(minutes)
def run(self, minutes):
t1 = Thread(target=self.send_timetable_and_clock_via_mqtt, args=(minutes,))
t1.start()
t1.join()
def send_timetable_and_clock_via_mqtt(self, minutes):
global station_name_list_gbl, group_location_gbl, run_local_timetable_gbl
global timetable_gbl
self.logLevel = 0
global timebase, print_count
# print "****************start send_timetable_and_clock_via_mqtt"
hour = int(timebase.getTime().getHours())
time = str(hour).zfill(2) + ":" + str(minutes).zfill(2)
file = self.directory2() + "train_operator_emblem.txt"
event = ""
event = self.read_list2()[0]
try:
self.send_clock_message(hour, minutes, event)
except:
if "print_count" not in globals(): print_count = 0
if print_count < 1: print "clock message not sent"
print_count += 1
if "station_name_list_gbl" not in globals():
station_name_list_gbl = ""
if "group_location_gbl" not in globals():
group_location_gbl = ""
# get list of origins, destinations and times at intermediate stations
timetable = self.get_timetable(hour, minutes)
if 'group_location_gbl' != "" and 'station_name_list_gbl' != "":
station_name = group_location_gbl
station_names_list = station_name_list_gbl
else:
station_name = 'Not Set'
station_names_list = ['Not Set']
self.generate_local_timetable(station_name, station_names_list, time, timetable)
if "run_local_timetable_gbl" not in globals():
print "run_local_timetable_gbl not defined"
return
if run_local_timetable_gbl == None:
print "run_local_timetable_gbl None"
return
if run_local_timetable_gbl:
if "timetable_gbl" in globals():
if timetable_gbl != None:
timetable_gbl.frame.setVisible(True)
else:
if "timetable_gbl" in globals():
if timetable_gbl != None:
timetable_gbl.frame.setVisible(False)
try:
self.send_timetable_messages(timetable)
except:
pass
def find_between(self, s, first, last):
try:
start = s.index(first) + len(first)
end = s.index(last, start)
return str(s[start:end])
except ValueError:
return ""
except IndexError:
print "index error find_between", "first", first, "last", last
def get_timetable(self, hour, minutes1):
global schedule_trains_hourly
global start_hour_gbl, end_hour_gbl
global fast_clock_rate
self.curr_time = minutes1 + hour * 60
timetable = []
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
train_list = TrainManager.getTrainsByTimeList()
for train in train_list:
if self.logLevel > 0: print "train", train, "train.getDescription()", train.getDescription()
if train.getDescription() is not None and "skip" not in train.getDescription():
if self.logLevel > 0: print "train", train, train.getDescription()
comment = train.getComment()
repeat = self.find_between(comment, "[repeat-", "-repeat]")
departure_time_minutes = train.getDepartTimeMinutes() % 60
departure_time_hour = train.getDepartureTimeHour()
train_name = train.getName()
if repeat == "Once":
minutes = [departure_time_minutes]
elif repeat == "Repeat every 20 mins":
minutes = [minutes for minutes in range(0,59) if (minutes % 20) == (int(departure_time_minutes) % 20)]
elif repeat == "Repeat every 30 mins":
minutes = [minutes for minutes in range(0,59) if (minutes % 30) == (int(departure_time_minutes) % 30)]
elif repeat == "Repeat every Hour":
minutes = [departure_time_minutes]
elif repeat == "Repeat every 2 Hours":
minutes = [departure_time_minutes]
else:
minutes = [0]
if repeat == "Once":
hours = [departure_time_hour]
else:
if hour < int(end_hour_gbl):
start_hour = max(hour, int(start_hour_gbl))
end_hour = max(hour + 3, int(start_hour_gbl))
else:
start_hour = int(start_hour_gbl)
end_hour = int(start_hour_gbl) + 3
hours = [hour1 for hour1 in range(start_hour, end_hour)]
if repeat == "Repeat every 2 Hours": #update hours if 2 hourly
hours = [hour1 for hour1 in hours if (int(train.getDepartureTimeHour()) % 2 == hour1 % 2)]
for train_mins in minutes:
for train_hour in hours:
depart_time = int(str(train_mins)) + int(str(train_hour)) * 60
train_route_start_time = str(train_hour).zfill(2) + ":" + str(train_mins).zfill(2)
if self.logLevel > 0: print "train", train, train.getDescription(), "train_route_start_time", train_route_start_time
train_route = train.getRoute()
if train_route is not None:
if self.logLevel > 0: print "train_route", train_route
locations = [location for location in train_route.getLocationsBySequenceList() \
if ".py" not in location.getName()]
first_location = locations[0]
first_station = str(first_location.getName())
last_location = locations[-1]
last_station = str(last_location.getName())
comments = [location.getComment() for location in train_route.getLocationsBySequenceList() \
if ".py" not in location.getName()]
journey_duration = 0
for comment in comments:
duration_sec = self.find_between(comment, "[duration_sec-", "-duration_sec]")
if self.logLevel > 0: print "duration_sec", duration_sec
if duration_sec != "":
duration = ((float(duration_sec) * int(str(fast_clock_rate))) / 60.0) # fast minutes
else:
# print "setting duration 0"
duration = 0
journey_duration += int(duration)
for i, route_location in enumerate(train_route.getLocationsBySequenceList()):
station_name = str(route_location.getName())
platform_name = str(MyTableModel7().get_location_platform(route_location.getLocation()))
if self.logLevel > 0: print "platform_name", platform_name
if platform_name == "":
platform_name = station_name
if self.logLevel > 0: print "platform_name", platform_name
if self.logLevel > 2: print "****************************", station_name, "***************************"
if ".py" in station_name: # exclude actions
break
timetable_entry_names = ["train_name", "station_name", "station_departure_time", "last_station",
"last_station_arrival_time", "via"]
# remove items from start of via list, and the destination
locations1 = train_route.getLocationsBySequenceList()
locations = [str(loc) for loc in locations1]
via = locations[i+1:-1]
via = [location2 for location2 in via if ".py" not in location2]
if via == []:
via = "-"
if i != 0 and last_station == station_name:
via = ["Terminates Here"]
via = str(via).replace('[','').replace(']','').replace("'", "")
comment = route_location.getComment()
if i == 0:
station_departure_time = train_route_start_time
time_to_station = 0
else:
duration_sec = self.find_between(comment, "[duration_sec-", "-duration_sec]")
if str(duration_sec) == "":
duration_sec = 0
if self.logLevel > 2: print route_location, "duration_sec", duration_sec
duration = float((float(duration_sec) * int(str(fast_clock_rate))) / 60.0)
if self.logLevel > 2: print route_location, "duration", duration
time_to_station = int(duration)
if self.logLevel > 2: print "time_to_station", time_to_station
previous_departure_time = station_departure_time
if self.logLevel > 0:
print train_name, "previous_departure_time", previous_departure_time
station_departure_time = self.add_times(station_departure_time, time_to_station)
if self.logLevel > 0: print train_name, route_location, "station_departure_time", station_departure_time
# if the wait_time and journey_time have been set we can set the arrival time
wait_time = self.find_between(comment, "[wait_time-", "-wait_time]")
journey_time = self.find_between(comment, "[journey_time-", "-journey_time]")
if journey_time == "":
journey_time = "0"
# convert journey time to fast minutes
journey_time_fast_mins = ((float(str(journey_time)) * int(str(fast_clock_rate))) / 60.0)
if wait_time != "" and journey_time != "":
if i == -1:
station_arrival_time = station_departure_time
else:
if self.logLevel > 0: print train_name, route_location, "journey_time", journey_time
station_arrival_time = self.add_times(previous_departure_time, journey_time_fast_mins)
else:
if i == 0:
station_arrival_time = ""
else:
station_arrival_time = station_departure_time
[h, m] = station_departure_time.split(":")
station_departure_time_in_mins = int(m) + int(h) * 60
# [h, m] = station_arrival_time.split(":")
# station_arrival_time_in_mins = int(m) + int(h) * 60
if i != 0 and last_station == station_name:
station_departure_time = ""
# make sure we don't display trains that have a departure time > current time
# keep departures up for 1 fast minutes after the departure time
if self.curr_time - 1 < station_departure_time_in_mins:
timetable_entry = [train_name, \
station_name , \
platform_name , \
station_arrival_time, \
station_departure_time, \
first_station, \
last_station, \
via]
timetable.append(timetable_entry)
#sort timetable by time
timetable.sort(key = lambda row: max(row[3],row[4]))
return timetable
def generate_local_timetable(self, station_name, station_names_list, time, timetable):
global timetable_gbl
if "timetable_gbl" not in globals():
timetable_gbl = Timetable(station_name)
timetable_gbl.update_timetable(station_name, station_names_list, time, timetable)
elif timetable_gbl == None:
timetable_gbl = Timetable(station_name)
timetable_gbl.update_timetable(station_name, station_names_list, time, timetable)
else:
# update the Timetable, Timetable class has already been initiated
timetable_gbl.update_timetable(station_name, station_names_list, time, timetable)
def send_timetable_messages(self,timetable):
i = 0
msg = "["
for [train_name, \
station_name , \
platform , \
station_arrival_time, \
station_departure_time, \
first_station, \
last_station, \
via] in timetable:
msg += '{"type" : "' + "schedule" + '", ' + \
'"train_name" : "' + str(train_name) + '", ' + \
'"station_name" : "' + str(station_name) + '", ' + \
'"platform" : "' + str(platform) + '", ' + \
'"station_arrival_time" : "' + str(station_arrival_time) + '", ' + \
'"station_departure_time" : "' + str(station_departure_time) + '", ' + \
'"first_station" : "' + str(first_station) + '", ' + \
'"last_station" : "' + str(last_station) + '", ' + \
'"via" : "' + str(via) + '"},'
i += 1
msg = msg[:-1]
msg += "]"
self.send_mqtt_message(msg)
def send_mqtt_message(self, msg):
global print_count
try:
# Find the MqttAdapter
mqttAdapter = jmri.InstanceManager.getDefault( jmri.jmrix.mqtt.MqttSystemConnectionMemo ).getMqttAdapter()
# create content to send "/jmri/timetable message content"
topic = "jmri/timetable"
payload = msg
mqttAdapter.publish(topic, payload)
except:
if "print_count" not in globals(): print_count = 0
if print_count < 1: print "failure mqtt message"
print_count += 1
def send_clock_message(self, hour, minutes, event):
msg = '[{"type" : "' + "clock" + '", ' + \
'"time" : "' + str(hour).zfill(2) + ":" + str(minutes).zfill(2) + '",' \
'"emblem" : "' + str(event) + '"}]'
self.send_mqtt_message(msg)
def add_times(self, station_departure_time, time_to_station):
# add time_to_station to station_departure time
# station_departure_time is in form hh:mm
# print "time_to_station", time_to_station , "should be mins"
[hours, mins] = station_departure_time.split(":")
# print "hours", hours, "mins", mins
hour = int(hours) + int(time_to_station) // 60
min = (int(mins) + int(time_to_station)) % 60
# print "hour", hour, "min", min
station_departure_time_new = str(hour).zfill(2) + ":" + str(min).zfill(2)
# print "station_departure_time_new", station_departure_time_new
return station_departure_time_new
def directory2(self):
# print "directory2"
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "train_operators_emblem"
# print "path", path
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def write_list2(self, a_list):
# store list in binary file so 'wb' mode
file = self.directory2() + "train_operator_emblem.txt"
if self.logLevel > 0: print "train_operator_emblem" , a_list
if self.logLevel > 0: print "file" , file
with open(file, 'wb') as fp:
if self.logLevel > 0: print "a_list", a_list
i = 0
for items in a_list:
if self.logLevel > 0: print "items", items
fp.write('%s' %items)
if i < 5 : fp.write(",")
i+=1
# Read list to memory
def read_list2(self):
# for reading also binary mode is important
file = self.directory2() + "train_operator_emblem.txt"
# print "file", file
n_list = []
try:
with open(file, 'rb') as fp:
for line in fp:
# print "line", line
# x = line[:-1]
# print x
y = line.split(",")
if self.logLevel > 0: print "y" , y
n_list = y
return n_list
except:
return ["", "", "", "", "", ""]
class RunRoute(jmri.jmrit.automat.AbstractAutomaton):
def __init__(self, route, graph, station_from, station_to, no_repetitions, train_name, \
delay = 0, scheduling_train = False, set_departure_times = False, train = None):
# print ("route" , route, "station_from", station_from, "station_to", station_to, \
# "no_repetitions", no_repetitions, "train_name", train_name, \
# "scheduling_train", scheduling_train)
# station_from is set to the initial position of the train, not necessarily
# the start position of the route
# station_to is set only if returning to start position
# in that case it is set to station_from
# the route gives the stations on the route
# note station_to and station_from are strings, while elements of route are locations
self.logLevel = 0
if self.logLevel > 0: print "loglevel", self.logLevel
if self.logLevel > 0: print "in init RunRoute"
if self.logLevel > 0: print route, station_from, station_to, no_repetitions, train_name, delay
self.delay = delay
self.scheduling_train = scheduling_train
self.set_departure_times = set_departure_times
if self.logLevel > 0: print "set_departure_times", set_departure_times
self.route = route
self.train = train # only used if scheduling_train = True
self.train_name = train_name
if route is None or train_name is None:
self.mycount = None
self.no_repetitions = -1
if self.logLevel > 0: print "RunRoute: route == ", route, " train_name == ", train_name
else:
if self.logLevel > 0: print "RunRoute: route =", route
self.graph = graph
self.station_from = station_from
self.station_to = station_to
self.no_repetitions = no_repetitions
self.mycount = 0
# self.train_name_in = train_name
self.train_name = train_name # null if train not in start block
# set up station_list
station_list_locations = self.route.getLocationsBySequenceList()
#convert station_list to strings
station_list = [location.getName() for location in station_list_locations]
station_comment_list = [location.getComment() for location in station_list_locations]
self.initial_station_in_route = station_list[0]
# prepend station_from if required
self.prepended = False
if self.logLevel > 0: print "station_list before", station_list, "self.station_from",self.station_from,"self.station_to",self.station_to,"station_list[0]",station_list[0]
if self.station_from == None: #ensure route starts at station_from
pass
elif self.station_from != station_list[0]:
try:
station_list.insert(0,self.station_from)
station_comment_list.insert(0, None)
except:
if self.logLevel > 0: print "fred"
self.prepended = True # we have to remove this initial station if we are repeating
if self.logLevel > 0: print "station_list",station_list
# append station_to if required
if self.station_to == None: #ensure route ends at station_to
pass
elif self.station_to != station_list[-1]:
station_list.append(self.station_to)
try:
station_comment_list.append(None)
except:
if self.logLevel > 0: print "jim"
if self.logLevel > 0: print "station_list",station_list
# if repeating append initial station in route
if self.no_repetitions > 0: #ensure route end at start point if repeating
if self.station_to != self.initial_station_in_route:
if station_list[-1] != self.initial_station_in_route:
station_list.append(self.initial_station_in_route)
station_comment_list.append(None)
if self.logLevel > 0: print "station_list after", station_list
self.station_list = station_list
self.station_comment_list = station_comment_list
if self.logLevel > 0: print "self.station_comment_list", self.station_comment_list
# ignore the number of repetitions if station_to was not set to station_from
if self.station_list[0] != self.station_list[-1]:
self.no_repetitions = 0
def handle(self):
if self.route is not None and self.train_name is not None:
if self.logLevel > 0: print "in handle", self.mycount
if self.delay > 0 and self.mycount == 0: # only delay on the first iteration
self.waitMsec(self.delay)
if int(self.mycount) <= int(self.no_repetitions):
# print "repeating", "self.mycount", self.mycount, "self.no_repetitions", self.no_repetitions
if self.logLevel > 0: print "station_list in handle", self.station_list, "in handle", self.mycount
response = self.run_route(self.train_name)
if self.logLevel > 0: print "prepended", self.prepended
if self.mycount == 0 and self.prepended:
if self.logLevel > 0: print "station_list before pop", self.station_list
self.station_list.pop(0)
self.station_comment_list.pop(0)
if self.logLevel > 0: print "station_list after pop", self.station_list
if self.logLevel > 0: print "returning true", "train_name", self.train_name, "mycount", self.mycount, "reps" , self.no_repetitions
self.mycount += 1 # 0 first time round
return True
else:
if self.logLevel > 0: print "returning false", "train_name", self.train_name, "mycount", self.mycount, "reps" , self.no_repetitions
return False
def run_route(self, train_to_move):
global check_action_route_flag
global fast_clock_rate
if self.logLevel > 0: print "************************************run train******************"
if self.logLevel > 0: print "! start run_route"
station_from = None
prev_station_index = 0
for station_index, station in enumerate(self.station_list):
# print "station_index", station_index, "station", station, "train_to_move", train_to_move
if self.logLevel > 0: print "self.scheduling_train", self.scheduling_train
# do action if one has been requested
if self.station_is_action(station): #if the station_name is a python_file
action = station
self.execute_action(action) # execute the python file
else:
# print "running at station", "station_from", station_from
station_to = station # both now strings
if station_from != None: # first time round station_from is not set up
# find the accumulated durations
if self.scheduling_train or self.set_departure_times:
durations = [MyTableModel5().find_between(comment, "[duration_sec-", "-duration_sec]")
for comment in self.station_comment_list]
# print "durations 4", durations
accumulated_durations = []
total = 0
for n in durations:
try:
total += int(n)
except:
pass
accumulated_durations.append(total)
if station_index != self.find_row_first_location(self.route):
previous_station_index = self.find_row_prev_location(station_index, self.route)
station_comment = self.station_comment_list[previous_station_index] # do not use prev_station_index as it includes actions
accumulated_duration = accumulated_durations[previous_station_index]
else:
station_comment = None
accumulated_duration = 0
if self.logLevel > 0: print "station", station, "station_comment", station_comment, \
"station_index", station_index, "prev_station_index", prev_station_index
if self.logLevel > 0: print "accumulated_duration", accumulated_duration
if self.logLevel > 0: print self.route.getName(), "! moving from", station_from, "to", station_to
self.station_from_name = station_from
self.station_to_name = station_to
start_block = blocks.getBlock(station_from)
if self.logLevel > 0: "start_block",start_block, "station_to", station_to
if self.logLevel > 0: print "calling move_between_stations","station_from",station_from,"station_to",station_to,"train_to_move",train_to_move
if self.set_departure_times:
# print "setting previous time"
previous_time = int(round(time.time())) # in secs
if self.scheduling_train:
self.wait_for_scheduled_time(self.route, previous_station_index, accumulated_duration, train_to_move)
# done when we know the transit name
# print "__________________________Start__" + train_to_move + "___________________________________"
strpad = station_index * " "
success = self.check_train_in_block_for_scheduling_margin_fast_minutes(start_block, train_to_move, strpad)
if success:
move_train = MoveTrain(station_from, station_to, train_to_move, self.graph, mode = "scheduling", route = self.route)
move_train.move_between_stations(station_from, station_to, train_to_move, self.graph, mode = "scheduling")
transit_name = move_train.transit_name
print "__________________________End____" + train_to_move + "__transit: " + transit_name
else:
print "failed to move train - no train in block - have waited for scheduling margin"
transit_name = move_train.transit_name
print "__________________________End____" + train_to_move + "__transit: " + transit_name
else:
success = self.check_train_in_block_allow_manual_repositioning(train_to_move, self.station_from_name)
if success:
move_train = MoveTrain(station_from, station_to, self.train_name, self.graph, route = self.route)
move_train.move_between_stations(station_from, station_to, self.train_name, self.graph)
move_train = None
# train has moved, if we are in departure_time_setting mode, store the journey time
if self.logLevel > 0: print "about to store departure times"
if self.set_departure_times:
if self.logLevel > 0: print "storing departure times"
current_time = int(round(time.time())) # in secs
journey_time_in_secs = current_time - previous_time
print "previous_time", previous_time, "current_time", current_time
if self.logLevel > 0: print "before store", "journey_time_in_secs", journey_time_in_secs
self.store_journey_time(self.route, station_index, str(journey_time_in_secs))
if self.logLevel > 0: print "after store"
if self.logLevel > 0: print "finished move between stations station_from = ", station_from, " station_to = ", station_to
end_block = blocks.getBlock(station_to) #do following in case the block sensor is a bit dodgy
end_block.setValue(self.train_name)
check_action_route_flag = False # This flag may have been set by the action appearing in the route
# before this move. It has to be reset.
# print "check_action_route_flag reset", check_action_route_flag
station_from = station_to
prev_station_index = station_index
if self.scheduling_train:
fast_minute = 1000*60/int(str(fast_clock_rate))
self.waitMsec(fast_minute)
else:
self.waitMsec(4000)
if self.logLevel > 0: print "! finished run_train"
def find_row_first_location(self, route):
# print "find_row_first_location"
# get the row (sequenceNo) of the first location that is not an action (a python file xx.py)
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
for routelocation in route.getLocationsBySequenceList() \
if ".py" not in routelocation.getName()]
# print "routelocationsSequenceNumber_list", routelocationsSequenceNumber_list
current_val = [[routelocation, sequenceNo] \
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
if 1 == sequenceNo][0]
# print "current_val", current_val
current_index = routelocationsSequenceNumber_list.index(current_val)
# print "current_index", current_index
# print "routelocations_list", routelocations_list, "index", index
try:
[routelocation, row] = routelocationsSequenceNumber_list[current_index]
# row = routelocationsSequenceNumber_list[currentIndex + 1]
except:
row = None
# print "row", row
return row - 1 # row number starts from 0
def find_row_prev_location(self, row, route):
# get the row (sequenceNo) of the first location that is not an action (a python file xx.py)
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
for routelocation in route.getLocationsBySequenceList() \
if ".py" not in routelocation.getName()]
current_val_list = [[routelocation, sequenceNo] \
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
if row == sequenceNo-1]
current_val = current_val_list[0]
current_index = routelocationsSequenceNumber_list.index(current_val)
[routelocation, row] = routelocationsSequenceNumber_list[current_index - 1]
return row - 1 # row number starts from 1
def check_train_in_block_for_scheduling_margin_fast_minutes(self, start_block, train_to_move, strpad = ""):
global scheduling_margin_gbl
global timebase
# print "__________________________Start__" + train_to_move + "___________________________________"
# timehm = str(timebase.getTime().getHours()) + ":" + str(timebase.getTime().getMinutes())
timehm = "{:02d}:{:02d}".format(timebase.getTime().getHours(), timebase.getTime().getMinutes())
print timehm, strpad, "check_train", train_to_move, "in_block", start_block.getUserName(), "for", scheduling_margin_gbl, "fast_minutes"
global fast_clock_rate
if self.logLevel > 0: print "check_train_in_block_for_scheduling_margin_fast_minutes"
for j in range(int(scheduling_margin_gbl)): # try to schedule train for scheduling_margin_gbl fast minutes
train_in_block = self.blockOccupied(start_block)
train_block_name = start_block.getValue()
if train_in_block and (train_block_name == train_to_move):
# print strpad + "--" + str(train_to_move) + " train in start block " + str(start_block.getUserName())
return True
else:
print (strpad + "--" + str(train_to_move) + " not in start_block: " + str(start_block.getUserName()) \
+ " time waited: " + str(j) + " fast minutes")
fast_minute = 1000*60/int(str(fast_clock_rate))
self.waitMsec(fast_minute)
return False
def check_train_in_block_allow_manual_repositioning(self, train_name, station_from_name):
i = 0
# print "train_name", train_name, "station_from_name", station_from_name
while self.check_train_in_start_block(train_name, station_from_name) == False:
if i > 2: # allow some time to recover
title = ""
msg = "Cannot run train, train not in start block\n" + \
train_name + " should be in block " + station_from_name + \
"\nmove it there manually and it might recover"
opt1 = "have moved train, try again"
opt2 = "cancel moving train"
reply = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
if reply == opt1: # "have moved train, try again"
i = -1
else: # opt2
return False # "cancel moving train"
self.waitMsec(5000)
i += 1
# move_train = MoveTrain(station_from, station_to, train_to_move, self.graph, station_comment)
# move_train.move_between_stations(station_from, station_to, train_to_move, self.graph)
return True
def store_journey_time(self, route, row, journey_time):
global CreateAndShowGUI5_glb
routeLocationList = route.getLocationsBySequenceList()
routeLocation = routeLocationList[row]
print "routeLocation", routeLocation, "row", row, "value", journey_time, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5"
# OptionDialog().displayMessageNonModal("about to set_value_in_comment", "OK")
self.set_value_in_comment(routeLocation, journey_time, "journey_time")
wait_time = self.get_value_in_comment(routeLocation, "wait_time")
duration_sec = int(journey_time) + int(wait_time)
self.set_value_in_comment(routeLocation, duration_sec, "duration_sec")
# OptionDialog().displayMessageNonModal("about to populate_action", "OK")
CreateAndShowGUI5_glb.populate_action(None)
# OptionDialog().displayMessageNonModal("about to update_journey_time_action", "OK")
CreateAndShowGUI5_glb.update_journey_time_action(None)
# OptionDialog().displayMessageNonModal("just did update_journey_time_action", "OK")
# CreateAndShowGUI5_glb.update_duration_action(None)
#
def set_value_in_comment(self, routeLocation, value, duration_string):
global CreateAndShowGUI5_glb
comment = routeLocation.getComment() #Null
if comment == None:
comment = ""
delim_start = "[" + duration_string + "-"
delim_end = "-" + duration_string + "]"
comment = CreateAndShowGUI5_glb.insert_between(comment, delim_start, delim_end, value)
routeLocation.setComment(comment)
def get_value_in_comment(self, routeLocation, duration_string):
delim_start = "[" + duration_string + "-"
delim_end = "-" + duration_string + "]"
comment = routeLocation.getComment()
value = self.find_between(comment, "[" + duration_string + "-", "-" + duration_string + "]")
return value
def find_between(self, s, first, last):
try:
start = s.index(first) + len(first)
end = s.index(last, start)
return s[start:end]
except ValueError:
return ""
def wait_for_scheduled_time(self, route, row, accumulated_durations, train_to_move):
global fast_clock_rate
global timebase
global scheduling_margin_gbl
if 'timebase' not in globals():
timebase = jmri.InstanceManager.getDefault(jmri.Timebase)
routeLocationList = route.getLocationsBySequenceList()
routeLocation = routeLocationList[row]
train_comment = self.train.getComment()
if self.logLevel > 0: print "train_to_move", train_to_move, "routeLocation", routeLocation
comment = routeLocation.getComment()
# print "train_comment", train_comment, "comment", comment
if self.logLevel > 0: print "x1"
repeat_command = TimeListener().find_between(train_comment, "[repeat-", "-repeat]")
if self.logLevel > 0: print "x3"
current_minutes = int(timebase.getTime().getMinutes())
if self.logLevel > 0: print "x2", "current_minutes", current_minutes
# the departure time for the train is the first one in the hour
# get what would be the current time if we were running the first train in the hour
# so we can get the difference of the two and hence get the wait time
# this is easier than getting the actual departure time minutes of the train
if repeat_command == "Once":
current_minutes_mod = current_minutes
current_minutes_mod_array = [current_minutes_mod]
elif repeat_command == "Repeat every 20 mins":
current_minutes_mod = current_minutes % 20
cmm20 = self.add_minutes(current_minutes_mod, 20)
cmm40 = self.add_minutes(current_minutes_mod, 40)
current_minutes_mod_array = [current_minutes_mod, cmm20, cmm40]
elif repeat_command == "Repeat every 30 mins":
current_minutes_mod = current_minutes % 30
cmm30 = self.add_minutes(current_minutes_mod, 30)
current_minutes_mod_array = [current_minutes_mod, cmm30]
elif repeat_command == "Repeat every Hour":
current_minutes_mod = current_minutes
current_minutes_mod_array = [current_minutes_mod]
elif repeat_command == "Repeat every 2 Hours":
current_minutes_mod = current_minutes
current_minutes_mod_array = [current_minutes_mod]
else:
print "error wrong repeat command"
return
if self.logLevel > 0: print "d", current_minutes, "current_minutes_mod", current_minutes_mod
current_hour = int(str(timebase.getTime().getHours()))
if self.logLevel > 0: print("a"), current_hour
current_time = str(current_hour).zfill(2) + ":" + str(current_minutes_mod).zfill(2)
if self.logLevel > 0: print "c", current_time
train_start_time = self.train.getDepartureTime()
if self.logLevel > 0: print "train_start_time", train_start_time, "accumulated_durations", accumulated_durations
accumulated_durations_fast_mins = (accumulated_durations / 60.0) * int(str(fast_clock_rate)) # convert to fast min
if self.logLevel > 0: print "accumulated_durations_fast_mins", accumulated_durations_fast_mins
station_start_time = self.add_minutes_to_time(train_start_time, accumulated_durations_fast_mins)
[station_start_hours, station_start_mins] = station_start_time.split(":")
if self.logLevel > 0: print "station_start_time", station_start_time
if self.logLevel > 0: print "current_time", current_time, "station_start_time", station_start_time
#calculate minutes to wait
minutes_to_wait_array = [self.subtract_minutes(station_start_mins, cm) for cm in current_minutes_mod_array]
if self.logLevel > 0: print "minutes_to_wait_array", minutes_to_wait_array
minutes_to_wait = min(minutes_to_wait_array)
if self.logLevel > 0: print "minutes_to_wait", minutes_to_wait
minutes_late = max([m-60 for m in minutes_to_wait_array]) # get the minutes late
abs_minutes_late = abs(minutes_late)
if self.logLevel > 0: print "minutes_late", minutes_late
if self.logLevel > 0: print "minutes_late", abs_minutes_late
index = minutes_to_wait_array.index(minutes_to_wait)
if abs_minutes_late < int(scheduling_margin_gbl):
if self.logLevel > 0: print "minutes_late2", minutes_late, "scheduling_margin_gbl", scheduling_margin_gbl
fast_ms_to_wait = 0
else:
if self.logLevel > 0: print "minutes_to_wait", minutes_to_wait
fast_ms_to_wait = abs(minutes_to_wait) * 60 * 1000
if self.logLevel > 0: print "waiting for ", current_minutes_mod_array[index]
if self.logLevel > 0: print "v"
ms_to_wait = fast_ms_to_wait / int(fast_clock_rate)
if self.logLevel > 0: print "w"
if self.logLevel > 0: print "waiting", "minutes_to_wait", minutes_to_wait
if self.logLevel > 0: print "waiting", "ms_to_wait", ms_to_wait, "fast_secs_to_wait", fast_ms_to_wait/1000
if self.logLevel > 0: print "time before wait", str(timebase.getTime())
self.waitMsec(ms_to_wait)
if self.logLevel > 0: print "time after wait", str(timebase.getTime())
if self.logLevel > 0: print "waited till start time"
def add_minutes(self, min1, min2):
min = (int(min1) + int(min2) ) % 60
return min
def add_minutes_to_time(self, time, minutes):
if self.logLevel > 0: print "z", time, minutes
[day, time_hours, time_mins] = time.split(":")
if self.logLevel > 0: print "add minutes to time"
if self.logLevel > 0: print "time", time, "minutes", minutes
# print "hours", hours, "mins", mins
hour = int(str(time_hours)) + (int(time_mins) + int(minutes)) // 60
if self.logLevel > 0: print "hour"
min = (int(minutes) + int(time_mins) ) % 60
if self.logLevel > 0: print "min", min
if self.logLevel > 0: print "hour", hour, "min", min
station_departure_time_new = str(hour).zfill(2) + ":" + str(min).zfill(2)
if self.logLevel > 0: print "station_departure_time_new", station_departure_time_new
return station_departure_time_new
def subtract_times(self, current_time, station_time):
if self.logLevel > 0: print "subtract times"
[curr_hours, curr_mins] = current_time.split(":")
# current_mins = int(curr_hours) * 60 + int(curr_mins)
current_mins = int(curr_mins)
if self.logLevel > 0: print "curr_hours", curr_hours, "curr_mins", curr_mins, "current_mins", current_mins
[dep_hours, dep_mins] = station_time.split(":")
# station_mins = int(dep_hours) * 60 + int(dep_mins)
station_mins = int(dep_mins)
if self.logLevel > 0: print "dep_hours", dep_hours, "dep_mins", dep_mins, "station_mins", station_mins
# print "current_time", current_time, "mins", mins
wait_time = station_mins - current_mins
if self.logLevel > 0: print "wait_time", wait_time
wait_time = wait_time % 60
if self.logLevel > 0: print "wait_time", wait_time
return wait_time
def subtract_minutes(self, min1, min2):
wait_time = int(min1) - int(min2)
if self.logLevel > 0: print "wait_time", wait_time
wait_time = wait_time % 60
if self.logLevel > 0: print "wait_time", wait_time
return wait_time
def subtract_times_neg(self, current_time, station_time):
if self.logLevel > 0: print "subtract times"
[curr_hours, curr_mins] = current_time.split(":")
# current_mins = int(curr_hours) * 60 + int(curr_mins)
current_mins = int(curr_mins)
if self.logLevel > 0: print "curr_hours", curr_hours, "curr_mins", curr_mins, "current_mins", current_mins
[dep_hours, dep_mins] = station_time.split(":")
# station_mins = int(dep_hours) * 60 + int(dep_mins)
station_mins = int(dep_mins)
if self.logLevel > 0: print "dep_hours", dep_hours, "dep_mins", dep_mins, "station_mins", station_mins
# print "current_time", current_time, "mins", mins
wait_time = station_mins - current_mins
if self.logLevel > 0: print "wait_time", wait_time
wait_time = wait_time % 60
if self.logLevel > 0: print "wait_time", wait_time
return wait_time - 60
def get_next_item_in_list(self,elem, li ):
if (li.index(elem))+1 != len(li):
thiselem = elem
nextelem = li[li.index(elem)+1]
indexNextElem = li.index(elem)+1
# print 'thiselem',thiselem
# print 'nextel',nextelem
else:
thiselem = elem
nextelem = elem
indexNextElem = li.index(elem)
# print 'thiselem',li[li.index(elem)]
# print 'nextel',li[li.index(elem)]
return [nextelem, indexNextElem]
def check_train_in_start_block(self, train_to_move, blockName):
block = blocks.getBlock(blockName)
if self.blockOccupied(block):
if block.getValue() == train_to_move:
return True
else:
"blockName" , blockName, "not occupied by", "train_to_move", train_to_move
blockName = [block for block in blocks.getNamedBeanSet() if block.getValue() == train_to_move]
if blockName != []:
blockName = blockName[0]
else:
blockName = "train not in any block"
#print "train_to_move", train_to_move, "in" , blockName
return False
else:
#print "train_to_move", train_to_move, "not in" , blockName
blockName = [block for block in blocks.getNamedBeanSet() if block.getValue() == train_to_move]
if blockName != []:
blockName = blockName[0]
else:
blockName = "train not in any block"
#print "train_to_move", train_to_move, "in" , blockName
return False
def blockOccupied(self, block):
if block.getState() == ACTIVE:
state = True
else:
state = False
return state
def station_is_action(self, station):
if station[-3:] == ".py":
return True
else:
return False
def action_directory_in_DispatcherSystem(self):
path = jmri.util.FileUtil.getScriptsPath() + "DispatcherSystem" + java.io.File.separator + "actions"
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def action_directory(self):
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "actions"
if not os.path.exists(path):
os.makedirs(path)
return path + java.io.File.separator
def execute_action(self, action):
# execute a python file in the dispatcher directory
file = self.action_directory() + action
if not os.path.isfile(file):
file = self.action_directory_in_DispatcherSystem() + action
if not os.path.isfile(file):
self.displayMessage("action file " + action + " does not exist, it must have been deleted\n" + \
"should be in directories:\n" + \
self.action_directory_in_DispatcherSystem() + " or\n" + \
self.action_directory())
if self.logLevel > 0: print self.route.getName()," executing file", file
exec(open(file).read()) # execute the file
def displayMessage(self, msg, title = ""):
self.CLOSED_OPTION = False
s = JOptionPane.showOptionDialog(None,
msg,
title,
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
None,
["OK"],
None)
#JOptionPane.showMessageDialog(None, msg, 'Message', JOptionPane.WARNING_MESSAGE)
if s == JOptionPane.CLOSED_OPTION:
self.CLOSED_OPTION = True
return
return s
class ScheduleTrains(jmri.jmrit.automat.AbstractAutomaton):
def setup(self):
self.logLevel = 0
return True
def handle(self):
# print "run trains"
self.run_trains() #schedule trains if schedule_trains_glb is set True external to this routine
# continue scheduling trains
# print "end run trains"
return True
def run_trains(self):
global trains_to_be_scheduled
global schedule_trains_glb
global fast_clock_running_at_operational_speed
global scheduled
global timebase
global fast_clock_rate
if self.logLevel > 0 : print "************************************run trains******************"
# schedule_trains_glb = True
if True:
if 'fast_clock_running_at_operational_speed' not in globals():
fast_clock_running_at_operational_speed = True
if self.logLevel > 0 : print "run trains started: loop: scheduled trains", trains_to_be_scheduled, \
"fast_clock_running_at_operational_speed", fast_clock_running_at_operational_speed
# print "scheduled", scheduled
if fast_clock_running_at_operational_speed:
for train in trains_to_be_scheduled:
# print "train", train, "type", type(train)
if train.getDescription() is not None:
# print "description", train.getDescription()
# print "scheduled[train]", scheduled[train]
if scheduled[train] == False:
if self.logLevel > 0: print "train",train,"scheduled[train]",scheduled[train]
route = train.getRoute()
if route is not None:
routeName = route.getName()
station_from, station_to = SchedulerMaster().get_first_and_last_station(route) # starting from beginning of route
start_block = blocks.getBlock(station_from)
if self.logLevel > 0: "start_block",start_block, "station_to", station_to
# train_block_name = start_block.getValue()
train_to_be_scheduled = train.getDescription()
# this is obsolete: now checked in check_train_in_block_for_scheduling_margin_fast_minutes in run_route in class RunRoute
# run_route_flag = self.check_train_ok_to_start(train, train_block_name)
no_repetitions = 0
if True:
if "stopping" in train.getDescription():
# print "running train %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", train
run_train = RunRoute(route, g.g_stopping, station_from, station_to, no_repetitions, train_to_be_scheduled, \
scheduling_train = True, train = train)
run_train.setName("running_route_" + routeName)
instanceList.append(run_train)
run_train.start()
else:
# print "running train %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", train
run_train = RunRoute(route, g.g_express, station_from, station_to, no_repetitions, train_to_be_scheduled, \
scheduling_train = True, train = train)
run_train.setName("running_route_" + routeName)
instanceList.append(run_train)
run_train.start()
scheduled[train] = True
trains_to_be_scheduled.pop(trains_to_be_scheduled.index(train))
if self.logLevel > 0: print "scheduled train ", train
if self.logLevel > 0: print "!!!!!!!!!!!!!!!!!!!!!run_trains finished"
if self.logLevel > 0: print "trains_to_be_scheduled ", trains_to_be_scheduled
if 'timebase' in globals():
if self.logLevel > 0: print "timebase.getRate()",timebase.getRate()
msecs_in_half_fast_minute = int(500.0 / float(str(fast_clock_rate)) * 60.0)
# noMsec = int(1000/timebase.getRate())
self.waitMsec(msecs_in_half_fast_minute) # twice every fast minute
def check_train_ok_to_start(self, train, train_block_name):
# check the scheduled train is in the starting block
if train_block_name == train.getDescription():
# print "returning true"
return True
else:
# print "returning false", "train_block_name", train_block_name, "train.getDescription()", train.getDescription()
return False