Exemple #1
0
        public static void Main(string[] args)
        {
            string sampleNamespaceId = "WaveData_SampleNamespace";
            string sampleTypeId = "WaveData_SampleType";
            string sampleStreamId = "WaveData_SampleStream";
            string sampleBehaviorId = "WaveData_SampleBehavior";

            Console.WriteLine("Creating a .NET Qi Administration Service...");
            IQiAdministrationService qiAdministrationService = GetQiAdministrationService();

            Console.WriteLine("Creating a .NET Qi Metadata Service...");
            IQiMetadataService qiMetadataService = GetQiMetadataService(sampleNamespaceId);

            Console.WriteLine("Creating a .NET Qi Data Service...");
            IQiDataService qiDataService = GetQiDataService(sampleNamespaceId);

            try
            {
                // Create a QiNamespace to hold the streams, types, and behaviors
                Console.WriteLine("Creating a QiNamespace to hold the streams, types, and behaviors");
                QiNamespace sampleNamespace = new QiNamespace(sampleNamespaceId);
                sampleNamespace = qiAdministrationService.GetOrCreateNamespaceAsync(sampleNamespace).GetAwaiter().GetResult();
                
                DelayForQiConsistency();

                // Create a Qi Type to reflect the event data being stored in Qi.
                // The Qi Client Libraries provide QiTypeBuilder which constructs a QiType object 
                // based upon a class you define in your code.  
                Console.WriteLine("Creating a Qi type for WaveData instances");
                QiTypeBuilder typeBuilder = new QiTypeBuilder();
                QiType sampleType = typeBuilder.Create<WaveData>();
                sampleType.Id = sampleTypeId;
                sampleType = qiMetadataService.GetOrCreateTypeAsync(sampleType).GetAwaiter().GetResult();

                DelayForQiConsistency();

                // now let's create the stream to contain the events
                // specify the type id of the QiType created above in the TypeId property of the QiStream object
                // All events submitted to this stream must be of this type
                Console.WriteLine("Creating a stream for simple event measurements");
                QiStream sampleStream = new QiStream()
                {
                    Name = "Wave Data Sample Stream",
                    Id = sampleStreamId,
                    TypeId = sampleTypeId,
                    Description = "This is a sample QiStream for storing WaveData type measurements"
                };

                sampleStream = qiMetadataService.GetOrCreateStreamAsync(sampleStream).GetAwaiter().GetResult();

                DelayForQiConsistency();

                #region CRUD Operations

                #region Create Events (Insert)

                Console.WriteLine("Artificially generating 100 events and inserting them into the Qi Service");

                // Insert a single event into a stream
                TimeSpan span = new TimeSpan(0, 1, 0);
                WaveData waveDataEvent = WaveData.Next(span, 2.0, 0);

                Console.WriteLine("Inserting the first event");
                qiDataService.InsertValueAsync(sampleStreamId, waveDataEvent).GetAwaiter().GetResult();

                // Inserting a collection of events into a stream
                List<WaveData> waveDataEvents = new List<WaveData>();
                for (int i = 2; i < 200; i += 2)
                {
                    waveDataEvent = WaveData.Next(span, 2.0, i);
                    waveDataEvents.Add(waveDataEvent);
                }

                Console.WriteLine("Inserting the rest of the events");
                qiDataService.InsertValuesAsync(sampleStreamId, waveDataEvents).GetAwaiter().GetResult();

                DelayForQiConsistency();

                #endregion

                #region Retrieve events for a time range

                // use the round trip formatting for time
                Console.WriteLine("Retrieving the inserted events");
                Console.WriteLine("==============================");
                IEnumerable<WaveData> foundEvents = qiDataService.GetWindowValuesAsync<WaveData>(sampleStreamId, "0", "198").GetAwaiter().GetResult();
                DumpEvents(foundEvents);
                #endregion

                #region Update an event

                Console.WriteLine();
                Console.WriteLine("Updating the first event");

                // take the first value inserted and update the value using a multiplier of 4, while retaining the order
                waveDataEvent = foundEvents.First();
                waveDataEvent = WaveData.Next(span, 4.0, waveDataEvent.Order);
                qiDataService.UpdateValueAsync(sampleStreamId, waveDataEvent).GetAwaiter().GetResult();

                // update the collection of events (same span, multiplier of 4, retain order)
                waveDataEvents = new List<WaveData>();
                foreach (WaveData evnt in waveDataEvents)
                {
                    waveDataEvent = WaveData.Next(span, 4.0, evnt.Order);
                    waveDataEvents.Add(waveDataEvent);
                }

                Console.WriteLine("Updating the rest of the events");
                qiDataService.UpdateValuesAsync(sampleStreamId, waveDataEvents).GetAwaiter().GetResult();

                DelayForQiConsistency();

                Console.WriteLine("Retrieving the updated values");
                Console.WriteLine("=============================");
                foundEvents = qiDataService.GetWindowValuesAsync<WaveData>(sampleStreamId, "0", "198").GetAwaiter().GetResult();
                DumpEvents(foundEvents);

                // illustrate how stream behaviors modify retrieval
                // First, pull three items back with GetRangeValues for range values between events.
                // The default behavior is continuous, so ExactOrCalculated should bring back interpolated values
                Console.WriteLine();
                Console.WriteLine(@"Retrieving three events without a stream behavior");
                foundEvents = qiDataService.GetRangeValuesAsync<WaveData>(sampleStreamId, "1", 0, 3, false, QiBoundaryType.ExactOrCalculated).GetAwaiter().GetResult();
                DumpEvents(foundEvents);

                // now, create a stream behavior with Discrete and attach it to the existing stream
                Console.WriteLine("Creating a QiStreamBehavior");
                QiStreamBehavior sampleBehavior = new QiStreamBehavior()
                {
                    Id = sampleBehaviorId,
                    Mode = QiStreamMode.StepwiseContinuousLeading
                };
                sampleBehavior = qiMetadataService.GetOrCreateBehaviorAsync(sampleBehavior).GetAwaiter().GetResult();

                DelayForQiConsistency();

                // update the stream to include this behavior
                Console.WriteLine("Updating the QiStream with the new QiStreamBehaivor");
                sampleStream.BehaviorId = sampleBehaviorId;
                qiMetadataService.UpdateStreamAsync(sampleStreamId, sampleStream).GetAwaiter().GetResult();

                DelayForQiConsistency();

                // repeat the retrieval
                Console.WriteLine();
                Console.WriteLine("Retrieving three events with a stepwise stream behavior in effect -- compare to last retrieval");
                foundEvents = qiDataService.GetRangeValuesAsync<WaveData>(sampleStreamId, "1", 0, 3, false, QiBoundaryType.ExactOrCalculated).GetAwaiter().GetResult();
                DumpEvents(foundEvents);

                #endregion

                #region Delete events

                Console.WriteLine();
                Console.WriteLine("Deleting first event");
                qiDataService.RemoveValueAsync(sampleStreamId, 0).GetAwaiter().GetResult();
                Console.WriteLine("Deleting the rest of the events");
                qiDataService.RemoveWindowValuesAsync(sampleStreamId, 2, 198).GetAwaiter().GetResult();

                DelayForQiConsistency();

                Console.WriteLine("Checking for events");
                Console.WriteLine("===================");
                foundEvents = qiDataService.GetWindowValuesAsync<WaveData>(sampleStreamId, "0", "198").GetAwaiter().GetResult();
                DumpEvents(foundEvents);
                Console.WriteLine("Test ran successfully");
                Console.WriteLine("====================");
                Console.WriteLine("Press any button to shutdown");
                Console.ReadLine();

                #endregion
                
                #endregion
            }
            catch (QiHttpClientException qerr)
            {
                PrintError("Error in Qi Service", qerr);
            }
            catch (Exception ex)
            {
                PrintError("Unknown Error", ex);
            }
            finally
            {
                // clean up all created entities so you can run this again
                // all entities are reference counted, so you must delete the stream, then the type it uses
                Console.WriteLine("Deleting the stream...");
                HandleQiCallAsync(async () => await qiMetadataService.DeleteStreamAsync(sampleStreamId)).GetAwaiter().GetResult();

                Console.WriteLine("Deleting the behavior...");
                HandleQiCallAsync(async () => await qiMetadataService.DeleteBehaviorAsync(sampleBehaviorId)).GetAwaiter().GetResult();

                Console.WriteLine("Deleting the type...");
                HandleQiCallAsync(async () => await qiMetadataService.DeleteTypeAsync(sampleTypeId)).GetAwaiter().GetResult();
            }
        }
