diff --git a/lib/i2c.js b/lib/i2c.js index 1ff537a..7469ee6 100644 --- a/lib/i2c.js +++ b/lib/i2c.js @@ -1,22 +1,22 @@ const wire = require('../build/Release/i2c'); const { EventEmitter } = require('events'); +const { promisify } = require('util'); const tick = setImmediate || process.nextTick; class i2c extends EventEmitter { - constructor(address, options) { super(); this.address = address; this.options = { debug: false, - device: "/dev/i2c-1", + device: '/dev/i2c-1', ...(options || {}) }; this.history = []; if (this.options.debug) { require('repl').start({ - prompt: "i2c > " + prompt: 'i2c > ' }).context.wire = this; process.stdin.emit('data', ''); // trigger repl } @@ -31,11 +31,26 @@ class i2c extends EventEmitter { console.log(`Error: ${err}`); }); - this.open(this.options.device, (err) => { - if (!err) { - this.setAddress(this.address); - } - }); + try { + this.open(this.options.device, (err) => { + if (!err) { + this.setAddress(this.address); + } + }); + } catch (err) { + // most likely no i2c device + console.log(err); + } + + // add promise methods + this.openAsync = promisify(this.open).bind(this); + this.scanAsync = promisify(this.scan).bind(this); + this.writeAsync = promisify(this.write).bind(this); + this.writeByteAsync = promisify(this.writeByte).bind(this); + this.writeBytesAsync = promisify(this.writeBytes).bind(this); + this.readAsync = promisify(this.read).bind(this); + this.readByteAsync = promisify(this.readByte).bind(this); + this.readBytesAsync = promisify(this.readBytes).bind(this); } scan(callback) { @@ -117,29 +132,35 @@ class i2c extends EventEmitter { readBytes(cmd, len, callback) { this.setAddress(this.address); - wire.readBlock(cmd, len, null, (err, actualBuffer) => { + wire.readBlock(cmd, len, (err, actualBuffer) => { tick(() => { if (callback) callback(err, actualBuffer); }); }); } - stream(cmd, len, delay) { - if (delay == null) delay = 100; + stream(cmd, len, delay = 100) { this.setAddress(this.address); - wire.readBlock(cmd, len, delay, (err, data) => { - if (err) { - this.emit('error', err); - } else { - this.emit('data', { - address: this.address, - data: data, - cmd: cmd, - length: len, - timestamp: Date.now() - }); - } - }); + + const intervalId = setInterval(() => { + this.readBytes(cmd, len, (err, data) => { + if (err) { + this.emit('error', err); + } else { + this.emit('data', { + address: this.address, + data: data, + cmd: cmd, + length: len, + timestamp: Date.now() + }); + } + }); + }, delay); + + return () => { + clearInterval(intervalId); + }; } } diff --git a/package.json b/package.json index 4d40dc3..dd3ee88 100644 --- a/package.json +++ b/package.json @@ -3,15 +3,28 @@ "version": "0.3.0", "description": "Native bindings for i2c-dev. Plays well with Raspberry Pi and BeagleBone.", "main": "main.js", - "author": "Kelly Korevec", + "author": { + "name": "Kelly Korevec", + "email": "korevec@gmail.com", + "url": "http://www.korevec.com" + }, "repository": { "type": "git", - "url": "http://github.com/korevec/node-i2c.git" + "url": "https://github.com/korevec/node-i2c.git" }, "license": "BSD-3-Clause-Attribution", "dependencies": { "bindings": "^1.5.0", "nan": "^2.24.0" }, - "engine": "node >= 18.0.0" + "engine": "node >= 18.0.0", + "keywords": [ + "i2c", + "raspberry-pi", + "beaglebone" + ], + "homepage": "https://github.com/korevec/node-i2c", + "bugs": { + "url": "https://github.com/korevec/node-i2c/issues" + } } diff --git a/src/i2c.cc b/src/i2c.cc index cb8d6af..2588aa5 100644 --- a/src/i2c.cc +++ b/src/i2c.cc @@ -155,32 +155,20 @@ void ReadBlock(const Nan::FunctionCallbackInfo& info) { int8_t cmd = info[0]->Int32Value(Nan::GetCurrentContext()).FromJust(); int32_t len = info[1]->Int32Value(Nan::GetCurrentContext()).FromJust(); - std::vector data(len); - Local err = Nan::New(Nan::Null()); - Local buffer = Nan::NewBuffer(len).ToLocalChecked(); + char* bufferData = node::Buffer::Data(buffer); + Local err = Nan::New(Nan::Null()); - while (fd > 0) { - if (i2c_smbus_read_i2c_block_data(fd, cmd, len, data.data()) != len) { - err = Nan::Error(Nan::New("Error reading length of bytes").ToLocalChecked()); - } - - memcpy(node::Buffer::Data(buffer), data.data(), len); + if (i2c_smbus_read_i2c_block_data(fd, cmd, len, (uint8_t*) bufferData) != len) { + err = Nan::Error(Nan::New("Error reading length of bytes").ToLocalChecked()); + } - if (info[3]->IsFunction()) { - const unsigned argc = 2; - Local callback = Local::Cast(info[3]); - Local argv[argc] = { err, buffer }; - Nan::Call(callback, Nan::GetCurrentContext()->Global(), argc, argv); - } - - if (info[2]->IsNumber()) { - int32_t delay = info[2]->Int32Value(Nan::GetCurrentContext()).FromJust(); - usleep(delay * 1000); - } else { - break; - } + if (info[2]->IsFunction()) { + const unsigned argc = 2; + Local callback = Local::Cast(info[2]); + Local argv[argc] = { err, buffer }; + Nan::Call(callback, Nan::GetCurrentContext()->Global(), argc, argv); } info.GetReturnValue().Set(buffer);