Пример #1
0
        /// <summary>
        /// Determines the size of the table based on the firmware version running in the meter
        /// </summary>
        /// <param name="fltRegFWRevision">The version.revision of register f/w expressed as a floating point number</param>
        /// <param name="uiRegFWBuild">The build of the register f/w expressed as a uint</param>
        /// <returns>The size of the table</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  01/10/13 jkw 2.70.56        Created
        //  07/16/13 mah 2.80.53        Added corrections for Michigan table size
        //  04/15/14 jrf 3.50.75 489638 Sizing table appropriately for Carbon version 5.006.xxx.
        //  12/29/14 AF  4.50.26 553961 Sizing table appropriately for RAM Robustness version 5.009.xxx.
        //  12/30/14 AF  4.50.27 NA     Change robustness name for merging with the 4.0 branch
        //
        private static uint GetTableSize(float fltRegFWRevision, uint uiRegFWBuild)
        {
            m_numberTasks = 11;

            if ((VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_5_5_CARBON) == 0) ||
                (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_CARBON) == 0) ||
                (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_5_8_BRIDGE_PHASE_2) == 0) ||
                (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_BORON_5_0) == 0 && uiRegFWBuild > 33))
            {
                m_numberTasks = 14;
            }
            else if ((VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_BORON_5_2) == 0) ||
                     (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_5_9_CARBON_BRIDGE_ROBUST_RAM) == 0))
            {
                m_numberTasks = 13;
            }
            else if ((VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_LITHIUM_3_12) == 0 && uiRegFWBuild > 119))
            {
                m_numberTasks = 10;
            }


            if (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_6_0_MICHIGAN) >= 0)
            {
                m_numberTasks = 15;
                m_tableSize   = 209;
            }
            else
            {
                m_tableSize = (uint)(SIZE_OF_TASK_RECORD * m_numberTasks + 4);
            }

            return(m_tableSize);
        }
Пример #2
0
        /// <summary>
        /// Checks the display FW Version
        /// </summary>
        //  Revision History
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  09/17/09 RCG 2.30.00           Created
        //  09/23/14 jrf 4.00.63 WR 534158 Modified way test details are set.
        private void CheckDisplayFWVersion()
        {
            // Only check this value if it's HW 2.0 or later and earlier than HW 3.0
            if (VersionChecker.CompareTo(m_AmiDevice.HWRevision, CENTRON_AMI.HW_VERSION_2_0) >= 0 &&
                VersionChecker.CompareTo(m_AmiDevice.HWRevision, CENTRON_AMI.HW_VERSION_3_0) < 0)
            {
                XMLOpenWayActiveFiles ActiveFiles = new XMLOpenWayActiveFiles();
                FirmwareSet           MeterFWSet  = ActiveFiles.GetFirmwareSet(FirmwareSet.DetermineMeterType(m_AmiDevice.DeviceClass,
                                                                                                              m_AmiDevice.HWRevision, m_AmiDevice.MeterKey_TransparentDeviceSupported));

                string MeterValue    = m_AmiDevice.DisplayModVer + "." + m_AmiDevice.DisplayModBuild;
                string ExpectedValue = "";
                string Result        = "";
                string Details       = "";
                string Reason        = "";

                if (MeterFWSet != null && File.Exists(FW_PATH + MeterFWSet.DisplayFWFile))
                {
                    CENTRON_AMI_FW_File FWFile = new CENTRON_AMI_FW_File(FW_PATH + MeterFWSet.DisplayFWFile);
                    ExpectedValue = FWFile.CompleteVersion;
                }
                else
                {
                    Reason = TestResources.ReasonNoFirmwareFile;
                }

                // Get the result string. We skip if the expected value is empty string. Pass if the values are equal
                Result = GetResultString(String.IsNullOrEmpty(ExpectedValue), MeterValue.Equals(ExpectedValue));

                Details = GetFWVersionDetails(MeterValue, ExpectedValue);

                AddTestDetail(TestResources.DisplayFirmwareVersion, Result, Details, Reason);
            }
        }
