public BrowseResultsEntry[] FlatBrowse(OpcUaClient client, string nodeToBrowse = objectsNode)
        {
            List <BrowseResultsEntry> browseResults = new List <BrowseResultsEntry>();

            foreach (ReferenceDescription entry in client.BrowseNodeReference(nodeToBrowse))
            {
                BrowseResultsEntry bre = new BrowseResultsEntry();
                log.Information("Processing entry {0}", JsonSerializer.Serialize <ReferenceDescription>(entry));
                if (entry.NodeClass == NodeClass.Variable)
                {
                    bre.displayName = entry.DisplayName.ToString();
                    bre.browseName  = entry.BrowseName.ToString();
                    bre.nodeId      = entry.NodeId.ToString();
                    browseResults.Add(bre);
                }
                browseResults.AddRange(FlatBrowse(client, entry.NodeId.ToString()));
            }

            return(browseResults.ToArray());
        }
        public async override Task <DatasourceResponse> Query(DatasourceRequest request, ServerCallContext context)
        {
            DatasourceResponse response = new DatasourceResponse {
            };

            try
            {
                log.Information("got a request: {0}", request);
                List <OpcUAQuery> queries  = ParseJSONQueries(request);
                OpcUaJsonData     jsonData = JsonSerializer.Deserialize <OpcUaJsonData>(request.Datasource.JsonData);
                OpcUaClient       client   = GetClient(request, jsonData);
                log.Information("got a client {0}", client);

                // Process the queries
                foreach (OpcUAQuery query in queries)
                {
                    QueryResult queryResult = new QueryResult();
                    queryResult.RefId = query.refId;
                    switch (query.call)
                    {
                    case "Browse":
                    {
                        log.Information("client {0}", client);
                        var results = client.BrowseNodeReference(query.callParams["nodeId"]);
                        BrowseResultsEntry[] browseResults = new BrowseResultsEntry[results.Length];
                        for (int i = 0; i < results.Length; i++)
                        {
                            browseResults[i] = new BrowseResultsEntry(results[i].DisplayName.ToString(), results[i].BrowseName.ToString(), results[i].NodeId.ToString());
                        }
                        var jsonResults = JsonSerializer.Serialize <BrowseResultsEntry[]>(browseResults);
                        queryResult.MetaJson = jsonResults;
                    }
                    break;

                    case "FlatBrowse":
                    {
                        if (this.browseResults == null)
                        {
                            var browseResults = this.FlatBrowse(client);
                            var jsonResults   = JsonSerializer.Serialize <BrowseResultsEntry[]>(browseResults);
                            this.browseResults = jsonResults;
                        }
                        queryResult.MetaJson = this.browseResults;
                    }
                    break;

                    case "ReadNode":
                    {
                        log.Information("ReadNode {0}", query.callParams["nodeId"]);
                        var readResults = client.ReadNode(query.callParams["nodeId"]);
                        log.Information("Results: {0}", readResults);
                        var jsonResults = JsonSerializer.Serialize <DataValue>(readResults);
                        queryResult.MetaJson = jsonResults;
                    }
                    break;

/*                        case "Subscription":
 *                          {
 *                              client.AddSubscription(query.refId, query.callParams["nodeId"], SubCallback);
 *                              queryResult.MetaJson = "";
 *                          }
 *                          break;*/
                    case "ReadDataRaw":
                    {
                        log.Information("Query: {0}", request.TimeRange);
                        DateTime fromTime = DateTimeOffset.FromUnixTimeMilliseconds(request.TimeRange.FromEpochMs).UtcDateTime;
                        DateTime toTime   = DateTimeOffset.FromUnixTimeMilliseconds(request.TimeRange.ToEpochMs).UtcDateTime;
                        log.Information("Parsed Time: {0} {1}", fromTime, toTime);

                        var readResults = client.ReadHistoryRawDataValues(
                            query.callParams["nodeId"],
                            fromTime,
                            toTime,
                            (uint)query.maxDataPoints,
                            false);

                        var jsonResults = JsonSerializer.Serialize <IEnumerable <DataValue> >(readResults);
                        queryResult.MetaJson = jsonResults;
                    }
                    break;

                    case "ReadDataProcessed":
                    {
                        DateTime fromTime    = DateTimeOffset.FromUnixTimeMilliseconds(request.TimeRange.FromEpochMs).UtcDateTime;
                        DateTime toTime      = DateTimeOffset.FromUnixTimeMilliseconds(request.TimeRange.ToEpochMs).UtcDateTime;
                        var      readResults = client.ReadHistoryProcessed(
                            query.callParams["nodeId"],
                            fromTime,
                            toTime,
                            query.callParams["aggregate"],
                            query.intervalMs,
                            (uint)query.maxDataPoints,
                            true);
                        var jsonResults = JsonSerializer.Serialize <IEnumerable <DataValue> >(readResults);
                        log.Information("Results: {0}", readResults);
                        queryResult.MetaJson = jsonResults;
                    }
                    break;
                    }
                    response.Results.Add(queryResult);
                }
            }
            catch (Exception ex)
            {
                // Close out the client connection.
                clientConnections[request.Datasource.Url].Disconnect();
                clientConnections.Remove(request.Datasource.Url);
                log.Information("Error: {0}", ex);
                QueryResult queryResult = new QueryResult();
                queryResult.Error = ex.ToString();
                response.Results.Add(queryResult);
            }

            return(response);
        }