06 Výhybka, snímač, návěstidlo…
Ukázky práce s nejčastěji používanými objekty ve skriptech.
Výhybky
Příklad práce s objektem typu výhybka. Výhybka může nabývat stavy s následujícími hodnotami:
UNKNOWN = 1
INCONSISTENT = 8
CLOSED = 2
THROWN = 4
Vzorový skript zjistí aktuální polohu výhybky a přestaví ji do opačné polohy.
# vyhybka_prehodit.py
import jmri
v1 = turnouts.provideTurnout("V1")
v2 = turnouts.provideTurnout("V2")
v3 = turnouts.provideTurnout("V3")
v4 = turnouts.provideTurnout("V4")
if (v2.getState() == CLOSED) :
v2.setState(THROWN)
else :
v2.setState(CLOSED)
Snímače
Příklad práce s objektem typu snímač. Snímač může nabývat stavy s následujícími hodnotami:
UNKNOWN = 1
INCONSISTENT = 8
ACTIVE = 2
INACTIVE = 4
Ukázkový skript otestuje u všech snímačů stav. Pokud jsou ve stavu Neznámý, tak je přestaví do stavu Neaktivní. Skript je dodán s aplikací jako vzorový http://jmri.org/jython/SetAllUnknownSensorsToInactive.py.
# Script to set all sensors with state UNKNOWN to INACTIVE
# This is particularly useful in simulator mode, when hardware sensors aren't updated
#
# Part of the JMRI distribution
import jmri
sCnt = 0
chgCnt = 0
# loop thru defined sensors, if UNKNOWN, set to INACTIVE
list = sensors.getNamedBeanSet()
for s in list :
sCnt += 1
cs = s.getKnownState()
if cs == UNKNOWN :
chgCnt += 1
s.setKnownState(INACTIVE)
print str(sCnt) + " sensors found, " + str(chgCnt) + " changed to INACTIVE"
Paměťová proměnná
Příklad práce s objektem typu paměťová proměnná. Paměť může obsahovat libovolnou hodnotu. Doporučuji se omezit pouze na hodnoty typu celé číslo a textový řetězec. V našem příkladu použijeme dvě proměnné. Jedna bude typu celé číslo a druhá bude typu textový řetězec.
Práce s proměnnou typu číslo. Do paměťové proměnné můžeme zapisovat/číst hodnoty dvěma způsoby. Pomocí metod setValue()/getValue() může být argumentem libovolná hodnota. Při použití metod setState()/getState() může být argumentem pouze číslo. Vzorový skript:
# pametCislo.py
import jmri
promennaCislo = memories.provideMemory("promennaCislo")
print "původní hodnota getValue() ".decode("UTF-8"), promennaCislo.getValue()
print "původní hodnota getState() ".decode("UTF-8"), promennaCislo.getState()
promennaCislo.setValue("2")
print "nová hodnota setValue('2') ".decode("UTF-8"), promennaCislo.getState()
promennaCislo.setState(3)
print "nová hodnota setState(3) ".decode("UTF-8"), promennaCislo.getState()
promennaCislo.setValue("rst")
print "nová hodnota setValue('rst')".decode("UTF-8"), promennaCislo.getValue()
promennaCislo.setState("uvw")
print "nová hodnota setState('uvw')".decode("UTF-8"), promennaCislo.getValue()
Při spuštění vzorového skriptu bude výsledek následující:
původní hodnota getValue() 1
původní hodnota getState() 1
nová hodnota setValue('2') 2
nová hodnota setState(3) 3
nová hodnota setValue('rst') rst
Původní hodnota proměnné byla 1. Je jedno, zdali ji získáme metodou getState() nebo getValue(). Pokud nastavíme hodnotu poměnné pomocí setValue(“2”) bude uloženo číslo 2. Pokud nastavíme hodnotu poměnné pomocí setState(3) bude uloženo číslo 3. Pokud nastavíme hodnotu poměnné pomocí setValue(“rst”) dojde k přetypování proměnné a bude uložen řetězec rst. Na přetypování číselné proměnné si musíme dávat pozor. Pokud se pokusíme nastavit číselný typ pomocí metody setState(“uvw”) dojde k běhové chybě. Nová hodnota se neuloží a v Systémové konzoli se zobrazí chybové hlášení:
2019-07-27 08:59:38,906 jython.InputWindow ERROR - Error executing script [AWT-EventQueue-0]
javax.script.ScriptException: TypeError: setState(): 1st arg can't be coerced to int in <script> at line number 12
at
...
Caused by: Traceback (most recent call last):
File "<script>", line 12, in <module>
TypeError: setState(): 1st arg can't be coerced to int
at
...
Práce s proměnnou typu text. Do paměťové proměnné můžeme zapisovat/číst hodnoty pouze jedním způsobem, a to pomocí metod setValue()/getValue(). Argumentem může být libovolný textový řetězec. Vzorový skript:
# pametText.py
import jmri
promennaText = memories.provideMemory("promennaText")
print "původní hodnota getValue() ".decode("UTF-8"), promennaText.getValue()
promennaText.setValue("xyz")
print "nová hodnota setValue('xyz') ".decode("UTF-8"), promennaText.getValue()
print "pokus získat číslo getState()".decode("UTF-8"), promennaText.getState()
Při spuštění vzorového skriptu bude výsledek následující:
původní hodnota getValue() abc
nová hodnota setValue('xyz') xyz
pokus získat číslo getState() -1
Původní hodnota proměnné byla abc. Hodnotu jsme získali metodou getValue(). Metodou setValue(“xyz”) jsme nastavili novou hodnotu xyz. Při pokusu přečíst číslo metodou getState() získáme konstantu -1, která značí, že v proměnné není číslo. K žádné běhové chybě nedojde.
Návěstidlo
Příklad práce s objektem typu návěstidlo. V tabulce návěstidel si vytvoříme dvě návěstidla. Oddílové návěstidlo So a jeho předvěst PřSo.
Návěstidla budou používat návěstní systém ČSD 1962 základní návěstidla http://jmri.org/xml/signals/CSD-1962-zakladni/index.shtml. Jedno bude typu Oddílová návěstidla a druhé bude typu Předvěsti oddílové.
Ve skriptu návěstidla získáme metodou getSignalMast(). Argumentem je buď uživatelský nebo systémový název.
# navestidlo.py
import jmri
navestidlo_So = masts.getSignalMast("So")
navestidlo_PrSo = masts.getSignalMast("PřSo".decode("UTF-8"))
print navestidlo_So.getUserName(), navestidlo_So.getSystemName()
print navestidlo_PrSo.getUserName(), navestidlo_PrSo.getSystemName()
Výsledek skriptu je následující:
So LF$dsm:CSD-1962-zakladni:block(101)
PřSo LF$dsm:CSD-1962-zakladni:block_distant(102)
Kromě uživatelského a systémového názvu můžeme u návěstidla zjišťovat další vlastnosti. Například zjistíme jaký návěstní systém jsme návěstidlu přiřadili:
# navestidlo_2.py
import jmri
navestidlo_So = masts.getSignalMast("So")
system_navesti = navestidlo_So.getSignalSystem()
print system_navesti.getUserName()
print system_navesti.getSystemName()
Výsledek podle očekávání je:
ČSD 1962 základní návěstidla
CSD-1962-zakladni
U návěstního systému můžeme zjišťovat jaké všechny návěsti obsahuje:
# navestidlo_3.py
import jmri
navestidlo_So = masts.getSignalMast("So")
system_navesti = navestidlo_So.getSignalSystem()
vsechny_navesti = systemNavesti.getAspects()
for jedna_navest in vsechny_navesti :
print jedna_navest
Výsledek opět nepřekvapí:
Stůj
Volno
Výstraha
Očekávej 40
Očekávej 60
Očekávej 80
Rychlost 40 a volno
Rychlost 40 a výstraha
Rychlost 40 a očekávej 40
Rychlost 40 a očekávej 60
Rychlost 40 a očekávej 80
Rychlost 60 a volno
Rychlost 60 a výstraha
Rychlost 60 a očekávej 40
Rychlost 60 a očekávej 60
Rychlost 60 a očekávej 80
Rychlost 80 a volno
Rychlost 80 a výstraha
Rychlost 80 a očekávej 40
Rychlost 80 a očekávej 60
Rychlost 80 a očekávej 80
Opakovaná volno
Opakovaná výstraha
Opakovaná očekávej 40
Opakovaná očekávej 60
Opakovaná očekávej 80
Zhasnuto
Posun zakázán
Posun dovolen
Posun dovolen - nezabezpečený
Opatrně na přivolávací návěst bez červené
Opatrně na přivolávací návěst
Podobně se můžeme zeptat návěstidla které návěsti může používat a které návěsti jsou u konkrétního návěstidla zakázané:
# navestidlo_4.py
import jmri
navestidlo_So = masts.getSignalMast("So")
mapa_navesti = navestidlo_So.getValidAspects()
for navest in mapa_navesti :
print navest, navestidlo_So.isAspectDisabled(navest)
V našem případě jsou povolené pouze dvě návěsti a žádná z nich není zakázaná:
Stůj False
Volno False
U návěstidla můžeme přečíst aktuální návěst a libovolnou návěst nastavit:
# navestidlo_5.py
import jmri
navest_Stuj = "Stůj".decode("UTF-8")
navest_Volno = "Volno"
navest_Vystraha = "Výstraha".decode("UTF-8")
navestidlo_So = masts.getSignalMast("So")
navestidlo_PrSo = masts.getSignalMast("PřSo".decode("UTF-8"))
print navestidlo_So.getUserName(), navestidlo_So.getAspect()
print navestidlo_PrSo.getUserName(), navestidlo_PrSo.getAspect()
navestidlo_So.setAspect(navest_Stuj)
navestidlo_PrSo.setAspect(navest_Vystraha)
print navestidlo_So.getUserName(), navestidlo_So.getAspect()
print navestidlo_PrSo.getUserName(), navestidlo_PrSo.getAspect()
Výsledek je opět podle očekávání:
So None
PřSo None
So Stůj
PřSo Výstraha
Blok
Příklad práce s objektem typu blok. Blok je úsek koleje. Pokud je k bloku připojen snímač detekce obsazení, tak můžeme sledovat obsazenost daného bloku. Bloky jsou definovány v tabulce bloků.
Blok může nabývat stavy s následujícími hodnotami:
UNKNOWN = 1
INCONSISTENT = 8
OCCUPIED = 2
UNOCCUPIED = 4
UNDETECTED = 16
Vzorový skript zjistí aktuální stav bloku.
# blok.py
import jmri
blok_1 = blocks.getBlock("BK1")
blok_2 = blocks.getBlock("BK2")
blok_3 = blocks.getBlock("BK3")
blok_4 = blocks.getBlock("BK4")
print blok_1.getUserName(), blok_1.getSystemName(), blok_1.getState()
print blok_2.getUserName(), blok_2.getSystemName(), blok_2.getState()
print blok_3.getUserName(), blok_3.getSystemName(), blok_3.getState()
print blok_4.getUserName(), blok_4.getSystemName(), blok_4.getState()
Výsledek vypadá následovně:
BK1 IB1 4
BK2 IB:AUTO:0001 4
BK3 IB:AUTO:0002 4
BK4 IB:AUTO:0003 4
Layout blok
Příklad práce s objektem typu Layout blok. Layout blok je je blok, který je použit v Layout Editoru. Layout blok rozšiřuje vlastnosti bloku. Layout blok může nabývat stavy s následujícími hodnotami:
UNKNOWN = 1
OCCUPIED = 2
EMPTY = 4
RESERVED = 8
Vzorový skript zjistí aktuální stav bloku:
# layout_blok.py
import jmri
layout_bloky = layoutblocks.getNamedBeanSet()
for lb in layout_bloky :
print lb.getUserName(), lb.getSystemName(), lb.getOccupancy(), lb.getUseExtraColor()
Výsledek může vypadat takto:
BK1 ILB1 2 False
BK2 ILB2 4 True
BK3 ILB3 4 True
BK4 ILB4 4 False
Layout blok BK1 je ve stavu 2, tedy je obsazený. Ostatní bloky jsou ve stavu 4, tedy volné. V Layout Editoru mohou být volné bloky ve dvou dalších stavech. Buď je blok neobsazený nebo může být blok v postavené vlakové cestě. Pokud je blok v postavené cestě, potom ze zobrazen na panelu v odlišné barvě.
Další objekty
Ve výše uvedeném návodu je popsán přístup k nejčastěji používaným objektům. Zástupci k dalším objektům jsou uvedeny v souboru jmri_bindings.py http://jmri.org/jython/jmri_bindings.py. Se znalostí programování a zdrojového kódu JMRI je pak možno přistupovat i k dalším objektům, které zde nebyly uvedeny.
vytvořeno 19. 9. 2019