All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.common.node.BoosterNode Maven / Gradle / Ivy

package org.bidib.wizard.common.node;

import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.LinkedList;

import org.bidib.jbidibc.messages.AccessoryState;
import org.bidib.jbidibc.messages.BidibLibrary;
import org.bidib.jbidibc.messages.Feature;
import org.bidib.jbidibc.messages.enums.BoosterControl;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.messages.utils.ConversionUtils;
import org.bidib.wizard.api.model.BoosterNodeInterface;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.event.NodeActionEvent;
import org.bidib.wizard.api.model.event.NodeActionEvent.ActionIdentifier;
import org.bidib.wizard.api.model.listener.BoosterStatusListener;
import org.bidib.wizard.model.status.BoosterStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoodies.binding.beans.Model;
import com.jgoodies.common.base.Objects;

import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Action;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.subjects.PublishSubject;

public class BoosterNode extends Model implements BoosterNodeInterface {
    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LoggerFactory.getLogger(BoosterNode.class);

    public static final String PROPERTY_BOOSTER_STATUS = "boosterStatus";

    private Integer boosterCurrent;

    private Long lastCurrentUpdate;

    private Integer boosterMaximumCurrent;

    private BoosterStatus boosterStatus;

    private Integer boosterTemperature;

    private Integer boosterVoltage;

    private BoosterControl boosterControl = BoosterControl.NONE;

    private Collection boosterStatusListeners = new LinkedList<>();

    private final WeakReference parent;

    private final ConnectionNodeAwarePublisher publisher;

    private PublishSubject subjectBoosterStatus;

    public BoosterNode(final NodeInterface parent, ConnectionNodeAwarePublisher publisher) {
        this.parent = new WeakReference<>(parent);
        this.publisher = publisher;

        subjectBoosterStatus = PublishSubject.create();
    }

    @Override
    public NodeInterface getNode() {
        return parent.get();
    }

    @Override
    public void addBoosterStatusListener(BoosterStatusListener listener) {
        boosterStatusListeners.add(listener);
    }

    @Override
    public void removeBoosterStatusListener(BoosterStatusListener listener) {
        boosterStatusListeners.remove(listener);
    }

    @Override
    public void setBoosterCurrent(Integer current, long timestamp) {

        // set the last current update time
        setLastCurrentUpdate(System.currentTimeMillis());

        LOGGER
            .debug("Booster current has changed, new: {}, old: {}, timestamp: {}", current, boosterCurrent, timestamp);
        this.boosterCurrent = current;
        fireBoosterCurrentChanged(current, timestamp);
    }

    @Override
    public Integer getBoosterCurrent() {
        return boosterCurrent;
    }

    @Override
    public void setBoosterMaximumCurrent(Integer maximumCurrent) {
        LOGGER.info("Set the new maximum current value: {}, previous: {}", maximumCurrent, boosterMaximumCurrent);

        this.boosterMaximumCurrent = maximumCurrent;
        fireBoosterMaximumCurrentChanged(maximumCurrent);
    }

    @Override
    public Integer getBoosterMaximumCurrent() {

        return boosterMaximumCurrent;
    }

    @Override
    public void fetchMaxBoosterCurrent() {

        try {
            Feature feature = Feature.findFeature(getNode().getNode().getFeatures(), BidibLibrary.FEATURE_BST_AMPERE);

            if (feature != null) {
                int maxBoosterCurrent = 0;
                maxBoosterCurrent = ConversionUtils.convertCurrent(feature.getValue());

                LOGGER
                    .info("Fetched the maximum current value from the booster: {} mA, uniqueId: {}", maxBoosterCurrent,
                        ByteUtils.getUniqueIdAsString(getNode().getUniqueId()));
                setBoosterMaximumCurrent(maxBoosterCurrent);
            }
            else {
                LOGGER.info("The feature FEATURE_BST_AMPERE is not available.");
            }

        }
        catch (Exception ex) {
            LOGGER.warn("Get FEATURE_BST_AMPERE from node failed.", ex);
        }
    }

    @Override
    public BoosterStatus getBoosterStatus() {
        return boosterStatus;
    }

    @Override
    public Integer getBoosterTemperature() {
        return boosterTemperature;
    }

    @Override
    public Integer getBoosterVoltage() {
        return boosterVoltage;
    }

    @Override
    public Long getLastCurrentUpdate() {
        return lastCurrentUpdate;
    }

    /**
     * @param lastCurrentUpdate
     *            the lastCurrentUpdate to set
     */
    public void setLastCurrentUpdate(Long lastCurrentUpdate) {
        this.lastCurrentUpdate = lastCurrentUpdate;
    }