Exemple #2
0
        private static void Main(string[] args)
        {
            // ==== Client constants ====
            var tenant   = ConfigurationManager.AppSettings["Tenant"];
            var address  = ConfigurationManager.AppSettings["Address"];
            var resource = ConfigurationManager.AppSettings["Resource"];
            var appId    = ConfigurationManager.AppSettings["AppId"];
            var appKey   = ConfigurationManager.AppSettings["AppKey"];

            var namespaceId = ConfigurationManager.AppSettings["Namespace"];

            // ==== Setup the namespace.  The namespace provides isolation within a Tenant. ====
            var admin = QiService.GetAdministrationService(new Uri(address), tenant, new QiSecurityHandler(resource, tenant, appId, appKey));

            var sampleNamespace = new QiNamespace(namespaceId);

            sampleNamespace = admin.GetOrCreateNamespaceAsync(sampleNamespace).GetAwaiter().GetResult();

            // ==== Setup the type and stream ====
            var config = QiService.GetMetadataService(new Uri(address), tenant, namespaceId, new QiSecurityHandler(resource, tenant, appId, appKey));

            QiType type = QiTypeBuilder.CreateQiType <WaveData>();

            type = config.GetOrCreateTypeAsync(type).GetAwaiter().GetResult();

            var stream = new QiStream
            {
                Id          = Guid.NewGuid().ToString(),
                Name        = "Wave Data Sample",
                TypeId      = type.Id,
                Description = "This is a sample QiStream for storing WaveData type measurements"
            };

            stream = config.GetOrCreateStreamAsync(stream).GetAwaiter().GetResult();

            // ==== Perform a number of CRUD opreations ====
            var client = QiService.GetDataService(new Uri(address), tenant, namespaceId, new QiSecurityHandler(resource, tenant, appId, appKey));

            // Insert a single event into a stream
            var wave = GetWave(0, 200, 2);

            client.InsertValueAsync(stream.Id, wave).GetAwaiter().GetResult();

            // Update will add the event as well
            wave.Order += 1;
            client.UpdateValueAsync(stream.Id, wave).GetAwaiter().GetResult();

            // Inserting a collection of events into a stream (more efficient)
            var waves = new List <WaveData>();

            for (var i = 2; i <= 200; ++i)
            {
                waves.Add(GetWave(i, 200, 2));
            }

            client.InsertValuesAsync(stream.Id, waves).GetAwaiter().GetResult();

            // Retrieve events for a the range.  Indexes are expected in string format.  Order property is is the Key
            IEnumerable <WaveData> retrieved = client.GetWindowValuesAsync <WaveData>(stream.Id, "0", "200").GetAwaiter().GetResult();

            Console.WriteLine("Retrieved {0} events", retrieved.Count());
            Console.WriteLine("\tfrom {0} {1}", retrieved.First().Order, retrieved.First().Sin);
            Console.WriteLine("\tto {0} {1}", retrieved.Last().Order, retrieved.Last().Sin);

            // Update some events
            UpdateWave(retrieved.First(), 4);
            client.UpdateValueAsync(stream.Id, retrieved.First()).GetAwaiter().GetResult();

            foreach (var value in waves)
            {
                UpdateWave(value, 4);
            }

            client.UpdateValuesAsync(stream.Id, waves.ToList()).GetAwaiter().GetResult();

            retrieved = client.GetWindowValuesAsync <WaveData>(stream.Id, "0", "200").GetAwaiter().GetResult();
            Console.WriteLine("Updated {0} events", retrieved.Count());
            Console.WriteLine("\tfrom {0} {1}", retrieved.First().Order, retrieved.First().Sin);
            Console.WriteLine("\tto {0} {1}", retrieved.Last().Order, retrieved.Last().Sin);

            // Stream behaviors modify retrieval
            // Retrieve a range of three values using the default behavior.  The default behavior is Continuous,
            // so ExactOrCalculated should bring back interpolated values
            retrieved = client.GetRangeValuesAsync <WaveData>(stream.Id, "1", 0, 3, false, QiBoundaryType.ExactOrCalculated).GetAwaiter().GetResult();
            Console.WriteLine("Default behavior {0} events", retrieved.Count());
            foreach (var value in retrieved)
            {
                Console.WriteLine("\t{0} {1}", value.Order, value.Sin);
            }

            // Modify the stream behavior to StepwiseContinuousLeading
            var stepwiseContinuousLeading = new QiStreamBehavior
            {
                Id   = Guid.NewGuid().ToString(),
                Mode = QiStreamMode.StepwiseContinuousLeading
            };

            stepwiseContinuousLeading = config.GetOrCreateBehaviorAsync(stepwiseContinuousLeading).GetAwaiter().GetResult();

            stream.BehaviorId = stepwiseContinuousLeading.Id;
            config.UpdateStreamAsync(stream.Id, stream).GetAwaiter().GetResult();

            retrieved = client.GetRangeValuesAsync <WaveData>(stream.Id, "1", 0, 3, false, QiBoundaryType.ExactOrCalculated).GetAwaiter().GetResult();
            Console.WriteLine("StepwiseContinuousLeading behavior {0} events", retrieved.Count());
            foreach (var value in retrieved)
            {
                Console.WriteLine("\t{0} {1}", value.Order, value.Sin);
            }

            // Delete the first event in the stream, the event at index zero
            client.RemoveValueAsync(stream.Id, 0).GetAwaiter().GetResult();

            // Delete the rest of the Events
            client.RemoveWindowValuesAsync(stream.Id, 1, 200).GetAwaiter().GetResult();

            retrieved = client.GetWindowValuesAsync <WaveData>(stream.Id, "0", "200").GetAwaiter().GetResult();
            Console.WriteLine("After delete {0} events remain", retrieved.Count());

            // Delete the stream and behavior
            config.DeleteStreamAsync(stream.Id).GetAwaiter().GetResult();
            config.DeleteBehaviorAsync(stepwiseContinuousLeading.Id).GetAwaiter().GetResult();

            // It is less common to remove the type and namespace
            config.DeleteTypeAsync(type.Id).GetAwaiter().GetResult();
            // admin.DeleteNamespaceAsync(sampleNamespace.Id).GetAwaiter().GetResult();
        }
