
org.bidib.wizard.simulation.OneControlSimulator Maven / Gradle / Ivy
package org.bidib.wizard.simulation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.collections4.MapUtils;
import org.bidib.jbidibc.core.AddressData;
import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.BidibPort;
import org.bidib.jbidibc.core.Feature;
import org.bidib.jbidibc.core.LcConfigX;
import org.bidib.jbidibc.core.enumeration.InputPortEnum;
import org.bidib.jbidibc.core.enumeration.LcOutputType;
import org.bidib.jbidibc.core.exception.ProtocolException;
import org.bidib.jbidibc.core.message.BidibCommand;
import org.bidib.jbidibc.core.message.FeedbackAddressResponse;
import org.bidib.jbidibc.core.message.FeedbackConfidenceResponse;
import org.bidib.jbidibc.core.message.FeedbackGetRangeMessage;
import org.bidib.jbidibc.core.message.FeedbackMultipleResponse;
import org.bidib.jbidibc.core.message.LcConfigXGetMessage;
import org.bidib.jbidibc.core.message.LcConfigXResponse;
import org.bidib.jbidibc.core.message.LcConfigXSetMessage;
import org.bidib.jbidibc.core.message.LcKeyMessage;
import org.bidib.jbidibc.core.message.LcKeyResponse;
import org.bidib.jbidibc.core.message.LcNotAvailableResponse;
import org.bidib.jbidibc.core.message.LcOutputQueryMessage;
import org.bidib.jbidibc.core.message.LcStatResponse;
import org.bidib.jbidibc.core.port.BytePortConfigValue;
import org.bidib.jbidibc.core.port.PortConfigValue;
import org.bidib.jbidibc.core.port.ReconfigPortConfigValue;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.bidib.jbidibc.core.utils.MessageUtils;
import org.bidib.jbidibc.simulation.SwitchingFunctionsNode;
import org.bidib.jbidibc.simulation.net.SimulationBidibMessageProcessor;
import org.bidib.wizard.comm.FeedbackPortStatus;
import org.bidib.wizard.comm.InputPortStatus;
import org.bidib.wizard.mvc.main.model.FeedbackAddressData;
import org.bidib.wizard.mvc.main.model.FeedbackPort;
import org.bidib.wizard.mvc.main.model.GenericPort;
import org.bidib.wizard.simulation.events.InputPortStatusEvent;
import org.bidib.wizard.simulation.ports.GenericSimulationPort;
import org.bushe.swing.event.EventBus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OneControlSimulator extends LightControlSimulator implements SwitchingFunctionsNode {
private static final Logger LOGGER = LoggerFactory.getLogger(OneControlSimulator.class);
private static final String SIMULATION_PANEL_CLASS = "org.bidib.wizard.mvc.simulation.view.panel.LightControlPanel";
private final Map genericPorts = new HashMap();
private final Map feedbackPorts = new HashMap();
private final AtomicBoolean statusFreeze = new AtomicBoolean();
private final AtomicBoolean statusValid = new AtomicBoolean();
private final AtomicBoolean statusSignal = new AtomicBoolean();
public OneControlSimulator(byte[] nodeAddress, long uniqueId, boolean autoAddFeature,
SimulationBidibMessageProcessor messageReceiver) {
super(nodeAddress, uniqueId, autoAddFeature, messageReceiver);
}
private void setupFeedbackPorts() {
for (int id = 0; id < 16; id++) {
FeedbackPort port = new FeedbackPort();
port.setId(id);
port.setStatus(id % 3 == 0 ? FeedbackPortStatus.FREE : FeedbackPortStatus.OCCUPIED);
feedbackPorts.put(id, port);
}
}
@Override
protected void prepareFeatures() {
LOGGER.info("Prepare the features.");
super.prepareFeatures();
Feature feature = getFeature(BidibLibrary.FEATURE_CTRL_PORT_FLAT_MODEL);
if (feature != null) {
int numPorts = feature.getValue();
LOGGER.info("Create generic ports, numPorts: {}", numPorts);
for (int portNumber = 0; portNumber < numPorts; portNumber++) {
GenericSimulationPort port = new GenericSimulationPort(portNumber);
genericPorts.put(portNumber, port);
}
}
}
@Override
public boolean isPortFlatModelAvailable() {
Feature feature = getFeature(BidibLibrary.FEATURE_CTRL_PORT_FLAT_MODEL);
if (feature != null && feature.getValue() > 0) {
return true;
}
return false;
}
@Override
public LcOutputType getPortType(BidibPort bidibPort) {
int portNumber = bidibPort.getPortNumber(getPortModel());
LOGGER.info("getPortType for portNumber: {}", portNumber);
LcOutputType outputType = null;
GenericPort genericPort = genericPorts.get(portNumber);
if (genericPort != null) {
outputType = genericPort.getCurrentPortType();
}
return outputType;
}
@Override
public void start() {
LOGGER.info("Start the simulator for address: {}", getAddress());
// prepare the feedback ports
setupFeedbackPorts();
super.start();
if (!MapUtils.isEmpty(genericPorts)) {
int index = 0;
for (int portNum = 0; portNum < servoPortCount; portNum++) {
GenericSimulationPort genericPort = genericPorts.get(portNum + index);
genericPort.setCurrentPortType(LcOutputType.SERVOPORT, 0x0004);
}
index += servoPortCount;
for (int portNum = 0; portNum < switchPortCount; portNum++) {
GenericSimulationPort genericPort = genericPorts.get(portNum + index);
genericPort.setCurrentPortType(LcOutputType.SWITCHPORT, 0x0001);
}
// index += switchPortCount;
// TODO this is a hack for the OneControl
index = inputPortOffset;
LOGGER.info("Set the port type for input ports, index: {}", index);
for (int portNum = 0; portNum < inputPortCount; portNum++) {
GenericSimulationPort genericPort = genericPorts.get(portNum + index);
genericPort.setCurrentPortType(LcOutputType.INPUTPORT, 0x8001);
}
}
}
@Override
public String getSimulationPanelClass() {
return SIMULATION_PANEL_CLASS;
}
@Override
protected byte[] prepareResponse(BidibCommand bidibMessage) {
byte[] response = null;
switch (ByteUtils.getInt(bidibMessage.getType())) {
case BidibLibrary.MSG_BM_GET_RANGE:
response = processBmGetRangeRequest(bidibMessage);
break;
case BidibLibrary.MSG_BM_MIRROR_MULTIPLE:
processBmMirrorMultipleRequest(bidibMessage);
break;
case BidibLibrary.MSG_BM_ADDR_GET_RANGE:
processBmAddrGetRangeRequest(bidibMessage);
break;
case BidibLibrary.MSG_BM_GET_CONFIDENCE:
response = processBmGetConfidenceRequest(bidibMessage);
break;
default:
response = super.prepareResponse(bidibMessage);
break;
}
return response;
}
protected byte[] processBmGetRangeRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the FeedbackGetRangeMessage: {}", bidibMessage);
byte[] response = null;
try {
FeedbackGetRangeMessage feedbackGetRangeMessage = (FeedbackGetRangeMessage) bidibMessage;
byte baseAddress = feedbackGetRangeMessage.getBegin();
int end = feedbackGetRangeMessage.getEnd();
byte feedbackSize =
ByteUtils.getLowByte(feedbackGetRangeMessage.getEnd() - feedbackGetRangeMessage.getBegin());
byte value = 0x00;
int index = 0;
byte[] feedbackMultiple = new byte[feedbackSize / 8];
int position = feedbackMultiple.length;
for (int portNum = end; portNum > baseAddress; portNum--) {
value = (byte) ((value & 0xFF) << 1);
FeedbackPort fbp = feedbackPorts.get(portNum - 1);
byte status = (byte) (fbp.getStatus().getType().getType() & 0x01);
value |= status;
index++;
if (index > 7) {
feedbackMultiple[position - 1] = value;
value = 0;
index = 0;
position--;
}
}
LOGGER.info("Prepared feedback multiple: {}", ByteUtils.bytesToHex(feedbackMultiple));
FeedbackMultipleResponse feedbackMultipleResponse =
new FeedbackMultipleResponse(bidibMessage.getAddr(), getNextSendNum(), baseAddress, feedbackSize,
feedbackMultiple);
response = feedbackMultipleResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create feedbackMultiple response failed.", ex);
}
return response;
}
protected void processBmMirrorMultipleRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the FeedbackMirrorMultipleMessage: {}, do nothing ...", bidibMessage);
}
protected void processBmAddrGetRangeRequest(BidibCommand bidibMessage) {
try {
for (FeedbackPort port : feedbackPorts.values()) {
int detectorNumber = port.getId();
Collection bidibAddresses = new ArrayList<>();
Collection addresses = port.getAddresses();
for (FeedbackAddressData addressData : addresses) {
AddressData bidibAddress = new AddressData(addressData.getAddress(), addressData.getType());
bidibAddresses.add(bidibAddress);
}
FeedbackAddressResponse feedbackAddressResponse =
new FeedbackAddressResponse(bidibMessage.getAddr(), getNextSendNum(), detectorNumber,
bidibAddresses);
byte[] response = feedbackAddressResponse.getContent();
LOGGER.info("Prepare feedbackAddressResponse: {}", ByteUtils.bytesToHex(response));
sendSpontanousResponse(response);
}
}
catch (ProtocolException ex) {
LOGGER.warn("Create feedbackAddress response failed.", ex);
}
}
protected byte[] processBmGetConfidenceRequest(BidibCommand bidibMessage) {
byte[] response = null;
try {
byte valid = (byte) (statusValid.get() ? 1 : 0);
byte freeze = (byte) (statusFreeze.get() ? 1 : 0);
byte signal = (byte) (statusSignal.get() ? 1 : 0);
// TODO if more than a single GBM16T is attached we must set more bits? See 4.7.4. Uplink: Nachrichten für
// Belegtmelder --> MSG_BM_CONFIDENCE
// Test with real system: See MainMessageListener.confidence()
FeedbackConfidenceResponse feedbackConfidenceResponse =
new FeedbackConfidenceResponse(bidibMessage.getAddr(), getNextSendNum(), valid, freeze, signal);
response = feedbackConfidenceResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create feedbackConfidence response failed.", ex);
}
return response;
}
protected byte[] processLcConfigXSetRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the LcConfigXSet request: {}", bidibMessage);
byte[] response = null;
if (getFlatPortModelPortCount() > 0) {
try {
LcConfigXSetMessage lcConfigXSetMessage = (LcConfigXSetMessage) bidibMessage;
int outputNumber = lcConfigXSetMessage.getPortNumber(getPortModel());
LcOutputType outputType = lcConfigXSetMessage.getPortType(getPortModel());
GenericPort port = null;
port = genericPorts.get(Integer.valueOf(outputNumber));
LOGGER.info("Set LcConfig for output number: {}, port: {}", outputNumber, port);
BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);
if (port != null) {
// the problem here is that the BIDIB_PCFG_RECONFIG overwrites the supported port types
LcConfigX lcConfigX = lcConfigXSetMessage.getLcConfigX();
ReconfigPortConfigValue reconfig =
(ReconfigPortConfigValue) lcConfigX.getPortConfig().get(BidibLibrary.BIDIB_PCFG_RECONFIG);
if (reconfig != null) {
// we must keep the supported port types
Integer supportedPortTypes = port.getSupportedPortTypes();
if (supportedPortTypes != null) {
ReconfigPortConfigValue newReconfig =
new ReconfigPortConfigValue(reconfig.getCurrentOutputType().getType(),
supportedPortTypes);
LOGGER.info("Prepared BIDIB_PCFG_RECONFIG to replace: {}", newReconfig);
lcConfigX.getPortConfig().put(BidibLibrary.BIDIB_PCFG_RECONFIG, newReconfig);
}
}
port.setPortConfig(lcConfigX.getPortConfig());
byte[] content = MessageUtils.getCodedPortConfig(lcConfigX, getPortModel());
// TODO remove this test
if (outputNumber == 5) {
content = new byte[] { 0x00, 0x05, 0x00, 0x0C };
}
LcConfigXResponse lcConfigXResponse =
new LcConfigXResponse(bidibMessage.getAddr(), getNextSendNum(), content);
response = lcConfigXResponse.getContent();
}
else {
LOGGER.warn("No port assigned!");
LcNotAvailableResponse magicResponse =
new LcNotAvailableResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort);
response = magicResponse.getContent();
}
}
catch (ProtocolException ex) {
LOGGER.warn("Create LcConfigX response failed.", ex);
}
}
else {
response = super.processLcConfigXSetRequest(bidibMessage);
}
return response;
}
protected byte[] processLcConfigXGetRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the LcConfigXGet request: {}", bidibMessage);
byte[] response = null;
if (getFlatPortModelPortCount() > 0) {
try {
LcConfigXGetMessage lcConfigXGetMessage = (LcConfigXGetMessage) bidibMessage;
int outputNumber = lcConfigXGetMessage.getPortNumber(getPortModel());
LcOutputType outputType = lcConfigXGetMessage.getPortType(getPortModel());
GenericPort port = null;
Map> values = new LinkedHashMap<>();
port = genericPorts.get(Integer.valueOf(outputNumber));
BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);
if (port != null) {
if (outputNumber >= 0 && outputNumber < 4) { // 4 servo ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x000402)));
}
else if (outputNumber >= 4 && outputNumber < (4 + 16)) { // 16 power ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x000100)));
values.put(BidibLibrary.BIDIB_PCFG_IO_CTRL, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
values.put(BidibLibrary.BIDIB_PCFG_TICKS, new BytePortConfigValue(Byte.valueOf((byte) 0x0F)));
}
else { // GPIO are all input ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x80010F)));
values.put(BidibLibrary.BIDIB_PCFG_IO_CTRL, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
values.put(BidibLibrary.BIDIB_PCFG_TICKS, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
}
// TODO remove this test
if (outputNumber == 2) {
values.put(BidibLibrary.BIDIB_PCFG_NONE, new BytePortConfigValue((byte) 12));
}
LOGGER.info("Return config of port: {}", port);
LcConfigX lcConfigX = new LcConfigX(bidibPort, values);
LcConfigXResponse lcConfigXResponse =
new LcConfigXResponse(bidibMessage.getAddr(), getNextSendNum(),
MessageUtils.getCodedPortConfig(lcConfigX, getPortModel()));
response = lcConfigXResponse.getContent();
}
else {
LOGGER.warn("No port available with port number: {}", outputNumber);
LcNotAvailableResponse notAvailableResponse =
new LcNotAvailableResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort);
response = notAvailableResponse.getContent();
}
}
catch (ProtocolException ex) {
LOGGER.warn("Create LcConfigX response failed.", ex);
}
}
else {
response = super.processLcConfigXGetRequest(bidibMessage);
}
return response;
}
protected void processLcConfigXGetAllRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the LcConfigXGetAll request: {}", bidibMessage);
if (getFlatPortModelPortCount() > 0) {
LcOutputType outputType = LcOutputType.SWITCHPORT;
Map> values = new LinkedHashMap<>();
try {
for (GenericPort port : genericPorts.values()) {
int portNumber = port.getPortNumber();
values.clear();
if (portNumber >= 0 && portNumber < 4) { // 4 servo ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x000402)));
}
else if (portNumber >= 4 && portNumber < (4 + 16)) { // 16 power ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x000100)));
values.put(BidibLibrary.BIDIB_PCFG_IO_CTRL, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
values.put(BidibLibrary.BIDIB_PCFG_TICKS, new BytePortConfigValue(Byte.valueOf((byte) 0x0F)));
}
else { // GPIO are all input ports
values.put(BidibLibrary.BIDIB_PCFG_RECONFIG,
new ReconfigPortConfigValue(Integer.valueOf(0x80010F)));
values.put(BidibLibrary.BIDIB_PCFG_IO_CTRL, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
values.put(BidibLibrary.BIDIB_PCFG_TICKS, new BytePortConfigValue(Byte.valueOf((byte) 0x00)));
}
// TODO remove this test
if (portNumber == 6) {
values.put(BidibLibrary.BIDIB_PCFG_NONE, new BytePortConfigValue((byte) 12));
}
LOGGER.info("Return config of port: {}", port);
BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, portNumber);
LcConfigX lcConfigX = new LcConfigX(bidibPort, values);
LcConfigXResponse lcConfigXResponse =
new LcConfigXResponse(bidibMessage.getAddr(), getNextSendNum(),
MessageUtils.getCodedPortConfig(lcConfigX, getPortModel()));
byte[] response = lcConfigXResponse.getContent();
LOGGER.info("Prepared lcConfigXResponse: {}", ByteUtils.bytesToHex(response));
sendSpontanousResponse(response);
}
}
catch (ProtocolException ex) {
LOGGER.warn("Create LcConfigXResponse response failed.", ex);
}
}
else {
super.processLcConfigXGetAllRequest(bidibMessage);
}
}
protected byte[] processLcOutputQueryRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the LcOutputQuery request: {}", bidibMessage);
byte[] response = null;
if (getFlatPortModelPortCount() > 0) {
byte portState = 0;
try {
LcOutputQueryMessage lcOutputQueryMessage = (LcOutputQueryMessage) bidibMessage;
LcOutputType outputType = lcOutputQueryMessage.getPortType(getPortModel());
int outputNumber = lcOutputQueryMessage.getPortNumber(getPortModel());
GenericPort port = genericPorts.get(Integer.valueOf(outputNumber));
BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);
if (port != null) {
portState = ByteUtils.getLowByte(0xFF);
}
else {
LOGGER.warn("No port available with portNumber: {}", outputNumber);
}
LcStatResponse lcStatResponse =
new LcStatResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort, portState);
response = lcStatResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create LcStat response failed.", ex);
}
}
else {
response = super.processLcOutputQueryRequest(bidibMessage);
}
return response;
}
protected byte[] processLcKeyQueryRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the LcKeyQuery request: {}", bidibMessage);
byte[] response = null;
if (getFlatPortModelPortCount() > 0) {
byte keyState = 0;
GenericSimulationPort port = null;
try {
LcKeyMessage lcKeyMessage = (LcKeyMessage) bidibMessage;
int portNumber = lcKeyMessage.getKeyNumber();
port = genericPorts.get(Integer.valueOf(portNumber));
if (port != null) {
keyState = port.getPortStatus();
}
else {
LOGGER.warn("No port available with portNumber: {}", portNumber);
}
LcKeyResponse lcKeyResponse =
new LcKeyResponse(bidibMessage.getAddr(), getNextSendNum(), ByteUtils.getLowByte(portNumber),
keyState);
response = lcKeyResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create LcKey response failed.", ex);
}
if (port != null) {
publishInputPortChange(port);
}
}
else {
response = super.processLcKeyQueryRequest(bidibMessage);
}
return response;
}
private void publishInputPortChange(GenericSimulationPort port) {
InputPortStatus status = InputPortStatus.valueOf(InputPortEnum.valueOf(port.getPortStatus()));
LOGGER.info("The inputport status has changed, notify the listeners, nodeAddress: {}", nodeAddress);
EventBus.publish(new InputPortStatusEvent(ByteUtils.bytesToHex(nodeAddress), port.getPortNumber(), status));
}
protected void changeInputPortStatus(int portNum) {
GenericSimulationPort port = genericPorts.get(portNum);
if (port != null) {
InputPortStatus portStatus = InputPortStatus.valueOf(InputPortEnum.valueOf(port.getPortStatus()));
switch (portStatus) {
case OFF:
port.setPortStatus(InputPortStatus.ON.getType().getType());
break;
default:
port.setPortStatus(InputPortStatus.OFF.getType().getType());
break;
}
// prepare the request
final LcKeyMessage lcKeyMessage = new LcKeyMessage(
portNum) {
@Override
public byte[] getAddr() {
return getNodeAddress();
}
};
processRequest(lcKeyMessage);
}
else {
LOGGER.warn("The requested input port is not available: {}", portNum);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy