Search in sources :

Example 1 with OutstationChangeSet

use of com.automatak.dnp3.OutstationChangeSet in project solarnetwork-node by SolarNetwork.

the class OutstationService method changeSetForDatumCapturedEvent.

private OutstationChangeSet changeSetForDatumCapturedEvent(final Datum datum, final Event event) {
    Map<MeasurementType, List<MeasurementConfig>> map = measurementTypeMap(getMeasurementConfigs());
    Map<ControlType, List<ControlConfig>> controlMap = controlTypeMap(getControlConfigs());
    if (datum == null || ((map == null || map.isEmpty()) && (controlMap == null || controlMap.isEmpty()))) {
        return null;
    }
    final String sourceId = datum.getSourceId();
    final Instant timestamp = datum.getTimestamp();
    if (timestamp == null) {
        return null;
    }
    final long ts = timestamp.toEpochMilli();
    final Map<String, ?> datumProps = datum.getSampleData();
    OutstationChangeSet changes = null;
    if (map != null) {
        for (Map.Entry<MeasurementType, List<MeasurementConfig>> me : map.entrySet()) {
            MeasurementType type = me.getKey();
            List<MeasurementConfig> list = me.getValue();
            for (ListIterator<MeasurementConfig> itr = list.listIterator(); itr.hasNext(); ) {
                MeasurementConfig config = itr.next();
                if (sourceId.equals(config.getSourceId())) {
                    Object propVal = datumProps.get(config.getPropertyName());
                    if (propVal != null) {
                        if (propVal instanceof Number) {
                            if (config.getUnitMultiplier() != null) {
                                propVal = applyUnitMultiplier((Number) propVal, config.getUnitMultiplier());
                            }
                            if (config.getDecimalScale() >= 0) {
                                propVal = applyDecimalScale((Number) propVal, config.getDecimalScale());
                            }
                        }
                        if (changes == null) {
                            changes = new OutstationChangeSet();
                        }
                        log.debug("Updating DNP3 {}[{}] from [{}].{} -> {}", type, itr.previousIndex(), sourceId, config.getPropertyName(), propVal);
                        switch(type) {
                            case AnalogInput:
                                if (propVal instanceof Number) {
                                    changes.update(new AnalogInput(((Number) propVal).doubleValue(), (byte) AnalogQuality.ONLINE.toType(), ts), itr.previousIndex());
                                }
                                break;
                            case AnalogOutputStatus:
                                if (propVal instanceof Number) {
                                    changes.update(new AnalogOutputStatus(((Number) propVal).doubleValue(), (byte) AnalogOutputStatusQuality.ONLINE.toType(), ts), itr.previousIndex());
                                }
                                break;
                            case BinaryInput:
                                changes.update(new BinaryInput(booleanPropertyValue(propVal), (byte) BinaryQuality.ONLINE.toType(), ts), itr.previousIndex());
                                break;
                            case BinaryOutputStatus:
                                changes.update(new BinaryOutputStatus(booleanPropertyValue(propVal), (byte) BinaryOutputStatusQuality.ONLINE.toType(), ts), itr.previousIndex());
                                break;
                            case Counter:
                                if (propVal instanceof Number) {
                                    changes.update(new Counter(((Number) propVal).longValue(), (byte) CounterQuality.ONLINE.toType(), ts), itr.previousIndex());
                                }
                                break;
                            case DoubleBitBinaryInput:
                                changes.update(new DoubleBitBinaryInput(booleanPropertyValue(propVal) ? DoubleBit.DETERMINED_ON : DoubleBit.DETERMINED_OFF, (byte) DoubleBitBinaryQuality.ONLINE.toType(), ts), itr.previousIndex());
                                break;
                            case FrozenCounter:
                                if (propVal instanceof Number) {
                                    changes.update(new FrozenCounter(((Number) propVal).longValue(), (byte) FrozenCounterQuality.ONLINE.toType(), ts), itr.previousIndex());
                                }
                                break;
                        }
                    }
                }
            }
        }
        if (controlMap != null) {
            int analogStatusOffset = typeConfigCount(MeasurementType.AnalogOutputStatus, map);
            int binaryStatusOffset = typeConfigCount(MeasurementType.BinaryOutputStatus, map);
            for (Map.Entry<ControlType, List<ControlConfig>> me : controlMap.entrySet()) {
                ControlType type = me.getKey();
                List<ControlConfig> list = me.getValue();
                for (ListIterator<ControlConfig> itr = list.listIterator(); itr.hasNext(); ) {
                    ControlConfig config = itr.next();
                    if (sourceId.equals(config.getControlId())) {
                        if (changes == null) {
                            changes = new OutstationChangeSet();
                        }
                        int index = (type == ControlType.Analog ? analogStatusOffset : binaryStatusOffset) + itr.previousIndex();
                        Object propVal = datumProps.get("value");
                        log.debug("Updating DNP3 control {}[{}] from [{}].value -> {}", type, index, sourceId, propVal);
                        switch(type) {
                            case Analog:
                                try {
                                    Number n = null;
                                    if (propVal instanceof Number) {
                                        n = (Number) propVal;
                                    } else {
                                        n = new BigDecimal(propVal.toString());
                                    }
                                    changes.update(new AnalogOutputStatus(n.doubleValue(), (byte) AnalogOutputStatusQuality.ONLINE.toType(), ts), index);
                                } catch (NumberFormatException e) {
                                    log.warn("Cannot convert control [{}] value [{}] to number: {}", sourceId, propVal, e.getMessage());
                                }
                                break;
                            case Binary:
                                changes.update(new BinaryOutputStatus(booleanPropertyValue(propVal), (byte) BinaryOutputStatusQuality.ONLINE.toType(), ts), index);
                                break;
                        }
                    }
                }
            }
        }
    }
    return changes;
}
Also used : AnalogInput(com.automatak.dnp3.AnalogInput) Counter(com.automatak.dnp3.Counter) FrozenCounter(com.automatak.dnp3.FrozenCounter) DoubleBitBinaryInput(com.automatak.dnp3.DoubleBitBinaryInput) MeasurementType(net.solarnetwork.node.io.dnp3.domain.MeasurementType) List(java.util.List) ArrayList(java.util.ArrayList) BinaryOutputStatus(com.automatak.dnp3.BinaryOutputStatus) MeasurementConfig(net.solarnetwork.node.io.dnp3.domain.MeasurementConfig) BinaryInput(com.automatak.dnp3.BinaryInput) DoubleBitBinaryInput(com.automatak.dnp3.DoubleBitBinaryInput) ControlConfig(net.solarnetwork.node.io.dnp3.domain.ControlConfig) Instant(java.time.Instant) BigDecimal(java.math.BigDecimal) OutstationChangeSet(com.automatak.dnp3.OutstationChangeSet) FrozenCounter(com.automatak.dnp3.FrozenCounter) ControlType(net.solarnetwork.node.io.dnp3.domain.ControlType) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) AnalogOutputStatus(com.automatak.dnp3.AnalogOutputStatus)

