I have mosquitto MQTT broker running on my machine. And I want to run the MQTT client from browser. This is what I have done in a Django app:
<html>
<head>
<title>Mosquitto Websockets</title>
{% load staticfiles %}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="{% static 'js/mqttws31-min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/jquery.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/config.js' %}" type="text/javasacript"></script>
<script type="text/javascript">
var mqtt;
var reconnectTimeout = 2000;
function MQTTconnect() {
host = '127.0.0.1';
port = 1883;
useTLS = false;
cleansession = true;
username = null;
password = null;
mqtt = new Paho.MQTT.Client(host, port,
"myclientid_" + parseInt(Math.random() * 100, 10));
/*mqtt = new Messaging.Client(
host,
port,
"web_" + parseInt(Math.random() * 100,
10));
*/
var options = {
timeout: 3,
useSSL: useTLS,
cleanSession: cleansession,
onSuccess: onConnect,
onFailure: function (message) {
$('#status').val("Connection failed: " + message.errorMessage + "Retrying");
setTimeout(MQTTconnect, reconnectTimeout);
}
};
mqtt.onConnectionLost = onConnectionLost;
mqtt.onMessageArrived = onMessageArrived;
if (username != null) {
options.userName = username;
options.password = password;
}
console.log("Host="+ host + ", port=" + port + " TLS = " + useTLS + " username=" + username + " password=" + password);
mqtt.connect(options);
}
function onConnect() {
$('#status').val('Connected to ' + host + ':' + port);
// Connection succeeded; subscribe to our topic
mqtt.subscribe(topic, {qos: 0});
$('#topic').val(topic);
}
function onConnectionLost(response) {
setTimeout(MQTTconnect, reconnectTimeout);
$('#status').val("connection lost: " + responseObject.errorMessage + ". Reconnecting");
};
function onMessageArrived(message) {
var topic = message.destinationName;
var payload = message.payloadString;
$('#ws').prepend('<li>' + topic + ' = ' + payload + '</li>');
};
$(document).ready(function() {
MQTTconnect();
});
</script>
</head>
<body>
<h1>Mosquitto Websockets</h1>
<div>
<div>Subscribed to <input type='text' id='topic' disabled />
Status: <input type='text' id='status' size="80" disabled /></div>
<ul id='ws' style="font-family: 'Courier New', Courier, monospace;"></ul>
</div>
</body>
</html>
I get
WebSocket connection to 'ws://127.0.0.1:1883/mqtt' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET mqttws31-min.js:15
Host=127.0.0.1, port=1883 TLS = false username=null password=null (index):47
I am new to this so am unable to resolve this. Any help?
Edit1:
I tweaked the config file and now it successfully connects to test.mosquitto.org:8080. I subscribed to #, but it is unable to retrieve the published message. I think function onMessageArrived(message) is not working. There are no errors in the console so unable to identify any errors.
Are you sure that you have configured the broker to accept websockets connections on port 1883? By default you would expect this to be listening for MQTT connections, not websockets.
Try putting the following in your config file:
listener 8080
protocol websockets
As Scott says, you could try connecting your client to test.mosquitto.org:8080 to see if it works.
Here is a site which runs a "MQTT over Websockets" server where the URL can act as a client so you can publish, then have your own browser act as a client subscribing to given topic
http://test.mosquitto.org/ws.html
it might let you tease apart connection issues ... also here is another nodejs library which implements similar functionality
https://www.npmjs.com/package/mqtt-ws
Based on your comment #toothie
"I tried connecting to 'test.mosquitto.org' and got this error: WebSocket connection to 'ws://test.mosquitto.org/:1883/mqtt' failed: Error during WebSocket handshake: Unexpected response code: 404"
The connection string you are sending seems bad formatted. How are you building it?
For me, the separation of concerns using the JSON object definition to instance the library saved me from a couple of headaches:
{
protocol: 'wss',
host: `${process.env.MQTT_ENDPOINT}`,
port: 9001,
username: 'admin',
password: '123'
}
Maybe something is helpful for you.
Related
I'm trying to connect to websocket client of MQTT.js but unable to get a handshake with the server.
My Code :
<html>
<head>
<title>test Ws mqtt.js</title>
</head>
<body>
<script src="//unpkg.com/mqtt#2.5.0/dist/mqtt.min.js"></script>
<script>
var options = {
clientId: 'service-3Kx03pKnM2',
connectTimeout: 5000,
hostname: 'xxx.xxx.xxx',
port: 8000
};
var client = mqtt.connect(options);
client.on('connect', function () {
client.subscribe('presence');
client.publish('presence', 'Hello mqtt')
});
client.on('message', function (topic, message) {
console.log(message.toString());
client.end();
});
</script>
</body>
</html>
I'm getting this error : WebSocket connection to 'ws://broker.hivemq.com:8000/' failed: Connection closed before receiving a handshake response.
Please let me know if I'm doing any mistake.
I'm not using any other scripts other than unpkg.com/mqtt#2.5.0/dist/mqtt.min.js
You are missing the path in your connection options.
The HiveMQ public broker listens on /mqtt for websocket connections, which is in accordance with the Eclipse Wiki
The path portion of the url specified on the MQTT connect should be "mqtt"
For instance ws://m2m.eclipse.org:800/mqtt . mqtt should be the default with the option for an alternative to be configured / specified
You need to add path: '/mqtt' in your options.
var options = {
clientId: 'service-3Kx03pKnM2',
connectTimeout: 5000,
hostname: 'xxx.xxx.xxx',
port: 8000,
path: '/mqtt'
};
I want to use flask, flask-socketio to implement an application which accept "command string" (like: ping 8.8.8.8) at the browser, then the server execute it and return the command's output to browser in real time.
My implementation is as below.
The client side emits 'exec_event' event to the server, the server runs the command and continually emit 'exec_response' event to client when new output is generated by the command.
The client can also send 'ctrlc_event' to server if it want to terminate the command.
Problem I got is:
The server can't handle the 'ctrlc_event' when it's handling the previous 'exec_event'. If I directly killed the long-running command like 'ping 8.8.8.8' on the server, then the server begin to handle 'ctrlc_event'.
Can anyone point me out the reason or give me some direction?
Server side code
from gevent import monkey
monkey.patch_all()
from flask import Flask, render_template, session, Response
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask.ext.socketio import SocketIO, emit
import os
import time
from subprocess import Popen, PIPE
class ExecForm(Form):
command = StringField('Command: ', validators=[DataRequired()])
submit = SubmitField('Execute')
class CtrlCForm(Form):
submit = SubmitField('Ctrl C')
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'hard-to-guess'
socketio = SocketIO(app)
#app.route('/')
def index():
exec_form = ExecForm()
ctrlc_form = CtrlCForm()
return render_template('index.html',
exec_form=exec_form,
ctrlc_form=ctrlc_form)
#socketio.on('exec_event', namespace='/test')
def execute(message):
command = message['data']
process = Popen(command, shell=True, stdout=PIPE, stderr=PIPE,
close_fds=True, preexec_fn=os.setsid)
session['pid'] = process.pid
for out in iter(process.stdout.readline, ''):
out = '<pre>' + out + '</pre>'
emit('exec_response', {'data': out})
time.sleep(0.001)
out = "Command finished." + '<br /><br />'
emit('exec_terminate', {'data': out})
#socketio.on('ctrlc_event', namespace='/test')
def ctrlc(message):
print("Received ctrlc")
# do something to kill the process
# finally emit an event.
out = "Process killed." + '<br /><br/>'
emit('ctrlc_response', {'data': out})
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=8080)
Client code is
<html>
<head>
<title>Example</title>
<script type="text/javascript" src='//code.jquery.com/jquery-1.11.0.min.js'></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
$('#exec_form').submit(function(event) {
socket.emit('exec_event', {data: $('#exec_input').val()});
return false;
});
$('#ctrlc_form').submit(function(event) {
socket.emit('ctrlc_event', {data: 'nothing'});
return false;
});
socket.on('exec_response', function(msg) {
$('#result').append(msg.data);
});
socket.on('exec_terminate', function(msg) {
$('#result').append(msg.data);
});
socket.on('ctrlc_response', function(msg) {
$('#result').append(msg.data);
});
});
</script>
<style>
.result {
overflow-y: scroll;
width: 100%;
height: 400px;
border: 4px solid red;
}
.result pre {
margin: 2px;
}
</style>
</head>
<body>
<h3>Flask Example</h3>
<form id="exec_form" method='POST' action='#' target='result'>
{{ exec_form.command.label }}
{{ exec_form.command(id="exec_input", placeholder="command", size=100) }}
{{ exec_form.submit(id="exec_btn") }}
</form>
<form id="ctrlc_form" method='POST' action='#' target='result'>
{{ ctrlc_form.submit(id="ctrlc_btn") }}
</form>
<div id="result" class="result"></div>
</body>
</html>
The problem is caused by the way the gevent-socketio server is structured. When the server receives an event from a client (let's say your exec_event), it dispatches the event by calling the appropriate handler. That thread will then run the event handler, and only once the handler returns it will go back to check for new client originated events.
The solution is to send the ctrlc_event on a different communication channel, not the same that you use for exec_event. For example, open two connections on different namespaces, then each connection will get its own server thread.
I'm actually working on a little application. I have one server written in C which is listening on the port 5260. In the other side I have a NodeJS client which is listening on the port 7777. A HTML page can be reach via this port. In the HTML page I have a simple button.
When I click on this one a message is sent to my NodeJS server and is written on the terminal. Now I would like to fetch this command and send it to my C server which is still running and waiting for a request.
My client.js :
var http = require('http');
var ejs = require('ejs');
var express=require('express');
var app = express();
app.engine('html', ejs.renderFile);
app.set('/', __dirname);
app.get('/', function(request,response) {
response.render('index.ejs.html');
})
var options = {
host: '192.168.1.154',
path: '/',
port: '5260',
method: 'POST'
};
app.post('/play', function(req, res){
var res = http.request(options);
console.log("START_BG;BG1\n");
});
app.listen(7777);
And my HTML file :
<html>
<head>
<script type="text/javascript" src="client.js"></script>
<script type="text/javascript">
function sendMessage() {
var xhr = new XMLHttpRequest();
xhr.open('POST', '/play', true);
xhr.onload = function() {
console.log(xhr);
};
xhr.send();
}
</script>
</head>
<body>
<button onclick="sendMessage()">VIDEO</button>
</body>
</html>
Well. I see some strange things in your code
1 You're making the post request to 192.168.1.254:5620/play without sending any data on it
2 You're not waiting fro the request to end and blindly print on your console without checking the result. Don't know if its the desired behaviour, but it seems a bit strange
Without more knowledge about the scenario is difficult to suggest an idea.
What is the answer you expect from the remote server?
It's suposed to print something in the (remote) console ?
What it should return via HTTP ?
Anyway I suggest you correct your code as follows:
app.post('/play', function(req, res){
var res = http.request(options, function(response){
// do any checking about response status and/or body if any
console.log("START_BG;BG1\n");
});
});
I've been attempting to learn enough html, css, and Dart to create my first web page and all is going well, except that I do not understand how to create a simple page and a server side web-socket server that will just echo it back. The examples that I find tend to illustrate other Dart tools and either connect to echo server on the web or do other things that make their code not simple for a newbie.
I've tried to simplify Seth Ladd's example "dart-example-web-sockets-client" as the 'best' example. I can receive what is sent from the page, repackage it and think i'm sending it back but absolutely nothing happens on the web page. I start the page by clicking on the URL returned when the web-server is run from inside the Dart editor. Since the page is not, AFAIK, run in the debugger I'm hampered in diagnosing the error.
Here is simplified code from Seth's server:
void handleEchoWebSocket(WebSocket webSocket) {
log.info('New WebSocket connection');
// Listen for incoming data. We expect the data to be a JSON-encoded String.
webSocket
.map((string) => JSON.decode(string))
.listen((json) {
// The JSON object should contain a 'request' entry.
var request = json['request'];
switch (request) {
case 'search':
var input = json['input'];
log.info("Received request '$request' for '$input'");
var response = {
'response': request,
'input': input,
};
webSocket.add(JSON.encode(response)); // can't detect page receiving this.
log.info("Echoed request..$request $input"); // correct data
break;
default:
log.warning("Invalid request: '$request'");
}
}, onError: (error) {
log.warning('Bad WebSocket request');
});
}
This example took the user input using it as input to two search engines, packaged the results and returned them to the page for display creating new DOM elements on the fly.
I just need to be pointed to a simple example that will echo what is submitted.
Here is a simple websocket client/server echo example. Messages doesn't show in browser window, but they are printed in console window. You have to start server.dart and main.dart separately. Both processes print messages to their own console window.
Edit: I added an output div for displaying the message also in browser.
bin\ws_server.dart:
import "dart:convert";
import 'dart:io';
import 'package:route/server.dart' show Router;
void handleWebSocket(WebSocket webSocket) {
// Listen for incoming data. We expect the data to be a JSON-encoded String.
webSocket
.map((string)=> JSON.decode(string))
.listen((json) {
// The JSON object should contains a 'echo' entry.
var echo = json['echo'];
print("Message to be echoed: $echo");
var response='{"response": "$echo"}';
webSocket.add(response);
}, onError: (error) {
print('Bad WebSocket request');
});
}
void main() {
int port = 9223;
HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, port).then((server) {
print("Search server is running on "
"'http://${server.address.address}:$port/'");
var router = new Router(server);
// The client will connect using a WebSocket. Upgrade requests to '/ws' and
// forward them to 'handleWebSocket'.
router.serve('/ws')
.transform(new WebSocketTransformer())
.listen(handleWebSocket);
});
}
web\index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Websocket echo</title>
</head>
<body>
<p>Websocket test</p>
<div id="output"></div>
<script type="application/dart" src="main.dart"></script>
</body>
</html>
web\main.dart:
library main;
import 'dart:async';
import 'dart:convert';
import 'dart:html';
class WebsocketService {
WebSocket webSocket;
WebsocketService() {
connect();
}
void connect() {
webSocket = new WebSocket('ws://127.0.0.1:9223/ws');
webSocket.onOpen.first.then((_) {
onConnected();
sendws("Hello websocket server");
webSocket.onClose.first.then((_) {
print("Connection disconnected to ${webSocket.url}");
onDisconnected();
});
});
webSocket.onError.first.then((_) {
print("Failed to connect to ${webSocket.url}. "
"Please run bin/server.dart and try again.");
onDisconnected();
});
}
void onConnected() {
webSocket.onMessage.listen((e) {
onMessage(e.data);
});
}
void onDisconnected() {
print("Disconnected, trying again in 3s");
new Timer(new Duration(seconds:3), (){
connect();
});
}
void onMessage(data) {
var json = JSON.decode(data);
var echoFromServer = json['response'];
print("Received message: $echoFromServer");
var output=querySelector('#output');
output.text="Received message: $echoFromServer";
new Timer(new Duration(seconds:3), (){ //Send a new message to server after 3s
String now = new DateTime.now().toString();
sendws("Time: $now");
});
}
void sendws(String msg){
var request = '{"echo": "$msg"}';
print("Send message to server: $request");
webSocket.send(request);
}
}
void main() {
WebsocketService ws=new WebsocketService();
}
The following codes for the Window Live Contacts API to Get all email address from. Its works fine in login, log-out, and other authentications. I can collect all user information of logged in user with Get Data function call, but am getting email hashes of users, rest of the email hashes are blank. I have 10 email address in my contact book.
How do i get the email addresses of my contacts using this api?
<html>
<head>
<script src="https://js.live.net/v5.0/wl.js" type="text/javascript"></script>
</head>
<body>
<a href='javascript:void(0);' onclick='signUserIn();'>signUserIn</a> <br>
<a href='javascript:void(0);' onclick='signUserOut()'>signUserOut</a><br>
<a href='javascript:void(0);' onclick='loginStatus()'>Check User Status</a>
<a href='javascript:void(0);' onclick='getData()'>Get Data</a>
<script type="text/javascript" >
WL.init({
client_id: '0000000044444444',
redirect_uri: 'http://domain.com/contact.php',
response_type: "token",
logging: true
});
var scopesArr = ['wl.signin', 'wl.basic', 'wl.emails'];
function signUserIn() {
WL.login({ scope: scopesArr });
}
function loginStatus() {
WL.getLoginStatus(function(response) {
alert("response " + response );
});
}
function getData() {
alert( "getData");
WL.api(
{
path: "me/contacts",
method: "GET",
scope: scopesArr
},
function (result) {
if (!result.error) {
var resultData = result.data;
var emailHashes = new Array;
for (i = 0; i < resultData.length; i++) {
for (j = 0; j < resultData[i].email_hashes.length; j++) {
alert( "resultData " + resultData[i].email_hashes[j]);
emailHashes[emailHashes.length] = resultData[i].email_hashes[j];
}
}
var resultText = "";
for (k = 0; k < emailHashes.length; k++) {
resultText += emailHashes[k] + "\r\n";
}
// document.getElementById("emailHashes").setAttribute("rows", emailHashes.length);
document.getElementById("lists").value = resultText;
}
else {
alert("Error getting contacts: " + result.error.message);
}
});
}
function signUserOut() {
WL.logout();
}
</script>
<textarea rows="10" cols="100" id="lists"></textarea>
</body>
</html>
I had the same problem and I find the solution, all you need to do is add the following scope to your list of scopes you're requesting: "wl.contacts_emails"
WL.login({scopes: ["wl.contacts_emails"]});
After did that, I had to remove my application from my profile to reset all scope and add a second time my application. (But if you don't want to ask all people who alerady use your apps, I can just reset secret token to force user to add again your app).
Microsoft does not allow you to get your contacts emails via API. They only issue email hashes used to match emails on your end.
Sorry to break it to you, but you are out of luck.
I have spent 5 days now trying to get Hotmail contacts and I can't figure it out.