Live audio recording and playing with 2 raspberry pis - javascript

I have a request...
I want to put a live audio with a transmitter a receiver, of course, I go through a server to link the two. I use for that socket.io and nodejs
I want to be able to read it on the web and mobile
But here is the problem - I do not know how to generate an audio stream that I can send then read it at the same time.
My environements:
Server:
let socket = require('socket.io')(4000)
socket.on('connection', function(client) {
client.on('audio', function(data){
client.broadcast.emit('emit', data)
})
})
Transmitter(raspberry pi 3) :
let socket = require('socket.io-client')('http://my_server')
socket.on('connection', function(server) {
server.emit('audio',{recorder: 'output_audio'})
})
Receiver (raspberry pi 3):
let socket = require('socker.io-client')('http://my_server')
socket.on('connection', function(server) {
server.on('emit', function(data) {
// read and play audio received
})
})

Related

Send data to Node.js Clients

I am trying to build a Node.js App to Monitor some Raspberry Pi's.
Since those Raspberries don’t have a static IP, they send an UDP Broadcast every 5 seconds.
I'm able to catch that Broadcast with Node.js, but I'm failing to trigger a new function to notify the Node.js Clients.
I tried WebSockets, ServerSendEvents and Socket.io.
I'm able to use Example Code and they work just fine.
But I'm not Experienced enough to build a function which will send data to the clients.
Node.js App:
// ==============================================================================================================
// ===== Dependencies ===========================================================================================
// ==============================================================================================================
var dgram = require('dgram');
var http = require('http');
var url = require("url");
var path = require("path");
var fs = require("fs");
// ==============================================================================================================
// ===== HTTP Serv ==============================================================================================
// ==============================================================================================================
var server = http.createServer(function(request, response) {
var uri = url.parse(request.url).pathname, filename = path.join(process.cwd(), uri);
var contentTypesByExtension = {
'.html': "text/html",
'.css': "text/css",
'.js': "text/javascript",
'.svg': "image/svg+xml"
};
fs.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
return;
}
if (fs.statSync(filename).isDirectory()) filename += '/index.html';
fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
return;
}
var headers = {};
var contentType = contentTypesByExtension[path.extname(filename)];
if (contentType) headers["Content-Type"] = contentType;
response.writeHead(200, headers);
response.write(file, "binary");
response.end();
});
});
});
// ==============================================================================================================
// ===== HeartBeat Broadcast ====================================================================================
// ==============================================================================================================
var bcast = dgram.createSocket('udp4');
bcast.on('message', function (message) {
console.log("Triggered: UDP Broadcast");
// If UDP Broadcast is received, send message/data to client.
});
bcast.bind(5452, "0.0.0.0");
// ==============================================================================================================
// ===== Start Server ===========================================================================================
// ==============================================================================================================
server.listen(80);
console.log("Static file server running/\nCTRL + C to shutdown");
EDIT:
I think I did not explain myself accurate enough.
I do not want to send a UDP message back.
This UDP Broadcast should fire an (Node.js) event, which should update the html and display the raspberry pi (whom send the UDP Package) as online.
EDIT:
In documentation from official page of nodejs (DOCUMENTATION):
var socket = require('socket.io')(http);
var bcast = dgram.createSocket('udp4');
bcast.bind(5452, "0.0.0.0");
bcast.on('message', function (message, remote) {
////if message is an Object pushed into Buffer////
message = message.toString('utf8');
socket.emit("HTML_Update", message);
//////////////////////////////////Solution for unedited question//////////////////////////
// var msgBuffer = Buffer.from(message.toString(); //creating a buffer //
// bcast.send(msgBuffer, 0, msgBuffer.length, remote.port, remote.address, (err) => { //
// bcast.close(); //
// }); //sending message to remote.address:remote.port (like localhost:23456) //
// //
// **build a function which will send data to the clients** //
//////////////////////////////////Solution for unedited question//////////////////////////
});
"If message is an Object pushed into Buffer" - lets say that one of the RPI turned on and started sending UDP message, what should the message pass to server so server can pass it to display: mac address only because if it sends something You can be sure its on, if it does not send its off simple as that. Also to show that change on client You should initialize TCP sockets on server to pass info to servers web page to update content on html with jquery.
Now here is the HTML java script part (I personally make main.js file and write all java script into it and use import it as src into html). Using jquery in main.js:
$(document).ready(function() {
var time = new Date();
var rpi = {
"list" : ["mac1", "mac2", "mac3"],
"time" : [time.getTime(), time.getTime(), time.getTime()],
"label" : ["label_ID1", "label_ID2", "label_ID3"]};
var socket = io.connect('http://your_server_address:80');
setInterval( function(){
for (var i = 0; i <= 2; i++){
if((rpi.time[i] + 10000) < time.getTime()){
$(rpi.label[i]).text("RPI " + rpi.list[i] + " is DOWN");
}
}
}, 5000);
socket.on("HTML_Update", function(data){
for (var i = 0; i<=2; i++) {
if (data.toString().equals(rpi.list[i])) {
$(rpi.label[i]).text("RPI: "+ rpi.list[i] + " is UP");
rpi.time[i] = time.getTime();
}
}
});
}
If You put text label in html to show if specific rpi is up or down this part of code works in this scheme:
Multiple RPI + Server - RPI sends UDP data with mac to server. Server device is used to receive data and show it on any device as web page and change data if RPI is UP/DOWN.

getting an error when trying to use socket.io

I am currently working with socket.io swift client. Running on Iphone SE. this is the swift code
let socket = SocketIOClient(socketURL: URL(string: "http://example.com:4000")!, config: [.log(true), .forcePolling(true)]);
socket.connect();
socket.on("connect") {data, ack in
print("socket is connected");
socket.emit("getData", ["data": 3]);
}
And on the server:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
socket.on('getData', function(result){
console.log(result);
});
});
app.listen(4000, function () {
console.log(' on at 4000!');
});
...And on the Xcode console, I get
2016-09-29 16:38:33.871895 proj[3070:1019256] LOG SocketEngine: Handshaking
2016-09-29 16:38:33.872301 proj[3070:1019256] LOG SocketEnginePolling: Doing polling request
2016-09-29 16:38:34.004312 proj[3070:1019256] LOG SocketEnginePolling: Got polling response
2016-09-29 16:38:34.004874 proj[3070:1019283] LOG SocketEngine: Got message: Cannot GET /socket.io/?transport=polling&b64=1
2016-09-29 16:38:34.005283 proj[3070:1019283] ERROR SocketIOClient: Got unknown error from server Cannot GET /socket.io/?transport=polling&b64=1
Which demonstrates a connection is made and the server is successfully found, but something else is wrong.
Would appreciate any help.
(Sidenote: If you don't need support for old browsers (or any browsers for that matter, since your client is a native mobile app) then you may consider using WebSocket which is an open standard. Socket.io is usually used to have a WebSocket-like functionality on browsers that don't support WebSocket. WebSocket on the other hand is an open standard, has a wide support (not only in browsers) and it has a better performance. See this answer for more details.)
Now, since you are already using Socket.io then here is how you can diagnose the problem. I would try to connect from a browser, which is a main way to connect with Socket.io, and see if that works. If it doesn't then it would mean that there's a problem in your server code. If it does then it could mean that there's a problem in your client. That would be the first thing to check. Going from there you can narrow the problem and hopefully fix it.
If you want to have a starting point with some working code using Socket.io, both server-site (Node.js) and client-side (browser vanilla JavaScript), then you can see the examples that I wrote originally for this answer, that are available on GitHub and on npm:
Socket.IO Server
Socket.IO server example using Express.js:
var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
console.error('socket.io connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js
Socket.IO Client
Socket.IO client example using vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html
You can compare the same code with WebSocket versions:
WebSocket Server
WebSocket server example using Express.js:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js
WebSocket Client
WebSocket client example using vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html
I hope this can help you evaluate whether staying with Socket.io or going with WebSocket is the right decision for you, and will give you some working client-side code to test your backend. The code is released under the MIT license (open source, free software) so feel free to use it in your project.

How can I have faye-websockets code running in the browser?

I'm new with node.js/express and all and I want to be able to notify any clients in browser about a new message received from some algorithm in the back-end. The publisher algorithm connect to the websocket and writes the message.
As far as I've looked there were examples which recommended websockets but I haven't been able to run that code in browser only in console.
Example client code:
var WebSocket = require('faye-websocket');
var ws = new WebSocket.Client('ws://localhost:1234');
var http = require('http');
var port = process.env.PORT || 1235;
var server = http.createServer()
.listen(port);
// receive a message from the server
ws.on('message', function(event) {
alert(JSON.parse(event.data));
});
Thank you
Found the answer after some trial/error iterations.
The algorithm now does a POST to an URL which in turn triggers a write to sockets for all connected clients via socket.io.
Client code:
var socket = io('http://localhost:7777');
socket.on('message', function (msg) {
document.body.insertAdjacentHTML( 'beforeend', '<div id="myID">'+msg+'</div>' );
});
And on the server, when client connects I retain it's socket into an array so I can write to each one:
Server code:
io.on('connection', function(socket){
console.log('a user connected: '+socket.id);
var id = clientCount++;
clientSockets[id] = socket;
socket.on('disconnect', function(){
console.log('user disconnected');
delete clientSockets[id];
socket = null
});
});
app.post('/alerts', function(req, res) {
req.accepts(['json', 'application']);
console.log("Algo did a POST on /alerts!");
// send the message to all clients
//console.log(req.body);
for(var i in clientSockets) {
clientSockets[i].send(JSON.stringify(req.body));
}
res.send(200);
});
In conclusion, I'm not using faye-websockets but instead socket.io

Node.js websocket-server and tcp-server connection

Related to this question Browser with JavaScript TCP Client I asked whether I can connect from a browser to a tcp server. I found out that it won't work so I asked for another solution. '0101' provided me to built up two servers. One tcp server for a c++ application that connects to and one websockets server that receives data from the browser. I have originally built up each one of them, but I don't know how to connect them so I can receive data from the browser in the c++ application.
Here is the websockets-server:
var ClientListe = {};
// Anzahl der Verbundenen Clients
var ClientAnzahl=0;
// Websocket-Server
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({host: '127.0.0.1',port: 80});
wss.on('connection', function(ws)
{
// Client-Anzahl hochzählen
ClientAnzahl++;
// Client-Verbindung mit in die Client-Liste Aufnehmen
ws['AUTH'] = ClientAnzahl;
ClientListe[ws['AUTH']] = ws;
// Ausgabe
console.log('client '+ClientAnzahl+' verbunden...');
ws.on('message', function(message)
{
console.log('von Client empfangen: ' + message);
for(client in ClientListe)
{
ClientListe[client].send('von Server empfangen: ' + message);
}
});
ws.on('close', function()
{
// Client aus der ClientListe Löschen
delete ClientListe[ws['AUTH']];
// Nachricht der Trennung an die Console ausgeben
console.log('Client '+ ws['AUTH'] +' getrennt.');
});
});
and here is the tcp server:
// Load the TCP Library
net = require('net');
// Keep track of the chat clients
var clients = [];
// Start a TCP Server
net.createServer(function (socket) {
// Identify this client
socket.name = socket.remoteAddress + ":" + socket.remotePort;
// Put this new client in the list
clients.push(socket);
// Send a nice welcome message and announce
socket.write("Welcome " + socket.name + "\n");
broadcast(socket.name + " joined the server\n", socket);
// Handle incoming messages from clients.
socket.on('data', function (data) {
broadcast(socket.name + " message: " + data, socket);
});
// Remove the client from the list when it leaves
socket.on('end', function () {
clients.splice(clients.indexOf(socket), 1);
broadcast(socket.name + " left the server.\n");
});
// Send a message to all clients
function broadcast(message, sender) {
clients.forEach(function (client) {
// Don't want to send it to sender
if (client === sender) return;
client.write(message);
});
// Log it to the server output too
process.stdout.write(message)
}
}).listen(80);
// Put a friendly message on the terminal of the server.
console.log("TCP Server running at localhost port 80\n");
Both are copied out of the internet for testing some cases
Create a TCP server (NodeJS example)
var net = require("net");
var server = net.createServer(function(c) { //'connection' listener
console.log('server connected');
c.on('end', function() {
console.log('server disconnected');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
Then in the same file (optionally of course) create a WS server with different port number
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({
port: 8080
});
wss.on("connection", function(ws) {
console.log("CONNECTED");
// ws.on("message"), ws.on("close"), ws.on("error")
});
Now you should have two servers, one for regular sockets and another one for WebSockets.
// As I mentioned in the previous question and Pete as well, it is a lot better to use WebSockets in C++ as well instead of creating two servers...
Drop the TCP server and make the C++ client connect to the websockets server instead. You'll need to implement the websockets protocol on top of your TCP connection at the C++ end (all you really need is a bit of pre-amble to negotiate the websocket). You have problems here with both servers trying to use port 80.
By the way, you should also consider using HTTPS for the websocket instead of HTTP since it avoids problems with proxy traversal. But get the HTTP case working first as this will be more complicated to implement on the C++ end.

How to create custom client events in node.js + socket.io

I'm just starting out with node.js, and from what I can tell so far, the way clients communicate with the server is through:
//Client Code 1
var iosocket = io.connect();
iosocket.on('connect', function () {
iosocket.send("Here's some info");
});
The server becomes aware of this when the 'message' event is recieved:
//Server Code 1
var socketio = require('socket.io');
var io = socketio.listen(server);
io.sockets.on('connection', function (client) {
client.on('message', function(msg) {
//msg== "Here's some info"
}
});
Now I want the client to be able to provide several distinct events such as:
//Server Code 2
client.on('buttonClicked', function() { ...
client.on('nameChanged', function(newName) { ...
But I'm having trouble figuring out how. The only solution I can come up with using the pieces I have is to send back messages, but have them contain key-value pairs of information:
//Server Code 3
client.on('message', function(msg) {
kvp = message.split(',');
if( kvp[0] == 'buttonClicked' )
...
else if( kvp[0] == 'nameChanged' )
...
}
But I'm certain there's a proper way of doing this that I just haven't seen in any examples yet. I expect that there's something similar to how the server can generate any event it wants using:
//Server Code 4
io.sockets.emit('serverCustomEvent', eventData);
Which are in turn monitored by the client using:
//Client Code 4
iosocket.on('serverCustomEvent', function(data) {
//process data
});
Can someone point me in the right direction?
You can use emit on the client to send custom messages to the server.
iosocket.emit('serverCustomEvent', data);
and on the server
io.sockets.on('connection', function(socket) {
socket.on('serverCustomEvent', login);
});

Categories

Resources