    @Override
    public void setBoosterStatus(BoosterStatus status) {
        LOGGER.info("Set the new booster status: {}", status);

        BoosterStatus oldValue = this.boosterStatus;

        this.boosterStatus = status;

        // if (status != this.boosterStatus) {
        // this.boosterStatus = status;
        LOGGER.info("Fire booster status changed: {}", status);
        fireBoosterStatusChanged(status);
        // }

        firePropertyChange(PROPERTY_BOOSTER_STATUS, oldValue, this.boosterStatus);
    }

    @Override
    public void setBoosterTemperature(Integer temperature) {
        if (!Objects.equals(temperature, this.boosterTemperature)) {
            this.boosterTemperature = temperature;
            fireBoosterTemperatureChanged(temperature);
        }
    }

    @Override
    public void setBoosterVoltage(Integer voltage) {
        if (!Objects.equals(voltage, this.boosterVoltage)) {
            this.boosterVoltage = voltage;
            fireBoosterVoltageChanged(voltage);
        }
    }

    @Override
    public BoosterControl getBoosterControl() {
        return boosterControl;
    }

    @Override
    public void setBoosterControl(BoosterControl boosterControl) {
        LOGGER.info("Set the new boosterControl value: {}", boosterControl);

        BoosterControl oldValue = this.boosterControl;
        this.boosterControl = boosterControl;

        fireBoosterControlChanged(boosterControl);

        firePropertyChange(PROPERTY_BOOSTER_CONTROL, oldValue, this.boosterControl);
    }

    @Override
    public void updateBoosterControl(final AccessoryState accessoryState) {
        LOGGER.info("Update the booster control, accessoryState: {}", accessoryState);

        BoosterControl boosterControl = null;
        if (accessoryState != null && !accessoryState.hasError()) {
            Integer activeAspect = accessoryState.getActiveAspect();
            boosterControl = BoosterControl.valueOf(ByteUtils.getLowByte(activeAspect));
        }

        if (boosterControl == null) {
            LOGGER.warn("The booster control is not available. Use NONE as state.");
            boosterControl = BoosterControl.NONE;
        }

        setBoosterControl(boosterControl);
    }

    private void fireBoosterControlChanged(BoosterControl control) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.controlChanged(parent.get(), control);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterControlEvent());
    }

    private void fireBoosterMaximumCurrentChanged(Integer maximumCurrent) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.maximumCurrentChanged(parent.get(), maximumCurrent);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterDiagEvent());
    }

    private void fireBoosterStatusChanged(BoosterStatus status) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.stateChanged(parent.get(), status);
        }

        if (status != null) {
            LOGGER.debug("Publish the changed command station state: {}", status);
            this.subjectBoosterStatus.onNext(status);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterStatusEvent());
    }

    private void fireBoosterTemperatureChanged(Integer temperature) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.temperatureChanged(parent.get(), temperature);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterDiagEvent());
    }

    private void fireBoosterVoltageChanged(Integer voltage) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.voltageChanged(parent.get(), voltage);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterDiagEvent());
    }

    private void fireBoosterCurrentChanged(Integer current, long timestamp) {
        for (BoosterStatusListener l : boosterStatusListeners) {
            l.currentChanged(parent.get(), current, timestamp);
        }

        publisher.getSubjectNodeEvents().onNext(buildBoosterDiagEvent());
    }

    private NodeActionEvent buildBoosterDiagEvent() {
        NodeActionEvent boosterDiagEvent =
            new NodeActionEvent(publisher.getConnectionId(), publisher.getUniqueId(), ActionIdentifier.BoosterDiag);
        return boosterDiagEvent;
    }

    private NodeActionEvent buildBoosterStatusEvent() {
        NodeActionEvent boosterStatusEvent =
            new NodeActionEvent(publisher.getConnectionId(), publisher.getUniqueId(), ActionIdentifier.BoosterStatus);
        return boosterStatusEvent;
    }

    private NodeActionEvent buildBoosterControlEvent() {
        NodeActionEvent boosterStatusEvent =
            new NodeActionEvent(publisher.getConnectionId(), publisher.getUniqueId(), ActionIdentifier.BoosterControl);
        return boosterStatusEvent;
    }

    @Override
    public Disposable subscribeSubjectBoosterState(
        Consumer onNext, Consumer onError, Action onComplete) {
        LOGGER.info("Subscribe to subjectBoosterStatus, consumer: {}", onNext);

        Disposable disposable =
            subjectBoosterStatus
                .subscribeOn(Schedulers.trampoline()).observeOn(Schedulers.computation())
                .subscribe(onNext, onError, onComplete);
        return disposable;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy