【问题标题】:Showing bluetooth devices in range via browser通过浏览器显示范围内的蓝牙设备
【发布时间】:2014-07-28 04:29:10
【问题描述】:

一个简单的想法。我想在通过 AJAX 调用时提供的网络浏览器中显示计算机范围内的蓝牙设备(通过蓝牙串行端口 NodeJS 包使用蓝牙加密狗)。

我遇到的问题是,使用以下脚本时,我无法同时扫描设备并提供网站服务。您能否解释一下这里的工作流程以及为什么/什么是纠正问题的好方向?

var http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs"),
    port = process.argv[2] || 8888,
    btSerial = new (require('bluetooth-serial-port')).BluetoothSerialPort();

btSerial.inquire();

// Get the devices
var devices = [];

btSerial.on('found', function(address, name) {
  if(typeof devices[address] === 'undefined'){
    devices.push({'address': address,'name': name});
    console.log("Device Found: "+address+" which is named: "+name);
  }
});

// Keep searching
btSerial.on('finished', function() {
  console.log("Done searching");
  console.log(devices);
  //btSerial.inquire();
});


http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname,
    filename = path.join(process.cwd(), uri);

  if (uri == '/devices') {
    response.writeHead(200, {"Content-Type": "application/json"});
    response.write(JSON.stringify(devices));
    response.end();
    return;
  }

  fs.exists(filename, function(exists) {
    if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) filename += 'public/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      if(err) {        
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }

      response.writeHead(200);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");

【问题讨论】:

  • 您是否尝试过使用setInterval在后台定期调用btSerial.inquire

标签: javascript node.js http bluetooth


【解决方案1】:

解决方案比预期的要简单得多。

首先,我创建了一个蓝牙扫描仪服务(永远运行),它打开一个套接字并在找到每个设备时向服务器服务提供更新的结果。我将 setTimeout 函数设置为 1s (1000ms) 否则结果将不会传递到侦听服务器。

var port = 9838,
    devices = {},
    socket = require('socket.io-client')('http://localhost:'+port);
    btSerial = new (require('bluetooth-serial-port')).BluetoothSerialPort();

var onFinishedFoundDevice = function(message){
    // Add new device to object array
    if(typeof message.address !== 'undefined' && typeof message.name !== 'undefined') 
        devices[message.address] = {'address': message.address,'name': message.name};

    console.log("Sent new device", message);
};

var sendMessage = function(type, message, callback){
    this.message = message;
    socket.emit(type, message);

    if(callback)
        callback(message);
};


var findBluetooths = function () {
  // Scan for BT devices in range
  btSerial.on('found', function(address, name) {
    if(typeof devices[address] === 'undefined'){
      var message = {'address': address, 'name': name}; // prepare message
      sendMessage('add-device', message, onFinishedFoundDevice); // actually send message to server
      console.log("Device Found: "+address+" which is named: "+name);
    }
  });

  // Keep searching
  btSerial.on('finished', function() {
    console.log("Received Finished... cont'd");
    setTimeout(function(){btSerial.inquire();}, 1000);
  });

  // Scan for devices
  console.log("Begin scanning");
  btSerial.inquire();
}

// Do the magic
findBluetooths();

然后我创建了一个服务器服务(也永远运行),它启用 HTTP 服务器以及 socket.io 事件的侦听器。它接收来自蓝牙扫描仪以及 index.html 页面的事件。

var app = require('http').createServer(handler), 
    io = require('socket.io')(app),
    fs = require('fs'),
    port = 9838,
    devices = [];

app.listen(port);

function handler (req, res) {
  fs.readFile(__dirname + '/public/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.on('connection', function (socket) {
  socket.emit('devices', devices);

  socket.on('add-device', function(device) {
        devices.push({'address': device.address,'name': device.name});
        socket.broadcast.emit('device-added', device); // send device to browsers
        console.log("Device Found: "+device.address+" which is named: "+device.name);
    });

  socket.on('get-devices', function(payload){
n  });

});

最后我创建了一个 public/index.html 文件来显示扫描结果以及从服务器发出请求以获取更多信息。

<!DOCTYPE html>
<html>
    <head>
        <title>Bluetooth Scanner</title>
        <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
        <script src="/socket.io/socket.io.js"></script>
        <script>
            var port = 9838;
            var hostname = window.location.hostname;
            var socket = io(hostname+':'+port);

            socket.on('welcome', function (message) {
                console.log(message);
            });

            socket.on('device-added', function (device) {
                $("#no-devices").hide();

                $('<li>', {
                    html: "Device named "+device.name+" with MAC "+ device.address+" is online."
                }).appendTo('#devices');
            });

            socket.on('devices', function(devices){
                if(devices.length > 0) $("#no-devices").hide();

                $.each(devices, function(key, device){
                    $('<li>', {
                        html: "Device named <b>"+device.name+"</b> with MAC <b>"+ device.address+"</b> is online."
                    }).appendTo('#devices');
                });

            });

        </script>
    </head>
    <body>
        <div>
            <span id="no-devices">No devices yet...</span>
            <ul id="devices"></ul>
        </div>
    </body>
</html>

感谢大家的帮助。它缺乏真正使它可用的必要功能,但它是我项目的良好开端

【讨论】:

    【解决方案2】:

    要在后台定期扫描设备,请使用setInterval

    setInterval(btSerial.inquire, 10000);
    

    这将每 10 秒调用一次 btSerial.inquire。您需要确定应用程序的最佳刷新间隔。权衡是您可以在更短的时间间隔内获取更多最新的设备数据,但这会减少您的服务器处理 HTTP 请求的时间。

    【讨论】:

    • btSerial.on('finished', function(){...}) 处理完成的每一轮扫描,让我可以无限期地继续搜索。除了 on('finished') 内置在包中之外, setInterval 具有类似的效果。 setInterval() 和 on('finished') 在查询运行期间仍会阻止 HTTP 调用。我希望在后台运行蓝牙扫描,当检测到新的东西时更新设备数组,仍然在 HTTP 请求进入时处理它们。
    • 好的。我在想蓝牙扫描仪会很快完成,就像在
    猜你喜欢
    • 1970-01-01
    • 2017-04-18
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2011-11-03
    相关资源
    最近更新 更多