001package jmri.jmrix.roco.z21; 002 003import jmri.Sensor; 004import jmri.implementation.AbstractSensor; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007 008/** 009 * Extend jmri.AbstractSensor for RocoMotion (RM) bus sensors on 010 * the Roco Z21. 011 * 012 * @author Paul Bender Copyright (C) 2018 013 */ 014public class Z21RMBusSensor extends AbstractSensor implements Z21Listener { 015 016 private boolean statusRequested = false; 017 018 private int address; 019 private int moduleAddress; /* The result of integer division of the 020 ( sensor address - 1) by 8 */ 021 022 private int bit; /* a bitmask for the bit of this sensor */ 023 024 private String systemName; 025 026 protected Z21TrafficController tc; 027 028 public Z21RMBusSensor(String systemName, String userName, Z21TrafficController controller, String prefix) { 029 super(systemName, userName); 030 tc = controller; 031 init(systemName, prefix); 032 } 033 034 public Z21RMBusSensor(String systemName, Z21TrafficController controller, String prefix) { 035 super(systemName); 036 tc = controller; 037 init(systemName, prefix); 038 } 039 040 /** 041 * Common initialization for all constructors. 042 */ 043 private void init(String id, String prefix) { 044 // store address 045 systemName = id; 046 address = Z21RMBusAddress.getBitFromSystemName(systemName, prefix); 047 // calculate the module address and the bit to examine 048 moduleAddress = ((address-1)/ 8); 049 int bitnumber = (address-1) % 8; 050 switch(bitnumber) { 051 case 0: 052 bit = 0x01; 053 break; 054 case 1: 055 bit = 0x02; 056 break; 057 case 2: 058 bit = 0x04; 059 break; 060 case 3: 061 bit = 0x08; 062 break; 063 case 4: 064 bit = 0x10; 065 break; 066 case 5: 067 bit = 0x20; 068 break; 069 case 6: 070 bit = 0x40; 071 break; 072 case 7: 073 bit = 0x80; 074 break; 075 default: 076 // no default action, we have exhausted the possibilities. 077 } 078 log.debug("Created Sensor {} (Module Address {}, contact {})", 079 systemName, moduleAddress, bitnumber); 080 tc.addz21Listener(this); 081 // Finally, request the current state from the layout. 082 requestUpdateFromLayout(); 083 } 084 085 /** 086 * Request an update on status by sending an Z21 message. 087 */ 088 @Override 089 public void requestUpdateFromLayout() { 090 Z21Message msg = Z21Message.getLanRMBusGetDataRequestMessage(moduleAddress<=10?0:1); // only two possiblities allowed. 091 synchronized (this) { 092 statusRequested = true; 093 } 094 tc.sendz21Message(msg, this); 095 } 096 097 /** 098 * initmessage is a package protected class which allows the Manger to send 099 * a feedback message at initialization without changing the state of the 100 * sensor with respect to whether or not a feedback request was sent. This 101 * is used only when the sensor is created by on layout feedback. 102 * 103 * @param l the feedback message to send 104 */ 105 synchronized void initmessage(Z21Reply l) { 106 boolean oldState = statusRequested; 107 reply(l); 108 statusRequested = oldState; 109 } 110 111 @Override 112 public synchronized void reply(Z21Reply l) { 113 log.debug("received message: {}",l); 114 if (l.isRMBusDataChangedReply()) { 115 if (((l.getElement((moduleAddress<10?5+moduleAddress:5+(moduleAddress-10))) & bit) != 0) ^ _inverted) { 116 setOwnState(Sensor.ACTIVE); 117 } else { 118 setOwnState(Sensor.INACTIVE); 119 } 120 } 121 } 122 123 /** 124 * Listen for the messages to the Z21. 125 */ 126 @Override 127 public void message(Z21Message l) { 128 } 129 130 @Override 131 public void dispose() { 132 tc.removez21Listener(this); 133 super.dispose(); 134 } 135 136 /** 137 * Package protected routine to get the Sensor Number. 138 * @return Sensor number 139 */ 140 int getNumber() { 141 return address; 142 } 143 144 /** 145 * Package protected routine to get the Sensor Base Address. 146 * @return address for this module. 147 */ 148 int getModuleAddress() { 149 return moduleAddress; 150 } 151 152 private final static Logger log = LoggerFactory.getLogger(Z21RMBusSensor.class); 153 154}