static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args); /* * Open a session and subscribe to a couple of topics. Once * subscribed, the server will begin to queue messages published * to these topics. They remain queued until read by the session. */ Console.WriteLine("Opening message read session..."); using (var readSession = MessageSession.Open(configuration)) { readSession.Subscribe("example.data"); readSession.Subscribe("example.exit"); /* * The read session will receive all messages for the the * subscribed topics, but not the message for the unknown * topic. The messages are read in order they are queued on the * server regardless of topic. There may be a small delay * between the message being published and it being queued and * available for reading. */ PublishMessages(configuration); Console.WriteLine("Message queue size: {0} of {1} bytes", readSession.QueueSize, readSession.MaxQueueSize); Console.WriteLine("Reading back messages..."); bool receivedExitMessage = false; while (!receivedExitMessage) { /* * Blocks until a message is available in the queue or a * brief amount of time has passed. Returns null when there * are no queued messages. */ var message = readSession.Read(); receivedExitMessage = HandleMessage(message); } /* * The server will discard any remaining queued messages when * disposing the session. */ Console.WriteLine("Remaining bytes in the message queue: {0}", readSession.QueueSize); } }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args, allowCloud: false); /* * Open a session and subscribe to a topic. Once subscribed, the * server will begin to queue messages published by Host.vi. */ Console.WriteLine("Opening message session..."); int messagesSent; int messagesReceived; using (var session = MessageSession.Open(configuration)) using (var exitSource = new CancellationTokenSource()) { session.Subscribe("Example to Client"); /* * Set up a CancelKeyPress handler to clean up the session * when pressing Ctrl+C to stop the example. The handler will * cancel our CancellationTokenSource, signalling our async * loops to stop. */ Console.CancelKeyPress += (s, e) => { if (e.SpecialKey == ConsoleSpecialKey.ControlBreak) { // Allow Ctrl+Break to terminate the process. return; } exitSource.Cancel(); Console.WriteLine("Stopping..."); e.Cancel = true; }; /* * Begin asynchronous tasks to read and publish messages until * the token is canceled, then wait for the tasks to complete. */ var mainLoopTask = RunLoopsAsync(session, exitSource.Token); (messagesSent, messagesReceived) = mainLoopTask.Result; } Console.WriteLine("Message session closed"); Console.WriteLine("Published {0} and received {1} messages", messagesSent, messagesReceived); }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args, allowCloud: false); /* * Create the TestDataManager for communicating with the server. */ var testDataManager = new TestDataManager(configuration); // Initialize a ResultData object. var resultData = new ResultData() { Operator = "John Smith", ProgramName = "File Attachment Test", Status = new Status(StatusType.Running), SerialNumber = Guid.NewGuid().ToString(), PartNumber = "NI-ABC-234-FILE", FileIds = new List <string>() }; // Create the test result on the SystemLink server. var testResult = testDataManager.CreateResult(resultData); // Upload some sample data as the file contents. var fileId = UploadFileData( configuration, "stream.txt", Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); // Add the file ID to the test result's list of attached files. resultData.FileIds.Add(fileId); // Set the test result status to done. resultData.Status = new Status(StatusType.Done); // Update the test result on the SystemLink server. testResult.Update(resultData); }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args, false); // Use the FileUploader for communicating with the server. var fileUploader = new FileUploader(configuration); var fileName = "stream.txt"; var fileContents = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); // Use in-memory data for the file upload. using (var memoryStream = new MemoryStream(fileContents)) { // Upload the file to the SystemLink server and get the ID of the uploaded file. var fileId = fileUploader.UploadFile(memoryStream, fileName); } }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args); /* * Create the TestDataManager for communicating with the server. */ var testDataManager = new TestDataManager(configuration); // Intialize the random number generator. var random = new Random(); // Set test limits var lowLimit = 0; var highLimit = 70; // Initialize a ResultData object. var resultData = new ResultData() { Operator = "John Smith", ProgramName = "Power Test", Status = new Status(StatusType.Running), SerialNumber = Guid.NewGuid().ToString(), PartNumber = "NI-ABC-123-PWR" }; // Create the test result on the SystemLink server. var testResult = testDataManager.CreateResult(resultData); // Automatically sync the result's runtime with its test steps. testResult.AutoUpdateTotalTime = true; /* * Simulate a sweep across a range of electrical current and voltage. * For each value, calculate the electrical power (P=IV). */ for (var current = 0; current < 10; current++) { // Generate a parent step to represent a sweep of voltages at a given current. var voltageSweepStepData = GenerateStepData("Voltage Sweep", "SequenceCall"); // Create the step on the SystemLink server. var voltageSweepStep = testResult.CreateStep(voltageSweepStepData); for (var voltage = 0; voltage < 10; voltage++) { // Simulate obtaining a power measurement. var(power, inputs, outputs) = MeasurePower(current, voltage); // Test the power measurement. var status = (power <lowLimit || power> highLimit) ? new Status(StatusType.Failed) : new Status(StatusType.Passed); var testParameters = BuildPowerMeasurementParams(power, lowLimit, highLimit, status); // Generate a child step to represent the power output measurement. var measurePowerOutputStepData = GenerateStepData( "Measure Power Output", "NumericLimit", inputs, outputs, testParameters, status); // Create the step on the SystemLink server. var measurePowerOutputStep = voltageSweepStep.CreateStep(measurePowerOutputStepData); // If a test in the sweep fails, the entire sweep failed. Mark the parent step accordingly. if (status.StatusType == StatusType.Failed) { voltageSweepStepData.Status = new Status(StatusType.Failed); // Update the parent test step's status on the SystemLink server. voltageSweepStep.Update(voltageSweepStepData); } } // If none of the child steps failed, mark the step as passed. if (voltageSweepStepData.Status.StatusType == StatusType.Running) { voltageSweepStepData.Status = new Status(StatusType.Passed); // Update the test step's status on the SystemLink server. voltageSweepStep.Update(voltageSweepStepData); } } // Update the top-level test result's status based on the most severe child step's status. testResult = testResult.DetermineStatusFromSteps(); }
static void Main(string[] args) { try { /* * When SystemLink Server is installed locally, or when running * on a system managed by a SystemLink Server, the * HttpConfigurationManager provides access to an automatic * configuration to communicate with the SystemLink Server. */ var manager = new HttpConfigurationManager(); var autoConfiguration = manager.GetConfiguration(); Console.WriteLine("Found automatic configuration for {0}", autoConfiguration.ServerUri); /* * Each class that takes in a configuration also has a default * constructor that uses the automatic configuration instead. */ using (var autoManager = new TagManager()) { } } catch (ApiException ex) { Console.WriteLine("Automatic configuration: {0}", ex.Message); } /* * When an automatic configuration isn't available (often during * application development) the HttpConfiguration class can * reference any SystemLink Server available over HTTP/HTTPS. * * Ideally, the username and password would be read from the user at * run time or from a file rather than checked into source. */ var serverConfiguration = new HttpConfiguration( new Uri("https://myserver"), "my_user", "my_password"); /* * To access SystemLink Cloud instead of a SystemLink Server * installation, log into https://www.systemlinkcloud.com and * generate an API key. Then use that API key with the * CloudHttpConfiguration class. * * Ideally, the API key would be read from a file or otherwise * protected rather than checked into source. */ var cloudConfiguration = new CloudHttpConfiguration("apikey"); /* * Configurations are shared across all SystemLink client APIs. */ var exampleConfiguration = ExampleConfiguration.Obtain(args); using (var manager = new TagManager(exampleConfiguration)) using (var session = MessageSession.Open(exampleConfiguration)) { } /* * Mixing configurations enables applications to synchronize data * across multiple servers and/or SystemLink Cloud. */ using (var cloudManager = new TagManager(cloudConfiguration)) using (var serverManager = new TagManager(serverConfiguration)) { } // See the tag and message API examples for specific usage. }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args); /* * Create the TagManager for communicating with the server. */ using (var manager = new TagManager(configuration)) { Console.WriteLine("Creating example tags..."); var createdTags = CreateTags(manager); Console.WriteLine(); WriteHeader(); Console.WriteLine("Retrieving tags..."); /* * Each created tag has an example property. We can query for * all tags with that property to retrieve only our tags. * Using a take value of five means each "page" of results will * only contain at most five tags before returning to the * server to retrieve more. */ var queryProperties = new Dictionary <string, string> { ["example"] = "query" }; var query = manager.Query(null, null, queryProperties, 0, 5); int tagsRead = 0; /* * Each iteration over the query result returns a single page * of results. Initially, only the first page is populated and * each iteration after the first results in a new request to * the server to populate the next page. */ foreach (var page in query) { // Overwrite the "Retrieving tags" indicator. Console.SetCursorPosition(0, Console.CursorTop - 1); if (tagsRead > 0 && tagsRead % 20 == 0) { WriteHeader(); } /* * Iterating over a page of query results gives the metadata * for each tag in the page. We output a row for each one. */ foreach (var tag in page) { ++tagsRead; var keywords = string.Join(", ", tag.Keywords); var properties = string.Join(", ", tag.Properties.Select(p => p.Key + "=" + p.Value)); Console.WriteLine(RowFormat, tag.Path, tag.DataType, keywords, properties); } Console.WriteLine(); /* * The TotalCount property indicates how many tags matched * the query, so we can determine if there are more pages. */ if (tagsRead >= query.TotalCount) { // There are no more pages; the foreach should exit. Console.WriteLine("{0}/{1} tags", tagsRead, query.TotalCount); } else if (!PromptForNextPage(tagsRead, query.TotalCount)) { // The user canceled early. break; } } Console.WriteLine(); Console.WriteLine("Deleting example tags..."); manager.Delete(createdTags); } }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args); /* * Create the TagManager for communicating with the server and the * tag writer for sending tag values to the server. */ using (var manager = new TagManager(configuration)) using (var writer = manager.CreateWriter(bufferSize: 10)) { /* * Initially create two tags and write values to them. Using * Update enables creating both tags in a single API call. */ var doubleTag = new TagData("example.selection.double", DataType.Double); var intTag = new TagData("example.selection.int", DataType.Int32); // Currently, SystemLink Server does not return tag values in // selections for tags that do not collect aggregates. doubleTag.CollectAggregates = intTag.CollectAggregates = true; Console.WriteLine("Creating example tags..."); manager.Update(new[] { doubleTag, intTag }); var doubleWriter = new DoubleTagValueWriter(writer, doubleTag); var intWriter = new Int32TagValueWriter(writer, intTag); doubleWriter.Write(Math.PI); intWriter.Write((int)Math.PI); writer.SendBufferedWrites(); /* * Create a selection containing all tags whose paths begin * with our example prefix. */ Console.WriteLine("Creating selection..."); using (var selection = manager.Open(new[] { "example.selection.*" })) { /* * Read each tag value. Since we're using a selection, this * only results in a single request to the server. */ var doubleReader = selection.Values[doubleTag.Path] as DoubleTagValueReader; var intReader = selection.Values[intTag.Path] as Int32TagValueReader; Console.WriteLine("Double tag value: {0}", doubleReader?.Read()); Console.WriteLine("Int tag value: {0}", intReader?.Read()); /* * Create two more example tags and edit the metadata for * the original example tags in a single API call. */ var boolTag = new TagData("example.selection.bool", DataType.Bool, keywords: new[] { "new" }, properties: null); var stringTag = new TagData("example.selection.string", DataType.String, keywords: new[] { "new" }, properties: null); // Currently, SystemLink Server does not return tag values in // selections for tags that do not collect aggregates. boolTag.CollectAggregates = stringTag.CollectAggregates = true; Console.WriteLine("Creating additional tags..."); manager.Update(new[] { new TagDataUpdate(boolTag, TagUpdateFields.All), new TagDataUpdate(stringTag, TagUpdateFields.All), new TagDataUpdate(doubleTag.Path, DataType.Double, keywords: new[] { "edited" }, properties: null), new TagDataUpdate(intTag.Path, DataType.Int32, keywords: new[] { "edited" }, properties: null) }); var boolWriter = new BoolTagValueWriter(writer, boolTag); var stringWriter = new StringTagValueWriter(writer, stringTag); doubleWriter.Write(Math.E); intWriter.Write((int)Math.E); boolWriter.Write(true); stringWriter.Write("example"); writer.SendBufferedWrites(); /* * Selections don't automatically update with changes made * on the server. Iterating over all tags in the selection * will only see the first two tags in their original state. */ OutputSelection(selection); /* * Refreshing the selection will update with changes made * on the server. We have the option to refresh only the * metadata, only the values, or both metadata and values. * Refreshing the values will detect new tags on the server * but will not retrieve keywords and properties. */ Console.WriteLine("Refreshing selection values..."); selection.RefreshValues(); OutputSelection(selection); /* * A metadata refresh will get keywords and properties. */ Console.WriteLine("Refreshing selection metadata..."); selection.RefreshMetadata(); OutputSelection(selection); /* * Selections also enable deleting multiple tags from the * server in a single request. */ Console.WriteLine("Deleting example tags..."); selection.DeleteTagsFromServer(); } } }
static void Main(string[] args) { /* * See the configuration example for how a typical application * might obtain a configuration. */ var configuration = ExampleConfiguration.Obtain(args); /* * Create the TagManager for communicating with the server and the * tag writer for sending tag values to the server. */ using (var manager = new TagManager(configuration)) using (var writer = manager.CreateWriter(NumTags * 2)) { /* * Create two tags. Make one a double and the other an int. * Using Update enables creating both tags in a single API call. */ var doubleTag = new TagData("example.subscription.double", DataType.Double); var intTag = new TagData("example.subscription.int", DataType.Int32); Console.WriteLine("Creating example tags..."); manager.Update(new[] { doubleTag, intTag }); var doubleWriter = new DoubleTagValueWriter(writer, doubleTag); var intWriter = new Int32TagValueWriter(writer, intTag); using (var selection = manager.CreateSelection(doubleTag, intTag)) { try { /* * Subscribe to receive events when the current values * of the tags change. */ Console.WriteLine("Subscribing to tag value changes..."); using (var subscription = selection.CreateSubscription()) using (var handler = new TagChangedHandler(subscription)) { /* * Write to each tag and send them to the server. */ Console.WriteLine("Writing tag values (1/2)..."); doubleWriter.Write(Math.PI); intWriter.Write((int)Math.PI); writer.SendBufferedWrites(); /* * Wait for our subscription to receive each value. * There may be a delay between the value changing * on the server and the event firing. */ if (!handler.WaitForNotifications(NumTags, TimeSpan.FromSeconds(10))) { Console.WriteLine("Did not receive all tag writes"); return; } /* * Subscriptions only receive the latest value when * multiple writes to the same tag occur in a short * period of time. */ Console.WriteLine("Writing tag values (2/2)..."); doubleWriter.Write(Math.E); doubleWriter.Write(12.123); intWriter.Write((int)Math.E); intWriter.Write(12); // Writes are sent automatically due to buffer size. if (!handler.WaitForNotifications(NumTags * 2, TimeSpan.FromSeconds(10))) { Console.WriteLine("Did not receive all tag writes"); return; } /* * Disposing of the subscription will unsubscribe. */ Console.WriteLine("Unsubscribing..."); } } finally { Console.WriteLine("Deleting example tags..."); selection.DeleteTagsFromServer(); } } } }