143 lines
4.8 KiB
JavaScript
143 lines
4.8 KiB
JavaScript
import { SerialPort } from 'serialport';
|
|
import { EventEmitter } from 'events';
|
|
|
|
// JTAG interface, TODO: change me!
|
|
const NANO_PRODUCT_ID = '1001';
|
|
const NANO_VENDOR_ID = '303a';
|
|
const NANO_BAUD_RATE = 115200;
|
|
|
|
|
|
class NanoDevices extends EventEmitter {
|
|
all_nano_devices = {};
|
|
connected_nano_devices = {};
|
|
|
|
_list() {
|
|
let p = new Promise((resolve, reject) => {
|
|
SerialPort.list().then((ports, err) => {
|
|
if (err) {
|
|
reject(err); // TODO format for errors?
|
|
}
|
|
else {
|
|
let found_nano_devices = []
|
|
for (let port of ports) {
|
|
if (port.productId === NANO_PRODUCT_ID && port.vendorId === NANO_VENDOR_ID) {
|
|
found_nano_devices.push(port.serialNumber);
|
|
if (this.all_nano_devices[port.serialNumber] === undefined) {
|
|
this.all_nano_devices[port.serialNumber] = port;
|
|
this.emit('nanodevices:device-attached', port.serialNumber);
|
|
console.log('attached', port.serialNumber);
|
|
}
|
|
}
|
|
}
|
|
resolve(found_nano_devices);
|
|
for (let serialNumber in this.all_nano_devices) {
|
|
if (found_nano_devices.indexOf(serialNumber) === -1) {
|
|
delete this.all_nano_devices[serialNumber];
|
|
this.emit('nanodevices:device-detached', serialNumber);
|
|
console.log('detached', serialNumber);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
return p;
|
|
};
|
|
|
|
|
|
_handle_data(connected_port, data) {
|
|
connected_port.data += data;
|
|
let lines = connected_port.data.split('\n');
|
|
if (lines.length > 1) {
|
|
for (let i = 0; i < lines.length - 1; i++) {
|
|
this.emit('nanodevices:update', connected_port.serialNumber, lines[i]);
|
|
}
|
|
connected_port.data = lines[lines.length - 1];
|
|
}
|
|
};
|
|
|
|
|
|
list_devices() {
|
|
let result = [];
|
|
for (const [key, value] of Object.entries(this.all_nano_devices)) {
|
|
if (value.serialNumber)
|
|
result.push(key);
|
|
}
|
|
console.log('list_devices', result);
|
|
return result;
|
|
};
|
|
|
|
|
|
async send(deviceid, jsonstr) {
|
|
let connected_port = this.connected_nano_devices[deviceid];
|
|
if (connected_port === undefined) {
|
|
return Promise.reject('Device not connected');
|
|
}
|
|
else {
|
|
connected_port.port.write(jsonstr+'\n');
|
|
return Promise.resolve();
|
|
}
|
|
};
|
|
|
|
|
|
async connect(deviceid) {
|
|
let p = new Promise();
|
|
let nano_device = this.all_nano_devices[deviceid];
|
|
if (nano_device === undefined) {
|
|
p.reject('Device not attached');
|
|
}
|
|
else {
|
|
let port = new SerialPort(nano_device.path, { baudRate: NANO_BAUD_RATE, autoOpen: false });
|
|
port.on('error', (err) => {
|
|
// forward error to FE
|
|
this.emit('nanodevices:error', nano_device.serialNumber, err);
|
|
});
|
|
port.on('close', (err) => {
|
|
if (err && err.disconnected) {
|
|
// forward close to FE
|
|
this.emit('nanodevices:disconnected', nano_device.serialNumber);
|
|
}
|
|
delete this.connected_nano_devices[nano_device.serialNumber];
|
|
});
|
|
port.on('open', () => {
|
|
p.resolve(nano_device.serialNumber);
|
|
this.connected_nano_devices[nano_device.serialNumber] = { port: port, data: '' };
|
|
this.emit('nanodevices:connected', nano_device.serialNumber);
|
|
});
|
|
port.on('data', (data) => {
|
|
let connected_port = this.connected_nano_devices[nano_device.serialNumber];
|
|
this._handle_data(connected_port, data);
|
|
});
|
|
port.open((err)=>{
|
|
if (err) {
|
|
p.reject(err);
|
|
}
|
|
});
|
|
}
|
|
return p;
|
|
};
|
|
|
|
|
|
disconnect(deviceid) {
|
|
let p = new Promise();
|
|
let nano_device = this.all_nano_devices[deviceid];
|
|
if (nano_device === undefined) {
|
|
p.reject('Device not attached');
|
|
}
|
|
else {
|
|
if (this.connected_nano_devices[nano_device.serialNumber] === undefined) {
|
|
p.reject('Device not connected');
|
|
}
|
|
else {
|
|
nano_device.close();
|
|
p.resolve(nano_device.serialNumber);
|
|
}
|
|
}
|
|
return p;
|
|
};
|
|
|
|
};
|
|
|
|
const nanodevices = new NanoDevices();
|
|
|
|
export default nanodevices;
|