Im trying to implement real time notifications in my django app.I have set up signals and consumers . Im getting an error in the javascript side
My javascript code:
<script>
document.addEventListener('DOMContentLoaded', function() {
const webSocketBridge = new channels.WebSocketBridge();
const nl = document.querySelector("#nl");
webSocketBridge.connect('student/dashboard/tasks/');
webSocketBridge.listen(function(action, stream) {
console.log("RESPONSE:", action);
if(action.event == "New Task") {
var el = document.createElement("li");
el.innerHTML = ` <b>${action.username}</b> completed Task
${action.title}`;
nl.appendChild(el);
}
})
document.ws = webSocketBridge; /* for debugging */
})
</script>
The error shows on the console :
TypeError: Invalid WebSocket constructor. Set
`options.constructor
Related
I am sending the message from a Python script as follows.
import firebase_admin
from firebase_admin import credentials, messaging
# initializations
cred = credentials.Certificate('Full path to firebase-admin-sdk.json')
print('Connecting...')
firebase_admin.initialize_app(cred)
registration_tokens = [
'valid_registration_token_from_client',
]
message = messaging.MulticastMessage(
data={'score': '850', 'time': '2:45'},
tokens = registration_tokens
)
response = messaging.send_multicast(message)
print('{0} messages were sent successfully.'.format(response.success_count))
After executing the above code, it prints 1 message sent successfully. I looked at my Firebase console and found that the number of sent notifications increased by 1. However, my React Js client does not seem to receive the message.
In react app,
Root public folder has firebase-messaging-sw.js file,
import { initializeApp } from "firebase/app";
import { getMessaging } from "firebase/messaging/sw";
import { onBackgroundMessage } from "firebase/messaging/sw";
const firebaseConfig = {
apiKey: "MY_API_KEY",
authDomain: "FIREBASE_APP_DOMAIN",
databaseURL: "DB_URL",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "SENDER_ID",
appId: "APP_ID",
measurementId: "MEASUREMENT_ID"
};
const firebaseApp = initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
onBackgroundMessage(messaging, (payload) => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/firebase-logo.png'
};
self.registration.showNotification(notificationTitle,
notificationOptions);
});
In App.js,
import React, {Component} from "react";
import { getMessaging, getToken, onMessage } from "firebase/messaging";
import { initializeApp } from "firebase/app";
export default class App extends Component {
constructor(props) {
super(props);
this.connectButtonPressed = this.connectButtonPressed.bind(this);
}
render() {
return (
<div><button onClick={this.connectButtonPressed}>Click</button></div>
)
}
connectButtonPressed(e) {
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.');
// TODO(developer): Retrieve a registration token for use with FCM.
// Get registration token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
const firebaseConfig = {
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
databaseURL: "DB_URL",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "SENDER_ID",
appId: "APP_ID",
measurementId: "MEASUREMENT_ID"
};
const firebaseApp = initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
onMessage(messaging, (payload) => {
console.log('Message received. ', payload);
});
getToken(messaging, { vapidKey: 'VAPID_KEY_FROM_CONSOLE' }).then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
console.log('currentToken: ', currentToken);
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
} else {
console.log('Unable to get permission to notify.');
}
});
}
}
The client can successfully request for and receive the registration token to which I send the message from the Python script. However, the onMessage event is not being triggered which makes me think that the client might not be receiving the message even though I sent the message to the token associated with this client.
What might be the issue here? What am I missing?
So this is what I am trying to do, I want to be able to send a message in a browser towards a python script. I've got to the point where I can send a message in the browser and the server sees it. For testing purposes I used io.emit('input', data) to send the data towards my python script but nothing happens on the python side.
script.py:
import socketio
sio = socketio.Client()
#sio.event
def connect():
print('connected')
#sio.on("input")
def on_input(key):
print(key)
sio.connect('http://192.168.2.9:5000', namespaces=['/justin'])
server.js:
const express = require('express')
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
var justin = null;
app.use(express.static('public'));
io.of('/justin').on('connection', function(socket){
console.log('justin connected');
justin = socket;
});
io.on('connection', function(socket){
console.log('a user connected');
socket.on('event', (data) => {
io.emit('input', data)
})
socket.on('disconnect', () => {
//
})
});
http.listen(5000, function(){
console.log('listening on *:5000');
});
Is there something I'm not seeing or is this just not possible?
Thanks in advance!
Hi i am copying parts of the github project multichat from the creator of django channels.
I am making slight changes to the code like not using jquery, renaming of some consumers and such.
I have literally no errors when running the code however when i join the page and the JS creates a websocket it says simply
[2017/08/03 13:13:48] WebSocket HANDSHAKING /chat/stream [127.0.0.1:37070]
[2017/08/03 13:13:48] WebSocket CONNECT /chat/stream [127.0.0.1:37070]
Which one would think is fine ofcourse... However i'n my connect function i have a print("********CONNECTED**********"), wich is nowhere to be seen in the console. It simply doesn't run the function i have told it to when someone connects but it still says the person connected and it throws no errors.
This is the main routing:
channel_routing = [
include("crypto_chat.routing.websocket_routing", path=r"^/chat-stream/$"),
include("crypto_chat.routing.chat_routing"),
]
Routing from app:
websocket_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
route("websocket.disconnect", ws_disconnect),
]
chat_routing = [
route("chat.receive", chat_send, command="^send$"),
route("chat.receive", user_online, command="^online$"),
Connect Consumer:
#channel_session_user_from_http
def ws_connect(message):
# only accept connection if you have any rooms to join
print("******************CONNECT*************************''")
message.reply_channel.send({"accept": True})
# init rooms - add user to the groups and pk num to the session
message.channel_session['rooms'] = []
for room in Room.objects.get(users=message.user):
room.websocket_group.add(message.reply_channel)
message.channel_session['rooms'].append(room.pk)
print(message.channel_session['rooms'])
Heres JS (note: i am using the JS extension that is available on the project website also):
function send_msg(){
var msg=document.getElementById('msg_input').value;
console.log("sending msg" + msg);
webSocketBridge.send({
"command": "send",
"room": "1",
"message": msg
});
}
// logging
var ws_path = "/chat/stream";
console.log("connecting to " + ws_path);
// connect
var webSocketBridge = new channels.WebSocketBridge();
webSocketBridge.connect(ws_path);
// listen loop
webSocketBridge.listen(function(data)
{
// read json file and act accordingly
if(data.error){
// post error message in chat
console.log("Error - " + data.error);
return;
}
// handle if the user comes back online
if(data.online){
console.log("User is online");
}
else if(data.offline){
console.log("User offline");
}
else if(data.message){
console.log("Got message");
}
else{ console.log("Unknown message type"); }
});
// Helpful debugging
webSocketBridge.socket.onopen = function () {
console.log("Connected to chat socket");
};
webSocketBridge.socket.onclose = function () {
console.log("Disconnected from chat socket");
}
Websocket paths should match on server and client side. On server side, you have /chat-stream/ and on client side /chat/stream. These should match. Also, make sure you don't forget the trailing slash as django explicitly requires it.
I've set a nodejs server along with simple python script with redis-py.
I have this on my nodejs server:
var http = require('http');
var server=http.createServer(onRequest).listen(3000);
var io = require('socket.io')(server);
var redis = require('redis');
var fs= require('fs');
var sub = redis.createClient();
sub.subscribe('channel');
function onRequest(req,res){
var index;
fs.readFile('./index.html', function (err, data) {
if (err) {
throw err;
}
index = data;
res.writeHead(200,{'Content-Type':'text/html'});
res.write(index);
res.end();
});
};
var sockets=[];
io.on('connection', function(socket){
console.log('a user connected');
sockets.push(socket);
console.log(sockets.length);
sub.on('message', function(channel, message){
console.log(message);
sockets[0].emit('chat message',message);
});
io.emit('chat message', "enter nickname");
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
This is just a simple test where I've tried to find out why my messages are sent multiple times.
I've figured that sub.on('message') is fired twice for each message that I send from python. Why?
The python code is pretty simple:
import redis
r=redis.StrictRedis()
pubsub=r.pubsub()
r.publish('channel',"HHHHHHH")
I have written a Node.js socket.io routine which will be called by a python socket io routine from my raspberry pi. It will communicate both ways. At the moment when I run these two routines on localhost it works fine. However when I deploy the server application to cloudfoundry and change the SocketIO connection link to cloudfoundry it does not work. Below is the client python
from socketIO_client import SocketIO
def on_updatepi_response(*args):
print 'updatepi'
def on_receivepi_response(*args):
print 'receiveepi'
with SocketIO('raspinode-server.cloudfoundry.com', 8080) as socketIO:
socketIO.on('receivepi', on_receivepi_response)
socketIO.on('updatepi', on_updatepi_response)
socketIO.emit('sendrabbit','testdata')
socketIO.wait(seconds=1)
I know cloudfoundry can be a bit strange as my first idea was to use rabbitmq but it is tied to the VCAP_SERVICES idea. However I did not think such a restriction would be there on a Node.js page.
Let me know if there is anything wrong with the above code and if not how can i get my external pi to send reading to my cloud app ?
Server Code is listed below though it is not relevant. It responds on localhost...I know the rabbitmq code is not hooked up yet
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var amqp = require('amqp');
var io = require('socket.io').listen(server)
function rabbitUrl() {
if (process.env.VCAP_SERVICES) {
conf = JSON.parse(process.env.VCAP_SERVICES);
return conf['rabbitmq-2.4'][0].credentials.url;
}
else {
return "amqp://localhost";
}
}
var port = process.env.VCAP_APP_PORT || 3000;
var messages = [];
function setup() {
var exchange = conn.exchange('cf-demo', {'type':'fanout', durable:false}, function(){
var queue = conn.queue('', {durable:false, exclusive:true},
function() {
queue.subscribe(function(msg) {
messages.push(htmlEscape(msg.body));
if (messages.length > 10) {
messages.shift();
}
});
queue.bind(exchange.name, '');
});
queue.on('queueBindOk', function() {httpServer(exchange);});
});
}
server.listen(8080);
io.sockets.on('connection', function(socket){
// when the client emits sendrabbit, this listens
socket.on('sendrabbit', function(data)
{
// we tell the client to execute updatepi with 2 parameters
io.sockets.emit('updatepi', socket.username, data)
});
socket.on('disconnect', function()
{
socket.broadcast.emit('updatepi', 'SERVER', socket.username + ' has disconnected');
});
});
It's my understanding that your server should listen on the port Cloud Foundry assigns it (available in an env var). You can't assume it will be 8080. Then the client talks to raspinode-server.cloudfoundry.com (no port) and Cloud Foundry routes it to the correct place.