{"id":29298,"date":"2022-08-23T00:56:42","date_gmt":"2022-08-23T07:56:42","guid":{"rendered":"https:\/\/digilent.com\/blog\/?p=29298"},"modified":"2022-08-23T00:56:42","modified_gmt":"2022-08-23T07:56:42","slug":"reading-generated-data-in-a-real-time-distributed-system-part-3","status":"publish","type":"post","link":"https:\/\/digilent.com\/blog\/reading-generated-data-in-a-real-time-distributed-system-part-3\/","title":{"rendered":"Reading Generated Data in a Real-Time Distributed System &#8211; Part 3"},"content":{"rendered":"<h2><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.digilent.com\/blog\/wp-content\/uploads\/2022\/08\/2022-ReadingGeneratedData-part3-580.png\" alt=\"\" width=\"580\" height=\"290\" class=\"aligncenter size-full wp-image-29326\" data-wp-pid=\"29326\" \/><\/h2>\n<h2>Creating an Application to View Data with VB.NET<\/h2>\n<p><span>In Part 2, we created a working application to read telemetry from sensors connected to a\u00a0<\/span><a href=\"https:\/\/www.mccdaq.com\/usb-data-acquisition\/USB-2408-Series.aspx\"><span onmouseover=\"ikb_showGlossaryToopTip(20);\" class=\"glossaryToolTip\">USB-2408<\/span><\/a><span>, write the telemetry or data to the screen in various ways, and write it out to the database we created in Part 1.<\/span><\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/reading-generated-data-in-a-real-time-distributed-system-part-1\/\">Part 1 &#8211; Setting Up an MS Database<\/a><\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/reading-generated-data-in-a-real-time-distributed-system-part-2\/\">Part 2 &#8211; Creating an Application to Collect and Pass Data<\/a><\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/reading-generated-data-in-a-real-time-distributed-system-part-4\/\">Part 4 &#8211; Distributing Applications<\/a><\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/reading-generated-data-in-a-real-time-distributed-system-part-5\/\">Part 5 &#8211; Using Additional Software Packages<\/a><\/p>\n<p style=\"font-weight: 400;\">Now, in Part 3, we will create the application to read the data back out of the database.\u00a0 It will be a mirror image of the part 2 application, but no data is collected here it will just show what was collected and stored to the database. \u00a0It will operate like dual ported memory.\u00a0 This is all in preparation for the next part where we will distribute the two applications so as to have one application (DataCollectionToDatabase) on one computer, and the other app (DatabaseToDataDisplay) on another computer in a different part of the building.<\/p>\n<p style=\"font-weight: 400;\">Again, launch Visual Basic, and start a new project.\u00a0 We will call it \u201cDatabaseToDataDisplay.\u201d\u00a0 Resize your form to 639, 358.<\/p>\n<p style=\"font-weight: 400;\">Add a MenuStrip, DataGridView, Timer, OpenFileDialog, Thermometer, 2 AnalogMeters, an LED, 2 buttons, and 7 labels.\u00a0 Rearrange and resize the objects so that your form design looks like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/10-Form-Design.png\" alt=\"\" width=\"593\" height=\"498\" class=\"aligncenter size-full wp-image-29295\" data-wp-pid=\"29295\" \/><\/p>\n<p>Change the following properties:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/11-Properties.png\" alt=\"\" width=\"428\" height=\"429\" class=\"aligncenter size-full wp-image-29296\" data-wp-pid=\"29296\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/11-Properties.png 428w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/11-Properties-150x150.png 150w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/11-Properties-300x300-cropped.png 300w\" sizes=\"auto, (max-width: 428px) 100vw, 428px\" \/><\/p>\n<p style=\"font-weight: 400;\">Of all the labels, only 2 need to be renamed:<\/p>\n<p style=\"font-weight: 400;\">The one under the thermometer:\u00a0 lblTempValue<\/p>\n<p style=\"font-weight: 400;\">The one to the right of Time:\u00a0 lblTime<\/p>\n<p style=\"font-weight: 400;\">All labels should be set to Autosize = True<\/p>\n<p style=\"font-weight: 400;\">From the Solution explorer, right click on Form1.vb, and select View Code.\u00a0 Above<span>\u00a0<\/span>Public<span>\u00a0<\/span>Class<span>\u00a0<\/span>Form1<span>\u00a0<\/span>insert the following:<\/p>\n<blockquote>\n<p style=\"font-weight: 400;\">ImportsSystem.Data.OleDb<\/p>\n<p style=\"font-weight: 400;\">ImportsSystem.Runtime.InteropServices<\/p>\n<p style=\"font-weight: 400;\">ImportsSystem.IO<\/p>\n<\/blockquote>\n<p style=\"font-weight: 400;\">Next, add the variable declarations:<\/p>\n<blockquote>\n<p style=\"font-weight: 400;\">&#8216;For database<\/p>\n<p style=\"font-weight: 400;\">DimsConnectionStringAsString<\/p>\n<p style=\"font-weight: 400;\">PublicobjConnAsNewOleDbConnection()<\/p>\n<p style=\"font-weight: 400;\">DimdsAsNewDataSet()<\/p>\n<p style=\"font-weight: 400;\">DimdaAsOleDb.OleDbDataAdapter<\/p>\n<p style=\"font-weight: 400;\">DimsqlAsString<\/p>\n<\/blockquote>\n<h2>Open the External Database and Read in the Data<\/h2>\n<p style=\"font-weight: 400;\">There is a lot less going on in this application, just about all of it in happening in the Timer, so open the Timer1_Tick() event, and paste in the following:<\/p>\n<blockquote>\n<p style=\"font-weight: 400;\">Try\u00a0&#8216;This goes out to the database<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 &#8216;How to open an oleDB data base<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 sConnectionString =&#8221;Provider=Microsoft.Jet.OLEDB.4.0;Data\u00a0 Source=c:\\Users\\Public\\Documents\\MCCGenericOdbc.mdb&#8221;\u00a0\u00a0&#8216;for oleDB<\/p>\n<p style=\"font-weight: 400;\">\u00a0\u00a0\u00a0 objConn =\u00a0NewOleDbConnection(sConnectionString)<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 objConn.Open()<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 &#8216;Obtain a DataRow object from the DataTable.<\/p>\n<p style=\"font-weight: 400;\">\u00a0\u00a0\u00a0 da =NewOleDb.OleDbDataAdapter(&#8220;SELECT * FROM TestData&#8221;, objConn)<\/p>\n<p style=\"font-weight: 400;\">\u00a0\u00a0\u00a0 da.FillSchema(ds,SchemaType.Source,&#8221;TestData&#8221;)<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 da.Fill(ds,&#8221;TestData&#8221;)<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 objConn.Close()<\/p>\n<p style=\"font-weight: 400;\">CatchexAsOleDbException<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Timer1.Enabled =False<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 objConn.Close()<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 MsgBox(ex.Message.ToString(),MsgBoxStyle.Information,&#8221;Error Message&#8221;)<\/p>\n<p style=\"font-weight: 400;\">EndTry<\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"font-weight: 400;\">Try<\/p>\n<p style=\"font-weight: 400;\">\u00a0\u00a0\u00a0DimMyDataScan = ds.Tables(&#8220;TestData&#8221;).Rows(0)<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 lblTime.Text = MyDataScan(1).ToString<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Thermometer1.TempValue =Convert.ToDouble(MyDataScan(2))<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 lblTempValue.Text = MyDataScan(2).ToString +&#8221;\u00b0C&#8221;<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 amPressure.Value =Convert.ToDouble(MyDataScan(3))<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 amTach.Value =Convert.ToDouble(MyDataScan(4)\/ 100)<\/p>\n<p style=\"font-weight: 400;\">\u00a0\u00a0\u00a0DimrAsBoolean=Convert.ToBoolean(Val(MyDataScan(5)))<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Led1.Value = r<\/p>\n<p style=\"font-weight: 400;\">CatchexAsOleDbException<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Timer1.Enabled =False<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 MsgBox(ex.Message.ToString(),MsgBoxStyle.Information,&#8221;Error Message&#8221;)<\/p>\n<p style=\"font-weight: 400;\">EndTry<\/p>\n<\/blockquote>\n<p style=\"font-weight: 400;\">As with the previous app, we want to open the database.\u00a0 But now we want to obtain existing data from the TestData table. When we read in the entire table we use the Fill Schema and Fill commands.\u00a0 Read in the first row from the table and parse it (Dim<span>\u00a0<\/span>MyDataScan = ds.Tables(&#8220;TestData&#8221;).Rows(0)).\u00a0 The data will automatically be placed into the array, \u2018MyDataScan()\u2019 for dissemination to the various labels and objects in this application.\u00a0 All the data is stored as strings, so there are data conversions going on in the code above.<\/p>\n<p style=\"font-weight: 400;\">The app could come up running, but for now let\u2019s use a Start\/Stop button, and so from the Form View, double click on \u201cStart\u201d button, and add the following to the btnStartStop_Click() event:<\/p>\n<blockquote>\n<p style=\"font-weight: 400;\">IfbtnStartStop.Text =&#8221;Start&#8221;Then<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 btnStartStop.Text =&#8221;Stop&#8221;<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Timer1.Enabled =True<\/p>\n<p style=\"font-weight: 400;\">Else<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 btnStartStop.Text =&#8221;Start&#8221;<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 Timer1.Enabled =False<\/p>\n<p style=\"font-weight: 400;\">\u00a0 \u00a0 objConn.Close()<\/p>\n<p style=\"font-weight: 400;\">EndIf<\/p>\n<\/blockquote>\n<p style=\"font-weight: 400;\">The If\/Then\/Else above, alternates the Text property of the button between \u2018Start\u2019 and \u2018Stop\u2019, but when IF condition is true we also enable or start the timer.\u00a0 When the IF condition is false, we stop the timer, and close the link to the data base.<\/p>\n<p style=\"font-weight: 400;\">Add a graceful way to exit the program:<\/p>\n<p style=\"font-weight: 400;\">From the Form view, regarding the MenuStrip1, click on<span>\u00a0<\/span><strong>File<\/strong>, and then double click on<span>\u00a0<\/span><strong>Exit<\/strong>, and add the following code:<\/p>\n<blockquote>\n<p style=\"font-weight: 400;\">Timer1.Enabled =False<\/p>\n<p style=\"font-weight: 400;\">End<\/p>\n<\/blockquote>\n<p style=\"font-weight: 400;\">Because this is Windows, and there is always more than one way to do anything, go back to the Form view, double click on the<span>\u00a0<\/span><strong>End<span>\u00a0<\/span><\/strong>button, and paste the same syntax there.<\/p>\n<p style=\"font-weight: 400;\">We are still missing a couple items, but that is as far as we need to go for this section.<\/p>\n<p style=\"font-weight: 400;\">The two applications are now complete.\u00a0 Let\u2019s run both of them from within the VisualBasic.NET environments.\u00a0 Here is what they look like, running in concert:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/14-VB-Environments-492x600.png\" alt=\"\" width=\"492\" height=\"600\" class=\"aligncenter size-medium wp-image-29300\" data-wp-pid=\"29300\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/14-VB-Environments-492x600.png 492w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/14-VB-Environments.png 642w\" sizes=\"auto, (max-width: 492px) 100vw, 492px\" \/><\/p>\n<p><span>Despite the different types of meters used in the two applications, you can see the two applications are sharing the data.\u00a0 What you can\u2019t see, is the top app is sending data to table \u201cTestData\u201d of database \u201cMccGenericOdbc.mdb\u201d, and the bottom app is reading data from the\u00a0<\/span><span>table \u201cTestData\u201d of database \u201cMccGenericOdbc.mdb\u201d<\/span><span>. Since the two apps are running their own timers, data reads and writes are happening \u2018on demand.\u2019 For these applications, the data is one second delayed, which is why the data on the two forms is not exactly the same. There will always be some delay due to timers, Windows OS, and network traffic.<\/span><\/p>\n<div class='watch-action'><div class='watch-position align-left'><div class='action-like'><a class='lbg-style6 like-29298 jlk' data-task='like' data-post_id='29298' data-nonce='ee750c7abc' rel='nofollow'><img src='https:\/\/digilent.com\/blog\/wp-content\/plugins\/wti-like-post-pro\/images\/pixel.gif' title='Like' \/><span class='lc-29298 lc'>0<\/span><\/a><\/div><div class='action-unlike'><a class='unlbg-style6 unlike-29298 jlk' data-task='unlike' data-post_id='29298' data-nonce='ee750c7abc' rel='nofollow'><img src='https:\/\/digilent.com\/blog\/wp-content\/plugins\/wti-like-post-pro\/images\/pixel.gif' title='Unlike' \/><span class='unlc-29298 unlc'>0<\/span><\/a><\/div><\/div> <div class='status-29298 status align-left'>Be the 1st to vote.<\/div><\/div><div class='wti-clear'><\/div>","protected":false},"excerpt":{"rendered":"<p>Creating an Application to View Data with VB.NET In Part 2, we created a working application to read telemetry from sensors connected to a\u00a0USB-2408, write the telemetry or data to &hellip; <\/p>\n","protected":false},"author":59,"featured_media":29339,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4325,4361,1563],"tags":[4359,4358],"ppma_author":[4507],"class_list":["post-29298","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-debug-validation-test","category-data-acquisition","category-guide","tag-daq","tag-mcc"],"jetpack_featured_media_url":"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2022\/08\/2022-ReadingGeneratedData2-part3-580.png","authors":[{"term_id":4507,"user_id":59,"is_guest":0,"slug":"jgreenberg","display_name":"Jeff Greenberg","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/7d7c29970e5c0f9f3acaf605ee106bd6?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Greenberg","last_name_2":"","first_name":"Jeff","first_name_2":"","job_title":"","description":""}],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/29298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/users\/59"}],"replies":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/comments?post=29298"}],"version-history":[{"count":1,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/29298\/revisions"}],"predecessor-version":[{"id":29475,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/29298\/revisions\/29475"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/media\/29339"}],"wp:attachment":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/media?parent=29298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/categories?post=29298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/tags?post=29298"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=29298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}