/// <summary>
        /// Requests the current data from the server.
        /// </summary>
        private CurData RequestCurData(IList <int> cnlNums, long cnlListID, bool useCache)
        {
            int cnlCnt = cnlNums == null ? 0 : cnlNums.Count;

            CurDataRecord[] records = new CurDataRecord[cnlCnt];
            CurData         curData = new()
            {
                ServerTime = TimeRecord.Create(DateTime.UtcNow, userContext.TimeZone),
                Records    = records,
                CnlListID  = "0"
            };

            if (cnlCnt > 0)
            {
                CnlData[] cnlDataArr = cnlListID > 0
                    ? clientAccessor.ScadaClient.GetCurrentData(ref cnlListID)
                    : clientAccessor.ScadaClient.GetCurrentData(cnlNums.ToArray(), useCache, out cnlListID);
                curData.CnlListID = cnlListID.ToString();
                CnlDataFormatter formatter = CreateFormatter();

                for (int i = 0; i < cnlCnt; i++)
                {
                    int     cnlNum  = cnlNums[i];
                    CnlData cnlData = i < cnlDataArr.Length ? cnlDataArr[i] : CnlData.Empty;

                    records[i] = new CurDataRecord
                    {
                        D  = new CurDataPoint(cnlNum, cnlData),
                        Df = formatter.FormatCnlData(cnlData, cnlNum, false)
                    };
                }
            }

            return(curData);
        }
        /// <summary>
        /// Requests historical data from the server.
        /// </summary>
        private HistData RequestHistData(int archiveBit, TimeRange timeRange, IList <int> cnlNums)
        {
            if (cnlNums == null)
            {
                cnlNums = Array.Empty <int>();
            }

            int cnlCnt = cnlNums.Count;

            HistData.RecordList[] trends = new HistData.RecordList[cnlCnt];

            HistData histData = new()
            {
                CnlNums    = cnlNums,
                Timestamps = Array.Empty <TimeRecord>(),
                Trends     = trends
            };

            if (cnlCnt > 0)
            {
                // request trends
                TrendBundle trendBundle = clientAccessor.ScadaClient.GetTrends(
                    archiveBit, timeRange, cnlNums.ToArray());

                // copy timestamps
                int          pointCount = trendBundle.Timestamps.Count;
                TimeRecord[] timestamps = new TimeRecord[pointCount];
                histData.Timestamps = timestamps;

                for (int i = 0; i < pointCount; i++)
                {
                    timestamps[i] = TimeRecord.Create(trendBundle.Timestamps[i], userContext.TimeZone);
                }

                // copy channel data
                CnlDataFormatter formatter = CreateFormatter();

                for (int cnlIdx = 0; cnlIdx < cnlCnt; cnlIdx++)
                {
                    int cnlNum = cnlNums[cnlIdx];
                    Cnl cnl    = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum);
                    HistData.RecordList     records     = trends[cnlIdx] = new(pointCount);
                    TrendBundle.CnlDataList cnlDataList = trendBundle.Trends[cnlIdx];

                    for (int ptIdx = 0; ptIdx < pointCount; ptIdx++)
                    {
                        CnlData cnlData = cnlDataList[ptIdx];
                        records.Add(new HistDataRecord
                        {
                            D  = cnlData,
                            Df = formatter.FormatCnlData(cnlData, cnl, false)
                        });
                    }
                }
            }

            return(histData);
        }