Example #1
0
        /// <summary>
        /// Validates the DES Keys
        /// </summary>
        //  Revision History
        //  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 Modified way test details are set.
        private void ValidateDESKeys()
        {
            string Details = "";
            string Reason  = "";
            bool   Skipped = File.Exists(m_strProgramFile) == false ||
                             EDLFile.IsEDLFile(m_strProgramFile) == false;
            ProcedureResultCodes ValidationResult = ProcedureResultCodes.COMPLETED;

            if (IsAborted == false)
            {
                foreach (CENTRON_AMI.DESKeys KeyType in Enum.GetValues(typeof(CENTRON_AMI.DESKeys)))
                {
                    if (Skipped == false)
                    {
                        ValidationResult = m_AmiDevice.ValidateDESKeys(m_strProgramFile, KeyType);
                        Details          = GetSecurityValidationDetails(ValidationResult);

                        if (ProcedureResultCodes.INVALID_PARAM == ValidationResult)
                        {
                            Details += ", " + TestResources.KeyNotConsistentWithProgram;
                        }
                    }
                    else
                    {
                        Reason  = TestResources.ReasonProgramFileNeededToValidate;
                        Details = TestResources.NoProgram;
                    }

                    AddTestDetail(KeyType.ToDescription(), GetResultString(Skipped, ProcedureResultCodes.COMPLETED == ValidationResult),
                                  Details, Reason);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Configures the meter to use the specified base energies
        /// </summary>
        /// <param name="baseEnergies">The base energy values to use.</param>
        /// <returns>The result of the procedure call</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/22/11 RCG 2.50.12 N/A    Created

        public override ProcedureResultCodes ConfigureBaseEnergies(List <BaseEnergies> baseEnergies)
        {
            ProcedureResultCodes Result = ProcedureResultCodes.UNRECOGNIZED_PROC;

            byte[] ProcResponse = null;
            byte[] ProcParam    = new byte[6];

            // Validate the energies parameter
            if (baseEnergies == null)
            {
                throw new ArgumentNullException("baseEnergies");
            }
            else if (baseEnergies.Count > ProcParam.Length)
            {
                throw new ArgumentException("Only " + ProcParam.Length.ToString(CultureInfo.InvariantCulture) + " energies may be configured", "baseEnergies");
            }

            // Add the energy values
            for (int iIndex = 0; iIndex < baseEnergies.Count; iIndex++)
            {
                ProcParam[iIndex] = (byte)baseEnergies[iIndex];
            }

            Result = ExecuteProcedure(Procedures.CONFIGURE_BASE_ENERGIES, ProcParam, out ProcResponse);

            // Give the meter a second to make sure that the base changes before we do anything else
            Thread.Sleep(1000);

            return(Result);
        }
Example #3
0
        /// <summary>
        /// Validates the enhanced security keys
        /// </summary>
        //  Revision History
        //  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 Modified way test details are set.
        private void ValidateEnhancedSecurityKeys()
        {
            CXMLOpenWaySystemSettings SystemSettings = new CXMLOpenWaySystemSettings("");
            bool   Skipped = File.Exists(SystemSettings.EnhancedSecurityFilePath) == false;
            string Details = "";
            string Reason  = "";
            ProcedureResultCodes ValidationResult = ProcedureResultCodes.COMPLETED;

            if (IsAborted == false)
            {
                foreach (CENTRON_AMI.EnhancedKeys KeyType in Enum.GetValues(typeof(CENTRON_AMI.EnhancedKeys)))
                {
                    if (Skipped == false)
                    {
                        ValidationResult = m_AmiDevice.ValidateEnhancedSecurityKey(SystemSettings.EnhancedSecurityFilePath, KeyType);
                        Details          = GetSecurityValidationDetails(ValidationResult);

                        if (ProcedureResultCodes.INVALID_PARAM == ValidationResult)
                        {
                            Details += ", " + TestResources.KeyNotConsistentWithSecurityFile;
                        }
                    }
                    else
                    {
                        Reason  = TestResources.ReasonProgramFileNeededToValidate;
                        Details = TestResources.NoProgram;
                    }

                    AddTestDetail(KeyType.ToDescription(), GetResultString(Skipped, ProcedureResultCodes.COMPLETED == ValidationResult),
                                  Details, Reason);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Queries the meter for the first 20 missing blocks for a firmware
        /// download pending table.
        /// </summary>
        /// <param name="eFWType">Firmware type (0 = Register, 1 = RFLAN,
        /// 2 = Zigbee)</param>
        /// <param name="iNumberOfBlocksReceived"></param>
        /// <param name="lstMissingBlocks"></param>
        /// <returns>Result code written to table 08 after the procedure is
        /// initiated</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 02/05/10 jrf 2.40.12  N/A     Created
        //
        public ProcedureResultCodes GetFirstTwentyMissingBlocks(FirmwareType eFWType,
                                                                out int iNumberOfBlocksReceived, out List <int> lstMissingBlocks)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcResponse;
            int    iBlockNumber = 0;

            ProcResult = GetFirstTwentyMissingBlocks(eFWType, out ProcResponse);

            lstMissingBlocks        = new List <int>();
            iNumberOfBlocksReceived = 0;

            if (ProcedureResultCodes.COMPLETED == ProcResult)
            {
                iNumberOfBlocksReceived = ProcResponse[0] | (ProcResponse[1] << 8);

                for (int iIndex = 2; iIndex < 42; iIndex += 2)
                {
                    iBlockNumber = ProcResponse[iIndex] | (ProcResponse[iIndex + 1] << 8);
                    if (0 != iBlockNumber)
                    {
                        lstMissingBlocks.Add(iBlockNumber);
                    }
                }
            }

            return(ProcResult);
        }
Example #5
0
        /// <summary>
        /// Calls standard procedure 2 - save configuration
        /// </summary>
        /// <returns>the result of the procedure call</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  03/18/13 AF  2.80.08 TR7578 Created
        //
        public ProcedureResultCodes SaveConfiguration()
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.DEVICE_SETUP_CONFLICT;

            byte[] ProcResponse;
            byte[] ProcParam = new byte[0];

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

            return(ProcResult);
        }
Example #6
0
        /// <summary>
        /// Clears a specific pending table by the table id
        /// </summary>
        /// <param name="TableID">the pending table to be cleared</param>
        /// <returns>the result of the procedure call</returns>
        //  Revision History
        //  MM/DD/YY Who Version  ID Number  Description
        //  -------- --- -------  -- ------  --------------------------------------------
        //  12/06/17 AF  4.73.00  Task 469254 Created
        //
        public ProcedureResultCodes ClearPendingTableByTableID(UInt16 TableID)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcResponse;
            byte[] ProcParam = new byte[2];
            Array.Copy(BitConverter.GetBytes((UInt16)TableID), ProcParam, 2);

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

            return(ProcResult);
        }
Example #7
0
        /// <summary>
        /// Activates the pending table with the specified Event Record
        /// </summary>
        /// <param name="pendingEvent">The Event Record for the event to activate</param>
        /// <returns>ProcedureResultCodes</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  05/07/07 RCG 8.10.07        Created

        public ProcedureResultCodes ActivatePendingTable(PendingEventRecord pendingEvent)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcResponse;

            ProcResult = ExecuteProcedure(Procedures.ACTIVATE_PENDING_TABLE,
                                          pendingEvent.EntireRecord,
                                          out ProcResponse);

            return(ProcResult);
        }
Example #8
0
        /// <summary>
        /// Clears the pending table with the specified Event Record
        /// </summary>
        /// <param name="pendingEvent">The Event Record for the event to clear</param>
        /// <returns>ProcedureResultCodes</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  05/07/07 RCG 8.10.07        Created

        public ProcedureResultCodes ClearPendingTable(PendingEventRecord pendingEvent)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcResponse;

            ProcResult = ExecuteProcedure(Procedures.CLEAR_SPECIFIC_PENDING_TABLE,
                                          pendingEvent.EntireRecord,
                                          out ProcResponse);

            return(ProcResult);
        }
Example #9
0
        /// <summary>
        /// Activates all pending tables in the meter.
        /// </summary>
        /// <returns>The result of the procedure.</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  11/05/08 RCG 2.00.03 122067 Created

        public ProcedureResultCodes ActivateAllPendingTables()
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcResponse;
            byte[] ProcParam = new byte[0];

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

            return(ProcResult);
        }
        /// <summary>
        /// This method activates the firmware download's pending table.
        /// </summary>
        /// <param name="FWType">The type of firmware to activate.</param>
        /// <returns>The result of the activate pending table procedure.</returns>
        //  Revision History
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  07/09/13 jrf 2.80.51 TC 15063  Created.
        //  08/24/16 PGH 4.70.15    701952 Added HAN OTA Firmware
        //
        public ProcedureResultCodes ActivateFW(FirmwareType FWType)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            byte byEventNumber = REGISTER_EVENT_NUMBER;

            switch (FWType)
            {
            case FirmwareType.RegisterFW:
            case FirmwareType.M2GTWY:
            case FirmwareType.DisplayFW:
            {
                byEventNumber = REGISTER_EVENT_NUMBER;
                break;
            }

            case FirmwareType.ZigbeeFW:
            {
                byEventNumber = ZIGBEE_EVENT_NUMBER;
                break;
            }

            case FirmwareType.RFLANFW:
            case FirmwareType.PLANFW:
            case FirmwareType.CiscoCommFW:
            case FirmwareType.CiscoCfgFW:
            case FirmwareType.ChoiceConnectFW:
            case FirmwareType.ICSFW:
            {
                byEventNumber = COMM_EVENT_NUMBER;
                break;
            }

            case FirmwareType.HAN_OTA_FW:
            case FirmwareType.HANDevFW:
            {
                byEventNumber = HAN_DEV_EVENT_NUMBER;
                break;
            }

            default:
            {
                throw new ArgumentException("Invalid Parameter", "FWType");
            }
            }

            // Activate the pending table
            ProcResult = ActivatePendingTable(false, false, byEventNumber,
                                              PendingEventRecord.PendingEventCode.NonTimeTrigger);

            return(ProcResult);
        }
