-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMarlinServer.js
151 lines (119 loc) · 3.83 KB
/
MarlinServer.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
149
150
151
const _ = require('lodash')
const chalk = require('chalk')
const Readline = require('serialport').parsers.Readline
const SerialPort = require('serialport')
const EventEmitter = require('events')
const Defered = require('./Defered')
module.exports = class MarlinServer extends EventEmitter{
constructor(options) {
super()
this.options = options || {}
this.promiseQueue = []
// Ready promise indicating reception of `start` string
this._ready = new Defered()
}
get name() {
return this.port ? this.port.path : 'DISCONNECTED'
}
async connect(serialPort) {
// Defaults to options.port
serialPort = serialPort || this.options.port || null
// Is it connecting/connected? Return last promise
if (this._connect) {
return await this._connect
}
// Must have a serialPort to seek
if (!serialPort) {
throw new Error('No serial port name or pattern provided')
}
// If serialPort is a string, use it as a object {comName: String}
if (_.isString(serialPort))
serialPort = {comName: serialPort}
else
serialPort = serialPort
// Try to find port
let portList = await SerialPort.list()
let portProp = _.find(portList, serialPort)
// If port was not found, reject promise
if (!portProp) {
throw new Error('Port not found: ' + JSON.stringify(serialPort))
}
// Create a new re-usable Promise that will wait for connection
this._connect = new Promise(async (resolve, reject) => {
try {
// Open Serial Port
this.port = new SerialPort(portProp.comName, { baudRate: 115200 })
// Bufferize Line and use as dataReceived
let lineBuffer = new Readline({ delimiter: '\n' })
// Proxy all data received by serial port to the line Buffer
this.port.pipe(lineBuffer)
// this.port.on('data', (data) =>{
// data = data.toString()
// console.log('( ', data.replace(/\n/g, chalk.yellow('\\n')).replace(/\r/g, chalk.yellow('\\r')))
// })
// Once there is data in the line Buffer, delegate to dataReceived
lineBuffer.on('data', (data) => this.dataReceived(data))
// Every time it opens/closes, reset the current queue
this.port.on('open', () => this.resetQueue())
this.port.on('close', () => this.resetQueue())
this.port.on('error', (err) => {
reject(err)
})
resolve()
} catch (e) {
reject(e)
}
})
await this._connect
}
ready() {
return this._ready.promise
}
resetQueue() {
let promise
while(promise = this.promiseQueue.shift())
promise.reject('Connection opening')
// this.promiseQueue = []
}
dataReceived(data) {
// Skip empty data packets
if (!data)
return
// Debug to console if debug flag is set
if (this.options.debug) {
// console.log('<', new Buffer(data))
console.log('<', data)
}
// Make sure it's a string
data = data.toString()
// Emit data
this.emit('data', data)
// Check for start packet
if (data.startsWith('start')) {
this.resetQueue()
return this._ready.resolve()
}
// Only packets starting with `:` are responses
if (!data.startsWith('ok')) {
return
}
let promise = this.promiseQueue.shift()
if (!promise)
return
promise.resolve(data)
}
execute(command) {
if (this.options.debug)
console.log('>', command)
// Combine with nl and cr
command += '\n'
// Write to serial port
// console.log(') ', command.replace(/\n/g, chalk.yellow('\\n')).replace(/\r/g, chalk.yellow('\\r')))
this.port.write(command)
// Return a new promise and pushes it to the queue
let promise = new Promise((resolve, reject) => {
this.promiseQueue.push({resolve, reject})
})
return promise
}
}