Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.bidib.wizard.common.node.Node Maven / Gradle / Ivy
package org.bidib.wizard.common.node;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bidib.jbidibc.core.node.ConfigurationVariable;
import org.bidib.jbidibc.exchange.vendorcv.VendorCvData;
import org.bidib.jbidibc.messages.FeedbackAddressData;
import org.bidib.jbidibc.messages.FeedbackDynStateData;
import org.bidib.jbidibc.messages.FeedbackPosition;
import org.bidib.jbidibc.messages.SoftwareVersion;
import org.bidib.jbidibc.messages.StringData;
import org.bidib.jbidibc.messages.enums.DetachedState;
import org.bidib.jbidibc.messages.enums.IdentifyState;
import org.bidib.jbidibc.messages.enums.LcOutputType;
import org.bidib.jbidibc.messages.enums.PositionLocationEnum;
import org.bidib.jbidibc.messages.enums.SysErrorEnum;
import org.bidib.jbidibc.messages.port.PortConfigValue;
import org.bidib.jbidibc.messages.port.PortMapUtils;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.messages.utils.NodeUtils;
import org.bidib.jbidibc.messages.utils.ProductUtils;
import org.bidib.wizard.api.model.Accessory;
import org.bidib.wizard.api.model.BoosterNodeInterface;
import org.bidib.wizard.api.model.CommandStationNodeInterface;
import org.bidib.wizard.api.model.Flag;
import org.bidib.wizard.api.model.InterfaceNodeInterface;
import org.bidib.wizard.api.model.LabelAware;
import org.bidib.wizard.api.model.Macro;
import org.bidib.wizard.api.model.MacroSaveState;
import org.bidib.wizard.api.model.NodeChangePublisher;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.OccupancyNodeInterface;
import org.bidib.wizard.api.model.PortsProvider;
import org.bidib.wizard.api.model.SwitchingNodeInterface;
import org.bidib.wizard.api.model.event.NodeStatusEvent;
import org.bidib.wizard.api.model.event.NodeStatusEvent.StatusIdentifier;
import org.bidib.wizard.api.model.listener.AccessoryListListener;
import org.bidib.wizard.api.model.listener.CvDefinitionListener;
import org.bidib.wizard.api.model.listener.FlagListListener;
import org.bidib.wizard.api.model.listener.MacroListListener;
import org.bidib.wizard.api.model.listener.NodeListener;
import org.bidib.wizard.api.model.listener.PortListListener;
import org.bidib.wizard.api.model.listener.PortListener;
import org.bidib.wizard.api.model.listener.PortValueListener;
import org.bidib.wizard.common.labels.WizardLabelWrapper;
import org.bidib.wizard.model.ports.AnalogPort;
import org.bidib.wizard.model.ports.BacklightPort;
import org.bidib.wizard.model.ports.FeedbackPort;
import org.bidib.wizard.model.ports.GenericPort;
import org.bidib.wizard.model.ports.InputPort;
import org.bidib.wizard.model.ports.LightPort;
import org.bidib.wizard.model.ports.MotorPort;
import org.bidib.wizard.model.ports.Port;
import org.bidib.wizard.model.ports.ServoPort;
import org.bidib.wizard.model.ports.SoundPort;
import org.bidib.wizard.model.ports.SwitchPairPort;
import org.bidib.wizard.model.ports.SwitchPort;
import org.bidib.wizard.model.status.BidibStatus;
import org.bidib.wizard.model.status.FeedbackConfidenceStatus;
import org.bidib.wizard.model.status.FeedbackPortStatus;
import org.bidib.wizard.model.stringdata.StoredStrings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jgoodies.binding.beans.Model;
/**
* The {@code Node} implementation represents a BiDiB node in the system.
*/
public class Node extends Model implements NodeInterface, LabelAware, NodeChangePublisher, PortsProvider {
private static final long serialVersionUID = 1L;
protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
private final List listeners = new LinkedList();
private List macroListListeners = new LinkedList<>();
private List accessoryListListeners = new LinkedList<>();
private List cvDefinitionListeners = new LinkedList<>();
private List flagListListeners = new LinkedList<>();
private Boolean addressMessagesEnabled;
private Boolean dccStartEnabled;
private Boolean externalStartEnabled;
private Boolean feedbackMessagesEnabled;
private Boolean feedbackMirrorDisabled;
private IdentifyState identifyState;
private DetachedState detachedState = DetachedState.ATTACHED;
private SysErrorEnum sysError;
private String reasonData;
private Boolean keyMessagesEnabled;
private String label;
private final org.bidib.jbidibc.messages.Node node;
private final PropertyChangeListener pclNode;
private final PropertyChangeListener pclBoosterNode;
private int storableMacroCount;
private int maxMacroSteps;
private int maxAspectsCount;
private boolean globalDetectorAvailable;
// the base number is the base number of the RF base in multi cell environments
private int baseNumber;
private boolean updatable;
private SoftwareVersion updateFirmwareVersion;
private boolean bootloaderNode;
private boolean nodeHasError;
private VendorCvData vendorCV;
private Object configVarsLock = new Object();
private Object genericPortsLock = new Object();
private final Map configVariables;
private List flags = new LinkedList<>();
private PortConfigHandler genericPortConfigHandler;
private AnalogPortHandler analogPortHandler;
private BacklightPortHandler backlightPortHandler;
private FeedbackPortHandler feedbackPortHandler;
private InputPortHandler inputPortHandler;
private LightPortHandler lightPortHandler;
private MotorPortHandler motorPortHandler;
private ServoPortHandler servoPortHandler;
private SoundPortHandler soundPortHandler;
private SwitchPortHandler switchPortHandler;
private SwitchPairPortHandler switchPairPortHandler;
private List macros = new LinkedList<>();
private List accessories = new LinkedList<>();
private Map, List> portListListeners = new LinkedHashMap<>();
private Map, List>>> portListeners =
new LinkedHashMap<>();
private Map, List>>> portValueListeners =
new LinkedHashMap<>();
private PropertyChangeListener macroPendingChangesListener;
private PropertyChangeListener accessoryPendingChangesListener;
private CommandStationNodeInterface commandStationNodeProxy;
private BoosterNodeInterface boosterNodeProxy;
private InterfaceNodeInterface interfaceNodeProxy;
private SwitchingNodeInterface switchingNodeProxy;
private OccupancyNodeInterface occupancyNodeProxy;
private StatusIdentifier nodeLoadStatus = StatusIdentifier.InitialLoadPending;
private final Object initialLoadFinishedLock = new Object();
// private AtomicBoolean initialLoadPartiallyFinished = new AtomicBoolean(false);
private ConnectionNodeAwarePublisher publisher;
private WizardLabelWrapper wizardLabelWrapper;
// keep the strings stored in namespace 2
private StoredStrings storedStringsNs2;
/**
* Create a new node with the associated bidib node.
*
* @param node
* the bidib node is mandatory
* @throws IllegalArgumentException
* if the bidib node is null
*/
public Node(org.bidib.jbidibc.messages.Node node) {
if (node == null) {
throw new IllegalArgumentException("The node must not be null!");
}
this.node = node;
this.configVariables = new LinkedHashMap<>();
// Listen on changes of the node name from the core node. If the name is read from the real node we must get the
// change.
pclNode = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// LOGGER.debug(">>> Property changed, name: {}", evt.getPropertyName());
switch (evt.getPropertyName()) {
case org.bidib.jbidibc.messages.Node.PROPERTY_USERNAME:
LOGGER
.info("The username of the node has changed: {}, oldvalue: '{}', newvalue: '{}'",
node.getStoredString(StringData.INDEX_USERNAME), evt.getOldValue(), evt.getNewValue());
break;
default:
break;
}
firePropertyChange(new PropertyChangeEvent(Node.this, PROPERTY_NODE_PREFIX + evt.getPropertyName(),
evt.getOldValue(), evt.getNewValue()));
}
};
this.node.addPropertyChangeListener(pclNode);
pclBoosterNode = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange(new PropertyChangeEvent(Node.this, "boosterNode." + evt.getPropertyName(),
evt.getOldValue(), evt.getNewValue()));
}
};
}
/**
* Set the event publisher.
*
* @param publisher
* the event publisher
*/
public void setEventPublisher(final ConnectionNodeAwarePublisher publisher) {
this.publisher = publisher;
}
/**
* Set the wizard label wrapper.
*
* @param wizardLabelWrapper
* the wizard label wrapper
*/
public void setWizardLabelWrapper(final WizardLabelWrapper wizardLabelWrapper) {
this.wizardLabelWrapper = wizardLabelWrapper;
}
/**
* Initialize the node.
*/
public void initialize() {
if (NodeUtils.hasCommandStationFunctions(node.getUniqueId())) {
LOGGER.info("The node has command station functions.");
commandStationNodeProxy = new CommandStationNode(this, publisher);
LOGGER.debug("Created new instance of CommandStationNode: {}", commandStationNodeProxy);
}
if (NodeUtils.hasBoosterFunctions(node.getUniqueId())) {
LOGGER.info("The node has booster functions.");
boosterNodeProxy = new BoosterNode(this, publisher);
// TODO verify if this is good ...
((BoosterNode) boosterNodeProxy).addPropertyChangeListener(pclBoosterNode);
}
if (NodeUtils.hasSubNodesFunctions(node.getUniqueId())) {
LOGGER.info("The node has subnodes functions.");
interfaceNodeProxy = new InterfaceNode(this);
}
if (NodeUtils.hasSwitchFunctions(node.getUniqueId()) || NodeUtils.hasAccessoryFunctions(node.getUniqueId())) {
LOGGER.info("The node has switching functions.");
switchingNodeProxy = new SwitchingNode(this);
}
if (NodeUtils.hasFeedbackFunctions(node.getUniqueId())) {
LOGGER.info("The node has occupancy functions.");
occupancyNodeProxy = new OccupancyNode(this);
}
// handler for generic ports
genericPortConfigHandler = new PortConfigHandler(this, publisher);
analogPortHandler = new AnalogPortHandler(this, publisher, wizardLabelWrapper);
backlightPortHandler = new BacklightPortHandler(this, publisher, wizardLabelWrapper);
feedbackPortHandler = new FeedbackPortHandler(this, publisher, wizardLabelWrapper);
inputPortHandler = new InputPortHandler(this, publisher, wizardLabelWrapper);
lightPortHandler = new LightPortHandler(this, publisher, wizardLabelWrapper);
motorPortHandler = new MotorPortHandler(this, publisher, wizardLabelWrapper);
servoPortHandler = new ServoPortHandler(this, publisher, wizardLabelWrapper);
soundPortHandler = new SoundPortHandler(this, publisher, wizardLabelWrapper);
switchPortHandler = new SwitchPortHandler(this, publisher, wizardLabelWrapper);
switchPairPortHandler = new SwitchPairPortHandler(this, publisher, wizardLabelWrapper);
macroPendingChangesListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.info("The pending changes flag of a macro has been changed.");
// force refresh of macro list
fireMacroPendingChangesChanged();
}
};
accessoryPendingChangesListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.trace("The property of an accessory has been changed.");
switch (evt.getPropertyName()) {
case Accessory.PROPERTY_PENDING_CHANGES:
// force refresh of accessory list
fireAccessoryPendingChangesChanged();
break;
case Accessory.PROPERTY_TOTAL_ASPECTS_OF_ACCESSORY:
Integer accessoryId = (evt.getNewValue() != null ? (Integer) evt.getNewValue() : null);
LOGGER
.info("The total aspects of an accessory have been changed, accessory id: {}", accessoryId);
// perform with accessory id
fireAccessoryChanged(accessoryId);
break;
case Accessory.PROPERTY_ACCESSORY_EXECUTION_STATE:
fireAccessoryExecutionStateChanged();
break;
default:
break;
}
}
};
}
@Override
public void postLoadNodeDataProcessing() {
// add the GPIO port identifiers for OneControl and OneDriveTurn nodes
if (node.isPortFlatModelAvailable()) {
LOGGER.info("Set the GPIO port identifiers. Current node: {}", this);
// special handling for OneControl and OneDriveTurn
String switchPortIdentifier = null;
if (ProductUtils.isOneControl(getUniqueId())) {
switchPortIdentifier = "POWER";
}
else if (ProductUtils.isOneDriveTurn(getUniqueId())) {
switchPortIdentifier = "MOTOR";
}
int gpioId = 0;
for (InputPort inputPort : getInputPorts()) {
inputPort.setPortIdentifier("GPIO " + gpioId++);
}
int switchPortId = 0;
gpioId = 0;
for (SwitchPort switchPort : getSwitchPorts()) {
LOGGER.debug("Current switch port: {}", switchPort);
if (!switchPort.isRemappingEnabled()
|| !PortMapUtils.supportsPortType(LcOutputType.INPUTPORT, switchPort.getPortConfigX())) {
if (switchPortIdentifier != null) {
switchPort
.setPortIdentifier(switchPortIdentifier + " " + switchPortId + "/" + (switchPortId + 1));
}
if (!switchPort.isRemappingEnabled()) {
switchPortId += 2;
}
}
else if (switchPort.isRemappingEnabled()) {
switchPort.setPortIdentifier("GPIO " + gpioId++);
}
}
switchPortId = 0;
gpioId = 0;
for (SwitchPairPort switchPairPort : getSwitchPairPorts()) {
LOGGER.debug("Current switchPair port: {}", switchPairPort);
if (!switchPairPort.isRemappingEnabled()
|| !PortMapUtils.supportsPortType(LcOutputType.INPUTPORT, switchPairPort.getPortConfigX())) {
if (switchPortIdentifier != null) {
switchPairPort
.setPortIdentifier(switchPortIdentifier + " " + switchPortId + "/" + (switchPortId + 1));
}
switchPortId += 2;
}
else if (switchPairPort.isRemappingEnabled()) {
switchPairPort.setPortIdentifier("GPIO " + gpioId);
gpioId += 2;
}
}
}
}
@Override
public void refreshNode() {
LOGGER.info("Refresh the node.");
firePortListChanged(AnalogPort.class);
firePortListChanged(BacklightPort.class);
firePortListChanged(InputPort.class);
firePortListChanged(LightPort.class);
firePortListChanged(MotorPort.class);
firePortListChanged(ServoPort.class);
firePortListChanged(SoundPort.class);
firePortListChanged(SwitchPairPort.class);
firePortListChanged(SwitchPort.class);
fireMacroListChanged();
fireAccessoryListChanged();
}
/**
* @return returns address of the node
*/
@Override
public byte[] getAddr() {
return node.getAddr();
}
/**
* @return returns the uniqueId of the node
*/
@Override
public long getUniqueId() {
return node.getUniqueId();
}
@Override
public CommandStationNodeInterface getCommandStationNode() {
return commandStationNodeProxy;
}
@Override
public BoosterNodeInterface getBoosterNode() {
return boosterNodeProxy;
}
@Override
public InterfaceNodeInterface getInterfaceNode() {
return interfaceNodeProxy;
}
@Override
public SwitchingNodeInterface getSwitchingNode() {
return switchingNodeProxy;
}
@Override
public OccupancyNodeInterface getOccupancyNode() {
return occupancyNodeProxy;
}
@Override
public void addNodeListener(NodeListener l) {
listeners.add(l);
addPropertyChangeListener(l);
}
@Override
public void removeNodeListener(NodeListener l) {
listeners.remove(l);
removePropertyChangeListener(l);
}
@Override
public void addPortListListener(Class> portClazz, PortListListener listener) {
List listeners = portListListeners.get(portClazz);
if (listeners == null) {
listeners = new LinkedList<>();
portListListeners.put(portClazz, listeners);
}
listeners.add(listener);
}
@Override
public void removePortListListener(Class> portClazz, PortListListener listener) {
List listeners = portListListeners.get(portClazz);
if (listeners != null) {
listeners.remove(listener);
}
}
@Override
public void addCvDefinitionListener(CvDefinitionListener listener) {
if (!cvDefinitionListeners.contains(listener)) {
cvDefinitionListeners.add(listener);
}
else {
LOGGER.warn("The cvDefinitionListener is registered already: {}", listener);
}
}
@Override
public void removeCvDefinitionListener(CvDefinitionListener listener) {
cvDefinitionListeners.remove(listener);
}
@Override
public void firePortListChanged(Class> portClazz) {
LOGGER.info("The port list has changed for class: {}", portClazz);
List listeners = portListListeners.get(portClazz);
if (listeners != null) {
notifyPortListListeners(listeners);
}
}
private void notifyPortListListeners(final Collection listeners) {
for (PortListListener l : listeners) {
l.listChanged();
}
}
@Override
public void addPortListener(Class> portClazz, PortListener extends Port extends BidibStatus>> listener) {
List>> listeners = portListeners.get(portClazz);
if (listeners == null) {
listeners = new LinkedList<>();
portListeners.put(portClazz, listeners);
}
if (listeners.contains(listener)) {
LOGGER.warn("Listener is already registered: {}", listener);
}
else {
listeners.add(listener);
}
}
@Override
public void removePortListener(Class> portClazz, PortListener extends Port extends BidibStatus>> listener) {
List>> listeners = portListeners.get(portClazz);
if (listeners != null) {
listeners.remove(listener);
}
}
@Override
public void firePortConfigChanged(final Port port) {
Class> portClazz = port.getClass();
LOGGER.debug("The port config has changed for port: {}", port);
List> listeners = portListeners.get(portClazz);
if (listeners != null) {
notifyPortConfigListeners(listeners, port);
}
else {
LOGGER.debug("No port config listeners available for portClazz: {}", portClazz);
}
}
private void notifyPortConfigListeners(
final List> listeners, final Port port) {
PortsChangeWrapper.notifyPortConfigChanged(listeners, this, port);
}
@Override
public void firePortStatusChanged(Class extends Port> portClazz, Port port) {
List> listeners = portListeners.get(portClazz);
if (listeners != null) {
notifyPortStatusListeners(listeners, port);
}
else {
LOGGER.debug("No port status listeners available for portClazz: {}", portClazz);
}
// must check for old nodes that have not port query all enabled
if (StatusIdentifier.InitialLoadFinished != getNodeLoadStatusIdentifier()) {
final SwitchingNodeInterface switchingNode = getSwitchingNode();
if (switchingNode != null && !switchingNode.isPortQueryAllEnabled()) {
// check for pending node status ... if none available trigger the initial node finished flag
AbstractPortHandler>[] handlers =
new AbstractPortHandler>[] { lightPortHandler, inputPortHandler, switchPortHandler,
switchPairPortHandler, servoPortHandler, backlightPortHandler, analogPortHandler,
motorPortHandler, soundPortHandler };
boolean pendingPortStatus = false;
for (AbstractPortHandler> handler : handlers) {
pendingPortStatus = handler.hasPendingPortStatus();
if (pendingPortStatus) {
LOGGER.debug("Found pending port status in handler: {}", handler);
break;
}
}
if (!pendingPortStatus) {
LOGGER.info("No pending port status found on node: {}", this);
signalInitialLoadFinished();
}
}
}
}
private void notifyPortStatusListeners(
final List> listeners, final Port port) {
PortsChangeWrapper.notifyPortStatusChanged(listeners, this, port);
}
/**
* Add a port value listener.
*
* @param portClazz
* the port class
* @param listener
* the listener to add
*/
@Override
public void addPortValueListener(Class> portClazz, PortValueListener> listener) {
List> listeners = portValueListeners.get(portClazz);
if (listeners == null) {
listeners = new LinkedList<>();
portValueListeners.put(portClazz, listeners);
}
listeners.add(listener);
}
/**
* Remove a port value listener.
*
* @param portClazz
* the port class
* @param listener
* the listener to remove
*/
@Override
public void removePortValueListener(Class> portClazz, PortValueListener> listener) {
List> listeners = portValueListeners.get(portClazz);
if (listeners != null) {
listeners.remove(listener);
}
}
@Override
public void firePortValueChanged(Class> portClazz, Port> port) {
LOGGER.info("The port value has changed for class: {}", portClazz);
List> listeners = portValueListeners.get(portClazz);
if (listeners != null) {
notifyPortValueListeners(listeners, port);
}
}
private void notifyPortValueListeners(final Collection> listeners, final Port> port) {
PortsChangeWrapper.notifyPortValueChanged(listeners, this, port);
}
@Override
public void addMacroListListener(MacroListListener listener) {
macroListListeners.add(listener);
}
@Override
public void removeMacroListListener(MacroListListener listener) {
macroListListeners.remove(listener);
}
@Override
public void addAccessoryListListener(AccessoryListListener l) {
accessoryListListeners.add(l);
}
@Override
public void removeAccessoryListListener(AccessoryListListener listener) {
accessoryListListeners.remove(listener);
}
@Override
public void addFlagListListener(FlagListListener l) {
flagListListeners.add(l);
}
@Override
public void removeFlagListListener(FlagListListener l) {
flagListListeners.remove(l);
}
@Override
public Boolean isAddressMessagesEnabled() {
return addressMessagesEnabled;
}
@Override
public void setAddressMessagesEnabled(Boolean addressMessagesEnabled) {
Boolean oldValue = this.addressMessagesEnabled;
this.addressMessagesEnabled = addressMessagesEnabled;
fireAddressMessagesEnabledChanged(addressMessagesEnabled);
firePropertyChange(PROPERTY_ADDRESSMESSAGESENABLED, oldValue, addressMessagesEnabled);
}
@Override
public Boolean isDccStartEnabled() {
return dccStartEnabled;
}
@Override
public void setDccStartEnabled(Boolean dccStartEnabled) {
this.dccStartEnabled = dccStartEnabled;
fireDccStartEnabledChanged(dccStartEnabled);
}
@Override
public Boolean isExternalStartEnabled() {
return externalStartEnabled;
}
@Override
public void setExternalStartEnabled(Boolean externalStartEnabled) {
this.externalStartEnabled = externalStartEnabled;
fireExternalStartEnabledChanged(externalStartEnabled);
}
@Override
public Boolean isFeedbackMessagesEnabled() {
return feedbackMessagesEnabled;
}
@Override
public void setFeedbackMessagesEnabled(Boolean feedbackMessagesEnabled) {
this.feedbackMessagesEnabled = feedbackMessagesEnabled;
fireFeedbackMessagesEnabledChanged(feedbackMessagesEnabled);
}
@Override
public Boolean isFeedbackMirrorDisabled() {
return feedbackMirrorDisabled;
}
@Override
public void setFeedbackMirrorDisabled(Boolean feedbackMirrorDisabled) {
LOGGER.info("Set the feedback mirror messages disabled: {}", feedbackMirrorDisabled);
this.feedbackMirrorDisabled = feedbackMirrorDisabled;
fireFeedbackMirrorDisabledChanged(feedbackMirrorDisabled);
}
@Override
public IdentifyState getIdentifyState() {
return identifyState;
}
@Override
public void setIdentifyState(final IdentifyState identifyState) {
LOGGER.info("Set the identifyState: {}", identifyState);
final IdentifyState oldValue = this.identifyState;
this.identifyState = identifyState;
firePropertyChange(PROPERTY_IDENTIFY_STATE, oldValue, this.identifyState);
fireIdentifyStateChanged(identifyState);
}
@Override
public void setDetachedState(final DetachedState detachedState) {
final DetachedState oldValue = this.detachedState;
this.detachedState = detachedState;
this.node.setDetached(detachedState == DetachedState.DETACHED);
firePropertyChange(PROPERTY_DETACHED, oldValue, this.detachedState);
fireDetachedStateChanged(detachedState);
}
@Override
public DetachedState getDetachedState() {
return detachedState;
}
public final static class ErrorStatePropertyChange {
private final SysErrorEnum sysError;
private final String reasonData;
public ErrorStatePropertyChange(SysErrorEnum sysError, String reasonData) {
super();
this.sysError = sysError;
this.reasonData = reasonData;
}
/**
* @return the sysError
*/
public SysErrorEnum getSysError() {
return sysError;
}
/**
* @return the reasonData
*/
public String getReasonData() {
return reasonData;
}
}
@Override
public void setErrorState(final SysErrorEnum sysError, final String reasonData) {
LOGGER.info("Set the error state: {}, reasonData: {}", sysError, reasonData);
final ErrorStatePropertyChange oldValue = new ErrorStatePropertyChange(this.sysError, this.reasonData);
this.sysError = sysError;
this.reasonData = reasonData;
final ErrorStatePropertyChange newValue = new ErrorStatePropertyChange(this.sysError, this.reasonData);
firePropertyChange(PROPERTY_ERROR_STATE, oldValue, newValue);
}
@Override
public SysErrorEnum getErrorState() {
return sysError;
}
@Override
public String getReasonData() {
return reasonData;
}
@Override
public void setReasonData(final String reasonData) {
final ErrorStatePropertyChange oldValue = new ErrorStatePropertyChange(this.sysError, this.reasonData);
this.reasonData = reasonData;
final ErrorStatePropertyChange newValue = new ErrorStatePropertyChange(this.sysError, this.reasonData);
LOGGER.info("New reason data was set.");
firePropertyChange(PROPERTY_REASON_DATA, oldValue, newValue);
}
@Override
public boolean isNodeHasRestartPendingError() {
return SysErrorEnum.BIDIB_ERR_RESET_REQUIRED.equals(sysError);
}
@Override
public Boolean isKeyMessagesEnabled() {
return keyMessagesEnabled;
}
@Override
public void setInputMessagesEnabled(Boolean keyMessagesEnabled) {
this.keyMessagesEnabled = keyMessagesEnabled;
fireKeyMessagesEnabledChanged(keyMessagesEnabled);
}
@Override
public String getLabel() {
if (this.node != null) {
// we prefer the name from the core node
String userName = this.node.getStoredString(StringData.INDEX_USERNAME);
LOGGER.trace("Found userName: {}", userName);
if (StringUtils.isNotBlank(userName)) {
return userName;
}
}
return label;
}
@Override
public void setLabel(String label) {
LOGGER.info("Set the label: {}", label);
String oldValue = this.label;
this.label = label;
firePropertyChange(PROPERTY_LABEL, oldValue, label);
fireLabelsChanged();
}
@Override
public org.bidib.jbidibc.messages.Node getNode() {
return node;
}
@Override
public int getStorableMacroCount() {
return storableMacroCount;
}
@Override
public void setStorableMacroCount(int storableMacroCount) {
this.storableMacroCount = storableMacroCount;
}
/**
* @return the maximum supported steps per macro
*/
@Override
public int getMaxMacroSteps() {
return maxMacroSteps;
}
/**
* @param maxMacroSteps
* the maximum supported steps per macro
*/
public void setMaxMacroSteps(int maxMacroSteps) {
this.maxMacroSteps = maxMacroSteps;
}
/**
* @return the genericPorts
*/
@Override
public List getGenericPorts() {
return genericPortConfigHandler.getGenericPorts();
}
@Override
public List> getPorts() {
List> ports = new LinkedList<>();
ports.addAll(analogPortHandler.getPorts(this));
ports.addAll(backlightPortHandler.getPorts(this));
ports.addAll(inputPortHandler.getPorts(this));
ports.addAll(lightPortHandler.getPorts(this));
ports.addAll(motorPortHandler.getPorts(this));
ports.addAll(servoPortHandler.getPorts(this));
ports.addAll(soundPortHandler.getPorts(this));
ports.addAll(switchPairPortHandler.getPorts(this));
ports.addAll(switchPortHandler.getPorts(this));
return ports;
}
/**
* @param genericPorts
* the genericPorts to set
*/
@Override
public void setGenericPorts(List genericPorts) {
synchronized (this.genericPortsLock) {
LOGGER.info("Set the generic ports on the node: {}", this);
genericPortConfigHandler.setGenericPorts(genericPorts);
clearPortCache();
}
}
/**
* @return the flag returns {@code true} after the generic ports are set, {@code false} otherwise
*/
@Override
public boolean isGenericPortsSet() {
return genericPortConfigHandler.isGenericPortsSet();
}
@Override
public void setPortConfig(
LcOutputType portType, int portNumber, Map> portConfig,
final PropertyChangeListener pcl) {
if (node.isPortFlatModelAvailable()) {
// use the port config handler to set the port config
genericPortConfigHandler.setPortConfig(portNumber, portConfig, pcl, this);
}
else {
LOGGER
.info("Set port config for type-oriented port model, porttype: {}, portNumber: {}", portType,
portNumber);
switch (portType) {
case ANALOGPORT:
setAnalogPortConfig(portNumber, portConfig);
break;
case BACKLIGHTPORT:
setBacklightPortConfig(portNumber, portConfig);
break;
case INPUTPORT:
setInputPortConfig(portNumber, portConfig);
break;
case LIGHTPORT:
setLightPortConfig(portNumber, portConfig);
break;
case MOTORPORT:
setMotorPortConfig(portNumber, portConfig);
break;
case SERVOPORT:
setServoPortConfig(portNumber, portConfig);
break;
case SOUNDPORT:
setSoundPortConfig(portNumber, portConfig);
break;
case SWITCHPORT:
setSwitchPortConfig(portNumber, portConfig);
break;
// add support for more port types
default:
break;
}
}
}
@Override
public void clearPortCache() {
LOGGER.info("Clear the port cache on node: {}", this);
synchronized (genericPortsLock) {
// clear all cached ports
analogPortHandler.clearPorts(this);
backlightPortHandler.clearPorts(this);
feedbackPortHandler.clearPorts(this);
inputPortHandler.clearPorts(this);
lightPortHandler.clearPorts(this);
motorPortHandler.clearPorts(this);
servoPortHandler.clearPorts(this);
soundPortHandler.clearPorts(this);
switchPortHandler.clearPorts(this);
switchPairPortHandler.clearPorts(this);
}
}
@Override
public void setAnalogPorts(List analogPorts) {
LOGGER.info("Set the analog ports on the node: {}", analogPorts);
analogPortHandler.setPorts(analogPorts, this);
}
@Override
public List getAnalogPorts() {
return analogPortHandler.getPorts(this);
}
@Override
public boolean hasAnalogPorts() {
LOGGER.debug("Check if analog ports are available.");
return analogPortHandler.hasPorts();
}
/**
* Set the configuration of the analog port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setAnalogPortConfig(int portNumber, Map> portConfig) {
analogPortHandler.setPortConfig(portNumber, portConfig, this);
}
@Override
public void setSwitchPorts(List switchPorts) {
LOGGER.info("Set the switch ports on the node: {}", switchPorts);
switchPortHandler.setPorts(switchPorts, this);
}
@Override
public List getSwitchPorts() {
return switchPortHandler.getPorts(this);
}
@Override
public List getEnabledSwitchPorts() {
return switchPortHandler.getEnabledPorts();
}
/**
* Set the configuration of the switch port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setSwitchPortConfig(int portNumber, Map> portConfig) {
switchPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return node has switch ports
*/
@Override
public boolean hasSwitchPorts() {
LOGGER.debug("Check if switch ports are available.");
return switchPortHandler.hasPorts();
}
/**
* Set the new switch port status.
*
* @param portNumber
* the port number
* @param portState
* the port state
*/
@Override
public void setSwitchPortStatus(final int portNumber, int portState) {
switchPortHandler.setPortStatus(portNumber, portState, this);
}
@Override
public void setSwitchPairPorts(List switchPairPorts) {
LOGGER.info("Set the switchPair ports on the node: {}", switchPairPorts);
switchPairPortHandler.setPorts(switchPairPorts, this);
}
@Override
public List getSwitchPairPorts() {
return switchPairPortHandler.getPorts(this);
}
@Override
public List getEnabledSwitchPairPorts() {
return switchPairPortHandler.getEnabledPorts();
}
/**
* Set the configuration of the switchPair port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setSwitchPairPortConfig(int portNumber, Map> portConfig) {
switchPairPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return node has switchPair ports
*/
@Override
public boolean hasSwitchPairPorts() {
LOGGER.debug("Check if switchPair ports are available.");
return switchPairPortHandler.hasPorts();
}
/**
* Set the new switchPair port status.
*
* @param portNumber
* the port number
* @param portState
* the port state
*/
@Override
public void setSwitchPairPortStatus(final int portNumber, int portState) {
switchPairPortHandler.setPortStatus(portNumber, portState, this);
}
@Override
public void setLightPorts(List lightPorts) {
LOGGER.info("Set the light ports on the node: {}", lightPorts);
lightPortHandler.setPorts(lightPorts, this);
}
@Override
public List getLightPorts() {
return lightPortHandler.getPorts(this);
}
@Override
public List getEnabledLightPorts() {
return lightPortHandler.getEnabledPorts();
}
/**
* Set the configuration of the light port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setLightPortConfig(int portNumber, Map> portConfig) {
LOGGER.info("Set the lightport config for port: {}", portNumber);
lightPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return node has light ports
*/
@Override
public boolean hasLightPorts() {
LOGGER.debug("Check if light ports are available.");
return lightPortHandler.hasPorts();
}
/**
* Set the new switch port status.
*
* @param portNumber
* the port number
* @param portState
* the port state
*/
@Override
public void setLightPortStatus(final int portNumber, int portState) {
lightPortHandler.setPortStatus(portNumber, portState, this);
}
@Override
public void setBacklightPorts(List backlightPorts) {
LOGGER.info("Set the backlight ports on the node: {}", backlightPorts);
backlightPortHandler.setPorts(backlightPorts, this);
}
/**
* @return the backlight ports
*/
@Override
public List getBacklightPorts() {
return backlightPortHandler.getPorts(this);
}
/**
* Set the configuration of the backlight port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setBacklightPortConfig(int portNumber, Map> portConfig) {
backlightPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return the port has backlight ports
*/
@Override
public boolean hasBacklightPorts() {
LOGGER.debug("Check if backlight ports are available.");
return backlightPortHandler.hasPorts();
}
@Override
public void setBacklightPortValue(int portNumber, int portValue) {
backlightPortHandler.setPortValue(portNumber, portValue, this);
}
@Override
public void setInputPorts(List inputPorts) {
LOGGER.info("Set the input ports on the node: {}", inputPorts);
inputPortHandler.setPorts(inputPorts, this);
}
@Override
public List getInputPorts() {
return inputPortHandler.getPorts(this);
}
@Override
public List getEnabledInputPorts() {
return inputPortHandler.getEnabledPorts();
}
/**
* Set the configuration of the input port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
public void setInputPortConfig(int portNumber, Map> portConfig) {
inputPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return the port has input ports
*/
@Override
public boolean hasInputPorts() {
LOGGER.debug("Check if input ports are available.");
return inputPortHandler.hasPorts();
}
@Override
public void setInputPortStatus(final int portNumber, int portState) {
inputPortHandler.setPortStatus(portNumber, portState, this);
}
@Override
public void setServoPorts(List servoPorts) {
LOGGER.info("Set the servo ports on the node: {}", servoPorts);
servoPortHandler.setPorts(servoPorts, this);
}
@Override
public List getServoPorts() {
return servoPortHandler.getPorts(this);
}
/**
* Set the configuration of the servo port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setServoPortConfig(int portNumber, Map> portConfig) {
servoPortHandler.setPortConfig(portNumber, portConfig, this);
}
@Override
public boolean hasServoPorts() {
LOGGER.debug("Check if servo ports are available.");
return servoPortHandler.hasPorts();
}
@Override
public void setServoPortValue(int portNumber, int portValue) {
servoPortHandler.setPortValue(portNumber, portValue, this);
}
@Override
public void setMotorPorts(List motorPorts) {
LOGGER.info("Set the motor ports on the node: {}", motorPorts);
motorPortHandler.setPorts(motorPorts, this);
}
@Override
public List getMotorPorts() {
return motorPortHandler.getPorts(this);
}
/**
* Set the configuration of the motor port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
public void setMotorPortConfig(int portNumber, Map> portConfig) {
motorPortHandler.setPortConfig(portNumber, portConfig, this);
}
@Override
public boolean hasMotorPorts() {
LOGGER.debug("Check if motor ports are available.");
return motorPortHandler.hasPorts();
}
@Override
public void setMotorPortValue(final int portNumber, int portValue) {
motorPortHandler.setPortValue(portNumber, portValue, this);
}
@Override
public void setSoundPorts(List soundPorts) {
LOGGER.info("Set the sound ports on the node: {}", soundPorts);
soundPortHandler.setPorts(soundPorts, this);
}
/**
* @return the sound ports
*/
@Override
public List getSoundPorts() {
return soundPortHandler.getPorts(this);
}
/**
* Set the configuration of the sound port.
*
* @param portNumber
* the port number
* @param portConfig
* the new port configuration
*/
@Override
public void setSoundPortConfig(int portNumber, Map> portConfig) {
soundPortHandler.setPortConfig(portNumber, portConfig, this);
}
/**
* @return the port has sound ports
*/
@Override
public boolean hasSoundPorts() {
LOGGER.debug("Check if sound ports are available.");
return soundPortHandler.hasPorts();
}
@Override
public List getEnabledSoundPorts() {
return soundPortHandler.getEnabledPorts();
}
/**
* Set the new sound port status.
*
* @param portNumber
* the port number
* @param portState
* the port state
*/
@Override
public void setSoundPortStatus(final int portNumber, int portState) {
soundPortHandler.setPortStatus(portNumber, portState, this);
}
@Override
public boolean isGlobalDetectorAvailable() {
return globalDetectorAvailable;
}
@Override
public void setGlobalDetectorAvailable(boolean globalDetectorAvailable) {
this.globalDetectorAvailable = globalDetectorAvailable;
}
@Override
public int getBaseNumber() {
return baseNumber;
}
@Override
public void setBaseNumber(int baseNumber) {
int oldValue = this.baseNumber;
this.baseNumber = baseNumber;
firePropertyChange(PROPERTY_BASENUMBER, oldValue, this.baseNumber);
}
@Override
public boolean isUpdatable() {
return updatable;
}
@Override
public void setUpdatable(boolean updatable) {
this.updatable = updatable;
}
@Override
public SoftwareVersion getUpdateFirmwareVersion() {
return this.updateFirmwareVersion;
}
@Override
public void setUpdateFirmwareVersion(SoftwareVersion updateFirmwareVersion) {
SoftwareVersion oldValue = this.updateFirmwareVersion;
this.updateFirmwareVersion = updateFirmwareVersion;
firePropertyChange(PROPERTY_UDPATE_FIRMWARE_VERSION, oldValue, this.updateFirmwareVersion);
}
/**
* @return the bootloaderNode
*/
@Override
public boolean isBootloaderNode() {
return bootloaderNode;
}
/**
* @param bootloaderNode
* the bootloaderNode to set
*/
@Override
public void setBootloaderNode(boolean bootloaderNode) {
this.bootloaderNode = bootloaderNode;
}
/**
* @return the nodeHasError
*/
@Override
public boolean isNodeHasError() {
return nodeHasError || (sysError != null && !SysErrorEnum.BIDIB_ERR_NONE.equals(sysError));
}
/**
* @param ignoreSysError
* flag to allow ignore sys errors
* @return node has error flag set
*/
@Override
public boolean isNodeHasError(boolean ignoreSysError) {
if (ignoreSysError) {
return nodeHasError;
}
return isNodeHasError();
}
/**
* @return the nodeHasSysError
*/
public boolean isNodeHasSysError() {
return (sysError != null && !SysErrorEnum.BIDIB_ERR_NONE.equals(sysError));
}
/**
* @param nodeHasError
* the nodeHasError to set
*/
@Override
public void setNodeHasError(boolean nodeHasError) {
LOGGER.info("The node has an error: {}", nodeHasError);
boolean oldValue = this.nodeHasError;
this.nodeHasError = nodeHasError;
if (!nodeHasError) {
setErrorState(null, null);
}
firePropertyChange(PROPERTY_NODE_HAS_ERROR, oldValue, this.nodeHasError);
}
@Override
public boolean isFlatPortModel() {
return getNode().isPortFlatModelAvailable();
}
/**
* @return the vendorCV
*/
@Override
public VendorCvData getVendorCV() {
return vendorCV;
}
/**
* @param vendorCV
* the vendorCV to set
*/
@Override
public void setVendorCV(VendorCvData vendorCV) {
LOGGER.debug("Set the vendorCV: {}", vendorCV);
this.vendorCV = vendorCV;
}
@Override
public Map getConfigVariables() {
if (configVariables == null) {
return Collections.emptyMap();
}
// TODO return Collections.unmodifiableMap() ???
return configVariables;
}
@Override
public void setConfigVariables(List configurationVariables) {
final List changedNames = new LinkedList<>();
synchronized (configVarsLock) {
LOGGER.info("Set the configuration variables. Clear the old configuration variables.");
this.configVariables.clear();
if (configurationVariables != null) {
// create list with distinct items
changedNames
.addAll(configurationVariables
.stream().map(cv -> cv.getName()).distinct().collect(Collectors.toList()));
// create a map with the cvName as key and the CV as value
this.configVariables
.putAll(configurationVariables
.stream().distinct().collect(Collectors.toMap(cv -> cv.getName(), cv -> cv)));
}
}
fireConfigurationVariablesChanged(false, changedNames);
}
/**
* @param configurationVars
* the configurationVariable values to update
*/
@Override
public void updateConfigVariableValues(final List configurationVars, final boolean read) {
// iterate over the collection of stored variables in the model and update the values.
// After that notify the tree and delete the new values that are now stored in the node
LOGGER.info("Write config variables to node, number of CVs: {}, read: {}", configurationVars.size(), read);
final List changedNames = new LinkedList<>();
synchronized (configVarsLock) {
for (ConfigurationVariable updatedCV : configurationVars) {
changedNames.add(updatedCV.getName());
ConfigurationVariable storedCV = this.configVariables.get(updatedCV.getName());
if (storedCV != null) {
storedCV.setValue(updatedCV.getValue());
storedCV.setTimeout(updatedCV.isTimeout());
}
else {
LOGGER
.info("Add new CV because the updated CV was not found in the stored CV values: {}", updatedCV);
configVariables.put(updatedCV.getName(), updatedCV);
}
}
LOGGER.info("Number of stored CV: {}", configVariables.size());
}
fireConfigurationVariablesChanged(read, changedNames);
}
private void fireConfigurationVariablesChanged(final boolean read, final List changedNames) {
notifyConfigurationVariableValueListeners(cvDefinitionListeners, read, changedNames);
}
private void notifyConfigurationVariableValueListeners(
final Collection listeners, final boolean read, final List changedNames) {
for (CvDefinitionListener l : listeners) {
l.cvDefinitionValuesChanged(read, changedNames);
}
}
private void fireAddressMessagesEnabledChanged(Boolean isAddressMessagesEnabled) {
for (NodeListener l : listeners) {
l.addressMessagesEnabledChanged(this, isAddressMessagesEnabled);
}
}
private void fireDccStartEnabledChanged(Boolean isDccStartEnabled) {
for (NodeListener l : listeners) {
l.dccStartEnabledChanged(this, isDccStartEnabled);
}
}
private void fireExternalStartEnabledChanged(Boolean isExternalStartEnabled) {
for (NodeListener l : listeners) {
l.externalStartEnabledChanged(this, isExternalStartEnabled);
}
}
private void fireFeedbackMessagesEnabledChanged(Boolean isFeedbackMessagesEnabled) {
for (NodeListener l : listeners) {
l.feedbackMessagesEnabledChanged(this, isFeedbackMessagesEnabled);
}
}
private void fireFeedbackMirrorDisabledChanged(Boolean feedbackMirrorDisabled) {
for (NodeListener l : listeners) {
l.feedbackMirrorDisabledChanged(this, feedbackMirrorDisabled);
}
}
private void fireIdentifyStateChanged(IdentifyState identifyState) {
for (NodeListener l : listeners) {
l.identifyStateChanged(this, identifyState);
}
}
private void fireDetachedStateChanged(DetachedState detachedState) {
for (NodeListener l : listeners) {
l.detachedStateChanged(this, detachedState);
}
}
private void fireKeyMessagesEnabledChanged(Boolean isKeyMessagesEnabled) {
for (NodeListener l : listeners) {
l.keyMessagesEnabledChanged(this, isKeyMessagesEnabled);
}
}
private void fireLabelsChanged() {
for (NodeListener l : listeners) {
l.labelsChanged(this);
}
}
@Override
public boolean equals(Object other) {
LOGGER.debug("equals, other: {}", other);
if (other != null) {
return ((Node) other).getNode().equals(node);
}
return false;
}
@Override
public int hashCode() {
if (node != null) {
return node.hashCode();
}
else {
LOGGER.warn("No core node available!");
}
return super.hashCode();
}
@Override
public String toString() {
String result = getLabel();
if (StringUtils.isNotBlank(result)) {
return "[" + NodeUtils.formatAddress(getAddr()) + "] " + result;
}
result = ByteUtils.getUniqueIdAsString(node.getUniqueId());
return "[" + NodeUtils.formatAddress(getAddr()) + "] " + result;
}
@Override
public String toNodeAddressAndUniqueString() {
final StringBuilder nodeData = new StringBuilder();
nodeData.append("[").append(NodeUtils.formatAddress(getAddr())).append("], ");
nodeData.append(ByteUtils.getUniqueIdAsString(node.getUniqueId()));
String result = getLabel();
if (StringUtils.isNotBlank(result)) {
nodeData.append(", ").append(result);
}
return nodeData.toString();
}
@Override
public FeedbackPort getGlobalDetectorFeedbackPort() {
LOGGER.debug("Get the feedback ports.");
return feedbackPortHandler.getGlobalDetectorFeedbackPort();
}
@Override
public List getFeedbackPorts() {
LOGGER.debug("Get the feedback ports.");
return feedbackPortHandler.getPorts(this);
}
@Override
public void setFeedbackPorts(List feedbackPorts) {
LOGGER.info("Set the feedback ports: {}", feedbackPorts);
feedbackPortHandler.setPorts(feedbackPorts, this);
}
@Override
public boolean hasFeedbackPorts() {
LOGGER.debug("Check if feedback ports are available.");
return feedbackPortHandler.hasPorts();
}
@Override
public int getFeedbackPortCount() {
if (getOccupancyNode() != null) {
return getOccupancyNode().getFeedbackPortCount();
}
return 0;
}
/**
* Set the feedback port status.
*
* @param detectorNumber
* the detector number
* @param status
* the new port status
* @param timestamp
* the timestamp
*/
@Override
public void setFeedbackPortStatus(int detectorNumber, final FeedbackPortStatus status, final Integer timestamp) {
LOGGER
.debug("feedback port status, detector number: {}, status: {}, timestamp: {}", detectorNumber, status,
timestamp);
feedbackPortHandler.setPortStatus(detectorNumber, status, timestamp, this);
}
/**
* Set the detected addresses for the feedback port.
*
* @param detectorNumber
* the detector number
* @param addresses
* the detected addresses
*/
@Override
public void setFeedbackPortAddresses(int detectorNumber, final List addresses) {
LOGGER.debug("feedback port addresses, detector number: {}, addresses: {}", detectorNumber, addresses);
feedbackPortHandler.setPortAddresses(detectorNumber, addresses, this);
}
/**
* Confidence is signaled from the node.
*
* @param feedbackConfidenceStatus
* the confidence status
*/
@Override
public void setFeedbackPortGroupConfidence(final FeedbackConfidenceStatus feedbackConfidenceStatus) {
LOGGER.debug("feedback port confidence, feedbackConfidenceStatus: {}", feedbackConfidenceStatus);
feedbackPortHandler
.setFeedbackPortGroupConfidence(feedbackConfidenceStatus, this, (propertyName, oldValue, newValue) -> {
LOGGER.info("Fire the property change for propertyName: {}, newValue: {}", propertyName, newValue);
firePropertyChange(propertyName, oldValue, newValue);
});
}
@Override
public FeedbackConfidenceStatus getFeedbackPortGroupConfidence() {
return feedbackPortHandler.getFeedbackPortGroupConfidence();
}
/**
* Confidence is signaled from the node.
*
* @param portNumber
* the port number (not the detector number)
* @param freeze
* the freeze flag of the detector
* @param noSignal
* the noSignal flag of the detector
* @param invalid
* {@code false} the occupancy detection is detected from the track signal of the detector, {@code true}
* detection of occupancy is not possible
*/
@Override
public void setFeedbackPortConfidence(int portNumber, boolean invalid, boolean freeze, boolean noSignal) {
LOGGER
.debug("feedback port confidence, port number: {}, invalid: {}, freeze: {}, noSignal: {}", portNumber,
invalid, freeze, noSignal);
feedbackPortHandler.setFeedbackPortConfidence(portNumber, invalid, freeze, noSignal, this);
}
@Override
public void setFeedbackPortSpeed(int detectorNumber, int address, int speed) {
LOGGER
.debug("feedback port speed, detector number: {}, address: {}, speed: {}", detectorNumber, address, speed);
feedbackPortHandler.setFeedbackPortSpeed(detectorNumber, address, speed, this);
}
@Override
public void setFeedbackPortDynStates(int detectorNumber, final List dynStates) {
feedbackPortHandler.setFeedbackPortDynStates(detectorNumber, dynStates, this);
}
@Override
public List getFlags() {
return Collections.unmodifiableList(flags);
}
@Override
public void setFlags(Collection flags) {
// synchronize because the flags can be accessed from different threads
synchronized (this.flags) {
this.flags.clear();
if (flags != null) {
this.flags.addAll(flags);
}
}
fireFlagListChanged();
}
/**
* Set the macros of the current node.
*
* @param macros
* the macros
*/
@Override
public void setMacros(List macros) {
synchronized (this.macros) {
// remove existing property change listener
for (Macro macro : this.macros) {
macro.removePropertyChangeListener(Macro.PROPERTY_PENDING_CHANGES, macroPendingChangesListener);
}
// clear references to existing macros
this.macros.clear();
if (macros != null) {
// ... and add new macros
this.macros.addAll(macros);
// sort by macro id
Collections.sort(this.macros, new Comparator() {
@Override
public int compare(Macro o1, Macro o2) {
return (o1.getId() - o2.getId());
}
});
}
// add property change listener to new macros
for (Macro macro : this.macros) {
macro.addPropertyChangeListener(Macro.PROPERTY_PENDING_CHANGES, macroPendingChangesListener);
}
}
fireMacroListChanged();
}
@Override
public List getMacros() {
synchronized (macros) {
return Collections.unmodifiableList(macros);
}
}
/**
* @return node has macros
*/
@Override
public boolean hasMacros() {
LOGGER.debug("Check if macros are available.");
synchronized (macros) {
return CollectionUtils.isNotEmpty(macros);
}
}
/**
* Check if all macros were loaded from the node.
*
* @return unloaded macro detected
*/
@Override
public boolean hasUnloadedMacros() {
synchronized (macros) {
for (Macro macro : macros) {
if (MacroSaveState.NOT_LOADED_FROM_NODE.equals(macro.getMacroSaveState())) {
return true;
}
}
}
return false;
}
/**
* Replace the macro with the provided macro.
*
* @param macro
* the new macro
*/
@Override
public Macro replaceMacro(final Macro macro, boolean silent) {
LOGGER.info("Replace the macro: {}", macro);
Macro existingMacro = null;
synchronized (macros) {
existingMacro = macros.get(macro.getId());
if (existingMacro != null) {
if (existingMacro == macro) {
LOGGER.info("Skip update the same instance: {}", macro);
}
else {
// replace the content of the existing macro but not the macro instance itself
existingMacro.clearFunctions();
existingMacro.clearStartConditions();
existingMacro.setFunctions(macro.getFunctions());
existingMacro.setStartConditions(macro.getStartConditions());
existingMacro.setCycles(macro.getCycles());
existingMacro.setSpeed(macro.getSpeed());
// keep the name of the macro
if (StringUtils.isNotBlank(macro.getLabel())) {
existingMacro.setLabel(macro.getLabel());
}
}
}
else {
LOGGER.warn("No existing macro found with id: {}", macro.getId());
}
}
if (!silent) {
fireMacroListChanged();
}
return existingMacro;
}
private void fireMacroListChanged() {
LOGGER.info("The macro list has changed.");
for (MacroListListener l : macroListListeners) {
l.listChanged();
}
}
private void fireMacroPendingChangesChanged() {
for (MacroListListener l : macroListListeners) {
l.pendingChangesChanged();
}
}
@Override
public void setAccessories(List accessories) {
List oldValue = null;
synchronized (this.accessories) {
LOGGER.info("Set accessories: {}", accessories);
// remove existing property change listener
for (Accessory accessory : this.accessories) {
accessory.removePropertyChangeListener(accessoryPendingChangesListener);
}
oldValue = new LinkedList<>(this.accessories);
this.accessories.clear();
if (accessories != null) {
this.accessories.addAll(accessories);
// sort by accessory id
Collections.sort(this.accessories, new Comparator() {
@Override
public int compare(Accessory o1, Accessory o2) {
return (o1.getId() - o2.getId());
}
});
}
// add property change listener to new accessory
for (Accessory accessory : this.accessories) {
accessory.addPropertyChangeListener(accessoryPendingChangesListener);
}
}
fireAccessoryListChanged();
firePropertyChange(PROPERTY_ACCESSORIES, oldValue, accessories);
}
@Override
public List getAccessories() {
synchronized (accessories) {
return Collections.unmodifiableList(accessories);
}
}
/**
* @return node has accessories
*/
@Override
public boolean hasAccessories() {
LOGGER.debug("Check if accessories are available.");
synchronized (accessories) {
return CollectionUtils.isNotEmpty(accessories);
}
}
@Override
public int getMaxAspects() {
return maxAspectsCount;
}
@Override
public void setMaxAspects(int maxAspectsCount) {
this.maxAspectsCount = maxAspectsCount;
}
@Override
public Accessory replaceAccessory(final Accessory accessory, boolean silent) {
Accessory existingAccessory = null;
synchronized (accessories) {
existingAccessory = accessories.get(accessory.getId());
LOGGER.info("Found accessory to update: {}", existingAccessory);
if (existingAccessory != null) {
// if (accessory.getStartupState() != null) {
existingAccessory.setStartupState(accessory.getStartupState());
// }
// else {
// LOGGER.info("Set the startup state to unchanged.");
// existingAccessory.setStartupState(BidibLibrary.ASPECT_PARAM_UNCHANGED);
// }
// keep the switch time
existingAccessory.setSwitchTime(accessory.getSwitchTime());
// keep the time base unit
existingAccessory.setTimeBaseUnit(accessory.getTimeBaseUnit());
// add the aspects
existingAccessory.setAspects(accessory.getAspects());
// keep the name of the accessory
if (StringUtils.isNotBlank(accessory.getLabel())) {
existingAccessory.setLabel(accessory.getLabel());
}
// sort by accessory id
Collections.sort(this.accessories, new Comparator() {
@Override
public int compare(Accessory o1, Accessory o2) {
return (o1.getId() - o2.getId());
}
});
}
else {
LOGGER.warn("No existing accessory found with id: {}", accessory.getId());
}
}
if (!silent) {
fireAccessoryListChanged();
}
return existingAccessory;
}
private void fireAccessoryPendingChangesChanged() {
for (AccessoryListListener l : accessoryListListeners) {
l.pendingChangesChanged();
}
}
private void fireAccessoryExecutionStateChanged() {
for (AccessoryListListener l : accessoryListListeners) {
l.pendingChangesChanged();
}
}
private void fireAccessoryChanged(Integer accessoryId) {
for (AccessoryListListener l : accessoryListListeners) {
l.accessoryChanged(accessoryId);
}
}
private void fireAccessoryListChanged() {
for (AccessoryListListener l : accessoryListListeners) {
l.listChanged();
}
}
private void fireFlagListChanged() {
notifyFlagListListeners(flagListListeners);
}
private void notifyFlagListListeners(final Collection listeners) {
for (FlagListListener l : listeners) {
l.listChanged();
}
}
@Override
public void setFeedbackPosition(
int decoderAddress, PositionLocationEnum locationType, int locationAddress, byte[] extendedData) {
// TODO keep the feedback positions?
FeedbackPosition feedbackPosition =
new FeedbackPosition(decoderAddress, locationType, locationAddress, extendedData,
System.currentTimeMillis());
firePropertyChange(PROPERTY_FEEDBACKPOSITIONS, null, feedbackPosition);
}
@Override
public boolean isCvDefinitionAvailable() {
return vendorCV != null;
}
@Override
public void firePortIndexedPropertyChange(
final Port port, String propertyName, int index, Object oldValue, Object newValue) {
super.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
}
@Override
public void signalInitialLoadRegistered() {
StatusIdentifier oldValue;
synchronized (this.initialLoadFinishedLock) {
oldValue = nodeLoadStatus;
this.nodeLoadStatus = StatusIdentifier.InitialLoadRegistered;
}
LOGGER
.info("The node load status is changed to registered, node: {}, address: {}, oldValue: {}", this,
NodeUtils.formatAddress(getAddr()), oldValue);
// TODO we should decouple the property change from the thread that changes the property value
firePropertyChange(PROPERTY_NODE_LOAD_STATUS, oldValue, StatusIdentifier.InitialLoadRegistered);
final NodeStatusEvent nse =
new NodeStatusEvent(publisher.getConnectionId(), publisher.getUniqueId(),
NodeUtils.formatAddress(getAddr()), StatusIdentifier.InitialLoadRegistered);
LOGGER.info("Publish the nodeStatusEvent: {}", nse);
publisher.getSubjectNodeEvents().onNext(nse);
}
@Override
public void signalInitialLoadFinished() {
StatusIdentifier oldValue;
synchronized (this.initialLoadFinishedLock) {
oldValue = nodeLoadStatus;
this.nodeLoadStatus = StatusIdentifier.InitialLoadFinished;
this.initialLoadFinishedLock.notifyAll();
}
LOGGER
.info("The initial load has finished, node: {}, address: {}, oldValue: {}", this,
NodeUtils.formatAddress(getAddr()), oldValue);
// TODO we should decouple the property change from the thread that changes the property value
firePropertyChange(PROPERTY_NODE_LOAD_STATUS, oldValue, StatusIdentifier.InitialLoadFinished);
final NodeStatusEvent nse =
new NodeStatusEvent(publisher.getConnectionId(), publisher.getUniqueId(),
NodeUtils.formatAddress(getAddr()), StatusIdentifier.InitialLoadFinished);
LOGGER.info("Publish the nodeStatusEvent: {}", nse);
publisher.getSubjectNodeEvents().onNext(nse);
}
@Override
public void signalInitialLoadPartiallyFinished() {
StatusIdentifier oldValue;
synchronized (this.initialLoadFinishedLock) {
oldValue = nodeLoadStatus;
this.nodeLoadStatus = StatusIdentifier.InitialLoadPartiallyFinished;
this.initialLoadFinishedLock.notifyAll();
}
LOGGER
.info("The initial load has partially finished, node: {}, address: {}, oldValue: {}", this,
NodeUtils.formatAddress(getAddr()), oldValue);
// TODO we should decouple the property change from the thread that changes the property value
firePropertyChange(PROPERTY_NODE_LOAD_STATUS, oldValue, StatusIdentifier.InitialLoadPartiallyFinished);
final NodeStatusEvent nse =
new NodeStatusEvent(publisher.getConnectionId(), publisher.getUniqueId(),
NodeUtils.formatAddress(getAddr()), StatusIdentifier.InitialLoadPartiallyFinished);
LOGGER.info("Publish the nodeStatusEvent: {}", nse);
publisher.getSubjectNodeEvents().onNext(nse);
}
@Override
public void signalResetInitialLoadFinished() {
// LOGGER.info("The initial load is reset, node: {}", this);
StatusIdentifier oldValue;
synchronized (this.initialLoadFinishedLock) {
oldValue = nodeLoadStatus;
this.nodeLoadStatus = StatusIdentifier.InitialLoadPending;
this.initialLoadFinishedLock.notifyAll();
}
LOGGER.info("The initial load is reset, node: {}, oldValue: {}", this, oldValue);
// TODO we should decouple the property change from the thread that changes the property value
firePropertyChange(PROPERTY_NODE_LOAD_STATUS, oldValue, StatusIdentifier.InitialLoadPending);
final NodeStatusEvent nse =
new NodeStatusEvent(publisher.getConnectionId(), publisher.getUniqueId(),
NodeUtils.formatAddress(getAddr()), StatusIdentifier.InitialLoadPending);
LOGGER.info("Publish the nodeStatusEvent: {}", nse);
publisher.getSubjectNodeEvents().onNext(nse);
}
@Override
public StatusIdentifier getNodeLoadStatusIdentifier() {
StatusIdentifier initialLoadFinished;
synchronized (this.initialLoadFinishedLock) {
initialLoadFinished = this.nodeLoadStatus;
}
LOGGER.debug("The current initialLoadFinished: {}, node: {}", initialLoadFinished, node);
return initialLoadFinished;
}
@Override
public Object getInitialLoadFinishedLock() {
return this.initialLoadFinishedLock;
}
@Override
public StoredStrings getStoredStringsNs2() {
return storedStringsNs2;
}
@Override
public void setStoredStringsNs2(StoredStrings storedStringsNs2) {
StoredStrings oldValue = getStoredStringsNs2();
this.storedStringsNs2 = storedStringsNs2;
firePropertyChange(PROPERTY_STOREDSTRINGS_NS2, oldValue, this.storedStringsNs2);
}
}