Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the openImmediatly flag in favor of the autoOpen option #830

Merged
merged 1 commit into from
May 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 32 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ You're reading the README for the master branch of serialport. You probably want

***

Imagine a world where you can write JavaScript to control blenders, lights, security systems, or even robots. Yes, I said robots. That world is here and now with node-serialport. It provides a very simple interface to the low level serial port code necessary to program [Arduino](http://www.arduino.cc/) chipsets, [X10](http://www.smarthome.com/manuals/protocol.txt) wireless communications, or even the rising [Z-Wave](http://www.z-wave.com/modules/ZwaveStart/) and [Zigbee](http://www.zigbee.org/) standards. The physical world is your oyster with this goodie. For a full break down of why we made this, please read [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics).
Imagine a world where you can write JavaScript to control blenders, lights, security systems, or even robots. Yes, I said robots. That world is here and now with node serialport. It provides a very simple interface to the low level serial port code necessary to program [Arduino](http://www.arduino.cc/) chipsets, [X10](http://www.smarthome.com/manuals/protocol.txt) wireless communications, or even the rising [Z-Wave](http://www.z-wave.com/modules/ZwaveStart/) and [Zigbee](http://www.zigbee.org/) standards. The physical world is your oyster with this goodie. For a full break down of why we made this, please read [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics).

***

Expand All @@ -46,7 +46,7 @@ For getting started with node-serialport, we recommend you begin with the follow
* [Listing Ports](#listing-ports)
* [Parsers](#parsers)
* [Methods](#methods)
* [SerialPort](#serialport-path-options-openimmediately-callback)
* [SerialPort](#serialport-path-options-opencallback)
* [close()](#close-callback)
* [drain()](#drain-callback)
* [flush()](#flush-callback)
Expand Down Expand Up @@ -177,54 +177,67 @@ When opening a serial port, you can specify (in this order).

### Opening a Port

Constructing a `SerialPort` object will open a port, eventually. You can bind events while the port is opening but you must wait until it is open to `write()` to it. (Most port functions require an open port.) You can call code when a port is opened in three ways.
Constructing a `SerialPort` object will open a port on `nextTick`. You can bind events while the port is opening but you must wait until it is open to `write()` to it. (Most port functions require an open port.) You can call code when a port is opened in three ways.

- The `open` event is always emitted when the port is opened
- The constructor callback is called when the port is opened and you haven't disabled the `openImmediately` option, if you have disabled it, the callback is only used for errors.
- The `.open()` function takes a callback that is called when the port is opened. This can be used if you disabled the `openImmediately` option or have previously closed an open port.
- The constructor's openCallback is passed to `.open()` when the `autoOpen` option hasn't been disabled, if you have disabled it the callback is ignored.
- The `.open()` function takes a callback that is called after the port is opened. This can be used if you disabled the `autoOpen` option or have previously closed an open port.


```js
var SerialPort = require('serialport');
var port = new SerialPort('/dev/tty-usbserial1');

port.on('open', function () {
port.on('open', function() {
port.write('main screen turn on', function(err) {
if (err) {
return console.log('Error: ', err.message);
return console.log('Error on write: ', err.message);
}
console.log('message written');
});
});

// open errors will be emitted as an error event
port.on('error', function(err) {
console.log('Error: ', err.message);
})
```

This could be moved to the constructor's callback.
```js
var SerialPort = require('serialport');
var port = new SerialPort('/dev/tty-usbserial1', function () {
var port = new SerialPort('/dev/tty-usbserial1', function (err) {
if (err) {
return console.log('Error: ', err.message);
}
port.write('main screen turn on', function(err) {
if (err) {
return console.log('Error: ', err.message);
return console.log('Error on write: ', err.message);
}
console.log('message written');
});
});
```

When disabling the `openImmediately` flag you'll need to open the port on your own. Note, in order to disable the `openImmediately` flag, we have to pass an options object.
When disabling the `autoOpen` option you'll need to open the port on your own.

```js
var SerialPort = require('serialport');
var port = new SerialPort('/dev/tty-usbserial1', {}, false);
var port = new SerialPort('/dev/tty-usbserial1', { autoOpen: false });

port.open(function (err) {
if (err) {
return console.log('Error opening port: ', err.message);
}

// errors will be emitted on the port since there is no callback to write
// write errors will be emitted on the port since there is no callback to write
port.write('main screen turn on');
});

// the open event will always be emitted
port.on('open', function() {
// open logic
});
```

### Listing Ports
Expand Down Expand Up @@ -272,7 +285,7 @@ var port = new SerialPort('/dev/tty-usbserial1', {
});
```

To use the raw parser, you just provide the function definition (or leave undefined):
To use the raw parser don't specify any parser, however if you really want to you can:

```js
var SerialPort = require('serialport');
Expand Down Expand Up @@ -302,9 +315,9 @@ Enjoy and do cool things with this code.

## Methods

### SerialPort (path, options, openImmediately, openCallback)
### SerialPort (path, options, openCallback)

Create a new serial port on `path`. In the case of invalid arguments or invalid options constructing a new serialport will throw an error. If `openImmediately` is true (the default) the `openCallback` will be passed to `.open()`
Create a new serial port object for the `path`. In the case of invalid arguments or invalid options when constructing a new SerialPort it will throw an error. The port will open automatically by default which is the equivalent of calling `port.open(openCallback)` in the next tick. This can be disabled by setting the option `autoOpen` to false.

**_path_**

Expand All @@ -314,6 +327,7 @@ The system path of the serial port to open. For example, `/dev/tty` on Mac/Linux

Port configuration options.

* `autoOpen` Automatically opens the port on `nextTick`, defaults to `true`.
* `baudRate` Baud Rate, defaults to 9600. Should be one of: 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 200, 150, 134, 110, 75, or 50. Custom rates as allowed by hardware is supported. Windows doesn't support custom baud rates.
* `dataBits` Data Bits, defaults to 8. Must be one of: 8, 7, 6, or 5.
* `stopBits` Stop Bits, defaults to 1. Must be one of: 1 or 2.
Expand All @@ -333,15 +347,11 @@ These properties are ignored for windows. An object with the following propertie
* `vmin` (default: 1) - see [`man termios`](http://linux.die.net/man/3/termios)
* `vtime` (default: 0) - see [`man termios`](http://linux.die.net/man/3/termios)

**_openImmediately (optional)_**
**_`openCallback` (optional)_**

Attempts to open a connection to the serial port on `process.nextTick`. The default is `true`. If you've provided a `openCallback` it will be given to `open()`. Set to `false` to manually call `open()`.

**_callback (optional)_**

Called when a connection has been opened. The callback should be a function that looks like: `function (error) { ... }`
This function is passed to `.open()` and called when a connection has been opened. The callback should be a function that looks like: `function (error) { ... }`

**Note:** The callback will NOT be called if openImmediately is set to false as the open will not be performed.
**Note:** The callback will NOT be called if autoOpen is set to false as the open will not be performed.

### .open (callback)

Expand Down
2 changes: 1 addition & 1 deletion examples/opening.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
// When disabling open immediately.

// var SerialPort = require('serialport');
// var port = new SerialPort('/dev/tty-usbserial1', {}, false);
// var port = new SerialPort('/dev/tty-usbserial1', { autoOpen: false });

// port.open(function (err) {
// if (err) {
Expand Down
20 changes: 10 additions & 10 deletions lib/serialport.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var kMinPoolSpace = 128;

var defaultSettings = {
baudRate: 9600,
autoOpen: true,
parity: 'none',
xon: false,
xoff: false,
Expand Down Expand Up @@ -76,19 +77,18 @@ function correctOptions(options) {
return options;
}

function SerialPort(path, options, openImmediately, callback) {
var args = Array.prototype.slice.call(arguments);
callback = args.pop();
if (typeof callback !== 'function') {
callback = null;
function SerialPort(path, options, callback) {
if (typeof callback === 'boolean') {
throw new TypeError('`openImmediately` is now called `autoOpen` and is a property of options');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see people not reading the upgrade notes for a while and this should help prevent issues with that.

}

options = (typeof options !== 'function') && options || {};

if (openImmediately === undefined || openImmediately === null) {
openImmediately = true;
if (typeof options === 'function') {
callback = options;
options = {};
}

options = options || {};

stream.Stream.call(this);

if (!path) {
Expand Down Expand Up @@ -151,7 +151,7 @@ function SerialPort(path, options, openImmediately, callback) {

this.options = settings;

if (openImmediately) {
if (this.options.autoOpen) {
// is nextTick necessary?
process.nextTick(this.open.bind(this, callback));
}
Expand Down
4 changes: 2 additions & 2 deletions test/integration-lite.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe('SerialPort light integration', function() {
});

it('cannot be opened twice', function(done) {
var port = new SerialPort(testPort, {}, false);
var port = new SerialPort(testPort, { autoOpen: false });
var calls = 0;
var errors = 0;
var spy = function(err) {
Expand All @@ -92,7 +92,7 @@ describe('SerialPort light integration', function() {
});

it('can open and close ports repetitively', function(done) {
var port = new SerialPort(testPort, {}, false);
var port = new SerialPort(testPort, { autoOpen: false });
port.open(function(err) {
assert.isNull(err);
port.close(function(err) {
Expand Down
40 changes: 25 additions & 15 deletions test/serialport.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@ describe('SerialPort', function() {
sandbox.restore();
});

describe('Legacy Constructor', function() {
it('still works', function(done){
describe('Depreciated options', function() {
it('legacy constructor still works', function(done){
this.port = new SerialPort.SerialPort('/dev/exists', done);
});

it('throws when `openImmediately` is set', function(done) {
try {
this.port = new SerialPort('/dev/exists', {}, false);
} catch (e) {
assert.instanceOf(e, TypeError);
done();
}
});
});

describe('Constructor', function() {
Expand Down Expand Up @@ -127,9 +136,10 @@ describe('SerialPort', function() {
xon: true,
xoff: true,
xany: true,
rtscts: true
rtscts: true,
autoOpen: false
};
var port = new SerialPort('/dev/exists', options, false);
var port = new SerialPort('/dev/exists', options);
assert.isTrue(port.options.xon);
assert.isTrue(port.options.xoff);
assert.isTrue(port.options.xany);
Expand All @@ -146,7 +156,7 @@ describe('SerialPort', function() {
describe('#open', function() {
it('passes the port to the bindings', function(done) {
var openSpy = sandbox.spy(bindings, 'open');
var port = new SerialPort('/dev/exists', {}, false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
expect(port.isOpen()).to.be.false;
port.open(function(err) {
expect(err).to.not.be.ok;
Expand Down Expand Up @@ -175,12 +185,12 @@ describe('SerialPort', function() {
assert.isFunction(cb);
done();
});
var port = new SerialPort('/dev/exists', {}, false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
port.open();
});

it('calls back an error when opening an invalid port', function(done) {
var port = new SerialPort('/dev/unhappy', {}, false);
var port = new SerialPort('/dev/unhappy', { autoOpen: false });
port.open(function(err) {
expect(err).to.be.ok;
done();
Expand Down Expand Up @@ -212,7 +222,7 @@ describe('SerialPort', function() {
});

it('cannot be opened twice', function(done) {
var port = new SerialPort('/dev/exists', {}, false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
var calls = 0;
var errors = 0;
var spy = function(err) {
Expand Down Expand Up @@ -265,7 +275,7 @@ describe('SerialPort', function() {
});

it('emits an error event or error callback but not both', function(done) {
var port = new SerialPort('/dev/exists', false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
var called = 0;
var doneIfTwice = function(err) {
assert.instanceOf(err, Error);
Expand Down Expand Up @@ -294,7 +304,7 @@ describe('SerialPort', function() {

it('errors when the port is not open', function(done) {
var cb = function() {};
var port = new SerialPort('/dev/exists', false, cb);
var port = new SerialPort('/dev/exists', { autoOpen: false }, cb);
port.close(function(err) {
assert.instanceOf(err, Error);
done();
Expand All @@ -304,13 +314,13 @@ describe('SerialPort', function() {

describe('#isOpen', function() {
it('returns false when the port is created', function(done) {
var port = new SerialPort('/dev/exists', {}, false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
assert.isFalse(port.isOpen());
done();
});

it('returns false when the port is opening', function(done) {
var port = new SerialPort('/dev/exists', {}, false);
var port = new SerialPort('/dev/exists', { autoOpen: false });
sandbox.stub(bindings, 'open', function() {
assert.isTrue(port.opening);
assert.isFalse(port.isOpen());
Expand Down Expand Up @@ -361,7 +371,7 @@ describe('SerialPort', function() {
describe('#set', function() {
it('errors when serialport not open', function(done) {
var cb = function() {};
var port = new SerialPort('/dev/exists', {}, false, cb);
var port = new SerialPort('/dev/exists', { autoOpen: false }, cb);
port.set({}, function(err) {
assert.instanceOf(err, Error);
done();
Expand Down Expand Up @@ -432,7 +442,7 @@ describe('SerialPort', function() {

it('flush errors when serialport not open', function(done) {
var cb = function() {};
var port = new SerialPort('/dev/exists', {}, false, cb);
var port = new SerialPort('/dev/exists', { autoOpen: false }, cb);
port.flush(function(err) {
assert.instanceOf(err, Error);
done();
Expand All @@ -441,7 +451,7 @@ describe('SerialPort', function() {

it('drain errors when serialport not open', function(done) {
var cb = function() {};
var port = new SerialPort('/dev/exists', {}, false, cb);
var port = new SerialPort('/dev/exists', { autoOpen: false }, cb);
port.drain(function(err) {
assert.instanceOf(err, Error);
done();
Expand Down