Binding callbacks on Laravel Echo with Laravel Websockets - laravel-echo

I want to know when my users are getting errors connecting or the connection drops out. I've read a lot saying this is possible but I'm getting no where and I'm starting to think it maybe an issue with a third party like https://github.com/beyondcode/laravel-websockets which I am using, has anyone had any issues with this?
The following yields no logs at all.
window.Echo.connector.pusher.bind('reconnect', (channel, data) => {
console.log('RE-CONNECTED');
});
window.Echo.connector.pusher.bind('reconnecting', (channel, data) => {
console.log('re-connecting...');
});
window.Echo.connector.pusher.bind('reconnect_error', (channel, data) => {
console.log('reconnection error!');
});
window.Echo.connector.pusher.bind('reconnect_attempt', (channel, data) => {
console.log('re-connecting...');
});
window.Echo.connector.pusher.bind('connect_error', (channel, data) => {
console.log('connect error...');
});
window.Echo.connector.pusher.bind('error', (channel, data) => {
console.log('error...');
});
window.Echo.connector.pusher.bind_global((channel, data) => {
console.log(channel, data);
});
If I use something like this which is being suggested
window.Echo.connector.socket.on('connect_error', function(){
console.log('connected', window.Echo.socketId());
});
window.Echo.connector.socket.on('connect', function(){
console.log('connected', window.Echo.socketId());
});
window.Echo.connector.socket.on('disconnect', function(){
console.log('disconnected');
});
window.Echo.connector.socket.on('reconnecting', function(attemptNumber){
console.log('reconnecting', attemptNumber);
});
I get Uncaught TypeError: Cannot read property 'on' of undefined

I have discovered the correct way to bind the events;
window.Echo.connector.pusher.connection.bind($eventName, (payload) => {});
Event references can be found here https://pusher.com/docs/channels/using_channels/connection
window.Echo.connector.pusher.connection.bind('connecting', (payload) => {
/**
* All dependencies have been loaded and Channels is trying to connect.
* The connection will also enter this state when it is trying to reconnect after a connection failure.
*/
console.log('connecting...');
});
window.Echo.connector.pusher.connection.bind('connected', (payload) => {
/**
* The connection to Channels is open and authenticated with your app.
*/
console.log('connected!', payload);
});
window.Echo.connector.pusher.connection.bind('unavailable', (payload) => {
/**
* The connection is temporarily unavailable. In most cases this means that there is no internet connection.
* It could also mean that Channels is down, or some intermediary is blocking the connection. In this state,
* pusher-js will automatically retry the connection every 15 seconds.
*/
console.log('unavailable', payload);
});
window.Echo.connector.pusher.connection.bind('failed', (payload) => {
/**
* Channels is not supported by the browser.
* This implies that WebSockets are not natively available and an HTTP-based transport could not be found.
*/
console.log('failed', payload);
});
window.Echo.connector.pusher.connection.bind('disconnected', (payload) => {
/**
* The Channels connection was previously connected and has now intentionally been closed
*/
console.log('disconnected', payload);
});
window.Echo.connector.pusher.connection.bind('message', (payload) => {
/**
* Ping received from server
*/
console.log('message', payload);
});

Related

Node JS emit socket after error in SQL query

**Hello, please do you know how can I send message to client via socket when I have error in my SQl query on server side ? **
Server side
io.on('connect', (socket) => {
console.log("User connected: " + socket.id);
socket.on('disconnet', () => {
console.log("disconnected");
})
.post('/addDiel', (req, res) => { //Pridanie dielu do DB
pool.getConnection((err, connection) => {
if(err) throw err
console.log(`Pripojene ako ID ${connection.threadId}`)
const params = req.body;
res.send({
MenoDielures: params.MenoDielu,
DruhDielures: params.DruhDielu,
ProjektNameres: params.ProjektName
})
ProjektNameDB = params.ProjektName.split('.').join("_");
connection.query('INSERT INTO `Skener_db`.`?` (`MenoDielu`, `DruhDielu`, `DatumCas`) VALUES (?, ?, NOW())', [ProjektNameDB, params.MenoDielu, params.DruhDielu],(err, rows)=> {
connection.release()
if(!err) {
res.send(console.log(`Hodnota ${params.MenoDielu} bola pridana.`))
} else {
console.log(err);
if (err.code == ('ER_DUP_ENTRY')) {
//send message to client
}
//res.send({alertMessage: 'Diel už bol oskenovaný. Oskenuj ďaľší.'})
}
})
console.log(req.body)
})
})
})
My client side:
socket.on('connect', () => {
$('#skuska').html("Socket pripojeny");
})
socket.on('receiveDUPmessage', message => {
$('#skuska').html(message);
})
The code here is just for example. I didnt find solution for my problem, so I'm asking here
You have to emit events and socket is locally scoped. io.sockets is not, So you can do it like this on the server-side:
if(!err) {
res.send(console.log(`Hodnota ${params.MenoDielu} bola pridana.`))
} else {
console.log(err);
if (err.code == ('ER_DUP_ENTRY')) {
//send message to client
io.sockets.emit('my error', 'Some error happened');
}
//res.send({alertMessage: 'Diel už bol oskenovaný. Oskenuj ďaľší.'})
}
And on the client-side do this:
socket.on('my error', function (text) {
console.log(text);
});
Here is some sort of posts that may help you:
How to emit error to be possible catch it on error handler on client-side?
How to emit a socket.io response within post request in NodeJS

WebRTC succesfully signalled offer and answer, but not getting any ICE candidates

I'm trying to establish a WebRTC connection between two browsers. I have a node.js server for them to communicate through, which essentially just forwards the messages from one client to the other. I am running the server and two tabs all on my laptop, but I have not been able to make a connection. I have been able to send the offers and answers between the two tabs successfully resulting in pc.signalingState = 'stable' in both tabs. I believe once this is done then the RTCPeerConnection objects should start producing icecandidate events, but this is not happening and I do not know why. Here is my code (I've omitted the server code):
'use strict';
// This is mostly copy pasted from webrtc.org/getting-started/peer-connections.
import { io } from 'socket.io-client';
const configuration = {
'iceServers': [
{ 'urls': 'stun:stun4.l.google.com:19302' },
{ 'urls': 'stun:stunserver.stunprotocol.org:3478' },
]
}
// Returns a promise for an RTCDataChannel
function join() {
const socket = io('ws://localhost:8090');
const pc = new RTCPeerConnection(configuration);
socket.on('error', error => {
socket.close();
throw error;
});
pc.addEventListener('signalingstatechange', event => {
// Prints 'have-local-offer' then 'stable' in one tab,
// 'have-remote-offer' then 'stable' in the other.
console.log(pc.signalingState);
})
pc.addEventListener('icegatheringstatechange', event => {
console.log(pc.iceGatheringState); // This line is never reached.
})
// Listen for local ICE candidates on the local RTCPeerConnection
pc.addEventListener('icecandidate', event => {
if (event.candidate) {
console.log('Sending ICE candidate'); // This line is never reached.
socket.emit('icecandidate', event.candidate);
}
});
// Listen for remote ICE candidates and add them to the local RTCPeerConnection
socket.on('icecandidate', async candidate => {
try {
await pc.addIceCandidate(candidate);
} catch (e) {
console.error('Error adding received ice candidate', e);
}
});
// Listen for connectionstatechange on the local RTCPeerConnection
pc.addEventListener('connectionstatechange', event => {
if (pc.connectionState === 'connected') {
socket.close();
}
});
// When both browsers send this signal they will both receive the 'matched' signal,
// one with the payload true and the other with false.
socket.emit('join');
return new Promise((res, rej) => {
socket.on('matched', async first => {
if (first) {
// caller side
socket.on('answer', async answer => {
await pc.setRemoteDescription(new RTCSessionDescription(answer))
.catch(console.error);
});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer)
.catch(console.error);
socket.emit('offer', offer);
// Listen for connectionstatechange on the local RTCPeerConnection
pc.addEventListener('connectionstatechange', event => {
if (pc.connectionState === 'connected') {
res(pc.createDataChannel('data'));
}
});
} else {
// recipient side
socket.on('offer', async offer => {
pc.setRemoteDescription(new RTCSessionDescription(offer))
.catch(console.error);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer)
.catch(console.error);
socket.emit('answer', answer);
});
pc.addEventListener('datachannel', event => {
res(event.channel);
});
}
});
});
}
join().then(dc => {
dc.addEventListener('open', event => {
dc.send('Hello');
});
dc.addEventListener('message', event => {
console.log(event.data);
});
});
The behavior is the same in both Firefox and Chrome. That behavior is, again, that the offers and answers are signalled successfully, but no ICE candidates are ever created. Does anyone know what I'm missing?
Okay, I found the problem. I have to create the RTCDataChannel before creating the offer. Here's a before and after comparison of the SDP offers:
# offer created before data channel:
{
type: 'offer',
sdp: 'v=0\r\n' +
'o=- 9150577729961293316 2 IN IP4 127.0.0.1\r\n' +
's=-\r\n' +
't=0 0\r\n' +
'a=extmap-allow-mixed\r\n' +
'a=msid-semantic: WMS\r\n'
}
# data channel created before offer:
{
type: 'offer',
sdp: 'v=0\r\n' +
'o=- 1578211649345353372 2 IN IP4 127.0.0.1\r\n' +
's=-\r\n' +
't=0 0\r\n' +
'a=group:BUNDLE 0\r\n' +
'a=extmap-allow-mixed\r\n' +
'a=msid-semantic: WMS\r\n' +
'm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n' +
'c=IN IP4 0.0.0.0\r\n' +
'a=ice-ufrag:MZWR\r\n' +
'a=ice-pwd:LfptE6PDVughzmQBPoOtvaU8\r\n' +
'a=ice-options:trickle\r\n' +
'a=fingerprint:sha-256 1B:C4:38:9A:CD:7F:34:20:B8:8D:78:CA:4A:3F:81:AE:C5:55:B3:27:6A:BD:E5:49:5A:F9:07:AE:0C:F6:6F:C8\r\n' +
'a=setup:actpass\r\n' +
'a=mid:0\r\n' +
'a=sctp-port:5000\r\n' +
'a=max-message-size:262144\r\n'
}
In both cases the answer looked similar to the offer. You an see the offer is much longer and mentions webrtc-datachannel in the second case. And sure enough, I started getting icecandidate events and everything is working now.

What's the best way to consume messages in RabbitMq?

I have about 100 different types of messages and I'd like to know the correct way to consume them in RabbitMq.
I have 2 solutions and I don't know which one is the best way.
1: Implement 100 consumers for 100 different types of messages.
2: Implement 1 consumer and process the messages by for example switch case or etc.
In your opinion what's the best way?
If you are going to be calling 100 different messaging services then you will need to set up 100 different consumers BUT use only on rabbitmq connection
Here is how I implemented my rabbitmq consumer
module.exports.start = async () => {
try{
const queue1 = 'email';
const connection = await amqplib.connect(process.env.QUEUE_SERVICE);
const channel = await connection.createChannel();
await channel.assertQueue(queue1, { durable: true });
await channel.prefetch(1);
console.log('Listening for emails...');
channel.consume(queue1, async (msg) => {
if (msg !== null) {
winston.info(`Got message ${msg.content.toString()}`);
const queueMessage = JSON.parse(msg.content.toString());
Emails.Mailer(queueMessage)
.then(() => {
channel.ack(msg)
})
.catch(err=> err);
}
});
const queue2 = 'sms';
await channel.assertQueue(queue2, { durable: true });
await channel.prefetch(1);
console.log('Listening for SMS...');
channel.consume(queue2, async (msg) => {
if (msg !== null) {
const queueMessage = JSON.parse(msg.content.toString());
Sms.sendPaymentSms(queueMessage).then(() => channel.ack(msg));
}
});
} catch (error) {
return error
}
};
Another thing you can do to maintain code readability is to modularize the various services you want to call and call them in your consumer using conditionals or strategy design pattern.

React Native BLE with MiBand

