134 lines
4.8 KiB
Python
134 lines
4.8 KiB
Python
# ExportLogixNG.py -- Export LogixNG definitions
|
|
|
|
# The details are at https://jmri.org/help/en/html/tools/logixng/ExportLogixNG.shtml
|
|
|
|
|
|
|
|
# The LogixNG content in the PanelPro xml data file looks simple but it is internally complex.
|
|
|
|
# The default is to use automatic system names. The format is xxxx:AUTO:nnnn. The xxxx is one of
|
|
# a couple dozen values. The nnnn is a sequential number. Since the system names are only unique
|
|
# within a xml data file, copying LogixNG content to another xml data file is impossible.
|
|
|
|
# The export process changes the system names to be unique. The AUTO keyword is replaced by a user
|
|
# supplied keyword. For example using XYZ, the result is that xxxx:AUTO:nnnn becomes xxxx$XYZ:nnnn.
|
|
# Notice that the first colon becomes a dollar character.
|
|
|
|
# The script has three prompts when started.
|
|
|
|
# 1 -- The input xml data file. If you want to export all of the LogixNG definitions, a current file
|
|
# can be used. If only some of the LogixNG definitions are to be exported, then some pre-processing
|
|
# is required. Except for the LogixNGs and/or Modules to be exported, the other LogixNGs, Modules,
|
|
# Tables and Global Variables need to be deleted. Also, the LogixNG clipboard should be emptied.
|
|
# After removing the other items, store the file with a new name. Select this file as the export
|
|
# input file.
|
|
|
|
# 2 -- The output xml data file. This file will be created or over written with no warnings. This
|
|
# is a PanelPro data file with the standard header and the LogixNG definitions. There are no other
|
|
# tables or panels. This file can be loaded after the normal data file. This results in adding the
|
|
# exported LogixNG definitions. This is a one time activity.
|
|
|
|
# 3 -- The alternate system name keyword.
|
|
|
|
# # # Warnings # # #
|
|
|
|
# The references in LogixNG definitions to other tables, such as sensors, turnouts, etc., are not
|
|
# changed. These will create errors if there are no matching entries in the normal tables.
|
|
|
|
# Any messages from the script will be on the JMRI system console.
|
|
|
|
# Author: Dave Sand, copyright 2024
|
|
# Part of the JMRI distribution.
|
|
|
|
import java
|
|
import jmri
|
|
|
|
from javax.swing import JFileChooser, JOptionPane
|
|
from javax.swing.filechooser import FileNameExtensionFilter
|
|
|
|
from org.slf4j import LoggerFactory
|
|
log = LoggerFactory.getLogger("jmri.jmrit.jython.exec.ExportLogixNG")
|
|
|
|
log.info('Run LogixNG Export v1.0')
|
|
|
|
inputFileName = None
|
|
outputFileName = None
|
|
newKeyword = None
|
|
|
|
header = True
|
|
logixNGs = False
|
|
lngItems = False
|
|
ready = True
|
|
|
|
lines = []
|
|
|
|
# Create a file chooser.
|
|
fc = JFileChooser(jmri.util.FileUtil.getUserFilesPath())
|
|
fc.setFileFilter(FileNameExtensionFilter("PanelPro XML Data File", ["xml"]));
|
|
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES)
|
|
|
|
# Select a XML file to be exported.
|
|
fc.setDialogTitle('Select Input XML Data File')
|
|
ret = fc.showOpenDialog(None)
|
|
if ret == JFileChooser.APPROVE_OPTION:
|
|
inputFileName = fc.getSelectedFile().toString()
|
|
if ret is None: ready = False
|
|
|
|
# Select a XML file to be created/replaced.
|
|
fc.setDialogTitle('Select Output XML Data File')
|
|
ret = fc.showSaveDialog(None)
|
|
if ret == JFileChooser.APPROVE_OPTION:
|
|
outputFileName = fc.getSelectedFile().toString()
|
|
if ret is None: ready = False
|
|
|
|
# Select the keyword to replace AUTO
|
|
newKeyword = JOptionPane.showInputDialog(
|
|
None,
|
|
'Enter the replacement keyword for AUTO',
|
|
'',
|
|
JOptionPane.PLAIN_MESSAGE);
|
|
if not newKeyword.isalnum():
|
|
log.error('"{}" is an invalid keyword'.format(newKeyword))
|
|
ready = False
|
|
|
|
if ready:
|
|
# Process each input line and add the retained lines to the 'lines' list.
|
|
with open(inputFileName) as infile:
|
|
for line in infile:
|
|
if header:
|
|
lines.append(line)
|
|
if '</jmriversion>' in line:
|
|
header = False
|
|
|
|
# Handle LogixNGs list
|
|
if not logixNGs:
|
|
if '<LogixNGs' in line:
|
|
logixNGs = True
|
|
|
|
if logixNGs:
|
|
lines.append(line)
|
|
if '</LogixNGs>' in line:
|
|
logixNGs = False
|
|
continue
|
|
|
|
# Handle remaining lines
|
|
if not lngItems:
|
|
if '<LogixNG' in line:
|
|
lngItems = True
|
|
|
|
if lngItems:
|
|
lines.append(line)
|
|
if '</LogixNG' in line:
|
|
lngItems = False
|
|
|
|
# Write each line from the "lines" list to the output file, finish with the final xml line.
|
|
with open(outputFileName, 'w') as outfile:
|
|
for line in lines:
|
|
outfile.write(line.decode("utf-8", "replace").replace(':AUTO:', '$' + newKeyword + ':').encode("utf-8"))
|
|
outfile.write('</layout-config>\n')
|
|
|
|
log.info('Export completed, AUTO replaced by {}, file {} has been created'.format(newKeyword.encode("ascii", "replace"), outputFileName.encode("ascii", "replace")))
|
|
else:
|
|
log.warn('Export aborted due to incomplete input')
|
|
|