/// <summary> /// Adds all of the intervals in the specified blocks. /// </summary> /// <param name="loadProfileData">The load profile object to add the intervals to.</param> /// <param name="loadProfileBlocks">The load profile blocks to add.</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/06/08 RCG 2.00.00 N/A Created private void AddIntervals(ref LoadProfileData loadProfileData, LPBlockDataRecord[] loadProfileBlocks) { for (int iBlock = 0; iBlock < loadProfileBlocks.Length; iBlock++) { LPBlockDataRecord CurrentBlock = loadProfileBlocks[iBlock]; LPIntervalDataRecord LastInterval = CurrentBlock.Intervals[CurrentBlock.Intervals.Length - 1]; for (int iInterval = 0; iInterval < CurrentBlock.Intervals.Length; iInterval++) { LPIntervalDataRecord CurrentInterval = CurrentBlock.Intervals[iInterval]; DateTime IntervalTime; if (iInterval + 1 < CurrentBlock.Intervals.Length) { // Figure out the time of the interval. IntervalTime = DetermineIntervalTime(CurrentBlock, iInterval, loadProfileData.IntervalDuration); IntervalTime = AdjustTimeForDST(IntervalTime, CurrentInterval, CurrentBlock.Intervals[iInterval + 1], LastInterval); } else { // We already know the time of the last interval. IntervalTime = (DateTime)CurrentBlock.BlockEndTime; } loadProfileData.AddInterval(CurrentInterval.IntervalData, ConvertChannelStatuses(CurrentInterval), ConvertIntervalStatus(CurrentInterval), IntervalTime, DisplayScaleOptions.UNITS); } } }
/// <summary> /// Gets the first block of the load profile data /// </summary> /// <param name="actualLimitingTable">The actual limiting table that applies to the data set</param> /// <param name="statusTable">The status table that applies to the data set</param> /// <param name="dataSetTable">The data set</param> /// <param name="setStatus">The status record for the data set at the time of the read</param> /// <returns>The first block of Load Profile Data</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/07/08 RCG 2.00.00 N/A Created // 12/12/11 RCG 2.53.20 Modified for Extended LP and IP support private LPBlockDataRecord GetFirstBlock(StdTable61 actualLimitingTable, StdTable63 statusTable, StdTable64 dataSetTable, out LPSetStatusRecord setStatus) { LPBlockDataRecord FirstBlock = null; LPSetActualLimits SetLimits = actualLimitingTable.GetSetLimits(dataSetTable.DataSet); LPSetStatusRecord SetStatusBeforeRead = null; LPSetStatusRecord SetStatusAfterRead = null; int BlockReadRetries = 0; ushort FirsBlockIndex = 0; do { SetStatusBeforeRead = statusTable.GetSetStatusRecord(dataSetTable.DataSet); if (SetStatusBeforeRead.DataListType == LPSetStatusRecord.ListType.Circular) { FirsBlockIndex = (ushort)((SetStatusBeforeRead.LastBlockElement + 1) % SetStatusBeforeRead.NumberOfValidBlocks); } if (SetStatusBeforeRead.NumberOfValidBlocks > 1) { FirstBlock = ReadLPBlock(dataSetTable, FirsBlockIndex, SetLimits.IntervalsPerBlock); } else { // The first block is the last block so we need to use the number of valid intervals FirstBlock = ReadLPBlock(dataSetTable, FirsBlockIndex, SetStatusBeforeRead.NumberOfValidIntervals); } SetStatusAfterRead = statusTable.GetSetStatusRecord(dataSetTable.DataSet); }while (BlockReadRetries < LP_READ_RETRIES && HasLastBlockRolledOver(SetStatusBeforeRead, SetStatusAfterRead)); setStatus = SetStatusAfterRead; return(FirstBlock); }
/// <summary> /// Determines the time of the interval but does not account for DST changes. /// </summary> /// <param name="block">The current block.</param> /// <param name="intervalIndex">The index of the interval in the block.</param> /// <param name="intervalLength">The length of one interval</param> /// <returns>The date and time of the interval.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/06/08 RCG 2.00.00 N/A Created private DateTime DetermineIntervalTime(LPBlockDataRecord block, int intervalIndex, int intervalLength) { DateTime IntervalTime = (DateTime)block.BlockEndTime; IntervalTime = IntervalTime.AddMinutes(-1 * (block.Intervals.Length - intervalIndex - 1) * intervalLength); return(IntervalTime); }
/// <summary> /// Determines the size of the table. /// </summary> /// <param name="Table0">The Table 0 object for the current device.</param> /// <param name="table2409">The Table 61 object for the current device.</param> /// <param name="table2410"> The Table 62 object for the current device</param> /// <returns>The size of the table in bytes.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/06/11 RCG 2.53.14 N/A Created private static uint DetermineTableSize(CTable00 Table0, OpenWayMFGTable2409 table2409, OpenWayMFGTable2410 table2410) { uint uiTableSize = 0; uiTableSize += table2409.Set4ActualLimits.NumberOfBlocks * LPBlockDataRecord.Size(Table0, table2409, table2410, LPDataSet.Set4); return(uiTableSize); }
/// <summary> /// Get the all of the Profile Data from the specified set of tables /// </summary> /// <param name="actualLimitingTable">The actual limiting table for the data set</param> /// <param name="controlTable">The control table for the data set</param> /// <param name="statusTable">The status table for the data set</param> /// <param name="dataSetTable">The data set table for the data set</param> /// <returns>The profile data that has been read.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/06/11 RCG 2.53.20 N/A Created // 06/15/12 jrf 2.60.32 199972 Adding logging statements to help debug issue next time we see it. // protected LoadProfileData GetProfileData(StdTable61 actualLimitingTable, StdTable62 controlTable, StdTable63 statusTable, StdTable64 dataSetTable) { LoadProfileData LPData = null; LPSetActualLimits SetLimits = actualLimitingTable.GetSetLimits(dataSetTable.DataSet); LPSetDataSelection SetDataSelection = controlTable.GetDataSelection(dataSetTable.DataSet); LPBlockDataRecord[] Blocks; LPBlockDataRecord FirstBlock; LPBlockDataRecord LastBlock; LPSetStatusRecord SetStatus; ushort NumberOfBlocks; ushort FirstBlockIndex; m_Logger.WriteLine(Logger.LoggingLevel.Functional, "Getting Profile Data"); SetStatus = statusTable.GetSetStatusRecord(dataSetTable.DataSet); m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Number of Blocks: " + SetStatus.NumberOfValidBlocks.ToString(CultureInfo.InvariantCulture)); m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Number of Intervals: " + SetStatus.NumberOfValidIntervals.ToString(CultureInfo.InvariantCulture)); if (SetStatus.NumberOfValidBlocks > 0 && SetStatus.NumberOfValidIntervals > 0) { OnShowProgress(new ShowProgressEventArgs(1, SetStatus.NumberOfValidBlocks, "Reading Load Profile data...", "Reading Load Profile data...")); // Read the first and last blocks GetFirstAndLastBlock(actualLimitingTable, statusTable, dataSetTable, out FirstBlock, out LastBlock, out SetStatus); // Read the rest of the blocks using the last block status NumberOfBlocks = SetStatus.NumberOfValidBlocks; Blocks = new LPBlockDataRecord[NumberOfBlocks]; Blocks[0] = FirstBlock; if (NumberOfBlocks > 1) { Blocks[NumberOfBlocks - 1] = LastBlock; FirstBlockIndex = (ushort)((SetStatus.LastBlockElement + 1) % NumberOfBlocks); for (ushort RelativeBlockIndex = 1; RelativeBlockIndex < NumberOfBlocks - 1; RelativeBlockIndex++) { ushort ActualBlockIndex = (ushort)((FirstBlockIndex + RelativeBlockIndex) % NumberOfBlocks); m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Reading Block # " + ActualBlockIndex.ToString(CultureInfo.InvariantCulture)); Blocks[RelativeBlockIndex] = ReadLPBlock(dataSetTable, ActualBlockIndex, SetLimits.IntervalsPerBlock); OnStepProgress(new ProgressEventArgs()); } } OnHideProgress(new EventArgs()); // Create the LoadProfileData object. LPData = CreateLoadProfileDataObject(Blocks, SetLimits, SetDataSelection); } return(LPData); }
/// <summary> /// Reads a block from the specified data set. /// </summary> /// <param name="dataSetTable">The data set to read from.</param> /// <param name="blockToRead">The block index for the block to read.</param> /// <param name="validIntervals">The number of valid intervals in the block</param> /// <returns>The block.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/07/08 RCG 2.00.00 N/A Created // 12/12/11 RCG 2.53.20 Modified for Extended LP and IP support private LPBlockDataRecord ReadLPBlock(StdTable64 dataSetTable, ushort blockToRead, ushort validIntervals) { PSEMResponse Response = PSEMResponse.Ok; LPBlockDataRecord Block = null; Response = dataSetTable.ReadBlock(blockToRead, validIntervals, out Block); // Handle any communication errors. if (Response != PSEMResponse.Ok) { throw new PSEMException(PSEMException.PSEMCommands.PSEM_READ, Response, "Error reading Load Profile block " + blockToRead.ToString(CultureInfo.CurrentCulture)); } return(Block); }
/// <summary> /// Gets the last block of Load Profile data. /// </summary> /// <param name="statusTable">The status table for the data set</param> /// <param name="dataSetTable">The data set to get the last block of.</param> /// <param name="setStatus">The set status at the time of reading.</param> /// <returns>The last load profile block.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/07/08 RCG 2.00.00 N/A Created // 12/12/11 RCG 2.53.20 Modified for Extended LP and IP support private LPBlockDataRecord GetLastBlock(StdTable63 statusTable, StdTable64 dataSetTable, out LPSetStatusRecord setStatus) { LPBlockDataRecord LastBlock = null; LPSetStatusRecord SetStatusBeforeRead = null; LPSetStatusRecord SetStatusAfterRead = null; int BlockReadRetries = 0; do { SetStatusBeforeRead = statusTable.GetSetStatusRecord(dataSetTable.DataSet); LastBlock = ReadLPBlock(dataSetTable, SetStatusBeforeRead.LastBlockElement, SetStatusBeforeRead.NumberOfValidIntervals); SetStatusAfterRead = statusTable.GetSetStatusRecord(dataSetTable.DataSet); }while (BlockReadRetries < LP_READ_RETRIES && (HasLastBlockRolledOver(SetStatusBeforeRead, SetStatusAfterRead) || HasNewIntervalOccured(SetStatusBeforeRead, SetStatusAfterRead))); setStatus = SetStatusAfterRead; return(LastBlock); }
/// <summary> /// Gets the first and last blocks of the load profile data. /// </summary> /// <param name="actualLimitingTable">The limiting table for the data set</param> /// <param name="statusTable">The status table for the data set</param> /// <param name="dataSetTable">The set to get the blocks from.</param> /// <param name="firstBlock">The first block.</param> /// <param name="lastBlock">The last block.</param> /// <param name="setStatus">The set status of the load profile data at the time of read.</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/07/08 RCG 2.00.00 N/A Created // 12/12/11 RCG 2.53.20 Modified for Extended LP and IP support // 06/15/12 jrf 2.60.32 199972 Adding logging statements to help debug issue next time we see it. // private void GetFirstAndLastBlock(StdTable61 actualLimitingTable, StdTable63 statusTable, StdTable64 dataSetTable, out LPBlockDataRecord firstBlock, out LPBlockDataRecord lastBlock, out LPSetStatusRecord setStatus) { LPSetStatusRecord FirstBlockStatus; LPSetStatusRecord LastBlockStatus; m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Read First Block"); firstBlock = GetFirstBlock(actualLimitingTable, statusTable, dataSetTable, out FirstBlockStatus); OnStepProgress(new ProgressEventArgs()); if (FirstBlockStatus.NumberOfValidBlocks > 1) { m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Read Last Block"); lastBlock = GetLastBlock(statusTable, dataSetTable, out LastBlockStatus); OnStepProgress(new ProgressEventArgs()); // Make sure the first block is still valid. if (HasLastBlockRolledOver(FirstBlockStatus, LastBlockStatus)) { m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Read First Block, Again"); firstBlock = GetFirstBlock(actualLimitingTable, statusTable, dataSetTable, out FirstBlockStatus); } // At this point we do not need to check the last block again as we should never // have multiple block rollovers in such a short period of time. We will use the // last blocks status in order to ensure the values match the last block. setStatus = LastBlockStatus; } else { // We only have one block so we should be ok. OnStepProgress(new ProgressEventArgs()); lastBlock = null; setStatus = FirstBlockStatus; } }
/// <summary> /// Determines the relative index of the block that contains the end date specified. /// </summary> /// <param name="setLimits">The actual limits for the data set.</param> /// <param name="setStatus">The status of the data set when last block was read.</param> /// <param name="lastBlock">The last block in the data set.</param> /// <param name="endDate">The end date that is being searched for.</param> /// <returns>The relative index of the block that contains the end time.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/08/08 RCG 2.00.00 N/A Created // 09/22/09 AF 2.30.02 Corrected the equation for determining last block private int DetermineEndBlockIndex(LPSetActualLimits setLimits, LPSetStatusRecord setStatus, LPBlockDataRecord lastBlock, DateTime endDate) { int EndBlockIndex = 0; DateTime LastBlockStartTime; bool IncludeLastBlock; LastBlockStartTime = DetermineIntervalTime(lastBlock, 0, setLimits.IntervalLength); if (lastBlock.Intervals.Length > 1) { LastBlockStartTime = AdjustTimeForDST(LastBlockStartTime, lastBlock.Intervals[0], lastBlock.Intervals[1], lastBlock.Intervals[setStatus.NumberOfValidIntervals - 1]); } IncludeLastBlock = endDate >= LastBlockStartTime; if (!IncludeLastBlock) { // We need to determine the last block. Start at the next to last block for (int iBlock = setStatus.NumberOfValidBlocks - 2; iBlock >= 1; iBlock--) { DateTime BlockStartTime = LastBlockStartTime; BlockStartTime = BlockStartTime.AddMinutes(-1 * (setStatus.NumberOfValidBlocks - (iBlock + 1)) * setLimits.IntervalsPerBlock * setLimits.IntervalLength); if (BlockStartTime <= endDate) { EndBlockIndex = iBlock; break; } } } else { EndBlockIndex = setStatus.NumberOfValidBlocks - 1; } return(EndBlockIndex); }
/// <summary> /// Determines the relative index of the block that contains the start date specified. /// </summary> /// <param name="setLimits">The actual limits for the data set.</param> /// <param name="setStatus">The status of the data set when last block was read.</param> /// <param name="firstBlock">The last block in the data set.</param> /// <param name="startDate">The start date that is being searched for.</param> /// <returns>The relative index of the block that contains the start date.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/08/08 RCG 2.00.00 N/A Created private int DetermineStartBlockIndex(LPSetActualLimits setLimits, LPSetStatusRecord setStatus, LPBlockDataRecord firstBlock, DateTime startDate) { int StartBlockIndex = 0; bool IncludeFirstBlock; IncludeFirstBlock = startDate <= firstBlock.BlockEndTime; if (!IncludeFirstBlock) { // We need to determine the starting block for (int iBlock = 1; iBlock < setStatus.NumberOfValidBlocks; iBlock++) { DateTime BlockEndTime = (DateTime)firstBlock.BlockEndTime; BlockEndTime = BlockEndTime.AddMinutes(iBlock * setLimits.IntervalsPerBlock * setLimits.IntervalLength); if (BlockEndTime >= startDate) { StartBlockIndex = iBlock; break; } } } else { StartBlockIndex = 0; } return(StartBlockIndex); }
/// <summary> /// Gets the load profile data between the specified dates. /// </summary> /// <param name="startDate">The start date of the load profile data to get.</param> /// <param name="endDate">The end date of the load profile data to get.</param> /// <param name="actualLimitingTable">The actual limiting table for the data set</param> /// <param name="controlTable">The control table for the data set</param> /// <param name="statusTable">The status table for the data set</param> /// <param name="dataSetTable">The data set table for the data set</param> /// <returns>The load profile data from the dates specified.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/06/11 RCG 2.53.20 N/A Created public LoadProfileData GetProfileData(DateTime startDate, DateTime endDate, StdTable61 actualLimitingTable, StdTable62 controlTable, StdTable63 statusTable, StdTable64 dataSetTable) { LPSetActualLimits SetLimits = actualLimitingTable.GetSetLimits(dataSetTable.DataSet); LPBlockDataRecord FirstBlock; LPBlockDataRecord LastBlock; LPBlockDataRecord[] Blocks; LPSetStatusRecord SetStatus; LoadProfileData LPData = null; int StartBlockIndex; int EndBlockIndex; int FirstBlockIndex; SetStatus = statusTable.GetSetStatusRecord(dataSetTable.DataSet); if (SetStatus != null) { if (SetStatus.NumberOfValidBlocks > 1 && SetStatus.NumberOfValidIntervals > 0) { OnShowProgress(new ShowProgressEventArgs(1, 2, "Determining blocks to read...", "Determining blocks to read...")); // Get the first and last blocks in order to determine the blocks we need to read. GetFirstAndLastBlock(actualLimitingTable, statusTable, dataSetTable, out FirstBlock, out LastBlock, out SetStatus); OnStepProgress(new ProgressEventArgs()); // Determine which blocks to read StartBlockIndex = DetermineStartBlockIndex(SetLimits, SetStatus, FirstBlock, startDate); EndBlockIndex = DetermineEndBlockIndex(SetLimits, SetStatus, LastBlock, endDate); Blocks = new LPBlockDataRecord[EndBlockIndex - StartBlockIndex + 1]; FirstBlockIndex = (SetStatus.LastBlockElement + 1) % SetStatus.NumberOfValidBlocks; OnHideProgress(new EventArgs()); OnShowProgress(new ShowProgressEventArgs(1, EndBlockIndex - StartBlockIndex, "Reading Load Profile data...", "Reading Load Profile data...")); // Read the blocks for (int RelativeBlockIndex = StartBlockIndex; RelativeBlockIndex <= EndBlockIndex; RelativeBlockIndex++) { int BlockArrayIndex = RelativeBlockIndex - StartBlockIndex; OnStepProgress(new ProgressEventArgs()); // We already have the first and last blocks so just add those if included. if (RelativeBlockIndex == 0) { Blocks[BlockArrayIndex] = FirstBlock; } else if (RelativeBlockIndex == SetStatus.NumberOfValidBlocks - 1) { // The last block Blocks[BlockArrayIndex] = LastBlock; } else { // We need to read the block ushort ActualBlockIndex = (ushort)((FirstBlockIndex + RelativeBlockIndex) % SetStatus.NumberOfValidBlocks); Blocks[BlockArrayIndex] = ReadLPBlock(dataSetTable, ActualBlockIndex, SetLimits.IntervalsPerBlock); } } OnStepProgress(new ProgressEventArgs("Creating Load Profile object...")); // Create the LoadProfileData object. LPData = CreateLoadProfileDataObject(Blocks, SetLimits, controlTable.GetDataSelection(dataSetTable.DataSet)); OnStepProgress(new ProgressEventArgs("Removing additional intervals...")); // Trim out intervals that were not requested. LPData.Intervals.RemoveAll(delegate(LPInterval interval) { return(interval.Time < startDate || interval.Time > endDate); }); OnHideProgress(new EventArgs()); } else if (SetStatus.NumberOfValidBlocks == 1) { OnShowProgress(new ShowProgressEventArgs(1, 3, "Reading Load Profile data...", "Reading Load Profile data...")); // Just get the first block the trim will take care of anything outside the range FirstBlock = GetFirstBlock(actualLimitingTable, statusTable, dataSetTable, out SetStatus); OnStepProgress(new ProgressEventArgs()); LPData = CreateLoadProfileDataObject(new LPBlockDataRecord[] { FirstBlock }, SetLimits, controlTable.GetDataSelection(dataSetTable.DataSet)); OnStepProgress(new ProgressEventArgs()); // Trim out intervals that were not requested. LPData.Intervals.RemoveAll(delegate(LPInterval interval) { return(interval.Time < startDate || interval.Time > endDate); }); OnStepProgress(new ProgressEventArgs()); OnHideProgress(new EventArgs()); } } return(LPData); }