Example #11
0
        /// <summary>
        /// Reconfigures SiteScan information
        /// </summary>
        /// <param name="serviceType">The new service type to use.</param>
        /// <param name="nominalVoltage">The new nominal voltage to use.</param>
        /// <returns>The result of the reconfigure</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 04/29/09 RCG 2.20.03 N/A    Created

        public SiteScanReconfigResult ReconfigureSiteScan(ServiceTypes serviceType, float nominalVoltage)
        {
            CloseConfigErrors      Errors         = CloseConfigErrors.None;
            ProcedureResultCodes   ProcResult     = ProcedureResultCodes.COMPLETED;
            PSEMResponse           Response       = PSEMResponse.Ok;
            SiteScanReconfigResult ReconfigResult = SiteScanReconfigResult.SUCCESS;

            // First make sure we have read the SiteScan config so we have the correct data.
            Response = SiteScanConfig.Read();

            if (Response == PSEMResponse.Ok)
            {
                // Open the config so that we can write to it.
                ProcResult = OpenConfig();

                if (ProcResult == ProcedureResultCodes.COMPLETED)
                {
                    // Set the new values.
                    SiteScanConfig.ServiceType    = serviceType;
                    SiteScanConfig.NominalVoltage = nominalVoltage;

                    // Write the new values
                    Response = SiteScanConfig.Write();

                    if (Response == PSEMResponse.Ok)
                    {
                        ProcResult = CloseConfig(CloseConfigOptions.SiteScan, out Errors);
                    }
                }
            }

            if (ProcResult == ProcedureResultCodes.NO_AUTHORIZATION)
            {
                ReconfigResult = SiteScanReconfigResult.SECURITY_ERROR;
            }
            else if (ProcResult != ProcedureResultCodes.COMPLETED)
            {
                ReconfigResult = SiteScanReconfigResult.ERROR;
            }

            if (Response == PSEMResponse.Isc)
            {
                ReconfigResult = SiteScanReconfigResult.SECURITY_ERROR;
            }
            else if (Response != PSEMResponse.Ok)
            {
                ReconfigResult = SiteScanReconfigResult.PROTOCOL_ERROR;
            }

            return(ReconfigResult);
        }
