/// <summary> /// Updates DST in the connected meter. This method does not reconfigure /// DST. Only future dates in 2007 and beyond are updated. /// </summary> /// <param name="DSTFileName">The filename including path for the DST file</param> /// <returns>A DSTUpdateResult</returns> /// // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 06/16/06 mcm 7.30.00 N/A Created // 01/24/07 mrj 8.00.08 Flushed status flags when updating dst // public override DSTUpdateResult UpdateDST(string DSTFileName) { FileStream EDLFileStream; XmlTextReader EDLXMLReader; string defaultEDLFileName; if (m_TOUTables == null) { m_TOUTables = new CentronTables(); } defaultEDLFileName = CRegistryHelper.GetFilePath(CentronII_REPLICA) + CentronII_PROGRAM_FOLDER + DEFAULT_PROGRAM; if (File.Exists(defaultEDLFileName)) { EDLFileStream = new FileStream(defaultEDLFileName, FileMode.Open, FileAccess.Read, FileShare.Read); EDLXMLReader = new XmlTextReader(EDLFileStream); // Load the Defaul EDL File as the file stream to process TOU and DST data m_TOUTables.LoadEDLFile(EDLXMLReader); } if (DSTFileName != null) { ClearDST(); // Key step to clear DST first ImportDST(); DSTDataSet = m_TOUTables.BuildPSEMStreams(2260); } AMIConfigureCentronII configureDevice = new AMIConfigureCentronII(m_PSEM); DSTUpdateResult result = configureDevice.ReconfigureDST(DSTDataSet) ? DSTUpdateResult.SUCCESS : DSTUpdateResult.ERROR; return(result); }
/// <summary> /// Reads Table 2511 (mfg 463) /// </summary> /// <param name="MeterTables">The meter tables object</param> /// <returns>The result of the read</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 09/03/13 AF 2.85.34 WR418110 Created // public PSEMResponse ReadTable2511(ref CentronTables MeterTables) { PSEMResponse PSEMResult = PSEMResponse.Ok; MemoryStream PSEMDataStream; byte[] PSEMData; ushort usTableSize = 0; object objData; byte bytNumberStatRecords = 0; if (MeterTables.IsCached((long)CentronTblEnum.MfgTbl462NumberOfStatRecords, null)) { MeterTables.GetValue((long)CentronTblEnum.MfgTbl462NumberOfStatRecords, null, out objData); bytNumberStatRecords = (byte)objData; } usTableSize = (ushort)(bytNumberStatRecords * ERT_STAT_DATA_RCD_SIZE); // Read the records PSEMResult = m_PSEM.OffsetRead(2511, 0, usTableSize, out PSEMData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(PSEMData, 0, PSEMData.Length, true, true); MeterTables.SavePSEMStream(2511, PSEMDataStream, 0); } return(PSEMResult); }
/// <summary> /// Updates the TOU for the program file. /// </summary> /// <param name="ProgramTables">Program data.</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/17/13 jrf 3.50.16 TQ 9560 Created. // 01/08/14 jrf 3.50.22 TQ 9560 Making sure CentronTables's Create25YearCalendarFromStandardTables(...) // gets called beforeUpdateTOUSeasonFromStandardTables(...). // // protected override void UpdateTOU(CentronTables ProgramTables) { if (null != m_BridgeDevice) { m_BridgeDevice.UpdateTOU(ProgramTables); } base.UpdateTOU(ProgramTables); }
/// <summary> /// Reconfigures TOU in the connected meter /// </summary> /// <param name="TOUFileName">The filename including path for the TOU</param> /// <param name="DSTFileName">The filename including path for the DST /// file. If this parameter is emtpy then client only wants to /// reconfigure TOU, not DST. The DSTFileName MUST be included if the /// meter is configured for DST. If the meter is not configured for DST /// and this filename is given, the operation will succeed, but it will /// return a conditional success code.</param> /// <returns>A TOUReconfigResult</returns> /// // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/04/10 SCW 9.70.14 Created public override TOUReconfigResult ReconfigureTOU(string TOUFileName, string DSTFileName) { FileStream EDLFileStream; XmlTextReader EDLXMLReader; string defaultEDLFileName; try { if (m_TOUTables == null) { m_TOUTables = new CentronTables(); } defaultEDLFileName = CRegistryHelper.GetFilePath(CentronII_REPLICA) + CentronII_PROGRAM_FOLDER + DEFAULT_PROGRAM; if (File.Exists(defaultEDLFileName)) { EDLFileStream = new FileStream(defaultEDLFileName, FileMode.Open, FileAccess.Read, FileShare.Read); EDLXMLReader = new XmlTextReader(EDLFileStream); // Load the Defaul EDL File as the file stream to process TOU and DST data m_TOUTables.LoadEDLFile(EDLXMLReader); } if (TOUFileName != null) { ClearTOU(); // Key step to clear TOU first ImportTOU(TOUFileName); TOUDataSet = m_TOUTables.BuildPSEMStreams(2090); } } catch (Exception) { throw new ArgumentException("Failure in importing EDL or DST files !!"); } CTable2048Header m_2048Header = new CTable2048Header(m_PSEM); AMIConfigureCentronII configureDevice = new AMIConfigureCentronII(m_PSEM); TOUReconfigResult result = configureDevice.ReconfigureTOU(TOUDataSet, m_2048Header.CalendarOffset, m_2048Header.TOUOffset) ? TOUReconfigResult.SUCCESS : TOUReconfigResult.ERROR; return(result); }
/// <summary> /// Handles the special case table reads /// </summary> /// <param name="usTableID">id of the table to read</param> /// <param name="MeterTables">reference to the CE dll object</param> /// <returns>the PSEM response to the read attempt</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- -------- ------------------------------------------- // 11/21/13 DLG 3.50.07 No WR Overriding here to handle ICS related tables. // 12/18/13 AF 3.50.16 WR444069 Removed the call to the base class ReadTable. It was causing a full // read of table 2524, which is not supported. // 05/08/14 AF 3.50.91 WR503773 Added cases for tables 2242 and 2243 // public override PSEMResponse ReadTable(ushort usTableID, ref CentronTables MeterTables) { MemoryStream PSEMDataStream; PSEMResponse PSEMResult = PSEMResponse.Ok; byte[] byaData; int iReadAttempt = 0; bool bRetry = true; while (bRetry) { switch (usTableID) { case 2242: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = ReadTable2242(ref MeterTables, ICS_MAX_OFFSET_READ_SIZE); } break; } case 2243: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = ReadTable2243(ref MeterTables, ICS_MAX_OFFSET_READ_SIZE); } break; } case 2508: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2508(ref MeterTables); } break; } case 2511: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2511(ref MeterTables); } break; } case 2524: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2524(ref MeterTables); } break; } default: { PSEMResult = m_PSEM.FullRead(usTableID, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData, 0, byaData.Length, true, true); MeterTables.SavePSEMStream(usTableID, PSEMDataStream); } break; } } iReadAttempt++; if (iReadAttempt < 3 && (PSEMResult == PSEMResponse.Bsy || PSEMResult == PSEMResponse.Dnr)) { bRetry = true; System.Threading.Thread.Sleep(1000); } else { bRetry = false; } } return(PSEMResult); }
/// <summary> /// Reconfigures TOU using the specified EDL file /// </summary> /// <param name="strFileName">The EDL file that contains the TOU data.</param> /// <param name="iSeasonIndex">The number of seasons from the current season to write</param> /// <returns>TOUReconfigResult code.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/24/06 RCG 7.40.00 N/A Created public WritePendingTOUResult WritePendingTOU(string strFileName, int iSeasonIndex) { WritePendingTOUResult Result = WritePendingTOUResult.SUCCESS; CentronTables DeviceTables = new CentronTables(); TableData[] PSEMData = null; DateTime dtSeasonStart = new DateTime(); DateTime dtNextSeasonStart = new DateTime(); bool bDemandReset = false; bool bSelfRead = false; // Load the file into the tables if (File.Exists(strFileName) == true) { try { OnStepProgress(new ProgressEventArgs("Loading EDL File...")); DeviceTables.LoadEDLFile(XmlReader.Create(strFileName)); OnStepProgress(new ProgressEventArgs("Selecting Season...")); DeviceTables.UpdateTOUSeasonFromStandardTables(DateTime.Now, iSeasonIndex, out dtSeasonStart, out bDemandReset, out bSelfRead, out dtNextSeasonStart); } catch (Exception) { Result = WritePendingTOUResult.INVALID_EDL_FILE; } } else { Result = WritePendingTOUResult.FILE_NOT_FOUND; } if (Result == WritePendingTOUResult.SUCCESS) { OnStepProgress(new ProgressEventArgs("Building Pending Table...")); // Build the streams for the pending table PSEMData = DeviceTables.BuildPSEMStreams(TOU_MFG_TABLE); OnStepProgress(new ProgressEventArgs("Checking for Available Pending Buffers...")); // Check to make sure there are enough Pending Table Buffers available if (Table04.NumberPendingTables + PSEMData.Length > Table04.NumberPendingSupported) { Result = WritePendingTOUResult.PENDING_BUFFERS_FULL; } } if (Result == WritePendingTOUResult.SUCCESS) { PSEMResponse PSEMResult = PSEMResponse.Ok; // Write the TOU to the meter foreach (TableData DataBlock in PSEMData) { OnStepProgress(new ProgressEventArgs("Writing Pending Table...")); if (PSEMResult == PSEMResponse.Ok) { MemoryStream PendingHeader = new MemoryStream(); if (PSEMData[0] == DataBlock) { // This is the first stream so set the Demand Reset and Self Read DeviceTables.BuildPendingHeader(PendingHeader, dtSeasonStart, bSelfRead, bDemandReset); } else { // Ignore the Self Read and Demand Reset since it was already set in the // first stream. DeviceTables.BuildPendingHeader(PendingHeader, dtSeasonStart, false, false); } DataBlock.AddPendingHeader(PendingHeader); if (DataBlock.FullTable == true) { PSEMResult = m_PSEM.FullWrite(DataBlock.TableID, DataBlock.PSEM.ToArray()); } else { PSEMResult = m_PSEM.OffsetWrite(DataBlock.TableID, (int)DataBlock.Offset, DataBlock.PSEM.ToArray()); } } } OnStepProgress(new ProgressEventArgs()); // Check the PSEM Result if (PSEMResult == PSEMResponse.Isc) { Result = WritePendingTOUResult.INSUFFICIENT_SECURITY_ERROR; } else if (PSEMResult != PSEMResponse.Ok) { Result = WritePendingTOUResult.PROTOCOL_ERROR; } // Clear the TOU information if we changed the current season. if (iSeasonIndex == 0) { m_TOUSchedule = null; Table2048.TOUConfig.State = AnsiTable.TableState.Unloaded; Table2048.CalendarConfig.State = AnsiTable.TableState.Unloaded; Table2048.BillingSchedConfig.State = AnsiTable.TableState.Unloaded; m_TOUExpireDate.Flush(); m_DayOfTheWeek.Flush(); m_uiNumTOURates.Flush(); m_MeterInDST.Flush(); } } return(Result); }
/// <summary> /// Reads Table 2524 (mfg 476) /// </summary> /// <param name="MeterTables">The meter tables object</param> /// <returns>The result of the read</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 06/27/13 AF 2.80.44 TR7648 Created // 07/16/13 AF 2.80.53 WR417522 Adjusted the size of the offset reads to make sure that each // reads an even multiple of entries. // 06/19/15 AF 4.20.14 591427 Calculate the table size instead of retrieving from the CE dlls // 07/23/15 AF 4.20.18 597509 The number of entries from table 2521 might not be correct so read from 2524 // public PSEMResponse ReadTable2524(ref CentronTables MeterTables) { PSEMResponse PSEMResult = PSEMResponse.Ok; MemoryStream PSEMDataStream; byte[] PSEMData; uint TableSize = 0; uint CurrentOffset = 0; uint NumberUnreadEntriesOffset; uint NumberUnreadEntriesLength; ushort NumberICSEntries = 0; uint HeaderSize; object objData; uint SizeOfEntry = ICS_LOG_RCD_BASIC; bool blnEventNumberFlag = false; if (MeterTables.IsCached((long)CentronTblEnum.MFGTBL473_EVENT_NUMBER_FLAG, null)) { MeterTables.GetValue((long)CentronTblEnum.MFGTBL473_EVENT_NUMBER_FLAG, null, out objData); blnEventNumberFlag = (bool)objData; } if (MeterTables.IsCached((long)CentronTblEnum.MFGTBL473_ICS_DATA_LENGTH, null)) { MeterTables.GetValue((long)CentronTblEnum.MFGTBL473_ICS_DATA_LENGTH, null, out objData); SizeOfEntry += (byte)objData; } if (blnEventNumberFlag) { SizeOfEntry += sizeof(UInt16); } MeterTables.GetFieldOffset((long)CentronTblEnum.MFGTBL476_NBR_UNREAD_ENTRIES, null, out NumberUnreadEntriesOffset, out NumberUnreadEntriesLength); HeaderSize = NumberUnreadEntriesOffset + NumberUnreadEntriesLength; // Read the header PSEMResult = m_PSEM.OffsetRead(2524, 0, (ushort)HeaderSize, out PSEMData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(PSEMData); MeterTables.SavePSEMStream(2524, PSEMDataStream, 0); CurrentOffset += HeaderSize; ushort BytesToRead; if (MeterTables.IsCached((long)CentronTblEnum.MFGTBL476_NBR_VALID_ENTRIES, null)) { MeterTables.GetValue((long)CentronTblEnum.MFGTBL476_NBR_VALID_ENTRIES, null, out objData); NumberICSEntries = (ushort)objData; } TableSize = HeaderSize + (SizeOfEntry * NumberICSEntries); // Read the entries while (CurrentOffset < TableSize) { if ((TableSize - CurrentOffset) < MAX_ENTRIES_IN_ONE_READ * SizeOfEntry) { BytesToRead = (ushort)(TableSize - CurrentOffset); } else { BytesToRead = (ushort)(MAX_ENTRIES_IN_ONE_READ * SizeOfEntry); } PSEMResult = m_PSEM.OffsetRead(2524, (int)CurrentOffset, BytesToRead, out PSEMData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(PSEMData); MeterTables.SavePSEMStream(2524, PSEMDataStream, CurrentOffset); CurrentOffset += BytesToRead; } else { break; } } } return(PSEMResult); }
/// <summary> /// Reads the specified table from the meter. /// </summary> /// <param name="usTableID">The table ID for the table to read.</param> /// <param name="MeterTables">The tables object to read the table into.</param> /// <returns>PSEMResponse code.</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- -------- ------------------------------------------- // 11/21/13 DLG 3.50.07 No WR Overriding to handle ICS related tables // 05/08/14 AF 3.50.91 WR503773 Added a case for table 2242 // 05/09/14 AF 3.50.91 WR503773 Removed the case for table 2242. We should be consistent with // CENTRON_AMI which also does not have a case for 2242. // 06/11/14 AF 4.00.25 WR442864 Added back the case for table 2242, due to test failures // 07/23/15 jrf 4.20.18 598314 Removing code that is duplicated from base class and // calling base.ReadTable(...) in default case to handle those cases. public override PSEMResponse ReadTable(ushort usTableID, ref CentronTables MeterTables) { PSEMResponse PSEMResult = PSEMResponse.Ok; int iReadAttempt = 0; bool bRetry = true; while (bRetry) { switch (usTableID) { case 2508: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2508(ref MeterTables); } break; } case 2511: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2511(ref MeterTables); } break; } case 2524: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = m_ICSTableReader.ReadTable2524(ref MeterTables); } break; } default: { PSEMResult = base.ReadTable(usTableID, ref MeterTables); iReadAttempt = 3; //Skipping retries since they will be handled in base class break; } } iReadAttempt++; if (iReadAttempt < 3 && (PSEMResult == PSEMResponse.Bsy || PSEMResult == PSEMResponse.Dnr)) { bRetry = true; System.Threading.Thread.Sleep(1000); } else { bRetry = false; } } return(PSEMResult); }
/// <summary> /// Creates an EDL file with the specified sections. /// </summary> /// <param name="FileName">Path to the file where the EDL file will be written.</param> /// <param name="IncludedSections">The sections to include in the EDL file.</param> /// <returns>CreateEDLResult Code.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 04/25/08 RCG 1.50.19 Created // 07/06/10 AF 2.42.02 Made virtual for use in the M2 Gateway public override CreateEDLResult CreateEDLFromMeter(string FileName, EDLSections IncludedSections) { CentronTables MeterTables = new CentronTables(); List <ushort> TablesToRead; int iFileNameStart; string strDirectory; CreateEDLResult Result = CreateEDLResult.SUCCESS; PSEMResponse PSEMResult = PSEMResponse.Ok; // First check to make sure we can create the file iFileNameStart = FileName.LastIndexOf(@"\", StringComparison.Ordinal); if (iFileNameStart > 0) { strDirectory = FileName.Substring(0, iFileNameStart); if (Directory.Exists(strDirectory) == false) { Result = CreateEDLResult.INVALID_PATH; } } // Make sure we will be able to write to the file if (Result == CreateEDLResult.SUCCESS && File.Exists(FileName) == true) { FileInfo OutputFile = new FileInfo(FileName); if ((OutputFile.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { Result = CreateEDLResult.INVALID_PATH; } } if (Result == CreateEDLResult.SUCCESS) { // Read the data from the meter TablesToRead = GetTablesToRead(IncludedSections); OnShowProgress(new ShowProgressEventArgs(1, TablesToRead.Count, "Creating EDL file...", "Creating EDL file...")); foreach (ushort TableID in TablesToRead) { if (PSEMResult == PSEMResponse.Ok) { // Read the table if it exists if ((Table00.IsTableUsed(TableID) == true)) { if (MeterTables.GetTableDependencies(TableID).Contains(TableID) || MeterTables.GetTableLength(TableID) > 0) { PSEMResult = ReadTable(TableID, ref MeterTables); if (PSEMResult == PSEMResponse.Bsy || PSEMResult == PSEMResponse.Dnr || PSEMResult == PSEMResponse.Iar || PSEMResult == PSEMResponse.Onp || PSEMResult == PSEMResponse.Err) { // We can't read the table but we should be able to continue we just need to // clear out anything that is there. MeterTables.ClearTable(TableID); PSEMResult = PSEMResponse.Ok; } } } OnStepProgress(new ProgressEventArgs()); } } if (PSEMResult == PSEMResponse.Isc) { Result = CreateEDLResult.SECURITY_ERROR; } else if (PSEMResult != PSEMResponse.Ok) { Result = CreateEDLResult.PROTOCOL_ERROR; } } #if (WindowsCE) //The saving of the EDL file on the handheld can take over 6 seconds so we need //to send a wait before. m_PSEM.Wait(CPSEM.MAX_WAIT_TIME); #endif // Generate the EDL file if (Result == CreateEDLResult.SUCCESS) { XmlWriterSettings WriterSettings = new XmlWriterSettings(); WriterSettings.Encoding = Encoding.ASCII; WriterSettings.Indent = true; WriterSettings.CheckCharacters = false; XmlWriter EDLWriter = XmlWriter.Create(FileName, WriterSettings); MeterTables.SaveEDLFile(EDLWriter, null, AllowTableExport, AllowFieldExport); System.Threading.Thread.Sleep(2000); } OnHideProgress(new EventArgs()); return(Result); }
/// <summary> /// Reads Table 2152 /// </summary> /// <param name="MeterTables">The tables for the meter.</param> /// <returns>The PSEM response for communications.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 05/15/08 RCG 1.50.24 N/A Created protected PSEMResponse ReadTable2152(ref CentronTables MeterTables) { PSEMResponse PSEMResult = PSEMResponse.Ok; MemoryStream PSEMDataStream; byte[] byaData; CentronTables TempTables = new CentronTables(); uint uiMaxOffsetReadBytes; uint uiReadMemorySize; uint uiNumberOfReads; uint uiBytesToRead; uint uiCurrentOffset; uint uiBlockOffset; uint uiBlockLength; uint uiMaxBlocksToRead; uint uiMaxBytesToRead; ushort usValidBlocks; ushort usNumberIntervals; ushort usNewValidBlocks; ushort usNewNumberIntervals; ushort usNewLastBlock; int iBlockToRead; // This must be initialized to false or you will break the retry logic. bool bBlocksReRead = false; object objData; // Since Voltage Monitoring Data can be very large (144k) it may not be able // to be read completely when doing a full read so we need to break // it up into multiple offset reads. Table 2149 must be read prior to this. if (MeterTables.IsCached((long)CentronTblEnum.MFGTBL101_MEMORY_LEN, null) == true) { uiMaxOffsetReadBytes = (m_PSEM.PacketSize - PACKET_OVERHEAD_SIZE) * PACKETS_PER_READ; // Because offset reads can be only up to ushort.MaxValue, limit to that if needed. if (uiMaxOffsetReadBytes > ushort.MaxValue) { uiMaxOffsetReadBytes = ushort.MaxValue; } MeterTables.GetValue(CentronTblEnum.MFGTBL103_NBR_VALID_BLOCKS, null, out objData); usValidBlocks = (ushort)objData; MeterTables.GetValue(CentronTblEnum.MFGTBL103_NBR_VALID_INT, null, out objData); usNumberIntervals = (ushort)objData; // Determine the size of a Voltage monitoring data block MeterTables.GetFieldOffset((long)CentronTblEnum.MFGTBL104_VM_DATA, new int[] { 0 }, out uiBlockOffset, out uiBlockLength); // Determine how many blocks can be read in an offset read uiMaxBlocksToRead = uiMaxOffsetReadBytes / uiBlockLength; uiMaxBytesToRead = uiMaxBlocksToRead * uiBlockLength; // Determine total amount to read uiReadMemorySize = usValidBlocks * uiBlockLength; // Determine how many reads need to be done uiNumberOfReads = usValidBlocks / uiMaxBlocksToRead; // Add in a read for any remaining data if (usValidBlocks % uiMaxBlocksToRead > 0) { uiNumberOfReads++; } uiCurrentOffset = 0; for (uint iIndex = 0; iIndex < uiNumberOfReads && PSEMResult == PSEMResponse.Ok; iIndex++) { uiBytesToRead = uiReadMemorySize - uiCurrentOffset; if (uiBytesToRead > uiMaxBytesToRead) { uiBytesToRead = uiMaxBytesToRead; } PSEMResult = m_PSEM.OffsetRead(2152, (int)uiCurrentOffset, (ushort)uiBytesToRead, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData); MeterTables.SavePSEMStream(2152, PSEMDataStream, uiCurrentOffset); uiCurrentOffset += uiBytesToRead; } OnStepProgress(new ProgressEventArgs()); } // Reread table 63 and make sure no new intervals have occurred while reading CentronTables.CopyTable(0, MeterTables, TempTables); CentronTables.CopyTable(1, MeterTables, TempTables); CentronTables.CopyTable(2148, MeterTables, TempTables); CentronTables.CopyTable(2149, MeterTables, TempTables); CentronTables.CopyTable(2150, MeterTables, TempTables); do { ReadTable(2151, ref TempTables); TempTables.GetValue(CentronTblEnum.MFGTBL103_NBR_VALID_BLOCKS, null, out objData); usNewValidBlocks = (ushort)objData; TempTables.GetValue(CentronTblEnum.MFGTBL103_NBR_VALID_INT, null, out objData); usNewNumberIntervals = (ushort)objData; if (usNewNumberIntervals != usNumberIntervals || usNewValidBlocks != usValidBlocks) { // This will limit us to only two tries at this. (if it is already true it will be set // to false which means we won't try this again.) bBlocksReRead = !bBlocksReRead; // A new interval has occurred so we need to reread atleast one block CentronTables.CopyTable(2151, TempTables, MeterTables); MeterTables.GetValue(CentronTblEnum.MFGTBL103_LAST_BLOCK_ELEMENT, null, out objData); usNewLastBlock = (ushort)objData; // Determine the offset of the block iBlockToRead = (int)usNewLastBlock; MeterTables.GetFieldOffset((long)CentronTblEnum.MFGTBL104_VM_DATA, new int[] { iBlockToRead }, out uiBlockOffset, out uiBlockLength); PSEMResult = m_PSEM.OffsetRead(2152, (int)uiBlockOffset, (ushort)uiBlockLength, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData); MeterTables.SavePSEMStream(2152, PSEMDataStream, uiBlockOffset); // Now if there was also a new block we need to reread the previous block as well. if (usNewValidBlocks != usValidBlocks) { if (usNewLastBlock - 1 < 0) { iBlockToRead = usNewValidBlocks - 1; } else { iBlockToRead = usNewLastBlock - 1; } // Determine the offset of the block MeterTables.GetFieldOffset((long)CentronTblEnum.MFGTBL104_VM_DATA, new int[] { iBlockToRead }, out uiBlockOffset, out uiBlockLength); PSEMResult = m_PSEM.OffsetRead(2152, (int)uiBlockOffset, (ushort)uiBlockLength, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData); MeterTables.SavePSEMStream(2152, PSEMDataStream, uiBlockOffset); } } } // Make sure that we save the new data to the old. usValidBlocks = usNewValidBlocks; usNumberIntervals = usNewNumberIntervals; } else // No new interval occurred { bBlocksReRead = false; } } while (bBlocksReRead == true); } else { throw new Exception("Table 2149 must be read prior to Table 2152."); } return(PSEMResult); }
/// <summary> /// Reads the specified table from the meter. /// </summary> /// <param name="usTableID">The table ID for the table to read.</param> /// <param name="MeterTables">The tables object to read the table into.</param> /// <returns>PSEMResponse code.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 10/19/06 RCG 7.40.00 Created // 01/11/07 RCG 8.00.05 Removed code that would do a full read since // the meter no longer supports full reads of 64 protected PSEMResponse ReadTable(ushort usTableID, ref CentronTables MeterTables) { MemoryStream PSEMDataStream; PSEMResponse PSEMResult = PSEMResponse.Ok; byte[] byaData; int iReadAttempt = 0; bool bRetry = true; while (bRetry) { switch (usTableID) { case 64: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = ReadTable64(ref MeterTables); } break; } case 2152: { if (PSEMResult == PSEMResponse.Ok) { PSEMResult = ReadTable2152(ref MeterTables); } break; } default: { if (0x0800 == usTableID) { PSEMResult = PSEMResponse.Ok; } PSEMResult = m_PSEM.FullRead(usTableID, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData); MeterTables.SavePSEMStream(usTableID, PSEMDataStream); } break; } } iReadAttempt++; if (iReadAttempt < 3 && (PSEMResult == PSEMResponse.Bsy || PSEMResult == PSEMResponse.Dnr)) { bRetry = true; System.Threading.Thread.Sleep(1000); } else { bRetry = false; } } return(PSEMResult); }
/// <summary> /// Checks to see if the item matches and then creates a ProgramValidationItem if it does not. /// </summary> /// <param name="item">The item to validate</param> /// <param name="meterTables">The table structure for the meter.</param> /// <param name="programTables">The table structure for the program.</param> /// <returns>Returns the ProgramValidationItem for the value if the items do not match, and null if the values match.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 05/23/07 RCG 8.10.05 Created // 12/18/13 jrf 3.50.16 TQ9560 Refactored retreival of a CentronTables value into its own method. protected override ProgramValidationItem ValidateItem(EDLValidationItem item, CentronTables meterTables, CentronTables programTables) { bool bItemsMatch = false; bool bCheckedInBaseClass = false; string strDisplayMeterValue = ""; string strDisplayProgramValue = ""; object objMeterValue; object objProgramValue; ProgramValidationItem InvalidItem = null; // Get the values objMeterValue = GetTableValue(item, meterTables); objProgramValue = GetTableValue(item, programTables); switch (item.Item) { case (long)CentronTblEnum.MFGTBL0_LOCK_SITESCAN_ERROR: { object ScrollMeterValue; object ScrollProgramValue; // Get the scroll values meterTables.GetValue(CentronTblEnum.MFGTBL0_SCROLL_SITESCAN_ERROR, item.Index, out ScrollMeterValue); programTables.GetValue(CentronTblEnum.MFGTBL0_SCROLL_SITESCAN_ERROR, item.Index, out ScrollProgramValue); strDisplayMeterValue = ConvertDisplayableErrors((bool)objMeterValue, (bool)ScrollMeterValue); strDisplayProgramValue = ConvertDisplayableErrors((bool)objProgramValue, (bool)ScrollProgramValue); if (strDisplayMeterValue == strDisplayProgramValue) { bItemsMatch = true; } break; } default: { InvalidItem = base.ValidateItem(item, meterTables, programTables); bCheckedInBaseClass = true; break; } } if (bItemsMatch == false && bCheckedInBaseClass == false) { // There is a mismatch so add the item. InvalidItem = new ProgramValidationItem(item.Category, item.Name, strDisplayProgramValue, strDisplayMeterValue); } return(InvalidItem); }
/// <summary> /// Checks to see if the item matches and then creates a ProgramValidationItem if it does not. /// </summary> /// <param name="item">The item to validate</param> /// <param name="meterTables">The table structure for the meter.</param> /// <param name="programTables">The table structure for the program.</param> /// <returns>Returns the ProgramValidationItem for the value if the items do not match, and null if the values match.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 12/12/13 jrf 3.50.16 TQ 9560 Created. // protected override ProgramValidationItem ValidateItem(EDLValidationItem item, CentronTables meterTables, CentronTables programTables) { bool blnFoundItem = false; ProgramValidationItem InvalidItem = null; if (null != m_BridgeDevice) { blnFoundItem = m_BridgeDevice.ValidateItem(item, meterTables, programTables, out InvalidItem); } if (blnFoundItem == false) { // If we didn't find item check base method. InvalidItem = base.ValidateItem(item, meterTables, programTables); } return(InvalidItem); }
/// <summary> /// Gets the list of Energies required by the program. /// </summary> /// <param name="programFile">The path to the program file</param> /// <returns>The list of required energies</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 03/22/11 RCG 2.50.12 N/A Created // 10/15/14 jrf 4.00.73 539220 Made method public for use in QC Tool. public override List <BaseEnergies> GetRequiredEnergiesFromProgram(string programFile) { List <BaseEnergies> RequiredEnergies = new List <BaseEnergies>(); XmlReader Reader; XmlReaderSettings ReaderSettings = new XmlReaderSettings(); // Create the CentronTables object to read the file ReaderSettings.ConformanceLevel = ConformanceLevel.Fragment; ReaderSettings.IgnoreWhitespace = true; ReaderSettings.IgnoreComments = true; ReaderSettings.CheckCharacters = false; Reader = XmlReader.Create(programFile, ReaderSettings); CentronTables ProgramTables = new CentronTables(); ProgramTables.LoadEDLFile(Reader); // Get the energy configuration for (int iIndex = 0; iIndex < NumberOfSupportedEnergies; iIndex++) { object objValue = null; int[] Indicies = new int[] { iIndex }; if (ProgramTables.IsCached((long)CentronTblEnum.MFGTBL0_ENERGY_LID, Indicies)) { ProgramTables.GetValue(CentronTblEnum.MFGTBL0_ENERGY_LID, Indicies, out objValue); // We need to add the Secondary Energy Base value to the byte returned to get the // actual LID value LID EnergyLid = CreateLID(SEC_ENERGY_LID_BASE + (byte)objValue); switch (EnergyLid.lidQuantity) { case DefinedLIDs.WhichOneEnergyDemand.WH_DELIVERED: { if (RequiredEnergies.Contains(BaseEnergies.PolyWhDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyWhDel); } break; } case DefinedLIDs.WhichOneEnergyDemand.WH_RECEIVED: { if (RequiredEnergies.Contains(BaseEnergies.PolyWhRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyWhRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.WH_UNI: case DefinedLIDs.WhichOneEnergyDemand.WH_NET: { if (RequiredEnergies.Contains(BaseEnergies.PolyWhDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyWhDel); } if (RequiredEnergies.Contains(BaseEnergies.PolyWhRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyWhRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.VAH_DEL_ARITH: { if (RequiredEnergies.Contains(BaseEnergies.PolyVAhArithDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyVAhArithDel); } break; } case DefinedLIDs.WhichOneEnergyDemand.VAH_REC_ARITH: { if (RequiredEnergies.Contains(BaseEnergies.PolyVAhArithRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyVAhArithRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.VAH_DEL_VECT: { if (RequiredEnergies.Contains(BaseEnergies.PolyVAhVectDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyVAhVectDel); } break; } case DefinedLIDs.WhichOneEnergyDemand.VAH_REC_VECT: { if (RequiredEnergies.Contains(BaseEnergies.PolyVAhVectRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyVAhVectRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.VAH_LAG: { if (RequiredEnergies.Contains(BaseEnergies.PolyVAhLag) == false) { RequiredEnergies.Add(BaseEnergies.PolyVAhLag); } break; } case DefinedLIDs.WhichOneEnergyDemand.VARH_DEL: { if (RequiredEnergies.Contains(BaseEnergies.PolyVarhDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhDel); } break; } case DefinedLIDs.WhichOneEnergyDemand.VARH_REC: { if (RequiredEnergies.Contains(BaseEnergies.PolyVarhRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.VARH_NET: { if (RequiredEnergies.Contains(BaseEnergies.PolyVarhDel) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhDel); } if (RequiredEnergies.Contains(BaseEnergies.PolyVarhRec) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhRec); } break; } case DefinedLIDs.WhichOneEnergyDemand.VARH_Q1: { if (RequiredEnergies.Contains(BaseEnergies.PolyVarhQ1) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhQ1); } break; } case DefinedLIDs.WhichOneEnergyDemand.VARH_Q4: { if (RequiredEnergies.Contains(BaseEnergies.PolyVarhQ4) == false) { RequiredEnergies.Add(BaseEnergies.PolyVarhQ4); } break; } } } } ProgramTables = null; Reader.Close(); return(RequiredEnergies); }
/// <summary> /// Checks to see if the item matches and then creates a ProgramValidationItem if it does not. /// </summary> /// <param name="item">The item to validate</param> /// <param name="meterTables">The table structure for the meter.</param> /// <param name="programTables">The table structure for the program.</param> /// <returns>Returns the ProgramValidationItem for the value if the items do not match, and null if the values match.</returns> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 05/23/07 RCG 8.10.05 Created // 03/26/12 AF 2.53.52 196102 Added the missing LED pulse weights // 04/19/12 jrf 2.53.56 195674 Modified to only check legacy voltage monitoring items when config is pre-Lithium. // 12/18/13 jrf 3.50.16 TQ9560 Refactored retreival of a CentronTables value into its own method. // protected override ProgramValidationItem ValidateItem(EDLValidationItem item, CentronTables meterTables, CentronTables programTables) { bool bItemsMatch = false; bool bCheckedInBaseClass = false; string strDisplayMeterValue = ""; string strDisplayProgramValue = ""; object objMeterValue; object objProgramValue; ProgramValidationItem InvalidItem = null; // Get the values objMeterValue = GetTableValue(item, meterTables); objProgramValue = GetTableValue(item, programTables); switch (item.Item) { case (long)CentronTblEnum.MFGTBL102_VH_LOW_THRESHOLD: case (long)CentronTblEnum.MFGTBL102_VH_HIGH_THRESHOLD: case (long)CentronTblEnum.MFGTBL102_RMS_VOLT_LOW_THRESHOLD: case (long)CentronTblEnum.MFGTBL102_RMS_VOLT_HIGH_THRESHOLD: { if (objMeterValue != null) { strDisplayMeterValue = objMeterValue.ToString() + "%"; } if (objProgramValue != null) { strDisplayProgramValue = objProgramValue.ToString() + "%"; } // Compare the values if (strDisplayMeterValue == strDisplayProgramValue) { bItemsMatch = true; } else if (true == IsConfigVersionEqualOrGreaterThan(CE_VERSION_LITHIUM_3_9, programTables)) { //Ignoring comparison if values do not match and program's CE version is Lithium or greater bItemsMatch = true; } break; } case (long)CentronTblEnum.MFGTBL0_BLINK_MISSING_PHASES: { bool bMeterValue; bool bProgramValue; if (objMeterValue != null) { bMeterValue = (bool)objMeterValue; if (bMeterValue) { strDisplayMeterValue = "Blink Phase Indicator"; } else { strDisplayMeterValue = "Turn Off Phase Indicator"; } } if (objProgramValue != null) { bProgramValue = (bool)objProgramValue; if (bProgramValue) { strDisplayProgramValue = "Blink Phase Indicator"; } else { strDisplayProgramValue = "Turn Off Phase Indicator"; } } if (strDisplayProgramValue == strDisplayMeterValue) { bItemsMatch = true; } break; } case (long)CentronTblEnum.MFGTBL121_PULSE_OUTPUT1_QUANTITY_NORMAL: case (long)CentronTblEnum.MFGTBL121_PULSE_OUTPUT1_QUANTITY_TEST: { LEDQuantity MeterQuantity = null; LEDQuantity ProgramQuantity = null; if (objMeterValue != null) { MeterQuantity = new LEDQuantity((uint)objMeterValue); strDisplayMeterValue = MeterQuantity.Description; } if (objProgramValue != null) { ProgramQuantity = new LEDQuantity((uint)objProgramValue); strDisplayProgramValue = ProgramQuantity.Description; } if (strDisplayMeterValue == strDisplayProgramValue) { bItemsMatch = true; } break; } case (long)CentronTblEnum.MFGTBL121_FORM_1S_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_2S_C200_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_2S_C320_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_3S_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_4S_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_9S_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_12S_C200_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_12S_C320_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_16S_C200_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_16S_C320_PULSE_WEIGHT: case (long)CentronTblEnum.MFGTBL121_FORM_45S_PULSE_WEIGHT: { float fMeterValue = 0.0f; float fProgramValue = 0.0f; if (objMeterValue != null) { fMeterValue = (ushort)objMeterValue * 0.025f; strDisplayMeterValue = fMeterValue.ToString("F3", CultureInfo.CurrentCulture); } if (objProgramValue != null) { fProgramValue = (ushort)objProgramValue * 0.025f; strDisplayProgramValue = fProgramValue.ToString("F3", CultureInfo.CurrentCulture); } if (fMeterValue == fProgramValue) { bItemsMatch = true; } break; } default: { InvalidItem = base.ValidateItem(item, meterTables, programTables); bCheckedInBaseClass = true; break; } } if (bItemsMatch == false && bCheckedInBaseClass == false) { // There is a mismatch so add the item. InvalidItem = new ProgramValidationItem(item.Category, item.Name, strDisplayProgramValue, strDisplayMeterValue); } return(InvalidItem); }