Coverage for /home/pi/Software/model-railway-signalling/model_railway_signals/library/track_sensors.py: 97%

54 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-05 16:40 +0100

1#--------------------------------------------------------------------------------------------------- 

2# This module is used for creating and managing track sensor library objects on the canvas 

3#--------------------------------------------------------------------------------------------------- 

4# 

5# External API - classes and functions (used by the Schematic Editor): 

6#  

7# track_sensor_callback_type (tells the calling program what has triggered the callback): 

8# track_sensor_callback_type.sensor_triggered (the track sensor has been triggered) 

9#  

10# create_track_sensor - Creates a track sensior and returns a "tag" for all tkinter canvas drawing objects  

11# This allows the editor to move the track sensor object on the schematic as required 

12# Mandatory Parameters: 

13# Canvas - The Tkinter Drawing canvas on which the track sensor is to be displayed 

14# sensor_id:int - The unique ID for the track sensor 

15# x:int, y:int - Position of the point on the canvas (in pixels) 

16# callback - the function to call on track sensor triggered events 

17# 

18# track_sensor_exists(sensor_id:int) - returns true if the if a track sensor object 'exists' 

19# 

20# delete_track_sensor(sensor_id:int) - To delete the specified track sensor from the schematic 

21# 

22# Classes and functions used by the other library modules: 

23# 

24# track_sensor_triggered (sensor_id:int, callback_type=None) - Called on gpio_sensor trigger 

25# events if the gpio_sensor has been configured to generate a "track sensor passed" event 

26# 

27#--------------------------------------------------------------------------------------------------- 

28 

29import enum 

30import logging 

31import tkinter as Tk 

32from . import common 

33 

34#--------------------------------------------------------------------------------------------------- 

35# Public API classes (to be used by external functions) 

36#--------------------------------------------------------------------------------------------------- 

37 

38class track_sensor_callback_type(enum.Enum): 

39 sensor_triggered = 61 # The sensor has been triggered (by the user or an GPIO sensor) 

40 

41#--------------------------------------------------------------------------------------------------- 

42# Track Sensors are maintained in a global dictionary (with a key of 'sensor_id') 

43# Each dictionary entry (representing a track sensor) is a dictionary of key-value pairs: 

44# 'canvas' - The tkinter canvas (that the drawing objects are created on)  

45# 'callback' - The callback function to make on track sensor triggered events 

46# 'button' - A reference to the Tkinter Button object (to simulate 'sensor triggered' events) 

47# 'tags' - The tags applied to all canvas drawing objects for the Track Sensor instance 

48#--------------------------------------------------------------------------------------------------- 

49 

50track_sensors = {} 

51 

52#--------------------------------------------------------------------------------------------------- 

53# API Function to check if a Track Sensor library object exists (in the dictionary of Track Sensors) 

54#--------------------------------------------------------------------------------------------------- 

55 

56def track_sensor_exists(sensor_id:int): 

57 if not isinstance(sensor_id, int): 

58 logging.error("Track Sensor "+str(sensor_id)+": track_sensor_exists - Sensor ID must be an integer") 

59 sensor_exists = False 

60 else: 

61 sensor_exists = str(sensor_id) in track_sensors.keys() 

62 return (sensor_exists) 

63 

64#--------------------------------------------------------------------------------------------------- 

65# API function called from the gpio_sensors module on GPIO trigger events (if a gpio sensor has  

66# been configured to raise "track sensor passed" events). Also used internally to track sensor 

67# button press events (to simulate the "track sensor passed" event). 

68#--------------------------------------------------------------------------------------------------- 

69 

70def track_sensor_triggered (sensor_id:int, callback_type=None): 

71 if not isinstance(sensor_id, int): 

72 logging.error("Track Sensor "+str(sensor_id)+": track_sensor_triggered - Sensor ID must be an integer") 

73 elif not track_sensor_exists(sensor_id): 

74 logging.error("Track Sensor "+str(sensor_id)+": track_sensor_triggered - Sensor ID does not exist") 

75 else: 

