189 lines
6.5 KiB
Python
189 lines
6.5 KiB
Python
# Persist the values of memory variables between sessions.
|
|
#
|
|
# Values are saved to a .csv file at shutdown and re-instated from said .csv file
|
|
# when script is launched.
|
|
#
|
|
# This script is based on TurnoutStatePersistence.py.
|
|
# Author: Dave Sand, copyright 2025
|
|
# Part of the JMRI distribution
|
|
#
|
|
|
|
import jmri
|
|
import java
|
|
|
|
import org.apache.commons.csv
|
|
from org.slf4j import LoggerFactory
|
|
|
|
# Define memory values file
|
|
# Default is 'MemoryValues.csv' stored in the user files location.
|
|
memoryFile = jmri.util.FileUtil.getUserFilesPath() + "MemoryValues.csv"
|
|
|
|
# -------------------------- Notes ----------------------
|
|
# Memory variable values can be any type of object. String objects are stored as is. Null values are
|
|
# stored as the word "None" and the word is used during loading. Other objects store the object
|
|
# reference which has no usable value when loaded.
|
|
|
|
# Copy this script to the profile's user files location and modify the "memoryNames" list.
|
|
# Append the system or user name of each memory variable value to be retained.
|
|
memoryNames = []
|
|
memoryNames.append('IMRATEFACTOR')
|
|
# memoryNames.append('nullTest')
|
|
# memoryNames.append('objTest')
|
|
|
|
# The script needs to be run after loading the layout data xml file so that the stored values replace
|
|
# any values in the layout data xml file.
|
|
|
|
# Define task to persist memory values at shutdown
|
|
class PersistMemoryValuesTask(jmri.implementation.AbstractShutDownTask):
|
|
|
|
# Get reference to the logger
|
|
#
|
|
# This reference is unique to instances of this class, hence the use of
|
|
# 'self.log' whenever it needs to be used
|
|
#
|
|
# The logger has been instantiated within the pseudo package:
|
|
# 'jmri.jmrit.jython.exec'
|
|
# This allows for easy identification and configuration of logging.
|
|
#
|
|
# NOTE: to enable logging, see https://www.jmri.org/help/en/html/apps/Debug.shtml
|
|
# Add the Logger Category name "jmri.jmrit.jython.exec" at DEBUG Level.
|
|
|
|
log = LoggerFactory.getLogger("jmri.jmrit.jython.exec.MemoryValuePersistence.PersistMemoryValuesTask")
|
|
|
|
# Define task to run at ShutDown
|
|
def run(self):
|
|
|
|
# Write an info entry to the log
|
|
self.log.info("Write memory values to file: '%s'" % memoryFile)
|
|
|
|
# Open file
|
|
|
|
csvFormat = org.apache.commons.csv.CSVFormat.Builder.create(org.apache.commons.csv.CSVFormat.DEFAULT).setCommentMarker('#').build()
|
|
csvFile = org.apache.commons.csv.CSVPrinter(java.io.FileWriter(memoryFile), csvFormat)
|
|
|
|
# Initialise counter
|
|
memoryCount = 0
|
|
|
|
# Write header
|
|
csvFile.print("System Name")
|
|
csvFile.print("User Name")
|
|
csvFile.print("Comment")
|
|
csvFile.print("Saved Value")
|
|
csvFile.println()
|
|
|
|
# Loop through all listed memories
|
|
for memoryName in memoryNames:
|
|
mem = memories.getMemory(memoryName)
|
|
if mem is None:
|
|
self.log.warn("Memory variable, {}, not found", memoryName)
|
|
continue
|
|
|
|
# Write a debug entry to the log
|
|
if (self.log.isDebugEnabled()):
|
|
self.log.debug("Storing memory value for {}", mem.getSystemName())
|
|
|
|
# Retrieve details to persist
|
|
csvFile.print(mem.getSystemName())
|
|
csvFile.print(mem.getUserName())
|
|
csvFile.print(mem.getComment())
|
|
csvFile.print(str(mem.getValue()))
|
|
|
|
# Notify end of record
|
|
csvFile.println()
|
|
|
|
# Increment counter
|
|
memoryCount += 1
|
|
|
|
# Write an info entry to the log
|
|
self.log.info("Stored values of %d memory variables" % memoryCount)
|
|
|
|
# Append a comment to the end of the file
|
|
csvFile.printComment("Written by JMRI version %s on %s" % (jmri.Version.name(), (java.util.Date()).toString()))
|
|
|
|
# Flush the write buffer and close the file
|
|
csvFile.flush()
|
|
csvFile.close()
|
|
|
|
# All done
|
|
return
|
|
|
|
# Define task to load memory values at script start
|
|
#
|
|
# This is implemented as a separate class so that it can run on a
|
|
# different thread in the background rather than holding up the main
|
|
# thread while executing
|
|
class LoadMemoryValues(jmri.jmrit.automat.AbstractAutomaton):
|
|
|
|
# Get reference to the logger
|
|
log = LoggerFactory.getLogger("jmri.jmrit.jython.exec.MemoryValuePersistence.LoadMemoryValues")
|
|
|
|
# Perform any initialisation
|
|
def init(self):
|
|
return
|
|
|
|
# Define task to run
|
|
def handle(self):
|
|
|
|
# Retrieve the values file as a File object
|
|
inFile = java.io.File(memoryFile)
|
|
|
|
# Check if state file exists
|
|
if inFile.exists():
|
|
|
|
# It does, so load it
|
|
csvFormat = org.apache.commons.csv.CSVFormat.Builder.create(org.apache.commons.csv.CSVFormat.DEFAULT).setHeader().setCommentMarker('#').build()
|
|
csvFile = org.apache.commons.csv.CSVParser.parse(inFile, java.nio.charset.StandardCharsets.UTF_8, csvFormat)
|
|
|
|
# Write an info entry to the log
|
|
self.log.info("Loading memory values file: %s" % memoryFile)
|
|
|
|
# Initialise counter
|
|
memoryCount = 0
|
|
|
|
# Loop through each record
|
|
for record in csvFile.getRecords():
|
|
|
|
# Read the record details
|
|
systemName = record.get("System Name")
|
|
userName = record.get("User Name")
|
|
comment = record.get("Comment")
|
|
savedValue = record.get("Saved Value")
|
|
|
|
# Get reference to the memory variable
|
|
memory = memories.provideMemory(systemName)
|
|
|
|
# Write a debug entry to the log
|
|
if (self.log.isDebugEnabled()):
|
|
self.log.debug("Setting value of memory: %s" % systemName)
|
|
|
|
# Set other parameters if specified
|
|
if (userName != ""):
|
|
memory.setUserName(userName)
|
|
if (comment != ""):
|
|
memory.setComment(comment)
|
|
|
|
# Finally, set the value
|
|
memory.setValue(savedValue)
|
|
|
|
# Increment counter
|
|
memoryCount += 1
|
|
|
|
# Close the file
|
|
csvFile.close()
|
|
|
|
# Write an info entry to the log
|
|
self.log.info("Loaded value of %d memory variables" % memoryCount)
|
|
|
|
else:
|
|
# It doesn't, so log this fact and carry on
|
|
self.log.warn("Memory values file '%s' does not exist" % memoryFile)
|
|
|
|
# All done
|
|
return False # Only need to run once
|
|
|
|
# Register the memory value persistence shutdown task
|
|
shutdown.register(PersistMemoryValuesTask("PersistMemoryValues"))
|
|
|
|
# Launch the load task
|
|
LoadMemoryValues().start()
|