Пример #1
0
        public static async Task <HttpResponseMessage> GetDeviceCode(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "device/connect/{deviceID?}")] HttpRequestMessage req,
            string deviceID,
            TraceWriter log)
        {
            DeviceConnectionInfo info = await _deviceManagement.ConnectDeviceAsync(deviceID);

            return(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(JsonConvert.SerializeObject(info), Encoding.UTF8, JsonMediaType)
            });
        }
Пример #2
0
        /// <summary>
        /// デバイスにメッセージを送信する
        /// </summary>
        /// <param name="deviceConnectionInfo">デバイス接続情報</param>
        /// <param name="messageBody">メッセージ</param>
        /// <remarks>エラーが発生した場合には例外を投げる</remarks>
        /// <returns>成功:true 失敗:falseを返す</returns>
        public async Task SendMessageAsync(DeviceConnectionInfo deviceConnectionInfo, string messageBody)
        {
            System.Diagnostics.Debug.Assert(deviceConnectionInfo != null, "deviceConnectionInfo != null");
            System.Diagnostics.Debug.Assert(deviceConnectionInfo?.EdgeId != null, "deviceConnectionInfo?.EdgeId != null");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key)");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value)");

            bool result = false;

            try
            {
                _logger.EnterJson("{0}", new { deviceConnectionInfo, messageBody });

                // メッセージを変換する
                var message = new Message(Encoding.UTF8.GetBytes(messageBody));
                using (var serviceClient = ServiceClient.CreateFromConnectionString(deviceConnectionInfo.IotHubConnectionString.Value))
                {
                    // メッセージの送信を依頼する
                    await _iotHubPolly.ExecuteAsync(
                        async() =>
                    {
                        await serviceClient.SendAsync(deviceConnectionInfo.EdgeId.ToString(), message);
                    });
                }

                result = true;
            }
            catch (FormatException ex)
            {
                // 設定した接続文字列のフォーマットが不正
                throw new RmsInvalidAppSettingException(ErrorMessage.InvalidFormat(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (UnauthorizedAccessException ex)
            {
                // 接続文字列の認証が通らない
                throw new RmsException(ErrorMessage.UnauthroizedAccess(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (Exception ex)
            {
                // その他例外
                throw new RmsException(ErrorMessage.Others(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            finally
            {
                _logger.LeaveJson("{0}", new { result });
            }
        }
Пример #3
0
        /// <summary>
        /// デバイスツインのdesiredプロパティを更新する
        /// </summary>
        /// <param name="deviceTwin">更新対象デバイスツイン</param>
        /// <param name="deviceConnectionInfo">デバイス接続情報</param>
        /// <param name="messageBody">desiredプロパティに設定するJSON文字列</param>
        /// <returns>非同期実行タスク</returns>
        /// <remarks>
        /// - プロパティに設定するJSON文字列の正当性はService層でチェックすること
        /// - エラーが発生した場合には例外を投げる
        /// </remarks>
        public async Task UpdateDeviceTwinDesiredProperties(Twin deviceTwin, DeviceConnectionInfo deviceConnectionInfo, string messageBody)
        {
            System.Diagnostics.Debug.Assert(deviceConnectionInfo != null, "deviceConnectionInfo != null");
            System.Diagnostics.Debug.Assert(deviceConnectionInfo?.EdgeId != null, "deviceConnectionInfo?.EdgeId != null");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key)");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value)");
            System.Diagnostics.Debug.Assert(deviceTwin != null, "deviceTwin != null");

            bool result = false;

            try
            {
                _logger.EnterJson("{0}", new { deviceTwin, deviceConnectionInfo });

                using (var registryManager = RegistryManager.CreateFromConnectionString(deviceConnectionInfo.IotHubConnectionString.Value))
                {
                    // メッセージの送信を依頼する
                    await _iotHubPolly.ExecuteAsync(
                        async() =>
                    {
                        await registryManager.UpdateTwinAsync(deviceTwin.DeviceId, messageBody, deviceTwin.ETag);
                    });
                }

                result = true;
            }
            catch (FormatException ex)
            {
                // 設定した接続文字列のフォーマットが不正
                throw new RmsInvalidAppSettingException(ErrorMessage.InvalidFormat(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (UnauthorizedAccessException ex)
            {
                // 接続文字列の認証が通らない
                throw new RmsException(ErrorMessage.UnauthroizedAccess(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (Exception ex)
            {
                // その他例外
                throw new RmsException(ErrorMessage.Others(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            finally
            {
                _logger.LeaveJson("{0}", new { result });
            }
        }
Пример #4
0
        /// <summary>
        /// ゲートウェイ機器にメッセージを送信する(ラッパー)
        /// </summary>
        /// <param name="deveiceConnectionInfo">デバイス接続情報</param>
        /// <param name="deliveryMessage">配信メッセージ</param>
        /// <param name="gatewayDevice">ゲートウェイ機器</param>
        /// <returns>送信依頼処理成功/失敗</returns>
        private async Task <bool> SendMessageAsyncWrapper(DeviceConnectionInfo deveiceConnectionInfo, string deliveryMessage, DtDevice gatewayDevice)
        {
            bool ret = false;

            try
            {
                await _requestDeviceRepository.SendMessageAsync(deveiceConnectionInfo, deliveryMessage);

                ret = true;
            }
            catch (Exception e)
            {
                // Sq1.6
                _logger.Error(e, nameof(Resources.CO_DLV_DLV_015), new object[] { gatewayDevice.EdgeId, gatewayDevice.EquipmentUid, e.Message });
            }

            return(ret);
        }
Пример #5
0
        /// <summary>
        /// デバイスツインを取得する
        /// </summary>
        /// <param name="deviceConnectionInfo">デバイス接続情報</param>
        /// <returns>デバイスツイン</returns>
        public async Task <Twin> GetDeviceTwin(DeviceConnectionInfo deviceConnectionInfo)
        {
            System.Diagnostics.Debug.Assert(deviceConnectionInfo != null, "deviceConnectionInfo != null");
            System.Diagnostics.Debug.Assert(deviceConnectionInfo?.EdgeId != null, "deviceConnectionInfo?.EdgeId != null");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Key)");
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value), "!string.IsNullOrEmpty(deviceConnectionInfo?.IotHubConnectionString.Value)");

            Twin deviceTwin = null;

            try
            {
                _logger.EnterJson("{0}", new { deviceConnectionInfo });

                using (var registryManager = RegistryManager.CreateFromConnectionString(deviceConnectionInfo.IotHubConnectionString.Value))
                {
                    deviceTwin = await registryManager.GetTwinAsync(deviceConnectionInfo.EdgeId.ToString());
                }
            }
            catch (FormatException ex)
            {
                // 設定した接続文字列のフォーマットが不正
                throw new RmsInvalidAppSettingException(ErrorMessage.InvalidFormat(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (UnauthorizedAccessException ex)
            {
                // 接続文字列の認証が通らない
                throw new RmsException(ErrorMessage.UnauthroizedAccess(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            catch (Exception ex)
            {
                // その他例外
                throw new RmsException(ErrorMessage.Others(deviceConnectionInfo.EdgeId, deviceConnectionInfo.IotHubConnectionString.Key), ex);
            }
            finally
            {
                _logger.LeaveJson("{0}", new { deviceTwin });
            }

            return(deviceTwin);
        }
Пример #6
0
        /// <summary>
        /// デバイス接続情報を取得する(ラッパー)
        /// </summary>
        /// <param name="gatewayDevice">ゲートウェイ機器</param>
        /// <returns>デバイス接続情報</returns>
        private async Task <DeviceConnectionInfo> GetDeviceConnectionInfoAsyncWrapper(DtDevice gatewayDevice)
        {
            DeviceConnectionInfo deveiceConnectionInfo = null;

            try
            {
                deveiceConnectionInfo = await _requestDeviceRepository.GetDeviceConnectionInfoAsync(gatewayDevice.EdgeId);

                if (deveiceConnectionInfo == null)
                {
                    // Sq1.5(デバイスが見つからない場合)
                    throw new RmsException("IoTHubの接続文字列が見つかりません");
                }
            }
            catch (Exception e)
            {
                // Sq1.5
                _logger.Error(e, nameof(Resources.CO_DLV_DLV_013), new object[] { gatewayDevice.EdgeId, gatewayDevice.EquipmentUid, e.Message });
            }

            return(deveiceConnectionInfo);
        }
Пример #7
0
        /// <summary>
        /// 端末へリモート接続のリクエストを行う
        /// </summary>
        /// <remarks>sd 03-2.リモート接続(ワンタイム接続)</remarks>
        /// <param name="request">リクエスト</param>
        /// <returns>結果</returns>
        public async Task <Result> RequestRemoteAsync(RequestRemote request)
        {
            Result result = null;
            RequestRemoteAsyncStatus status = RequestRemoteAsyncStatus.ReadDtDevice;

            try
            {
                _logger.EnterJson("In Param: {0}", request);

                // 端末データからDeviceIDをDeviceEdgeIdを取得する。
                DtDevice model = _dtDeviceRepository.ReadDtDevice(request.DeviceId);
                if (model == null)
                {
                    _logger.Error(nameof(Resources.CO_API_DRC_003));
                    result = new Result(ResultCode.NotFound, Resources.CO_API_DRC_003);
                    return(result);
                }

                // Sq3.1.1 接続先情報を取得する
                status = RequestRemoteAsyncStatus.GetDeviceConnectionInfoAsync;
                DeviceConnectionInfo deveiceConnectionInfo = await _requestDeviceRepository.GetDeviceConnectionInfoAsync(model.EdgeId);

                if (deveiceConnectionInfo == null)
                {
                    _logger.Error(nameof(Resources.CO_API_DRC_004));
                    result = new Result(ResultCode.NotFound, Resources.CO_API_DRC_004);
                    return(result);
                }

                // Sq3.1.2 メッセージを生成する
                string message = CreateMessage(request, out result);

                // Sq3.1.3 メッセージを送信する
                status = RequestRemoteAsyncStatus.SendMessageAsync;
                await _requestDeviceRepository.SendMessageAsync(deveiceConnectionInfo, message);

                _logger.Info(nameof(Resources.CO_API_DRC_007));
                result = new Result(ResultCode.Succeed, Resources.CO_API_DRC_007);
                return(result);
            }
            catch (Exception ex)
            {
                switch (status)
                {
                // ReadDtDeviceでnullを返さずにExceptionが発生した場合
                case RequestRemoteAsyncStatus.ReadDtDevice:
                    _logger.Error(nameof(Resources.CO_API_DRC_003));
                    result = new Result(ResultCode.NotFound, Resources.CO_API_DRC_003);
                    break;

                case RequestRemoteAsyncStatus.GetDeviceConnectionInfoAsync:
                    _logger.Error(ex, nameof(Resources.CO_API_DRC_004));
                    result = new Result(ResultCode.ServerEerror, Resources.CO_API_DRC_004);
                    break;

                case RequestRemoteAsyncStatus.SendMessageAsync:
                default:
                    _logger.Error(ex, nameof(Resources.CO_API_DRC_006));
                    result = new Result(ResultCode.ServerEerror, Resources.CO_API_DRC_006);
                    break;
                }

                return(result);
            }
            finally
            {
                _logger.LeaveJson("Result Param: {0}", result);
            }
        }
Пример #8
0
 public CDPParser(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo, bool AllowRecursion)
 {
     _Executor       = Executor;
     _ConnectionInfo = ConnectionInfo;
     _AllowRecursion = AllowRecursion;
 }
Пример #9
0
 public NXOS_CDPParser(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo, bool AllowRecursion) : base(Executor, ConnectionInfo, AllowRecursion)
 {
 }
 public override eDeviceError ConnectDevice(DeviceConnectionInfo param)
 {
     Connect(param.Address, param.TcpPort);
     Connected = true;
     return(base.ConnectDevice(param));
 }
Пример #11
0
        /// <summary>
        /// デバイス接続情報を取得する。
        /// </summary>
        /// <param name="edgeId">端末ID</param>
        /// <returns>デバイス接続情報を返す。対象デバイスが見つからない場合nullを返す。</returns>
        public async Task <DeviceConnectionInfo> GetDeviceConnectionInfoAsync(Guid edgeId)
        {
            DeviceConnectionInfo result = null;
            string connectionStringDps  = null;

            try
            {
                _logger.Enter($"{nameof(edgeId)}: {{0}}", new object[] { edgeId });

                // DPS接続文字列取得
                connectionStringDps = _appSettings.DpsConnectionString;
                if (string.IsNullOrWhiteSpace(connectionStringDps))
                {
                    throw new RmsInvalidAppSettingException("DpsConnectionString is required.");
                }

                string iotHubName = null;

                using (var service = ProvisioningServiceClient.CreateFromConnectionString(connectionStringDps))
                {
                    await _dpsPolly.ExecuteAsync(
                        async() =>
                    {
                        // 見つからなかったらProvisioningServiceClientHttpExceptionが発生して、
                        // その例外のStatusCodeにHttpStatusCode型のNotFoundになる。
                        // これ以外はとりあえず500にする。
                        DeviceRegistrationState deviceRegistrationState = await service.GetDeviceRegistrationStateAsync(edgeId.ToString());
                        iotHubName = deviceRegistrationState.AssignedHub;
                    });
                }

                string iotHubConnectionStringKey = string.Format(IoTHubNamePrefixOnAppSettings, iotHubName);

                // IoTHub接続文字列取得
                string iotHubConnectionStringValue = _appSettings.GetConnectionString(iotHubConnectionStringKey);
                if (string.IsNullOrWhiteSpace(iotHubConnectionStringValue))
                {
                    throw new RmsInvalidAppSettingException(string.Format("{0} is required.", iotHubConnectionStringKey));
                }

                result = new DeviceConnectionInfo()
                {
                    EdgeId = edgeId,
                    IotHubConnectionString = new KeyValuePair <string, string>(iotHubConnectionStringKey, iotHubConnectionStringValue),
                };
                return(result);
            }
            catch (RmsException)
            {
                throw;
            }
            catch (ArgumentException ex)
            {
                // 接続文字列がフォーマットに則っていない。
                throw new RmsInvalidAppSettingException("DpsConnectionString is invalid format.", ex);
            }
            catch (ProvisioningServiceClientHttpException ex) when(ex.StatusCode == HttpStatusCode.NotFound)
            {
                // 対象デバイスが見つからない
                result = null;
                return(result);
            }
            catch (ProvisioningServiceClientHttpException ex) when(ex.StatusCode == HttpStatusCode.Unauthorized)
            {
                // 使用した接続文字列で認証が通らなかった
                throw new RmsException(string.Format("DPSで認証エラーが発生しました。({0})", connectionStringDps), ex);
            }
            catch (Exception ex)
            {
                throw new RmsException("接続先のIoT Hub", ex);
            }
            finally
            {
                _logger.LeaveJson("{0}", new { result });
            }
        }
Пример #12
0
 public void HostUnreachable(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo)
 {
 }
Пример #13
0
        public bool DoCustomAction(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo, out dynamic ActionResult, out bool ConnectionDropped, out bool BreakExecution)
        {
            bool result = false;

            ActionResult      = "Custom action not implemented";
            ConnectionDropped = false;
            BreakExecution    = false;
            IScriptableSession st = (IScriptableSession)Executor.Session;
            int DeviceID          = 0;

            if (ConnectionInfo.CustomActionID == "PGTNetworkDiscovery")
            {
                if (ConnectionInfo.VendorName.ToLowerInvariant() == "cisco")
                {
                    #region Cisco
                    ActionResult = "Error processing PGTNetworkDiscovery for Cisco";
                    string show_ver        = string.Empty;
                    string device_type     = "router";
                    string actual_hostname = string.Empty;
                    string show_inventory  = string.Empty;
                    string system_serial   = string.Empty;

                    #region SHOW VER, Virtual switch, Stacked switch

                    Executor.ShowActivity("Retrieving device information...");
                    show_ver        = st.ExecCommand("sh ver");
                    actual_hostname = st.GetHostName();

                    string virtualswitch = st.ExecCommand("sh switch virtual");
                    bool   isVSS         = false;
                    try
                    {
                        isVSS = virtualswitch.SplitByLine().First().Split(':')[1].ToLowerInvariant().Trim() == "virtual switch";
                    }
                    catch (Exception Ex)
                    {
                        DebugEx.WriteLine(String.Format("CDP2VISIO : error parsing \"sh virtual switch\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
                    }
                    int    stackCount      = 0;
                    string stackedswitches = st.ExecCommand("sh switch");
                    try
                    {
                        if (stackedswitches.ToLowerInvariant().StartsWith("switch/stack"))
                        {
                            stackCount = stackedswitches.SplitByLine().Count(l => l.SplitBySpace()[0].Trim('*').IsInt());
                        }
                    }
                    catch (Exception Ex)
                    {
                        DebugEx.WriteLine(String.Format("CDP2VISIO : error parsing \"sh switch\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
                    }
                    #endregion

                    try
                    {
                        #region Identify device
                        show_inventory = st.ExecCommand("show inventory");
                        // Indicates that we are connected to an ASA, using later for VLAN discovery
                        bool isASA = show_inventory.IndexOf("Adaptive Security Appliance") >= 0;
                        // some switches doe no support the "show inventory" command
                        bool exec_error = show_inventory.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => show_inventory.IndexOf(w) >= 0);
                        if (exec_error)
                        {
                            DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh inventory\" command, parsing version information"), DebugLevel.Debug);
                            // try to parse sh_version to get system serial numbers
                            try
                            {
                                system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
                            }
                            catch (Exception Ex)
                            {
                                DebugEx.WriteLine(String.Format("CDP2VISIO : error searching serial number in \"sh version\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
                            }
                        }
                        else
                        {
                            // This should return system serial most of the time
                            try
                            {
                                if (stackCount > 0)
                                {
                                    // if stackCount > 0 the switch supported the "show switch" command. Probably also understands "show module"
                                    string modules = st.ExecCommand("show module");
                                    // some switches who support the "show switch" command may still do not understand "show modules"
                                    exec_error = modules.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => modules.IndexOf(w) >= 0);
                                    if (exec_error)
                                    {
                                        DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh module\" command, parsing version information"), DebugLevel.Debug);
                                        // try to parse sh_version to get system serial numbers
                                        system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
                                    }
                                    else
                                    {
                                        // select lines starting with a number. These are assumed the be the switches in stack
                                        var switchList = modules.SplitByLine().Where(l => l.SplitBySpace()[0].Trim('*').IsInt());
                                        // each line contains the serial number in th 4th column
                                        system_serial = string.Join(",", switchList.Select(m => m.SplitBySpace()[3]));
                                    }
                                }
                                else
                                {
                                    system_serial = show_inventory.SplitByLine().First(l => l.StartsWith("PID:")).Split(',')[2].Split(':')[1].Trim();
                                }
                            }
                            catch (Exception Ex)
                            {
                                system_serial = "parsing error";
                                DebugEx.WriteLine(string.Format("Error parsing serial number : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Error);
                            }
                        }
                        #endregion

                        #region Add New Device to DB with inlist
                        // Two devices considered identical if :
                        // - have the same hostname, or
                        // - have the same IPAddress
                        CDPDataSet.DevicesRow device_row = local_dataset.Devices.FirstOrDefault(d =>
                                                                                                d.IP_Address.SplitBySemicolon().Any(thisIP => thisIP == ConnectionInfo.DeviceIP) ||
                                                                                                d.Name.SplitBySemicolon().Any(thisName => DottedNameSpace.CompateTLD(thisName, ConnectionInfo.HostName))
                                                                                                );
                        if (device_row == null) //If NOT found in the DB have to ADD as new
                        {
                            device_row = local_dataset.Devices.NewDevicesRow();
                            device_row.SystemSerial = system_serial;
                            device_row.IP_Address   = ConnectionInfo.DeviceIP;
                            device_row.Name         = actual_hostname;
                            device_row.VersionInfo  = show_ver;
                            device_row.Type         = isASA ? "ASA" : isVSS ? "VSS" : stackCount > 1 ? string.Format("Stack{0}", stackCount) : device_type;
                            device_row.Inventory    = show_inventory;
                            local_dataset.Devices.AddDevicesRow(device_row);
                            DeviceID = device_row.ID;
                        }
                        else //IF found in the existing DB have to update!
                        {
                            device_row.VersionInfo  = show_ver;
                            device_row.Inventory    = show_inventory;
                            device_row.SystemSerial = system_serial;
                            if (isASA)
                            {
                                device_row.Type = "ASA";
                            }
                            else if (isVSS)
                            {
                                device_row.Type = "VSS";
                            }
                            else if (stackCount > 1)
                            {
                                device_row.Type = string.Format("Stack{0}", stackCount);
                            }
                        }

                        #endregion

                        #region SHOW CDP NEIGHBOUR
                        if (!isASA)
                        {
                            Executor.ShowActivity("Checking for CDP neighbors...");
                            string cdpResult = st.ExecCommand("sh cdp neighbors detail");

                            CDPParser thisParser;
                            if (show_ver.IndexOf("NX-OS") >= 0)
                            {
                                thisParser = new NXOS_CDPParser(Executor, ConnectionInfo, AllowRecursion);
                                thisParser.ProcessCDPResult(cdpResult, device_row, local_dataset);
                            }
                            else
                            {
                                thisParser = new IOS_CDPParser(Executor, ConnectionInfo, AllowRecursion);
                                thisParser.ProcessCDPResult(cdpResult, device_row, local_dataset);
                            }
                        }

                        #endregion

                        #region Collect interface configuration details for CDP connected interfaces
                        Executor.ShowActivity("Collecting CDP connected interface information...");
                        var query_local_interfaces = from device in local_dataset.Devices
                                                     where (device.ID == device_row.ID)
                                                     join neigh in local_dataset.Neighbours on device.ID equals neigh.Parent_ID
                                                     select new
                        {
                            local_int = neigh.Local_Interface,
                            ID        = device.ID,
                        };
                        foreach (var thisInterface in query_local_interfaces)
                        {
                            CDP2VISIO.CDPDataSet.InterfacesRow interface_row = null;
                            interface_row = local_dataset.Interfaces.NewInterfacesRow();


                            string command = "sh run interface " + thisInterface.local_int;


                            string commandResult = st.ExecCommand(command);
                            commandResult = commandResult.ToLower();

                            string[] lines_in_commandresult = commandResult.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            string   interface_config       = string.Empty;
                            bool     addtoconfig            = false;
                            foreach (var line in lines_in_commandresult)
                            {
                                if (line.IndexOf(RevConvInt(thisInterface.local_int)) >= 0)
                                {
                                    addtoconfig = true;
                                }
                                if (addtoconfig)
                                {
                                    interface_config = interface_config + line + "\r\n";
                                }
                            }

                            interface_row.ID             = thisInterface.ID;
                            interface_row.Name           = thisInterface.local_int;
                            interface_row.Running_config = interface_config;


                            local_dataset.Interfaces.AddInterfacesRow(interface_row);
                        }

                        #endregion

                        #region Collect overall interface status information
                        if (Options.Default.DisplayConnected && !isASA)
                        {
                            Executor.ShowActivity("Checking interface status...");
                            string[] ifDesc = st.ExecCommand("show interface description").SplitByLine();
                            foreach (string thisIfDescription in ifDesc.SkipWhile((string s, int i) => i < 1))
                            {
                                string[] ifDescrWords = thisIfDescription.SplitBySpace();
                                string   IFName       = Common.ConvInt(ifDescrWords[0]);
                                if (!IFName.StartsWith("vl")) // Don't care vlan interfaces here
                                {
                                    string IFStatus      = string.Format("{0}/{1}", ifDescrWords[1], ifDescrWords[2]);
                                    string IFDescription = string.Join(" ", ifDescrWords.SkipWhile((string s, int i) => i < 3));
                                    var    foundIF       = from thisIF in local_dataset.Interfaces where thisIF.ID == device_row.ID && thisIF.Name == IFName select thisIF;
                                    if (foundIF.Count() == 1)
                                    {
                                        // Update existing IF data
                                        foundIF.ElementAt(0).Status      = IFStatus;
                                        foundIF.ElementAt(0).Description = IFDescription;
                                    }
                                    else
                                    {
                                        // Add as new IF
                                        CDPDataSet.InterfacesRow thisIF = local_dataset.Interfaces.NewInterfacesRow();
                                        thisIF.ID          = device_row.ID;
                                        thisIF.Name        = IFName;
                                        thisIF.Status      = IFStatus;
                                        thisIF.Description = IFDescription;
                                        local_dataset.Interfaces.AddInterfacesRow(thisIF);
                                    }
                                }
                            }
                        }
                        #endregion

                        #region Collect VLAN interface information
                        if (isASA)
                        {
                            Executor.ShowActivity("Gathering VLAN information...");
                            // Contains the L3 information : interface names, interface ip, network, mask
                            List <string> VLANInfo = new List <string>();
                            string        asaIFs   = st.ExecCommand("sh int ip brief");
                            device_row.L3InterfaceInformation = asaIFs;
                            foreach (string thisInterface in asaIFs.SplitByLine().SkipWhile(l => l.StartsWith("Interface")))
                            {
                                string[] ifWords      = thisInterface.SplitBySpace();
                                string   asaIFName    = ifWords[0];
                                string   nameIF       = "";
                                string   secLevel     = "";
                                string   vlanIPAddr   = "";
                                string   vlanNetMask  = "";
                                string   netaddress   = "";
                                int      maskLength   = 0;
                                int      vlanID       = 0;
                                string   thisIFConfig = st.ExecCommand(string.Format("sh run int {0}", asaIFName));
                                foreach (string thisConfigLine in thisIFConfig.SplitByLine().Select(s => s.Trim()))
                                {
                                    if (thisConfigLine.StartsWith("vlan"))
                                    {
                                        int.TryParse(thisConfigLine.SplitBySpace()[1], out vlanID);
                                    }
                                    else if (thisConfigLine.StartsWith("nameif"))
                                    {
                                        nameIF = thisConfigLine.SplitBySpace()[1];
                                    }
                                    else if (thisConfigLine.StartsWith("security-level"))
                                    {
                                        secLevel = thisConfigLine.SplitBySpace()[1];
                                    }
                                    else if (thisConfigLine.StartsWith("ip address"))
                                    {
                                        string[] lineWords = thisConfigLine.SplitBySpace();
                                        vlanIPAddr  = lineWords[2];
                                        vlanNetMask = lineWords[3];
                                        maskLength  = IPOperations.GetMaskLength(vlanNetMask);
                                        netaddress  = IPOperations.GetNetworkAddress(vlanIPAddr, maskLength);
                                    }
                                }
                                string networkAddressPrint = "";
                                if (maskLength > 0)
                                {
                                    networkAddressPrint = string.Format("{0}/{1}", netaddress, maskLength);
                                }
                                string reportedIFName = string.Format("{0} name: {1} security-level: {2}", asaIFName, nameIF, secLevel);
                                VLANInfo.Add(string.Join(";", new string[] { vlanID == 0 ? "routed" : vlanID.ToString(), reportedIFName, vlanIPAddr, vlanNetMask, networkAddressPrint }));

                                #region Add ASA interface to inventory database
                                string IFStatus = "n/a";
                                if (ifWords.Length == 6)
                                {
                                    IFStatus = string.Format("{0}/{1}", ifWords[4], ifWords[5]);
                                }
                                else if (ifWords.Length == 7)
                                {
                                    IFStatus = string.Format("{0} {1}/{2}", ifWords[4], ifWords[5], ifWords[6]);
                                }
                                var foundIF = from thisIF in local_dataset.Interfaces where thisIF.ID == device_row.ID && thisIF.Name == asaIFName select thisIF;
                                if (foundIF.Count() == 1)
                                {
                                    // Update existing IF data
                                    foundIF.ElementAt(0).Status      = IFStatus;
                                    foundIF.ElementAt(0).Description = reportedIFName;
                                }
                                else
                                {
                                    // Add as new IF
                                    CDPDataSet.InterfacesRow thisIF = local_dataset.Interfaces.NewInterfacesRow();
                                    thisIF.ID          = device_row.ID;
                                    thisIF.Name        = asaIFName;
                                    thisIF.Status      = IFStatus;
                                    thisIF.Description = reportedIFName;
                                    local_dataset.Interfaces.AddInterfacesRow(thisIF);
                                }
                                #endregion
                            }
                            device_row.VLANInformation = string.Join(Environment.NewLine, VLANInfo);
                        }
                        else
                        {
                            Executor.ShowActivity("Gathering VLAN interface information...");
                            // TODO : for routers, also include "sh ip int brief"
                            string vlanIFs = st.ExecCommand("sh ip int brief | i [Vv]lan");
                            device_row.L3InterfaceInformation = vlanIFs;

                            #region Collect network details for VLANs
                            // Contains the list of VLAN interface names
                            List <string> VLANInterfaces = Regex.Matches(vlanIFs, "^Vlan(\\d+)", RegexOptions.Multiline).Cast <Match>().Select(m => m.Value.ToLowerInvariant()).ToList();
                            // Contains the L3 information : interface names, interface ip, network, mask
                            List <string> VLANInfo        = new List <string>();
                            string        vlans           = st.ExecCommand("sh vlan");
                            bool          addLineToOutput = false;
                            foreach (string line in vlans.SplitByLine())
                            {
                                if (line.StartsWith("---"))
                                {
                                    addLineToOutput = !addLineToOutput;
                                    if (!addLineToOutput)
                                    {
                                        break;
                                    }
                                }
                                else if (addLineToOutput)
                                {
                                    string[] words  = line.SplitBySpace();
                                    int      vlanID = -1;
                                    if (int.TryParse(words[0], out vlanID))
                                    {
                                        string vlanName    = words[1];
                                        string vlanIPAddr  = "";
                                        string vlanNetMask = "";
                                        string netaddress  = "";
                                        int    maskLength  = 0;
                                        // Check if current VLAN has a corresponding VLAN interface definition
                                        if (VLANInterfaces.Contains(string.Format("vlan{0}", vlanID)))
                                        {
                                            string vlanIntConfig = st.ExecCommand(string.Format("sh run int vlan{0}", vlanID));
                                            string ipAddressLine = vlanIntConfig.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith("ip address"));
                                            if (ipAddressLine != null)
                                            {
                                                string[] addr = ipAddressLine.SplitBySpace();
                                                vlanIPAddr  = addr[2];
                                                vlanNetMask = addr[3];
                                                maskLength  = IPOperations.GetMaskLength(vlanNetMask);
                                                netaddress  = IPOperations.GetNetworkAddress(vlanIPAddr, maskLength);
                                            }
                                            else
                                            {
                                                ipAddressLine = vlanIntConfig.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith("no ip address"));
                                                if (ipAddressLine != null)
                                                {
                                                    vlanIPAddr = "no ip address";
                                                }
                                            }
                                        }
                                        string networkAddressPrint = "";
                                        if (maskLength > 0)
                                        {
                                            networkAddressPrint = string.Format("{0}/{1}", netaddress, maskLength);
                                        }
                                        VLANInfo.Add(string.Join(";", new string[] { vlanID.ToString(), vlanName, vlanIPAddr, vlanNetMask, networkAddressPrint }));
                                    }
                                }
                            }
                            device_row.VLANInformation = string.Join(Environment.NewLine, VLANInfo);
                            #endregion
                        }
                        #endregion

                        result       = true;
                        ActionResult = "Discovery information processing finished successfully.";
                        if (system_serial == "")
                        {
                            ActionResult += "Warning : Could not identify system serial number.";
                        }
                    }
                    catch (Exception Ex)
                    {
                        ActionResult = string.Format("Unexpected processing error : {0} {1}", Ex.Message, Ex.InnerException?.Message);
                    }
                    #endregion
                }
                else if (ConnectionInfo.VendorName.ToLowerInvariant() == "junos")
                {
                    #region JunOS
                    //
                    // http://www.juniper.net/documentation/en_US/junos11.1/topics/task/configuration/802-1x-lldp-cli.html
                    //
                    ActionResult = "Error processing PGTNetworkDiscovery for JunOS";
                    string show_ver        = string.Empty;
                    string device_type     = "router";
                    string actual_hostname = string.Empty;
                    string show_inventory  = string.Empty;
                    string system_serial   = string.Empty;
                    int    stackCount      = 0;

                    #region Identify device
                    show_inventory = st.ExecCommand("show chassis hardware");
                    // Indicates that we are connected to an ASA, using later for VLAN discovery
                    bool isASA = show_inventory.IndexOf("Adaptive Security Appliance") >= 0;
                    // some switches doe no support the "show inventory" command
                    bool exec_error = show_inventory.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => show_inventory.IndexOf(w) >= 0);
                    if (exec_error)
                    {
                        DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh inventory\" command, parsing version information"), DebugLevel.Debug);
                        // try to parse sh_version to get system serial numbers
                        try
                        {
                            system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
                        }
                        catch (Exception Ex)
                        {
                            DebugEx.WriteLine(String.Format("CDP2VISIO : error searching serial number in \"sh version\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
                        }
                    }
                    else
                    {
                        // This should return system serial most of the time
                        try
                        {
                            if (stackCount > 0)
                            {
                                // if stackCount > 0 the switch supported the "show switch" command. Probably also understands "show module"
                                string modules = st.ExecCommand("show module");
                                // some switches who support the "show switch" command may still do not understand "show modules"
                                exec_error = modules.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => modules.IndexOf(w) >= 0);
                                if (exec_error)
                                {
                                    DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh module\" command, parsing version information"), DebugLevel.Debug);
                                    // try to parse sh_version to get system serial numbers
                                    system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
                                }
                                else
                                {
                                    // select lines starting with a number. These are assumed the be the switches in stack
                                    var switchList = modules.SplitByLine().Where(l => l.SplitBySpace()[0].Trim('*').IsInt());
                                    // each line contains the serial number in th 4th column
                                    system_serial = string.Join(",", switchList.Select(m => m.SplitBySpace()[3]));
                                }
                            }
                            else
                            {
                                system_serial = show_inventory.SplitByLine().First(l => l.StartsWith("PID:")).Split(',')[2].Split(':')[1].Trim();
                            }
                        }
                        catch (Exception Ex)
                        {
                            system_serial = "parsing error";
                            DebugEx.WriteLine(string.Format("Error parsing serial number : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Error);
                        }
                    }
                    #endregion


                    #endregion
                }
            }
            return(result);
        }