76 logging.info("Track Sensor "+str(sensor_id)+": Track Sensor Passed Event ****************************************") 

77 # Pulse the button to provide a visual indication (but not if a shutdown has been initiated) 

78 if not common.shutdown_initiated: 78 ↛ 82line 78 didn't jump to line 82, because the condition on line 78 was never false

79 track_sensors[str(sensor_id)]["button"].config(bg="red") 

80 common.root_window.after(1000,lambda:reset_sensor_button(sensor_id)) 

81 # Make the external callback specified for the track sensor 

82 callback = track_sensors[str(sensor_id)]["callback"] 

83 callback(sensor_id, track_sensor_callback_type.sensor_triggered) 

84 return () 

85 

86def reset_sensor_button (sensor_id:int): 

87 if track_sensor_exists(sensor_id): track_sensors[str(sensor_id)]["button"].config(bg=common.bgraised) 

88 

89#--------------------------------------------------------------------------------------------------- 

90# API Function to create a Track Sensor library object on the schematic 

91#--------------------------------------------------------------------------------------------------- 

92 

93def create_track_sensor(canvas, sensor_id:int, x:int, y:int, callback): 

94 global track_sensors 

95 # Set a unique 'tag' to reference the tkinter drawing objects 

96 canvas_tag = "sensor"+str(sensor_id) 

97 if not isinstance(sensor_id, int) or sensor_id < 1: 

98 logging.error("Track Sensor "+str(sensor_id)+": create_track_sensor - Sensor ID must be a positive integer") 

99 elif track_sensor_exists(sensor_id): 

100 logging.error("Track Sensor "+str(sensor_id)+": create_track_sensor - Sensor ID already exists") 

101 else: 

102 logging.debug("Track Sensor "+str(sensor_id)+": Creating library object on the schematic") 

103 # Create the new drawing objects (tagged with the canvas_tag) - the oval is to give us 

104 # a reasonable selection area when we subsequently get the bbox of the tagged objects 

105 sensor_button = Tk.Button(canvas, text="O", padx=1, pady=1, font=('Courier',2,"normal")) 

106 sensor_button.config(command=lambda:track_sensor_triggered(sensor_id)) 106 ↛ exitline 106 didn't run the lambda on line 106

107 canvas.create_window(x, y, window=sensor_button, tags=canvas_tag) 

108 canvas.create_oval(x-15, y-15, x+15, y+15, outline="grey60", tags=canvas_tag) 

109 # Store the details of the Track Sensor Object in the dictionary of Track Sensors 

110 track_sensors[str(sensor_id)] = {} 

111 track_sensors[str(sensor_id)]['canvas'] = canvas 

112 track_sensors[str(sensor_id)]['button'] = sensor_button 

113 track_sensors[str(sensor_id)]['callback'] = callback 

114 track_sensors[str(sensor_id)]['tags'] = canvas_tag 

115 # Return the canvas_tag for the tkinter drawing objects 

116 return(canvas_tag) 

117 

118#--------------------------------------------------------------------------------------------------- 

119# Function to delete a Track Sensor library object from the schematic 

120#--------------------------------------------------------------------------------------------------- 

121 

122def delete_track_sensor(sensor_id:int): 

123 global track_sensors 

124 if not isinstance(sensor_id, int): 

125 logging.error("Track Sensor "+str(sensor_id)+": delete_track_sensor - Sensor ID must be an integer") 

126 elif not track_sensor_exists(sensor_id): 

127 logging.error("Track Sensor "+str(sensor_id)+": delete_track_sensor - Sensor ID does not exist") 

128 else: 

129 logging.debug("Track Sensor "+str(sensor_id)+": Deleting library object from the schematic") 

130 # Delete all tkinter drawing objects 

131 track_sensors[str(sensor_id)]['canvas'].delete(track_sensors[str(sensor_id)]["tags"]) 

132 track_sensors[str(sensor_id)]['button'].destroy() 

133 # Delete the track sensor entry from the dictionary of track sensors 

134 del track_sensors[str(sensor_id)] 

135 return() 

136 

137#####################################################################################################