private static void PrintViewMapProperties(SdsViewMap sdsViewMap) { foreach (var prop in sdsViewMap.Properties) { if (prop.TargetId != null) { Console.WriteLine($"{prop.SourceId} => {prop.TargetId}"); } else { Console.WriteLine($"{prop.SourceId} => Not Mapped"); } } Console.WriteLine(); }
private static async Task MainAsync() { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json"); IConfiguration configuration = builder.Build(); // ==== Client constants ==== string tenantId = configuration["TenantId"]; string namespaceId = configuration["NamespaceId"]; string address = configuration["Address"]; string resource = configuration["Resource"]; string clientId = configuration["ClientId"]; string clientKey = configuration["ClientKey"]; string aadInstanceFormat = configuration["AADInstanceFormat"]; // ==== Metadata IDs ==== string StreamId = "WaveStreamId"; string TypeId = "WaveDataTypeId"; string TargetTypeId = "WaveDataTargetTypeId"; string TargetIntTypeId = "WaveDataTargetIntTypeId"; string AutoViewId = "WaveDataAutoViewId"; string ManualViewId = "WaveDataManualViewId"; SdsSecurityHandler securityHandler = new SdsSecurityHandler(resource, tenantId, aadInstanceFormat, clientId, clientKey); HttpClient httpClient = new HttpClient(securityHandler) { BaseAddress = new Uri(address) }; Console.WriteLine(@"-------------------------------------------------------"); Console.WriteLine(@" _________ .___ _____________________ ____________________"); Console.WriteLine(@" / _____/ __| _/_____\______ \_ _____// _____/\__ ___/"); Console.WriteLine(@" \_____ \ / __ |/ ___/| _/| __)_ \_____ \ | | "); Console.WriteLine(@" / \/ /_/ |\___ \ | | \| \/ \ | | "); Console.WriteLine(@"/_______ /\____ /____ >|____|_ /_______ /_______ / |____| "); Console.WriteLine(@" \/ \/ \/ \/ \/ \/ "); Console.WriteLine(@"-------------------------------------------------------"); Console.WriteLine(); Console.WriteLine($"Sds endpoint at {address}"); Console.WriteLine(); try { // create a SdsType Console.WriteLine("Creating a SdsType"); SdsType waveType = BuildWaveDataType(TypeId); HttpResponseMessage response = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{waveType.Id}", new StringContent(JsonConvert.SerializeObject(waveType))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // create a SdsStream Console.WriteLine("Creating a SdsStream"); SdsStream waveStream = new SdsStream { Id = StreamId, Name = "WaveStream", TypeId = waveType.Id }; response = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}", new StringContent(JsonConvert.SerializeObject(waveStream))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // insert data Console.WriteLine("Inserting data"); // insert a single event WaveData wave = GetWave(0, 1, 2.0); response = await httpClient.PostAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/InsertValue", new StringContent(JsonConvert.SerializeObject(wave))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // insert a list of events List <WaveData> waves = new List <WaveData>(); for (int i = 2; i < 20; i += 2) { WaveData newEvent = GetWave(i, 2, 2.0); waves.Add(newEvent); } response = await httpClient.PostAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/InsertValues", new StringContent(JsonConvert.SerializeObject(waves))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(); } // get last event Console.WriteLine("Getting latest event"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetLastValue"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } WaveData retrieved = JsonConvert.DeserializeObject <WaveData>(await response.Content.ReadAsStringAsync()); Console.WriteLine(retrieved.ToString()); Console.WriteLine(); // get all events Console.WriteLine("Getting all events"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetWindowValues?startIndex=0&endIndex={waves[waves.Count - 1].Order}"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } List <WaveData> retrievedList = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); Console.WriteLine($"Total events found: {retrievedList.Count}"); foreach (var evnt in retrievedList) { Console.WriteLine(evnt.ToString()); } Console.WriteLine(); // update events Console.WriteLine("Updating events"); // update one event var updateEvent = retrieved; updateEvent.Sin = 1 / 2.0; updateEvent.Cos = Math.Sqrt(3) / 2; updateEvent.Tan = 1; response = await httpClient.PutAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/UpdateValue", new StringContent(JsonConvert.SerializeObject(updateEvent))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // update all events, adding ten more List <WaveData> updateWaves = new List <WaveData>(); for (int i = 0; i < 40; i += 2) { WaveData newEvent = GetWave(i, 4, 6.0); updateWaves.Add(newEvent); } response = await httpClient.PutAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/UpdateValues", new StringContent(JsonConvert.SerializeObject(updateWaves))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } Console.WriteLine("Getting updated events"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetWindowValues?startIndex={updateWaves[0].Order}&endIndex={updateWaves[updateWaves.Count - 1].Order}"); retrievedList = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); Console.WriteLine($"Total events found: {retrievedList.Count}"); foreach (var evnt in retrievedList) { Console.WriteLine(evnt.ToString()); } Console.WriteLine(); // replacing events Console.WriteLine("Replacing events"); // replace one event var replaceEvent = retrievedList[0]; replaceEvent.Sin = 4 * (Math.Sqrt(2) / 2); replaceEvent.Cos = 4 * (Math.Sqrt(2) / 2); replaceEvent.Tan = 4; response = await httpClient.PutAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/ReplaceValue", new StringContent(JsonConvert.SerializeObject(replaceEvent))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // replace all events var replaceEvents = retrievedList; foreach (var evnt in replaceEvents) { evnt.Sin = 6 * (Math.Sqrt(2) / 2); evnt.Cos = 6 * (Math.Sqrt(2) / 2); evnt.Tan = 6; } response = await httpClient.PutAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/ReplaceValues", new StringContent(JsonConvert.SerializeObject(replaceEvents))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } Console.WriteLine("Getting replaced events"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetWindowValues?startIndex={updateWaves[0].Order}&endIndex={updateWaves[updateWaves.Count - 1].Order}"); retrievedList = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); Console.WriteLine($"Total events found: {retrievedList.Count}"); foreach (var evnt in retrievedList) { Console.WriteLine(evnt.ToString()); } Console.WriteLine(); // Property Overrides Console.WriteLine("Property Overrides"); Console.WriteLine("Sds can interpolate or extrapolate data at an index location where data does not explicitly exist:"); Console.WriteLine(); // We will retrieve three events using the default behavior, Continuous response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetRangeValues?startIndex={1}&count={3}&boundaryType={SdsBoundaryType.ExactOrCalculated}"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } List <WaveData> rangeValuesContinuous = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); Console.WriteLine("Default (Continuous) stream behavior, requesting data starting at index location '1', Sds will interpolate this value:"); foreach (var waveData in rangeValuesContinuous) { Console.WriteLine($"Order: {waveData.Order}, Radians: {waveData.Radians}, Cos: {waveData.Cos}"); } Console.WriteLine(); // Create a Discrete stream PropertyOverride indicating that we do not want Sds to calculate a value for Radians and update our stream SdsStreamPropertyOverride propertyOverride = new SdsStreamPropertyOverride { SdsTypePropertyId = "Radians", InterpolationMode = SdsInterpolationMode.Discrete }; var propertyOverrides = new List <SdsStreamPropertyOverride>() { propertyOverride }; // update the stream waveStream.PropertyOverrides = propertyOverrides; response = await httpClient.PutAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}", new StringContent(JsonConvert.SerializeObject(waveStream))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } Console.WriteLine("We can override this behavior on a property by property basis, here we override the Radians property instructing Sds not to interpolate."); Console.WriteLine("Sds will now return the default value for the data type:"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetRangeValues?startIndex={1}&count={3}&boundaryType={SdsBoundaryType.ExactOrCalculated}"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } List <WaveData> rangeValuesDiscrete = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); foreach (var waveData in rangeValuesDiscrete) { Console.WriteLine($"Order: {waveData.Order}, Radians: {waveData.Radians}, Cos: {waveData.Cos}"); } Console.WriteLine(); // Stream views Console.WriteLine("SdsViews"); // create target types var targetType = BuildWaveDataTargetType(TargetTypeId); var targetIntType = BuildWaveDataTargetIntType(TargetIntTypeId); HttpResponseMessage targetTypeResponse = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{TargetTypeId}", new StringContent(JsonConvert.SerializeObject(targetType))); if (!targetTypeResponse.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } HttpResponseMessage targetIntTypeResponse = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{TargetIntTypeId}", new StringContent(JsonConvert.SerializeObject(targetIntType))); if (!targetIntTypeResponse.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // create views var autoView = new SdsView() { Id = AutoViewId, SourceTypeId = TypeId, TargetTypeId = TargetTypeId }; // create explicit mappings var vp1 = new SdsViewProperty() { SourceId = "Order", TargetId = "OrderTarget" }; var vp2 = new SdsViewProperty() { SourceId = "Sin", TargetId = "SinInt" }; var vp3 = new SdsViewProperty() { SourceId = "Cos", TargetId = "CosInt" }; var vp4 = new SdsViewProperty() { SourceId = "Tan", TargetId = "TanInt" }; var manualView = new SdsView() { Id = ManualViewId, SourceTypeId = TypeId, TargetTypeId = TargetIntTypeId, Properties = new List <SdsViewProperty>() { vp1, vp2, vp3, vp4 } }; response = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{AutoViewId}", new StringContent(JsonConvert.SerializeObject(autoView))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } response = await httpClient.PostAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{ManualViewId}", new StringContent(JsonConvert.SerializeObject(manualView))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } Console.WriteLine("Here is some of our data as it is stored on the server:"); foreach (var evnt in rangeValuesDiscrete) { Console.WriteLine($"Sin: {evnt.Sin}, Cos: {evnt.Cos}, Tan {evnt.Tan}"); } Console.WriteLine(); // get data with autoview response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetRangeValues?startIndex={1}&count={3}&boundaryType={SdsBoundaryType.ExactOrCalculated}&viewId={AutoViewId}"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } List <WaveDataTarget> autoViewData = JsonConvert.DeserializeObject <List <WaveDataTarget> >(await response.Content.ReadAsStringAsync()); Console.WriteLine("Specifying a view with a SdsType of the same shape returns values that are automatically mapped to the target SdsType's properties:"); foreach (var value in autoViewData) { Console.WriteLine($"SinTarget: {value.SinTarget} CosTarget: {value.CosTarget} TanTarget: {value.TanTarget}"); } Console.WriteLine(); Console.WriteLine("SdsViews can also convert certain types of data, here we return integers where the original values were doubles:"); // get data with manualview response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetRangeValues?startIndex={1}&count={3}&boundaryType={SdsBoundaryType.ExactOrCalculated}&viewId={ManualViewId}"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } List <WaveDataInteger> manualViewData = JsonConvert.DeserializeObject <List <WaveDataInteger> >(await response.Content.ReadAsStringAsync()); foreach (var value in manualViewData) { Console.WriteLine($"SinInt: {value.SinInt} CosInt: {value.CosInt} TanInt: {value.TanInt}"); } Console.WriteLine(); // get SdsViewMap Console.WriteLine("We can query Sds to return the SdsViewMap for our SdsView, here is the one generated automatically:"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{AutoViewId}/Map"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } SdsViewMap sdsViewMap = JsonConvert.DeserializeObject <SdsViewMap>(await response.Content.ReadAsStringAsync()); PrintViewMapProperties(sdsViewMap); Console.WriteLine("Here is our explicit mapping, note SdsViewMap will return all properties of the Source Type, even those without a corresponding Target property:"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{ManualViewId}/Map"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } sdsViewMap = JsonConvert.DeserializeObject <SdsViewMap>(await response.Content.ReadAsStringAsync()); PrintViewMapProperties(sdsViewMap); // tags, metadata and search Console.WriteLine("Let's add some Tags and Metadata to our stream:"); var tags = new List <string> { "waves", "periodic", "2018", "validated" }; var metadata = new Dictionary <string, string>() { { "Region", "North America" }, { "Country", "Canada" }, { "Province", "Quebec" } }; response = await httpClient.PutAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Tags", new StringContent(JsonConvert.SerializeObject(tags))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } response = await httpClient.PutAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Metadata", new StringContent(JsonConvert.SerializeObject(metadata))); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Tags"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } tags = JsonConvert.DeserializeObject <List <string> >(await response.Content.ReadAsStringAsync()); Console.WriteLine(); Console.WriteLine($"Tags now associated with {StreamId}:"); foreach (var tag in tags) { Console.WriteLine(tag); } Console.WriteLine(); Console.WriteLine($"Metadata now associated with {StreamId}:"); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Metadata/Region"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } var region = JsonConvert.DeserializeObject <string>(await response.Content.ReadAsStringAsync()); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Metadata/Country"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } var country = JsonConvert.DeserializeObject <string>(await response.Content.ReadAsStringAsync()); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}/Metadata/Province"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } var province = JsonConvert.DeserializeObject <string>(await response.Content.ReadAsStringAsync()); Console.WriteLine("Metadata key Region: " + region); Console.WriteLine("Metadata key Country: " + country); Console.WriteLine("Metadata key Province: " + province); Console.WriteLine(); Console.WriteLine("We can also use our tags to search for streams, let's search for streams tagged with 'periodic':"); Console.WriteLine(); Console.WriteLine("Pausing to allow for search indexing..."); // allow time for search indexing await Task.Delay(15000); response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams?query=periodic"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } var streams = JsonConvert.DeserializeObject <List <SdsStream> >(await response.Content.ReadAsStringAsync()); foreach (var strm in streams) { Console.WriteLine(strm.Id); } Console.WriteLine(); Console.WriteLine("Deleting values from the SdsStream"); // delete one event response = await httpClient.DeleteAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/RemoveValue?index=0"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } // delete all Events response = await httpClient.DeleteAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/RemoveWindowValues?startIndex=0&endIndex=40"); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.ToString()); } response = await httpClient.GetAsync( $"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{waveStream.Id}/Data/GetWindowValues?startIndex=0&endIndex=40"); retrievedList = JsonConvert.DeserializeObject <List <WaveData> >(await response.Content.ReadAsStringAsync()); if (retrievedList.Count == 0) { Console.WriteLine("All values deleted successfully!"); } Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e.Message); } finally { Console.WriteLine("Cleaning up"); // Delete the stream, types and views Console.WriteLine("Deleteing stream"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Streams/{StreamId}"); Console.WriteLine("Deleteing views"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{AutoViewId}"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Views/{ManualViewId}"); Console.WriteLine("Deleteing types"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{TypeId}"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{TargetTypeId}"); await httpClient.DeleteAsync($"api/Tenants/{tenantId}/Namespaces/{namespaceId}/Types/{TargetIntTypeId}"); Console.WriteLine("done"); } Console.ReadKey(); }