I am currently trying to make a 2 player HTML/JS boardgame and am using PeerJS to connect two players sessions together but cant get it to work.
Here is a quick test i havent been able to get to send/receive data even though connecting works
On the sending end
var peer = new Peer();
var con;
function c() {
con = peer.connect('id');
con.on('error', function(err) { alert(err); });
con.on('data', function(data){ console.log(data) });
};
function send() {
con.on('open', function(){
con.send('HELLO WORLD')
});
}
and on the receiving end:
var peer = new Peer('id');
peer.on('connection', function(con){
console.log('connected')
con.on('error', function(err) { alert(err) });
con.on('open', () => {
con.on('data', (data) => {
console.log('Incoming data', data);
con.send('REPLY');
});
});
});
You need to configure stun and turn servers for Peer. Here is complete working example.
/**********
var peer = new Peer({
config: {
'iceServers': [
{ url: 'stun:stun.l.google.com:19302' },
]
} /* Sample servers, please use appropriate ones */
*******/
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
var peer = new Peer({
config: {
'iceServers': [
{ url: 'stun:stun.l.google.com:19302' },
]
} /* Sample servers, please use appropriate ones */
});
peer.on("open", function (id) {
$("#chat").hide()
$("#peerid").text(id)
$("form#connect").submit(function () {
var remoteID = $(this).find('input[type="text"]').val()
console.log("connect to", remoteID);
var conn = peer.connect(remoteID)
gotConnection(conn)
return false;
})
})
peer.on("connection", gotConnection)
function gotConnection(conn) {
conn.on("error", function (err) {
console.error("connection error", err, conn)
})
conn.on("open", function () {
console.log("conn open", conn)
$("#remoteid").text(conn.peer)
$("form#connect").hide()
$("#chat").show()
$("#chat form").submit(function () {
var message = $(this).find('input[type="text"]').val()
console.log("send", message);
conn.send(message)
$(this).find('input[type="text"]').val("")
$("#messages").append($('<li>' + peer.id + ': ' + message + '</li>'))
return false;
})
conn.on("data", function (data) {
console.log("got", data);
$("#messages").append($('<li>' + conn.peer + ': ' + data + '</li>'))
})
})
}
</script>
Related
have a strange thing happening running a Google cloud function. The function starts and logs the user id and job id as expected. Then it calls firestore db and basically sits there for 1 minute, sometimes 2 before it executes the first call... It was even timing out on 240 seconds.
const AWS = require('aws-sdk');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.run = functions.https.onCall((data, context) => {
var id = data.id;
var userid = data.uid;
var retry = data.retry;
var project;
var db = admin.firestore();
var storage = admin.storage();
console.log("Starting Collect");
console.log("UID: " + userid);
console.log("id ID: " + id);
// Times out on this call
db.collection("users").doc(userid).collection("ids").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
createexport();
}).catch(function(err) {
console.log(err);
error('Loading DB Error, ' + err, false);
});
function createexport() {
db.collection("exports").doc(id).set({
status: 'Collecting',
stage: 'Export Checker',
percent: 0,
id: id,
}).then(function() {
console.log("Creating Export");
setdb();
}).catch(function(err) {
error("Error creating export in database :" + err, true)
});
}
function setdb() {
db.collection("users").doc(userid).collection("ids").doc(id).update({
status: 'Analyzing Files',
stage: 'Collecting'
}).then(function() {
getaudio();
}).catch(function(err) {
error("Error updating users id in database :" + err, true)
});
}
function getaudio() {
const from = userid + '/projects/' + project.originalproject.id + '/audio.' + project.originalproject.extension;
const to = userid + '/' + id + '/audio.' + project.originalproject.extension;
storage.bucket('---------').file(from).copy(storage.bucket('---------').file(to)).then(function() {
console.log("Collecting files");
copy2();
}).catch(function(err) {
error('Collecting Audio Error, ' + err, true);
});
}
function copy2() {
const from = userid + '/projects/' + project.originalproject.id + '/overlay.png';
const to = userid + '/' + id + '/overlay.png';
storage.bucket('--------.appspot.com').file(from).copy(storage.bucket('---------').file(to)).then(function() {
updateexport();
}).catch(function(err) {
error('Collecting Overlay Error, ' + err, true);
});
}
function updateexport() {
db.collection("exports").doc(id).update({ status: "Waiting" }).then(function() {
console.log("All files collected");
return { status: 'Success' };
}).catch(function(err) {
error("Error creating export entry in database :" + err, true)
});
}
function error(evt, evt2) {
AWS.config.update({ region: "us-east-1" });
var html;
var sub = 'Error with id ' + id;
console.log(evt);
if (evt2) {
db.collection('users').doc(userid).collection('ids').doc(id).update({
status: 'Error'
}).catch(function(err) {
console.log(err);
});
db.collection("exports").doc(id).update({
status: 'Error',
stage: 'Collecting',
error: evt,
}).catch(function(err) {
console.log(err);
});
html = `
Username: ${project.username} <br>
UserID: ${userid} <br>
Email: ${project.email} <br>
id: ${id}
`
} else {
html = `id: ${id}<br>
UserID: ${userid} <br>
Message: Error logged was: ${evt}
`
}
var params = {
Destination: {
ToAddresses: [
'errors#mail.com'
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: html
},
},
Subject: {
Charset: 'UTF-8',
Data: sub
}
},
Source: 'errors#mail.com',
ReplyToAddresses: [
project.email
],
};
var sendPromise = new AWS.SES({
apiVersion: "2010-12-01",
"accessKeyId": "-----------",
"secretAccessKey": "------------------------",
"region": "--------",
}).sendEmail(params).promise();
sendPromise.then(function(data) {
return { data: data };
}).catch(function(err) {
return { err: err };
});
}
});
Seems to me to be way too long for a database call of only a few kb. I will attach the cloud log to show time difference. After this initial slump it then performs as expected.
Cloud log image
Anyone got any ideas as to why this could be happening? Many thanks...
Your function is appearing to hang because it isn't handling promises correctly. Also, it doesn't appear to be sending a specific response to the client app. The main point of callable functions is to send a response.
I suggest reviewing the documentation, where you will learn that callable functions are required to return a promise that resolves with an object to send to the client app, after all the async work is complete.
Minimally, it will take a form like this:
return db.collection("users").doc(userid).collection("files").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
return { "data": "to send to the client" };
}
Note that the promise chain is being returned, and the promise itself resolves to an object to send to the client.
I have problem with my Lambda, actually in promise nodejs. I have wrote code like this in my Lambda:
'use strict'
const Alexa = require('alexa-sdk');
const mqtt = require('mqtt');
const APP_ID = undefined;
const WELCOME_MESSAGE = 'Welcome to the lamp control mode';
const WELCOME_REPROMT = 'If you new please say help'
const HELP_MESSAGE = 'In this skill you can controlling lamp to turn off or on, dim the lamp, change the lamp color and schedule the lamp';
const STOP_MESSAGE = 'Thanks for using this skill, Goodbye!';
const OFF_RESPONSE = 'Turning off the lamp';
const ON_RESPONSE = 'Turning on the lamp';
const DIM_RESPONSE = 'Dimming the lamp';
const CHANGE_RESPONSE = 'Changing the lamp color';
const AFTER_RESPONSE = 'Wanna control something again ?';
const handlers = {
'LaunchRequest': function () {
this.emit(':ask', WELCOME_MESSAGE, WELCOME_REPROMT);
},
'OnOffIntent' : function () {
var status = this.event.request.intent.slots.status.value;
var location = this.event.request.intent.slots.location.value;
console.log(status);
console.log(location);
if (status == 'on') {
// Promise Start
var mqttPromise = new Promise(function(resolve, reject) {
var options = {
port: '1883',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
username: 'username',
password: 'password',
};
var client = mqtt.connect('mqtt://broker-address', options)
client.on('connect', function() {
client.publish("lamp/status", status + ' ' + location, function() {
console.log("Message is published");
client.end();
resolve('Done Sending');
});
});
});
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
);
// Promise END
// this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
// client.publish("lamp/status", status + ' ' + location);
} else if (status == 'off') {
this.emit(':ask', OFF_RESPONSE, AFTER_RESPONSE);
// client.publish("lamp/status", status + ' ' + location);
}
},
'DimIntent' : function () {
// to do here
},
'ChangeColorIntent' : function () {
// to do here
},
'ShceduleIntent' : function () {
// to do here
},
'AMAZON.HelpIntent': function () {
this.emit(':ask', HELP_MESSAGE, 'Wanna control something ?');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', STOP_MESSAGE);
}
};
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context, callback);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
}
I test my code with Service Simulator in Alexa Developer and get this result :
Result Image
So I checked output in Lambda and I got this error report :
Error in Lamda
Can anyone please help me? I have no idea with this because this is my first trial :)
The crux of your error seems to be this specific line in the log:
Cannot read property 'emit' of undefined
And after following the flow of your program, it's likely ocurring here:
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
// It's probably ocurring in this line below
this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
)
The log is saying that you tried using this, it's undefined and doesn't have an emit property. Thats ocurring because of how this works in Js. You could workaround this problem by saving a reference to this
var that = this;
var mqttPromise = new Promise(function(resolve, reject) {
var options = {
port: '1883',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
username: 'username',
password: 'password',
};
var client = mqtt.connect('mqtt://broker-address', options)
client.on('connect', function() {
client.publish("lamp/status", status + ' ' + location, function() {
console.log("Message is published");
client.end();
resolve('Done Sending');
});
});
});
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
that.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
);
I would also recommend reading up a bit on "How 'this' works in Javascript"
MDN
Stack Overflow - "how does 'this' work"
I am currently working through the code to programmatically create a youtube playlist using a nodejs server that I received from a previous question I had and am using the working code below to do so:
var google = require('googleapis');
var Lien = require("lien");
var OAuth2 = google.auth.OAuth2;
var server = new Lien({
host: "localhost"
, port: 5000
});
var oauth2Client = new OAuth2(
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET',
'http://localhost:5000/oauthcallback'
);
var scopes = [
'https://www.googleapis.com/auth/youtube'
];
var youtube = google.youtube({
version: 'v3',
auth: oauth2Client
});
server.addPage("/", lien => {
var url = oauth2Client.generateAuthUrl({
access_type: "offline",
scope: scopes
});
lien.end("<a href='"+url+"'>Authenticate yourself</a>");
})
server.addPage("/oauthcallback", lien => {
console.log("Code obtained: " + lien.query.code);
oauth2Client.getToken(lien.query.code, (err, tokens) => {
if(err){
return console.log(err);
}
oauth2Client.setCredentials(tokens);
youtube.playlists.insert({
part: 'id,snippet',
resource: {
snippet: {
title:"Test",
description:"Description",
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
lien.end(data);
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
});
});
I am now moving on to the part of my project where I am in need of a way to add videos to this playlist once I have created it. The sample code that I am following along with is only written in JS and does not detail nodejs and I am therefore stuck on how to achieve this implementation with nodejs. How could I create a method like this (received from the JS implementation from the link above):
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
in the NodeJS language using the implementation I have already started?
I get what you mean now.If you want to add a video on your playlist then you can do that in Node using this.
youtube.playlistItems.insert({
part: 'id,snippet',
resource: {
snippet: {
playlistId:"YOUR_PLAYLIST_ID",
resourceId:{
videoId:"THE_VIDEO_ID_THAT_YOU_WANT_TO_ADD",
kind:"youtube#video"
}
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
lien.end(data);
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
If you want to render the result as HTML, First you need to use a view engine like (jade or pug) then create a template then lastly render it along with the response.
Base on your example you can do it this way:
First Create a template( Im using Pug) Save it as results.pug
html
head
title= title
body
h1= title
p=description
img(src=thumbnails.medium.url)
Then update your code below:
var google = require('googleapis');
var Lien = require("lien");
var OAuth2 = google.auth.OAuth2;
var pug = require('pug')
var server = new Lien({
host: "localhost"
, port: 5000,
views:{
path:__dirname,
name:'pug'
}
});
var oauth2Client = new OAuth2(
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET',
'http://localhost:5000/oauthcallback'
);
var scopes = [
'https://www.googleapis.com/auth/youtube'
];
var youtube = google.youtube({
version: 'v3',
auth: oauth2Client
});
server.addPage("/", lien => {
var url = oauth2Client.generateAuthUrl({
access_type: "offline",
scope: scopes
});
lien.end("<a href='"+url+"'>Authenticate yourself</a>");
})
server.addPage("/oauthcallback", lien => {
console.log("Code obtained: " + lien.query.code);
oauth2Client.getToken(lien.query.code, (err, tokens) => {
if(err){
return console.log(err);
}
oauth2Client.setCredentials(tokens);
youtube.playlists.insert({
part: 'id,snippet',
resource: {
snippet: {
title:"Test",
description:"Description",
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
//lien.end(data);
lien.render('results',data.snippet)
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
});
});
The things that I update on your code are:
var server = new Lien({
host: "localhost"
, port: 5000,
views:{
path:__dirname,
name:'pug'
}
});
And
//lien.end(data);
lien.render('results',data.snippet)
I would use the promises of angularJS to fill data to a grid. I'd like to load data "row by row" as soon as the nodeJS's server, on which use the module "mssql" with the "stream" enabled, back to client every single line from the DB.
On the client side I use these functions:
function asyncGreet() {
var deferred = $q.defer();
var _url = 'http://localhost:1212/test';
$http.get(_url).
then(function(result) {
deferred.resolve(result);
}, function(error) {
deferred.reject(error);
}, function(value) {
deferred.notify(value); //<<-- In "value" I would like to get every single row
});
return deferred.promise;
}
$scope.btnTest = function () {
var promise = asyncGreet();
promise.then(function(res) {
console.log('Success: ' + res.data + "\n");
}, function(reason) {
console.log('Failed: ' + reason);
}, function(update) {
console.log('Got notification: ' + update); //<<--
});
};
On nodeJS server those:
app.get('/test', function (req, res) {
//sql for test
var _query = 'select top 50 * from tb_test';
var sql = require('mssql');
var connection;
var config = {
user: 'testUser',
password: '12345',
server: 'localhost\\test',
database: 'testDB',
stream: true
};
connection = new sql.Connection(config, function (err) {
var request = new sql.Request(connection);
request.query(_query);
request.on('recordset', function(columns) {
// Emitted once for each recordset in a query
//res.send(columns);
});
request.on('row', function(row) {
res.write(JSON.stringify(row)); //<<-- I would like intercept this event on client side
// and get the result in my angularJS function on deferred.notify
});
request.on('error', function(err) {
// May be emitted multiple times
console.error(err)
});
request.on('done', function(returnValue) {
// Always emitted as the last one
res.end('DONE');
});
});
});
Anyone can help me with this?
Thanks!
I'm done it using socket.io :)
On angularJS side:
// count the row for test only
$scope.count = 0;
$scope.prova = function () {
mySocket.emit('getTableByRow', {});
mySocket.on('resRow', function (data) {
if (data.event == 'ROW') {
$scope.count += 1;
}else {
$scope.count += " !!DONE!! ";
}
});
};
On NodeJS side:
[ ... connection with DB ... ]
io.on('connection', function (socket) {
socket.on('getTableByRow', function (data) {
_getTableByRow(socket, data);
});
});
_getTableByRow function:
var _getTableByRow = function (socket, data) {
var _query = 'select top 50 * from tb_test';
request.query(_query);
request.on('row', function(row) {
// return only the ids for test
socket.emit('resRow', {event: 'ROW', data: row.id.toString()});
});
request.on('done', function(returnValue) {
socket.emit('resRow', {event: 'DONE'});
});
request.on('recordset', function(columns) {
console.log(columns);
});
request.on('error', function(err) {
socket.emit('resRow', {event: 'ERROR', data: err});
});
}
In this way, as soon as one row is read from the DB, it is immediately sent to the client :)
This is my code:
var amqp = require('amqp');
var connection = amqp.createConnection( { host: 'localhost' }, { defaultExchangeName: 'testexchange' });
connection.on('ready', function () {
console.log('Connected to rabbitmq');
var exchange = connection.exchange('testexchange', {confirm:true}, function(exch){
console.log('Created exchange: ' + exch.name);
var queue = connection.queue('testqueue', { durable: true }, function(q) {
exch.publish('testqueue', {a:1}, {}, function(error) {
console.log(error);
});
});
});
});
I'm using node 0.10.2 and node-amqp 0.1.6,
I can see textexchange by rabbitmqctl list_exchanges , but there's no testqueue by rabbitmqctl list_queues, what's wrong ?
You have to define it first.
connection.queue('testqueue', { durable: true })