/// <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 // -------- --- ------- ------ --------------------------------------- // 07/06/10 AF 2.42.03 Created // protected PSEMResponse ReadTable(ushort usTableID, ref GatewayTables MeterTables) { MemoryStream PSEMDataStream; PSEMResponse PSEMResult = PSEMResponse.Ok; byte[] byaData; int iReadAttempt = 0; bool bRetry = true; while (bRetry) { PSEMResult = m_PSEM.FullRead(usTableID, out byaData); if (PSEMResult == PSEMResponse.Ok) { PSEMDataStream = new MemoryStream(byaData); MeterTables.SavePSEMStream(usTableID, PSEMDataStream); } iReadAttempt++; if (iReadAttempt < 3 && (PSEMResult == PSEMResponse.Bsy || PSEMResult == PSEMResponse.Dnr)) { bRetry = true; System.Threading.Thread.Sleep(1000); } else { bRetry = false; } } return(PSEMResult); }
/// <summary> /// Handles and special cases. /// </summary> /// <param name="item">The item to handle</param> /// <param name="meterTables">The table structure for the meter.</param> /// <param name="programTables">The table structure for the program.</param> /// <returns>The list of invalid items for the special case.</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 07/08/10 AF 2.42.03 Created // protected List <ProgramValidationItem> HandleSpecialCases(long item, GatewayTables meterTables, GatewayTables programTables) { List <ProgramValidationItem> InvalidItems = new List <ProgramValidationItem>(); switch (item) { case (long)StdTableEnum.STDTBL123_EXCEPTION_REPORT: { InvalidItems = GetInvalidExceptionItems(meterTables, programTables); break; } } return(InvalidItems); }
/// <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 // -------- --- ------- ------ --------------------------------------- // 07/06/10 AF 2.42.02 Created // public override CreateEDLResult CreateEDLFromMeter(string FileName, EDLSections IncludedSections) { GatewayTables MeterTables = new GatewayTables(); 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); } OnHideProgress(new EventArgs()); return(Result); }
/// <summary> /// Gets a list of invalid exception items. /// </summary> /// <param name="meterTables">The table structure for the meter.</param> /// <param name="programTables">The table structure for the program.</param> /// <returns>The list of invalid items.</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 07/08/10 AF 2.42.03 Created // 03/06/12 AF 2.53.48 193820 We can no longer assume that the meter and program items will // be in the same order. We have to search both lists for mismatches // protected virtual List <ProgramValidationItem> GetInvalidExceptionItems(GatewayTables meterTables, GatewayTables programTables) { List <ProgramValidationItem> InvalidItems = new List <ProgramValidationItem>(); ProgramValidationItem ValidationItem = null; object objMeterValue; object objProgramValue; ushort usMeterHosts; ushort usProgramHosts; ushort usMeterEvents; ushort usProgramEvents; ushort usMaxHosts; ushort usMaxEvents; // We shouldn't validate this if Table 123 is not cached in the program. if (programTables.IsAllCached(123)) { // Get the number of exception hosts meterTables.GetValue(StdTableEnum.STDTBL121_NBR_EXCEPTION_HOSTS, null, out objMeterValue); programTables.GetValue(StdTableEnum.STDTBL121_NBR_EXCEPTION_HOSTS, null, out objProgramValue); usMeterHosts = (ushort)objMeterValue; usProgramHosts = (ushort)objProgramValue; // Get the number of exception events meterTables.GetValue(StdTableEnum.STDTBL121_NBR_EXCEPTION_EVENTS, null, out objMeterValue); programTables.GetValue(StdTableEnum.STDTBL121_NBR_EXCEPTION_EVENTS, null, out objProgramValue); usMeterEvents = (ushort)objMeterValue; usProgramEvents = (ushort)objProgramValue; // Determine the maximum values. if (usMeterHosts >= usProgramHosts) { usMaxHosts = usMeterHosts; } else { usMaxHosts = usProgramHosts; } if (usMeterEvents >= usProgramEvents) { usMaxEvents = usMeterEvents; } else { usMaxEvents = usProgramEvents; } // Verify each of the hosts for (int iHost = 0; iHost < usMaxHosts; iHost++) { bool meterValidHost = iHost < usMeterHosts; bool programValidHost = iHost < usProgramHosts; List <ushort> meterEventsList = new List <ushort>(); List <ushort> programEventsList = new List <ushort>(); List <ushort> invalidMeterItemsList = new List <ushort>(); List <ushort> invalidProgramItemsList = new List <ushort>(); // the event number is just an index used for labeling the invalid item int iEventNumber = 1; int[] iIndexer = { iHost }; string strCategory = "Exception Host " + (iHost + 1).ToString(CultureInfo.CurrentCulture); ValidationItem = ValidateItem(new EDLValidationItem((long)StdTableEnum.STDTBL123_APTITLE_NOTIFY, iIndexer, "Exception Host Aptitle", strCategory), meterTables, programTables); if (ValidationItem != null) { InvalidItems.Add(ValidationItem); } ValidationItem = ValidateItem(new EDLValidationItem((long)StdTableEnum.STDTBL123_MAX_NUMBER_OF_RETRIES, iIndexer, "Max Number of Retries", strCategory), meterTables, programTables); if (ValidationItem != null) { InvalidItems.Add(ValidationItem); } ValidationItem = ValidateItem(new EDLValidationItem((long)StdTableEnum.STDTBL123_RETRY_DELAY, iIndexer, "Retry Delay", strCategory), meterTables, programTables); if (ValidationItem != null) { InvalidItems.Add(ValidationItem); } ValidationItem = ValidateItem(new EDLValidationItem((long)StdTableEnum.STDTBL123_EXCLUSION_PERIOD, iIndexer, "Exclusion Period", strCategory), meterTables, programTables); if (ValidationItem != null) { InvalidItems.Add(ValidationItem); } if (meterValidHost == true) { for (int iEvent = 0; iEvent < usMeterEvents; iEvent++) { meterTables.GetValue(StdTableEnum.STDTBL123_EVENT_REPORTED, new int[] { iHost, iEvent }, out objMeterValue); meterEventsList.Add((ushort)objMeterValue); } } if (programValidHost == true) { for (int iEvent = 0; iEvent < usProgramEvents; iEvent++) { programTables.GetValue(StdTableEnum.STDTBL123_EVENT_REPORTED, new int[] { iHost, iEvent }, out objProgramValue); programEventsList.Add((ushort)objProgramValue); } } foreach (ushort item in meterEventsList) { if (!programEventsList.Contains(item)) { invalidMeterItemsList.Add(item); } } foreach (ushort item in invalidMeterItemsList) { string strMeterException = ""; if (EventDescriptions.TryGetValue((int)item, out strMeterException) == false) { // The TryGetValue failed so say it is an unknown event. strMeterException = "Unknown Event " + item.ToString(CultureInfo.InvariantCulture); } // We don't know which program item this belongs with so just make the program item blank InvalidItems.Add(new ProgramValidationItem(strCategory, "Event " + iEventNumber.ToString(CultureInfo.CurrentCulture), "", strMeterException)); iEventNumber++; } foreach (ushort item in programEventsList) { if (!meterEventsList.Contains(item)) { invalidProgramItemsList.Add(item); } } foreach (ushort item in invalidProgramItemsList) { string strProgramException = ""; if (EventDescriptions.TryGetValue((int)item, out strProgramException) == false) { // The TryGetValue failed so say it is an unknown event. strProgramException = "Unknown Event " + item.ToString(CultureInfo.InvariantCulture); } // We don't know which meter item this belongs with so just make the meter item blank InvalidItems.Add(new ProgramValidationItem(strCategory, "Event " + iEventNumber.ToString(CultureInfo.CurrentCulture), strProgramException, "")); iEventNumber++; } } } return(InvalidItems); }
/// <summary> /// Returns a list of items that are not consistent between the configuration /// of the program and the device. /// </summary> /// <param name="strProgramName">The name of the program to validate against.</param> /// <returns> /// A list of items that failed the validation. Returns an empty list if /// all items match. /// </returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 07/08/10 AF 2.42.03 Created // public override List <ProgramValidationItem> ValidateProgram(string strProgramName) { PSEMResponse Response = PSEMResponse.Ok; List <ProgramValidationItem> InvalidItemsList = new List <ProgramValidationItem>(); List <EDLValidationItem> ItemsToValidate = GetValidationList(); List <ushort> ValidationTablesToRead = GetValidationTablesToRead(); FileStream EDLFileStream = new FileStream(strProgramName, FileMode.Open, FileAccess.Read, FileShare.Read); XmlTextReader EDLReader = new XmlTextReader(EDLFileStream); GatewayTables ProgramTables = new GatewayTables(); GatewayTables MeterTables = new GatewayTables(); OnShowProgress(new ShowProgressEventArgs(1, ValidationTablesToRead.Count)); // Read the data from the meter. // NOTE: ReadTable is defined in M2_Gateway_ICreateEDL so this will not compile if // that file is not included. We may want to move this method eventually, but // we are keeping Interfaces separate in case we wish to support OpenWay in HH-Pro foreach (ushort TableID in ValidationTablesToRead) { OnStepProgress(new ProgressEventArgs()); if (Response == PSEMResponse.Ok) { if (MeterTables.IsTableKnown(TableID) && Table00.IsTableUsed(TableID) && (TableID == 0 || MeterTables.GetTableLength(TableID) > 0)) { Response = ReadTable(TableID, ref MeterTables); } } } if (Response != PSEMResponse.Ok) { throw new PSEMException(PSEMException.PSEMCommands.PSEM_READ, Response, "Error reading device for validation."); } else { // Load the EDL file. ProgramTables.LoadEDLFile(EDLReader); // Compare the values foreach (EDLValidationItem Item in ItemsToValidate) { ProgramValidationItem InvalidItem; // Only compare items where the meter's FW version is greater than or equal to // the minimum required for that item and the FW version is less than // the version in which it became obsolete. Max set to high for active items. if ((VersionChecker.CompareTo(FWRevision, Item.MinFWVersion) >= 0) && (VersionChecker.CompareTo(FWRevision, Item.MaxFWVersion) < 0)) { // We need to handle the display items differently than the rest of the items since // there can be a different number of Normal and Test items. if (RequiresSpecialHandling(Item.Item) == false) { InvalidItem = ValidateItem(Item, MeterTables, ProgramTables); // Only add the item if it does not match. if (null != InvalidItem) { InvalidItemsList.Add(InvalidItem); } } else { InvalidItemsList.AddRange(HandleSpecialCases(Item.Item, MeterTables, ProgramTables)); } } } } return(InvalidItemsList); }
protected ProgramValidationItem ValidateItem(EDLValidationItem item, GatewayTables meterTables, GatewayTables programTables) { bool bItemsMatch = 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)StdTableEnum.STDTBL34_SEC_DISP_SOURCES: { if (objMeterValue != null) { if (String.Compare(objMeterValue.ToString(), "3", StringComparison.OrdinalIgnoreCase) == 0) { strDisplayMeterValue = "No Display Item"; } else { int iIndex = Convert.ToInt32(objMeterValue.ToString(), CultureInfo.InvariantCulture); strDisplayMeterValue = "Comm. Status Field " + (iIndex + 1).ToString(CultureInfo.InvariantCulture); } } if (objProgramValue != null) { if (String.Compare(objProgramValue.ToString(), "3", StringComparison.OrdinalIgnoreCase) == 0) { strDisplayProgramValue = "No Display Item"; } else { int iIndex = Convert.ToInt32(objProgramValue.ToString(), CultureInfo.InvariantCulture); strDisplayProgramValue = "Comm. Status Field " + (iIndex + 1).ToString(CultureInfo.InvariantCulture); } } if (strDisplayMeterValue.Equals(strDisplayProgramValue)) { bItemsMatch = true; } break; } case (long)StdTableEnum.STDTBL123_APTITLE_NOTIFY: { if (objMeterValue != null) { strDisplayMeterValue = ESNConverter.Decode((byte[])objMeterValue); } if (objProgramValue != null) { strDisplayProgramValue = ESNConverter.Decode((byte[])objProgramValue); } if (strDisplayMeterValue.Equals(strDisplayProgramValue)) { bItemsMatch = true; } break; } case (long)StdTableEnum.STDTBL53_TIME_ZONE_OFFSET: { TimeSpan tsOffset; short sOffset; if (objMeterValue != null) { sOffset = (short)objMeterValue; tsOffset = TimeSpan.FromMinutes((double)sOffset); strDisplayMeterValue = "GMT " + tsOffset.Hours + ":00"; } if (objProgramValue != null) { sOffset = (short)objProgramValue; tsOffset = TimeSpan.FromMinutes((double)sOffset); strDisplayProgramValue = "GMT " + tsOffset.Hours + ":00"; } // Compare the values if (strDisplayMeterValue == strDisplayProgramValue) { bItemsMatch = true; } break; } case (long)GatewayTblEnum.MFGTBL145_EXCEPTION_SECURITY_MODEL: { OpenWayMFGTable2193.SecurityFormat MeterValue = OpenWayMFGTable2193.SecurityFormat.None; OpenWayMFGTable2193.SecurityFormat ProgramValue = OpenWayMFGTable2193.SecurityFormat.None; if (objMeterValue != null) { MeterValue = (OpenWayMFGTable2193.SecurityFormat)(byte) objMeterValue; strDisplayMeterValue = OpenWayMFGTable2193.GetSecurityFormatString(MeterValue); } if (objProgramValue != null) { ProgramValue = (OpenWayMFGTable2193.SecurityFormat)(byte) objProgramValue; strDisplayProgramValue = OpenWayMFGTable2193.GetSecurityFormatString(ProgramValue); } bItemsMatch = ProgramValue == MeterValue; break; } case (long)GatewayTblEnum.MfgTbl145C1218OverZigBee: { bool bMeterValue = false; bool bProgramValue = false; strDisplayProgramValue = null; if (objMeterValue != null) { // We need to use the value of the bit bMeterValue = (bool)objMeterValue; } strDisplayMeterValue = bMeterValue.ToString(CultureInfo.CurrentCulture); if (objProgramValue != null) { bProgramValue = (bool)objProgramValue; strDisplayProgramValue = bProgramValue.ToString(CultureInfo.CurrentCulture); } bItemsMatch = strDisplayMeterValue.Equals(strDisplayProgramValue); break; } case (long)GatewayTblEnum.MFGTBL145_REQUIRE_ENHANCED_SECURITY: { strDisplayProgramValue = null; if (objMeterValue != null) { strDisplayMeterValue = ((bool)objMeterValue).ToString(CultureInfo.CurrentCulture); } if (objProgramValue != null) { strDisplayProgramValue = ((bool)objProgramValue).ToString(CultureInfo.CurrentCulture); } bItemsMatch = strDisplayMeterValue.Equals(strDisplayProgramValue); break; } case (long)GatewayTblEnum.MfgTbl58SecurityMode: { byte bySecurityMode; byte byDeviceAuthMode; byte byCBKEMode; // Get the Meter value if (objMeterValue != null && meterTables.IsCached((long)GatewayTblEnum.MfgTbl58DeviceAuthMode, null) && meterTables.IsCached((long)GatewayTblEnum.MfgTbl58CbkeMode, null)) { // We have already retrieved the Security Mode bySecurityMode = (byte)objMeterValue; // Get the other two modes meterTables.GetValue(GatewayTblEnum.MfgTbl58DeviceAuthMode, null, out objMeterValue); byDeviceAuthMode = (byte)objMeterValue; meterTables.GetValue(GatewayTblEnum.MfgTbl58CbkeMode, null, out objMeterValue); byCBKEMode = (byte)objMeterValue; // Get the HAN Profile Name strDisplayMeterValue = CHANMfgTable2106.GetHANSecurityProfile(bySecurityMode, byDeviceAuthMode, byCBKEMode); } // Get the Program value if (objProgramValue != null && programTables.IsCached((long)GatewayTblEnum.MfgTbl58DeviceAuthMode, null) && programTables.IsCached((long)GatewayTblEnum.MfgTbl58CbkeMode, null)) { // We have already retrieved the Security Mode bySecurityMode = (byte)objProgramValue; // Get the other two modes programTables.GetValue(GatewayTblEnum.MfgTbl58DeviceAuthMode, null, out objProgramValue); byDeviceAuthMode = (byte)objProgramValue; programTables.GetValue(GatewayTblEnum.MfgTbl58CbkeMode, null, out objProgramValue); byCBKEMode = (byte)objProgramValue; // Get the HAN Profile Name strDisplayProgramValue = CHANMfgTable2106.GetHANSecurityProfile(bySecurityMode, byDeviceAuthMode, byCBKEMode); } bItemsMatch = strDisplayMeterValue.Equals(strDisplayProgramValue); break; } case (long)GatewayTblEnum.MfgTbl58InterPanMode: { bool blnSkipComparison = false; // Get the Meter value if (objMeterValue != null) { // Get the Inter PAN Mode description strDisplayMeterValue = CHANMfgTable2106.GetInterPANMode((byte)objMeterValue); } // Get the Program value if (objProgramValue != null) { // Get the Inter PAN Mode description strDisplayProgramValue = CHANMfgTable2106.GetInterPANMode((byte)objProgramValue); } else if (programTables.IsCached((long)GatewayTblEnum.MFGTBL2045_CE_VERSION_NUMBER, null)) { object objValue = null; programTables.GetValue(GatewayTblEnum.MFGTBL2045_CE_VERSION_NUMBER, null, out objValue); string strValue = objValue as string; string[] astrCEVersion = strValue.Split(new char[] { ' ', '.', '-' }); float fltCEVersion = Convert.ToSingle(astrCEVersion[0] + "." + astrCEVersion[1]); if (0 <= VersionChecker.CompareTo(fltCEVersion, CE_VERSION_LITHIUM_3_9)) { //Only skipping comparison if program value is null and program's CE version is Lithium or greater blnSkipComparison = true; } } if (true == blnSkipComparison) { bItemsMatch = true; } else { bItemsMatch = strDisplayMeterValue.Equals(strDisplayProgramValue); } break; } default: { // The GatewayTables object may return null so make sure we don't // cause an exception first. if (objMeterValue != null) { // Trim spaces and null characters so that they will display and validate correctly strDisplayMeterValue = objMeterValue.ToString().Trim(new char[] { ' ', '\0' }); } if (objProgramValue != null) { // Trim spaces and null characters so that they will display and validate correctly strDisplayProgramValue = objProgramValue.ToString().Trim(new char[] { ' ', '\0' }); } // Compare the values if (strDisplayMeterValue == strDisplayProgramValue) { bItemsMatch = true; } break; } } if (bItemsMatch == false) { // There is a mismatch so add the item. InvalidItem = new ProgramValidationItem(item.Category, item.Name, strDisplayProgramValue, strDisplayMeterValue); } return(InvalidItem); }
/// <summary> /// Constructor /// </summary> /// <param name="PSEMObject">PSEM protocol object</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 06/11/10 AF 2.41.09 Created // 07/08/10 AF 2.42.03 Updated // public AMIConfigureM2Gateway(CPSEM PSEMObject) : base(PSEMObject) { m_GatewayTables = new GatewayTables(); }