
org.bidib.wizard.simulation.GBMboostNodeSimulator Maven / Gradle / Ivy
package org.bidib.wizard.simulation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.bidib.jbidibc.core.AddressData;
import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.Feature;
import org.bidib.jbidibc.core.enumeration.BoosterState;
import org.bidib.jbidibc.core.exception.ProtocolException;
import org.bidib.jbidibc.core.message.BidibCommand;
import org.bidib.jbidibc.core.message.BoostDiagnosticResponse;
import org.bidib.jbidibc.core.message.BoostOffMessage;
import org.bidib.jbidibc.core.message.BoostOnMessage;
import org.bidib.jbidibc.core.message.BoostStatResponse;
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.utils.ByteUtils;
import org.bidib.jbidibc.simulation.net.SimulationBidibMessageProcessor;
import org.bidib.jbidibc.simulation.nodes.DefaultNodeSimulator;
import org.bidib.wizard.comm.FeedbackPortStatus;
import org.bidib.wizard.mvc.main.model.FeedbackAddressData;
import org.bidib.wizard.mvc.main.model.FeedbackPort;
import org.bidib.wizard.mvc.main.model.Port;
import org.bidib.wizard.simulation.events.FeedbackConfidenceSetEvent;
import org.bidib.wizard.simulation.events.FeedbackConfidenceStatusEvent;
import org.bidib.wizard.simulation.events.FeedbackPortStatusEvent;
import org.bushe.swing.event.EventBus;
import org.bushe.swing.event.annotation.AnnotationProcessor;
import org.bushe.swing.event.annotation.EventSubscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GBMboostNodeSimulator extends DefaultNodeSimulator {
private static final Logger LOGGER = LoggerFactory.getLogger(GBMboostNodeSimulator.class);
private static final String SIMULATION_PANEL_CLASS =
"org.bidib.wizard.mvc.simulation.view.panel.GBMboostMasterPanel";
private final Map feedbackPorts = new HashMap();
private final AtomicBoolean statusFreeze = new AtomicBoolean();
private final AtomicBoolean statusValid = new AtomicBoolean();
private final AtomicBoolean statusSignal = new AtomicBoolean();
private BoosterState boosterState = BoosterState.OFF;
protected final ScheduledExecutorService boosterDiagWorker = Executors.newScheduledThreadPool(1);
public GBMboostNodeSimulator(byte[] nodeAddress, long uniqueId, boolean autoAddFeature,
SimulationBidibMessageProcessor messageReceiver) {
super(nodeAddress, uniqueId, autoAddFeature, messageReceiver);
}
@Override
protected void prepareFeatures() {
super.prepareFeatures();
features.add(new Feature(BidibLibrary.FEATURE_BST_VOLT_ADJUSTABLE, 1));
features.add(new Feature(BidibLibrary.FEATURE_BST_VOLT, 18));
features.add(new Feature(BidibLibrary.FEATURE_BST_CUTOUT_AVAIALABLE, 1));
features.add(new Feature(BidibLibrary.FEATURE_BST_CUTOUT_ON, 1));
features.add(new Feature(BidibLibrary.FEATURE_BST_AMPERE_ADJUSTABLE, /* 1 */0));
features.add(new Feature(BidibLibrary.FEATURE_BST_CV_AVAILABLE, 1));
features.add(new Feature(BidibLibrary.FEATURE_BST_CV_ON, 0));
features.add(new Feature(BidibLibrary.FEATURE_BST_AMPERE, 155));
features.add(new Feature(BidibLibrary.FEATURE_BST_CURMEAS_INTERVAL, 200));
// features.add(new Feature(BidibLibrary.FEATURE_BM_CURMEAS_AVAILABLE, 1));
features.add(new Feature(BidibLibrary.FEATURE_BM_SIZE, 16));
features.add(new Feature(BidibLibrary.FEATURE_BM_ADDR_DETECT_ON, 1));
features.add(new Feature(BidibLibrary.FEATURE_BM_ON, 1));
}
@Override
public String getSimulationPanelClass() {
return SIMULATION_PANEL_CLASS;
}
@Override
public void start() {
LOGGER.info("Start the simulator for address: {}", getAddress());
AnnotationProcessor.process(this);
// prepare the feedback ports
setupFeedbackPorts();
super.start();
}
@Override
public void stop() {
AnnotationProcessor.unprocess(this);
if (boosterDiagWorker != null) {
LOGGER.info("Stop the booster diag worker.");
boosterDiagWorker.shutdownNow();
}
super.stop();
}
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 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;
case BidibLibrary.MSG_BOOST_QUERY:
response = processBoostQueryRequest(bidibMessage);
break;
case BidibLibrary.MSG_BOOST_ON:
response = processBoostOnRequest(bidibMessage);
break;
case BidibLibrary.MSG_BOOST_OFF:
response = processBoostOffRequest(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;
int feedbackByteSize = feedbackSize / 8 + (feedbackSize % 8 > 0 ? 1 : 0);
byte[] feedbackMultiple = new byte[feedbackByteSize];
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;
feedbackMultiple[position - 1] = value;
index++;
if (index > 7) {
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[] processBoostQueryRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the BoostQuery request: {}", bidibMessage);
byte[] response = null;
try {
BoostStatResponse boostStatResponse =
new BoostStatResponse(bidibMessage.getAddr(), getNextSendNum(), boosterState);
response = boostStatResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create BoostStatResponse response failed.", ex);
}
return response;
}
private ScheduledFuture> futureTriggerBoostDiagnostic;
protected byte[] processBoostOnRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the BoostOn request: {}", bidibMessage);
byte[] response = null;
try {
BoostOnMessage boostOnMessage = (BoostOnMessage) bidibMessage;
byte broadcast = boostOnMessage.getBroadcast();
LOGGER.info("BoostOn with broadcast: {}", broadcast);
if (broadcast == BoostOnMessage.BROADCAST_MESSAGE) {
// TODO handle the requested broadcast
}
// activate the booster
boosterState = BoosterState.ON;
BoostStatResponse boostStatResponse =
new BoostStatResponse(bidibMessage.getAddr(), getNextSendNum(), boosterState);
response = boostStatResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create BoostStatResponse response failed.", ex);
}
// use executor to send response
if (futureTriggerBoostDiagnostic == null) {
LOGGER.info("Schedule the boost diagnostic trigger.");
futureTriggerBoostDiagnostic = boosterDiagWorker.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
LOGGER.info("Trigger boost diag");
try {
triggerBoostDiagnosticResponse();
}
catch (Exception ex) {
LOGGER.warn("Trigger the boost diagnostic failed.", ex);
}
LOGGER.info("Trigger boost has finished.");
}
}, 500, 2000, TimeUnit.MILLISECONDS);
}
return response;
}
protected byte[] processBoostOffRequest(BidibCommand bidibMessage) {
LOGGER.info("Process the BoostOff request: {}", bidibMessage);
byte[] response = null;
try {
BoostOffMessage boostOffMessage = (BoostOffMessage) bidibMessage;
byte broadcast = boostOffMessage.getBroadcast();
LOGGER.info("BoostOn with broadcast: {}", broadcast);
if (broadcast == BoostOnMessage.BROADCAST_MESSAGE) {
// TODO handle the requested broadcast
}
// deactivate the booster
boosterState = BoosterState.OFF;
BoostStatResponse boostStatResponse =
new BoostStatResponse(bidibMessage.getAddr(), getNextSendNum(), boosterState);
response = boostStatResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create BoostStatResponse response failed.", ex);
}
if (futureTriggerBoostDiagnostic != null) {
LOGGER.info("Stop the boost diagnostic trigger.");
futureTriggerBoostDiagnostic.cancel(false);
futureTriggerBoostDiagnostic = null;
}
return response;
}
protected void triggerBoostDiagnosticResponse() {
LOGGER.info("Trigger the boostDiagnostic repsonse.");
byte[] response = null;
try {
BoostDiagnosticResponse boostDiagnosticResponse =
new BoostDiagnosticResponse(nodeAddress, getNextSendNum(), 0x44, 0xA9, 0x13);
response = boostDiagnosticResponse.getContent();
}
catch (ProtocolException ex) {
LOGGER.warn("Create boostDiagnostic response failed.", ex);
}
sendSpontanousResponse(response);
}
private void publishFeedbackPortChange(Port> port) {
FeedbackPort feedbackPort = (FeedbackPort) port;
FeedbackPortStatus status = feedbackPort.getStatus();
LOGGER.info("The feedbackport status has changed, notify the listeners, nodeAddress: {}", nodeAddress);
EventBus.publish(new FeedbackPortStatusEvent(ByteUtils.bytesToHex(nodeAddress), feedbackPort, status));
}
@Override
public void queryStatus(Class> portClass) {
if (FeedbackPort.class.equals(portClass)) {
for (FeedbackPort feedbackPort : feedbackPorts.values()) {
publishFeedbackPortChange(feedbackPort);
}
// publish the confidence
publishFeedbackConfidenceStatusEvent(statusValid.get(), statusFreeze.get(), statusSignal.get());
}
}
@EventSubscriber(eventClass = FeedbackConfidenceSetEvent.class)
public void feedbackConfidenceSetEvent(FeedbackConfidenceSetEvent feedbackConfidenceEvent) {
String nodeAddress = feedbackConfidenceEvent.getNodeAddr();
LOGGER.info("The change of the feedback confidence was requested, nodeAddress: {}", nodeAddress);
// check if the node is addressed
if (!isAddressEqual(nodeAddress)) {
LOGGER.trace("Another node is addressed.");
return;
}
statusValid.set(feedbackConfidenceEvent.getValid());
statusFreeze.set(feedbackConfidenceEvent.getFreeze());
statusSignal.set(feedbackConfidenceEvent.getSignal());
byte valid = (byte) (statusValid.get() ? 1 : 0);
byte freeze = (byte) (statusFreeze.get() ? 1 : 0);
byte signal = (byte) (statusSignal.get() ? 1 : 0);
try {
FeedbackConfidenceResponse feedbackConfidenceResponse =
new FeedbackConfidenceResponse(this.nodeAddress, getNextSendNum(), valid, freeze, signal);
LOGGER.info("Prepared feedbackConfidenceResponse: {}", feedbackConfidenceResponse);
sendSpontanousResponse(feedbackConfidenceResponse.getContent());
}
catch (ProtocolException ex) {
LOGGER.warn("Send feedbackConfidenceResponse failed.", ex);
}
publishFeedbackConfidenceStatusEvent(statusValid.get(), statusFreeze.get(), statusSignal.get());
}
private void publishFeedbackConfidenceStatusEvent(boolean valid, boolean freeze, boolean signal) {
LOGGER.info("The feedbackport confidence status has changed, notify the listeners, nodeAddress: {}",
nodeAddress);
EventBus.publish(new FeedbackConfidenceStatusEvent(ByteUtils.bytesToHex(nodeAddress), valid, freeze, signal));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy