feat: 增加 cert:generate 和 arduino:install 脚本
This commit is contained in:
@@ -29,5 +29,5 @@ module.exports = {
|
||||
"new-parens": 2, // new时必须加小括号
|
||||
"eqeqeq": 0, // 必须使用全等
|
||||
"no-import-assign": 0
|
||||
},
|
||||
}
|
||||
};
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@ package-lock.json
|
||||
yarn.lock
|
||||
dist
|
||||
/temp
|
||||
/arduino-cli
|
||||
/certs
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "mixly"]
|
||||
path = mixly
|
||||
url = https://gitee.com/bnu_mixly/mixly3.git
|
||||
31
arduino-cli.json
Normal file
31
arduino-cli.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"board_manager": {
|
||||
"additional_urls": [
|
||||
"http://download.mixlylibs.cloud/arduino-packages/index/package_esp8266com_index.json",
|
||||
"https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json"
|
||||
]
|
||||
},
|
||||
"daemon": {
|
||||
"port": "50051"
|
||||
},
|
||||
"directories": {
|
||||
"data": "",
|
||||
"downloads": "",
|
||||
"user": ""
|
||||
},
|
||||
"library": {
|
||||
"enable_unsafe_install": false
|
||||
},
|
||||
"logging": {
|
||||
"file": "",
|
||||
"format": "text",
|
||||
"level": "info"
|
||||
},
|
||||
"metrics": {
|
||||
"addr": "9090",
|
||||
"enabled": true
|
||||
},
|
||||
"sketch": {
|
||||
"always_export_binaries": false
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEXjCCAsagAwIBAgIQC+VBZ3EzgSGCMSBQIbLy+jANBgkqhkiG9w0BAQsFADCB
|
||||
hTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMS0wKwYDVQQLDCRERVNL
|
||||
VE9QLVZQMU4zNzJcVXNlckBERVNLVE9QLVZQMU4zNzIxNDAyBgNVBAMMK21rY2Vy
|
||||
dCBERVNLVE9QLVZQMU4zNzJcVXNlckBERVNLVE9QLVZQMU4zNzIwHhcNMjQxMTI5
|
||||
MTgwODE0WhcNMjcwMzAxMTgwODE0WjBYMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxv
|
||||
cG1lbnQgY2VydGlmaWNhdGUxLTArBgNVBAsMJERFU0tUT1AtVlAxTjM3MlxVc2Vy
|
||||
QERFU0tUT1AtVlAxTjM3MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMBMqCJwWtIStsMQMjW0HuLjEZNAQiys1B5XRfd2NE/HJkv2AwKGwGT70gzG28BB
|
||||
2v7EOhfPCN7yXrzIw5BIItu76eCVnwfbd+KhyFNyfRsqHkQp3yFcAXJ+NonyoU8u
|
||||
28dP0CTxTz3n3Pn9yx8p26ePpr2D7fYbB7lyKByxEkoWHnTCCZ8wPeZ58JEba4ob
|
||||
SSuGSYOm3xdqcTBFQVCRi/1AGk9R4YozGNpnycGNqEythsIp4J7chjIVtC2WONFp
|
||||
s0YG/GuPIHIxv/2bHMQJMg3GW5oLJP53E+C7xI1tVv572STv7ZGWFopgsmDomWs5
|
||||
S/XkvdXM3xx5Yr+P9gmRGRMCAwEAAaN2MHQwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud
|
||||
JQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFIb2OJENGB0jIgBAczrFu8nddW/m
|
||||
MCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATAN
|
||||
BgkqhkiG9w0BAQsFAAOCAYEAeYZYXyR3xacF9xZGJwYS8pjm5lBA3Wfuqdl+U7J6
|
||||
u4rRs+vrAGMfDyL1BWRLcwJuDKhog8QyAFsBk/L++vxG1zeDAFRisdu5fcO3yHfl
|
||||
9nlh44sFhvRHs5ZHz/EG7vaduAkV6yu4kBfctPFvyekT3YJ/+1gujcVHrAnw16LA
|
||||
aC59e33ouWDw3+apTO7c9kiNxA3m4RTn6LLpVkSPqthe8OYm+QaoOR9eci8HJzYs
|
||||
DyEGrSBtHdIOivmlbEn7FAqnaVshFg0JnjHvSLp2Nj90JCRPVsTPSHqCwLWBT8RH
|
||||
aT4Tuotz7k8QAMa/LiOFMJdQF/kPIg3rNh37F4W7xz/C7lgfuvMCKqxLdDoBDROO
|
||||
pZPdQuPVGKna2boFp+Hd3eXHPq3UZNjbU1xmYxBg9R0CgTvSZgdCjSrqTjujkLwp
|
||||
qAhcdgxxfZ9JqAwJLmnPJ8Oq+1dJ1aI+JlDWNY4GpIHc7vYPSMT4+4RcfYvK3n2/
|
||||
jXJAGJALls4DN5T7+Zl20Bqh
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDATKgicFrSErbD
|
||||
EDI1tB7i4xGTQEIsrNQeV0X3djRPxyZL9gMChsBk+9IMxtvAQdr+xDoXzwje8l68
|
||||
yMOQSCLbu+nglZ8H23fiochTcn0bKh5EKd8hXAFyfjaJ8qFPLtvHT9Ak8U8959z5
|
||||
/csfKdunj6a9g+32Gwe5cigcsRJKFh50wgmfMD3mefCRG2uKG0krhkmDpt8XanEw
|
||||
RUFQkYv9QBpPUeGKMxjaZ8nBjahMrYbCKeCe3IYyFbQtljjRabNGBvxrjyByMb/9
|
||||
mxzECTINxluaCyT+dxPgu8SNbVb+e9kk7+2RlhaKYLJg6JlrOUv15L3VzN8ceWK/
|
||||
j/YJkRkTAgMBAAECggEAJj6YqdDCn0kNhBnygm/CPMmAM1LyVkRBI4+j4KVnnf4z
|
||||
haP10UjPdsYGbngWOFRgo46PJzELyJtXcCBVlJpkJGNpDjtzl3J0k2QtnTsF2qMz
|
||||
xca2E8Jin0yuuBzDLCZbm3YqJU7AvcUhU66/+QCwKNEPDl3ws6OIk786bwpgYs9P
|
||||
GJYtLxsXt0eoTK9shWBX4J0QP+rBe5gyR9RYQr0SGBX0L4R3bSks1RnSjLTSz0Tr
|
||||
J/mUlTwgtbVVnLJCckbjYFngSMSp4Lqiamh0u5uCIrUkmyx9fJvhSc4dpU1zOijk
|
||||
fMpepXfd03Jmt9QNbFnPC/hhaXkmao6VutKH0bgY4QKBgQDgiBAtFyawSd1HUs3U
|
||||
aHdhy7/Cf053atVqxF7IDQIBcbOBvO8jcQ7QdL+rtabHbrGAdAypIQee4CHhj4In
|
||||
LWNNk9YEqgWygByID/19dFOKAq/KdK0WwJ32bSmozjxB5KSDXrSxd7aOO+3gyzsd
|
||||
ef4mzNN+NV2Z0TZAex8/lyMcawKBgQDbQCTOAt3G6q1nSEk+43q2NrUbzCcKGQuy
|
||||
thdqyXJMkytACnUlsRyLXgXt6nIucm+fcpevy8DAya7HTb/ditu+cuIx9YcFRXff
|
||||
P56A3d2wkDB3m0UjUHrrS2+1T6Yhy/FdwTnK2sbCavZy8ztijuxvpKjPZrfxv0f/
|
||||
yhyE3kyf+QKBgQCCeS6FNTXLLTEDmC95ZbcxwhdNa3LqW89menPlZgGrWyoHkwWX
|
||||
n8QPCDi1DBq9Oyq0TTtqMIJgJTgq/ZyRLYPN+cFc9nvXDTEHM9uGwkklIoiKaiCG
|
||||
3ykroKWbrTRAyh97I1Z25ezUXCjP/uj8KP6yB0ZCybn5fyQ6dhFjf2zsvwKBgQCk
|
||||
lErMZfRqfAD8lZN95K5Zl0lt+1qWxuQ0G2IKo/rrplGB+hej2oZNy59xz1o0qWxG
|
||||
6XMZ4D3pubs8Go3a1IBNPtmynNbkyxfHem8V1vWxsxrevawxbRlIBNFu7cIMfpXJ
|
||||
ReGG96DZkgc7lH/QZO7wg07AmR+dFXQLe4Da8C/eqQKBgG9xSwti9qIaEXvJBOcs
|
||||
mNo3eWeUrLcC4MfYcMwxCNMBUUtgdiSWg2pMJSSaePzidPbJ3GJrz7v8NIHr2n6g
|
||||
4PpbeD6ixS+eynXkbWhuf3F+N1orDwO+B56VXdvLSRmu1p4OyQdV2MY83F2kT6cn
|
||||
INRTi8PwMq1JtN4RglT2Ejow
|
||||
-----END PRIVATE KEY-----
|
||||
29
config.json
Normal file
29
config.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"debug": true,
|
||||
"arduino": {
|
||||
"path": {
|
||||
"folder": "./arduino-cli",
|
||||
"cli": "./arduino-cli/arduino-cli.exe",
|
||||
"libraries": [
|
||||
"./arduino-cli/libraries"
|
||||
],
|
||||
"cache": "./arduino-cli/cache",
|
||||
"config": "./arduino-cli/arduino-cli.json"
|
||||
}
|
||||
},
|
||||
"micropython": {
|
||||
"path": {
|
||||
"ampy": "./mixly/tools/python/ampy_main.py",
|
||||
"esptool": "./mixly/tools/python/esptool_main.py"
|
||||
}
|
||||
},
|
||||
"python": {
|
||||
"path": {
|
||||
"cli": "python3"
|
||||
}
|
||||
},
|
||||
"tempPath": "./temp",
|
||||
"clientPath": "./mixly",
|
||||
"mode": "web-socket",
|
||||
"port": 4000
|
||||
}
|
||||
1
mixly
Submodule
1
mixly
Submodule
Submodule mixly added at 3b10f7742c
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"watch": [
|
||||
"dist",
|
||||
"src"
|
||||
"config.json"
|
||||
],
|
||||
"ext": "js,json",
|
||||
"exec": "node dist/bundle.js"
|
||||
"ext": "cjs,json",
|
||||
"exec": "node dist/bundle.cjs"
|
||||
}
|
||||
891
package-lock.json
generated
891
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"name": "mixly3-server",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"build:dev": "webpack --config=webpack.dev.js",
|
||||
"build:prod": "webpack --config=webpack.prod.js",
|
||||
"start-server": "nodemon --watch dist --exec node dist/bundle.js",
|
||||
"watch": "webpack --watch --config=webpack.dev.js",
|
||||
"cert:generate": "node ./scripts/cert-generate.js",
|
||||
"arduino:install": "node ./scripts/arduino-install.js",
|
||||
"build:dev": "webpack --config=webpack.dev.cjs",
|
||||
"build:prod": "webpack --config=webpack.prod.cjs",
|
||||
"start-server": "nodemon --exec node dist/bundle.cjs",
|
||||
"watch": "webpack --watch --config=webpack.dev.cjs",
|
||||
"start": "npm-run-all --parallel watch start-server"
|
||||
},
|
||||
"repository": {
|
||||
@@ -20,6 +23,8 @@
|
||||
"await-to-js": "^3.0.0",
|
||||
"better-sse": "^0.14.1",
|
||||
"commander": "^12.1.0",
|
||||
"decompress": "^4.2.1",
|
||||
"decompress-unzip": "^4.0.1",
|
||||
"express": "^4.21.1",
|
||||
"fs-extra": "^11.2.0",
|
||||
"fs-plus": "^3.1.1",
|
||||
@@ -27,17 +32,20 @@
|
||||
"lodash": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"mustache": "^4.2.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"node-forge": "^1.3.1",
|
||||
"serialport": "^12.0.0",
|
||||
"shelljs": "^0.8.5",
|
||||
"shelljs": "^0.9.2",
|
||||
"shortid": "^2.2.17",
|
||||
"simple-git": "^3.27.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"tar": "^7.4.3",
|
||||
"usb": "^2.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.51.0",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
"nodemon": "^3.1.7",
|
||||
"nodemon": "^3.1.10",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
|
||||
99
scripts/arduino-install.js
Normal file
99
scripts/arduino-install.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import os from 'node:os';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import fsPlus from 'fs-plus';
|
||||
import fetch from 'node-fetch';
|
||||
import decompress from 'decompress';
|
||||
import decompressUnzip from 'decompress-unzip';
|
||||
import * as tar from 'tar';
|
||||
import shell from 'shelljs';
|
||||
|
||||
|
||||
const version = '0.35.2';
|
||||
|
||||
|
||||
function getPlatformTarget() {
|
||||
const platform = os.platform();
|
||||
const arch = os.arch();
|
||||
if (platform === 'win32') {
|
||||
return arch === 'x64' ? 'arduino-cli_' + version + '_Windows_64bit.zip' : null;
|
||||
}
|
||||
if (platform === 'darwin') {
|
||||
return 'arduino-cli_' + version + '_macOS_64bit.tar.gz';
|
||||
}
|
||||
if (platform === 'linux') {
|
||||
if (arch === 'x64') return 'arduino-cli_' + version + '_Linux_64bit.tar.gz';
|
||||
if (arch === 'arm64') return 'arduino-cli_' + version + '_Linux_ARM64.tar.gz';
|
||||
if (arch.startsWith('arm')) return 'arduino-cli_' + version + '_Linux_ARMv7.tar.gz';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function arduinoInstall() {
|
||||
const filename = getPlatformTarget();
|
||||
if (!filename) {
|
||||
console.error('当前系统或架构不受支持');
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/${filename}`;
|
||||
|
||||
const temp = path.resolve(process.cwd(), 'temp');
|
||||
await fsExtra.ensureDir(temp);
|
||||
const dest = path.resolve(temp, filename);
|
||||
const cliDirPath = path.resolve(process.cwd(), 'arduino-cli');
|
||||
await fsExtra.ensureDir(cliDirPath);
|
||||
let cliPath = '';
|
||||
if (os.platform() === 'win32') {
|
||||
cliPath = path.resolve(cliDirPath, 'arduino-cli.exe');
|
||||
} else {
|
||||
cliPath = path.resolve(cliDirPath, 'arduino-cli');
|
||||
}
|
||||
const configPath = path.resolve(cliDirPath, 'arduino-cli.json');
|
||||
const config = await fsExtra.readJson(path.resolve(process.cwd(), 'arduino-cli.json'));
|
||||
config.directories = {
|
||||
data: path.resolve(cliDirPath, 'Arduino15'),
|
||||
downloads: path.resolve(cliDirPath, 'staging'),
|
||||
user: path.resolve(cliDirPath, 'Arduino')
|
||||
};
|
||||
await fsExtra.writeJson(configPath, config, {
|
||||
spaces: ' '
|
||||
});
|
||||
if (!fsPlus.isFileSync(cliPath)) {
|
||||
console.log(`开始下载: ${url}`);
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) throw new Error(`下载失败: ${res.statusText}`);
|
||||
const fileStream = fs.createWriteStream(dest);
|
||||
await new Promise((resolve, reject) => {
|
||||
res.body.pipe(fileStream);
|
||||
res.body.on('error', reject);
|
||||
fileStream.on('finish', resolve);
|
||||
});
|
||||
|
||||
console.log('下载完成,开始解压...');
|
||||
if (filename.endsWith('.zip')) {
|
||||
await decompress(dest, cliDirPath, {
|
||||
plugins: [decompressUnzip()]
|
||||
});
|
||||
} else {
|
||||
await tar.x({
|
||||
file: dest,
|
||||
cwd: cliDirPath,
|
||||
strict: true
|
||||
});
|
||||
}
|
||||
fs.unlinkSync(dest);
|
||||
console.log('解压完成,arduino-cli可执行文件已准备好');
|
||||
}
|
||||
|
||||
shell.exec(`"${cliPath}" core update-index --config-file "${configPath}"`);
|
||||
console.log('\n开始下载: Arduino AVR');
|
||||
shell.exec(`"${cliPath}" core install arduino:avr@1.8.6 --config-file "${configPath}"`);
|
||||
console.log('\n开始下载: Arduino ESP8266');
|
||||
shell.exec(`"${cliPath}" core install esp8266:esp8266@3.1.1 --config-file "${configPath}"`);
|
||||
console.log('\n开始下载: Arduino ESP32');
|
||||
shell.exec(`"${cliPath}" core install esp32:esp32@2.0.15 --config-file "${configPath}"`);
|
||||
}
|
||||
|
||||
await arduinoInstall();
|
||||
32
scripts/cert-generate.js
Normal file
32
scripts/cert-generate.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import shell from 'shelljs';
|
||||
import fsExtra from 'fs-extra';
|
||||
|
||||
|
||||
export function getDefaultHosts() {
|
||||
const interfaceDict = os.networkInterfaces();
|
||||
const addresses = [];
|
||||
for (const key in interfaceDict) {
|
||||
const interfaces = interfaceDict[key];
|
||||
if (interfaces) {
|
||||
for (const item of interfaces) {
|
||||
const family = item.family;
|
||||
if (family === 'IPv4') {
|
||||
addresses.push(item.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['localhost', ...addresses];
|
||||
}
|
||||
|
||||
export function generateCertificate() {
|
||||
const certPath = path.resolve(process.cwd(), 'certs');
|
||||
fsExtra.ensureDirSync(certPath);
|
||||
shell.cd(certPath);
|
||||
shell.exec(`mkcert -key-file server.key -cert-file server.crt ${getDefaultHosts().join(' ')}`);
|
||||
console.log('new certificate generated successfully!');
|
||||
}
|
||||
|
||||
generateCertificate();
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import MString from './mstring';
|
||||
import { ARDUINO } from './config';
|
||||
import MString from './mstring.js';
|
||||
import { ARDUINO } from './config.js';
|
||||
|
||||
|
||||
const Boards = {};
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import os from 'node:os';
|
||||
import CONFIG from '../user/config.json';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
|
||||
|
||||
function processConfig(data) {
|
||||
for (let i in data.path) {
|
||||
if (data.path[i] instanceof String) {
|
||||
data.path[i] = path.resolve(process.cwd(), data.path[i]);
|
||||
} else if (data.path[i] instanceof Array) {
|
||||
for (let j in data.path[i]) {
|
||||
if (!(data.path[i][j] instanceof String)) {
|
||||
continue;
|
||||
}
|
||||
data.path[i][j] = path.resolve(process.cwd(), data.path[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
const CONFIG = fsExtra.readJSONSync(path.resolve(process.cwd(), 'config.json'));
|
||||
export const DEBUG = CONFIG.debug;
|
||||
export const ARDUINO = CONFIG.arduino;
|
||||
export const MICROPYTHON = CONFIG.micropython;
|
||||
export const PYTHON = CONFIG.python;
|
||||
export const ARDUINO = processConfig(CONFIG.arduino);
|
||||
export const MICROPYTHON = processConfig(CONFIG.micropython);
|
||||
export const PYTHON = processConfig(CONFIG.python);
|
||||
export const CURRENT_PLANTFORM = os.platform();
|
||||
export const TEMP_PATH = CONFIG.tempPath;
|
||||
export const CLIENT_PATH = CONFIG.clientPath;
|
||||
export const TEMP_PATH = path.resolve(process.cwd(), CONFIG.tempPath);
|
||||
export const CLIENT_PATH = path.resolve(process.cwd(), CONFIG.clientPath);
|
||||
export const CERTS_PATH = path.resolve(process.cwd(), 'certs');
|
||||
export const PORT = CONFIG.port;
|
||||
export const MODE = CONFIG.mode;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DEBUG } from './config';
|
||||
import { DEBUG } from './config.js';
|
||||
|
||||
const Debug = {};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Events from './events';
|
||||
import Events from './events.js';
|
||||
|
||||
|
||||
export default class EventsBase {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// import mitt from 'mitt';
|
||||
import _ from 'lodash';
|
||||
import shortid from 'shortid';
|
||||
import Debug from './debug';
|
||||
import Registry from './registry';
|
||||
import Debug from './debug.js';
|
||||
import Registry from './registry.js';
|
||||
|
||||
|
||||
export default class Events {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Debug from './debug';
|
||||
import Debug from './debug.js';
|
||||
|
||||
|
||||
export default class Registry {
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
ByteLengthParser
|
||||
} from 'serialport';
|
||||
import _ from 'lodash';
|
||||
import EventsBase from './events-base';
|
||||
import { CURRENT_PLANTFORM } from './config';
|
||||
import EventsBase from './events-base.js';
|
||||
import { CURRENT_PLANTFORM } from './config.js';
|
||||
|
||||
|
||||
export default class Serial extends EventsBase {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mustache from 'mustache';
|
||||
import Shell from './shell';
|
||||
import { MICROPYTHON, PYTHON } from './config';
|
||||
import Shell from './shell.js';
|
||||
import { MICROPYTHON, PYTHON } from './config.js';
|
||||
|
||||
|
||||
export default class ShellAmpy extends Shell {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import Shell from './shell';
|
||||
import { ARDUINO } from './config';
|
||||
import Shell from './shell.js';
|
||||
import { ARDUINO } from './config.js';
|
||||
|
||||
|
||||
export default class ShellArduino extends Shell {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from 'node:path';
|
||||
import Shell from './shell';
|
||||
import MString from './mstring';
|
||||
import { MICROPYTHON, PYTHON, CLIENT_PATH } from './config';
|
||||
import Shell from './shell.js';
|
||||
import MString from './mstring.js';
|
||||
import { MICROPYTHON, PYTHON, CLIENT_PATH } from './config.js';
|
||||
|
||||
|
||||
export default class ShellMicroPython extends Shell {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { execFile, exec } from 'node:child_process';
|
||||
import EventsBase from './events-base';
|
||||
import { CURRENT_PLANTFORM } from './config';
|
||||
import EventsBase from './events-base.js';
|
||||
import { CURRENT_PLANTFORM } from './config.js';
|
||||
|
||||
|
||||
export default class Shell extends EventsBase {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Server } from 'socket.io';
|
||||
import to from 'await-to-js';
|
||||
import { to } from 'await-to-js';
|
||||
import { usb } from 'usb';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import Serial from './serial';
|
||||
import Debug from './debug';
|
||||
import Registry from './registry';
|
||||
import ShellArduino from './shell-arduino';
|
||||
import ShellMicroPython from './shell-micropython';
|
||||
import ShellAmpy from './shell-ampy';
|
||||
import MString from './mstring';
|
||||
import Boards from './boards';
|
||||
import { TEMP_PATH, CLIENT_PATH } from './config';
|
||||
import Serial from './serial.js';
|
||||
import Debug from './debug.js';
|
||||
import Registry from './registry.js';
|
||||
import ShellArduino from './shell-arduino.js';
|
||||
import ShellMicroPython from './shell-micropython.js';
|
||||
import ShellAmpy from './shell-ampy.js';
|
||||
import MString from './mstring.js';
|
||||
import Boards from './boards.js';
|
||||
import { TEMP_PATH, CLIENT_PATH } from './config.js';
|
||||
|
||||
|
||||
export default class Socket {
|
||||
@@ -213,7 +213,6 @@ export default class Socket {
|
||||
});
|
||||
|
||||
socket.on('arduino.compile', async (config, callback) => {
|
||||
console.log(config)
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path = config?.path ?? {};
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
|
||||
76
src/common/utils.js
Normal file
76
src/common/utils.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import fsPlus from 'fs-plus';
|
||||
import forge from 'node-forge';
|
||||
import shell from 'shelljs';
|
||||
import _ from 'lodash';
|
||||
import { CERTS_PATH } from './config.js';
|
||||
|
||||
|
||||
export function getDefaultHosts() {
|
||||
const interfaceDict = os.networkInterfaces();
|
||||
const addresses = [];
|
||||
for (const key in interfaceDict) {
|
||||
const interfaces = interfaceDict[key];
|
||||
if (interfaces) {
|
||||
for (const item of interfaces) {
|
||||
const family = item.family;
|
||||
if (family === 'IPv4') {
|
||||
addresses.push(item.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['localhost', ...addresses];
|
||||
}
|
||||
|
||||
function generateCertificate() {
|
||||
fsExtra.ensureDirSync(CERTS_PATH);
|
||||
shell.cd(CERTS_PATH);
|
||||
shell.exec(`mkcert -key-file server.key -cert-file server.crt ${getDefaultHosts().join(' ')}`);
|
||||
console.log('new certificate generated successfully!');
|
||||
const certPem = fsExtra.readFileSync(path.resolve(CERTS_PATH, 'server.crt'));
|
||||
const keyPem = fsExtra.readFileSync(path.resolve(CERTS_PATH, 'server.key'));
|
||||
return {
|
||||
key: keyPem,
|
||||
cert: certPem
|
||||
};
|
||||
}
|
||||
|
||||
export function getCertificate() {
|
||||
const crtPath = path.resolve(CERTS_PATH, 'server.crt');
|
||||
const keyPath = path.resolve(CERTS_PATH, 'server.key');
|
||||
let data = {};
|
||||
if (!fsPlus.isFileSync(crtPath) || !fsPlus.isFileSync(keyPath)) {
|
||||
data = generateCertificate();
|
||||
} else {
|
||||
data.cert = fsExtra.readFileSync(crtPath);
|
||||
data.key = fsExtra.readFileSync(keyPath);
|
||||
}
|
||||
const cert = forge.pki.certificateFromPem(data.cert);
|
||||
const now = new Date();
|
||||
const notBefore = cert.validity.notBefore;
|
||||
const notAfter = cert.validity.notAfter;
|
||||
if (now < notBefore || now > notAfter) {
|
||||
data = generateCertificate();
|
||||
}
|
||||
const sanExt = cert.extensions.find(ext => ext.name === 'subjectAltName');
|
||||
if (sanExt && sanExt.altNames) {
|
||||
const hosts = [];
|
||||
for (let item of sanExt.altNames) {
|
||||
if (item.type === 2) {
|
||||
hosts.push(item.value);
|
||||
} else if (item.type === 7) {
|
||||
hosts.push(item.ip);
|
||||
}
|
||||
}
|
||||
const currentHosts = getDefaultHosts();
|
||||
if (_.xor(currentHosts, hosts).length !== 0) {
|
||||
data = generateCertificate();
|
||||
}
|
||||
} else {
|
||||
data = generateCertificate();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
62
src/index.js
62
src/index.js
@@ -1,18 +1,20 @@
|
||||
import express from 'express';
|
||||
import path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { createServer } from 'node:https';
|
||||
import Socket from './common/socket';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import express from 'express';
|
||||
import Socket from './common/socket.js';
|
||||
import { getCertificate } from './common/utils.js';
|
||||
import { CLIENT_PATH, PORT, MODE } from './common/config.js';
|
||||
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
const __dirname = path.dirname(url.fileURLToPath(new URL(import.meta.url)));
|
||||
const app = express();
|
||||
const httpsServer = createServer({
|
||||
key: readFileSync(path.resolve(__dirname, '../certs/server.key')),
|
||||
cert: readFileSync(path.resolve(__dirname, '../certs/server.crt'))
|
||||
}, app);
|
||||
if (CLIENT_PATH) {
|
||||
app.use(express.static(CLIENT_PATH));
|
||||
}
|
||||
const httpsServer = createServer(getCertificate(), app);
|
||||
|
||||
if (MODE !== 'static') {
|
||||
const socket = new Socket(httpsServer, {
|
||||
path: '/mixly-socket/',
|
||||
maxHttpBufferSize: 1e8,
|
||||
@@ -26,19 +28,45 @@ const socket = new Socket(httpsServer, {
|
||||
|
||||
const io = socket.getIO();
|
||||
|
||||
function close() {
|
||||
process.on('SIGINT', () => {
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
close();
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
close();
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const mixlyConfigPath = path.resolve(CLIENT_PATH, 'sw-config.json');
|
||||
const mixlyConfig = fsExtra.readJSONSync(mixlyConfigPath);
|
||||
|
||||
if (MODE === 'web-compiler') {
|
||||
mixlyConfig['webCompiler']['enabled'] = true;
|
||||
mixlyConfig['webCompiler']['url'] = `wss://127.0.0.1:${PORT}`;
|
||||
mixlyConfig['webSocket']['enabled'] = false;
|
||||
} else if (MODE === 'web-socket') {
|
||||
mixlyConfig['webCompiler']['enabled'] = false;
|
||||
mixlyConfig['webSocket']['url'] = `wss://127.0.0.1:${PORT}`;
|
||||
mixlyConfig['webSocket']['enabled'] = true;
|
||||
} else {
|
||||
mixlyConfig['webCompiler']['enabled'] = false;
|
||||
mixlyConfig['webSocket']['enabled'] = false;
|
||||
}
|
||||
|
||||
fsExtra.writeJSONSync(mixlyConfigPath, mixlyConfig, {
|
||||
spaces: ' '
|
||||
});
|
||||
|
||||
httpsServer.listen(4000);
|
||||
httpsServer.listen(PORT);
|
||||
if (CLIENT_PATH) {
|
||||
console.log(`Static服务器正在运行: https://127.0.0.1:${PORT}`);
|
||||
}
|
||||
if (MODE !== 'static') {
|
||||
console.log(`Socket.io服务器正在运行: wss://127.0.0.1:${PORT}/mixly-socket`);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"debug": true,
|
||||
"arduino": {
|
||||
"path": {
|
||||
"folder": "D:/gitee/arduino-cli-win32/arduino-cli",
|
||||
"cli": "D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.exe",
|
||||
"libraries": [
|
||||
"D:/gitee/arduino-cli-win32/arduino-cli/libraries"
|
||||
],
|
||||
"cache": "D:/gitee/arduino-cli-win32/arduino-cli/cache",
|
||||
"config": "D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.json"
|
||||
}
|
||||
},
|
||||
"micropython": {
|
||||
"path": {
|
||||
"ampy": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/ampy_main.py",
|
||||
"esptool": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/esptool_main.py"
|
||||
}
|
||||
},
|
||||
"python": {
|
||||
"path": {
|
||||
"cli": "D:/gitee/mixly3.0-win32-x64/mixpyBuild/win_python3/python3.exe"
|
||||
}
|
||||
},
|
||||
"tempPath": "D:/gitee/mixly3-server/temp",
|
||||
"clientPath": "D:/gitee/mixly3.0-win32-x64/resources/app/src"
|
||||
}
|
||||
@@ -7,7 +7,7 @@ module.exports = {
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'bundle.js'
|
||||
filename: 'bundle.cjs'
|
||||
},
|
||||
externals: [nodeExternals()],
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
const common = require('./webpack.common');
|
||||
const common = require('./webpack.common.cjs');
|
||||
const { merge } = require('webpack-merge');
|
||||
const ESLintPlugin = require('eslint-webpack-plugin');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const common = require('./webpack.common');
|
||||
const common = require('./webpack.common.cjs');
|
||||
const { merge } = require('webpack-merge');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user