初始化提交

This commit is contained in:
王立帮
2024-07-19 10:16:00 +08:00
parent 4c7b571f20
commit 4a2d56dcc4
7084 changed files with 741212 additions and 63 deletions

View File

@@ -0,0 +1,188 @@
class SerialWorker {
#receiveBuffer_ = [];
#bufferLength_ = 0;
#encoder_ = new TextEncoder();
#decoder_ = new TextDecoder('utf-8');
#baud_ = 115200;
#dtr_ = false;
#rts_ = false;
#isOpened_ = false;
#port_ = '';
constructor(port) {
this.#port_ = port;
this.resetBuffer();
}
decodeBuffer(buffer) {
let output = '';
for (let i in buffer) {
output += this.decodeByte();
}
return output;
}
/* UTF-8编码方式
* ------------------------------------------------------------
* |1字节 0xxxxxxx |
* |2字节 110xxxxx 10xxxxxx |
* |3字节 1110xxxx 10xxxxxx 10xxxxxx |
* |4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
* |5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
* |6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx|
* ------------------------------------------------------------
**/
decodeByte(byte) {
let output = '';
if ((byte & 0x80) === 0x00) {
// 1字节
this.#receiveBuffer_ = [];
this.#bufferLength_ = 0;
output += String.fromCharCode(byte);
} else if ((byte & 0xc0) === 0x80) {
/*
* 2字节以上的中间字节10xxxxxx
* 如果没有起始头,则丢弃这个字节
* 如果不是2字节及以上的起始头则丢弃这个字节
**/
if (!this.#receiveBuffer_.length || this.#bufferLength_ < 2) {
return output;
}
this.#receiveBuffer_.push(byte);
if (this.#bufferLength_ === this.#receiveBuffer_.length) {
output += this.#decoder_.decode(new Uint8Array(this.#receiveBuffer_));
this.#receiveBuffer_ = [];
}
} else {
// 2字节以上的起始头
if (this.#receiveBuffer_) {
this.#receiveBuffer_ = [];
}
this.#bufferLength_ = this.#getBufferLength_(byte);
this.#receiveBuffer_.push(byte);
}
return output;
}
#getBufferLength_(data) {
let len = 2;
if ((data & 0xFC) === 0xFC) {
len = 6;
} else if ((data & 0xF8) === 0xF8) {
len = 5;
} else if ((data & 0xF0) === 0xF0) {
len = 4;
} else if ((data & 0xE0) === 0xE0) {
len = 3;
} else if ((data & 0xC0) === 0xC0) {
len = 2;
}
return len;
}
resetBuffer() {
this.#receiveBuffer_ = [];
this.#bufferLength_ = 0;
}
open() {}
close() {}
toggle() {
if (this.isOpened()) {
this.close();
} else {
this.open();
}
}
setBaudRate(baud) {
this.#baud_ = baud;
}
setDTR(dtr) {
this.#dtr_ = dtr;
}
setRTS(rts) {
this.#rts_ = rts;
}
setDTRAndRTS(dtr, rts) {
this.#dtr_ = dtr;
this.#rts_ = rts;
}
getPortName() {
return this.#port_;
}
getBaudRate() {
return this.#baud_;
}
getDTR() {
return this.#dtr_;
}
getRTS() {
return this.#rts_;
}
sendString(str) {}
sendBuffer(buffer) {}
onBuffer(buffer) {
const data = this.decodeBuffer(buffer);
if (!data) {
return;
}
self.postMessage({
port: this.getPortName(),
event: 'onBuffer',
message: data
});
}
onOpen() {
this.#isOpened_ = true;
self.postMessage({
port: this.getPortName(),
event: 'onOpen'
});
}
onClose(code) {
this.#isOpened_ = false;
self.postMessage({
port: this.getPortName(),
event: 'onClose',
message: code
});
}
onError(error) {
self.postMessage({
port: this.getPortName(),
event: 'onError',
message: error
});
}
isOpened() {
return this.#isOpened_;
}
config(info) {
if (typeof info !== Object) {
return;
}
this.#baud_ = info.baud;
this.setBaudRate(this.#baud_);
this.#dtr_ = info.dtr;
this.setDTR(this.#dtr_);
this.#rts_ = info.rts;
this.setDTR(this.#rts_);
}
}

View File

@@ -0,0 +1,66 @@
const chokidar = require('chokidar');
let watchedPath = {};
const watch = function(inPath) {
if (watchedPath[watchedPath]) {
return;
}
watchedPath[inPath] = chokidar.watch(inPath, {
persistent: true,
depth: 0,
ignoreInitial: true
});
watchedPath[inPath].on('add', (actionPath, stats) => {
self.postMessage({
watcher: inPath,
event: 'add',
path: actionPath,
stats
});
});
watchedPath[inPath].on('addDir', (actionPath, stats) => {
self.postMessage({
watcher: inPath,
event: 'addDir',
path: actionPath,
stats
});
});
watchedPath[inPath].on('unlink', (actionPath, stats) => {
self.postMessage({
watcher: inPath,
event: 'unlink',
path: actionPath,
stats
});
});
watchedPath[inPath].on('unlinkDir', (actionPath, stats) => {
self.postMessage({
watcher: inPath,
event: 'unlinkDir',
path: actionPath,
stats
});
});
}
const unwatch = function(inPath) {
if (!watchedPath[inPath]) {
return;
}
watchedPath[inPath].close();
delete watchedPath[inPath];
}
self.addEventListener('message', function(event) {
if (event.data.func === 'watch') {
watch(...event.data.args);
} else if (event.data.func === 'unwatch') {
unwatch(...event.data.args);
}
});

View File

@@ -0,0 +1,92 @@
importScripts('../common/serial-worker.js');
const lodash_fp = require('lodash/fp');
const child_process = require('node:child_process');
const serialport = require('serialport');
const {
SerialPort,
ReadlineParser,
ByteLengthParser
} = serialport;
const portsOperator = {};
class NodeSerialWorker extends SerialWorker {
#serialport_ = null;
#parserBytes_ = null;
constructor(port) {
super(port);
}
#addEventsListener_() {
this.#parserBytes_.on('data', (buffer) => {
this.onBuffer(buffer);
});
this.#serialport_.on('error', (error) => {
this.onError(error);
this.onClose(1);
});
this.#serialport_.on('open', () => {
this.onOpen();
});
this.#serialport_.on('close', () => {
this.onClose(1);
});
}
open() {
super.open();
this.#serialport_ = new SerialPort({
path: this.getPortName(),
baudRate: this.getBaudRate() - 0, // 波特率
dataBits: 8, // 数据位
parity: 'none', // 奇偶校验
stopBits: 1, // 停止位
flowControl: false,
autoOpen: false // 不自动打开
}, false);
this.#parserBytes_ = this.#serialport_.pipe(new ByteLengthParser({ length: 1 }));
this.#serialport_.open((error) => {
if (error) {
this.onError(error);
// this.onClose(1);
}
});
this.#addEventsListener_();
}
close() {
super.close();
if (this.isOpened()) {
try {
this.#serialport_.close();
} catch (error) {
console.log(error);
}
}
}
onBuffer(buffer) {
super.onBuffer(buffer);
}
}
const create = (port) => {
if (!portsOperator[port]) {
portsOperator[port] = new NodeSerialWorker(port);
}
portsOperator[port].open();
}
self.addEventListener('message', function(event) {
console.log(event.data);
const { port, type } = event.data;
if (type === 'open') {
create(port);
} else if (type === 'close') {
portsOperator[port] && portsOperator[port].close();
}
});

