Skip to content
Permalink
Browse files

Add custom properts to Loconet Turnout

1 - BypassBushby - when true OPC_SW_ACK is used, this passes thru the CS when Bushby bit is set.
2 - SendOnAndOff - when false only the turn out ON is sent, the default for loconet is currently to send
                   an ON followed by an OFF. For UlenB if set to true it wil send ON followed by OFF.
  • Loading branch information...
Pugwash1 committed May 21, 2019
1 parent 516b238 commit d165dfdba9a1ea71d55bf0d15ac2b8e104c1fcd8
@@ -81,6 +81,11 @@ public LnTurnout(String prefix, int number, LocoNetInterface controller) throws
*/
boolean feedbackDeliberatelySet = false; // package to allow access from LnTurnoutManager

@Override
public void setBinaryOutput(boolean state) {
// TODO Auto-generated method stub
binaryOutput = state;
}
@Override
public void setFeedbackMode(@Nonnull String mode) throws IllegalArgumentException {
feedbackDeliberatelySet = true;
@@ -129,14 +134,30 @@ public void setUseOffSwReqAsConfirmation(boolean state) {
_useOffSwReqAsConfirmation = state;
}

public boolean isByPassBushbyBit() {
if (getProperty(LnTurnoutManager.BYPASSBUSHBYBITKEY) != null) {
return (boolean) getProperty(LnTurnoutManager.BYPASSBUSHBYBITKEY) ;
} else {
return false;
}
}

public boolean isSendOnAndOff() {
if (getProperty(LnTurnoutManager.SENDONANDOFFKEY) != null) {
return (boolean) getProperty(LnTurnoutManager.SENDONANDOFFKEY) ;
} else {
return !binaryOutput;
}
}

// Handle a request to change state by sending a LocoNet command
@Override
protected void forwardCommandChangeToLayout(final int newstate) {

// send SWREQ for close/thrown ON
sendOpcSwReqMessage(adjustStateForInversion(newstate), true);
// schedule SWREQ for closed/thrown off, unless in basic mode
if (!binaryOutput) {
if (isSendOnAndOff()) {
meterTask = new java.util.TimerTask() {
int state = newstate;

@@ -165,7 +186,11 @@ public void run() {
*/
void sendOpcSwReqMessage(int state, boolean on) {
LocoNetMessage l = new LocoNetMessage(4);
l.setOpCode(LnConstants.OPC_SW_REQ);
if (isByPassBushbyBit()) {
l.setOpCode(LnConstants.OPC_SW_ACK);
} else {
l.setOpCode(LnConstants.OPC_SW_REQ);
}

// compute address fields
int hiadr = (_number - 1) / 128;
@@ -236,6 +261,7 @@ void sendSetOffMessage(int state) {
public void message(LocoNetMessage l) {
// parse message type
switch (l.getOpCode()) {
case LnConstants.OPC_SW_ACK:
case LnConstants.OPC_SW_REQ: {
/* page 9 of Loconet PE */

@@ -1,6 +1,12 @@
package jmri.jmrix.loconet;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.*;
import jmri.BooleanPropertyDescriptor;
import jmri.NamedBean;
import jmri.NamedBeanPropertyDescriptor;

import jmri.Turnout;
import jmri.managers.AbstractTurnoutManager;
import org.slf4j.Logger;
@@ -238,6 +244,40 @@ public String getEntryToolTip() {
return entryToolTip;
}

public static final String BYPASSBUSHBYBITKEY = "Bypass Bushby Bit";
public static final String SENDONANDOFFKEY = "Send ON/OFF";

/**
* {@inheritDoc}
*/
@Override
public List<NamedBeanPropertyDescriptor<?>> getKnownBeanProperties() {
List<NamedBeanPropertyDescriptor<?>> l = new ArrayList<>();
l.add(new BooleanPropertyDescriptor(BYPASSBUSHBYBITKEY, false) {
@Override
public String getColumnHeaderText() {
return Bundle.getMessage("LnByPassBushbyHeader");
}

@Override
public boolean isEditable(NamedBean bean) {
return bean.getClass().getName().contains("LnTurnout");
}
});
l.add(new BooleanPropertyDescriptor(SENDONANDOFFKEY, _binaryOutput ? false : true) {
@Override
public String getColumnHeaderText() {
return Bundle.getMessage("SendOnOffHeader");
}

@Override
public boolean isEditable(NamedBean bean) {
return bean.getClass().getName().contains("LnTurnout");
}
});
return l;
}

private final static Logger log = LoggerFactory.getLogger(LnTurnoutManager.class);

}
@@ -102,6 +102,9 @@ LN_MSG_SENSOR_STATE_HIGH = High
# LnTurnout (Add to table pane) items
AddOutputEntryToolTip = enter a number from 1 to 2048 (inclusive).
AddInputEntryToolTip = enter a number from 1 to 2048 (inclusive).
# LnTurnout additional properties.
LnByPassBushbyHeader = Bypass Bushby Bit
SendOnOffHeader = Send ON and OFF

# cmdstnconfig shared Bundle items (hardware specific strings fetched using ResourceBundle)
TitleXConfig = Configure {0}
@@ -75,6 +75,25 @@ public void checkIncoming() {
lnis.sendTestMessage(m);
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}
@Test
public void checkIncomingWithAck() {
// notify the Ln that somebody else changed it...using OPC_SW_ACK
LocoNetMessage m = new LocoNetMessage(4);
m.setOpCode(0xbd);
m.setElement(1, 0x14); // set CLOSED
m.setElement(2, 0x30);
m.setElement(3, 0x00);
lnis.sendTestMessage(m);
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.CLOSED);

m = new LocoNetMessage(4);
m.setOpCode(0xbd);
m.setElement(1, 0x14); // set THROWN
m.setElement(2, 0x10);
m.setElement(3, 0x00);
lnis.sendTestMessage(m);
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}

// LnTurnout test for incoming status message
@Test
@@ -101,6 +120,32 @@ public void testLnTurnoutStatusMsg() {

}

// LnTurnout test for incoming status message
@Test
public void testLnTurnoutStatusMsgAck() {
// prepare an interface
// set closed
try {
t.setProperty(LnTurnoutManager.BYPASSBUSHBYBITKEY, true);
t.setCommandedState(jmri.Turnout.THROWN);
} catch (Exception e) {
log.error("TO exception: " + e);
}
Assert.assertTrue(lnis.outbound.elementAt(0)
.toString().equals("BD 14 10 00")); // thrown loconet message
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);

// notify the Ln that somebody else changed it...
LocoNetMessage m = new LocoNetMessage(4);
m.setOpCode(0xb1);
m.setElement(1, 0x14); // set thrown
m.setElement(2, 0x10);
m.setElement(3, 0x7b);
lnis.sendTestMessage(m);
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);

}

// LnTurnout test for exact feedback
@Test
public void testLnTurnoutExactFeedback() {
@@ -255,6 +300,63 @@ public void testBasicSet() throws InterruptedException {
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}

// test that only one message is sent when property SendOnAndOff is false.
@Test
public void testPropertySet() throws InterruptedException {
t.setBinaryOutput(false);
t.setProperty(LnTurnoutManager.SENDONANDOFFKEY, false);
t.setCommandedState(jmri.Turnout.THROWN);

// Make sure that timed message has fired by waiting
synchronized (this) {
this.wait(LnTurnout.METERINTERVAL + 25);
}

// check for messages
Assert.assertTrue("just one messages", lnis.outbound.size() == 1);
Assert.assertEquals(lnis.outbound.elementAt(lnis.outbound.size() - 1).toString(),
"B0 14 10 00"); // THROWN/ON loconet message
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}

// test that only two messages are sent when property SendOnAndOff is true.
@Test
public void testPropertySet1() throws InterruptedException {
t.setBinaryOutput(false);
t.setProperty(LnTurnoutManager.SENDONANDOFFKEY, true);
t.setCommandedState(jmri.Turnout.THROWN);

// Make sure that timed message has fired by waiting
synchronized (this) {
this.wait(LnTurnout.METERINTERVAL + 25);
}

// check for messages
Assert.assertTrue("just two messages", lnis.outbound.size() == 2);
Assert.assertEquals(lnis.outbound.elementAt(lnis.outbound.size() - 1).toString(),
"B0 14 00 00"); // THROWN/OFF loconet message
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}

// test that only two messages are sent when property SendOnAndOff is true, even if (ulenbook) binary set.
@Test
public void testPropertySet2() throws InterruptedException {
t.setBinaryOutput(true);
t.setProperty(LnTurnoutManager.SENDONANDOFFKEY, true);
t.setCommandedState(jmri.Turnout.THROWN);

// Make sure that timed message has fired by waiting
synchronized (this) {
this.wait(LnTurnout.METERINTERVAL + 25);
}

// check for messages
Assert.assertTrue("just two messages", lnis.outbound.size() == 2);
Assert.assertEquals(lnis.outbound.elementAt(lnis.outbound.size() - 1).toString(),
"B0 14 00 00"); // THROWN/OFF loconet message
Assert.assertTrue(t.getCommandedState() == jmri.Turnout.THROWN);
}

LocoNetInterfaceScaffold lnis;
LocoNetSystemConnectionMemo memo;

@@ -1,6 +1,13 @@
package jmri.jmrix.loconet.configurexml;

import jmri.Turnout;
import jmri.jmrix.loconet.LnTurnout;
import jmri.jmrix.loconet.LnTurnoutManager;
import jmri.jmrix.loconet.LocoNetInterfaceScaffold;
import jmri.jmrix.loconet.LocoNetSystemConnectionMemo;
import jmri.util.JUnitUtil;

import org.jdom2.Element;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -18,14 +25,61 @@ public void testCtor(){
Assert.assertNotNull("LnTurnoutManagerXml constructor", new LnTurnoutManagerXml());
}

@Test
public void testSaveAndRestoreWithProperties() {
LnTurnoutManagerXml lntmXml = new LnTurnoutManagerXml();
LnTurnout lnto = (LnTurnout) lmtm.newTurnout("LT61", "UNAMEt61");
// check defaults UlenB binaryoutput true
lnto.setBinaryOutput(true);
Assert.assertFalse("Bypass is false",lnto.isByPassBushbyBit());
Assert.assertFalse("SendOnOff is false",lnto.isSendOnAndOff());

// check defaults Loconet binaryoutput false
lnto.setBinaryOutput(false);
Assert.assertFalse("Bypass is false",lnto.isByPassBushbyBit());
Assert.assertTrue("SendOnOff is true",lnto.isSendOnAndOff());

// update defaults
lnto.setProperty(LnTurnoutManager.SENDONANDOFFKEY, false);
lnto.setProperty(LnTurnoutManager.BYPASSBUSHBYBITKEY, true);
Assert.assertTrue("Bypass is true",lnto.isByPassBushbyBit());
Assert.assertFalse("SendOnOff is false",lnto.isSendOnAndOff());
Element stored = lntmXml.store(lmtm);
Assert.assertNotNull(stored);
jmri.InstanceManager.getDefault().clearAll();
jmri.InstanceManager.setTurnoutManager(lmtm);

lntmXml.load(stored, null);
LnTurnout t = (LnTurnout) lmtm.getBySystemName("LT61");
Assert.assertNotNull(t);
Assert.assertTrue("Bypass is true",t.isByPassBushbyBit());
Assert.assertFalse("SendOnOff is false",t.isSendOnAndOff());
}

LocoNetInterfaceScaffold lnis;
LocoNetSystemConnectionMemo memo;
LnTurnoutManager lmtm;

// The minimal setup for log4J
@Before
public void setUp() {
JUnitUtil.setUp();
// prepare an interface
jmri.util.JUnitUtil.setUp();
jmri.util.JUnitUtil.resetInstanceManager();
// prepare an interface, register
memo = new LocoNetSystemConnectionMemo("L", "LocoNet");
lnis = new LocoNetInterfaceScaffold(memo);
// create and register the manager object
lmtm = new LnTurnoutManager(lnis, lnis, memo.getSystemPrefix(), false);
jmri.InstanceManager.setTurnoutManager(lmtm);
}

@After
public void tearDown() {
memo.dispose();
lnis = null;
lmtm = null;
JUnitUtil.tearDown();
}

0 comments on commit d165dfd

Please sign in to comment.
You can’t perform that action at this time.