forked from ruudverheijden/node-p1-reader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
147 lines (113 loc) · 4 KB
/
main.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
var EventEmitter = require('events');
var util = require('util');
var serialPort = require('serialport');
var serialPortUsed = false;
var availablePorts = [];
var constructor;
var timer;
var parsePacket = require('./lib/parsePacket');
var debug = require('./lib/debug');
var config = require('./config/config.json');
function P1Reader(options) {
debug.setDebugMode(options.debug);
if (options.emulator) {
serialPort = require('./lib/emulateSerialport');
serialPort.setEmulatorOverrides(options.emulatorOverrides);
}
constructor = this;
EventEmitter.call(this);
// Either force a specific port or automatically discover it
if (options && options.serialPort) {
availablePorts[0] = options.serialPort;
_setupSerialConnection();
} else {
serialPort.list(function (err, ports) {
if (err) {
throw new Error('Serialports could not be listed: ' + err);
}
debug.logAvailablePorts(ports);
for (var i = 0; i < ports.length; i++) {
availablePorts[i] = ports[i].comName;
}
_setupSerialConnection();
});
}
}
util.inherits(P1Reader, EventEmitter);
/**
* Retrieve the name of the serial port being used
*/
P1Reader.prototype.getSerialPort = function () {
return serialPortUsed;
};
module.exports = P1Reader;
/**
* Setup serial port connection
*/
function _setupSerialConnection() {
var port = availablePorts[0];
debug.log('Trying to connect to Smart Meter via port: ' + port);
// Go to the next port if this one didn't respond within the timeout limit
timer = setTimeout(function() {
if (!serialPortUsed) {
_tryNextSerialPort();
}
}, config.connectionSetupTimeout);
// Open serial port connection
var sp = new serialPort(port, config.serialPort);
var received = '';
sp.on('open', function () {
debug.log('Serial connection established');
sp.on('data', function (data) {
received += data.toString();
var startCharPos = received.indexOf(config.startCharacter);
var endCharPos = received.indexOf(config.stopCharacter);
// Package is complete if the start- and stop character are received
if (startCharPos >= 0 && endCharPos >= 0) {
var packet = received.substr(startCharPos, endCharPos - startCharPos);
var parsedPacket = parsePacket(packet);
received = '';
// Verify if connected to the correct serial port at initialization
if (!serialPortUsed) {
if (parsedPacket.timestamp !== null) {
debug.log('Connection with Smart Meter established');
serialPortUsed = port;
constructor.emit('connected', port);
} else {
_tryNextSerialPort();
}
}
debug.writeToLogFile(packet, parsedPacket);
constructor.emit('reading-raw', packet);
if (parsedPacket.timestamp !== null) {
constructor.emit('reading', parsedPacket);
} else {
constructor.emit('error', 'Invalid reading');
}
}
});
});
sp.on('error', function (error) {
constructor.emit('error', error);
// Reject this port if we haven't found the correct port yet
if (!serialPortUsed) {
_tryNextSerialPort();
}
});
sp.on('close', function () {
constructor.emit('close');
});
}
/**
* Try the next serial port if available
*/
function _tryNextSerialPort() {
clearTimeout(timer);
availablePorts.shift();
if (availablePorts.length > 0) {
debug.log('Smart Meter not attached to this port, trying another...');
_setupSerialConnection();
} else {
throw new Error('Could not find an attached Smart Meter');
}
}