Exemple #3
0
        private static void Main(string[] args)
        {
            // ==== Create the client ====
            var tenant    = ConfigurationManager.AppSettings["Tenant"];
            var address   = ConfigurationManager.AppSettings["Address"];
            var aadFormat = ConfigurationManager.AppSettings["AADInstanceFormat"];
            var resource  = ConfigurationManager.AppSettings["Resource"];
            var appId     = ConfigurationManager.AppSettings["AppId"];
            var appKey    = ConfigurationManager.AppSettings["AppKey"];

            // A formal client should be wrapped in a retry handler.
            HttpClient client = HttpClientFactory.Create(new WebRequestHandler(),
                                                         new AuthenticationHandler(resource, tenant, aadFormat, appId, appKey));

            client.BaseAddress = new Uri(address);

            // ==== Get or create the namespace, type and stream(s) ====
            var space = new QiNamespace()
            {
                Id = ConfigurationManager.AppSettings["Namespace"]
            };
            HttpResponseMessage response = client.GetAsync($"Qi/{tenant}/Namespaces/{space.Id}").GetAwaiter().GetResult();

            if (response.StatusCode == HttpStatusCode.NotFound)
            {
                response = client.PostAsJsonAsync($"Qi/{tenant}/Namespaces", space).GetAwaiter().GetResult();
            }
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            var type = QiTypeBuilder.CreateQiType <WaveData>();

            response = client.GetAsync($"Qi/{tenant}/{space.Id}/Types/{type.Id}").GetAwaiter().GetResult();
            if (response.StatusCode == HttpStatusCode.NotFound)
            {
                response = client.PostAsJsonAsync($"Qi/{tenant}/{space.Id}/Types", type).GetAwaiter().GetResult();
            }
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            var stream = new QiStream()
            {
                Id          = Guid.NewGuid().ToString(),
                Name        = typeof(WaveData).Name,
                Description = "Sample",
                TypeId      = type.Id
            };

            response = client.GetAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}").GetAwaiter().GetResult();
            if (response.StatusCode == HttpStatusCode.NotFound)
            {
                response = client.PostAsJsonAsync($"Qi/{tenant}/{space.Id}/Streams", stream).GetAwaiter().GetResult();
            }
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            // ==== Perform basic CRUD optations ====

            // insert a single event
            var wave = GetWave(0, 200, 2);

            response =
                client.PutAsJsonAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/UpdateValue", wave)
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            // Insert another single event using a Post instead of a Put
            wave.Order += 1;
            response    =
                client.PostAsJsonAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/InsertValue", wave)
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            // Insert a collection of events
            var events = new List <WaveData>();

            for (var i = 2; i <= 200; i += 2)
            {
                events.Add(GetWave(i, 200, 2));
            }

            response =
                client.PostAsJsonAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/InsertValues", events)
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            // retrieve the newly inserted events
            response =
                client.GetAsync(
                    $"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/GetValues?startIndex={0}&endIndex={200}&count={100}")
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }
            var retrievedEvents = response.Content.ReadAsAsync <WaveData[]>().GetAwaiter().GetResult();

            // Update the events
            Array.ForEach(retrievedEvents, w => GetWave(w.Order, 200, 3));
            response =
                client.PutAsJsonAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/UpdateValues", events)
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            // ==== Clean up ====

            // It's not necessary to delete the values if you're deleting the stream
            response =
                client.DeleteAsync(
                    $"Qi/{tenant}/{space.Id}/Streams/{stream.Id}/Data/RemoveWindowValues?startIndex={0}&endIndex={200}")
                .GetAwaiter()
                .GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }

            response = client.DeleteAsync($"Qi/{tenant}/{space.Id}/Streams/{stream.Id}").GetAwaiter().GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }
            response = client.DeleteAsync($"Qi/{tenant}/{space.Id}/Types/{type.Id}").GetAwaiter().GetResult();
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpResponseException(response);
            }
        }