forked from evanshortiss/obd-parser-serial-connection
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
148 lines (121 loc) · 3.5 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
'use strict';
var SerialPort = require('serialport')
, Promise = require('bluebird')
, VError = require('verror')
, conn = null
, assert = require('assert')
, debug = require('debug')(require('./package.json').name);
// Keep track of connection requests
var connQ = [];
/**
* Factory function that can be used to get connections.
*
* It's not possible to have more than one connection so this will ensure
* that all callers share the same connection.
*
* @param {Object} opts
* @return {Promise | Socket}
*/
module.exports = function (opts) {
assert.equal(
typeof opts,
'object',
'an options object must be provided to obd-serial-connection'
);
assert.equal(
typeof opts.serialPath,
'string',
'opts.serialPath should be a string provided to obd-serial-connection'
);
assert.equal(
typeof opts.serialOpts,
'object',
'opts.serialOpts should be an Object provided to obd-serial-connection'
);
return function _obdSerialConnectorFn (configureFn) {
assert.equal(
typeof configureFn,
'function',
'you must provide a configureFn that returns a promise'
);
return new Promise(function (resolve, reject) {
debug('creating serialport connection');
if (conn && conn.ready) {
debug('returning existing connection instance');
resolve(conn);
} else {
debug('opening a serial connection');
// Keep track of the promise(s) we're returning
connQ.push({
resolve: resolve,
reject: reject
});
// Create our connection
conn = new SerialPort(opts.serialPath, opts.serialOpts);
// Connect to the serial port
conn.on('open', function () {
onConnectionOpened(configureFn);
});
conn.on('error', function (err) {
onConnectionOpened(configureFn, err);
});
}
});
};
};
/**
* Parses serial data and emits and event related to the PID of the data.
* Pollers will listen for events related to their PID
* @param {String} str
*/
function onSerialData (str) {
debug('received obd data %s', str);
}
/**
* Resolves/rejects any pending connection requests, depending on Error passed
* @param {Error} err
*/
function respondToConnectionRequests (err) {
connQ.forEach(function (req) {
if (err) {
req.reject(err);
} else {
req.resolve(conn);
}
});
}
/**
* General callback for the "error" event on the connection to ensure
* all errors are cpatured and logged.
* @param {Erorr} err
*/
function onSerialError (err) {
debug('serial emitted an error %s', err.toString());
debug(err.stack);
}
/**
* Handler for the "open" event for connections.
*
* This performs error handling if the connection fails, or sets up the
* connection with useful defaults if the connection is successful.
*
* @param {Error} err
*/
function onConnectionOpened (configureFn, err) {
if (err) {
err = new VError(err, 'failed to connect to ecu');
debug('error establishing a serial connection: %s', err);
respondToConnectionRequests(err);
} else {
debug('serial connection established, running configuration function');
// Bind listeners for data and errors
conn.on('error', onSerialError);
conn.on('data', onSerialData);
return configureFn(conn)
.then(function onConfigurationComplete () {
debug('finished running configuration function, returning connection');
conn.ready = true;
respondToConnectionRequests();
});
}
}