예제 #1
0
        /// <summary>
        /// Builds the pending table header
        /// </summary>
        /// <param name="strmPSEM">Stream to which the data is written</param>
        /// <param name="bSelfRead">tells whether or not to perform a self read
        /// before table is activated</param>
        /// <param name="bDemandReset">tells whether or not to perform a demand
        /// reset before table is activated</param>
        /// <param name="byMfgEventCode">Mfg assigned code identifying event for
        /// activating pending table</param>
        /// <param name="eCode">Event code for status bitfield.  2 => non-time activated</param>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 08/16/06 AF 7.35.00  N/A    Created
        // 10/04/06 AF 7.40.00  N/A    Moved from CENTRON_AMI.cs
        // 06/08/07 RCG 8.10.07        Changed to call BuildEventRecord

        protected void BuildPendingHeader(ref MemoryStream strmPSEM, bool bSelfRead, bool bDemandReset,
                                          byte byMfgEventCode, PendingEventRecord.PendingEventCode eCode)
        {
            PendingEventRecord EventRecord = new PendingEventRecord();

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

            // Write the event record to the stream
            strmPSEM.Write(EventRecord.EntireRecord, (int)strmPSEM.Position, EventRecord.EntireRecord.Length);
        }
예제 #2
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);
        }
예제 #3
0
        /// <summary>
        /// Builds a PendingEventRecord object for a Non Time Activated pending event
        /// with the specified parameters.
        /// </summary>
        /// <param name="bSelfRead">Whether or not a Self Read should be performed on activation.</param>
        /// <param name="bDemandReset">Whether or not a Demand Reset should be performed on activation.</param>
        /// <param name="byMfgEventCode">The manufacturer event code for the pending event.</param>
        /// <param name="eCode">The event code for the pending event.</param>
        /// <returns>The EventRecord object.</returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  06/07/07 RCG 8.10.07        Created
        //  02/05/09 AF  -.--.00        Changed the access modifier from protected to public
        //                              for automated firmware testing project

        public PendingEventRecord BuildPendingEventRecord(bool bSelfRead, bool bDemandReset,
                                                          byte byMfgEventCode, PendingEventRecord.PendingEventCode eCode)
        {
            PendingEventRecord EventRecord = new PendingEventRecord();
            ASCIIEncoding      AE          = new ASCIIEncoding();

            byte[] abyManufacturer = new byte[5];

            // Set up the event selector bitfield
            EventRecord.EventCode          = eCode;
            EventRecord.PerformSelfRead    = bSelfRead;
            EventRecord.PerformDemandReset = bDemandReset;

            // Copy the manufacturer ID to the device storage
            AE.GetBytes(MANUFACTURER).CopyTo(abyManufacturer, 0);

            // Copy the manufaturer event code
            abyManufacturer[abyManufacturer.Length - 1] = byMfgEventCode;
            EventRecord.EventStorage = abyManufacturer;

            return(EventRecord);
        }
예제 #4
0
        /// <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
        // -------- --- ------- ------ ---------------------------------------
        // 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/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        //
        public FWDownloadResult DownloadFWNoActivate(string path, PendingEventRecord.PendingEventCode eventCode)
        {
            FWDownloadResult Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            PSEMResponse     ProtocolResponse = PSEMResponse.Ok;
            byte             byEventNumber    = 0;
            ushort           idTable          = (ushort)CANSIDevice.FWDLTableIds.RegisterFWTbl | CANSIDevice.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.ICSFW:
                    {
                        byEventNumber = CANSIDevice.COMM_EVENT_NUMBER;
                        idTable       = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
                        break;
                    }

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

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

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

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

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * m_ANSIDevice.FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        m_ANSIDevice.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)
                    {
                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    m_ANSIDevice.OnHideProgress(new EventArgs());
                }
            }

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

            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);
        }