618 views
in System Integration by
Hi All,

 I'm trying to get data moving out of my native() JS for Websockets. I have an socket.onmessage event function. But the native() is exited before the passed variables are stuffed by this event.

I thought I should maybe call my associated update {}Method from within the socket.onmessage. However, putting "var device = EmWiApp._GetAutoObject( EmWiApp.Application.DeviceObject );" at the start of my native() produces a "EmWi error: TypeError: Cannot read property '_variants' of undefined!"

What's the correct way to handle server sent MessageEvents in Javascript?
by

[Option1]

This is the more elegant option. 

Use Init{} to open the websocket connection, as you don't want a new socket for each query when the timer goes off.

Setup a DriverTimer timer object, at some rate, say 1 second. This calls a slot method, getDriverData, that runs native javascript code to do a websocket.send() and then setup the websocket.onmessage() handler:

// javascript locals       
var float ref_co2;

native(ref_co2)
{
	// plumb access to the EW Device object (dont specify a class!) so we can run its {}Methods
    var device = EmWiApp._GetAutoObject( EmWiApp.Application.Device );

	ws.binaryType = "arraybuffer";
	ws.send("websocket_command");

	ws.onmessage = function(evt) {
		  onMessage(evt);
	};

	function onMessage(evt) {   
		var data = evt.data;
		var dv = new DataView(data);      
	    
		ref_co2 = dv.getFloat32(0);
      
        
  		device.IRGA_update(ref_co2); // this launches the EW method once the event handler stuffs these variables
        EmWiApp._RequestUpdate();    // JS runs outside GUI, so let GUI know to update
	}
}

 

by

[Option 2]

Use a secondary timer that monitors a flag that the websocket.onmessage() handler sets. Run this at say 10ms.

DriverTimer's onEvent 'getDriverData' {}Slot is now as follows:


native()
{
    flag = 0;

	ws.binaryType = "arraybuffer";
	ws.send("websocket_command");

	ws.onmessage = function(evt) {
		  onMessage(evt);
	};

	function onMessage(evt) {   
		var data = evt.data;
		var dv = new DataView(data);      
	    
		ref_co2 = dv.getFloat32(0);    
        
  		flag = 1;
	}
}

 

Note we dont pass any locals into the native(). They have to be defined as javascript globals using an Inline block, otherwise they wont be available in both slots for each timer.

The secondary timer monitor, which looks for a flag that indicates these globals were stuffed, launches a WebsocketProcessor slot. This slot moves the javascript vars, now with data, into Chora locals to then be sent into an update {}method:

// locals
var int8 l_flag = 0;
var float l_ref_co2; 

native(l_ref_co2)
{    
  // websocket.onmessage() event handler just filled our global vars, so stuff locals     
  l_flag = flag;
  l_ref_co2 = ref_co2;

  flag = 0;
}


// websocket.onmessage() event handler just filled our global vars, so pass locals on
if(l_flag == 1)
{
  IRGA_update(l_ref_co2);
}

 

1 Answer

0 votes
by

Hello,

are you sure the names Application and DeviceObject are valid? I have tried similar and the error occurs when I address an object with not existing name. Just check your Embedded Wizard project if there is an autoobject DeviceObject within the unit Application.

If the object really exists, maybe it has been eliminated during the code generation. Thus check also the attribute Generator of this autoobject. It should be true.

Does it help you further?

Best regards

Paul Banach

by

That was it. My DeviceClass is using the default DeviceClass name. But the example code uses DeviceObject for some reason?!

That said I did figure out a less eligant way to handle 'slow' websocket MessageHandler events. I'll spell out the two options below. Hopefully this saves someone else some time.

 

by

As Paul was kind enough to point out in another thread this is erronious as well. I needed to specify an Object not a Class as such:

 var device = EmWiApp._GetAutoObject( EmWiApp.Application.Device );

and also issue a GUI update in the JS native() since it runs outside the GUI:

 EmWiApp._RequestUpdate();  // JS runs outside GUI, so let GUI know to update

 

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...