get multiple variables from form with websockets in python - javascript

Just starting to learn websockets and python. for now I am using Socket-IO and have the very basic 'pull from form and echo it back out' but I need to be able to pull in 2+ variables from the form and use them in the program. The guides i have seen for the beginner are all just one variable and i'm struggling to figure it out and could use some help.
Im looking for a second text field in the form and be able to get the variable in the app. I'm assuming it would be in the form of {'data': message['data']} and {'data': message['data2']} for instance but as long as I can get the values, thats whats important.
What I have right now:
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Flask-SocketIO Test</title>
<script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
namespace = '/test'; // change to an empty string to use the global namespace
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
socket.on('connect', function() {
socket.emit('my event', {data: 'Connected... Waiting for you...'});
});
socket.on('my response', function(msg) {
$('#log').append('<br>' + msg.data);
});
$('form#emit').submit(function(event) {
socket.emit('my event', {data: $('#emit_data').val()});
return false;
});
});
</script>
</head>
<body>
<h1>Flask-SocketIO Test</h1>
<h2>Send:</h2>
<form id="emit" method='POST' action='#'>
<input type="text" name="emit_data" id="emit_data" placeholder="Message"><br>
<input type="submit" value="Echo"></div>
</form>
<h2>Receive:</h2>
<div id="log"></div>
</body>
</html>
app.py
from gevent import monkey
monkey.patch_all()
import time
from threading import Thread
from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
thread = None
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
time.sleep(60)
count += 1
#'<br>Received #' + msg.count + ': ' + msg.data
socketio.emit('my response', {'data': 'Connection to server still alive'}, namespace='/test')
#app.route('/')
def index():
#kick off thread that every 10 seconds sends a response
global thread
if thread is None:
thread = Thread(target=background_thread)
thread.start()
return render_template('index.html')
#socketio.on('my event', namespace='/test')
def test_message(message):
print message
emit('my response', {'data': message['data']})
#socketio.on('connect', namespace='/test')
def test_connect():
emit('my response', {'data': 'Trying to connect to server...'})
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected')
if __name__ == '__main__':
socketio.run(app)
Im looking for a second text field in the form and be able to get the variable in the app. I'm assuming it would be in the form of {'data': message['data']} and {'data': message['data2']} for instance but as long as I can get the values, thats whats important.

Just send as many variables as you want:
socket.emit('my event', {data: $('#emit_data').val(), data2: $('#emit_data2').val()});
data is only an example name for a variable. You can use any number and names of dictionary keys.

Related

Flask event stream app with js eventsource overwrites previous stream output

My flask app:
import eventlet
eventlet.monkey_patch()
from flask import Flask, render_template, Response
from shelljob import proc
from time import sleep
app = Flask(__name__)
#app.route('/')
def index():
return render_template('stream.html')
#app.route('/stream')
def stream():
g = proc.Group()
p = g.run([ "bash", "-c", "sudo tcpdump -i ens4 -s 0 -nX tcp port 5000" ])
def read_process():
while g.is_pending():
lines = g.readlines()
for proc, line in lines:
yield "data:" + str(line) + "\n\n"
return Response(read_process(), mimetype='text/event-stream')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001)
stream.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Output</h1>
<div id="dumps"></div>
</body>
<script>
var targetContainer = document.getElementById("dumps");
var eventSource = new EventSource("/stream");
eventSource.onmessage = function(e) {
targetContainer.innerHTML = e.data;
};
</script>
</html>
My issue:
The outputs seems to get to the browser but any new streamed output overwrites the previous one. For e.g. the following is all i see in the browser and the line keeps changing as stream is updated:
Output
b'\t0x0020: 8011 01fa ce65 0000 0101 080a 1984 6ce7 .....e........l.\n' <=== keeps updating
What i'd like to achieve is a stream of tcpdump output rendered on my browser as an actual bash output would look like.
This works fine if i point to url path /stream and the reason why i'm embedding into html is to be able to give it some style.
Changed to targetContainer.innerHTML += e.data + "<br/> in <script>

Flask SocketIO messages not received

I am new to Flask and the IO. I'm trying to implement a basic data receiver for a machine with RoS. I have a python script sending data to a web server running on Flask.
The issue is that the java-script callback is never called and thus the numbers are strangely never added to the list, even though there are no errors.
The relevant parts are this:
Within Python Webserver:
#socketio.on('connect', namespace='/test')
def test_connect():
print("CALLED")
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected')
It is supposed to post a random number defined by the following Ros Callback function (This is called every 0.5s):
def forklift_callback(self, msg):
#SOCKET TEST
number = random.randint(1,101)
print(number)
socketio.emit('newnumber', {'number': number}, namespace='/test')
Perhaps the way I define it is important:
*import statements*
from std_msgs.msg import String, UInt32
from umd_msgs.msg import PCNotification, RoverStatus, Barcode
mod = Blueprint('api', __name__)
msg = String()
started = "robot started"
socketio = SocketIO(app)
... All functionality ...
if __name__ == '__main__':
socketio.run(app)
This is connected to the html page at the following location:
<html>
<head>
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<script>
$(document).ready(function(){
//connect to the socket server.
console.log('http://' + document.domain + ':' + location.port + '/test')
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
var numbers_received = [];
//receive details from server
socket.on('newnumber', function(msg) {
console.log("Blank")
console.log("Received number" + msg.number);
//maintain a list of ten numbers
if (numbers_received.length >= 10){
numbers_received.shift()
}
numbers_received.push(msg.number);
numbers_string = '';
for (var i = 0; i < numbers_received.length; i++){
numbers_string = numbers_string + '<p>' + numbers_received[i].toString() + '</p>';
}
$('#log').html(numbers_string);
});
});
</script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Asynchronous Flask Communication</h1>
<p>Random numbers generated by the Flask server will appear below, asynchronously.</p>
</div>
</div>
</div>
<div class="container" id="content">
<div class="row">
<p>Asynchronous page updates will appear here:</p>
<h3>Number list:</h3>
<div id="log">
</div> <!-- /#log -->
</div>
</div>
Try somethin like this,maybe it helps
You can do it with Thread that will run your function
yourThread = Thread()
thread_stop_event = Event()
class someClass(Thread):
def __init__(self):
self.delay = 1
super(someClass,self).__init__()
def forklift_callback(self):
while not thread_stop_event.isSet():
number = random.randint(1,101)
print(number)
socketio.emit('newnumber', {'number': number}, namespace='/test')
sleep(self.delay)
def run(self):
self.forklift_callback()
#socketio.on('connect', namespace='/test')
def test_connect():
print("CALLED")
global yourThread
if(not yourThread.isAlive()):
yourThread = someClass()
yourThread.start()
or just run it after client connects your server
#socketio.on('connect', namespace='/test')
def test_connect():
//your function here
print("CALLED")

Is there way to change the value of a variable in a python script from javascript?

I have a python script and apache web server running in a raspberry pi. I want to change the value of a variable in my python script from a web page using javascript. It is possible?
We can use socket. for easily using socket, we can use socket.io
Start.html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
</head>
<body>
<h1>Socket.IO GPIO control</h1>
<button id="btnGpio">Change GPIO</button>
<script>
var socket = io.connect('http://localhost:5000');
var index = 0;
socket.on('connect', function () {
console.log('connected')
document.getElementById('btnGpio').addEventListener('click', () => {
index = index + 1;
console.log('index', index)
socket.emit('change_gpio', { status: (index % 2 == 0) })
})
});
</script>
</body>
</html>
socket_server.py
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
#app.route("/")
def home():
return render_template("Start.html")
socketio = SocketIO(app)
pin = True
#socketio.on('change_gpio')
def handle_my_custom_event(json):
pin = json['status']
print('pin = ' , pin)
#socketio.on('connect', namespace='/')
def test_connect():
print('Connected')
if __name__ == '__main__':
socketio.run(app)
Install library with pip
pip install flask
pip install flask-socketio
Document:
https://flask-socketio.readthedocs.io/en/latest/

Javascript client will not continuously listen with Flask-SocketIO

I am learning websockets with Flask-SocketIO. The goal is to get have my div continuously populated by a random number every second. When I run the code below, only the last number appears. However in the console I see that all arrive at the same time.
<script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
socket.on('pony_update', function(msg){
console.log("pony update");
console.log(msg);
$('#ponies').html(msg.data);
});
To update this div
<div id="ponies"></div>
The "controller" method is
#socketio.on('the_ponies', namespace='/test')
def run_numbers(message):
for i in range(5):
time.sleep(1)
x = random.random()
emit('pony_update', {'data': x}, broadcast=True)
It blocks in the thread. Try use start_background_task with gevent monkey_patch
#socketio.on('pony_update', namespace='/chat')
def run_numbers(message):
#copy_current_request_context
def back_work():
print('start')
for i in range(5):
time.sleep(1)
x = random.random()
print(x)
emit('my response', {'data': x}, broadcast=True)
socketio.start_background_task(target=back_work)
Please don't forgot to put the monkey patch in top of your file. :)

html + javascript + socketio

I've some problem in sending a simple message trough socket.io:
giving a button in index.html:
<button id="button" onclick="functionTest()"> buttonTest </button>
and this function in my js :
function functionTest( function(event) {
socket.emit('myevent', {data: "testval"});
return false;
});
if I have a Flask server with:
#socketio.on('myevent', namespace='/test')
def test_message(message):
print message
I should see in the Flask log, the message, but it doesn't work.
Where am I wrong?
thank you

Categories

Resources