use of com.alliander.osgp.adapter.protocol.iec61850.domain.valueobjects.ScheduleEntry in project Protocol-Adapter-IEC61850 by OSGP.
the class Iec61850SetScheduleCommand method createScheduleEntries.
/**
* Returns a map of schedule entries, grouped by the internal index.
*/
private Map<Integer, List<ScheduleEntry>> createScheduleEntries(final List<ScheduleDto> scheduleList, final Ssld ssld, final RelayTypeDto relayTypeDto, final SsldDataService ssldDataService) throws FunctionalException {
final Map<Integer, List<ScheduleEntry>> relaySchedulesEntries = new HashMap<>();
final RelayType relayType = RelayType.valueOf(relayTypeDto.name());
for (final ScheduleDto schedule : scheduleList) {
for (final LightValueDto lightValue : schedule.getLightValue()) {
final List<Integer> indexes = new ArrayList<>();
if (lightValue.getIndex() == 0 && (RelayType.TARIFF.equals(relayType) || RelayType.TARIFF_REVERSED.equals(relayType))) {
// Index 0 is not allowed for tariff switching.
throw new FunctionalException(FunctionalExceptionType.VALIDATION_ERROR, ComponentType.PROTOCOL_IEC61850);
} else if (lightValue.getIndex() == 0 && RelayType.LIGHT.equals(relayType)) {
// Index == 0, getting all light relays and adding their
// internal indexes to the indexes list.
final List<DeviceOutputSetting> settings = ssldDataService.findByRelayType(ssld, relayType);
for (final DeviceOutputSetting deviceOutputSetting : settings) {
indexes.add(deviceOutputSetting.getInternalId());
}
} else {
// Index != 0, adding just the one index to the list.
indexes.add(ssldDataService.convertToInternalIndex(ssld, lightValue.getIndex()));
}
ScheduleEntry scheduleEntry;
try {
scheduleEntry = this.convertToScheduleEntry(schedule, lightValue);
} catch (final ProtocolAdapterException e) {
throw new FunctionalException(FunctionalExceptionType.VALIDATION_ERROR, ComponentType.PROTOCOL_IEC61850, e);
}
for (final Integer internalIndex : indexes) {
if (relaySchedulesEntries.containsKey(internalIndex)) {
// Internal index already in the Map, adding to the List
relaySchedulesEntries.get(internalIndex).add(scheduleEntry);
} else {
// First time we come across this relay, checking its
// type.
this.checkRelayForSchedules(ssldDataService.getDeviceOutputSettingForInternalIndex(ssld, internalIndex).getRelayType(), relayType, internalIndex);
// Adding it to scheduleEntries.
final List<ScheduleEntry> scheduleEntries = new ArrayList<>();
scheduleEntries.add(scheduleEntry);
relaySchedulesEntries.put(internalIndex, scheduleEntries);
}
}
}
}
return relaySchedulesEntries;
}
use of com.alliander.osgp.adapter.protocol.iec61850.domain.valueobjects.ScheduleEntry in project Protocol-Adapter-IEC61850 by OSGP.
the class Iec61850SetScheduleCommand method setScheduleOnDevice.
public void setScheduleOnDevice(final Iec61850Client iec61850Client, final DeviceConnection deviceConnection, final RelayTypeDto relayType, final List<ScheduleDto> scheduleList, final Ssld ssld, final SsldDataService ssldDataService) throws ProtocolAdapterException {
final String tariffOrLight = relayType.equals(RelayTypeDto.LIGHT) ? "light" : "tariff";
try {
// Creating a list of all Schedule entries, grouped by relay index.
final Map<Integer, List<ScheduleEntry>> relaySchedulesEntries = this.createScheduleEntries(scheduleList, ssld, relayType, ssldDataService);
final Function<Void> function = new Function<Void>() {
@Override
public Void apply(final DeviceMessageLog deviceMessageLog) throws Exception {
for (final Integer relayIndex : relaySchedulesEntries.keySet()) {
final List<ScheduleEntry> scheduleEntries = relaySchedulesEntries.get(relayIndex);
final int numberOfScheduleEntries = scheduleEntries.size();
if (numberOfScheduleEntries > MAX_NUMBER_OF_SCHEDULE_ENTRIES) {
throw new ProtocolAdapterException("Received " + numberOfScheduleEntries + " " + tariffOrLight + " schedule entries for relay " + relayIndex + " for device " + ssld.getDeviceIdentification() + ". Setting more than " + MAX_NUMBER_OF_SCHEDULE_ENTRIES + " is not possible.");
}
final LogicalNode logicalNode = LogicalNode.getSwitchComponentByIndex(relayIndex);
final NodeContainer schedule = deviceConnection.getFcModelNode(LogicalDevice.LIGHTING, logicalNode, DataAttribute.SCHEDULE, Fc.CF);
iec61850Client.readNodeDataValues(deviceConnection.getConnection().getClientAssociation(), schedule.getFcmodelNode());
// entries.
for (int i = 0; i < MAX_NUMBER_OF_SCHEDULE_ENTRIES; i++) {
final String scheduleEntryName = SubDataAttribute.SCHEDULE_ENTRY.getDescription() + (i + 1);
final NodeContainer scheduleNode = schedule.getChild(scheduleEntryName);
final boolean enabled = scheduleNode.getBoolean(SubDataAttribute.SCHEDULE_ENABLE).getValue();
LOGGER.info("Checking if schedule entry {} is enabled: {}", i + 1, enabled);
if (enabled) {
LOGGER.info("Disabling schedule entry {} of {} for relay {} before setting new {} schedule", i + 1, MAX_NUMBER_OF_SCHEDULE_ENTRIES, relayIndex, tariffOrLight);
scheduleNode.writeBoolean(SubDataAttribute.SCHEDULE_ENABLE, false);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_ENABLE, Boolean.toString(false));
}
}
for (int i = 0; i < numberOfScheduleEntries; i++) {
LOGGER.info("Writing {} schedule entry {} for relay {}", tariffOrLight, i + 1, relayIndex);
final ScheduleEntry scheduleEntry = scheduleEntries.get(i);
final String scheduleEntryName = SubDataAttribute.SCHEDULE_ENTRY.getDescription() + (i + 1);
final NodeContainer scheduleNode = schedule.getChild(scheduleEntryName);
final BdaBoolean enabled = scheduleNode.getBoolean(SubDataAttribute.SCHEDULE_ENABLE);
if (enabled.getValue() != scheduleEntry.isEnabled()) {
scheduleNode.writeBoolean(SubDataAttribute.SCHEDULE_ENABLE, scheduleEntry.isEnabled());
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_ENABLE, Boolean.toString(scheduleEntry.isEnabled()));
}
final Integer day = scheduleNode.getInteger(SubDataAttribute.SCHEDULE_DAY).getValue();
if (day != scheduleEntry.getDay()) {
scheduleNode.writeInteger(SubDataAttribute.SCHEDULE_DAY, scheduleEntry.getDay());
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_DAY, Integer.toString(scheduleEntry.getDay()));
}
/*
* A schedule entry on the platform is about
* switching on a certain time, or on a certain
* trigger. The schedule entries on the device are
* about a period with a time on and a time off. To
* bridge these different approaches, either the on
* or the off values on the device are set to a
* certain default to indicate they are not relevant
* to the schedule entry.
*/
int timeOnValue = DEFAULT_SCHEDULE_VALUE;
byte timeOnTypeValue = DEFAULT_SCHEDULE_VALUE;
int timeOffValue = DEFAULT_SCHEDULE_VALUE;
byte timeOffTypeValue = DEFAULT_SCHEDULE_VALUE;
if (scheduleEntry.isOn()) {
timeOnValue = scheduleEntry.getTime();
timeOnTypeValue = (byte) scheduleEntry.getTriggerType().getIndex();
} else {
timeOffValue = scheduleEntry.getTime();
timeOffTypeValue = (byte) scheduleEntry.getTriggerType().getIndex();
}
final Integer timeOn = scheduleNode.getInteger(SubDataAttribute.SCHEDULE_TIME_ON).getValue();
if (timeOn != timeOnValue) {
scheduleNode.writeInteger(SubDataAttribute.SCHEDULE_TIME_ON, timeOnValue);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TIME_ON, Integer.toString(timeOnValue));
}
final Byte timeOnActionTime = scheduleNode.getByte(SubDataAttribute.SCHEDULE_TIME_ON_TYPE).getValue();
if (timeOnActionTime != timeOnTypeValue) {
scheduleNode.writeByte(SubDataAttribute.SCHEDULE_TIME_ON_TYPE, timeOnTypeValue);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TIME_ON_TYPE, Byte.toString(timeOnTypeValue));
}
final Integer timeOff = scheduleNode.getInteger(SubDataAttribute.SCHEDULE_TIME_OFF).getValue();
if (timeOff != timeOffValue) {
scheduleNode.writeInteger(SubDataAttribute.SCHEDULE_TIME_OFF, timeOffValue);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TIME_OFF, Integer.toString(timeOffValue));
}
final Byte timeOffActionTime = scheduleNode.getByte(SubDataAttribute.SCHEDULE_TIME_OFF_TYPE).getValue();
if (timeOffActionTime != timeOffTypeValue) {
scheduleNode.writeByte(SubDataAttribute.SCHEDULE_TIME_OFF_TYPE, timeOffTypeValue);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TIME_OFF_TYPE, Byte.toString(timeOffTypeValue));
}
final Integer minimumTimeOn = scheduleNode.getUnsignedShort(SubDataAttribute.MINIMUM_TIME_ON).getValue();
final Integer newMinimumTimeOn = scheduleEntry.getMinimumLightsOn() / 60;
if (minimumTimeOn != newMinimumTimeOn) {
scheduleNode.writeUnsignedShort(SubDataAttribute.MINIMUM_TIME_ON, newMinimumTimeOn);
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.MINIMUM_TIME_ON, Integer.toString(newMinimumTimeOn));
}
final Integer triggerMinutesBefore = scheduleNode.getUnsignedShort(SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_BEFORE).getValue();
if (triggerMinutesBefore != scheduleEntry.getTriggerWindowMinutesBefore()) {
scheduleNode.writeUnsignedShort(SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_BEFORE, scheduleEntry.getTriggerWindowMinutesBefore());
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_BEFORE, Integer.toString(scheduleEntry.getTriggerWindowMinutesBefore()));
}
final Integer triggerMinutesAfter = scheduleNode.getUnsignedShort(SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_AFTER).getValue();
if (triggerMinutesAfter != scheduleEntry.getTriggerWindowMinutesAfter()) {
scheduleNode.writeUnsignedShort(SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_AFTER, scheduleEntry.getTriggerWindowMinutesAfter());
deviceMessageLog.addVariable(logicalNode, DataAttribute.SCHEDULE, Fc.CF, scheduleEntryName, SubDataAttribute.SCHEDULE_TRIGGER_MINUTES_AFTER, Integer.toString(scheduleEntry.getTriggerWindowMinutesAfter()));
}
}
}
DeviceMessageLoggingService.logMessage(deviceMessageLog, deviceConnection.getDeviceIdentification(), deviceConnection.getOrganisationIdentification(), false);
return null;
}
};
iec61850Client.sendCommandWithRetry(function, "SetSchedule", deviceConnection.getDeviceIdentification());
} catch (final FunctionalException e) {
throw new ProtocolAdapterException(e.getMessage(), e);
}
}
use of com.alliander.osgp.adapter.protocol.iec61850.domain.valueobjects.ScheduleEntry in project Protocol-Adapter-IEC61850 by OSGP.
the class Iec61850SetScheduleCommand method convertToScheduleEntry.
private ScheduleEntry convertToScheduleEntry(final ScheduleDto schedule, final LightValueDto lightValue) throws ProtocolAdapterException {
final ScheduleEntry.Builder builder = new ScheduleEntry.Builder();
try {
if (schedule.getTime() != null) {
builder.time(this.convertTime(schedule.getTime()));
}
final WindowTypeDto triggerWindow = schedule.getTriggerWindow();
if (triggerWindow != null) {
if (triggerWindow.getMinutesBefore() > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Schedule TriggerWindow minutesBefore must not be greater than " + Integer.MAX_VALUE);
}
if (triggerWindow.getMinutesAfter() > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Schedule TriggerWindow minutesAfter must not be greater than " + Integer.MAX_VALUE);
}
builder.triggerWindowMinutesBefore((int) triggerWindow.getMinutesBefore());
builder.triggerWindowMinutesAfter((int) triggerWindow.getMinutesAfter());
}
builder.triggerType(this.extractTriggerType(schedule));
builder.enabled(schedule.getIsEnabled() == null ? true : schedule.getIsEnabled());
final WeekDayTypeDto weekDay = schedule.getWeekDay();
if (WeekDayTypeDto.ABSOLUTEDAY.equals(weekDay)) {
final DateTime specialDay = schedule.getStartDay();
if (specialDay == null) {
throw new IllegalArgumentException("Schedule startDay must not be null when weekDay equals ABSOLUTEDAY");
}
builder.specialDay(specialDay);
} else {
builder.weekday(ScheduleWeekday.valueOf(schedule.getWeekDay().name()));
}
builder.on(lightValue.isOn());
if (schedule.getMinimumLightsOn() != null) {
builder.minimumLightsOn(schedule.getMinimumLightsOn());
}
return builder.build();
} catch (IllegalStateException | IllegalArgumentException e) {
throw new ProtocolAdapterException("Error converting ScheduleDto and LightValueDto into a ScheduleEntry: " + e.getMessage(), e);
}
}
Aggregations