Files
JIMRI/jython/BlockOccupancyAnnouncer.py
T
2026-06-17 14:00:51 +02:00

93 lines
3.3 KiB
Python

# Listen to all sensors, printing an info line when they change state.
# If the sensor has a "matching" block, print some block detail and speak
# the most useful attributes audibly.
# This is useful for validating occupancy and block setup and wiring
#
# Author: mstevetodd, copyright 2013
# based on SensorLog.py and BlockLister.py
# Part of the JMRI distribution
import java
import java.beans
import jmri
# Define routine to map status numbers to text
def stateName(state) :
if (state == ACTIVE) :
return "ACTIVE"
if (state == INACTIVE) :
return "INACTIVE"
if (state == INCONSISTENT) :
return "INCONSISTENT"
if (state == UNKNOWN) :
return "UNKNOWN"
return "(invalid)"
# convert block state to english
def cvtBlockStateToText(state) :
rep = ""
if (state == jmri.Block.OCCUPIED) :
rep = rep + "Occupied "
if (state == jmri.Block.UNOCCUPIED) :
rep = rep + "Unoccupied "
return rep
# use external "nircmd" command to "speak" some text (I prefer this voice to eSpeak)
def speak(msg) :
#uncomment next line for speech (Jenkins doesn't like this command)
#java.lang.Runtime.getRuntime().exec('C:\\Progra~2\\nircmd\\nircmd speak text "' + msg +'"')
return
# Define the sensor listener:
# Print details on all sensor changes, and speak key blocks
# items if sensor is a block occupancy sensor
class SensorListener(java.beans.PropertyChangeListener):
def propertyChange(self, event):
if (event.propertyName == "KnownState") :
sensor_num = event.source.systemName[2:]
mesg = "Sensor "+event.source.systemName
if (event.source.userName != None) :
mesg += " ("+event.source.userName+")"
mesg += " from "+stateName(event.oldValue)
mesg += " to "+stateName(event.newValue)
#look for block based on our naming convention, and speak some info if found
block_name = "ILB" + sensor_num
b = blocks.getByUserName(block_name)
if (b != None) :
block_length = str(round(b.getLengthIn())).rstrip('0').rstrip('.') + " inches "
mesg += " for block " + block_name + ", " + block_length
#only speak for occupied blocks (cuts down on noise level)
if (b.getState() == jmri.Block.OCCUPIED) :
spoken_mesg = b.userName + " "
#spoken_mesg += cvtBlockStateToText(b.getState()) + ", "
spoken_mesg += block_length
speak(spoken_mesg)
print mesg
return
listener = SensorListener()
# Define a Manager listener. When invoked, a new
# item has been added, so go through the list of items removing the
# old listener and adding a new one (works for both already registered
# and new sensors)
class ManagerListener(java.beans.PropertyChangeListener):
def propertyChange(self, event):
list = event.source.getNamedBeanSet()
for sensor in list :
sensor.removePropertyChangeListener(listener)
sensor.addPropertyChangeListener(listener)
# Attach the sensor manager listener
sensors.addPropertyChangeListener(ManagerListener())
# For the sensors that exist, attach a sensor listener
list = sensors.getNamedBeanSet()
for i in list :
sensor.addPropertyChangeListener(listener)
speak("block occupancy announcer started")