I'm trying to learn JavaScript and following Daniel Shiffman's p5.js tutorial. I made a fun little pong game and wanted it to take it to the next level by making it multiplayer. I want to start with the basics and just follow Daniel's Socket tutorial. I can successfully access my site and see my canvas. However, I want to take it to the next level by making it available over the LAN. I am not sure how to do this, and I am having some trouble. Here is the client code I used:
var socket;
function setup() {
socket = io.connect();
createCanvas(200, 200);
}
function draw() {
background(0);
fill(255);
ellipse(mouseX, mouseY, 60, 60);
}
The server code is:
// Imports
var express = require('express');
var socket = require('socket.io');
// Create Local host
var app = express();
var server = app.listen('3000')
app.use(express.static('public'));
// Sockets
var io = socket(server);
io.sockets.on('connection', newConnection);
// New Connection
function newConnection(socket) {
console.log("New Connection: " + socket.id);
}
console.log("Server running...");
if needed here is my index.html code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Learning Sockets</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="/libraries/addons/p5.min.js"></script>
<script src="/libraries/addons/p5.dom.min.js"></script>
<script src="/libraries/addons/p5.sound.min.js"></script>
<script src="sketch.js"></script>
<script src="/libraries/addons/p5.dom.js"></script>
</head>
<body>
</body>
</html>
Keep in mind that I am a beginner. I have tried looking at other posts, but the answers were too complicated, and in the end, I don't think that it solved my problem. Not sure if it matters but I do have node.js, express, and socket.io installed. I have tried connecting by using http://my-ip:3000. I can connect from my computer via localhost:3000 and my-IP:3000. But when I try to connect from another computer it doesn't work. And yes I am connected to the same network.
Daniel Shiffman's playlist: https://www.youtube.com/playlist?list=PLRqwX-V7Uu6b36TzJidYfIYwTFEq3K5qH
Sorry, I looked at my IP address again, and I used the wrong one. Silly me. PROBLEM SOLVED :D
Related
so I've been trying to create a simple web page with Apache made with bootstrap from where I can send/receive publication with Mosquitto.
My issue here is that when I try to connect to the mqtt client i get this errors, i tried every combination that i found looking on guides and other stuff i founded, i either get ERR_CONNECTION_REFUSED or Error 404 or CONNECTION_RESET.
WebSocket connection to 'ws://localhost:9001/mqtt' failed: Error in
connection establishment: net::ERR_CONNECTION_REFUSED
I tried looking up ways to fix this, so I added in /etc/mosquitto/mosquitto.conf:
#listener 8081
#protocol websockets
#listener 8080
#protocol websockets
#port 9001
listener 9001
protocol websockets
My index.php file (at some point i just kept adding stuff):
<head >
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<!-- MQTT Websocket -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.2/mqttws31.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
var mqtt;
var reconnectTimeout = 2000;
var host = 'localhost';
var port = 9001;
function onConnect() {
message = new Paho.MQTT.Message("Test");
message.destinationName = 'test';
mqtt.send(message);
}
function onFail() {
console.log("fail")
}
function MQTTconnect() {
mqtt = new Paho.MQTT.Client(host, port, '/mqtt', "mark");
var options = {
cleanSession: true,
useSSL: false,
timeout: 3,
onSuccess: onConnect,
onFailure: onFail,
};
mqtt.connect(options);
}
</script>
If anyone could kindly tell me if i missed something or what i have to do to make the connection work I'd gladly appreciate! I've been stuck like this for hours now.
EDIT :
I think I found the issue i think I just had to type on a terminal
sudo mosquitto -c /etc/mosquitto/mosquitto.conf
and leave it open to make it work.
I am new to Node.js and javascript, hence don't have much experience and in need of some help.
I have a script that opens a simple server socket and just listens to incoming connection and prints the incoming message to the screen:
var net = require('net');
var server = net.createServer();
server.on('connection', handleConnection);
server.listen(9000, function() {
console.log('server listening to %j', server.address());
});
function handleConnection(conn) {
var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
console.log('new client connection from %s', remoteAddress);
conn.on('data', onConnData);
conn.once('close', onConnClose);
conn.on('error', onConnError);
function onConnData(d) {
var chunks = [];
chunks.push(d);
console.log('Client at %s says %s', remoteAddress, Buffer.concat(chunks).toString());
conn.write(d);
}
function onConnClose() {
console.log('connection from %s closed', remoteAddress);
}
function onConnError(err) {
console.log('Connection %s error: %s', remoteAddress, err.message);
}
}
I have tested it and it works when i run it from the IDE (eclipse).
What I am trying to do is to incorporate this code inside an HTML file.
The HTML file does not suppose to be accessed from the out side, its for learning purposes only.
Basically i would like to open the HTML file, it should run the code in the background (listen to the socket) and once the is a connection and data coming in it should print it on the screen (sing alert for example).
The HTML code looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>some title</title>
</head>
<body>
<script
type = "text/javascript" src = "simple_server.js">
</script>
</body>
</html>
While trying to open the HTML file using a browser or inside eclipse it does nothing.
My question is, is it even possible? If it is, what am i doing wrong and how may I fix it?
Any help would be appreciated. Thank you.
i have a device that send data strings via mqtt to my mosquitto broker on ubuntu i currently use node-red to then receive these strings and use javascript function node to do everything else i need, data conversions, insert into query etc but that one thing im struggling with is i want to move away from node-red so i just have files with pure code, i have tried the code provided on npm website but i need an idiots guide haha does anyone have any idea's where i can look or anyone able to help me ? all my html files are currently displayed from an apache server
my current set up for mqtt is mosquito running on ubuntu i have enabled websockets in the configuration files with listner of 1883
mosquitto configuration
listener 1883
listener 1884
protocol websockets
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
mqtt code i have tried :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script> <script type="text/javascript">
var wsbroker = "localhost"; //mqtt websocket enabled broker
var wsport = 1883 // port for above
var client = new Paho.MQTT.Client(wsbroker, wsport,
"myclientid_" + parseInt(Math.random() * 100, 10));
client.onConnectionLost = function (responseObject) {
console.log("connection lost: " + responseObject.errorMessage);
};
client.onMessageArrived = function (message) {
console.log(message.destinationName, ' -- ', message.payloadString);
};
var options = {
timeout: 3,
onSuccess: function () {
console.log("mqtt connected");
client.subscribe('/tracked', {qos: 1});
},
onFailure: function (message) {
console.log("Connection failed: " + message.errorMessage);
}
};
function init() {
client.connect(options);
}
</head>
<body onload="init();">
</body>
So as mentioned in the comments.
You are trying to connect to port 1883 which is the native MQTT port.
To use the Javascript client from a webpage you need to use MQTT over Websockets, you have added a Websocket listener on port 1884.
So you need to edit the code as follows:
var wsbroker = "localhost"; //mqtt websocket enabled broker
var wsport = 1884 // Websocket port for above
var client = new Paho.MQTT.Client(wsbroker, wsport,
"myclientid_" + parseInt(Math.random() * 100, 10));
I'm trying to create a webapp for a web art class using node (w/ npm) and express. The idea is to have the body of the site be all one color, but anyone can text the site a hexcode/CSS color at a Twilio number and the color of the site will instantly change to that color value.
Essentially how it works is the server receives a POST request from Twilio at http://example.com/message, which contains the body of the text message. It writes it to a temporary file at ~/app/.data/color.tmp, which is accessed by the client with a jQuery .get() call to http://example.com/color, which returns
So here's the problem: I got a version of the app working on glitch.me, so I know that this code can work, but I'm having a lot of trouble getting it to work on my domain. I installed the app and can start it with npm, and it successfully shows me the HTML page, but the Chrome devtools show the script is receiving a 403 when it tries to access /color. Also, new texts to my site aren't changing the color value in /.data/color.tmp. I thought it might be a permissions issue but I checked them and they seem fine.
Here's the server file and the script on the index.html page:
app/server.js
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
var dataPath = '.data/color.tmp';
// set a new color (saves posted color to disk)
app.post("/message", function (request, response) {
var dataStr = JSON.stringify(request.body.Body);
fs.writeFile(dataPath, dataStr);
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
var dataStr = fs.readFileSync(dataPath).toString();
response.send(JSON.parse(dataStr));
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
app/views/index.html
<script>
// checks server for color value and sets background
function checkForColorChange() {
$.get('/color', function getColorComplete(data) {
document.body.style.backgroundColor = data;
console.log(data);
})
}
// Poll the server at 2000ms interval
setInterval(checkForColorChange, 2000);
checkForColorChange();
</script>
Anyway, I feel like I must be missing something really obvious if it worked so easily on Glitch and won't on my website, but I've been stuck for a few days and am not making any progress! Any help would be so appreciated. Let me know if anything's unclear too.
(See update below for a working example)
TL;DR - example:
Original answer
There are few problems with your code:
you're not checking for errors
you're using blocking functions
you're implicitly relying on file permissions but you're not checking it
you're using string concatenation instead of path.join to join paths
you're constantly polling for new data instead of waiting for it to change
you're not catching exceptions of functions that can raise exception
you're not waiting for async operations to finish and you don't handle errors
The main problem that you're experiencing right now is most likely with the file permissions. The good news is that you don't need any file access for what you're doing and using files for that is not optimal anyway. All you need is to store the color in a variable if you don't need it it persist between server restarts - and even if you do then I would use a simple database for that.
For example:
// some initial value:
var color = '#ffffff';
app.post("/message", function (request, response) {
var color = request.body.Body;
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
response.send(color);
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
This is the first change that I would use - don't rely on the file system, permissions, race conditions etc.
Another problem that you had with your code was using blocking functions inside of request handlers. You should never use any blocking function (those with "Sync" in their name) except the first tick of the event loop.
Another improvement that I would make would be using WebSocket or Socket.io instead of polling for data on regular intervals. This would be quite easy to code. See this answer for examples:
Differences between socket.io and websockets
A plus of doing that would be that all of your students would get the color changed instantly and at the same time instead of in random moments spanning 2 seconds.
Update
I wrote an example of what I was describing above.
The POST endpoint is slightly different - it uses /color route and color=#abcdef instead of /message and Body=... but you can easily change it if you want - see below.
Server code - server.js:
// requires removed for brevity
const app = express();
const server = http.Server(app);
const io = socket(server);
let color = '#ffffff';
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', express.static(path.join(__dirname, 'html')));
io.on('connection', (s) => {
console.log('Socket.io client connected');
s.emit('color', color);
});
app.post('/color', (req, res) => {
color = req.body.color;
console.log('Changing color to', color);
io.emit('color', color);
res.send({ color });
});
server.listen(3338, () => console.log('Listening on 3338'));
HTML page - index.html:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Node Live Color</title>
<link href="/style.css" rel=stylesheet>
</head>
<body>
<h1>Node Live Color</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="/script.js"></script>
</body>
</html>
Style sheet - style.css:
body {
transition: background-color 2s ease;
background-color: #fff;
}
Client-side JavaScript - script.js:
var s = io();
s.on('color', function (color) {
document.body.style.backgroundColor = color;
});
What is particularly interesting is how simple is the client side code.
For your original endpoint use this in server.js:
app.post('/message', (req, res) => {
color = req.body.Body;
console.log('Changing color to', color);
io.emit('color', color);
res.end();
});
Full example is available on GitHub:
https://github.com/rsp/node-live-color
I tested it locally and on Heroku. You can click this button to deploy it on Heroku and test yourself:
Enjoy.
I think, the problem is in var dataStr = fs.readFileSync(dataPath).toString();. Please change your dataPath as follow:
var dataPath = __dirname + '/data/color.tmp';
And also make sure that file has read/write permission by the .
I am using hapijs in my MEAN stack and implemented socket.io (using this for reference: http://matt-harrison.com/using-hapi-js-with-socket-io/) Everything works fine, no problems there. It works great in my application!
However, there will be script I will be running via command line separately (which will be doing some maintenance on the application) that I was hoping to connect to the same web socket and be able to push to clients messages if data needs to be refreshed.
My index.js taken straight from the example:
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 3000 });
var io = require('socket.io')(server.listener);
io.on('connection', function (socket) {
socket.emit('Hello');
});
server.start();
I tried to create a separate JS file, and do a:
var socket = require('socket.io');
var io = socket.listen(3000);
Then passed io to send a message. This doesn't seem right... I guess I'm wondering if this can even be done. Messing around I've either created a separate web socket or no connection to the client.
Please let me know if I need to provide more information.
Thanks.
T
In your provided code, you're creating 2 servers. [io.listen()][1] listens on a port as a server.
What you need to do instead to pass messages around is to create a socket.io client in your separate script. There's a separate module for this called socket.io-client, which you can require to be a client:
client.js
var io = require('socket.io-client');
var socket = io('http://localhost:3000');
socket.on('beep', function () {
console.log('beep');
socket.emit('boop');
});
server.js
Here's a slightly updated version of your server script too (hapi v9.0.0 has a mandatory callback for server.start()):
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 3000 });
var io = require('socket.io')(server.listener);
io.on('connection', function (socket) {
socket.emit('beep');
socket.on('boop', function () {
console.log('boop');
});
});
server.start(function () {
console.log('Started Server!');
});
If you open up a couple of terminals and run these, you should see messages passed between them and beep and boop logged out: