-
Notifications
You must be signed in to change notification settings - Fork 331
/
Z21ReporterManager.java
169 lines (156 loc) · 6.89 KB
/
Z21ReporterManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package jmri.jmrix.roco.z21;
import jmri.InstanceManager;
import jmri.RailComManager;
import jmri.Reporter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
/**
* Z21ReporterManager implements the Reporter Manager interface for Roco Z21
* systems.
*
* @author Paul Bender Copyright (C) 2016
*/
public class Z21ReporterManager extends jmri.managers.AbstractReporterManager implements Z21Listener {
private boolean autoCreateInternalReporter = false; // disable automatic
// creation of the internal reporter
// by default. It interferes with
// reports from the Roco 10808
// which it preceeds in the circuit.
/**
* Create a new Z21ReporterManager
*
* @param memo an instance of Z21SystemConnectionMemo this manager is
* associated with.
*/
public Z21ReporterManager(Z21SystemConnectionMemo memo) {
super(memo);
try {
InstanceManager.getDefault(RailComManager.class);
} catch (NullPointerException npe) {
// there is no RailComManager, so create a new one
InstanceManager.setDefault(RailComManager.class,
new jmri.managers.DefaultRailComManager());
}
// register for messages
memo.getTrafficController().addz21Listener(this);
// make sure we are going to get railcom data from the command station
// set the broadcast flags so we get messages we may want to hear
memo.getRocoZ21CommandStation().setRailComMessagesFlag(true);
memo.getRocoZ21CommandStation().setRailComAutomaticFlag(true);
memo.getRocoZ21CommandStation().setCanDetectorFlag(true);
// and forward the flags to the command station.
memo.getTrafficController().sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(
memo.getRocoZ21CommandStation().getZ21BroadcastFlags()), null);
// And then send a message requesting an update from the hardware.
// This is required because the RailCom data currently requires polling.
memo.getTrafficController().sendz21Message(Z21Message.getLanRailComGetDataRequestMessage(), this);
}
/**
* {@inheritDoc}
*/
@Override
public Z21SystemConnectionMemo getMemo() {
return (Z21SystemConnectionMemo) memo;
}
@Override
public Reporter createNewReporter(String systemName, String userName) {
if (!systemName.matches(getSystemPrefix() + typeLetter() + "[" + 1 + "]")) {
int bitNum = Z21CanBusAddress.getBitFromSystemName(systemName, getSystemPrefix());
if (bitNum != -1) {
Reporter r = new Z21CanReporter(systemName, userName, getMemo());
register(r);
return r;
} else {
log.warn("Invalid Reporter name: {} ", systemName);
throw new IllegalArgumentException("Invalid Reporter name: " + systemName);
}
}
// Create and register the reporter
Reporter r = new Z21Reporter(systemName, userName, getMemo());
register(r);
return r;
}
// the Z21 Listener interface
/**
* Member function that will be invoked by a z21Interface implementation to
* forward a z21 message from the layout.
*
* @param msg The received z21 reply. Note that this same object may be
* presented to multiple users. It should not be modified here.
*/
@Override
public void reply(Z21Reply msg) {
// LAN_RAILCOM_DATACHANGED messages are related to the built in
// reporter.
if (autoCreateInternalReporter && msg.isRailComDataChangedMessage()) {
log.debug("Received RailComDatachanged message");
String systemName = getSystemPrefix() + typeLetter() + 1;
Z21Reporter r = (Z21Reporter) getBySystemName(systemName); // there is only one built in reporter.
if (null == r) {
log.debug("Creating reporter {}",systemName);
// need to create a new one, and send the message on
// to the newly created object.
((Z21Reporter) provideReporter(systemName)).reply(msg);
}
// LAN_CAN_DETECTOR message are related to CAN reporters.
} else if (msg.isCanDetectorMessage()) {
int type = (msg.getElement(9) & 0xFF);
log.debug("reporter message type {}", type);
if (type >= 0x11 && type <= 0x1f) {
log.debug("Received LAN_CAN_DETECTOR message");
int netID = (msg.getElement(4) & 0xFF) + ((msg.getElement(5) & 0xFF) << 8);
int msgPort = (msg.getElement(8) & 0xFF);
int address = (msg.getElement(6) & 0xFF) + ((msg.getElement(7) & 0xFF) << 8);
String sysName = getSystemPrefix() + typeLetter() + address + ":" + msgPort;
log.debug("asking for reporter {}", sysName);
Z21CanReporter r = (Z21CanReporter) getBySystemName(sysName);
if (null == r) {
// try with the module's CAN network ID
sysName = getSystemPrefix() + typeLetter() + String.format("%4X", netID) + ":" + msgPort;
log.debug("not found; asking for reporter {}", sysName);
r = (Z21CanReporter) getBySystemName(sysName);
if (null == r) {
log.debug("Creating reporter {}", sysName);
// need to create a new one, and send the message on
// to the newly created object.
((Z21CanReporter) provideReporter(sysName)).reply(msg);
}
}
}
}
}
/**
* Member function that will be invoked by a z21Interface implementation to
* forward a z21 message sent to the layout. Normally, this function will do
* nothing.
*
* @param msg The received z21 message. Note that this same object may be
* presented to multiple users. It should not be modified here.
*/
@Override
public void message(Z21Message msg) {
// we don't need to handle outgoing messages, so just ignore them.
}
/**
* Enable automatic creation of the Internal Z21 Reporter from messages.
* Defaults to disabled.
*/
public void enableInternalReporterCreationFromMessages() {
autoCreateInternalReporter = true;
}
/**
* {@inheritDoc}
*/
@Override
public Reporter getBySystemName(String sName){
Z21SystemNameComparitor comparitor = new Z21SystemNameComparitor(getSystemPrefix(),typeLetter());
for(Map.Entry<String,Reporter> e:_tsys.entrySet()){
if(0==comparitor.compare(e.getKey(),sName)){
return e.getValue();
}
}
return null;
}
private static final Logger log = LoggerFactory.getLogger(Z21ReporterManager.class);
}