Search code examples
angularsocketsfeathersjs

How to display real time data from the feathersjs server using angular and socket io


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.


Solution

  • 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;
      }  
    }