I'm trying to learn Flask-SocketIO, Now i'm trying to do simple chat, but no one receives messages except the user in browser. Python/Flask code:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = '?-.'
socketio = SocketIO(app)
#socketio.on('joined')
def handle_message(who):
emit('back', who)
#app.route("/")
def main_page():
return render_template("index.html")
if __name__ == '__main__':
socketio.run(app)
and Javascript:
var socket = io.connect('http://' + document.domain + ':' + location.port);
$('#mybut').on("click", function(){
socket.emit('joined', {who:'someone'});
});
socket.on('back', function(data) {
console.log(data['who'] + ' joined.')
});
You need to set the broadcast parameter in this case. Check the Flask-SocketIO docs on broadcasting.
I.e. change your handler to the following:
#socketio.on('joined')
def handle_message(who):
emit('back', who, broadcast=True)
Related
I am currently trying to get a small server running on my RaspberryPi and accessing it from my PC within the LAN.
I get the following error when accessing the Raspberry, where the index.html is displayed to me just fine. Apparently it seems there are problems with my "resetList" endpoint.
I also tried the solution Solve Cross Origin Resource Sharing with Flask but it did not work for me. Thank you in advance.
I have the following Python code:
gevent.monkey.patch_all()
from flask import Flask, render_template
from flask_socketio import SocketIO
import dbfunctions as db
import json
from flask_cors import CORS
app = Flask(__name__, template_folder='./build', static_folder='./build/static')
CORS(app)
socket_io = SocketIO(app)
#app.route('/', methods=['GET', 'POST', 'PUT'])
def index():
return render_template('index.html')
# receiving messages
#socket_io.on('resetList')
def reset_list():
database = r"data.db"
conn = db.create_connection(database)
with conn:
data = db.get_data_without_initial(conn)
fields = ["id", "name", "profit", "sum", "high", "maxProfit", "last_update"]
json_list = []
for i in range(len(data)):
item_to_add = {fields[j]: data[i][j] for j in range(len(fields))}
json_list.append(item_to_add)
json.dumps(json_list)
socket_io.emit('receivedData', json_list)
if __name__ == '__main__':
socket_io.run(app, host='0.0.0.0', port=5000, debug=True)
i found a solution, the problem was not my python code it was my java code :/
a simple add of " transports: ["polling"] " solve the problem
import io from "socket.io-client";
let endPoint = "http://localhost:5000";
let socket = io.connect(`${endPoint}`, { transports: ["polling"] });
function receiveData(cb) {
socket.on("receivedData", (resp) => cb(resp));
}
export { receiveData };
I am trying to build a simple Tic-Tac-Toe web app. I would like to connect my frontend to my backend logic where I will be running a python script. I believe flask is what I need to use to create a localserver & ajax can be used with jquery to connect button press with python logic. Everything I tried has returned errors or at most I am getting a html page response when I should be getting a json file.
I am very tired and have spent all day trying to figure this out with no success so any help would be greatly appreciated.
My folder structure looks like this:
folder structure
My .js code:
$(document).click(function (e) {
if ($(e.target).attr("id") == "head") {
var tossVal = $(e.target).attr('value')
passCoinToss(tossVal)
var soundbyte = document.createElement("audio")
soundbyte.src = "/static/Assets/click1.mp3"
soundbyte.play()
remvCoinflip()
} })
function passCoinToss(Value) {
$.ajax({
url: "http://127.0.0.1:5000//test",
type: "GET",
success: function(response){
alert(response);
}
}); }
My python script with flask
# Using flask for simple webhook initialization in order to run our webpage.
from flask import Flask, redirect, url_for, render_template, request, jsonify
from static.Backend.algorithm import coinToss
import os, json
# Declaring the app
app = Flask(__name__)
# Render homepage
#app.route("/")
def main():
return render_template('index.html')
# Route for CoinToss
#app.route("/test", methods=['GET', "POST"])
#cross_origin()
def test():
data = {"picked": "1"}
return json.dumps(data)
if __name__ == "__main__":
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port, debug=True)
#app.route("/test", methods=['GET', "POST"])
#cross_origin()
def test():
data = {"picked": "1"}
return jsonify(data)
If you want to return a json data, you can use the jsonify function of flask builtin function.
SOLUTION
Must Json.dumps the data first and then jsonify
# Route for CoinToss
#app.route("/test", methods=['GET', "POST"])
def test():
data = {"picked": "1"}
j = json.dumps(data)
return jsonify(j)
Check to make sure that the url is correct
function passCoinToss(Value) {
$.ajax({
url: "/test",
type: "GET",
contentType: "application/json",
success: function (response) {
alert(response);
}
});
}
I am working with Flask Socketio. My code right now console logs every time a user opens a page. However when I open the page in a new tab/window the console of the original user in not updated. Below is the code, have a look at it
let socket = io.connect("http://127.0.0.1:5000/")
socket.on("connect",() => {
socket.emit("my custom event",{text:"I have joined"})
})
socket.on("my response",function(msg) {
console.log(msg)
})
And here is the python code for flask
from flask import Flask, render_template, request
import requests
from flask_socketio import SocketIO, emit, send
app = Flask(__name__)
app.config["SECRET_KEY"] = "hope"
socketio = SocketIO(app)
#app.route('/')
def hello_world():
return render_template("index.html")
#app.route('/1')
def random_route():
return render_template("index2.html")
#socketio.on('message')
def message(data):
print(data)
#socketio.on('my custom event')
def handle_custom_event(data):
emit("my response", data)
if __name__ == "__main__":
socketio.run(app, debug=True)
The default for the emit function is to address the event only to the sender. If you want to address all your connected clients, you have to indicate so with the broadcast option:
#socketio.on('my custom event')
def handle_custom_event(data):
emit("my response", data, broadcast=True)
I have a React Client which needs to consume messages emitted by a flask_socketio server, it works fine if I emit a single message on 'connect' however if i keep emitting it in a while loop it doesn't get picked up on the client-side. I presume it could be due to action being performed in an active thread. I cannot find any posts online that talks about the issue.
Below is my React js client code.
class MyClient extends Component {
constructor() {
super();
this.state = {
endpoint:"http://127.0.0.1:5000",
response: ""
};
}
componentDidMount() {
console.log("test")
const {endpoint} = this.state;
//Very simply connect to the socket
const socket = socketIOClient(endpoint);
//Listen for data
socket.on("connect", dd => {
socket.on("log", dx => this.setState({response: dx.data}));
});
}
render() {
const {response} = this.state;
return (
<div>
<h1>Test {response}</h1>
{console.log(response)}>
</div>
)
}
}
The client looks for "log" to be emitted from the server, for now I added time to mock changing data.
When client loads i see the data, and when I disconnect and reconnect the server I get to see the new data on the client. Am wondering how do I emit the data continuously
from flask import Flask, render_template, request, jsonify
from flask_socketio import SocketIO, emit
from flask_cors import CORS
from datetime import datetime
import time
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
app = Flask(__name__)
app.config['SECRET_KEY'] = 'justasecretkeythatishouldputhere'
socketio = SocketIO(app,cors_allowed_origins="*")
CORS(app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/api')
def api():
query = dict(request.args)
socketio.emit('log', dict(data=str(query)), broadcast=True)
return jsonify(dict(success=True, message='Received'))
#socketio.on('connect')
def on_connect():
time.sleep(1)
t = str(time.clock())
print(t)
socketio.emit('log', {'data': t, 'time': t})
if __name__ == '__main__':
socketio.run(app,port=5000)
Below loop does not work, should i run it as a background thread or is there an async property that i need to add to socketio. Any help is greatly appreciated.
#socketio.on('connect')
def on_connect():
while True:
time.sleep(1)
t = str(time.clock())
print(t)
socketio.emit('log', {'data': t, 'time': t})
In your client side you can make use of setInterval method to emit an event, after every few milliseconds.
On server side you can emit the event via which you can send the data.
So, all together, it will be something like below:
Client Side:
setInterval(function() {
socket.emit('time');
}, 1) // 1 millisecond is almost close to continues
socket.on('time', function(data) {
console.log(data)
});
Server Side:
#socket.on('time')
def time():
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
emit('time', current_time)
In the console log of your browser, you can see the continues data getting logged.
I hope this helps.
Note: Client side code, which I have provide here, is of pure JavaScript. Since, React is based on JavaScript, there will be some or the other way to use setInterval.
import os
from flask import Flask
from flask import request
from flask import url_for
from flask import render_template
from twilio.rest import TwilioRestClient
from twilio import twiml
Declare and configure application
app = Flask(__name__, static_url_path='/static')
ACCOUNT_SID = "AACxxxxx"
AUTH_TOKEN = "xxxxxx"
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
Configure this number to a toll-free Twilio number to accept incoming calls.
#app.route('/caller', methods=['GET', 'POST'])
def caller():
response = twiml.Response()
response.say("Thank you for calling" \
"Please hold.")
response.enqueue("Queue Demo", waitUrl='/wait')
return str(response)
Configure waiting room to notify user of current position in the queue and
play the sweet, soothing sounds of Twilio's coffeeshop collection.
#app.route('/wait', methods=['GET', 'POST'])
def wait():
response = twiml.Response()
twilio_client.sms.messages.create(
to="+44xxxxxxxxxx",
from_="+44xxxxxxxxxx",
body="Hey Jenny! Good luck on the bar exam!",
)
response.say("You are number %s in line." % request.form['QueuePosition'])
response.play("https://s3-us-west-2.amazonaws.com/" \
"twilio/music1.mp3")
response.redirect('/wait')
return str(response)
Connect to support queue - assign to Twilio number for agent to call.
#app.route('/agent', methods=['GET', 'POST'])
def agent():
response = twiml.Response()
with response.dial() as dial:
dial.queue("Queue Demo")
return str(response)
If PORT not specified by environment, assume development config.
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
if port == 5000:
app.debug = False
app.run(host='0.0.0.0', port=port)
Why does it not send the sms?
Ok I resolved it, so if you are using python on twilio, this is the code to have your phone system that answers the call, puts the caller on hold playing music and then sends you an sms then you can call the number to help the caller.
Here it is:
import os
from flask import Flask
from flask import request
from flask import url_for
from flask import render_template
from twilio.rest import TwilioRestClient
from twilio import twiml
Declare and configure application
app = Flask(__name__, static_url_path='/static')
Configure this number to accept incoming calls.
#app.route('/caller', methods=['GET', 'POST'])
def caller():
response = twiml.Response()
response.say("Thank you for calling " \
"Please hold.")
response.enqueue("Queue Demo", waitUrl='/wait')
return str(response)
Configure the waiting room to notify the user of their current position in the queue and play the holding music or marketing message.
#app.route('/wait', methods=['GET', 'POST'])
def wait():
response = twiml.Response()
response.say("You are number %s in line." % request.form['QueuePosition'])
response.play("https://s3-us-west-2.amazonaws.com/" \
"triptorigatwilio/eventpremrigaholdmusic1.mp3")
response.redirect('/wait')
Notify agent of call via SMS
client = TwilioRestClient("your account sid...AC...", "your account auth token...xxxx")
client.sms.messages.create(
to="put number to send sms here",
from_="put the twilio number to send sms from here",
body="A caller is in the queue. Call now to help them.",
)
return str(response)
Connect to support queue - assign to Twilio number for agent to call.
#app.route('/agent', methods=['GET', 'POST'])
def agent():
response = twiml.Response()
with response.dial() as dial:
dial.queue("Queue Demo")
return str(response)
If PORT not specified by environment, assume development config.
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
if port == 5000:
app.debug = True
app.run(host='0.0.0.0', port=port)
Don't forget to configure your active numbers in twilio. The number the caller calls should point to /caller and the number for the agent calls should point to /agent. Good luck...