View File

@@ -0,0 +1,132 @@
importScripts('../../../web-modules/workerpool.min.js');
importScripts('../../../web-modules/browserfs.min.js');
let fs = BrowserFS.fs;
const createPromise = function(func, ...args) {
return new Promise((resolve, reject) => {
func(...args, function() {
resolve([...arguments]);
});
});
}
const addFileSystemHandler = function(filesystem) {
return new Promise((resolve, reject) => {
BrowserFS.configure({
fs: "FileSystemAccess",
options: { handle: filesystem }
}, function (error) {
if (error) {
reject(error);
return;
}
fs = BrowserFS.fs;
resolve('/' + filesystem.name);
});
});
}
const rename = function(oldPath, newPath) {
return createPromise(fs.rename, oldPath, newPath);
}
const stat = function(p) {
return createPromise(fs.stat, p);
}
const open = function(p, flag, mode) {
return createPromise(fs.open, p, flag, mode);
}
const unlink = function(p) {
return createPromise(fs.unlink, p);
}
const rmdir = function(p) {
return createPromise(fs.rmdir, p);
}
const mkdir = function(p, mode) {
return createPromise(fs.mkdir, p, mode);
}
const readdir = function(p) {
return createPromise(fs.readdir, p);
}
const exists = function(p) {
return createPromise(fs.exists, p);
}
const realpath = function(p) {
return createPromise(fs.realpath, p);
}
const truncate = function(p, len) {
return createPromise(fs.truncate, p, len);
}
const readFile = function(fname, encoding, flag) {
return createPromise(fs.readFile, fname, encoding);
}
const writeFile = function(fname, data, encoding, flag, mode) {
return createPromise(fs.writeFile, fname, data, encoding, flag, mode);
}
const appendFile = function(fname, data, encoding, flag, mode) {
return createPromise(fs.appendFile, fname, data, encoding, flag, mode);
}
const chmod = function(p, mode) {
return createPromise(fs.chmod, p, mode);
}
const chown = function(p, new_uid, new_gid) {
return createPromise(fs.chown, p, new_uid, new_gid);
}
const utimes = function(p, atime, mtime) {
return createPromise(fs.utimes, p, atime, mtime);
}
const link = function(srcpath, dstpath) {
return createPromise(fs.link, srcpath, dstpath);
}
const symlink = function(srcpath, dstpath, type) {
return createPromise(fs.symlink, srcpath, dstpath, type);
}
const readlink = function(p) {
return createPromise(fs.readlink, p);
}
const syncClose = function(method, fd) {
return fs.syncClose(method, fd);
}
workerpool.worker({
addFileSystemHandler,
rename,
stat,
open,
unlink,
rmdir,
mkdir,
readdir,
exists,
realpath,
truncate,
readFile,
writeFile,
appendFile,
chmod,
chown,
utimes,
link,
symlink,
readlink,
syncClose
});