Example #12
0
        /// <summary>
        /// This method resets the C12.22 stack.
        /// </summary>
        /// <returns>The result of the procedure.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/18/10 jrf 2.40.26	       Created
        public ProcedureResultCodes ResetC1222Stack()
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcParam;
            byte[] ProcResponse;

            ProcParam    = new byte[1];
            ProcParam[0] = (byte)RFLANDebugProcedures.C1222_STACK_RESET;
            ProcResult   = m_AMIDevice.ExecuteProcedure(Procedures.RFLAN_DEBUG_PROCEDURE,
                                                        ProcParam, out ProcResponse);

            return(ProcResult);
        }
Example #13
0
        /// <summary>
        /// This method resets RFLAN MCU
        /// </summary>
        /// <returns>The result of the procedure.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 06/08/10 MMD 2.41.07	       Created
        public ProcedureResultCodes ResetRFLANMCU()
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcParam;
            byte[] ProcResponse;

            ProcParam    = new byte[1];
            ProcParam[0] = (byte)RFLANProcedure.RESET_RFLAN_MCU;
            ProcResult   = m_AMIDevice.ExecuteProcedure(Procedures.RFLAN_PROCEDURE,
                                                        ProcParam, out ProcResponse);

            return(ProcResult);
        }
Example #14
0
        /// <summary>
        /// This method forces a NET registration.
        /// </summary>
        /// <returns>The result of the procedure.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/18/10 jrf 2.40.26	       Created
        public ProcedureResultCodes ForceNetRegistration()
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcParam;
            byte[] ProcResponse;

            ProcParam    = new byte[1];
            ProcParam[0] = (byte)RFLANProcedure.FORCE_NET_REGISTER;
            ProcResult   = m_AMIDevice.ExecuteProcedure(Procedures.RFLAN_PROCEDURE,
                                                        ProcParam, out ProcResponse);

            return(ProcResult);
        }
Example #15
0
        /// <summary>
        /// Queries the meter for the first 20 missing blocks for a firmware
        /// download pending table.
        /// </summary>
        /// <param name="eFWType">Firmware type (0 = Register, 1 = RFLAN,
        /// 2 = Zigbee)</param>
        /// <param name="ProcResponse">byte array containing the response from
        /// the meter</param>
        /// <returns>Result code written to table 08 after the procedure is
        /// initiated</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 10/02/06 AF 7.40.00  N/A     Created
        // 10/04/06 AF 7.40.00  N/A     Moved from CENTRON_AMI.cs
        //
        protected ProcedureResultCodes GetFirstTwentyMissingBlocks(FirmwareType eFWType,
                                                                   out byte[] ProcResponse)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] byParameters = new byte[1];  // The procedure takes 1 parameter
            byParameters[0] = (byte)eFWType;

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

            return(ProcResult);
        }
