I have implemented a feathers service to get data from temperature sensor and i want to display real time data using angular and socket io. At the moment i am getting 'user connected' message in server console but i'm having trouble figuring out how to display data in angular client side.
Here is my server side code (app.js)
const path = require('path');
const favicon = require('serve-favicon');
const compress = require('compression');
const helmet = require('helmet');
const cors = require('cors');
const logger = require('./logger');
const io = require('socket.io-client');
const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const middleware = require('./middleware');
const services = require('./services');
const appHooks = require('./app.hooks');
const channels = require('./channels');
const mongodb = require('./mongodb');
// Set up Socket.io client with the socket
const app = express(feathers());
app.configure(socketio());
app.configure(socketio(function(io) {
io.on('connection', (socket) => {
socket.emit('message', { text: 'A client connected!' });
console.log('user connected');
socket.send('Sent a message 4seconds after connection!');
console.log('message sent');
socket.on('clientEvent', function(data) {
console.log(data);});
});
io.use(function (socket, next) {
// Exposing a request property to services and hooks
socket.feathers.referrer = socket.request.referrer;
next();
});
}));
messages.class.js
const { Service } = require('feathers-mongodb');
const MongoClient = require('mongodb').MongoClient;
exports.Messages = class Messages extends Service {
constructor(options, app) {
var cors = require('cors')
var awsIot = require('aws-iot-device-sdk');
//
// Replace the values of '<YourUniqueClientIdentifier>' and '<YourCustomEndpoint>'
// with a unique client identifier and custom host endpoint provided in AWS IoT.
// NOTE: client identifiers must be unique within your AWS account; if a client attempts
// to connect with a client identifier which is already in use, the existing
// connection will be terminated.
//
var device = awsIot.device({
keyPath: '*****************',
certPath: '*****************',
caPath: '*****************',
clientId: '*****************',
host: '*****************'
});
device
.on('connect', function() {
console.log('connect');
device.subscribe('outTopic');
//device.publish('appoutTopic', JSON.stringify({ test_data: 1}));
});
device
.on('message', function(topic, payload) {
var obj = JSON.parse(payload);
var msg = JSON.stringify(obj);
MongoClient.connect('mongodb://localhost:27017/feathers')
.then(function(client){
// Set the model now that we are connected
app.service('messages').Model = client.db('feathers').collection('messages');
app.service('messages').create({
msg
}).then(message => console.log('Created message', message));
}).catch(error => console.error(error));
const messages = app.service('messages');
messages.on ('created', (message,context)=> console.log('created',message,context));
});
super(options);
}
};
angular service (chat.service.ts)
import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable,Subject } from 'rxjs';
import * as feathers from 'feathers/client';
import * as socketio from 'feathers-socketio/client';
import * as hooks from 'feathers-hooks';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private url: string = 'http://localhost:8080';
public socket: SocketIOClient.Socket;
public app: any;
constructor() {
this.socket = io(this.url);
this.app = feathers()
.configure(socketio(this.socket))
.configure(hooks());
}
getMessages() {
let observable = new Observable(observer => {
this.socket.on('created', (message) => {
console.log(message);
observer.next(message);
});
return () => {
this.socket.disconnect();
};
})
return observable;
}
}
receive.components.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { ChatService } from '../chat.service';
@Component({
selector: 'app-receive',
templateUrl: './receive.component.html',
styleUrls: ['./receive.component.css'],
providers: [ChatService]
})
export class ReceiveComponent implements OnInit, OnDestroy {
messages = [];
connection;
message;
constructor(private chatService:ChatService) {}
ngOnInit() {
this.connection = this.chatService.getMessages().subscribe(message => {
this.messages.push(message);
})
}
ngOnDestroy() {
this.connection.unsubscribe();
}
}
Since this is my first question in stackoverflow please excuse my mistakes and point them out so i could update question accordingly.
The Feathers guide, specifically the quick start and the frontend guide explains how everything fits together.
There also is feathers-reactive which gives you real-time observables automatically and the feathers-chat-angular with an Angular (8) example of the chat application that uses feathers-reactive
.
In your case, you don't want to listen on the socket (this.socket
) in getMessages
but on the messages
service in this.app
:
import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable,Subject } from 'rxjs';
import * as feathers from 'feathers/client';
import * as socketio from 'feathers-socketio/client';
import * as hooks from 'feathers-hooks';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private url: string = 'http://localhost:8080';
public socket: SocketIOClient.Socket;
public app: any;
constructor() {
this.socket = io(this.url);
this.app = feathers()
.configure(socketio(this.socket))
.configure(hooks());
}
getMessages() {
let observable = new Observable(observer => {
this.app.service('messages').on('created', (message) => {
console.log(message);
observer.next(message);
});
return () => {
this.socket.disconnect();
};
})
return observable;
}
}