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.

CCS/LAUNCHXL-F28379D: problem with loggin data in gui composer V2

Part Number: LAUNCHXL-F28379D


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))
}

  • Hello Diego, 

    I think you need to ensure that if (templateObj.$.ti_widget_droplist....)  does what you are expecting it. I would check whether you .gui file has "ti_widget_droplist" widget and whether the value is set to what you are expecting. I would suggest that you open the debugger and step through your code. See link below for some help on how to do this. After you open debugger, press CTRL+P and enter the file name where you are making these code changes, i.e. "newfile_0.js", you should then be able to set a breakpoint in this function to see what it is doing. 

    martin

     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;
            }
        );