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

gurux.dlms.objects.GXDLMSClock Maven / Gradle / Ivy

The newest version!
//
// --------------------------------------------------------------------------
//  Gurux Ltd
// 
//
//
// Filename:        $HeadURL$
//
// Version:         $Revision$,
//                  $Date$
//                  $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
//  DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License 
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
// See the GNU General Public License for more details.
//
// More information of Gurux products: https://www.gurux.org
//
// This code is licensed under the GNU General Public License v2. 
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------

package gurux.dlms.objects;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.stream.XMLStreamException;

import gurux.dlms.GXByteBuffer;
import gurux.dlms.GXDLMSClient;
import gurux.dlms.GXDLMSSettings;
import gurux.dlms.GXDateTime;
import gurux.dlms.ValueEventArgs;
import gurux.dlms.enums.ClockStatus;
import gurux.dlms.enums.DataType;
import gurux.dlms.enums.DateTimeSkips;
import gurux.dlms.enums.ErrorCode;
import gurux.dlms.enums.ObjectType;
import gurux.dlms.internal.GXCommon;
import gurux.dlms.objects.enums.ClockBase;

/**
 * Online help: 
* https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSClock */ public class GXDLMSClock extends GXDLMSObject implements IGXDLMSBase { private ClockBase clockBase; private int deviation; private boolean enabled; private GXDateTime end = new GXDateTime(); private java.util.Set status; private GXDateTime begin = new GXDateTime(); private int timeZone; private GXDateTime time = new GXDateTime(); /** * Constructor. */ public GXDLMSClock() { this("0.0.1.0.0.255", 0); } /** * Constructor. * * @param ln * Logical Name of the object. */ public GXDLMSClock(final String ln) { this(ln, 0); } /** * Constructor. * * @param ln * Logical Name of the object. * @param sn * Short Name of the object. */ public GXDLMSClock(final String ln, final int sn) { super(ObjectType.CLOCK, ln, sn); status = new HashSet(); status.add(ClockStatus.OK); deviation = 0; java.util.Set value = new HashSet(); value.add(DateTimeSkips.MONTH); value.add(DateTimeSkips.DAY); begin.setSkip(value); end.setSkip(begin.getSkip()); clockBase = ClockBase.NONE; } @Override public final DataType getUIDataType(final int index) { if (index == 2 || index == 5 || index == 6) { return DataType.DATETIME; } return super.getUIDataType(index); } /** * @return Time of COSEM Clock object. */ public final GXDateTime getTime() { return time; } /** * @param value * Time of COSEM Clock object. */ public final void setTime(final GXDateTime value) { time = value; } /** * @param value * Time of COSEM Clock object. */ public final void setTime(final Date value) { time = new GXDateTime(value); } /** * @param value * Time of COSEM Clock object. */ public final void setTime(final java.util.Calendar value) { time = new GXDateTime(value.getTime()); } /** * @return TimeZone of COSEM Clock object. */ public final int getTimeZone() { return timeZone; } /** * @param value * TimeZone of COSEM Clock object. */ public final void setTimeZone(final int value) { timeZone = value; } /** * @return Status of COSEM Clock object. */ public final java.util.Set getStatus() { return status; } /** * @param value * Status of COSEM Clock object. */ public final void setStatus(final java.util.Set value) { status = value; } public final GXDateTime getBegin() { return begin; } public final void setBegin(final GXDateTime value) { begin = value; } public final GXDateTime getEnd() { return end; } public final void setEnd(final GXDateTime value) { end = value; } public final int getDeviation() { return deviation; } public final void setDeviation(final int value) { deviation = value; } public final boolean getEnabled() { return enabled; } public final void setEnabled(final boolean value) { enabled = value; } /** * @return Clock base of COSEM Clock object. */ public final ClockBase getClockBase() { return clockBase; } /** * @param value * Clock base of COSEM Clock object. */ public final void setClockBase(final ClockBase value) { clockBase = value; } @Override public final Object[] getValues() { return new Object[] { getLogicalName(), getTime(), getTimeZone(), getStatus(), getBegin(), getEnd(), getDeviation(), getEnabled(), getClockBase() }; } /** * @return Returns current time. */ public GXDateTime now() { Calendar now = Calendar.getInstance(); GXDateTime tm = new GXDateTime(now); if (timeZone == -1 || timeZone == -32768 || timeZone == 0x8000) { tm.getSkip().add(DateTimeSkips.DEVITATION); } else { // If clock's time zone is different what user want's to use. int offset = timeZone + now.getTimeZone().getRawOffset() / 60000; if (offset != 0) { TimeZone tz = GXDateTime.getTimeZone(timeZone, enabled); if (tz != null) { now = Calendar.getInstance(tz); } else { // Use current time zone if time zone is not found. now = Calendar.getInstance(); } tm.setMeterCalendar(now); } } // If clock's daylight saving is active but user do not want to use it. if (!enabled && now.getTimeZone().observesDaylightTime()) { tm.getStatus().remove(ClockStatus.DAYLIGHT_SAVE_ACTIVE); tm.getMeterCalendar().add(Calendar.MINUTE, -deviation); } return tm; } @Override @SuppressWarnings("squid:S1168") public final byte[] invoke(final GXDLMSSettings settings, final ValueEventArgs e) { // Resets the value to the default value. // The default value is an instance specific constant. if (e.getIndex() == 1) { GXDateTime dt = getTime(); java.util.Calendar tm = Calendar.getInstance(); tm.setTime(dt.getMeterCalendar().getTime()); int minutes = tm.get(java.util.Calendar.MINUTE); if (minutes < 8) { minutes = 0; } else if (minutes < 23) { minutes = 15; } else if (minutes < 38) { minutes = 30; } else if (minutes < 53) { minutes = 45; } else { minutes = 0; tm.add(java.util.Calendar.HOUR_OF_DAY, 1); } tm.set(java.util.Calendar.MINUTE, minutes); tm.set(java.util.Calendar.SECOND, 0); tm.set(java.util.Calendar.MILLISECOND, 0); dt.setMeterCalendar(tm); setTime(dt); } else if (e.getIndex() == 3) { // Sets the meter's time to the nearest minute. GXDateTime dt = getTime(); java.util.Calendar tm = Calendar.getInstance(); tm.setTime(dt.getMeterCalendar().getTime()); int s = tm.get(java.util.Calendar.SECOND); if (s > 30) { tm.add(java.util.Calendar.MINUTE, 1); } tm.set(java.util.Calendar.SECOND, 0); tm.set(java.util.Calendar.MILLISECOND, 0); dt.setMeterCalendar(tm); setTime(dt); } else if (e.getIndex() == 5) { List arr = (List) e.getParameters(); // Presets the time to a new value (preset_time) and defines // avalidity_interval within which the new time can be activated. GXDateTime presetTime = (GXDateTime) GXDLMSClient.changeType((byte[]) arr.get(0), DataType.DATETIME, e.getSettings()); // GXDateTime validityIntervalStart = (GXDateTime) GXDLMSClient.changeType((byte[]) arr.get(1), DataType.DATETIME, e.getSettings()); // GXDateTime validityIntervalEnd = (GXDateTime) GXDLMSClient.changeType((byte[]) arr.get(2), DataType.DATETIME, e.getSettings()); setTime(presetTime); } else if (e.getIndex() == 6) { // Shifts the time. int shift = ((Number) e.getParameters()).intValue(); GXDateTime dt = getTime(); java.util.Calendar tm = Calendar.getInstance(); tm.setTime(dt.getMeterCalendar().getTime()); tm.add(java.util.Calendar.SECOND, shift); dt.setMeterCalendar(tm); setTime(dt); } else { e.setError(ErrorCode.READ_WRITE_DENIED); } return null; } /* * Sets the meter's time to the nearest (+/-) quarter of an hour value * (*:00, *:15, *:30, *:45). */ public final byte[][] adjustToQuarter(final GXDLMSClient client) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { return client.method(this, 1, 0, DataType.INT8); } /* * Sets the meter's time to the nearest (+/-) starting point of a measuring * period. */ public final byte[][] adjustToMeasuringPeriod(final GXDLMSClient client) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { return client.method(this, 2, 0, DataType.INT8); } /* * Sets the meter's time to the nearest minute. If second_counter < 30 s, so * second_counter is set to 0. If second_counter ³ 30 s, so second_counter * is set to 0, and minute_counter and all depending clock values are * incremented if necessary. */ public final byte[][] adjustToMinute(final GXDLMSClient client) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { return client.method(this, 3, 0, DataType.INT8); } /* * This method is used in conjunction with the preset_adjusting_time method. * If the meter's time lies between validity_interval_start and * validity_interval_end, then time is set to preset_time. */ public final byte[][] adjustToPresetTime(final GXDLMSClient client) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { return client.method(this, 4, 0, DataType.INT8); } /* * Presets the time to a new value (preset_time) and defines a * validity_interval within which the new time can be activated. */ public final byte[][] presetAdjustingTime(final GXDLMSClient client, final Date presetTime, final Date validityIntervalStart, final Date validityIntervalEnd) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { GXByteBuffer buff = new GXByteBuffer(44); buff.setUInt8(DataType.STRUCTURE.getValue()); buff.setUInt8(3); GXCommon.setData(null, buff, DataType.OCTET_STRING, presetTime); GXCommon.setData(null, buff, DataType.OCTET_STRING, validityIntervalStart); GXCommon.setData(null, buff, DataType.OCTET_STRING, validityIntervalEnd); return client.method(this, 5, buff.array(), DataType.ARRAY); } /* * Shifts the time by n (-900 <= n <= 900) s. */ public final byte[][] shiftTime(final GXDLMSClient client, final int forTime) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { if (forTime < -900 || forTime > 900) { throw new IllegalArgumentException("Invalid shift time."); } return client.method(this, 6, forTime, DataType.INT16); } /* * Returns collection of attributes to read. If attribute is static and * already read or device is returned HW error it is not returned. */ @Override public final int[] getAttributeIndexToRead(final boolean all) { java.util.ArrayList attributes = new java.util.ArrayList(); // LN is static and read only once. if (all || getLogicalName() == null || getLogicalName().compareTo("") == 0) { attributes.add(1); } // Time if (all || canRead(2)) { attributes.add(2); } // TimeZone if (all || !isRead(3)) { attributes.add(3); } // Status if (all || canRead(4)) { attributes.add(4); } // Begin if (all || !isRead(5)) { attributes.add(5); } // End if (all || !isRead(6)) { attributes.add(6); } // Deviation if (all || !isRead(7)) { attributes.add(7); } // Enabled if (all || !isRead(8)) { attributes.add(8); } // ClockBase if (all || !isRead(9)) { attributes.add(9); } return GXDLMSObjectHelpers.toIntArray(attributes); } /* * Returns amount of attributes. */ @Override public final int getAttributeCount() { return 9; } /* * Returns amount of methods. */ @Override public final int getMethodCount() { return 6; } @Override public final DataType getDataType(final int index) { switch (index) { case 1: return DataType.OCTET_STRING; case 2: return DataType.OCTET_STRING; case 3: return DataType.INT16; case 4: return DataType.UINT8; case 5: return DataType.OCTET_STRING; case 6: return DataType.OCTET_STRING; case 7: return DataType.INT8; case 8: return DataType.BOOLEAN; case 9: return DataType.ENUM; default: throw new IllegalArgumentException("getDataType failed. Invalid attribute index."); } } /* * Returns value of given attribute. */ @Override public final Object getValue(final GXDLMSSettings settings, final ValueEventArgs e) { switch (e.getIndex()) { case 1: return GXCommon.logicalNameToBytes(getLogicalName()); case 2: return getTime(); case 3: return getTimeZone(); case 4: return ClockStatus.toInteger(status); case 5: return getBegin(); case 6: return getEnd(); case 7: return getDeviation(); case 8: return getEnabled(); case 9: return getClockBase().ordinal(); default: e.setError(ErrorCode.READ_WRITE_DENIED); break; } return null; } /* * Set value of given attribute. */ @Override public final void setValue(final GXDLMSSettings settings, final ValueEventArgs e) { switch (e.getIndex()) { case 1: setLogicalName(GXCommon.toLogicalName(e.getValue())); break; case 2: if (e.getValue() == null) { setTime(new GXDateTime()); } else { GXDateTime tmp; if (e.getValue() instanceof byte[]) { tmp = (GXDateTime) GXDLMSClient.changeType((byte[]) e.getValue(), DataType.DATETIME, e.getSettings()); } else { tmp = (GXDateTime) e.getValue(); } setTime(tmp); } break; case 3: if (e.getValue() == null) { setTimeZone(0); } else { setTimeZone(((Number) e.getValue()).intValue()); } break; case 4: if (e.getValue() == null) { Set val = new HashSet(); val.add(ClockStatus.OK); setStatus(val); } else { setStatus(ClockStatus.forValue(((Number) e.getValue()).intValue())); } break; case 5: if (e.getValue() == null) { setBegin(new GXDateTime()); } else if (e.getValue() instanceof byte[]) { GXDateTime tmp; tmp = (GXDateTime) GXDLMSClient.changeType((byte[]) e.getValue(), DataType.DATETIME, e.getSettings()); setBegin(tmp); } else { setBegin((GXDateTime) e.getValue()); } break; case 6: if (e.getValue() == null) { setEnd(new GXDateTime()); } else if (e.getValue() instanceof byte[]) { GXDateTime tmp; tmp = (GXDateTime) GXDLMSClient.changeType((byte[]) e.getValue(), DataType.DATETIME, e.getSettings()); setEnd(tmp); } else { setEnd((GXDateTime) e.getValue()); } break; case 7: if (e.getValue() == null) { setDeviation(0); } else { setDeviation(((Number) e.getValue()).intValue()); } break; case 8: if (e.getValue() == null) { setEnabled(false); } else { setEnabled(((Boolean) e.getValue()).booleanValue()); } break; case 9: if (e.getValue() == null) { setClockBase(ClockBase.NONE); } else { setClockBase(ClockBase.values()[((Number) e.getValue()).intValue()]); } break; default: e.setError(ErrorCode.READ_WRITE_DENIED); break; } } @Override public final void load(final GXXmlReader reader) throws XMLStreamException { time = reader.readElementContentAsDateTime("Time"); timeZone = reader.readElementContentAsInt("TimeZone"); status = ClockStatus.forValue(reader.readElementContentAsInt("Status")); begin = reader.readElementContentAsDateTime("Begin"); end = reader.readElementContentAsDateTime("End"); deviation = reader.readElementContentAsInt("Deviation"); enabled = reader.readElementContentAsInt("Enabled") != 0; clockBase = ClockBase.values()[reader.readElementContentAsInt("ClockBase")]; } @Override public final void save(final GXXmlWriter writer) throws XMLStreamException { writer.writeElementString("Time", time); writer.writeElementString("TimeZone", timeZone); writer.writeElementString("Status", ClockStatus.toInteger(status)); writer.writeElementString("Begin", begin); writer.writeElementString("End", end); writer.writeElementString("Deviation", deviation); writer.writeElementString("Enabled", enabled); writer.writeElementString("ClockBase", clockBase.ordinal()); } @Override public final void postLoad(final GXXmlReader reader) { // Not needed for this object. } @Override public String[] getNames() { return new String[] { "Logical Name", "Time", "Time Zone", "Status", "Begin", "End", "Deviation", "Enabled", "Clock Base" }; } @Override public String[] getMethodNames() { return new String[] { "Adjust to quarter", "Adjust to measuring period", "Adjust to minute", "Adjust to preset time", "Preset adjusting time", "Shift time" }; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy