I would like to use websockets to send updates from the server to the clients.
I know I can use Server Sent Events but Internet Explorer doesn't have great compatibility with it so I prefer to use websocket.
The TotalJs WebSocket allow me to use it like a client?
I'm trying to do this: (TotalJs Websocket Example)
exports.install = function(framework) {
framework.route('/');
framework.route('/send/', send_message);
framework.websocket('/', socket_homepage, ['json']);
};
function send_message() {
var controller = this;
var socket = new WebSocket('ws://127.0.0.1:8000/');
socket.onopen = function() {
socket.send(encodeURIComponent(JSON.stringify({ message: "send_message" })));
};
socket.close();
socket = null;
}
function socket_homepage() {
var controller = this;
controller.on('open', function(client) {
console.log('Connect / Online:', controller.online);
client.send({ message: 'Hello {0}'.format(client.id) });
controller.send({ message: 'Connect new user: {0}\nOnline: {1}'.format(client.id, controller.online) }, [], [client.id]);
});
controller.on('close', function(client) {
console.log('Disconnect / Online:', controller.online);
controller.send({ message: 'Disconnect user: {0}\nOnline: {1}'.format(client.id, controller.online) });
});
controller.on('message', function(client, message) {
console.log(message);
if (typeof(message.username) !== 'undefined') {
var old = client.id;
client.id = message.username;
controller.send({ message: 'rename: ' + old + ', new: ' + client.id });
return;
}
// send to all without this client
message.message = client.id + ': ' + message.message;
console.log(message);
controller.send(message);
});
}
When someone connect to http://127.0.0.1/send all clients connected to the server will receive a message.
Node.js doesn't have native WebSocket support so the send_message() function does not work. I would like to use TotalJs Websocket support but I don't know how to use it like a client.
Thats it.
Thank you very much.
I know this is the not best way but I used a global variable to resolve.
exports.install = function(framework) {
framework.route('/');
framework.route('/send/', send_message);
framework.websocket('/', socket_homepage, ['json']);
};
function send_message() {
if (websocket == null) return;
websocket.send({ message: "Hello World!" });
}
var websocket = null;
function socket_homepage() {
//var controller = this;
websocket = this;
websocket.on('open', function(client) {
console.log('Connect / Online:', websocket.online);
client.send({ message: 'Hello {0}'.format(client.id) });
websocket.send({ message: 'Connect new user: {0}\nOnline: {1}'.format(client.id, websocket.online) }, [], [client.id]);
});
websocket.on('close', function(client) {
console.log('Disconnect / Online:', websocket.online);
websocket.send({ message: 'Disconnect user: {0}\nOnline: {1}'.format(client.id, websocket.online) });
});
websocket.on('message', function(client, message) {
console.log(message);
if (typeof(message.username) !== 'undefined') {
var old = client.id;
client.id = message.username;
websocket.send({ message: 'rename: ' + old + ', new: ' + client.id });
return;
}
// send to all without this client
message.message = client.id + ': ' + message.message;
console.log(message);
websocket.send(message);
});
}
Related
I'm new to socket.io. I have a working message chat set up and I'm trying to add names to the messages. I have a var called name which holds each users name who has logged in. below is the code.
On the HTML page that holds the chat. chat-room.html
const room = 'waiting';
const socket = io('/tech');
$('form').submit(() => {
let msg = $('#m').val();
socket.emit('message', { msg, room });
$('#m').val('');
return false;
});
socket.on('connect', () => {
// emiting to everybody
socket.emit('join', { room: room });
})
socket.on('message', (msg) => {
$('#messages').append($('<li>').text(name + msg));
})
On the server script. index.js
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const port = 3001;
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/virtualsim/learning/chat-room.html');
});
app.get('/trainees', (req, res) => {
res.sendFile(__dirname + '/virtualsim/learning/chat-room2.html');
});
const tech = io.of('/tech');
tech.on('connection', (socket) => {
socket.on('join', (data) => {
socket.join(data.room);
tech.in(data.room).emit('message', `joined ${data.room} room!`);
})
socket.on('message', (data) => {
console.log(`message: ${data.msg}`);
tech.in(data.room).emit('message', data.msg);
});
socket.on('disconnect', () => {
console.log('user disconnected');
tech.emit('message', 'user disconnected');
})
})
Obvious, the way I have it now just sends back the user his or her name for every message sent, even messages send by other users. I need to add the variable name to the server script some how and I'm having difficulties getting it to work. Thanks for any help. John
Here is my Frontend code for set the username
<script>
const form = document.querySelector("form");
const input = document.querySelector(".input");
const messages = document.querySelector(".messages");
const username = prompt("Please enter a username: ", "");
const socket = io();
socket.on("old_message", {message: "hello"});
form.addEventListener("submit", function(event) {
event.preventDefault();
addMessage(username + ": " + input.value);
socket.emit("chat_message", {
message: input.value
});
input.value = "";
return false;
}, false);
socket.on("chat_message", function(data) {
addMessage(data.username + ": " + data.message);
});
socket.on("user_join", function(data) {
addMessage(data + " just joined the chat!");
});
socket.on("user_leave", function(data) {
addMessage(data + " has left the chat.");
});
socket.on("old_message", function() {
console.log('----data', data);
});
socket.on("getList", function(data) {
console.log('----MessageList', data);
});
addMessage("You have joined the chat as '" + username + "'.");
socket.emit("user_join", username);
socket.emit("old_message")
function addMessage(message) {
const li = document.createElement("li");
li.innerHTML = message;
messages.appendChild(li);
window.scrollTo(0, document.body.scrollHeight);
}
Here is backend code
const users = []; io.on('connection', (socket) => { socket.on('user_join', (data) => {
this.username = data;
// here check in DB with sender, receiver if record not exist then create
users.push({
socketId: socket.id,
userId: data,
});
socket.broadcast.emit('user_join', data); });
socket.on('chat_message', async (data) => {
const a = {
sender: data.senderId,
receiver: data.receiverId,
type: 'TEXT',
message: data.message,
};
await model.conversations.create(a);
data.username = this.username;
socket.broadcast.emit('chat_message', data); });
socket.on('disconnect', (data) => {
socket.broadcast.emit('user_leave', this.username); });
socket.on('old_message', async (data) => {
const messageList = await model.conversations.findAll({
where: {
sender: data.senderId,
receiver: data.receiverId,
},
});
socket.broadcast.emit('getList', messageList); }); });
Thanks for the answers back. I have figured out what I had to do.
First (on the HTML page) I had to emit the var name which holds all the users names to the server script on connect. This gives the proper name when one enters the room.
socket.on('connect', () => {
socket.emit('join', { room: room, name: name });
})
Then I added it to the messages being sent
$('form').submit(() => {
let msg = $('#m').val();
socket.emit('message', { name, msg, room });
$('#m').val('');
return false;
});
Then on the server script I added.
On connect
tech.in(data.room).emit('message', `${data.name} joined ${data.room} room!`);
Then again for the messages being sent
tech.in(data.room).emit('message', data.name + data.msg);
I'm sure there is a better way to join the names and messages but like I said I'm new to socket and I have spent way too much time on this :) If you know a better way please do let me know. Thanks!
prompt for the name first, then append it to the start of every message they emit
socket.emit(name+msg, ()=>{...});
I wrote a mqtt client.js, but realized I need multiple instances of this script so I rewrote it into a class.
Now I ended up with a lot of 'this.foo' references vor my variables, which made me wonder, is this the correct way of using classes in javascript?
Here´s how part of my class looks like:
this.client = mqtt.connect("mqtts://" + this.host, options); // mqtts for tls connection
// client event handling
this.client.on("connect", () => {
log.write("LOG_INFO", "PubClient connected to Broker: " + this.host + ":" + this.settings.port);
this.client.publish("client/publisher/status", "online", { qos: 1, retain: true });
this.clientToSocket.pubConnect(true);
});
this.client.on("close", () => {
//log.write("LOG_INFO", "PubClient close");
});
this.client.on("disconnect", (packet) => {
log.write("LOG_INFO", "PubClient disconnected. Reasoncode: " + packet.reasoncode);
});
this.client.on("offline", () => {
log.write("LOG_INFO", "PubClient offline");
this.clientToSocket.pubConnect(false);
});
this.client.on("error", (err) => {
//log.write("LOG_ERR", "PubClient Error: " + err.message);
});
this.client.on("packetreceive", (packet) => {
//log.write("LOG_INFO", "PubClient packet received: " + packet.cmd);
});
}
}
publish(topic, qos, msg) {
if(this.client !== undefined) {
this.client.publish(topic, msg, { qos: parseInt(qos), retain: true });
//log.write("LOG_INFO", "Publishing Message with: topic: " + topic + " payload: " + msg);
} else {
log.write("LOG_ERR", "Error: Publish not possible because client undefined");
}
}
close() {
if(this.client !== undefined) {
this.client.end();
log.write("LOG_INFO", "PubClient closing");
}
}
}
You can simplify it, using local variables. When work is done can assign to this. You can also use restructure to use the variables.
Local Var
constructor() {
const client = mqtt.connect("mqtts://" + host, options); // mqtts for tls connection
client.on("close", () => {
//log.write("LOG_INFO", "PubClient close");
});
this.client = client;
}
De-Structure:
doSomthingOnClient() {
const {client} = this // destrcuture
client.get() // use it
}
Whole class:
class Client {
constructor() {
const client = mqtt.connect("mqtts://" + host, options); // mqtts for tls connection
client.on("connect", () => {
log.write(
"LOG_INFO",
"PubClient connected to Broker: " + host + ":" + settings.port
);
client.publish("client/publisher/status", "online", {
qos: 1,
retain: true,
});
clientToSocket.pubConnect(true);
});
client.on("close", () => {
//log.write("LOG_INFO", "PubClient close");
});
client.on("disconnect", (packet) => {
log.write(
"LOG_INFO",
"PubClient disconnected. Reasoncode: " + packet.reasoncode
);
});
this.client = client;
}
getClient() {
return this.client;
}
doSomthingOnClient() {
const {client} = this // destrcuture
client.get() // use it
}
}
I am new to JS.
I am trying to build API server, this server must received data from other server using socket.
Currently I am using net library, I am facing a problem.
I should get data to check whether hardware worked or not, but I only get
undefiend(empty array).
I found some sources making async function to get called, but still I can't get it.
here is my code.
router.post("/Updated", async function(req, res, next) {
.....
//connect to station server for locking
var data = {
cmd: "lockStationQuery",
stationId: STATION_ID,
powerBankId: POWER_BANK_ID,
userId: USER_ID,
number: channelValue
};
var stringData = JSON.stringify(data);
var jsonData = JSON.parse(stringData);
var [client, recvData] = await getConnectionSocket(
USER_ID,
res,
merchant_uid,
amount
);
let successToWriteData = await writeData(client, stringData);
//Fail to send data to lock the Station
if (!successToWriteData) {
res.status(500).json({
RESULT: "FAIL",
REASON:
"error code 504"
});
res.end();
return;
}
console.log("received data", recvData); //this is empty array
jsonData = JSON.parse(recvData[0]);
Here is my getConnectionSocket function.
async function getConnectionSocket(USER_ID, res, merchant_uid, amount) {
//서버에 해당 포트로 접속
var client = "";
var recvData = [];
var local_port = "";
let status = {};
client = net.connect({ port: 8999, host: "localhost" }, function() {
console.log(
"connect log======================================================================"
);
console.log("connect success");
console.log("local = " + this.localAddress + ":" + this.localPort);
console.log("remote = " + this.remoteAddress + ":" + this.remotePort);
local_port = this.localPort;
this.setEncoding("utf8");
this.setTimeout(300000); // timeout : 10분
console.log("client setting Encoding:binary, timeout:300000");
console.log("client connect localport : " + local_port);
});
// 접속 종료 시 처리
client.on("close", function() {
console.log("client Socket Closed : " + " localport : " + local_port);
});
// 데이터 수신 후 처리
await client.on("data", function(data) {
console.log(
"data recv log======================================================================"
);
recvData.push(data);
console.log(recvData); //I want this data
console.log("data.length : " + data.length);
console.log("data recv : " + data);
let jsonData = JSON.parse(data);
if (jsonData.cmd === "removedPowerBank") {
if (jsonData.errorCode !== 0) {
//환불
console.log("환불 시작");
let cancel = cancelOrder(merchant_uid, USER_ID, res);
//여기서 환불 purchase db에 쓰기
} else {
console.log("PURCHASE 성공후 디비에 씀");
//구매 purchase db에 쓰기(getRentId에 썼음)
let purchased = writePurchaseDataInDB(
USER_ID,
res,
merchant_uid,
amount
);
console.log(purchased);
}
}
client.end();
});
client.on("end", function() {
console.log("client Socket End");
});
client.on("error", function(err) {
console.log("client Socket Error: " + JSON.stringify(err));
});
client.on("timeout", function() {
console.log("client Socket timeout: ");
});
client.on("drain", function() {
console.log("client Socket drain: ");
});
client.on("lookup", function() {
console.log("client Socket lookup: ");
});
return [client, recvData]; //recvData is always empty array
}
which way is best to address to resolve this?
Need some clarification on below point
are you getting correct value(s) in below log ? Or you undefined in them too.
console.log("data.length : " + data.length);
console.log("data recv : " + data);
also add this one
console.log("data type : " + typeof(data));
I am trying to create web-sockets in APEX for automatic refresh with node
but I am getting error This is not valid JSON:
java script code
$(function(){
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
console.log('Sorry websockets');
}
else {
var connection = new WebSocket('ws://127.0.0.1:1337');
connection.onerror = function (error) {
console.log( 'Sorry, but there is some problem with your connection or the server is down.');
};
connection.onmessage = function (message) {
console.log(message.data);
try {
var json = JSON.parse(message.data);
if (json.message=='REFRESH') {
gReport.pull();
}
else {
console.log(json.message);
}
}
catch (e) {
console.log('Thisnot valid JSON: ' + message.data);
}
};
}
});
Having difficulty with this working at seemingly random times. When I go into the chat page, the controller activates, and immediately after that the before addlistener and after addlistener console.logs fire, and then sometimes when I send a message, it is received with a console printout of the package contents, but more often it isn't. And sometimes, it is printed on the console of the computer that fires off the send message instead of the receiving end.
At the very least, though, whenever I send a message, even if I don't get a console printout of the package, I get a corresponding [QBChat RECV]:, [object Object] - hit the button ten times, get ten QBChat RECVs.
.controller('ChatCtrl', function($scope, $stateParams, $timeout, $rootScope, $ionicLoading) {
console.log("Inside ChatCtrl");
QB.createSession(function(err,result){
console.log('Session create callback', err, result);
console.log('Session create callback' + JSON.stringify(result));
});
$scope.settings = {};
$scope.user = {};
$scope.error = {};
$scope.signInClick = function() {
console.log('Login was clicked');
$scope.loading = $ionicLoading.show({
content: 'Logging in',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
var params = {'login': ($scope.user.username), 'password': ($scope.user.password)}
console.log("params... " + JSON.stringify(params));
QB.users.create(params, function(err, user){
if (user) {
console.log("successful user.create... " + JSON.stringify(user));
var jid = user.id + "-#####" + "#chat.quickblox.com";
var chatparams = {'jid': jid, 'password': ($scope.user.password)};
QB.chat.connect(chatparams, function(err, roster) {
console.log("err from qb.chat.connect... " + JSON.stringify(err));
console.log("roster from qb.chat.connect .... " + JSON.stringify(roster));
});
} else {
if (err.message == "Unprocessable Entity"){
QB.login(params, function(err, user){
if (user) {
console.log("Logged into QB with " + JSON.stringify(user));
var jid = user.id + "-#####" + "#chat.quickblox.com";
console.log(user.login + "'s jid is......" + jid);
var chatparams = {'jid': jid, 'password': ($scope.user.password)};
QB.chat.connect(chatparams, function(err, roster) {
console.log("stringifying the roster... " + JSON.stringify(roster));
});
}
else {
console.log(JSON.stringify(err));
}
});
}
}
});
// var chatparams = {'jid': jid, 'password': ($scope.user.password)};
// console.log("the jid is......" + jid);
// console.log("chatparams is ......" + JSON.stringify)
Parse.User.logIn(($scope.user.username) , $scope.user.password, {
success: function(_user) {
console.log('Login Success');
console.log('user = ' + _user.attributes.username);
console.log('email = ' + _user.attributes.email);
$ionicLoading.hide();
$rootScope.user = _user;
$rootScope.isLoggedIn = true;
// $state.go('tab.home');
},
error: function(user, err) {
$ionicLoading.hide();
// The login failed. Check error to see why.
if (err.code === 101) {
$scope.error.message = 'Invalid login credentials';
} else {
$scope.error.message = 'An unexpected error has ' +
'occurred, please try again.';
}
$scope.$apply();
}
});
// $state.go('tab.profile');
};
$scope.sendMessageClick = function() {
var user = $rootScope.user.attributes.username;
console.log("user = " + user);
console.log('sendMessageclick');
var countchew = "3354163-######chat.quickblox.com"; //countchew
var starshipenterprise = "3354099-######chat.quickblox.com"; //starshipenterprise
QB.chat.roster.get(function(roster) {
console.log("roster.get before if block " + JSON.stringify(roster));
});
if (user == "countchew"){
QB.chat.roster.confirm(starshipenterprise, function(){
console.log("roster.confirm called");
});
QB.chat.roster.add(starshipenterprise, function() {
console.log("roster.add called");
});
QB.chat.send(starshipenterprise, {
type: 'chat',
name: 'testmessage',
body: 'Hello world!',
extension: {save_to_history: 1}
});
// QB.chat.roster.remove(starshipenterprise, function() {
// console.log("roster.remove starship ... ");
// });
QB.chat.roster.get(function(roster) {
console.log("end of if statement " + JSON.stringify(roster));
});
} else if (user == "starshipenterprise"){
QB.chat.roster.confirm(countchew, function() {
console.log("roster.confirm called");
});
QB.chat.roster.add(countchew, function() {
console.log("roster.add called");
});
QB.chat.send(countchew, {
type: 'chat',
body: 'Hello world!'
});
}
};
console.log("before addlistener");
QB.chat.addListener({from: '3354163-######chat.quickblox.com'}, function() {
QB.chat.onMessageListener = function(userId, message) {
console.log('userId ..... ' + userId);
console.log('message .... ' + JSON.stringify(message));
};
});
console.log("after addlistener");
var chatparams1 = {from: '3354099-######chat.quickblox.com'};
console.log("before addlistener");
QB.chat.addListener(chatparams1, function() {
QB.chat.onMessageListener = function(userId, message) {
console.log('userId ..... ' + userId);
console.log('message .... ' + JSON.stringify(message));
};
});
console.log("after addlistener");
})
Great! Figured it out.
You need to pay attention to the XML packages that it sends. What was happening is that somehow, when it first got up and running and was working well with the corresponding QB chat addresses for the account, after that, at some point it started appending a string of numbers-quickblox-numbers (35896363-quickblox-20942 or whatever) in the 'from' field for the address, which is what I had my listener listening to. The confusing thing is that this worked sporadically.
You can't hardcode the addresses because this string of numbers at the end changes with every login.
Instead, it is working for the time being to just listen for messages with the parameters {name: 'message', type: 'chat'}.
A better way could be:
QB.chat.addListener( {name: 'message'}, function() {
$log.debug(" main: QB listener by filter was triggered");
});
Or just:
QB.chat.onMessageListener = showMessage;
That code has to be run once (at first init, on system loading).
onMessageListener will be triggered every time.
addListener will be triggered only if msg is with name'message'. (filter of listener)
Then you need a function with such a signature:
function showMessage(userId, msg) {
console.log('main.showMessage:: on message', msg)
}