Example websocket service in RoboPro Coding

Alles rund um TX(T) und RoboPro, mit ft-Hard- und Software
Computing using original ft hard- and software
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
vleeuwen
Beiträge: 1560
Registriert: 31 Okt 2010, 22:23
Wohnort: Enschede (NL)
Kontaktdaten:

Example websocket service in RoboPro Coding

Beitrag von vleeuwen » 02 Jan 2022, 17:56

A base for the communication between a TXT4.0 and a web browser an example:
1) basic code for the websocket server.
A) The place for your normal code.
2) replacement for the "repeat for ever" Blockly. This because of the asyncio endless loop.
3) the additional imports.
Used technogies: Python, JSON, HTML5 (XML-technology), sockets.

This examples shows how the communication works only. It is up to you to add the right JSON definitions and the communication with the sensors and actuators.
Have fun and happy new year
websocketserver01.JPG
websocketserver01.JPG (106.29 KiB) 2004 mal betrachtet
Under the original RoboPro this kind of low level code is hidden in the RoboPro extension elements.

Program code 1

Code: Alles auswählen

#(c) 2022 C. van Leeuwen 
# Code may be used in whole or in part with this copyright notice.
# Only for non-commercial applications. 
# [2022-01-02]
print('start')
async def server(websocket, path):
    # Get received data from websocket
    print("wait for recv")
    try:
      data = await websocket.recv()
      # Send response back to client to acknowledge receiving message
      print('server: recv raw=' + data)
    except exceptions.ConnectionClosed as e:
      print("exception 01 "+str(e.code)+" ",str(e.reason))
    else:
      try:
        respondsData=""
        mesg1=json.loads(data) #From JSON to Python format
        #mesg=json.dumps(data)
        #mesg=json.dumps(data, indent=4)
        #respondsData=mesg
        #From JSON to Python dictionary format
        dictP=eval(data)   
        print("   ="+ str(dictP))
        t=dictP['actuators']
        print("   ="+ str(dictP['actuators']))
        tt=dictP['actuators']
        print("   ="+str(tt[0]))
        print("   ="+str(tt[1]))
        #print("   ="+str(tt[1]['M']['p'][2]))
        print("   ="+str(tt[1]['S'][2]))
        print("   ="+str(tt[2]))
        respondsData=json.dumps(mesg1)
      except JSONDecodeError as e:
        respondsData="no JSON format "+e.msg+ " pos="+str(e.pos)+" doc="+e.doc
      try:
        #await websocket.send("msg Thanks for your message: " +respondsData)
        await websocket.send( respondsData)
        print("server: send data="+respondsData)
      except exceptions.ConnectionClosed:
        print("exception 02")
      try: 
        await server( websocket, path)
        # print("try empty")
      except exceptions.ConnectionClosed:
        print("exception 03")

print('test1')
# Create websocket server 0.0.0.0 open for external acces, localhost only local
start_server = serve(server, "0.0.0.0", 8085, ssl=None)
print('test2')
# Start and run websocket server forever
loop=asyncio.get_event_loop()
loop.run_until_complete(start_server)
print('test3A')
Program code 2

Code: Alles auswählen

#(c) 2022 C. van Leeuwen 
# Code may be used in whole or in part with this copyright notice.
# Only for non-commercial applications. 
# [2022-01-02]
print('test3B')
# this repplace the normal repeat endless loop from the Blockly,
#  which is not asyncio
loop.run_forever()
print('test4')

Program code 3

Code: Alles auswählen

import asyncio
import time
import subprocess
from json import JSONDecodeError
import json
#from lib.controller import *
from websockets import serve, exceptions
Web page for testing.
Don't forget to replace the IP-address 192.168.20.175 with the actual IP-address of your TXT4.0!!
[2022-01-02 22:45, updated]

Code: Alles auswählen

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<!--(c) 2022 C. van Leeuwen Enschede -->
<head>
  <title>Test</title>
  <script type='text/javascript' language="javascript">
  <!--
  var connection;
  var keepAlive = false;
  var printError = function(error, explicit) {
    console.log(`[${explicit ? 'EXPLICIT' : 'INEXPLICIT'}] ${error.name}: ${error.message}`);
     }
  const jj= '{"actuators":[{"M":{"i":1,"p":[0,0,214,214]}},{"M":{"i":2,"p":[0,0,214,214]}},{"M":{"i":3,"p":[0,0,214,214]}}]}';
  const j={"actuators":[{"M":{"i":1,"p":[0,0,214,214]}},{"S":[0, 6,512]},{"firstName":"Peter","lastName":"Jones"}]};
  //const j=   {"actuators":[{"M":{"i":1,"p":[0,0,214,214]}},{"M":{"i":2,"p":[0,0,214,214]}},{"M":{"i":3,"p":[0,0,214,214]}}]};

 function sendButton1(par1,par2){
     //parameters not is use for the moment
     myJSON=JSON.stringify(j);// to a JSON object
	document.getElementById('msg').innerHTML="Not yet send";
	console.log('sendButton1: ' + myJSON );
	if (typeof connection === 'undefined'){
	 	 console.log('Server: connection is undefined');
	   }else {
	   if (connection.readyState === WebSocket.OPEN){
         connection.send(myJSON);
	    } else {
	 	 console.log('Server: connection closed, state='+connection.readyState);
	    }
    } }
function sendButton2(par1,par2){
    //parameters not is use for the moment
    myJSON=JSON.stringify(j);// to a JSON object
	document.getElementById('msg').innerHTML="Not yet send";
	console.log('sendButton2: ' + myJSON );
	if (typeof connection === 'undefined'){
	 	 console.log('Server: connection is undefined');
	   }else {
	   if (connection.readyState === WebSocket.OPEN){
         connection.send(myJSON);
	    } else {
	 	 console.log('Server: connection closed, state='+connection.readyState);
	    }
    }
  }  
function sendButton3(par1,par2){
     //parameters not is use for the moment
     myJSON=JSON.stringify(j);// to a JSON object
	document.getElementById('msg').innerHTML="Not yet send";
	console.log('sendButton3: ' + myJSON );
	if (typeof connection === 'undefined'){
	 	 console.log('Server: connection is undefined');
	   }else {
	   if (connection.readyState === WebSocket.OPEN){
         connection.send(myJSON);
	    } else {
	 	 console.log('Server: connection closed, state='+connection.readyState);
	    }
    }  }    
  
  function load() {
    connection = new  WebSocket("ws://192.168.20.175:8085/");
    connection.onopen = function () {
        //var send = "init " + Math.round(Math.random()*4294967294+1);
        console.log('Client: connection with server has been created' );
	    document.getElementById('msg').innerHTML="Client: connection with server has been created";

      };
    connection.onclose = () => {
            console.log('WebSocket connectionhas been  closed');
			document.getElementById('msg').innerHTML="WebSocket connectionhas been  closed";

		};	
    connection.onerror = function (error) {
        keepAlive = false;
        connection.close();
        console.log('WebSocket error: ' + error);
        alert("WebSocket error: "+ error);
      };
    connection.onmessage = function (e) {
        console.log('Message: ' + e.data);
		var msgStr = document.getElementById('msg');
		try{
		var objJ=JSON.parse(e.data);
		var tt=objJ.actuators[1].S;//tt=objJ.actuators[1].S[1];
		msgStr.innerHTML ="<strong>Data received: </strong><br/>"+  e.data+" <br/><br/><b>JSON object:</b><br> "+JSON.stringify(objJ) +" <br><br><b>JSON object selection:</b><br>"+JSON.stringify(tt);
 		
		}catch(ex){
		   if (ex instanceof SyntaxError) {
             printError(ex, true);
		     msgStr.innerHTML = "Exception: Parse syntax error, data received=<br/>"+ e.data;
 		   } else {
             printError(ex, false);
		     msgStr.innerHTML = "Exception: No parse error, data received=<br/>"+ e.data;
   	       }
 	    }
      };
  }
  //-->
  </script> 

</head>
/<!-- <body onload="load()"> -->
<body>
 <input type="button" onclick="load();" value="Open websocket server"></button>
 <input type="button" onclick="connection.close();" value="Close websocket server"></button>
  <input type="button" onclick="sendButton1('msg A','10');" value="msg 1"></button>
  <input type="button" onclick="sendButton2('msg B','10');" value="msg 2"></button>
  <input type="button" onclick="sendButton3('msg C','10');" value="msg 3"></button>
  <input type="button" onclick="connection.send('msg D');" value="msg 4"></button>
  <br/>
  <p id="msg"></p>
</body>
</html>
software enigineer/teacher/advisor
Google translate
http://tescaweb.nl/Carel/?p=713

chehr
Beiträge: 193
Registriert: 07 Apr 2015, 21:07
Wohnort: Friedrichshafen

Re: Example websocket service in RoboPro Coding

Beitrag von chehr » 03 Jan 2022, 18:34

Many thanks for sharing,
I tried this proof of concept and it is working :)

vleeuwen
Beiträge: 1560
Registriert: 31 Okt 2010, 22:23
Wohnort: Enschede (NL)
Kontaktdaten:

Re: Example websocket service in RoboPro Coding

Beitrag von vleeuwen » 03 Jan 2022, 18:47

@ chehr
Thanks for your feedback.
The client is now a html/JS application but you can also use a program in a different language as client.
I am now busy to port my virtual joystick application to the TXT4.0 from 3 years ago.
The websocket could also be replace by a Berkely socket with a transfer area construction. This will be faster then JSON.
This enable to option to control your application in away that the previous fischertechnik interface were also remotely working.

Have fun, have a fine New Year
software enigineer/teacher/advisor
Google translate
http://tescaweb.nl/Carel/?p=713

minimik
Beiträge: 3
Registriert: 19 Jan 2012, 09:58

Re: Example websocket service in RoboPro Coding

Beitrag von minimik » 03 Apr 2022, 10:38

Hi,

I'm quite new with the ft controller stuff.
I have a Robo TXT 4.0 and I found your thread here. I gave it a try and it works well. I'm able to control my machine with my mobile phone.

Since I did not get the sticks on my phone (the PNGs are not found, and I do not know why) I'm asking myself, it should be possible to store the files at the TXT and access the page from there directly.
Since I'm absolutely new with this TXTs I'd like to know if this could be a possible way to implement a webserver which is accessible at port 8888 and I have access to it?

Do you have any hints regarding this point....

Many thanx in advance and
best regards
Michael

vleeuwen
Beiträge: 1560
Registriert: 31 Okt 2010, 22:23
Wohnort: Enschede (NL)
Kontaktdaten:

Re: Example websocket service in RoboPro Coding

Beitrag von vleeuwen » 04 Apr 2022, 18:16

This is possible.
However the Appache webserver on the TXT4.0 (configuration and data directories) is for the moment behind the root account and the configuration can not be changed.

But on the TXT it was very easy to implement.
On the TXT I was using an Embedded Civet Web server (including web sockets, SQL server) but on the TXT C++ was the low level language under RoboPro.

What you could do is to implement a simple webserver in Python and add it to the RoboPro code application.
software enigineer/teacher/advisor
Google translate
http://tescaweb.nl/Carel/?p=713

Antworten