protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
        {
            SnmpWorkSettings settings = Host.Settings;

            if (settings.SpeedTargets._IsSamei("none") || settings.SpeedTargets._IsSamei("null"))
            {
                return;
            }

            string[] speedTargets = settings.SpeedTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

            count++;


            foreach (string target in speedTargets)
            {
                ParseTargetString(target, out string hostnameAndPort, out string alias);

                cancel.ThrowIfCancellationRequested();

                string[] tokens = hostnameAndPort._Split(StringSplitOptions.RemoveEmptyEntries, '|');
                string   host;
                int      port = 9821;
                host = tokens[0];
                if (tokens.Length >= 2)
                {
                    port = tokens[1]._ToInt();
                }

                //long downloadBps_1 = 0;
                //long uploadBps_1 = 0;
                long downloadBps_32 = 0;
                long uploadBps_32   = 0;

                int intervalBetween = settings.SpeedIntervalsSec * 1000;
                if (count <= 1)
                {
                    intervalBetween = 0;
                }

                int numTry = settings.SpeedTryCount;
                if (count <= 1)
                {
                    numTry = 1;
                }

                int span = settings.SpeedSpanSec * 1000;
                if (count <= 1)
                {
                    span = 2000;
                }

                try
                {
                    IPAddress ipAddress = await LocalNet.GetIpAsync(host, cancel : cancel);

                    try
                    {
                        var downloadResult_32 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 32, span, SpeedTestModeFlag.Download, numTry, intervalBetween, cancel);

                        downloadBps_32 = downloadResult_32.Select(x => x.BpsDownload).OrderByDescending(x => x).FirstOrDefault();
                    }
                    catch (Exception ex)
                    {
                        ex._Debug();
                    }
                    try
                    {
                        var uploadResult_32 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 32, span, SpeedTestModeFlag.Upload, numTry, intervalBetween, cancel);

                        uploadBps_32 = uploadResult_32.Select(x => x.BpsUpload).OrderByDescending(x => x).FirstOrDefault();
                    }
                    catch (Exception ex)
                    {
                        ex._Debug();
                    }


                    //try
                    //{
                    //    var downloadResult_1 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 1, span, SpeedTestModeFlag.Download, numTry, intervalBetween, cancel);

                    //    downloadBps_1 = downloadResult_1.Select(x => x.BpsDownload).OrderByDescending(x => x).FirstOrDefault();
                    //}
                    //catch (Exception ex)
                    //{
                    //    ex._Debug();
                    //}


                    //try
                    //{
                    //    var uploadResult_1 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 1, span, SpeedTestModeFlag.Upload, numTry, intervalBetween, cancel);

                    //    uploadBps_1 = uploadResult_1.Select(x => x.BpsUpload).OrderByDescending(x => x).FirstOrDefault();
                    //}
                    //catch (Exception ex)
                    //{
                    //    ex._Debug();
                    //}
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }

                ret.TryAdd($"{alias} - RX (Mbps)", ((double)downloadBps_32 / 1000.0 / 1000.0).ToString("F3"));
                ret.TryAdd($"{alias} - TX (Mbps)", ((double)uploadBps_32 / 1000.0 / 1000.0).ToString("F3"));

                //ret.TryAdd($"{alias} - 01_RX (Mbps)", ((double)downloadBps_1 / 1000.0 / 1000.0).ToString("F3"));
                //ret.TryAdd($"{alias} - 01_TX (Mbps)", ((double)uploadBps_1 / 1000.0 / 1000.0).ToString("F3"));
            }
        }
        protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
        {
            SnmpWorkSettings settings = Host.Settings;

            if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
            {
                return;
            }

            string hopsStr = "Hops";

            if (settings.HopsToTTL)
            {
                hopsStr = "TTL";
            }

            string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

            numPerform++;

            foreach (string pingTarget in pingTargets)
            {
                cancel.ThrowIfCancellationRequested();

                ParseTargetString(pingTarget, out string hostname, out string alias);

                bool ok = false;

                try
                {
                    IPAddress ipAddress = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                    if (FirstPing.IsFirstCall())
                    {
                        // JIT 対策
                        try
                        {
                            await LocalNet.SendPingAsync(ipAddress, pingCancel : cancel);
                        }
                        catch { }
                    }

                    int numTry = 3;

                    if (numPerform >= 2)
                    {
                        // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
                        await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);

                        // 試行回数を指定する
                        numTry = Math.Min(Math.Max(settings.PingNumTry, 1), 100);
                    }

                    SendPingReply reply = await LocalNet.SendPingAndGetBestResultAsync(ipAddress, pingCancel : cancel, numTry : numTry);

                    if (reply.Ok)
                    {
                        double rtt = reply.RttDouble;

                        rtt = Math.Min(rtt, 2.0);

                        int ttl = reply.Ttl;

                        bool ttl_ok = false;

                        if (ttl == 0)
                        {
                            // Use ping command to get TTL
                            try
                            {
                                var result = await EasyExec.ExecAsync(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6?Consts.LinuxCommands.Ping6 : Consts.LinuxCommands.Ping,
                                                                      $"-W 1 -c 1 {ipAddress.ToString()}",
                                                                      cancel : cancel,
                                                                      throwOnErrorExitCode : false);

                                string[] lines = result.OutputStr._GetLines(true);

                                foreach (string line in lines)
                                {
                                    OneLineParams param  = new OneLineParams(line, ' ', false);
                                    string        ttlStr = param._GetStrFirst("ttl");
                                    if (ttlStr._IsFilled())
                                    {
                                        ttl    = ttlStr._ToInt();
                                        ttl_ok = true;
                                        break;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                ex._Debug();
                            }
                        }
                        else
                        {
                            ttl_ok = true;
                        }

                        ret.TryAdd($"Time - {alias}", (rtt * 1000.0).ToString("F3"));


                        if (ttl > 128)
                        {
                            ttl -= 128;
                        }
                        else if (ttl > 64)
                        {
                            ttl -= 64;
                        }

                        int hops = 64 - ttl;

                        if (ttl_ok == false)
                        {
                            hops = 0;
                        }

                        hops._SetMax(0);
                        hops._SetMin(64);

                        ret.TryAdd($"{hopsStr} - {alias}", hops.ToString());

                        ok = true;
                    }
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }

                if (ok == false)
                {
                    ret.TryAdd($"Time - {alias}", "");
                    ret.TryAdd($"{hopsStr} - {alias}", "0");
                }
            }
        }
        protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
        {
            SnmpWorkSettings settings = Host.Settings;

            if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
            {
                return;
            }

            string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

            KeyValueList <string, IPAddress> kvList = new KeyValueList <string, IPAddress>();

            // 名前解決
            foreach (string pingTarget in pingTargets)
            {
                cancel.ThrowIfCancellationRequested();

                try
                {
                    ParseTargetString(pingTarget, out string hostname, out string alias);

                    IPAddress ip = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                    kvList.Add(alias, ip);
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }
            }

            List <Task <double> > taskList = new List <Task <double> >();

            int interval = 0;
            int count    = 3;

            // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
            numPerform++;
            if (numPerform >= 2)
            {
                interval = settings.PktLossIntervalMsec;
                count    = settings.PktLossTryCount;

                await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);
            }

            // 並列実行の開始
            foreach (var kv in kvList)
            {
                taskList.Add(PerformOneAsync(kv.Value, count, settings.PktLossTimeoutMsecs, interval, cancel));
            }

            // すべて終了するまで待機し、結果を整理
            for (int i = 0; i < kvList.Count; i++)
            {
                var kv   = kvList[i];
                var task = taskList[i];

                double lossRate = await task._TryAwait();

                double quality = 1.0 - lossRate;

                quality = Math.Max(quality, 0.0);
                quality = Math.Min(quality, 1.0);

                ret.TryAdd($"{kv.Key}", ((double)quality * 100.0).ToString("F3"));
            }
        }