moscajs / mosca

MQTT broker as a module
mosca.io
3.2k stars 513 forks source link

MQTT over WS with Mosca+Express #802

Open kocil opened 4 years ago

kocil commented 4 years ago

Dear sir. I'm trying to use mqtt over web socket, as described https://github.com/mcollina/mosca/wiki/MQTT-over-Websockets

The client is running on Chrome. Using the embedded MOSCA, it worked well.

But using the MQTT.js Browserify Bundle, it did not work. My server side initialization is as follow:

//============================================= // Mosca & Express initialization var mosca = require("mosca"); var broker = new mosca.Server({}); var express = require("express"); var http = require("http"); var app = express() var srv = http.createServer(app)

broker.attachHttpServer(srv);

// mqtt.js from node_modules/mosca/public was copied to the public folder // thus the web root is the default public app.use(express.static('public'));

app.listen(3000, () => console.log('WebApp listening on port 3000!')); //=====================================

The express worked, it can serve the static HTML as well as the API. However the MQTT client was failed with the following error: WebSocket connection to 'ws://192.168.100.5:3000/' failed: Error during WebSocket handshake: Unexpected response code: 200

Please help. Thank you in advance.

Reda1000 commented 4 years ago

Just stumbling across your problem while looking for a different problem.

You should not need to connect to ws://...:3000 if :3000 is an HTTP-Endpoint serving the mqtt.js file (see Unexpected response code). The response should indicate a downgrade from http to ws.

Since you dont config any more details for mosca.Server I guess mosca sets up an mqtt-TCP-listener on 1883 - which would mean that you need another listener for WS-Connections with default port probably 9001.

kocil commented 4 years ago

thank you for responding this rather old question :)

Yes, I was thingking the same. I just do not know what config is to set the WS listener port, nor the default.

Reda1000 commented 4 years ago

Currently I am working with this:

Backend Node Express (TypeScript) + Mosca

// All other imports
const app = express();
const mosca = require('mosca');

const mqtt = new mosca.Server({
  http: {
    port: 3000,
    bundle: true,
    static: './'
  }
});

mqtt.on('clientConnected', (client) => {
//...
});

// fired when a message is received
mqtt.on('published', (packet, client) => {
//...
});

mqtt.on('ready', () => {
//...
});

/* This is optional to me since my Frontend already has proper MQTT Client integrated */
const path = require('path');
app.use('/mqtt-client', express.static(path.dirname(require.resolve('mosca')) + '/public'));

Frontend Angular2+ (Typescript) in app.module.ts:

import { IMqttMessage, MqttModule, IMqttServiceOptions } from 'ngx-mqtt';

export const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = {
  hostname: 'some-host-with-mqtt-on-port-3000',
  port: 3000,
  path: '/mqtt'
};

It should also work with plain HTML + JS when loading MQTT-client by Backend-Endpoint '/mqtt-client'.

I know it is not the best version so far - make it work then make it right. In case you need a better version i might come up with some nicer implementation next days / weeks.