webrtc data channel not workinig - javascript

I am trying to setup a text chat using webrtc data channel.
my network his a private network so i can't use any dependencies or frameworks like peerjs or similar.
I published my project on java play server so
i have one webrtsPeerConnection object that user can choose to initiate connection or to accept connection from someone else.
the problem : data channel is setup and active for the user who initiate the call.
but for the user who joined the call data channel don't activate and onDataChannel event never fires.
any suggestions??
Thanks in advance!
my code java script:
// init peer connection and data channel objects
var pc = new RTCpeerConnection(null,null);
var DC,DCnam;
function InitConnection(){
//created RTCpeerConnection
createDataChannel();
pc.createOffer(function(desc){
pc.setLocalDescripyion(desc,function(){},function(){})
enter code here
})
}
//create data channel
function createDataChannel(){
DC = pc.createDataChannel(DCname,{
reliable:true
});
}
//when user A call user B set remote description and create answer
function CheckCalls(){
&http.get("/checkCslls").success(function(data){
if(data[0])
{
//get offer and offerer
offerer = data[0].offerer;
pc.odataChannel function(e){
console.log(e);
}
pc.setRemoteDescription(new sessionDescription()data[0].offer));
pc.createAnswer(function(answerDesc){
pc.setLocalDescripyion(answerDesc);
})
}
})
}
//when user B send answer
(onDataChannel event fires on user A object).
function checkAnswers(){
$http.get("/checkAnswers").success(function(data){
if(data.answer){
pc.setRemoteDescription(new sessionDescription(data.answer));
}
})

It can be that you misspelled the callback:
pc.odataChannel function(e){
console.log(e);
}
it is ondatachannel with an "n" and lower case "c" and a "=" to define the function and callbacks to do something when messages are delivered;
something like:
var receiveChannel;
pc.ondatachannel = function (event) {
console.log('Receive Channel Callback');
receiveChannel = event.channel;
receiveChannel.onmessage = gotCMessage;
receiveChannel.onopen = dcOpen;
receiveChannel.onclose = dcClose;
console.log(event);
}

Related

Trigger a Client function with a service worker

I have a chat platform I'm building for fun. I have built notifications into the platform. On a browser it looks like this when you click the notification, with noticeSource being the user the new message is from. So it knows, to focus the page and then use the loadChat() function to load the chat associated with that user.
note.onclick=function(){
parent.focus();
console.log(this);
loadChat(noticeSource,el);
this.close()
};
However, I am also running this as PWA for android, so when it detects its on a phone it uses the Service worker showNotification method. I use this function to detect the click and to bring the app into focus.
self.addEventListener('notificationclick', function (event)
{
console.log("EVENT!",event.notification.data);
var target=event.notification.data;
const rootUrl = new URL('./index.php', location).href;
event.notification.close();
event.waitUntil(
clients.matchAll().then(matchedClients => {
for (let client of matchedClients){
console.log(client.url,rootUrl);
if (client.url.indexOf(rootUrl) >= 0){
console.log("Focus1");
return client.focus();
}
}
return clients.openWindow(rootUrl).then(
function (client) {
console.log("Focus2");
client.focus();
}
);
})
);
});
What I can't figure out is how to communicate between the SW and the client that the client should run the loadChat() function and pass along the user it should run it for. In general if someone could point me toward a resource that explains how to communicate between the SW and the client that would be appreciated. I've looked but haven't found anything and I am assuming it's because I'm not really clear on how service workers are suppose to work.
As is often the case, I found an answer after I posted the question. The client object has a method postMessage(), so once I have my client found I can use that to post a message with the userName, on the client side I can use eventListener navigator.serviceWorker.onmessage to catch messages from the sw and execute functions.
self.addEventListener('notificationclick', function (event)
{
console.log("EVENT!",event.notification.data);
var target=event.notification.data;
const rootUrl = new URL('./index.php', location).href;
event.notification.close();
console.log(clients);
event.waitUntil(
clients.matchAll().then(matchedClients => {
for (let client of matchedClients){
console.log(client.url,rootUrl);
if (client.url.indexOf(rootUrl) >= 0){
console.log(client);
client.focus();
client.postMessage(event.notification.data);
return ;
}
}
return clients.openWindow(rootUrl).then(
function (client) {
console.log("Focus2");
client.focus();
}
);
})
);
});
and on the client side
sw=navigator.serviceWorker;
sw.register('sw.js').then(function(registration){console.log("Scope:",registration.scope)});
sw.onmessage=function(event){
loadChat(event.data,document.getElementById(event.data));
}

Send cloud to device messages from Azure Function to device via IoT hub

Could you help me with the Java code which I use in a Function App?
IoT Hub which built endpoint is used as an IoT Hub(event hub) for a Function App is receiving telemetry from a device. By the following function, I extract values from the message received, process them and put in a CosmoDsB once the IoT Hub build endpoint has gotten a message from the device!
The main problem is that i need to send every processed value of the "totalLevel" variable back to the device via IoT Hub.
Once again : the entire structure is an "OPC server (MQTT)" <-/-> "IoT Hub" -"build endpoint IoT Hub" - "Function APP" -> back to the device.
C2D
I have not found any simple example how to do this in Java as an addition to the
existing function. Does anybody know any easy way to do this?
I found these examples but don't have enough skills to modify it.
https://learn.microsoft.com/en-US/azure/iot-hub/quickstart-send-telemetry-java
https://learn.microsoft.com/en-US/azure/iot-hub/iot-hub-java-java-c2d
thank you in advance
module.exports = function (context, IoTHubMessages) {
context.log(`JavaScript eventhub trigger function called for message array: ${IoTHubMessages}`);
IoTHubMessages.forEach(message => {
context.log(`Processed message: ${message}`);
});
context.done();
};
module.exports = function (context, IoTHubMessages) {
context.log(`JavaScript eventhub trigger function called for message array:
${IoTHubMessages}`);
var count = 0;
var totalLevel = 0.0;
var totalHumidity = 0.0;
var deviceId = "";
IoTHubMessages.forEach(message => {
context.log(`Processed message: ${message}`);
count++;
totalLevel = message.L1 + message.L2 + message.L3;
RestartPLC = message.L4;
deviceId = message.deviceId;
});
var output = {
"deviceId": deviceId,
"PLC_Restart_state": RestartPLC,
// "measurementsCount": count,
"gemessener Gesamtabfluss, mm": totalLevel
//"averageHumidity": totalHumidity/count
};
context.log(`Output content: ${output}`);
context.bindings.outputDocument = output;
context.done();
};

Failed to set local answer sdp: Called in wrong state: STATE_INPROGRESS

I have two clients :
1) Chrome (version 50.0.2661.102 m) on Windows 7 PC
2) Chrome (version 50.0.2661.89) on Android tablet
Both are in the same network (so no need for STUN/TURN server).
I use my own signal server built with node.js (webSocket) on a VirtualBox VM with Centos 6.
The communication with video/sound between the clients works fine. Now I want to transfer a file from one client to another. As base of my code i use the code of this example
here
As this code suggess, I create the dataChannnel exactly after the creation of PeerConnection.
function createPeerConnection() {
....
myPeerConnection = new RTCPeerConnection(iceServers, optional);
myDataChannel = myPeerConnection.createDataChannel('myDataChannel');
// Set up event handlers for the ICE negotiation process.
myPeerConnection.onicecandidate = handleICECandidateEvent;
myPeerConnection.onaddstream = handleAddStreamEvent;
myPeerConnection.onnremovestream = handleRemoveStreamEvent;
myPeerConnection.oniceconnectionstatechange = handleICEConnectionStateChangeEvent;
myPeerConnection.onicegatheringstatechange = handleICEGatheringStateChangeEvent;
myPeerConnection.onsignalingstatechange = handleSignalingStateChangeEvent;
myPeerConnection.onnegotiationneeded = handleNegotiationNeededEvent;
myPeerConnection.ondatachannel = handleDataChannel;
myDataChannel.onmessage = handleDataChannelMessage;
myDataChannel.onopen = handleDataChannelOpen;
}
...
...
function invite(peerId) {
...
createPeerConnection();
...
}
...
...
function handleVideoOfferMsg(msg) {
thereIsNegotiation = true;
targetUsername = msg.name;
// Call createPeerConnection() to create the RTCPeerConnection.
log("Starting to accept invitation from " + targetUsername);
createPeerConnection();
// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.
var desc = new RTCSessionDescription(msg.sdp);
myPeerConnection.setRemoteDescription(desc)
.then(function(stream) {
log("-- Calling myPeerConnection.addStream()");
return myPeerConnection.addStream(localStream);
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: clientId,
room: roomId,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};
// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.
log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(handleGetUserMediaError);
}
When the second client makes the offer, the first client when tries to make the answer, I get the error
Error opening your camera and / or microphone : failed to set local answer
spd: Failed to push down transport description: Local fingerprint provided
but no identity available.
or
Error opening your camera and / or microphone : failed to set local answer
spd: Called in wrong state : STATE_INPROGRESS
Only one time the creation was successful.
Do I have to create DataChannel in other place? Like here :
function handleICEConnectionStateChangeEvent {
switch(myPeerConnection.iceConnectionState) {
...
case "connected":
createDataChannel();
break;
}
}
function createDataChannel(){
myDataChannel = myPeerConnection.createDataChannel('myDataChannel');
myPeerConnection.ondatachannel = handleDataChannel;
myDataChannel.onmessage = handleDataChannelMessage;
myDataChannel.onopen = handleDataChannelOpen;
}
Any suggestions?
The error in this code is that both sender and receiver create new datachannel. The right thing is, one to create the datachannel
myDataChannel = myPeerConnection.createDataChannel('myDataChannel')
and the other to wait for the creation of dataChannel:
myPeerConnection.ondatachannel = handleDataChannel;

Creating and using a data channel between two peers with webRTC

I am trying to setup a peer to peer file sharing system using WebRTC. I'm able to open a data channel on each side, but I can't send messages from one user to another. Moreover, if one peer closes the channel, the other, the onclose event is only triggered for this user.
What's the proper way to setup and use a data channel with webRTC?
Could you tell me what's wrong or missing in my code?
//create RTC peer objet.
var RTCPeerConnection = webkitRTCPeerConnection;
var RTCIceCandidate = window.RTCIceCandidate;
var RTCSessionDescription = window.RTCSessionDescription;
var iceServers = {
iceServers: [{
url: 'stun:stun.l.google.com:19302'
}]
};
var p2p_connection = new RTCPeerConnection({
iceServers: [
{ 'url': (IS_CHROME ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121') }
]
});
// send offer (only executes in one browser)
function initiateConnection() {
p2p_connection.createOffer(function (description) {
p2p_connection.setLocalDescription(description);
server_socket.emit('p2p request', description,my_username);
});
};
// receive offer and send answer
server_socket.on('p2p request', function(description,sender){
console.log('received p2p request');
p2p_connection.setRemoteDescription(new RTCSessionDescription(description));
p2p_connection.createAnswer(function (description) {
p2p_connection.setLocalDescription(description);
server_socket.emit('p2p reply', description,sender);
});
});
// receive answer
server_socket.on('p2p reply', function(description,sender){
console.log('received p2p reply');
p2p_connection.setRemoteDescription(new RTCSessionDescription(description));
});
// ICE candidates
p2p_connection.onicecandidate = onicecandidate; // sent event listener
// locally generated
function onicecandidate(event) {
if (!p2p_connection || !event || !event.candidate) return;
var candidate = event.candidate;
server_socket.emit('add candidate',candidate,my_username);
}
// sent by other peer
server_socket.on('add candidate', function(candidate,my_username){
p2p_connection.addIceCandidate(new RTCIceCandidate({
sdpMLineIndex: candidate.sdpMLineIndex,
candidate: candidate.candidate
}));
});
// data channel
var dataChannel = p2p_connection.createDataChannel('label');
dataChannel.onmessage = function (event) {
var data = event.data;
console.log("I got data channel message: ", data);
};
dataChannel.onopen = function (event) {
console.log("Data channel ready");
dataChannel.send("Hello World!");
};
dataChannel.onclose = function (event) {
console.log("Data channel closed.");
};
dataChannel.onerror = function (event) {
console.log("Data channel error!");
}
Update:
Found the solution there: http://www.html5rocks.com/en/tutorials/webrtc/basics/
p2p_connection.ondatachannel = function (event) {
receiveChannel = event.channel;
receiveChannel.onmessage = function(event){
console.log(event.data);
};
};
You might consider using the simple-peer library to avoid dealing with these complexities in the future. The WebRTC API calls are confusing and the ordering is sometimes hard to get right.
simple-peer supports video/voice streams, data channel (text and binary data), and you can even use the data channel as a node.js-style duplex stream. It also supports advanced options like disabling trickle ICE candidates (so each client only needs to send one offer/answer message instead of many repeated ice candidate messages). It's un-opinionated and works with any backend.
https://github.com/feross/simple-peer
Abstractions!
https://github.com/feross/simple-peer (noted above by #Feross)
https://github.com/rtc-io/rtc-mesh
https://github.com/dominictarr/scuttlebutt
https://github.com/mafintosh/peervision
https://github.com/muaz-khan/DataChannel
Gigantic list of related projects...
https://github.com/kgryte/awesome-peer-to-peer

Connect two clients in websocket with PyWebSocket

i am new to websocket using pywebsocket, basically trying to create a simple chat application with websocket and pywebsocket.
Until now i am done with following script
if ("WebSocket" in window)
{
//alert("WebSocket is supported by your Browser!");
// Let us open a web socket
var ws = new WebSocket("ws://192.168.1.3:9998/echo");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
console.log("Channel opened");
//ws.send("Message to send");
//alert("Message is sent...");
//console.log("Message is sent...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
//alert("Message is received..."+received_msg);
console.log("message : "+received_msg);
};
ws.onclose = function()
{
// websocket is closed.
//alert("Connection is closed...");
console.log("connection closed");
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
function sendmessage(){
msg=document.getElementById("chat").value;
console.log(msg);
ws.send(msg);
document.getElementById("chat").value="";
}
Now the problem is the messages that are sent are echoed to the system itself, if another client connect to same channel its messages are echoed to itself, they are sent to another client which is connected with same channel.
pywebsocket is initialized as follows
python standalone.py -p 9998 -w ../example/
So how can i connect two system and allow chat.
Thanks in advance
Not sure, but if you want to broadcast any received message (sent by any connected client) to all other currently connected clients, that is not "echo" .. but "broadcast".
Here is an example using AutobahnPython.
Disclosure: I am original author of Autobahn and work for Tavendo.

Categories