I'm really new to this but I already know (by searching other projects through the Internet) that the MiBands have an authentication process.
The thing is I have tried to write without and with response to the only service UUID I got through the connection and it's always saying the band has not that UUID Service.
I am using React-Native-BLE-PLX library.
As it can be seen in the image I use the device's Service UUID since I cannot get any other service but it always says that it does not exist.
search(){
this.manager = new BleManager();
this.manager.startDeviceScan(null, null, (error, device) => {
if (error) {
console.log(error.message);
return;
}
if (device.name == 'Mi Band 3') {
this.manager.stopDeviceScan();
this.device = device;
this.connect();
}
});
}
connect() {
console.log("CONNECTING...");
this.device.connect()
.then(async (device) => {
console.log("CONNECTED!!!");
console.log("DEVICE CONNECTED:\n");
console.log(device);
this.auth(device);
// return this.manager.discoverAllServicesAndCharacteristicsForDevice(device.id)
})
// .then((device) => {
// console.log(device);
// this.send(device);
// })
// .catch((error) => {
// console.log("ERROR: ");
// console.log(error);
// });
}
async auth(device) {
console.log("DEVICE: \n");console.log(this.device);
console.log("DEVICE'S SERVICE UUID: \n" +this.device.serviceUUIDs[0]);
console.log("TRYING");
this.manager.writeCharacteristicWithoutResponseForDevice('D7:2D:F8:F2:24:3F', '0000fee0-0000-1000-8000-00805f9b34fb', '00000009-0000-3512-2118-0009af100700', 0x01 + 0x00 + new Buffer("OLA MUNDO"))
.then((device) => {
console.log("STUFF GOING ON:\n");
console.log(device);
})
.catch((error) => {
throw error;
});
}
Really need help and thanks for that.
If there is something I need to describe more please just tell me.
Directly after getting connected you must first discover the services and characteristics. After that you can start the authentication part. However your authentication part is totally wrong. Do a bit of Googling to find out how to do it properly...

Custom Authentication AngularFire2 Ionic2

I update my application from Ionic 1 to Ionic 2.
For the first App (Ionic 1) I use AngularFire and custom authentication (with Slim Framework). With Ionic 2 I try to do the same thing with AngularFire2 (and firebase 2.4.2) but I have this error when I auth to firebase.
Code (App.ts):
#App({
templateUrl: './build/app.html',
providers: [
FIREBASE_PROVIDERS,
defaultFirebase('https://<APP>.firebaseio.com/'),
firebaseAuthConfig({
provider: AuthProviders.Custom,
method: AuthMethods.CustomToken
})
]
})
Code (Login.ts):
export class LoginPage {
n_adherent:number = null;
password:string = '';
constructor(..., private af:AngularFire, private _authService:AuthService) {}
connect() {
let credentials = {
n_adherent: parseInt(this.n_adherent, 10),
password: this.password
};
// Send credentials to my PHP server
this._autService.login(credentials)
.subscribe(data => {
if (data.token) {
// I get the token
let token = data.token;
// Authenticate to Firebase
this.af.auth.login(token)
.then((data) => console.log(data))
.catch((error) => console.log(error));
}
});
}
}
Error (in console):
You must include credentials to use this auth method.
Code from firebase/php-jwt:
<?php
use \Firebase\JWT\JWT;
$key = "example_key";
$token = array(
"iss" => "http://example.org",
"aud" => "http://example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
/**
* IMPORTANT:
* You must specify supported algorithms for your application. See
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
* for a list of spec-compliant algorithms.
*/
$jwt = JWT::encode($token, $key);
$decoded = JWT::decode($jwt, $key, array('HS256'));
print_r($decoded);
/*
NOTE: This will now be an object instead of an associative array. To get
an associative array, you will need to cast it as such:
*/
$decoded_array = (array) $decoded;
/**
* You can add a leeway to account for when there is a clock skew times between
* the signing and verifying servers. It is recommended that this leeway should
* not be bigger than a few minutes.
*
* Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
*/
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, $key, array('HS256'));
?>
Your help is needed.
Your token is a string, right?
We just had the same error and had to debug the source code.
We realised, that the this.af.auth.login method is waiting for two parameters.
Simply put, use the following:
this.af.auth.login(token, {})
Cheers,
Marcell
This should fix your issue:
this.af.auth.login(data.token, {
provider: AuthProviders.Custom,
method: AuthMethods.CustomToken
})
.then(data => {
console.log(data);
})
.catch(error => {
console.log(error);
});
Cheers.