context: //
  // --------------------------------------------------------------------------
  //  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
  //---------------------------------------------------------------------------
  
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Globalization;
  using System.Xml.Serialization;
  using Gurux.DLMS.Internal;
  using Gurux.DLMS.Objects.Enums;
  using Gurux.DLMS.Enums;
  
  namespace Gurux.DLMS.Objects
  {
      /// <summary>
      /// Online help:
      /// https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSClock
      /// </summary>
      public class GXDLMSClock : GXDLMSObject, IGXDLMSBase
      {
          /// <summary>
          /// Constructor.
          /// </summary>
          public GXDLMSClock()
          : this("0.0.1.0.0.255", 0)
          {
          }
  
          public override DataType GetUIDataType(int index)
          {
              if (index == 2 || index == 5 || index == 6)
              {
                  return DataType.DateTime;
              }
              return base.GetUIDataType(index);
          }
  
          /// <summary>
          /// Constructor.
          /// </summary>
          /// <param name="ln">Logical Name of the object.</param>
          public GXDLMSClock(string ln)
          : this(ln, 0)
          {
          }
  
          /// <summary>
          /// Constructor.
          /// </summary>
          /// <param name="ln">Logical Name of the object.</param>
          /// <param name="sn">Short Name of the object.</param>
          public GXDLMSClock(string ln, ushort sn)
          : base(ObjectType.Clock, ln, sn)
          {
              Time = new GXDateTime(DateTime.MinValue);
          }       
  
          /// <summary>
          /// Time of COSEM Clock object.
          /// </summary>
          [XmlIgnore()]
          public GXDateTime Time
          {
              get;
              set;
          }
  
          /// <summary>
          /// TimeZone of COSEM Clock object.
          /// </summary>
          [XmlIgnore()]
          public int TimeZone
          {
              get;
              set;
          }
  
          /// <summary>
          /// Status of COSEM Clock object.
          /// </summary>
          [XmlIgnore()]
          public ClockStatus Status
          {
              get;
              set;
          }
  
          [XmlIgnore()]
          public GXDateTime Begin
          {
              get;
              set;
          }
  
          [XmlIgnore()]
          public GXDateTime End
          {
              get;
              set;
          }
  
          [XmlIgnore()]
          public int Deviation
          {
              get;
              set;
          }
  
          /// <summary>
          /// Is summer time enabled.
          /// </summary>
          [XmlIgnore()]
          public bool Enabled
          {
              get;
              set;
          }
  
          /// <summary>
          /// Clock base of COSEM Clock object.
          /// </summary>
          [XmlIgnore()]
          public ClockBase ClockBase
          {
              get;
              set;
          }
  
          /// <inheritdoc cref="GXDLMSObject.GetValues"/>
          public override object[] GetValues()
          {
              return new object[] { LogicalName, Time, TimeZone, Status, Begin, End,
                                Deviation, Enabled, ClockBase
                              };
          }
  
          #region IGXDLMSBase Members
  
          byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
          {
              DateTimeOffset tm = this.Time.Value;
              // Resets the value to the default value.
              // The default value is an instance specific constant.
              if (e.Index == 1)
              {
                  int minutes = tm.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 = tm.AddHours(1);
                  }
                  tm = tm.AddMinutes(-tm.Minute + minutes);
                  tm = tm.AddSeconds(-tm.Second);
                  tm = tm.AddMilliseconds(-tm.Millisecond);
                  this.Time.Value = tm;
              }
              // Sets the meter's time to the nearest minute.
              else if (e.Index == 3)
              {
                  tm = this.Time.Value;
                  int s = tm.Second;
                  if (s > 30)
                  {
                      tm = tm.AddMinutes(1);
                  }
  
gt:                 tm = tm.AddSeconds(-tm.Second);