Tool/software: Code Composer Studio
hello.
I tried to use the example "XDS_SaveVariableToFile" in gui composer V2, for logging data.
I have copied the program to my guide, I have modified the index by adding the two lines of code.
my variables that I want to logging are
new_B.Fcn_T1
new_B.Fcn_T2
the problem is that when I press save and after stop, it downloads the file "mydata1.txt" but it is always empty.
thank you.
///////////////////////////////////////////////////////// newfile_0.js /////////////////////////////////////////////////////
/* * 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 || {}; // How to use ti-widget-streamsaver // 1. Add <ti-widget-streamsaver> to gui file. // Open index.gui and search ti-widget-streamsaver to see how to add it. There are 2 lines, // <link rel="import" href="../ti-widget-streamsaver/ti-widget-streamsaver.html"> // <ti-widget-streamsaver id="ti_widget_streamsaver" class="_TI_"></ti-widget-streamsaver> // 2. Add a js file and add the following code. The idea is, // (a) use saveStart to create a stream writer, // (b) then use saveData to write data, you can have repeated calls here, see saveDummyData. // If you keep calling saveData, you will find the browser eventually says it is 'downloading' a file. // (c) use saveStop to flush and close the data stream. You will the browser finished 'downloaded' the file. // After this point, you can no longer write data to the stream writer. // (d) In case you want to abort the stream writer, use saveAbort. // After this point, you can no longer write data to the stream writer. // [ Start of code var mystream; var mywriter; //Text Encoder. var myTextEnc = new TextEncoder(); // index.gui file contains: <ti-widget-button id="ti_widget_button" label="Save Start" button-type="default" raised visible tooltip="Create stream writer to start save" bindable-trigger="8" animated elevation="1" onclick="saveStart()" class="_TI_" title="Create stream writer to start save"></ti-widget-button> // which triggers this function being called to create necessary stream objects to be able to stream/write data to a file. var saveStart = function(filename) { if (!filename) filename = 'mydata1.txt'; mystream = streamSaver.createWriteStream(filename); mywriter = mystream.getWriter(); }; // index.gui file contains: <ti-widget-button id="ti_widget_button2" label="Save Stop" button-type="default" raised visible tooltip="Finish save. The stream writer is closed here" bindable-trigger="10" animated elevation="1" onclick="saveStop()" class="_TI_" title="Finish save. The stream writer is closed here"></ti-widget-button> // which triggers this function being called to stop writing to a file and close the stream. var saveStop = function() { if (mywriter) { mywriter.close(); mywriter = null; } }; // index.gui file contains: <ti-widget-button id="ti_widget_button3" label="Save Abort" button-type="default" raised visible tooltip="Abort the stream writer." bindable-trigger="7" animated elevation="1" onclick="saveAbort()" class="_TI_" title="Abort the stream writer."></ti-widget-button> // which triggers this function being called to abort writing to a file. var saveAbort = function() { if (mywriter){ mywriter.abort('reason'); mywriter = null; } }; /* * 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('widget.date.value', // dependant bindings needed in order to compute the date, in name/value pairs. { weekday: 'widget.dayOfWeek.selectedText', day: 'widget.dayOfMonth.value', month: 'widget.month.selectedText', year: 'widget.year.value' }, // getter for date computation function(values) { // compute and return the string value to bind to the widget with id 'date' return values.weekday + ', ' + values.month + ' ' + values.day + ', ' + values.year; } ); */ // Regular bindings on target variables are used to perform some data transformation on data. In this case we are using // these bindings to add additional functionality to save data to a file rather than to do any data transformation, thus // we are returning the same the same unmodified value // // This function is bound to blinkCounter global variable and saves it to a file that is configured when user clicks Start button and // dropdown widget is set to save blinkCounter. gc.databind.registry.bind('widget.ti_widget_textbox10.value',"new_B.Fcn_T1", // getter for date computation function(value) { if (templateObj.$.ti_widget_droplist.selectedValue == "new_B.Fcn_T1" && mywriter) { var encodedData = myTextEnc.encode(value.toString() + '\n'); mywriter.write(encodedData); } // compute and return the string value to bind to the widget with id 'date' return value; } ); // Regular bindings on target variables are used to perform some data transformation on data. In this case we are using // these bindings to add additional functionality to save data to a file rather than to do any data transformation, thus // we are returning the same the same unmodified value // // This function is bound to tablicaArray global variable, which is an array of 10 elements and saves it to a file that is configured when user clicks Start button and // dropdown widget is set to save tablicaArray. gc.databind.registry.bind('ti_widget_scalargraph3.series_0_values',"new_B.Fcn_T2", // getter for date computation function(value) { if (templateObj.$.ti_widget_droplist.selectedValue == "new_B.Fcn_T2" && mywriter) { var encodedData = myTextEnc.encode(value.toString() + '\n'); mywriter.write(encodedData); } // compute and return the string value to bind to the widget with id 'date' 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)) }