Socket.io receiving data from multiple sockets in Node - javascript

I started developing in Node just a couple of days ago. I'm currently developing an online game that uses Node as server-side application. This application simply provides the .html and .js files to the client and handles the logic of the game.
I'm using Socket.io to exchange data with the clients. When a new client connects to the server through Socket.io the program looks for a room (array of objects containing the sockets for the two users and the game object that handles the logic) that has an empty space and places the user (registering the socket) in it.
I've been able to correctly send to each client the position of the sprites, but I have a problem with retrieving data from each socket: If I try to send some data from the client to the server, that data flows through only one of the two sockets, no matter which client is sending that.
Initializing the room array
for(var i = 0; i < roomsNumber; i++) {
//player1 and player 2 are going to store the sockets
rooms[i] = { player1 : null, player2 : null, game: null};
}
Socket.io handling the connections
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log("We have a new client: " + socket.id);
insertPlayer(socket);
socket.on('disconnect', function() {
console.log("Client has disconnected: " + socket.id);
removePlayer(socket);
});
});
Adding the clients to rooms
function insertPlayer(socket) { //Check for an empty spot in a room
for(var i = 0; i < rooms.length; i++) {
if(!rooms[i].player1) {
rooms[i].player1 = socket; //Register the socket to the room
checkRooms();
return;
}
if(!rooms[i].player2) {
rooms[i].player2 = socket; //Register the socket to the room
checkRooms();
return;
}
}
}
Creating the Game object when a room if full (and destructing it when a player leaves)
function checkRooms() { //Checks if a room is full to initialize the game
for(var i = 0; i < rooms.length; i++) {
if(rooms[i].player1 && rooms[i].player2 && !rooms[i].game) {
rooms[i].game = new Game([rooms[i].player1, rooms[i].player2]); //The constructor passes the sockets
console.log('New game started');
}
if((!rooms[i].player1 || !rooms[i].player2) && rooms[i].game) {
rooms[i].game.endGame();
rooms[i].game = null;
console.log('Game stopped');
}
}
}
Receiving data in the Game class
constructor(sockets) {
this.sockets = sockets;
this.snakes = [];
var self = this;
for(var i = 0; i < this.sockets.length; i++) {
this.snakes[i] = new Snake(i*100 + 100, 200);
var currentSnake = this.snakes[i];
var currentSocket = this.sockets[i];
currentSocket.on('keyPressed', function(data) {
currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite
console.log(currentSocket.id + " - " + data);
});
}

I see a problem with the currentSnake variable in your Game constructor. That variable is scoped to your whole constructor so there's only one variable there, but you're trying to have a separate variable for each player and that isn't working. Thus, every time you get the keyPressed message, you operation on the same snake, no matter which player the key came from.
If you're using node.js v6+, then change var currentSnake in that constructor to let currentSnake so that the variable is separately scoped to each invocation of the for loop.
constructor(sockets) {
this.sockets = sockets;
this.snakes = [];
var self = this;
for(var i = 0; i < this.sockets.length; i++) {
this.snakes[i] = new Snake(i*100 + 100, 200);
// change these to be declared with let so they are separately scoped
// for each invocation of the for loop
let currentSnake = this.snakes[i];
let currentSocket = this.sockets[i];
currentSocket.on('keyPressed', function(data) {
currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite
console.log(currentSocket.id + " - " + data);
});
}
}
Or, if you are running an older version of node.js, switch to .forEach() to replace the for loop as this will also make a new separate scope for each invocation of the loop.
constructor(sockets) {
this.sockets = sockets;
this.snakes = [];
var self = this;
this.sockets.forEach(function(currentSocket, i) {
this.snakes[i] = new Snake(i*100 + 100, 200);
var currentSnake = this.snakes[i];
currentSocket.on('keyPressed', function(data) {
currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite
console.log(currentSocket.id + " - " + data);
});
});
}

Related

Getting a 'Cannot read property 'on' of undefined' when calling a function in a class in a node module

Here's my code:
From the module's index.js:
class TSL5 extends EventEmitter {
constructor () {
super()
//Message Format
this._PBC = 0 //offset
this._VER = 2
this._FLAGS = 3
this._SCREEN = 4
this._INDEX = 6
this._CONTROL = 8
this._LENGTH = 10
}
listenUDP(port) {
this.server = dgram.createSocket('udp4')
this.server.bind(port)
this.server.on('message',(msg, rinfo) => {
this.processTally(msg,rinfo)
debug('Message recieved: ', msg)
})
this.server.on('listening', () => {
var address = this.server.address();
debug(`server listening ${address.address}:${address.port}`);
});
this.server.on('error', (err) => {
debug('server error: ', err);
throw err;
});
return this.server;
}
processTally(data,rinfo) {
let buf = Buffer.from(data)
let tally = { display: {} }
tally.sender = rinfo.address
tally.pbc = buf.readInt16LE(this._PBC)
tally.ver = buf.readInt8(this._VER)
tally.flags = buf.readInt8(this._VER)
tally.screen = buf.readInt16LE(this._SCREEN)
tally.index = buf.readInt16LE(this._INDEX)
tally.control = buf.readInt16LE(this._CONTROL)
tally.length = buf.readInt16LE(this._LENGTH)
tally.display.text = buf.toString('ascii', this._LENGTH+2)
tally.display.rh_tally = (tally.control >> 0 & 0b11);
tally.display.text_tally = (tally.control >> 2 & 0b11);
tally.display.lh_tally = (tally.control >> 4 & 0b11);
tally.display.brightness = (tally.control >> 6 & 0b11);
tally.display.reserved = (tally.control >> 8 & 0b1111111);
tally.display.control_data = (tally.control >> 15 & 0b1);
this.emit('message',tally)
}
and then the server side index.js:
let umd = new TSL5;
for (let i = 0; i < source_connections.length; i++) {
if (source_connections[i].sourceId === sourceId) {
AddPort(port, sourceId);
logger(`Source: ${source.name} Creating TSL 5.0 UDP Connection.`, 'info-quiet');
//source_connections[i].server = dgram.createSocket('udp4');
//source_connections[i].server.bind(port);
source_connections[i].server = umd.listenUDP(port);
source_connections[i].server.on('message', function (message) {
processTSL5Tally(sourceId, message);
});
logger(`Source: ${source.name} TSL 5.0 Server started. Listening for data on UDP Port: ${port}`, 'info');
for (let j = 0; j < sources.length; j++) {
if (sources[j].id === sourceId) {
sources[j].connected = true;
break;
}
}
UpdateSockets('sources');
UpdateCloud('sources');
break;
}
}
Whenever I try to call the function that the lower block of code is in, then I get the Cannot read property 'on' of undefined error. The only way to get the error to go away is add a return this.server to the listenUDP function. If I do this however, then all of the data that function is supposed to emit through the processTally function is lost.
Your current issue is caused by those lines:
source_connections[i].server = umd.listenUDP(port);
source_connections[i].server.on('message', function (message) {
processTSL5Tally(sourceId, message);
});
source_connections[i].server is the result of calling listenUDP. Therefore if you do not return the server (through return this.server), then there's nothing to call .on upon.
And returning the server is causing another issue that you have:
// in processTally
this.emit('message',tally)
But inside your loop, you're calling
source_connections[i].server.on('message', function (message) {
The event emitter itself is emitting this new "message", but you are still listening on the "event emitter's server". The emitter (TSL5 class) is a wrapper over the server. So instead of listening on the server's message, you should listen on the event emitter, that emits "message" as well, that is the result of working on the internal server's message:
// just the emitter, not the server
source_connections[i].on('message', function (message) {
processTSL5Tally(sourceId, message);
});
As a side note - just remember you're having a single instance for the emitter. Therefore if that loops runs multiple times (for different connections), things will get scrambled. Therefore you'd probably need to create new emitter for each iteration, but not sure if that's your case.

How to fix BeagleBone Black Service File Autostart Script Error, status=203/EXEC

I want my BeagleBone machine to automatically start a script called server.js.
It includes BoneScript (BeagleBone's unique function) and many functions including reading voltage and ampere from other machines.
I used this tutorial
Executing a script on startup using BeagleBone Black
It kept showing status=203/EXEC error.
I tried the same tutorial for simple programs without Bonescript and Functions.
Indeed, simple sending and receiving scripts are working without any issue.
How can I remove the error?
I think it happens from importing BeagleScript and Functions.
I'm not familiar with Linux environment.
Can anyone help to solve the issue?
Thanks,
https://stackoverflow.com/questions/28854705/executing-a-script-on-startup-using-beaglebone-black
-crontab
-service file
-8 days of trying, fail and searching Google
Service File (password hidden *****)
[Unit]
After=network-online.target
[Service]
Type=simple
ExecStart=/var/lib/cloud9/Projects echo ****** | sudo -S bash scriptname.sh
[Install]
WantedBy=multi-user.target
Shell File
#!/bin/bash
cd /var/lib/cloud9/Projects
node server.js
Javascript
// Constants and global parameters
const NUM_ADC_READS = 100;
const ADC_OFFSET = 0.027 // Offset for difference between ADC_GND and GND
const ZERO_OFFSET = 0.5; // Current sensor output centred at midpoint
const ADC_GAIN = 1.8; // Function returns 0-1, 0=0V, 1=1.8V
const VOLT_DIVIDER = 0.3491; // Voltage divider to reduce from 5V current sensor output to <1.8V ADC input
const MAX_VOLTAGE = 1.7456; // Max voltage divider output for max current sensor output
const CURRENT_CONVERSION = 25; // Current sensor sensitivity 25 A/V
const COMBINED_GAIN = 128.9; // CURRENT_CONVERSION * ADC_GAIN / VOLT_DIVIDER
const COMBINED_OFFSET = 0.473; // ZERO_OFFSET - ADC_OFFSET
//Loading modules
var http = require('http');
var fs = require('fs');
var path = require('path');
var b = require('bonescript');
// Create variables for relays
var relay_load_1 = "P8_12"; // Relay control for output load 1
var relay_load_2 = "P8_11"; // Relay control for output load 2
var relay_bat_bank_1 = "P8_7"; // Relay control for input battery bank 1
var relay_bat_bank_2 = "P8_8"; // Relay control for input battery bank 2
var relay_bat_bank_3 = "P8_10"; // Relay control for input battery bank 3
// Create variables for current readings
var current_load = ["P9_39", "P9_40"];
var current_bat = ["P9_37", "P9_38", "P9_33"];
// Initialize the relay control variables as OUTPUTS
b.pinMode(relay_load_1, b.OUTPUT);
b.pinMode(relay_load_2, b.OUTPUT);
b.pinMode(relay_bat_bank_1, b.OUTPUT);
b.pinMode(relay_bat_bank_2, b.OUTPUT);
b.pinMode(relay_bat_bank_3, b.OUTPUT);
// Initialize the server on port 8888
var server = http.createServer(function (req, res) {
// requesting files
var file = '.'+((req.url=='/')?'/index.html':req.url);
var fileExtension = path.extname(file);
var contentType = 'text/html';
// Uncoment if you want to add css to your web page
/*
if(fileExtension == '.css'){
contentType = 'text/css';
}*/
fs.exists(file, function(exists){
if(exists){
fs.readFile(file, function(error, content){
if(!error){
// Page found, write content
res.writeHead(200,{'content-type':contentType});
res.end(content);
}
})
}
else{
// Page not found
res.writeHead(404);
res.end('Page not found');
}
})
}).listen(1111);
// Loading socket io module
var io = require('socket.io').listen(server);
// When communication is established
io.on('connection', function (socket) {
socket.on('changeState_load_1', handleChangeState_load_1);
});
io.on('connection', function (socket) {
socket.on('changeState_load_2', handleChangeState_load_2);
});
io.on('connection', function (socket) {
socket.on('changeState_bat_1', handleChangeState_bat_1);
});
io.on('connection', function (socket) {
socket.on('changeState_bat_2', handleChangeState_bat_2);
});
io.on('connection', function (socket) {
socket.on('changeState_bat_3', handleChangeState_bat_3);
});
// Change relay state when a button is pressed
function handleChangeState_load_1(data) {
var newData = JSON.parse(data);
var status;
if (newData.state == 1) {
status = "OFF"
}
else {
status = "ON"
}
console.log("Load 1 Relay =" + status);
//console.log("Load 1 Relay =" + newData.state);
// turn the load relay ON or OFF
b.digitalWrite(relay_load_1, newData.state);
return status;
}
//function handleChangeState_load_1(data) {
// var newData = JSON.parse(data);
// console.log("Load 1 Relay =" + newData.state);
// turn the load relay ON or OFF
// b.digitalWrite(relay_load_2, newData.state);
// return newData.state;
//}
// Change relay state when a button is pressed
function handleChangeState_load_2(data) {
var newData = JSON.parse(data);
console.log("Load 2 Relay =" + newData.state);
// turn the load relay ON or OFF
b.digitalWrite(relay_load_2, newData.state);
}
// Change relay state when a button is pressed
function handleChangeState_bat_1(data) {
var newData = JSON.parse(data);
console.log("Bat 1 Relay =" + newData.state);
// turn the battery bank relay ON or OFF
b.digitalWrite(relay_bat_bank_1, newData.state);
}
// Change relay state when a button is pressed
function handleChangeState_bat_2(data) {
var newData = JSON.parse(data);
console.log("Bat 2 Relay =" + newData.state);
// turn the battery bank relay ON or OFF
b.digitalWrite(relay_bat_bank_2, newData.state);
}
// Change relay state when a button is pressed
function handleChangeState_bat_3(data) {
var newData = JSON.parse(data);
console.log("Bat 3 Relay =" + newData.state);
// turn the battery bank relay ON or OFF
b.digitalWrite(relay_bat_bank_3, newData.state);
}
// Read load currents from analog inputs
function readLoadCurrent(data) {
var current = 0;
var max_current = 0;
var min_current =1.0;
for (let i = 0; i < NUM_ADC_READS; i++) {
current = b.analogRead(current_load[data]);
if (max_current < current) max_current = current;
if (min_current > current) min_current = current;
}
// console.log("Load Current =" + ((max_current - min_current)/2.0));
return ((((max_current - min_current)/2.0)) * COMBINED_GAIN);
}
// Read battery bank currents from analog inputs
function readBatCurrent(data) {
var current = 0;
var max_current = 0;
var min_current = 1.0;
for (let i = 0; i < NUM_ADC_READS; i++) {
current = b.analogRead(current_bat[data]);
if (max_current < current) max_current = current;
if (min_current > current) min_current = current;
}
// console.log("Bat Current =" + ((max_current - min_current)/2.0));
return ((((max_current - min_current)/2.0)) * COMBINED_GAIN);
}
var listener = io.listen(server);
var currentBat_1 = readBatCurrent(1);
function battery1power(data){
while(1) { return currentBat_1*data;
}
}
listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('battery1power', {'battery1power': battery1power(0)});
}, 2000);
});
listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('currentLoad_1', {'currentLoad_1': readLoadCurrent(0)});
}, 2000);
});
listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('currentLoad_2', {'currentLoad_2': readLoadCurrent(1)});
}, 2000);
});
listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('currentBat_1', {'currentBat_1': readBatCurrent(0)});
}, 2000);
});
listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('currentBat_2', {'currentBat_2': readBatCurrent(1)});
}, 2000);
});
/*listener.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('currentBat_3', {'currentBat_3': readBatCurrent(2)});
}, 2000);
});*/
// Displaying a console message for user feedback
server.listen(console.log("Server Running ..."));
var currentBat_2 = readBatCurrent(1);
function battery2power(voltage){
while(1){ return currentBat_2*voltage;}}
var currentBat_3 = readBatCurrent(2);
function battery3power(voltage){
return currentBat_3*voltage;
}
var currentLoad_1 = readLoadCurrent(0);
function load1power(voltage){
return currentLoad_1*voltage;
}
var currentLoad_2 = readLoadCurrent(1);
function load2power(voltage){
return currentLoad_2*voltage;
}
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
// Create periodical which ends a message to the client every 5 seconds
// 1000 ms is 1 second, so 5 second is 5000 ms
var interval = setInterval(function() {
//console.log('powerBat_1 ' + battery1power(116).toFixed(4));
client.send(
//'Serial Number: A33******************' + load1shandleChangeState_load_1(0) +
'33333powerBat_1 ' + battery1power(116).toFixed(4) +
';powerBat_2 ' + battery2power(110).toFixed(4) +
';powerBat_3 ' + battery3power(110).toFixed(4) +
';powerLoad_1 ' + load1power(116).toFixed(4) +
';powerLoad_2 ' + load2power(110).toFixed(4) +
';currentLoad_1 ' + readLoadCurrent(0).toFixed(4) +
';currentLoad_2 ' + readLoadCurrent(1).toFixed(4) +
';currentBat_1 ' + readBatCurrent(0).toFixed(4) +
';currentBat_2 ' + readBatCurrent(1).toFixed(4) +
';currentBat_3 ' + readBatCurrent(2).toFixed(4), 0, 10000, PORT, HOST, 0);
},5);
Error Message
● scriptname.service
Loaded: loaded (/etc/systemd/system/scriptname.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2019-09-05 23:47:06 UTC; 8s ago
Main PID: 27859 (code=exited, status=203/EXEC)
You may want to try to set up your .service file like this:
[Unit]
Description=Your Description for your File!
[Service]
ExecStart=/home/debian/var/lib/cloud9/file.js
[Install]
WantedBy=multi-user.target
Use the .service file outside of the Cloud9 IDE. So, this will help:
Create a directory
cd into that directory
Put your files in the directory you just created and cd'd into
Last but not least, use the /etc/systemd/system/ dir. to establish your .servive file.
Now...
If you are in your /home/debian/ dir. and have already created your .service file, change the .service file to look like this idea:
[Unit]
Description=Whatever you want goes here to describe your file use...
[Service]
ExecStart=/home/debian/<NewlyMadeDirectory>/<TheFileYouWantToRunWithFileSuffix>
[Install]
WantedBy=multi-user.target
Try that idea and get back to me.
Seth
P.S. I will wait to hear from you on how this worked out. Oh and you need, in the node.js file, to make sure it is executable and then use chmod a+x yourFile.js to set permissions.

Reduce lags on a nodejs game

I have created a nodejs game. i have a setInterval function on the server which sends all the objects near the player. but it doesnt seem to be as smooth as i get when i run it locally. the data package has about 60 objects. here's the server code for sending objects and receiving them on the client. any way to compress the package or reduce the lags? pinka.herokuapp.com
server:
setInterval(function() {
server.update();
for(var key in sockets) {
var socket = sockets[key];
var player = server.players.filter(function(p) {
return p.id == socket.id
})[0];
var package = [];
var blobs = server.getNodesInRange(player.centerX, player.centerY);
for(var i = 0; i < blobs.length; i++) {
var b = blobs[i];
package.push({
x: b.x,
y: b.y,
nick: b.nick,
size: Math.sqrt(b._mass) * 10,
hue: b.hue
});
};
socket.emit("update blobs", package);
socket.emit("leaders", server.getLeaders());
if(player.blobs.length == 0) {
socket.emit("dead");
continue;
}
var translateX = player._centerX * player._drawZoom - player.screenWidth / 2;
var translateY = player._centerY * player._drawZoom - player.screenHeight / 2;
socket.emit("center and zoom", {
centerX: translateX,
centerY: translateY,
zoom: player._drawZoom
});
}
}, 1000/60);
client:
socket.on("update blobs", function(data) {
blobs = data;
});
this is the whole communication part.
As Jonas W. said, the problem is in the server-client communication.
To be efficient a realtime system with socket.io should be based on events and not in interval checks.
I'd suggest you to have something like this:
On the client, emit a 'user:move' event when the user moves. Prevent too many events to relief the server with unnecessary updates.
On the server, react to a specific 'player:move' event. If the events needs to be broadcasted to the other players, a filter with the ones that can actually "see" the action will avoid unnecessary information for the client too.
An example with pseudo code:
Client
let updating = false;
let timeout = 0;
// Assuming this function is triggered everytime the user moves (i.e. presses a key)
onUserMove (data) {
if ('same press as before' && updating) {
// ignore move if it's the same that has just been done
return;
} else {
socket.emit('user:move', data);
// 'Block' the emit for same movement for 20ms
updating = true;
clearTimeout(timeout);
timeout = setTimeout(() => {
updating = false;
}, 20);
}
}
Server
socket.on('user:move', (data) => {
const dataForTheUser = processingYouAreAlreadyDoing(data);
socket.emit('data:for:user', dataForTheUser);
// In case there's information to be sent to every user
const dataToBroadcast = getDataToBroadcast(data);
const usersToBroadcast = getCloseUsers(data);
for (let user in usersToBroadcast) {
user.socket.emit('whatever:event', dataToBroadcast);
}
})

Javascript sharedworker inside for loops

I'm trying to create 7 Javascript shared workers inside a for loop.
My IDE (Pycharm) is giving me a warning for these two variables container-frame and worker:
"Mutable variable is accessible from closure"
Each of these shared worker is communicating with network_worker.js
Below is my JS code:
socket = io.connect('http://' + document.domain + ':4999/layout');
// Set up CSS
for (var i=0; i<player_dict.length; i++) {
var _id = player_dict[i]['_id'];
var container_frame = document.getElementById("container-frame-" + _id);
container_frame.style.display = "none";
setup_communication();
console.log(_id)
var client_id = _id;
var alarm_flag= "";
var alarm_metric="";
if (client_id != null && client_id == 0 && parseInt(location.port) == 4999) { // player_0_hack (for now). Remove and have work properly.
label = "";
} else if (client_id != null){
label = "Service " + (parseInt(location.port) - 5000 + 1);
} else {
label = "Invalid player id";
}
var worker = new SharedWorker('../static/js/network_worker.js', client_id);
console.log(worker);
worker.port.addEventListener('message', worker_callback, false);
window.addEventListener("beforeunload", function () {
worker.port.postMessage('label_close');
});
worker.port.start();
function worker_callback(e) {
console.log(e.data)
if(e.data.type == "update_label") {
console.log(container_frame)
container_frame.style.animationDuration = Math.random() + "s";
}
}
worker.port.postMessage({type: "label_connection", payload: {domain: document.domain, port: location.port, client_id: client_id, label: label}, alarm_flag: alarm_flag, alarm_rate: 1, alarm_metric: alarm_metric});
}
Ultimately what I'm trying to do is animating the container-frame for 7 HTML elements. I'm iterating over these elements using the for loop. These animations happen when an event is triggered from a JS script (update label).
Currently, I have 7 HTML elements. The last element only is having the animation working properly.
My doubt is that when I have put the worker_callback function inside the for loop, the JS compiler became confused about the scope of container_frame but I'm not sure.
Any suggestions please ?
The problem was the two variables container_frame and worker where defined as var not const. Thanks to #Edmund Lee

How to display data from socket.io connection?

I am trying to use socket.io to transfer data from a node.js script to an HTML webpage. The node.js script is executing a function (that uses a BeagleBone Black sensor) and returning a certain value. I want to transfer this value via a socket to the HTML page. I then want the HTML page to display this value. I have been able to get the webpage to log everything on Chrome's Javascript console. I don't understand though why the data is not being printed on the actual page.
// Install socket.io: terminal, goto /var/lib/cloud9 and enter: npm install socket.io
var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
var fs = require('fs');
var b = require('bonescript');
var fulldata = 0;
// count how many pulses
var pulses = 0;
// track the state of the pulse pin
var lastflowpinstate;
//time between pulses
var lastflowratetimer = 0;
// used to calculate a flow rate
var flowrate;
// Interrupt is called once a millisecond, looks for any pulses
var value = 0;
var liters = 0;
app.listen(8090);
/* socket.io options go here
io.set('log level', 2); // reduce logging - set 1 for warn, 2 for info, 3 for debug
io.set('browser client minification', true); // send minified client
io.set('browser client etag', true); // apply etag caching logic based on version number
*/
console.log('Server running on: http://' + getIPAddress() + ':8090');
var Sensor = "P8_19";
b.pinMode('P8_19', b.INPUT);
console.log(b.digitalRead('P8_19'));
function handler (req, res) {
if (req.url == "/favicon.ico"){ // handle requests for favico.ico
res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
//console.log('favicon requested');
return;
}
fs.readFile('SensorHTML.html', // load html file
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function(socket) {
setInterval(function() {
//doSomething();
b.pinMode('P8_19', b.INPUT);
value = b.digitalRead('P8_19');
if (value == lastflowpinstate)
{
lastflowratetimer++;
//return; // nothing changed!
}
if (value == '1')
{
//low to high transition!
pulses++;
}
lastflowpinstate = value;
flowrate = 1000.0;
flowrate /= lastflowratetimer; // in hertz
lastflowratetimer = 0;
liters = pulses / (450);
fulldata += liters;
JSON.stringify(fulldata);
//send temperature reading out to connected clients
socket.emit('water', {'water': fulldata});
}, 500);
//function doSomething() {
});
// Get server IP address on LAN
function getIPAddress() {
var interfaces = require('os').networkInterfaces();
for (var devName in interfaces) {
var iface = interfaces[devName];
for (var i = 0; i < iface.length; i++) {
var alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
return alias.address;
}
}
return '0.0.0.0';
}
And the HTML file:
<html>
<head>
<!-- include bootstrap, jquery for easy div manipulation -->
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="node_modules/socket.io-client/dist/socket.io.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<h1>SmartWater</h1>
<th>Flow (liters)</th>
<script>
var socket = io.connect('http://192.168.7.2:8090/'); //enter the IP of your beaglebone and port you are using in app.js
socket.on('water', function(data) {
//$('#').html(data.full_data);
$('#water').html(data.fulldata);
console.log(data.fulldata);
});
</script>
<div id="water"></div>
</body>
</html>
Any help or insight would be appreciated.
In the client, change:
$('#water').html(data.fulldata);
console.log(data.fulldata);
to this:
$('#water').html(data.water);
console.log(data.water);
The property name you're setting on the server is water, not fulldata.
Also, on the server, remove this line:
JSON.stringify(fulldata)
There is no need to stringify a single number that is just being passed as a property on an object. In fact, it will probably cause a problem for you.
On the server, you will also need to save the timer from the call to setInterval() so you can clearInterval() when the socket is disconnected. I would suggest storing the interval timer handle as a custom property on the socket object itself as that will make it easier to access in the 'disconnect' event.
Here's an example of how to do that:
io.on('connection', function(socket) {
var tm = setInterval(function() {
//doSomething();
b.pinMode('P8_19', b.INPUT);
value = b.digitalRead('P8_19');
if (value == lastflowpinstate)
{
lastflowratetimer++;
//return; // nothing changed!
}
if (value == '1')
{
//low to high transition!
pulses++;
}
lastflowpinstate = value;
flowrate = 1000.0;
flowrate /= lastflowratetimer; // in hertz
lastflowratetimer = 0;
liters = pulses / (450);
fulldata += liters;
//send temperature reading out to connected clients
socket.emit('water', {'water': fulldata});
}, 500);
socket.on('disconnect', function() {
clearInterval(tm);
});
//function doSomething() {
});
Thanks for the tip (about turning off the timer). I made some edits in the server code, but I'm not sure if they're correct.
io.on('connection', function(socket) {
function to_start()
{
tm=window.setInterval('timer()', 500);
}
to_start();
function timer()
{
....
}
socket.on('disconnect', function () {
window.clearInterval(tm);
});
});

Categories

Resources