Example 2 with OutstationChangeSet

use of com.automatak.dnp3.OutstationChangeSet in project solarnetwork-node by SolarNetwork.

the class OutstationDemo method run.

public static void run(DNP3Manager manager) throws Exception {
    // Create a tcp channel class that will connect to the loopback
    Channel channel = manager.addTCPServer("client", LogMasks.NORMAL | LogMasks.APP_COMMS, ServerAcceptMode.CloseNew, "127.0.0.1", 20000, new Slf4jChannelListener());
    // Create the default outstation configuration
    OutstationStackConfig config = new OutstationStackConfig(DatabaseConfig.allValues(5), EventBufferConfig.allTypes(50));
    // Create an Outstation instance, pass in a simple a command handler that responds successfully to everything
    Outstation outstation = channel.addOutstation("outstation", SuccessCommandHandler.getInstance(), DefaultOutstationApplication.getInstance(), config);
    outstation.enable();
    // all this stuff just to read a line of text in Java. Oh the humanity.
    String line = "";
    InputStreamReader converter = new InputStreamReader(System.in);
    BufferedReader in = new BufferedReader(converter);
    int i = 0;
    while (true) {
        System.out.println("Enter something to update a counter or type <quit> to exit");
        line = in.readLine();
        if (line.equals("quit"))
            break;
        else {
            OutstationChangeSet set = new OutstationChangeSet();
            set.update(new Counter(i, (byte) 0x01, 0), 0);
            outstation.apply(set);
            ++i;
        }
    }
}
Also used : Slf4jChannelListener(net.solarnetwork.dnp3.util.Slf4jChannelListener) Outstation(com.automatak.dnp3.Outstation) Counter(com.automatak.dnp3.Counter) InputStreamReader(java.io.InputStreamReader) OutstationChangeSet(com.automatak.dnp3.OutstationChangeSet) Channel(com.automatak.dnp3.Channel) OutstationStackConfig(com.automatak.dnp3.OutstationStackConfig) BufferedReader(java.io.BufferedReader)

Example 3 with OutstationChangeSet

use of com.automatak.dnp3.OutstationChangeSet in project solarnetwork-node by SolarNetwork.

the class OutstationService method applyDatumCapturedUpdates.

private void applyDatumCapturedUpdates(Datum datum, Event event) {
    OutstationChangeSet changes = changeSetForDatumCapturedEvent(datum, event);
    if (changes == null) {
        return;
    }
    synchronized (this) {
        Outstation station = getOutstation();
        if (station != null) {
            log.info("Applying changes to DNP3 [{}]", getUid());
            station.apply(changes);
        }
    }
}
Also used : Outstation(com.automatak.dnp3.Outstation) OutstationChangeSet(com.automatak.dnp3.OutstationChangeSet)

Aggregations

OutstationChangeSet (com.automatak.dnp3.OutstationChangeSet)3 Counter (com.automatak.dnp3.Counter)2 Outstation (com.automatak.dnp3.Outstation)2 AnalogInput (com.automatak.dnp3.AnalogInput)1 AnalogOutputStatus (com.automatak.dnp3.AnalogOutputStatus)1 BinaryInput (com.automatak.dnp3.BinaryInput)1 BinaryOutputStatus (com.automatak.dnp3.BinaryOutputStatus)1 Channel (com.automatak.dnp3.Channel)1 DoubleBitBinaryInput (com.automatak.dnp3.DoubleBitBinaryInput)1 FrozenCounter (com.automatak.dnp3.FrozenCounter)1 OutstationStackConfig (com.automatak.dnp3.OutstationStackConfig)1 BufferedReader (java.io.BufferedReader)1 InputStreamReader (java.io.InputStreamReader)1 BigDecimal (java.math.BigDecimal)1 Instant (java.time.Instant)1 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Map (java.util.Map)1 Slf4jChannelListener (net.solarnetwork.dnp3.util.Slf4jChannelListener)1