View File

@@ -0,0 +1,123 @@
// importScripts('../../web-modules/workerpool.min.js');
const workerpool = require('../../web-modules/workerpool.min.js');
const encoder = new TextEncoder();
const decoder = new TextDecoder('utf-8');
class SerialWorker {
constructor(serial) {
this.serial = serial;
this.receiveBuffer = [];
this.receiveStr = '';
this.bufferLength = 0;
const test = setInterval(() => {
const message = generateRandomString(5);
this.onData(encoder.encode(message));
}, 1000);
setTimeout(() => {
clearInterval(test);
}, 120 * 1000);
}
onOpen() {
}
onData(data) {
/* UTF-8编码方式
* ------------------------------------------------------------
* |1字节 0xxxxxxx |
* |2字节 110xxxxx 10xxxxxx |
* |3字节 1110xxxx 10xxxxxx 10xxxxxx |
* |4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
* |5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
* |6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx|
* ------------------------------------------------------------
*/
for (let i in data) {
if ((data[i] & 0x80) === 0x00) {
// 1字节
this.receiveBuffer = [];
this.bufferLength = 0;
this.receiveStr += String.fromCharCode(data[i]);
} else if ((data[i] & 0xc0) === 0x80) {
// 2字节以上的中间字节10xxxxxx
// 如果没有起始头,则丢弃这个字节
if (!this.receiveBuffer.length) {
return;
}
// 如果不是2字节及以上的起始头则丢弃这个字节
if (this.bufferLength < 2) {
return;
}
this.receiveBuffer.push(data[i]);
if (this.bufferLength === this.receiveBuffer.length) {
this.receiveStr += decoder.decode(new Uint8Array(this.receiveBuffer));
this.receiveBuffer = [];
}
} else {
// 2字节以上的起始头
if (this.receiveBuffer) {
this.receiveBuffer = [];
}
this.bufferLength = this.#getBufferLength(data[i]);
this.receiveBuffer.push(data[i]);
}
}
}
onError() {
}
onClose() {
}
#getBufferLength(data) {
let len = 2;
if ((data & 0xFC) === 0xFC) {
len = 6;
} else if ((data & 0xF8) === 0xF8) {
len = 5;
} else if ((data & 0xF0) === 0xF0) {
len = 4;
} else if ((data & 0xE0) === 0xE0) {
len = 3;
} else if ((data & 0xC0) === 0xC0) {
len = 2;
}
return len;
}
}
const createSerialWork = function(serial) {
return new Promise((resolve, reject) => {
console.log(serial)
const serialWork = new SerialWorker(serial);
const test = setInterval(() => {
const data = serialWork.receiveStr;
serialWork.receiveStr = '';
workerpool.workerEmit({
status: 'data',
data: data
});
}, 5000);
setTimeout(() => {
workerpool.workerEmit({
status: 'close'
});
resolve();
}, 120 * 1000);
});
}
function generateRandomString() {
return '1234';
}
workerpool.worker({
createSerialWork,
generateRandomString
});