client is esp32cam(camera module)
It is send Image to app.js every 3seconds
app.js
client.on("message", async(topic, message)=>{ // {"LED" : "ON"} or {"MOTER" : "ON"}
if(topic == "JPG")
{
var obj = message.toString();
app.get("/img", function(req,res,next){
res.set("content-Type", "text/json");
//res.send(JSON.stringify({data : obj}));
res.json({
data: obj || "no image yet"
});
console.log(obj);//number 1
});
console.log(obj);//number 2
}
}
number 1 is print same data every 3seconds
number 2 is print different data every 3seconds
how can number1 print different data each time??
html
$(function() {
timer = setInterval( function () {
console.log("timer")
$.ajax({
url: "http://ip:3000/img",
type: "get",
context : this,
cache : false,
error : function(request,status,error){
console.log("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);
},
success:function(obj){
$("#imguri").html('<img src="'+obj.data+'">');
$("#imguri").attr("src", obj.data);
console.log("mqtt in " + obj.data);
// console.log("TEST");
}
});
}, 3000);
});
my problem
This is because you are stacking multiple app.get("/img",...) routes (one for every incoming message).
Only the first one will ever be called, so the HTTP client will always just get the very first image.
You should make the MQTT client callback store the new image in a global variable and then just have one instance of the /img route return that global variable.
var img;
client.on("message", async(topic, message)=>{ // {"LED" : "ON"} or {"MOTER" : "ON"}
if(topic == "JPG")
{
var obj = message.toString();
img = obj
}
}
app.get("/img", function(req,res,next){
res.set("content-Type", "text/json");
res.json({
data: img || "no image yet"
});
console.log(obj);//number 1
});
Related
I'm using NodeJS and Socket.io. I'm getting a query from the user (https://localhost:3000?id=12345) and using this query I want to send this specific user unique content.
Now my problem is that all clients are getting data according to the last query from the last client.
I've tried to make rooms and multiple other solutions that I've thought about or found online but with no luck.
I'm getting the query of the page like that,
app.get('/', async ({ query }, response) => { ... }
Client
$(document).ready(function () {
socket.emit('room', key);
socket.on('a1', function (data) {
$("#a1").empty().append(data);
});
socket.on('a2', function (data) {
$("#a2").empty().append(data);
});
socket.on('a3', function (data) {
$("#a3").empty().append(data);
});
socket.on('a4', function (data) {
$("#a4").empty().append(data);
});
…
Server
io.on('connection', function (socket) {
console.log('Connection');
socket.removeAllListeners();
socket.on('create', function (data) {
console.log(`Data: ${data}`);
socket.join(data);
io.in(data).emit('a1', a1);
io.in(data).emit('a2', a2);
io.in(data).emit('a3', a3);
io.in(data).emit('a4', a4);
})
});
…
I really can't understand how to separate each client query from the server and then send unique content to each client without one client's content interfering with another.
My initial thought was to make one room per client and send their unique content by using that room but for some reason, it's like the content is ending up in every client.
Thank you very much!
Is just you turn the object used to manage the content better like this:
The clientside:
$(document).ready(function () {
const userKey = 'unique-id-for-each-user'
socket.emit('room', {key : key, userKey : userKey});
//if you emit something in this channel (same as userKey) on server will get here
socket.on(userKey, function (data) {
if(data.key === 'a1')
$("#a1").empty().append(data.content);
if(data.key === 'a2')
$("#a2").empty().append(data.content);
if(data.key === 'a3')
$("#a3").empty().append(data.content);
});
//if you emit something in this channel ('allClients') on server will get here
socket.on('allClients', function(data) {
if(data.key === 'a1')
$("#a1").empty().append(data.content);
if(data.key === 'a2')
$("#a2").empty().append(data.content);
if(data.key === 'a3')
$("#a3").empty().append(data.content);
})
});
The serverside:
io.on('connection', function (socket) {
console.log('Connection');
socket.removeAllListeners();
socket.on('room', function (data) {
console.log(`Data: ${data}`);
if(data.key === 'a1')
io.sockets.emit(data.userKey, {key : 'a1', content: a1});
if(data.key === 'a2')
io.sockets.emit(data.userKey, {key : 'a2', content: a2});
if(data.key === 'a3')
io.sockets.emit(data.userKey, {key : 'a3', content: a3});
if(data.key === 'a4')
io.sockets.emit(data.userKey, {key : 'a4', content: a4});
})
});
As you see, i just change the variable you pass as parameter to give me what i need, as serverside as clientside.
im trying webrtc for the first time for a video chat app , i want up to 3 person in each chat ... my code works fine with 2 person chat
but as soon as 3rd person joins the chat everything goes wrong ... i get multiple video tags in the page and none of them are from the 3rd pear .... i'd appreciate any pointers or suggestion most tutorials cover 2 person chat
here is working url
https://chate-test-3000.herokuapp.com/
here is my code
const PEARS = [];
var video_counter = 0 ;
const STREAMES = [] ;
var myVideoArea = document.querySelector('#myvideo');
var configuration = {
'iceServers': [{
'url': 'stun:stun.l.google.com:19302'
}]
};
var rtcPeerConn;
const ROOM = 'caht1';
const SIGNAL_ROOM = 'newsingal1234567898765';
io = io.connect("" , {transports:['websocket']});
io.emit('ready' , { chat_room : ROOM , signaling_room : SIGNAL_ROOM});
io.emit('signal' , { text :'ready for video ? ' , room : SIGNAL_ROOM , type : 'user_here'});
io.on('signlaing_message' , function(data){
console.log('signal recived');
console.log(data);
if(!PEARS.includes(data.pear_id))
{
console.log('adding new pear --- ' , data.pear_id);
PEARS.push(data.pear_id);
startSignaling(data.pear_id);
}
if (data.type != "user_here")
{
var message = JSON.parse(data.message);
if (message.sdp) {
rtcPeerConn.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
// if we received an offer, we need to answer
if (rtcPeerConn.remoteDescription.type == 'offer') {
rtcPeerConn.createAnswer(sendLocalDesc, logError);
}
}, logError);
}
else {
rtcPeerConn.addIceCandidate(new RTCIceCandidate(message.candidate));
}
}
})
function startSignaling(pear_id) {
if(!rtcPeerConn)
rtcPeerConn = new RTCPeerConnection(configuration);
// send any ice candidates to the other peer
rtcPeerConn.onicecandidate = function (evt) {
if (evt.candidate)
io.emit('signal',{"type":"ice candidate", "message": JSON.stringify({ 'candidate': evt.candidate }), "room":SIGNAL_ROOM});
displaySignalMessage("completed that ice candidate...");
};
// let the 'negotiationneeded' event trigger offer generation
rtcPeerConn.onnegotiationneeded = function () {
displaySignalMessage("on negotiation called");
rtcPeerConn.createOffer(sendLocalDesc, logError);
}
// once remote stream arrives, show it in the remote video element
rtcPeerConn.ontrack = function (evt) {
displaySignalMessage("going to add their stream...");
video_counter++ ;
let vid = 'video-box-'+video_counter ;
console.log('adding new STREAM !!')
console.log('###### streams ' , evt.streams);
if(!STREAMES.includes(evt.streams[0].id))
{
STREAMES.push(evt.streams[0].id);
$('#video-wrapper').append(`<video data-id="${evt.streams[0].id}" id="${vid}" autoplay loop autobuffer muted playsinline controls></video>`);
console.log(' video length ..... ' , $('#video-wrapper').find('#'+vid).length );
var theirVideoArea = $('#video-wrapper').find('#'+vid)[0];
console.log(theirVideoArea);
theirVideoArea.srcObject = evt.streams[0] ;
theirVideoArea.play();
}
};
// get a local stream, show it in our video tag and add it to be sent
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({
'audio': true,
'video': true
}, function (stream) {
displaySignalMessage("going to display my stream...");
myVideoArea.srcObject = stream
myVideoArea.play();
for (const track of stream.getTracks()) {
rtcPeerConn.addTrack(track, stream);
}
}, logError);
}
function sendLocalDesc(desc) {
rtcPeerConn.setLocalDescription(desc, function () {
displaySignalMessage("sending local description");
io.emit('signal',{"type":"SDP", "message": JSON.stringify({ 'sdp': rtcPeerConn.localDescription }), "room":SIGNAL_ROOM});
}, logError);
}
function logError(error) {
$('#error-area').append(`<div> ${error.name} : ${error.message}</div>`);
}
function displaySignalMessage(text ){
$('#signal-area').append(`<div>${text}</div>`);
}
i also use a simple nodejs server for signaling and use socket.io to connect to the server
------------------------- EDIT - PEER.JS -----------------
here is my code after switching to peerjs
const SIGNAL_ROOM = 'zxsingalroom';
var MY_PEER_ID = '' ;
const CurrentPeers = [] ;
io = io.connect("" , {transports:['websocket']});
io.emit('ready' , { chat_room : ROOM , signaling_room : SIGNAL_ROOM});
var peer = new Peer({
config: {'iceServers': [
{ url: 'stun:stun.l.google.com:19302' },
]} /* Sample servers, please use appropriate ones */
});
peer.on('open', function(id) {
console.log('My peer ID is: ' + id);
MY_PEER_ID = id ;
io.emit('peer_id_offer' , { chat_room : ROOM , id : id});
});
peer.on('call' , function (call) {
navigator.mediaDevices.getUserMedia({ video : true , audio : true })
.then((stream) => {
call.answer(stream);
call.on('stream' , function(remoteStream){
if(!CurrentPeers.includes(call.peer))
{
CurrentPeers.push(call.peer);
addRemoteVideo(remoteStream);
}
})
})
.catch( (e)=>{
console.log('error2' , e );
});
})
io.on('peer_id_recived' , function(data){
console.log(`peer id recived : `);
console.log(data);
for (let [key, value] of Object.entries(data.peer_ids)) {
if(value.peer_id != MY_PEER_ID)
{
callPeer(value.peer_id);
}
}
});
function callPeer( id )
{
console.log('calling peers 1 .... ');
navigator.mediaDevices.getUserMedia({ video : true , audio : true })
.then( (stream) => {
console.log('calling peers 2 .... ' + id);
addOurVideo(stream);
let call = peer.call(id , stream);
console.log( typeof call);
call.on('stream' , function(remoteStream){
console.log('calling peers 3 .... ');
if(!CurrentPeers.includes(call.peer))
{
CurrentPeers.push(call.peer);
addRemoteVideo(remoteStream);
}
})
})
.catch( (e)=>{
console.log('error1' , e );
});
}
function addRemoteVideo(stream){
console.log(' adding remote stream!!!');
let total_perrs = CurrentPeers.length ;
let vid = `video-box-${total_perrs}`;
$('#video-wrapper').append(`<video id="${vid}" autoplay loop autobuffer muted playsinline controls></video>`);
var theirVideoArea = $('#video-wrapper').find('#'+vid)[0];
theirVideoArea.srcObject = stream ;
theirVideoArea.play();
}
function addOurVideo(stream){
console.log(' adding our stream');
var ourVideArea = $('#video-wrapper').find('#our-video')[0];
ourVideArea.srcObject = stream ;
ourVideArea.play();
}
You should use some sort of P2P or Media Server to handle multiple simultaneous connections from different clients PeerJS is a great option.
for the WebRTC: ICE failed, add a TURN server and see about:webrtc for more details error its exactly what it says STUN servers are used to create the connection but if the P2P connection cannot be established, the fallback is that all the communication goes through a TURN server, so they need high resources and bandwidth.
TURN servers are generally not free but one open source option that might fix your problem is using a COTURN server https://github.com/coturn/coturn
you should put the following example config in your PeerJS options
"iceServers": [
{
"urls": "stun:vc.example.com:3478"
},
{
"urls": "turn:vc.example.com:3478",
"username": "coturnUser",
"credential": "coturnUserPassword"
}
],
you could specify "iceTransportPolicy": "relay" before urls to only use relay server(without P2P)
I have come to post this question after 2 days of torture not being able to understand how I can actually publish the historic messages stored on my pubnub storage account. To try and understand it at its most basic I have made a chat app and used the history function as described in the SDK but still every time I refresh the page the messages are lost. I have tried the backfill and the restore attributes in subscribe with no luck. All I want to do is click refresh on chrome and see the messages still there.
<div><input id=input placeholder=you-chat-here /></div>
Chat Output
<div id=box></div>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.4.0.min.js"></script>
<script>(function(){
var pubnub = new PubNub({ publishKey : 'demo', subscribeKey : 'demo' });
function $(id) { return document.getElementById(id); }
var box = $('box'), input = $('input'), channel = 'chat';
pubnub.addListener({
message: function(obj) {
box.innerHTML = (''+obj.message).replace( /[<>]/g, '' ) + '<br>' + box.innerHTML
}});
pubnub.history({
channel: 'chat',
reverse: true, // Setting to true will traverse the time line in reverse starting with the oldest message first.
count: 100, // how many items to fetch
callback : function(msgs) {
pubnub.each( msgs[0], chat );
}
},
function (status, response) {
// handle status, response
console.log("messages successfully retreived")
});
pubnub.subscribe({channels:[channel],
restore: true,
backfill: true,
ssl: true});
input.addEventListener('keyup', function(e) {
if ((e.keyCode || e.charCode) === 13) {
pubnub.publish({channel : channel, message : input.value,x : (input.value='')});
}
});
})();
</script>
</body>
EDIT: updated link that was broken. New version of history function is called fetchMessages.
I think your history code is not correct. No need for the callback as your code response will be in the function argument. This example is from the JavaScript SDK docs.
// deprecated function
pubnub.history(
{
channel: 'chat',
},
function (status, response) {
var msgs = response.messages;
if (msgs != undefined && msgs.length > 0) {
// if msgs were retrieved, do something useful
console.log(msgs);
}
}
);
// latest function (response output format has changed)
pubnub.fetchMessages(
{
channels: ['chat']
},
(status, response) => {
console.log(msgs);
}
);
I need to send print Job to my printer using Google Cloud Print. It is a Classic Printer Named RISO ComColor 7150. My Code in Apps Script is as follows:-
function printGoogleDocument(docID, printerID, docName , type , duplex) {
var ticket = {
version: "1.0",
print: {
color: {
type: type,
vendor_id: "Color"
},
duplex: {
type: duplex
}
}
};
var payload = {
"printerid" : printerID,
"title" : docName,
"content" : DriveApp.getFileById(docID).getBlob(),
"contentType": "application/pdf",
"ticket" : JSON.stringify(ticket),
"pages" : "1,2"
};
var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/submit', {
method: "POST",
payload: payload,
headers: {
Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
},
"muteHttpExceptions": true
});
response = JSON.parse(response);
if (response.success) {
Logger.log("%s", response.message);
} else {
Logger.log("Error Code: %s %s", response.errorCode, response.message);
}
}
problem is When i am Sending type to STANDARD_COLOR and duplex to NO_DUPLEX than it is Working fine but when i change them to MONOCHROME and DUPLEX than it is Giving me Color print with no duplex again. Also i am Sending Page Number but it Prints whole pdf instead of giving me print of specific page.
Can Anybody tell me what i am doing worng here??
Thanks in Advance.
you can set all the things in print job ticket, no need to specify the page number outside ticket.
Here ,a CJT am recommending ,
var ticket = "{\"version\":\"1.0\",\"print\":{\"color\":{\"vendor_id\":\"1\",\"type\":1},\"duplex\":{\"type\":0},\"page_orientation\":{\"type\":"0"},\"copies\":{\"copies\": "2"},\"fit_to_page\":{\"type\":3},\"page_range\":{\"interval\":[{\"start\": "1",\"end\":"2"}]},\"media_size\":{\"width_microns\":210000,\"height_microns\":297000,\"is_continuous_feed\":false,\"vendor_id\":\"9\"},\"collate\":{\"collate\":false},\"reverse_order\":{\"reverse_order\":false}}}";
so you can specify duplex, page limit..etc
It would be nice if you can go this documentation.
https://developers.google.com/cloud-print/docs/cdd#pts
And for duplex,its an integer expecting, you can set this way..if NO_DUPLEX is needed you need to send 0,
NO_DUPLEX = 0;
LONG_EDGE = 1;
SHORT_EDGE = 2;
I want to show my notification to the user till i desired by default it is shown up to 19 sec approx. can somebody tell me about any trick regarding this?
i also tried to update again and again to keep it showing but not succeed, actually not got appropriate syntax for doing that.
currently i am using below code to register service worker.
by this code i am able show notification for 19 sec approx, but i want to show it for 1 min.
var url = "https://example.com/json-data.php?param="+Math.random();
self.addEventListener('push', function(event) {
event.waitUntil(
fetch(url).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.log('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
return self.registration.showNotification(title, {
body: message,
icon: icon,
data: {
url: data.notification.url
}
});
});
}).catch(function(err) {
console.log('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = 'img/design19.jpg';
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
// The user has clicked on the notification ...
self.addEventListener('notificationclick', function(event) {
console.log(event.notification.data.url);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWind`enter code here`ow(event.notification.data.url);
}`enter code here`
})
);
});
There is no parameter as of now on setting the timeout for the notification. It is by default that the notification will show for 20 seconds then the desktop version of Chrome will auto-minimize the notification.
Alternatively, there is a parameter in the options requireInteraction which is false by default. By enabling this to true will make the notification stay visible until the user has interacted with it.
I think you can't directly set how long a notification should be shown.
A possible hacky way to do it would be, once browsers will support persistent notifications (I don't know if Chrome or Firefox do at the moment), to show a persistent notification and then close it after a timeout.
According to hacky way Marco said, It Works!
"notification" => [
"title" => isset($arrData['title']) ? $arrData['title'] : '',
"body" => isset($arrData['description']) ? $arrData['description'] : '',
"icon" => s3_url("images/push-logo.jpg"),
"click_action" => isset($arrData['target_url']) ? $arrData['target_url'] : '',
"image" => isset($arrData['image']) ? $arrData['image'] : '',
],
"data" => [
"requireInteraction" => true,
"duration" => (20 * 1000), // 20 sec
],
"to" => "/topics/$topic",
And set the requireInterationTrue on onMessage , after push notification is shown take duration from data and close notification inside a setTimeout
messaging.onMessage(function(payload) {
console.log('Message received. ', payload.data);
const noteTitle = payload.notification.title;
const noteRequireInteraction = (payload.data.requireInteraction === 'true');
const noteDuration = payload.data.duration;
const noteOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
image: payload.notification.image,
requireInteraction: noteRequireInteraction,
};
if (!document.hidden) {
var notification = new Notification(noteTitle, noteOptions);
setTimeout(function () {
notification.close();
}, noteDuration);
notification.onclick = function(event) {
event.preventDefault();
if(typeof payload.notification.click_action != 'undefined' && payload.notification.click_action != '')
window.open(payload.notification.click_action,'_blank');
notification.close();
}
}
});