javascript - 通过浏览器显示范围内的蓝牙设备

标签 javascript node.js http bluetooth

一个简单的想法。我想在通过 AJAX 调用时提供的 Web 浏览器中显示计算机范围内的蓝牙设备(通过蓝牙串行端口 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");

最佳答案

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

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

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>

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

关于javascript - 通过浏览器显示范围内的蓝牙设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24900797/

相关文章:

javascript - Node.js 中的 xml 宽度架构为 json

javascript - webdriver-manager 更新错误 : EACCES, 权限被拒绝

node.js - 在通用/同构应用程序中组织 package.json 依赖项

ruby-on-rails-3 - 无法在 Ruby on Rails 中使用 XML 数据执行 http POST

javascript - 如何在特定页面不执行JS代码

javascript - 如何在 QWebView 中获取 Javascript 以创建基于 C++ 的类的新实例?

javascript - 使用具有两个输入的箭头函数调用 Array.prototype.map() 的目的是什么?

javascript - TinyMCE 自托管 React

http - Angular2 http 默认 header 通用授权 token

python - 为什么我的 HTTP POST 请求数据字符串(可能)被错误编码?