Example #16
0
        /// <summary>
        /// Clears a specific pending table by calling standard procedure 15
        /// </summary>
        /// <param name="bSelfRead">Whether or not a self read should be performed
        /// before activation</param>
        /// <param name="bDemandReset">Whether or not a demand reset should be
        /// performed before activation</param>
        /// <param name="byMfgEventCode">Mfg assigned code identifying event for
        /// activating pending table</param>
        /// <param name="eCode">Event code for status bitfield.  Use this field
        /// to identify the pending table</param>
        /// <returns>ProcedureResultCodes</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 08/25/06 AF 7.35.00  N/A     Created
        // 09/01/06 AF 7.35.00          Corrected code to copy stream to array
        // 10/04/06 AF 7.40.00  N/A     Moved from CENTRON_AMI.cs
        // 06/08/07 RCG 8.10.07        Changed to call ClearPendingTable with PendingEventRecord

        protected ProcedureResultCodes ClearPendingTable(bool bSelfRead,
                                                         bool bDemandReset,
                                                         byte byMfgEventCode,
                                                         PendingEventRecord.PendingEventCode eCode)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            PendingEventRecord   EventRecord;

            // Build the event record
            EventRecord = BuildPendingEventRecord(bSelfRead, bDemandReset, byMfgEventCode, eCode);

            // Clear the pending table
            ProcResult = ClearPendingTable(EventRecord);

            return(ProcResult);
        }
Example #17
0
        /// <summary>
        /// Calls the procedures needed to populate the ICM event tables (2521 and 2524).  Does not read the tables.
        /// </summary>
        /// <returns>The result of the procedure calls</returns>
        //  Revision History
        //  MM/DD/YY Who Version ID Issue# Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  03/14/14 AF  3.50.49 WR 464163 Created so that we can populate the event table without reading it
        //
        public ProcedureResultCodes SetUpForICMEvents()
        {
            ProcedureResultCodes Result    = ProcedureResultCodes.UNRECOGNIZED_PROC;
            ICSCommModule        ICSModule = CommModule as ICSCommModule;

            byte[] commandResponse;

            if (ICSModule != null)
            {
                if (ICSModule.FilterICSEvents() == ProcedureResultCodes.COMPLETED)
                {
                    Result = ICSModule.UpdateEventTables(new DateTime(1970, 1, 1), DateTime.MaxValue, out commandResponse);
                }
            }

            return(Result);
        }
Example #18
0
        /// <summary>
        /// Translates a ProcedureResultCodes into a FWDownloadResult
        ///</summary>
        /// <param name="ProcResult">Table 08 results codes</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 11/15/13 AF  3.50.03	       Class re-architecture - Cloned from CENTRON_AMI
        // 01/06/14 DLG 3.50.19        Class re-architecture - Moved from ICS_Gateway to
        //                             CommonFirmwareDownload.
        //
        private FWDownloadResult TranslateProcedureResult(ProcedureResultCodes ProcResult)
        {
            FWDownloadResult Result;

            switch (ProcResult)
            {
            case ProcedureResultCodes.COMPLETED:
            {
                Result = FWDownloadResult.SUCCESS;
                break;
            }

            case ProcedureResultCodes.INVALID_PARAM:
            {
                Result = FWDownloadResult.INVALID_CONFIG;
                break;
            }

            case ProcedureResultCodes.UNRECOGNIZED_PROC:
            {
                Result = FWDownloadResult.UNSUPPORTED_OPERATION;
                break;
            }

            case ProcedureResultCodes.TIMING_CONSTRAINT:
            {
                Result = FWDownloadResult.DEVICE_BUSY;
                break;
            }

            case ProcedureResultCodes.NO_AUTHORIZATION:
            {
                Result = FWDownloadResult.SECURITY_ERROR;
                break;
            }

            default:
            {
                Result = FWDownloadResult.WRITE_ERROR;
                break;
            }
            }

            return(Result);
        }
Example #19
0
        /// <summary>
        /// Displays the details for a security validation.
        /// </summary>
        /// <param name="ValidationResult">The result of the security validation.</param>
        /// <returns>Details from security validation.</returns>
        //  Revision History
        //  MM/DD/YY Who Version ID Number Description
        //  -------- --- ------- -- ------ -------------------------------------------
        //  09/23/14 jrf 4.00.63 WR 534158 Modified way test details are set.
        private string GetSecurityValidationDetails(ProcedureResultCodes ValidationResult)
        {
            string Details = "";

            if (ProcedureResultCodes.COMPLETED == ValidationResult)
            {
                Details = TestResources.Valid;
            }
            else if (ProcedureResultCodes.INVALID_PARAM == ValidationResult)
            {
                Details = TestResources.Invalid;
            }
            else
            {
                Details = TestResources.ValidationFailed;
            }

            return(Details);
        }
Example #20
0
        /// <summary>
        /// This method sets the preferred cell ID for the RFLAN.  The comm module
        /// will try for this cell for about 10 minutes before it will clear the cell
        /// ID out and try all cells.
        /// </summary>
        /// <param name="uiCellID">The preferred cell ID.</param>
        /// <returns>The result of the procedure.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/18/10 jrf 2.40.26	       Created
        // 02/17/14 jrf 3.00.35 460349 Updated method.
        public ProcedureResultCodes SetPreferredCellID(UInt32 uiCellID)
        {
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            MemoryStream         ProcParam  = new MemoryStream(5);

            byte[] ProcResponse;
            uint   uiParam2 = 0;
            uint   uiParam3 = 0;

            BinaryWriter ParamWriter = new BinaryWriter(ProcParam);

            ParamWriter.Write((byte)RFLANDebugProcedures.SET_PREFERRED_CELL);
            ParamWriter.Write(uiCellID);
            ParamWriter.Write(uiParam2);
            ParamWriter.Write(uiParam3);

            ProcResult = m_AMIDevice.ExecuteProcedure(Procedures.RFLAN_DEBUG_PROCEDURE,
                                                      ProcParam.ToArray(), out ProcResponse);

            return(ProcResult);
        }
Example #21
0
        /// <summary>
        /// Gets the current LED Quantity
        /// </summary>
        /// <returns>The currently pulsing quantity or null if the procedure fails.</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 03/07/11 RCG 2.50.06 N/A    Created

        public LEDQuantity GetCurrentPolyLEDQuantity()
        {
            LEDQuantity          CurrentQuantity = null;
            ProcedureResultCodes Result          = ProcedureResultCodes.UNRECOGNIZED_PROC;

            byte[]           ProcResponse   = null;
            byte[]           ProcParam      = new byte[] { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 };
            MemoryStream     ResponseStream = null;
            PSEMBinaryReader ResponseReader = null;

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

            if (Result == ProcedureResultCodes.COMPLETED && ProcResponse != null && ProcResponse.Length >= 4)
            {
                ResponseStream = new MemoryStream(ProcResponse);
                ResponseReader = new PSEMBinaryReader(ResponseStream);

                CurrentQuantity = new LEDQuantity(ResponseReader.ReadUInt32());
            }

            return(CurrentQuantity);
        }
Example #22
0
        /// <summary>
        /// Validates the HAN keys
        /// </summary>
        //  Revision History
        //  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 Modified way test details are set.
        //  05/23/17 CFB 4.72.00 WR 741323 Removed validation of HAN link key as it is no longer used in the meter
        private void ValidateHANKeys()
        {
            string NetworkKey = (string)CRegistryHelper.GetApplicationValue("GasPro", "Key");
            string LinkKey    = (string)CRegistryHelper.GetApplicationValue("GasPro", "GlobalLinkKey");
            ProcedureResultCodes ValidationResult = ProcedureResultCodes.COMPLETED;
            string Details = "";

            if (IsAborted == false)
            {
                //Network Key validation
                ValidationResult = m_AmiDevice.ValidateHANSecurityKeys(NetworkKey, CENTRON_AMI.HANKeys.NetworkKey);
                Details          = GetSecurityValidationDetails(ValidationResult);

                if (ProcedureResultCodes.INVALID_PARAM == ValidationResult)
                {
                    Details += ", " + TestResources.KeyNotConsistentWithRegistry;
                }

                AddTestDetail(TestResources.HANNetworkKey, GetResultString(ProcedureResultCodes.COMPLETED == ValidationResult),
                              Details);
            }
        }
Example #23
0
        /// <summary>
        /// Clears the sitescan snapshots in the meter.  This is not supported by
        /// the Vectron.
        /// </summary>
        /// <returns>A ItronDeviceResult</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ ---------------------------------------------
        //  02/21/07 mrj 8.00.13		Created
        //
        ItronDeviceResult ISiteScan.ClearSiteScanSnapshots()
        {
            ItronDeviceResult    Result     = ItronDeviceResult.SUCCESS;
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;

            byte[] ProcParam;
            byte[] ProcResponse;

            ProcParam  = new byte[0];             // No parameters for this procedure
            ProcResult = ExecuteProcedure(Procedures.CLEAR_SITESCAN_SNAPSHOTS,
                                          ProcParam, out ProcResponse);

            switch (ProcResult)
            {
            case ProcedureResultCodes.COMPLETED:
            {
                //Success
                Result = ItronDeviceResult.SUCCESS;
                break;
            }

            case ProcedureResultCodes.NO_AUTHORIZATION:
            {
                //Isc error
                Result = ItronDeviceResult.SECURITY_ERROR;
                break;
            }

            default:
            {
                //General Error
                Result = ItronDeviceResult.ERROR;
                break;
            }
            }

            return(Result);
        }
Example #24
0
        /// <summary>
        /// Implements the ISiteScan interface.  Resets the diagnostic counters
        /// </summary>
        /// Revision History
        /// MM/DD/YY who Version Issue# Description
        /// -------- --- ------- ------ ---------------------------------------
        /// 05/24/06 mrj 7.30.00 N/A    Created
        ///
        ItronDeviceResult ISiteScan.ResetDiagCounters()
        {
            ItronDeviceResult Result = ItronDeviceResult.ERROR;

            byte[] ProcResponse;
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;


            //Execute the reset conters MFG procedure
            byte[] byParameter = BitConverter.GetBytes((uint)Reset_Counter_Types.RESET_NUM_DIAG_COUNTERS);
            ProcResult = ExecuteProcedure(Procedures.RESET_COUNTERS, byParameter, out ProcResponse);

            switch (ProcResult)
            {
            case ProcedureResultCodes.COMPLETED:
            {
                //Success
                Result = ItronDeviceResult.SUCCESS;
                break;
            }

            case ProcedureResultCodes.NO_AUTHORIZATION:
            {
                //Isc error
                Result = ItronDeviceResult.SECURITY_ERROR;
                break;
            }

            default:
            {
                //General Error
                Result = ItronDeviceResult.ERROR;
                break;
            }
            }

            return(Result);
        }