Пример #3
0
        /// <summary>
        /// Gets the size of the table
        /// </summary>
        /// <param name="fltRegFWRevision">The register firmware version for the current meter.</param>
        /// <returns>The size of the table in bytes</returns>
        //  Revision History
        //  MM/DD/YY who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  10/24/12 jrf 2.70.33 238238 Created
        //
        private static uint GetTableSize(float fltRegFWRevision)
        {
            uint TableSize = INITIAL_TABLE_SIZE;

            if (VersionChecker.CompareTo(fltRegFWRevision, CENTRON_AMI.VERSION_MICHIGAN) >= 0)
            {
                TableSize = BERYLLIUM_ADJUSTED_TABLE_SIZE;
            }

            return(TableSize);
        }
Пример #4
0
        /// <summary>
        /// Determines the meter type.
        /// </summary>
        /// <param name="strDeviceClass">The device class of the meter.</param>
        /// <param name="fHWVersion">The hardware version</param>
        /// <param name="bTransDevMeterKey">The meter key bit for transparent devices</param>
        /// <returns>The meter type.</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  09/20/10 SCW  1.00.00       Created
        //
        public static MeterType DetermineMeterType(string strDeviceClass, float fHWVersion, bool bTransDevMeterKey)
        {
            MeterType SelectedMeterType = MeterType.Unknown;

            if (VersionChecker.CompareTo(fHWVersion, HW_VERSION_3_0) > 0)
            {
                if (strDeviceClass == ITRA_DEVICE_CLASS)
                {
                    SelectedMeterType = MeterType.HW30Single;
                }
            }
            return(SelectedMeterType);
        }
Пример #5
0
        /// <summary>
        /// Runs the test.
        /// </summary>
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  09/17/09 RCG 2.30.00           Created
        //  09/19/14 jrf 4.00.63 WR 534158 Using new method to set test result string
        //
        //  10/02/14 jrf 4.00.66 WR 431248 Making sure if logon is called and exception occurs then a logoff is
        //                                 attempted so other tests may continue if possible.
        public override Test RunTest()
        {
            PSEMResponse Response = PSEMResponse.Ok;

            m_TestResults      = new Test();
            m_TestResults.Name = TestName;

            m_bTestPassed = true;

            try
            {
                Response = LogonToDevice();

                if (Response == PSEMResponse.Ok)
                {
                    if (VersionChecker.CompareTo(m_AmiDevice.FWRevision, CENTRON_AMI.VERSION_2_SP5) >= 0)
                    {
                        ValidateOpticalPasswords();
                        ValidateDESKeys();
                        ValidateEnhancedSecurityKeys();
                        ValidateHANKeys();
                    }
                    else
                    {
                        m_bTestSkipped       = true;
                        m_TestResults.Reason = TestResources.ReasonSP5OrLaterRequired;
                    }
                }
                else
                {
                    m_bTestPassed        = false;
                    m_TestResults.Reason = TestResources.ReasonLogonFailed;
                }
            }
            catch (Exception e)
            {
                throw (e);
            }
            finally
            {
                if (m_AmiDevice != null)
                {
                    m_AmiDevice.Logoff();
                }
            }

            // Set the final result.
            m_TestResults.Result = GetTestResultString(m_bTestSkipped, m_bTestPassed);

            return(m_TestResults);
        }
Пример #6
0
        /// <summary>
        /// Gets the size of the
        /// </summary>
        /// <param name="version">The firmware version of the meter.</param>
        /// <returns>The size of the table in bytes</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ ---------------------------------------------
        //  12/09/11 RCG 2.53.20        Created

        private static ushort GetTableSize(float version)
        {
            ushort TableSize = 0;

            if (VersionChecker.CompareTo(version, CENTRON_AMI.VERSION_LITHIUM_3_12) < 0)
            {
                TableSize = TABLE_SIZE_PRE_LI;
            }
            else
            {
                TableSize = TABLE_SIZE_LI;
            }

            return(TableSize);
        }
Пример #7
0
        /// <summary>
        /// Parse the data from the meter.
        /// </summary>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ ---------------------------------------------
        //  04/30/09 RCG 2.20.03        Created
        //  10/24/12 jrf 2.70.33 238238 Adding reading date last updated when FW is Beryllium.
        //
        private void ParseData()
        {
            m_byForm              = m_Reader.ReadByte();
            m_byServiceType       = m_Reader.ReadByte();
            m_fInsVoltsPhaseA     = m_Reader.ReadSingle();
            m_fInsVoltsPhaseB     = m_Reader.ReadSingle();
            m_fInsVoltsPhaseC     = m_Reader.ReadSingle();
            m_fInsAmpsPhaseA      = m_Reader.ReadSingle();
            m_fInsAmpsPhaseB      = m_Reader.ReadSingle();
            m_fInsAmpsPhaseC      = m_Reader.ReadSingle();
            m_fVoltsPhaseBAngle   = m_Reader.ReadSingle();
            m_fVoltsPhaseCAngle   = m_Reader.ReadSingle();
            m_fAmpsPhaseAAngle    = m_Reader.ReadSingle();
            m_fAmpsPhaseBAngle    = m_Reader.ReadSingle();
            m_fAmpsPhaseCAngle    = m_Reader.ReadSingle();
            m_fInsW               = m_Reader.ReadSingle();
            m_fInsVar             = m_Reader.ReadSingle();
            m_fInsVA              = m_Reader.ReadSingle();
            m_fInsPF              = m_Reader.ReadSingle();
            m_byActiveDiagnostics = m_Reader.ReadByte();
            m_byDiag1Count        = m_Reader.ReadByte();
            m_byDiag2Count        = m_Reader.ReadByte();
            m_byDiag3Count        = m_Reader.ReadByte();
            m_byDiag4Count        = m_Reader.ReadByte();
            m_byDiag5TotalCount   = m_Reader.ReadByte();
            m_byDiag5ACount       = m_Reader.ReadByte();
            m_byDiag5BCount       = m_Reader.ReadByte();
            m_byDiag5CCount       = m_Reader.ReadByte();
            m_byDiag6Count        = m_Reader.ReadByte();
            m_byDiagnosticStatus  = m_Reader.ReadByte();

            if (VersionChecker.CompareTo(m_fltRegFWVersion, CENTRON_AMI.VERSION_MICHIGAN) >= 0)
            {
                //Beryllium added time data in table was last updated.
                m_dtTimeOfLastUpdate = m_Reader.ReadLTIME(PSEMBinaryReader.TM_FORMAT.UINT32_TIME);
            }
        }
Пример #8
0
        /// <summary>
        /// Reconfigures the LED Quantity on a Polyphase meter.
        /// </summary>
        /// <param name="quantity">The quantity to reconfigure.</param>
        /// <param name="pulseWeight">The pulse weight to use. Note: The pulse weight will be divided by 40 to get the actual value.</param>
        /// <returns>The result of the procedure call.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/07/11 RCG 2.50.06 N/A    Created

        public ProcedureResultCodes ReconfigurePolyLEDQuantity(LEDQuantity quantity, ushort pulseWeight)
        {
            ProcedureResultCodes Result = ProcedureResultCodes.UNRECOGNIZED_PROC;

            byte[]           ProcResponse    = null;
            MemoryStream     ParameterStream = new MemoryStream(new byte[6]);
            PSEMBinaryWriter ParameterWriter = new PSEMBinaryWriter(ParameterStream);

            ParameterWriter.Write(quantity.QuantityID);

            if (VersionChecker.CompareTo(FWRevision, VERSION_HYDROGEN_3_10) == 0)
            {
                // 3.10 builds had a bug in this procedure so we need to set this based on the Meter Class
                ParameterWriter.Write(CalculatePulseWeightValueForLEDReconfigureBug(pulseWeight));
            }
            else
            {
                ParameterWriter.Write(pulseWeight);
            }

            Result = ExecuteProcedure(Procedures.POLY_LED_RECONFIGURE, ParameterStream.ToArray(), out ProcResponse);

            return(Result);
        }
        /// <summary>
        /// Performs a manufacturer procedure 37 to tell the meter to get ready for
        /// firmware download
        /// </summary>
        /// <param name="strFilePath">path to the f/w file to download</param>
        /// <returns>ProcedureResultCodes</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------
        // 08/21/06 AF  7.35.00     N/A    Created
        // 09/05/06 AF  7.35.00            Corrected the order of the data in the
        //                                 procedure parameters
        // 10/04/06 AF  7.40.00     N/A    Moved from CENTRON_AMI.cs
        // 07/31/07 KRC 8.10.16     3058   Adding more detailed errors;
        // 01/23/12 RCG 2.53.33 CQ 191589  Adding the Device Class to the parameter list in order to support Gas Ranger Extended FW DL
        // 05/10/12 JJJ 2.60.xx            Tweaking FW Type so Register sees ChoiceConnect FW as RFLAN FW
        // 07/08/13 jrf 2.80.51 TC 15063   Adding special failure case for ICS FW same version.
        // 08/16/13 jrf 2.85.19 WR 420068  Modified special failure case for ICS FW same version.
        // 12/02/13 jrf 3.50.10            Refactored code used to modify the FWType byte to it's own method.
        // 02/07/14 jrf 3.50.32 WR 419257  Modified to use a dynamic FWDL block size based on the negotiated
        //                                 PSEM packet size.
        //
        private FWDownloadResult EnterFirmwareDownloadMode(string strFilePath)
        {
            //Construct the parameters for mfg proc 37 and execute the procedure
            FileInfo fi = new FileInfo(strFilePath);
            bool     bIsThirdPartyFWDownload = (this is M2_Gateway == false) && (VersionChecker.CompareTo(FWRevision, CENTRON_AMI.VERSION_LITHIUM_3_12) >= 0);

            byte[] bybuf        = new byte[FW_HEADER_LENGTH];
            byte[] byParameters = null;
            byte[] byImageSize  = new byte[IMAGE_SIZE_FIELD_LEN];
            byte[] byChunkSize  = new byte[CHUNK_SIZE_FIELD_LEN];
            byte[] ProcResponse;
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            FWDownloadResult     FWResult   = FWDownloadResult.UNKNOWN_DRIVER_ERROR;

            try
            {
                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                   "Initiating Firmware Download");

                // Most of the procedure parameters are in the f/w file header
                FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Read(bybuf, 0, FW_HEADER_LENGTH);
                fs.Close();

                if (bIsThirdPartyFWDownload == true)
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_THIRD_PARTY_LEN];
                }
                else
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_PARAM_LEN];
                }

                byParameters.Initialize();

                // CRC LSB first
                byParameters[0] = bybuf[1];
                byParameters[1] = bybuf[0];

                // Retrieve the parameters out of the header
                Array.Copy(bybuf, 5, byParameters, 2, 9);

                //Some devices may require this byte to be adjusted.
                byParameters[6] = SelectFWTypeByte(byParameters[6]);

                // image size
                byImageSize = BitConverter.GetBytes((int)fi.Length);
                Array.Copy(byImageSize, 0, byParameters, 11, IMAGE_SIZE_FIELD_LEN);

                byChunkSize = BitConverter.GetBytes(FWDLBlockSize);
                Array.Copy(byChunkSize, 0, byParameters, 15, CHUNK_SIZE_FIELD_LEN);

                if (bIsThirdPartyFWDownload == true)
                {
                    // The Device Class is a required parameter for 3rd Party Firmware Downloads
                    // The meter needs this in the reverse order that it is stored in the firmware file
                    byParameters[17] = bybuf[17];
                    byParameters[18] = bybuf[16];
                    byParameters[19] = bybuf[15];
                    byParameters[20] = bybuf[14];
                }

                ProcResult = ExecuteProcedure(Procedures.INITIATE_FW_LOADER_SETUP,
                                              byParameters,
                                              out ProcResponse);


                if (ProcedureResultCodes.INVALID_PARAM == ProcResult)
                {
                    // The Firmware load did not work.  At some point during development they added
                    //  more detail in the Response, so we can read the byte and see what the error is
                    switch (ProcResponse[0])
                    {
                    case 1:
                        FWResult = FWDownloadResult.FW_IMAGE_TOO_BIG;
                        break;

                    case 2:
                        FWResult = FWDownloadResult.HW_REVISION_OUTSIDE_RANGE;
                        break;

                    case 3:
                        FWResult = FWDownloadResult.HW_VERSION_OUTSIDE_RANGE;
                        break;

                    case 10:
                        FWResult = FWDownloadResult.FW_TYPE_IS_INVALID;
                        break;

                    case 11:
                        FWResult = FWDownloadResult.ZIGBEE_FW_TYPE_INVALID;
                        break;

                    default:
                        FWResult = FWDownloadResult.INVALID_CONFIG;
                        break;
                    }
                }
                else
                {
                    FWResult = TranslateProcedureResult(ProcResult);
                }
            }
            catch (PSEMException PSEMExp)
            {
                //TODO - This does not catch the error for same version when the device is an ITRU
                if (PSEMResponse.Err == PSEMExp.PSEMResponse &&
                    (byte)FirmwareType.ICSFW == byParameters[6] &&
                    CommModuleVersion == byParameters[2] &&
                    CommModuleRevision == byParameters[3] &&
                    CommModuleBuild == byParameters[4])
                {
                    //This is how an attempt to download the same OW ICS comm module firmware
                    //version will fail.
                    FWResult = FWDownloadResult.ICS_SAME_VERSION_REJECTION;
                }
                else
                {
                    // Log it and pass it up
                    m_Logger.WriteException(this, PSEMExp);
                    throw (PSEMExp);
                }
            }
            catch (Exception e)
            {
                // Log it and pass it up
                m_Logger.WriteException(this, e);
                throw (e);
            }


            return(FWResult);
        }
Пример #10
0
        /// <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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        /// <summary>
        /// Performs a manufacturer procedure 37 to tell the meter to get ready for
        /// firmware download
        /// </summary>
        /// <param name="strFilePath">path to the f/w file to download</param>
        /// <returns>ProcedureResultCodes</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 08/21/06 AF  7.35.00 N/A     Created
        // 09/05/06 AF  7.35.00         Corrected the order of the data in the
        //                             procedure parameters
        // 10/04/06 AF  7.40.00 N/A     Moved from CENTRON_AMI.cs
        // 07/31/07 KRC 8.10.16 3058    Adding more detailed errors;
        // 01/23/12 RCG 2.53.33 191589 Adding the Device Class to the parameter list in order to support Gas Ranger Extended FW DL
        // 05/10/12 JJJ 2.60.xx        Tweaking FW Type so Register sees ChoiceConnect FW as RFLAN FW

        private FWDownloadResult EnterFirmwareDownloadMode(string strFilePath)
        {
            //Construct the parameters for mfg proc 37 and execute the procedure
            FileInfo fi = new FileInfo(strFilePath);
            bool     bIsThirdPartyFWDownload = this is M2_Gateway == false && VersionChecker.CompareTo(FWRevision, CENTRON_AMI.VERSION_LITHIUM_3_12) >= 0;

            byte[] bybuf        = new byte[FW_HEADER_LENGTH];
            byte[] byParameters = null;
            byte[] byImageSize  = new byte[IMAGE_SIZE_FIELD_LEN];
            byte[] byChunkSize  = new byte[CHUNK_SIZE_FIELD_LEN];
            byte[] ProcResponse;
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            FWDownloadResult     FWResult   = FWDownloadResult.UNKNOWN_DRIVER_ERROR;

            try
            {
                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                   "Initiating Firmware Download");

                // Most of the procedure parameters are in the f/w file header
                FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Read(bybuf, 0, FW_HEADER_LENGTH);
                fs.Close();

                if (bIsThirdPartyFWDownload == true)
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_THIRD_PARTY_LEN];
                }
                else
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_PARAM_LEN];
                }

                byParameters.Initialize();

                // CRC LSB first
                byParameters[0] = bybuf[1];
                byParameters[1] = bybuf[0];

                // Retrieve the parameters out of the header
                Array.Copy(bybuf, 5, byParameters, 2, 9);

                // if MSM ChoiceConnect meter and ChoiceConnect FWDL request, spoof RFLAN FWDL
                CENTRON_AMI AmiDevice = this as CENTRON_AMI;
                if (AmiDevice != null &&
                    byParameters[6] == (byte)FirmwareType.ChoiceConnectFW &&
                    AmiDevice.IsChoiceConnectMsmMeter)
                {
                    byParameters[6] = (byte)FirmwareType.RFLANFW;
                }

                // image size
                byImageSize = BitConverter.GetBytes((int)fi.Length);
                Array.Copy(byImageSize, 0, byParameters, 11, IMAGE_SIZE_FIELD_LEN);

                // chunk size -- 64 or 128 bytes; hard coded here to 128
                byChunkSize = BitConverter.GetBytes(BLOCK_SIZE);
                Array.Copy(byChunkSize, 0, byParameters, 15, CHUNK_SIZE_FIELD_LEN);

                if (bIsThirdPartyFWDownload == true)
                {
                    // The Device Class is a required parameter for 3rd Party Firmware Downloads
                    // The meter needs this in the reverse order that it is stored in the firmware file
                    byParameters[17] = bybuf[17];
                    byParameters[18] = bybuf[16];
                    byParameters[19] = bybuf[15];
                    byParameters[20] = bybuf[14];
                }

                ProcResult = ExecuteProcedure(Procedures.INITIATE_FW_LOADER_SETUP,
                                              byParameters,
                                              out ProcResponse);


                if (ProcedureResultCodes.INVALID_PARAM == ProcResult)
                {
                    // The Firmware load did not work.  At some point during development they added
                    //  more detail in the Response, so we can read the byte and see what the error is
                    switch (ProcResponse[0])
                    {
                    case 1:
                        FWResult = FWDownloadResult.FW_IMAGE_TOO_BIG;
                        break;

                    case 2:
                        FWResult = FWDownloadResult.HW_REVISION_OUTSIDE_RANGE;
                        break;

                    case 3:
                        FWResult = FWDownloadResult.HW_VERSION_OUTSIDE_RANGE;
                        break;

                    case 10:
                        FWResult = FWDownloadResult.FW_TYPE_IS_INVALID;
                        break;

                    case 11:
                        FWResult = FWDownloadResult.ZIGBEE_FW_TYPE_INVALID;
                        break;

                    default:
                        FWResult = FWDownloadResult.INVALID_CONFIG;
                        break;
                    }
                }
                else
                {
                    FWResult = TranslateProcedureResult(ProcResult);
                }
            }
            catch (Exception e)
            {
                // Log it and pass it up
                m_Logger.WriteException(this, e);
                throw (e);
            }


            return(FWResult);
        }
Пример #13
0
        /// <summary>
        /// This method updates the IO configuration in the meter.
        /// </summary>
        /// <param name="IOConfig">KYZ configuration data object.</param>
        /// <returns>The result of the configuration.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 04/22/09 jrf 2.20.02 n/a	   Created
        // 04/19/10 AF  2.40.39        Made virtual for M2 Gateway override
        // 07/08/10 jrf 2.42.02 157552 Setting the CPC reset bit on close config to fix
        //                             LED lock issue.
        //
        public virtual ItronDeviceResult ConfigureIO(KYZData IOConfig)
        {
            byte[] ProcParam = new byte[0];
            byte[] ProcResponse;
            ProcedureResultCodes ProcResult =
                ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse Result = PSEMResponse.Err;

            ItronDeviceResult    ConfigResult = ItronDeviceResult.ERROR;
            CTable2048_OpenWay   OW2048       = Table2048 as CTable2048_OpenWay;
            CENTRON_AMI_IOConfig IOTable      = OW2048.IOConfig as CENTRON_AMI_IOConfig;

            // Open the Config
            ProcResult = ExecuteProcedure(Procedures.OPEN_CONFIG_FILE, ProcParam, out ProcResponse);

            // Execute Write of IO Table in 2048
            if (ProcedureResultCodes.COMPLETED == ProcResult)
            {
                IOTable.IOData = IOConfig;
                Result         = IOTable.Write();
            }
            else if (ProcedureResultCodes.NO_AUTHORIZATION == ProcResult)
            {
                Result = PSEMResponse.Isc;
            }
            else
            {
                m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                   "Open config procedure failed with result = " +
                                   ProcResult);
                Result = PSEMResponse.Err;
            }

            if (Result == PSEMResponse.Ok)
            {
                // Close the Config
                // Data reset bits - we don't want to reset any data, so
                // just initialize them to 0
                ProcParam = new byte[4];
                ProcParam.Initialize();

                // Okay we do want to reset data if we are a HW2.0 Poly.  Need to do this to
                // prevent the worm on the display from freezing.
                if (0 == VersionChecker.CompareTo(HWRevisionFiltered, HW_VERSION_2_5) ||
                    0 == VersionChecker.CompareTo(HWRevisionFiltered, HW_VERSION_2_6))
                {
                    //We need to reset CPC
                    MemoryStream ParamStream = new MemoryStream(ProcParam);
                    BinaryWriter BinWriter   = new BinaryWriter(ParamStream);

                    BinWriter.Write((uint)CloseConfigOptions.CPC);
                }

                ProcResult = ExecuteProcedure(Procedures.CLOSE_CONFIG_FILE, ProcParam, out ProcResponse);

                if (ProcedureResultCodes.COMPLETED != ProcResult)
                {
                    ConfigResult = ItronDeviceResult.ERROR;
                }
                else
                {
                    ConfigResult = ItronDeviceResult.SUCCESS;
                }
            }
            else
            {
                if (Result == PSEMResponse.Isc)
                {
                    ConfigResult = ItronDeviceResult.SECURITY_ERROR;
                }
                else
                {
                    ConfigResult = ItronDeviceResult.ERROR;
                }
            }

            return(ConfigResult);
        }
Пример #14
0
        /// <summary>
        /// Runs the test.
        /// </summary>
        //  Revision History
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  09/17/09 RCG 2.30.00        Created
        //  12/09/09 jrf 2.30.26        Removing upper nibble of hardware version before
        //                              displaying for PrismLite devices.
        //  02/19/13 AF  2.70.69 322427 Show InterPAN Mode only for pre-Lithium meters
        //  09/19/14 jrf 4.00.63 WR 534158 Using new method to set test result string and
        //                                 modified way test details are set.
        //  10/02/14 jrf 4.00.66 WR 431248 Making sure if logon is called and exception occurs then a logoff is
        //                                 attempted so other tests may continue if possible.
        public override Test RunTest()
        {
            PSEMResponse Response = PSEMResponse.Ok;
            string       strValue = "";

            m_TestResults      = new Test();
            m_TestResults.Name = TestName;


            m_bTestPassed = true;

            try
            {
                Response = LogonToDevice();

                if (Response == PSEMResponse.Ok)
                {
                    if (IsAborted == false)
                    {
                        AddTestDetail(TestResources.MeterID, TestResources.OK, m_AmiDevice.UnitID);
                        AddTestDetail(TestResources.SerialNumber, TestResources.OK, m_AmiDevice.SerialNumber);
                        AddTestDetail(TestResources.MFGSerialNumber, TestResources.OK, m_AmiDevice.MFGSerialNumber);


                        if (m_AmiDevice.CommModule != null)
                        {
                            strValue = m_AmiDevice.CommModule.ElectronicSerialNumber;
                        }
                        else
                        {
                            strValue = TestResources.NotAvailable;
                        }

                        AddTestDetail(TestResources.ElectronicSerialNumber, TestResources.OK, strValue);
                    }

                    if (IsAborted == false)
                    {
                        CheckRegisterFWVersion();
                        CheckRFLANFWVersion();
                        CheckZigBeeFWVersion();
                        CheckDisplayFWVersion();

                        float fltHWRev = m_AmiDevice.HWRevision;

                        // If this is a PrismLite device we need to ignore the upper nibble of the hardware version
                        if (((byte)(fltHWRev) & PRISM_LITE_HW_MASK) == PRISM_LITE_HW_MASK)
                        {
                            fltHWRev -= (float)PRISM_LITE_HW_MASK;
                        }

                        AddTestDetail(TestResources.HardwareVersion, TestResources.OK, fltHWRev.ToString("F3", CultureInfo.CurrentCulture));
                    }

                    if (IsAborted == false)
                    {
                        AddTestDetail(TestResources.TimeZone, TestResources.OK, m_AmiDevice.TimeZoneOffset.Hours + ":00");
                        AddTestDetail(TestResources.DeviceTime, TestResources.OK, m_AmiDevice.DeviceTime.ToString("G", CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.TOUEnabled, TestResources.OK, m_AmiDevice.TOUEnabled.ToString(CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.DSTEnabled, TestResources.OK, m_AmiDevice.DSTEnabled.ToString(CultureInfo.CurrentCulture));


                        for (int iIndex = 0; iIndex < m_AmiDevice.DST.Count; iIndex++)
                        {
                            AddTestDetail(TestResources.DSTFromDate + (iIndex + 1).ToString(CultureInfo.CurrentCulture),
                                          TestResources.OK, m_AmiDevice.DST[iIndex].FromDate.ToString("G", CultureInfo.CurrentCulture));
                            AddTestDetail(TestResources.DSTToDate + (iIndex + 1).ToString(CultureInfo.CurrentCulture),
                                          TestResources.OK, m_AmiDevice.DST[iIndex].ToDate.ToString("G", CultureInfo.CurrentCulture));
                        }
                    }

                    if (IsAborted == false)
                    {
                        AddTestDetail(TestResources.MinutesOnBattery, TestResources.OK, m_AmiDevice.NumberOfMinutesOnBattery.ToString(CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.DateLastProgrammed, TestResources.OK, m_AmiDevice.DateProgrammed.ToString("G", CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.DateOfLastDemandReset, TestResources.OK, m_AmiDevice.DateLastDemandReset.ToString("G", CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.DateOfLastOutage, TestResources.OK, m_AmiDevice.DateLastOutage.ToString("G", CultureInfo.CurrentCulture));
                        AddTestDetail(TestResources.DateOfLastTest, TestResources.OK, m_AmiDevice.DateLastTestMode.ToString("G", CultureInfo.CurrentCulture));


                        if ((m_AmiDevice is OpenWayBasicPoly == true) || (m_AmiDevice is OpenWayAdvPoly == true))
                        {
                            AddTestDetail(TestResources.NormalKh, TestResources.OK, (m_AmiDevice.NormalKh / 40.0).ToString("F3", CultureInfo.CurrentCulture));
                        }
                        else
                        {
                            AddTestDetail(TestResources.NormalKh, TestResources.OK, (m_AmiDevice.NormalKh / 10.0).ToString("F3", CultureInfo.CurrentCulture));
                        }
                    }

                    if (IsAborted == false)
                    {
                        CheckLPRunning();

                        CheckDeviceErrors();

                        GetRFLANMac();

                        if (m_AmiDevice.CommModule != null)
                        {
                            RFLANCommModule RFLANModule = m_AmiDevice.CommModule as RFLANCommModule;

                            if (RFLANModule != null)
                            {
                                strValue = RFLANModule.CommModuleLevel;
                            }
                            else
                            {
                                strValue = TestResources.NotAvailable;
                            }
                        }
                        else
                        {
                            strValue = TestResources.NotAvailable;
                        }

                        AddTestDetail(TestResources.RFLANSynchLevel, TestResources.OK, strValue);
                    }

                    if (IsAborted == false)
                    {
                        AddTestDetail(TestResources.HANMACAddress, TestResources.OK, m_AmiDevice.HANServerMACAddr);
                        AddTestDetail(TestResources.HANSecurityProfile, TestResources.OK, m_AmiDevice.HANSecurityProfile);

                        if (VersionChecker.CompareTo(m_AmiDevice.FWRevision, CENTRON_AMI.VERSION_3_12_LITHIUM) < 0)
                        {
                            AddTestDetail(TestResources.InterPANMode, TestResources.OK, m_AmiDevice.InterPANMode);
                        }

                        AddTestDetail(TestResources.ZigBeeEnabled, TestResources.OK, ConvertYesOrNo(m_AmiDevice.IsZigBeeEnabled));
                        AddTestDetail(TestResources.ANSIC1218OverZigBeeEnabled, TestResources.OK, ConvertYesOrNo(m_AmiDevice.IsC1218OverZigBeeEnabled));
                        AddTestDetail(TestResources.ZigBeePrivateProfileEnabled, TestResources.OK, ConvertYesOrNo(m_AmiDevice.IsZigBeePrivateProfileEnabled));

                        AddTestDetail(TestResources.EnhancedBlurtsEnabled, TestResources.OK, ConvertYesOrNo(m_AmiDevice.MeterKey_EnhancedBlurtsSupported));
                        AddTestDetail(TestResources.AdvancedPolyMeter, TestResources.OK, ConvertYesOrNo(m_AmiDevice.MeterKey_AdvancedPolySupported));
                    }
                }
                else
                {
                    m_TestResults.Reason = TestResources.ReasonLogonFailed;
                    m_bTestPassed        = false;
                }
            }
            catch (Exception e)
            {
                throw (e);
            }
            finally
            {
                if (m_AmiDevice != null)
                {
                    m_AmiDevice.Logoff();
                }
            }

            // Set the final result.
            m_TestResults.Result = GetTestResultString(m_bTestSkipped, m_bTestPassed);

            return(m_TestResults);
        }