This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
Possible: yes. However, it requires a bit of javascript coding. Thus depending on your comfort level with javascript it may be an option. I have put together a trivial example with hard coded array data to demonstrate how to setup & configure the graph. The main thing that you would then need to do is get the data from your target device and add a function that sets that data for your graph. In the example below, when you click on the app to run it, there will be a Readme pop up with some further instructions.
martin
It may depend which widget you used in your application design. The example is specific to Plot type widget. If you used a Line Graph widget then those properties would not work. Plot has more advanced capabilities but it is harder to use as it requires a bit of javascript to set values for it, rather than just adding bindings to global variables or json objects.
Martin
Hi Jed,
You would need to combine couple of examples that I am referring to below.
1. First example (youtube video) shows how to add functions in javascript that allow you to pre or post process the data that is received/sent to the device. You would not be doing any data processing in this case, but you would use this function to update the plot widget.
2. Second example shows how to update plot widget with data. You can run it from Gallery, but to see how works, you would import it into GUI Composer Designer and follow instructions that are shown in pop up when your first run it. The example is hard coded to show specific set of data, but in summary you would use solution shown in #1 to add functions and instead of processing, you would set the plot widgets data fields with your data.
Hi Martin,
I'm attempting to replicate the example shown in the video, except i'm getting the data from my target device. Shown below is what I typed into my javascript file, which isn't working. Could you explain why? I want to grab the variable Gui_VSet1 and have it display in ti_widget_numberbox1.
Thank You.
gc.databind.registry.bind('ti_widget_numberbox1.value',
// dependant bindings needed in order to compute the date, in name/value pairs.
"my_xds.Gui_VSet1.value",
function (value) {
// compute and return the string value to bind to the widget with id 'date'
return value;
}
);
Hi Jed,
I think your target variable needs to be just "my_xds.Gui_VSet1", the entry after my_xds needs to be exactly what you would add to expression view to watch that variable. GC will automatically create a "value" variable, assign to it the data that is obtained from the target and pass it to the function.
Martin
Please see attached mockup.js file that I tweaked, I added a few comments to attempt to explain what the code does. Please let me know if it is unclear. The plot graph only works with arrays rather than single values, thus I created couple of javascript arrays one for x and another for y. X array is just initialized with fixed data from 0-199. Y array holds the data from my target variable. In the callback function I also call the function that sets the data for the plot and then calls the redraw.
martin
/* * gc global variable provides access to GUI Composer infrastructure components and project information. * For more information, please see the Working with Javascript guide in the online help. */ var gc = gc || {}; gc.services = gc.services || {}; //varaibles to store data var dataBuffer = []; var xAxis_Buffer = []; var BUFFER_SIZE = 200; /* * Boilerplate code for creating computed data bindings */ document.addEventListener('gc-databind-ready', function() { /* * Add custom computed value databindings here, using the following method: * * function gc.databind.registry.bind(targetBinding, modelBinding, [getter], [setter]); * * param targetBinding - single binding string or expression, or array of binding strings for multi-way binding. * param modelBinding - single binding string or expression, or array of binding strings for multi-way binding. * param getter - (optional) - custom getter function for computing the targetBinding value(s) based on modelBinding value(s). * param setter - (optional) - custom setter function for computing the modelBinding value(s) based on targetBinding value(s). */ // For example, a simple computed values based on simple expression // gc.databind.registry.bind('widget.id.propertyName', "targetVariable == 1 ? 'binding is one' : 'binding is not one'"); // Or a custom two-way binding with custome getter and setter functions. (setter is optional) (getter only indicates one-way binding) // gc.databind.registry.bind('widget.id.propertyName', "targetVariable", function(value) { return value*5/9 + 32; }, function(value) { (return value-32)*9/5; }); // Event 1 to n bindings gc.databind.registry.bind('ti_widget_plot_touchtrace.data[0].y', "MY_TEST_VAR", // getter for date computation function(value) { //first fill data buffer with values from MY_TEST_VAR global variable. if (dataBuffer < BUFFER_SIZE) { dataBuffer.push(value); xAxis_Buffer.push(dataBuffer.length); //fill x axis buffer with values from 0-199 } else { //once buffer is full remove first element dataBuffer.shift(); //append new value dataBuffer.push(value); } // call function to plots x and y data and redraw the graph onSim(dataBuffer) return value; } ); }); /* * Boilerplate code for creating custom actions */ document.addEventListener('gc-nav-ready', function() { /* * Add custom actions for menu items using the following api: * * function gc.nav.registryAction(id, runable, [isAvailable], [isVisible]); * * param id - uniquely identifies the action, and should correspond to the action property of the menuaction widget. * param runable - function that performs the custom action. * param isAvailable - (optional) - function called when the menu action is about to appear. Return false to disable the action, or true to enable it. * param isVisible - (optional) - function called when the menu action is about to appear. Return false to hide the action, or true to make it visible. */ // For example, // gc.nav.registerAction('myCustomCloseAction', function() { window.close(); }, function() { return true; }, function() { return true; }); // Alternatively, to programmatically disable a menu action at any time use: // gc.nav.disableAction('myCustomCloseAction); then enable it again using: gc.nav.enableAction('myCustomCloseAction'); }); /* * Boilerplate code for working with components in the application gist */ var initComplete = false; var templateObj; // Wait for DOMContentLoaded event before trying to access the application template var init = function() { templateObj = document.querySelector('#template_obj'); // Wait for the template to fire a dom-change event to indicate that it has been 'stamped' // before trying to access components in the application. templateObj.addEventListener('dom-change',function(){ if (initComplete) return; this.async(function(){ initComplete = true; console.log("Application template has been stamped."); // Now that the template has been stamped, you can use 'automatic node finding' $ syntax to access widgets. // e.g. to access a widget with an id of 'widget_id' you can use templateObj.$.widgetId },1); }); }; templateObj = document.querySelector('#template_obj'); if (templateObj) { init(); } else { document.addEventListener('DOMContentLoaded',init.bind(this)) } var onSim = function(data) { // say somehow I get the x and y data if (templateObj) { templateObj.$.ti_widget_plot_touchtrace.data[0].y=data; templateObj.$.ti_widget_plot_touchtrace.data[0].x=xAxis_Buffer; templateObj.$.ti_widget_plot_touchtrace.redraw(); } };