Example #25
0
        /// <summary>
        /// Gets the current pulse weight
        /// </summary>
        /// <returns>The current pulse weight or null if the procedure fails</returns>
        //  Revision History
        //  MM/DD/YY Who Version  ID Number  Description
        //  -------- --- -------  -- ------  --------------------------------------------
        //  01/15/15 AF  4.00.92  WR 535491  Created
        //  03/25/15 AF  4.10.09  WR 573774  The scale factor for the response depends on the meter class
        //
        public float?GetCurrentPolyPulseWeight()
        {
            float?PulseWeight           = null;
            ProcedureResultCodes Result = ProcedureResultCodes.UNRECOGNIZED_PROC;

            byte[]           ProcResponse   = null;
            byte[]           ProcParam      = new byte[] { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 };
            MemoryStream     ResponseStream = null;
            PSEMBinaryReader ResponseReader = null;

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

            if (Result == ProcedureResultCodes.COMPLETED && ProcResponse != null && ProcResponse.Length >= 6)
            {
                ResponseStream = new MemoryStream(ProcResponse);
                ResponseReader = new PSEMBinaryReader(ResponseStream);

                ResponseReader.ReadUInt32();
                PulseWeight = (float)(ResponseReader.ReadUInt16()) / (float)DetermineEnergyDivisor();  // Scale factor depends on the meter class
            }

            return(PulseWeight);
        }
Example #26
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);
        }
Example #27
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
        // -------- --- ------- ------ ---------------------------------------
        // 11/15/13 AF  3.50.03	       Class re-architecture - Cloned from CENTRON_AMI
        // 01/06/14 DLG 3.50.19        Class re-architecture - Moved from ICS_Gateway to
        //                             CommonFirmwareDownload.
        // 02/03/14 AF  3.50.30 TQ9508 We needed to reverse the order of the bytes in the device class
        //                             before adding it to the parameter list
        // 02/07/14 jrf 3.50.32 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);

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

            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, CANSIDevice.FW_HEADER_LENGTH);
                fs.Close();

                byParameters = new byte[CANSIDevice.INIT_FW_DOWNLOAD_THIRD_PARTY_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);

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

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

                // Add the device class
                // The meter needs the Device Class 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 = m_ANSIDevice.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 (CommModVers != null)
                {
                    if (PSEMResponse.Err == PSEMExp.PSEMResponse &&
                        (byte)FirmwareType.ICSFW == byParameters[6] &&
                        CommModVers.CommModuleVersion == byParameters[2] &&
                        CommModVers.CommModuleRevision == byParameters[3] &&
                        CommModVers.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);
        }
Example #28
0
        public FWDownloadResult DownloadFW(string path, ref ushort usBlockIndex, bool blnRetry = false, bool blnActivate = true)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
            ushort usNumberChunks = 0;
            //A non-zero starting block means we are need to pick up were we left off.
            bool blnResumeFWDL = (0 != usBlockIndex);

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                if (true == blnResumeFWDL)
                {
                    Result = FWDownloadResult.SUCCESS;

                    m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                       "Resuming Firmware Download @ Block " + usBlockIndex.ToString());
                }
                else
                {
                    // Tell the meter to enter firmware download mode
                    Result = EnterFirmwareDownloadMode(path);
                }

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.ICSFW:
                    {
                        byEventNumber = CANSIDevice.COMM_EVENT_NUMBER;
                        idTable       = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not supported");
                    }
                    }

                    m_ANSIDevice.BuildPendingHeader(ref streamHeader, false, false,
                                                    byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / m_ANSIDevice.FWDLBlockSize);

                    if (streamFile.Length != m_ANSIDevice.FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    m_ANSIDevice.OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                                          "Firmware Download",
                                                                          "Downloading..."));

                    ushort usSendSize = m_ANSIDevice.FWDLBlockSize;

                    for (;
                         (usBlockIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         usBlockIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == usBlockIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % m_ANSIDevice.FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = m_ANSIDevice.FWDLBlockSize;
                            }
                        }

                        m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                           "Firmware Download - Sending Block " + usBlockIndex.ToString());

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, usBlockIndex * m_ANSIDevice.FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              usBlockIndex * m_ANSIDevice.FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    //Check on success and then activate the table
                    if (PSEMResponse.Ok == ProtocolResponse)
                    {
                        ProcResult = ProcedureResultCodes.COMPLETED;

                        if (ProcResult == ProcedureResultCodes.COMPLETED)
                        {
                            if (true == blnActivate)
                            {
                                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                                   "Activating Firmware Download");

                                // Activate the pending table using mfg proc 69
                                ProcResult = m_ANSIDevice.ActivateFWDLTable(idTable, (byte)FirmwareType.ICSFW, bybuffer[5], bybuffer[6], bybuffer[7], bybuffer[8]);

                                Result = TranslateProcedureResult(ProcResult);
                            }
                        }
                        else
                        {
                            //TODO - not sure this is the correct error
                            Result = FWDownloadResult.SECURITY_ERROR;
                        }

                        m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                    }
                    else //PSEMResponse.Ok != ProtocolResponse
                    {
                        //Decrement the block index so we make sure we restart on the block that we failed on.
                        usBlockIndex--;

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    m_ANSIDevice.OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                m_Logger.WriteException(this, e);

                if (false == blnRetry)
                {
                    // Log it and pass it up
                    m_ANSIDevice.OnHideProgress(new EventArgs());

                    throw e;
                }
                else
                {
                    Result = FWDownloadResult.WRITE_ERROR;
                }
            }

            return(Result);
        }
        /// <summary>
        /// Downloads the firmware file to the meter and activates it.
        /// The activation will cause the meter to drop the psem task so meter log off must
        /// follow this function call on success.  This method supports resuming
        /// a previous failed FWDL.
        /// </summary>
        /// <param name="path">Complete file path of the firmware file</param>
        /// <param name="usBlockIndex">Dual purpose parameter. The passed in value indicates
        /// which block to begin downloading. The passed out parameter indicates which block to
        /// resume downloading in case there was a failure. This can then passed in again to
        /// restart the download at the point where it left off.</param>
        /// <param name="blnRetry">Whether or not to leave the FWDL in a state
        /// to permit subsequent retries at point of faliure. If false the pending table
        /// will be cleared on failure.</param>
        /// <param name="blnActivate">Whether or not to activate the firmware.</param>
        /// <returns>Itron.Metering.Device.FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version ID Number Description
        // -------- --- ------- -- ------ ---------------------------------------
        // 08/28/06 AF  7.35.00    N/A    Created
        // 09/15/06 AF  7.35.00    N/A    Added Catch for TimeOutException
        // 10/18/06 AF  7.40.00    N/A    Removed wait within the main loop
        // 05/13/08 AF  1.50.24           Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39           Added M2 Gateway support
        // 08/18/11 AF  2.52.05           Added support for authentication using a hash code
        // 08/26/11 AF  2.52.08           Added support for Cisco f/w
        // 09/22/11 AF  2.52.21    N/A    Added support for Cisco config file f/w d/l - TODO remove when no longer needed
        // 10/12/11 AF  2.53.00           Changed the Cisco Comm fw enum name
        // 03/22/12 JJJ 2.60.xx           Added support for ChoiceConnect FW
        // 05/10/12 JJJ 2.60.xx           Tweaked FW Type passed to AuthenticateFWDL if ChoiceConnect, make RFLAN
        // 04/19/13 jrf 2.80.21 TQ 7639   Adding support for ICS comm module FWDL.
        // 07/08/13 jrf 2.80.51 TC 13201  Created to support retries of FWDL.
        // 07/15/13 jrf 2.80.?? TC 15062  Added parameter to control activation.
        // 08/22/13 jrf 2.85.26 WR 420902 Decrementing the block index on a failed block write, so
        //                                on a retry we will start back on the correct block.
        // 11/07/13 AF  3.50.02 TQ9508,9514 Have to activate the pending table using mfg proc 69 rather than std proc 13
        //                                  for I-210 and kV2c ICM firmware
        //  11/15/13 AF  3.50.03	    Class re-architecture - removed code specific to ICS_Gateway
        // 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.
        // 08/24/16 PGH 4.70.15 701952     Added HAN OTA Firmware
        // 02/06/17 AF  4.71.07 743128     Added supported for ICM modem firmware
        // 03/10/17 AF  4.71.09 749833     Renamed the firmware type because 37 is for Verizon LTE only
        // 12/05/17 AF  4.73.00 Task 469253 Added back the verizon modem fwdl
        // 12/06/17 AF  4.73.00 Task 469254 Added ATT/Rogers modem fwdl
        //
        public FWDownloadResult DownloadFW(string path, ref ushort usBlockIndex, bool blnRetry = false, bool blnActivate = true)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            //A non-zero starting block means we are need to pick up were we left off.
            bool blnResumeFWDL = (0 != usBlockIndex);

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                if (true == blnResumeFWDL)
                {
                    Result = FWDownloadResult.SUCCESS;
                }
                else
                {
                    // Tell the meter to enter firmware download mode
                    Result = EnterFirmwareDownloadMode(path);
                }


                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    case (byte)FirmwareType.ICSFW:
                    case (byte)FirmwareType.ICS_MODEM_FW_Sierra_Verizon_LTE:
                    case (byte)FirmwareType.ICS_MODEM_FW_Sierra_ATT_Rogers_Bell_LTE:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HAN_OTA_FW:
                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false,
                                       byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / FWDLBlockSize);

                    if (streamFile.Length != FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = FWDLBlockSize;

                    for (;
                         (usBlockIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         usBlockIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == usBlockIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = FWDLBlockSize;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, usBlockIndex * FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              usBlockIndex * FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    //Check on success and then activate the table
                    if (PSEMResponse.Ok == ProtocolResponse)
                    {
                        if (FWDLLogSupported)
                        {
                            //Construct the hash code and call the procedure to authenticate
                            CENTRON_AMI_FW_File FWFile = new CENTRON_AMI_FW_File(path);
                            byte[] FWHashCode          = FWFile.HashCode;

                            if ((bybuffer[9] != (byte)FirmwareType.ICSFW) && (bybuffer[9] != (byte)FirmwareType.ICS_MODEM_FW_Sierra_Verizon_LTE))
                            {
                                //Some devices may require this byte to be adjusted.
                                bybuffer[9] = SelectFWTypeByte(bybuffer[9]);

                                ProcResult = AuthenticateFWDL(idTable, bybuffer[9], FWHashCode);
                            }
                            else //Skip authenticate for ICS comm module and modem FWDL
                            {
                                ProcResult = ProcedureResultCodes.COMPLETED;
                            }
                        }
                        else
                        {
                            ProcResult = ProcedureResultCodes.COMPLETED;
                        }

                        if (ProcResult == ProcedureResultCodes.COMPLETED)
                        {
                            if (true == blnActivate)
                            {
                                // Activate the pending table using std proc 13
                                ProcResult = ActivatePendingTable(false, false, byEventNumber,
                                                                  PendingEventRecord.PendingEventCode.NonTimeTrigger);

                                Result = TranslateProcedureResult(ProcResult);
                            }
                        }
                        else
                        {
                            if (false == blnRetry)
                            {
                                //We couldn't authenticate using the hash code so activation will fail
                                ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                               PendingEventRecord.PendingEventCode.NonTimeTrigger);
                            }

                            //TODO - not sure this is the correct error
                            Result = FWDownloadResult.SECURITY_ERROR;
                        }

                        OnStepProgress(new ProgressEventArgs());
                    }
                    else //PSEMResponse.Ok != ProtocolResponse
                    {
                        //Decrement the block index so we make sure we restart on the block that we failed on.
                        usBlockIndex--;

                        if (false == blnRetry)
                        {
                            // Write failed, so clear the pending table
                            ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                           PendingEventRecord.PendingEventCode.NonTimeTrigger);
                        }

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                if (false == blnRetry)
                {
                    // Log it and pass it up
                    OnHideProgress(new EventArgs());
                    m_Logger.WriteException(this, e);
                    throw e;
                }
                else
                {
                    Result = FWDownloadResult.WRITE_ERROR;
                }
            }

            return(Result);
        }
        /// <summary>
        /// Downloads the firmware file to the device but does NOT
        /// activate.  On download failure, the pending table is cleared.
        /// </summary>
        /// <param name="path">Complete path to the firmware file</param>
        /// <param name="eventCode">event code activation method</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 10/05/06 AF  7.35.00  N/A   Created
        // 10/18/06 AF  7.40.00  N/A   Removed wait within the main loop
        // 05/13/08 AF  1.50.24        Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39        Added M2 Gateway support
        // 03/21/12 JJJ 2.60.xx        Added support for ChoiceConnect FW
        // 08/17/12 AF  2.60.55        Added support for RF Mesh FW and RF Mesh Config
        // 02/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        // 06/15/15 mah 4.50.140 577669 Added a retry if a busy response was received
        // 08/24/16 PGH 4.70.15 701952     Added HAN OTA Firmware
        public FWDownloadResult DownloadFWNoActivate(string path, PendingEventRecord.PendingEventCode eventCode)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            ushort intIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                Result = EnterFirmwareDownloadMode(path);

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HAN_OTA_FW:
                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not yet supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false, byEventNumber, eventCode);

                    usNumberChunks = (ushort)(streamFile.Length / FWDLBlockSize);

                    if (streamFile.Length != FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = FWDLBlockSize;

                    for (intIndex = 0;
                         (intIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         intIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == intIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = FWDLBlockSize;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, intIndex * FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * FWDLBlockSize,
                                                              streamPSEM.ToArray());

                        // WR 577669 - The fwdl process is failing on ICS meters with a device busy status.  The intent of the next
                        // paragraph is to recognize that the meter may be off doing other operations when we first tried to download
                        // a block.

                        if (ProtocolResponse == PSEMResponse.Bsy)
                        {
                            // Wait for the device to complete it's current task, then retry to download the same block

                            Thread.Sleep(1500); // 1.5 seconds is an arbitary value - the intent is to give the meter enough time to
                                                // complete it's work

                            ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                                  intIndex * FWDLBlockSize,
                                                                  streamPSEM.ToArray());
                        }
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    // If any write failed, give up and clear the pending table
                    if (PSEMResponse.Ok != ProtocolResponse)
                    {
                        // Write failed, so clear the pending table
                        ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                       PendingEventRecord.PendingEventCode.NonTimeTrigger);

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                // Log it and pass it up
                OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }