diff --git a/.gitignore b/.gitignore index 24e54fe..0ece01a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ yarn.lock dist /temp /arduino-cli -/certs +/bundle.cjs +/nw_cache diff --git a/cert/server.crt b/cert/server.crt new file mode 100644 index 0000000..3caa820 --- /dev/null +++ b/cert/server.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEXjCCAsagAwIBAgIQawifoA3zcQJDuoDTSaOE7DANBgkqhkiG9w0BAQsFADCB +hTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMS0wKwYDVQQLDCRERVNL +VE9QLVZQMU4zNzJcVXNlckBERVNLVE9QLVZQMU4zNzIxNDAyBgNVBAMMK21rY2Vy +dCBERVNLVE9QLVZQMU4zNzJcVXNlckBERVNLVE9QLVZQMU4zNzIwHhcNMjUwNTIy +MTAzNDM4WhcNMjcwODIyMTAzNDM4WjBYMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxv +cG1lbnQgY2VydGlmaWNhdGUxLTArBgNVBAsMJERFU0tUT1AtVlAxTjM3MlxVc2Vy +QERFU0tUT1AtVlAxTjM3MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +APJR4a5Xjf7MTkUocnqH2HqvhArI7hV7XZDbKPBJSlcyQUGKFRBXA7vrHg7YlVCZ +4vKHieUKNNNaPLUUVRGzjV2W6JFCmtYyoLBSijIxjEcT9iNHT8ndF3vx+ExfQmRB +qYvmGWCvnZ5NpF807ZIbabSmF7ZLrl6atp437SZ3a+xTCsGIkJf9JQvIfj5Un9tR +ed6h/P0mOJGlxzq28yljUTpgolU2iCLnE4zlnNttkm1o+X0CnhtqK2oO0h0x7Nlz +UkMvl4Y0CiUZpqG0r3Fy8JRrM7ZXf4EXTzT2uTQVI9+Hh4T+lBqCJ4QZXqJWrQ3a +EqQ1+3NWRfWe/41Oq+rkKSkCAwEAAaN2MHQwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud +JQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFIb2OJENGB0jIgBAczrFu8nddW/m +MCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcErBhRrIcEqf4ojYcEwKjMAYcEfwAAATAN +BgkqhkiG9w0BAQsFAAOCAYEAe+oeVFZfEtz7dOSpqELA937hN4buhIGgB+gLZV1O +3HR5fh22lVl3CldcxdGoGWcpWurrd37DVBtM04OHOzS1R6cMeXlksRe6hPBRT0F2 +D/9dtr2n8vIEEjRv2C6heuU8uSHHzgsD5PSSRdbCJ5UkoEMqVhbH2G5y7SBLc3uY +GnTb+BLA2+CP5IJIScXi0CGh/NN+fLEm8zYmxfeR5aP8O40DS0NobyM+wiv0UUsw +d0CK6GS/0iOFB05f/pGINiFRsgN5l1O0FXnWCt043XO10yqOG2yw6rB1NsvzsAuG +D2wl8BcAres9qT87Ac80h1lXDJ0gZIJxNUSJBPJxJ9c8U9NVrXMXMMBkYrXFbdQH +J7cQ8/yQjkz4aqHEtt1Z+9bdx/1WEKsgoXtyZEYiGE97rD9kZ+7qJHFkDAKI3wS2 +eD14gFISoPt/X3eV+rbfrdcyUrIqesTXT7wF/L8+6XIrhRXXlq4S1zGZOf4HryH2 +QLD0nwTcDhtpz7m7wKANkXga +-----END CERTIFICATE----- diff --git a/cert/server.key b/cert/server.key new file mode 100644 index 0000000..5abcd15 --- /dev/null +++ b/cert/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDyUeGuV43+zE5F +KHJ6h9h6r4QKyO4Ve12Q2yjwSUpXMkFBihUQVwO76x4O2JVQmeLyh4nlCjTTWjy1 +FFURs41dluiRQprWMqCwUooyMYxHE/YjR0/J3Rd78fhMX0JkQamL5hlgr52eTaRf +NO2SG2m0phe2S65emraeN+0md2vsUwrBiJCX/SULyH4+VJ/bUXneofz9JjiRpcc6 +tvMpY1E6YKJVNogi5xOM5ZzbbZJtaPl9Ap4baitqDtIdMezZc1JDL5eGNAolGaah +tK9xcvCUazO2V3+BF0809rk0FSPfh4eE/pQagieEGV6iVq0N2hKkNftzVkX1nv+N +Tqvq5CkpAgMBAAECggEBALgdVM9FwSL/Et1jLRBClU4qe7ZCEvwJfv8oNgPUfAKi +sYhdpUGEC9dFftIi59iVBCXoq/J1/cs0vfmMGFLZzSh2GAD+zWzAjO1L2arnkMEU +vqjxbwNe1JAdOt60ZlqMtYkRbOjUpnr4XVLlgTjJUVir9kpRWIyTGvw+XBclF8A3 +oe856SzNp7sErkNDULrv8EYAjiynlg1NB1s4Ek5t9pxlQcx8G6qRWjVhdvNAarRy +32mmWRkTt58e/I4ZPHHWG9NUHVRqeNK45Ak4dw0dth4j/BShhq+VWCoQmLESHtu7 +PU30u+57tC2DuvXUsmWFqGwVkU4g942QHYQicMeCLw0CgYEA+pWBdxtSH2ItwwLv +IyNLCQjzz4Wq/0X8l5K+w98vb53buzSEHWoC/JQkChkAxYppe1dUQwLLX07FgYTp +dAhFuHuJkSil8i6kwLoArNzdybUgQORKps2oi820ANRzFljBBqkcCGGYpbzGu3fd +eEhiUeGALyzzIwt7wtGxfu7aumsCgYEA946mW5pMBcRbQhfT1dfhiCj6HZW47wXh +b7u20tCQOFGpHEcLcwWHaFNUBTTbvrqXYFjI3VKY4adXdvj6Qgc71Tv0mQRiUjxg +dAeV5wwEKCSRelNtbNcsXMe6oxn7jzNdtRn/zzP3OZ9Yo8O4cgQSBthYBx8NLI55 +Uv4RWV9zN7sCgYA/mtFY5UNsGeSZulXu6ldyfKY+R6SG1UHvS11GpJEK2NvcYdEj +EjSd3hBjy8LpYV+y4hDOTZhHodv6Kz2CqVLhJ+JcSSAOIA7LqKrhNdLKD0KXlhro +ygz9J4KIL2TjCDY+tZAbBILVltwu25cIn/7s37tEvjkc7R5F7ioKmSBF7wKBgQDe +nnp9j9DjssN6OSE3ga6AGpFpv3WSBRDIwN7Uz9eRveW81yq1ofg12hGJqRIff36X +lt/zH875xdnC1H2AmS62P/djD203lLIMRbIJF2Y5j0D/5zxVD18GhFoTSE9PZJrV +PG8trwaY2/IDOwOIDJ8FZtIqfUMEmY8DEhUZ8NsU9wKBgQCwfDybwBJMQ6uueNW6 +MfMlYaiQkoc5G5JjJgLRdXspsVUTsVtKmW3OWMxYjHoX2il1o+SvhNyl6pT6ydK4 +X674hLtkCYiXHQvBimNTu5S0/8N/SG5k0NDKEDYHdMLT/s/mMzNofte1Tr8wGXzy +choMXR4QUuGbI/CPicSC+bD9Fg== +-----END PRIVATE KEY----- diff --git a/config.json b/config.json index f0b20ee..1f9011d 100644 --- a/config.json +++ b/config.json @@ -23,14 +23,15 @@ }, "client": { "path": "./mixly", - "port": 4000 + "port": 7000, + "protocol": "https:" }, "server": { "path": { "temp": "./temp" }, "mode": "all", - "protocol": "wss", - "port": 4000 + "protocol": "wss:", + "port": 7000 } } \ No newline at end of file diff --git a/config.json.nw b/config.json.nw new file mode 100644 index 0000000..f61842b --- /dev/null +++ b/config.json.nw @@ -0,0 +1,37 @@ +{ + "debug": true, + "arduino": { + "path": { + "folder": "./arduino-cli", + "cli": "./arduino-cli/arduino-cli.exe", + "libraries": [ + "./arduino-libs/arduino-cli/libraries" + ], + "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" + } + }, + "client": { + "path": "./mixly", + "port": 7000, + "protocol": "http:" + }, + "server": { + "path": { + "temp": "./temp" + }, + "mode": "compiler", + "protocol": "ws:", + "port": 7000 + } +} \ No newline at end of file diff --git a/mixly b/mixly index 13463ce..c3e7039 160000 --- a/mixly +++ b/mixly @@ -1 +1 @@ -Subproject commit 13463ce183528c636adc06d4153bc22ecdcd4d4c +Subproject commit c3e7039ffafd1bba8cf5eb3c2caafcca5b3eefa3 diff --git a/package.json b/package.json index 3d283a4..9680496 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "type": "module", "version": "1.0.0", "description": "", - "main": "src/index.js", + "main": "./src/index.js", "scripts": { "cert:generate": "node ./scripts/cert-generate.js", "arduino:install": "node ./scripts/arduino-install.js", diff --git a/package.json.nw b/package.json.nw new file mode 100644 index 0000000..1323326 --- /dev/null +++ b/package.json.nw @@ -0,0 +1,72 @@ +{ + "name": "mixly3-server", + "version": "1.0.0", + "description": "", + "node-main": "./bundle.cjs", + "main": "http://127.0.0.1:7000/mixly", + "node-remote": "http://127.0.0.1:7000/mixly", + "scripts": { + "start": "nw ./ --remote-debugging-port=9222", + "build:prod": "webpack --config=webpack.nw.cjs", + "build:nw:win:x64": "npm run build:prod && build --tasks win-x64 --mirror https://npmmirror.com/mirrors/nwjs/ .", + "build:nw:win:x86": "npm run build:prod && build --tasks win-x86 --mirror https://npmmirror.com/mirrors/nwjs/ .", + "build:nw:linux:x64": "npm run build:prod && build --tasks linux-x64 --mirror https://npmmirror.com/mirrors/nwjs/ .", + "build:nw:mac:x64": "npm run build:prod && build --tasks mac-x64 --mirror https://npmmirror.com/mirrors/nwjs/ ." + }, + "window": { + "icon": "mixly/common/media/mixly.png", + "position": "center" + }, + "keywords": [ + "NW.js", + "server" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/bnu_mixly/mixly3-server.git" + }, + "author": "Mixly Team", + "license": "MIT", + "dependencies": { + "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": "^0.0.1-security", + "fs-extra": "^11.2.0", + "fs-plus": "^3.1.1", + "http": "^0.0.1-security", + "iconv-lite": "^0.6.3", + "lodash": "^4.17.21", + "mitt": "^3.0.1", + "mustache": "^4.2.0", + "node-fetch": "^3.3.2", + "node-forge": "^1.3.1", + "path": "^0.12.7", + "serialport": "^12.0.0", + "shelljs": "^0.9.2", + "shortid": "^2.2.17", + "simple-git": "^3.27.0", + "socket.io": "^4.8.1", + "tar": "^7.4.3", + "url": "^0.11.0", + "usb": "^2.14.0" + }, + "build": { + "nwVersion": "0.72.0" + }, + "devDependencies": { + "eslint": "^8.57.1", + "eslint-webpack-plugin": "^4.0.1", + "nodemon": "^3.1.10", + "npm-run-all": "^4.1.5", + "nw": "0.72.0-sdk", + "nwjs-builder-phoenix": "^1.15.0", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "webpack-merge": "^6.0.1", + "webpack-node-externals": "^3.0.0" + } +} diff --git a/src/common/config.js b/src/common/config.js index 8542424..bf58585 100644 --- a/src/common/config.js +++ b/src/common/config.js @@ -29,9 +29,10 @@ export const MICROPYTHON = processConfig(CONFIG.micropython); export const PYTHON = processConfig(CONFIG.python); export const CURRENT_PLANTFORM = os.platform(); export const TEMP_PATH = path.resolve(process.cwd(), CONFIG.server.path.temp); -export const CLIENT_PATH = path.resolve(process.cwd(), CONFIG.client.path); export const CERTS_PATH = path.resolve(process.cwd(), 'certs'); export const CLIENT_PORT = CONFIG.client.port; +export const CLIENT_PATH = path.resolve(process.cwd(), CONFIG.client.path); +export const CLIENT_PROTOCOL = CONFIG.client.protocol; export const SERVER_PORT = CONFIG.server.protocol === 'wss' ? CLIENT_PORT : CONFIG.server.port; export const SERVER_MODE = CONFIG.server.mode; export const SERVER_PROTOCOL = CONFIG.server.protocol; \ No newline at end of file diff --git a/src/common/serial.js b/src/common/serial.js index b3580c2..5ec3a39 100644 --- a/src/common/serial.js +++ b/src/common/serial.js @@ -1,12 +1,17 @@ import { exec } from 'node:child_process'; -import { - SerialPort, - ReadlineParser, - ByteLengthParser -} from 'serialport'; import _ from 'lodash'; import EventsBase from './events-base.js'; -import { CURRENT_PLANTFORM } from './config.js'; +import { CURRENT_PLANTFORM, SERVER_MODE } from './config.js'; + + +let SerialPort, ReadlineParser, ByteLengthParser; + +if (SERVER_MODE === 'all') { + const serial = await import('serialport'); + SerialPort = serial.SerialPort; + ReadlineParser = serial.ReadlineParser; + ByteLengthParser = serial.ByteLengthParser; +} export default class Serial extends EventsBase { diff --git a/src/common/socket.js b/src/common/socket.js index a66b073..9075ddb 100644 --- a/src/common/socket.js +++ b/src/common/socket.js @@ -1,6 +1,5 @@ import { Server } from 'socket.io'; import { to } from 'await-to-js'; -import { usb } from 'usb'; import path from 'node:path'; import fsExtra from 'fs-extra'; import Serial from './serial.js'; @@ -11,7 +10,7 @@ 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'; +import { TEMP_PATH, CLIENT_PATH, SERVER_MODE } from './config.js'; export default class Socket { @@ -37,12 +36,16 @@ export default class Socket { this.#shellAmpy_.register(socket.id, new ShellAmpy()); this.#addEventsListenerForMode2_(socket); }); - usb.on('attach', (device) => { - this.#namespaceAll_.emit('serial.attachEvent', device); - }); - usb.on('detach', (device) => { - this.#namespaceAll_.emit('serial.detachEvent', device); - }); + if (SERVER_MODE === 'all') { + import('usb').then(({ usb }) => { + usb.on('attach', (device) => { + this.#namespaceAll_.emit('serial.attachEvent', device); + }); + usb.on('detach', (device) => { + this.#namespaceAll_.emit('serial.detachEvent', device); + }); + }); + } } #addEventsListenerForMode1_(socket) { diff --git a/src/common/utils.js b/src/common/utils.js index 00dbc3e..33ee478 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -2,9 +2,9 @@ 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 forge from 'node-forge'; import shell from 'shelljs'; -import _ from 'lodash'; +// import _ from 'lodash'; import { CERTS_PATH } from './config.js'; @@ -50,7 +50,7 @@ export function getCertificate() { data.cert = fsExtra.readFileSync(crtPath); data.key = fsExtra.readFileSync(keyPath); } - const cert = forge.pki.certificateFromPem(data.cert); + /* const cert = forge.pki.certificateFromPem(data.cert); const now = new Date(); const notBefore = cert.validity.notBefore; const notAfter = cert.validity.notAfter; @@ -73,6 +73,6 @@ export function getCertificate() { } } else { data = generateCertificate(); - } + } */ return data; } \ No newline at end of file diff --git a/src/index.js b/src/index.js index 22d79d0..502eedd 100644 --- a/src/index.js +++ b/src/index.js @@ -5,21 +5,43 @@ import fsExtra from 'fs-extra'; import express from 'express'; import Socket from './common/socket.js'; import { getCertificate } from './common/utils.js'; -import { CLIENT_PATH, CLIENT_PORT, SERVER_PORT, SERVER_MODE, SERVER_PROTOCOL } from './common/config.js'; +import { + CLIENT_PATH, CLIENT_PORT, CLIENT_PROTOCOL, + SERVER_MODE, SERVER_PORT, SERVER_PROTOCOL +} from './common/config.js'; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const app = express(); + if (CLIENT_PATH) { - app.use(express.static(CLIENT_PATH)); + if (typeof nw === 'object') { + app.use(express.static(path.resolve(CLIENT_PATH, '../'))); + } else { + app.use(express.static(CLIENT_PATH)); + } } -const httpsServer = https.createServer(getCertificate(), app); -let httpServer = null; -if (CLIENT_PORT !== SERVER_PORT) { - httpServer = http.createServer() + +let staticServer = null; +let socketServer = null; + +if (CLIENT_PROTOCOL === 'https:') { + staticServer = https.createServer(getCertificate(), app); +} else { + staticServer = http.createServer(app); } + if (SERVER_MODE !== 'static') { - const socket = new Socket(httpServer ? httpServer : httpsServer, { + if (CLIENT_PORT === SERVER_PORT) { + socketServer = staticServer; + } else { + if (SERVER_PROTOCOL === 'wss:') { + socketServer = https.createServer(getCertificate()); + } else { + socketServer = http.createServer(); + } + } + const socket = new Socket(socketServer, { path: '/mixly-socket/', maxHttpBufferSize: 1e8, cors: { @@ -52,11 +74,11 @@ const mixlyConfig = fsExtra.readJSONSync(mixlyConfigPath); if (SERVER_MODE === 'compiler') { mixlyConfig['webCompiler']['enabled'] = true; - mixlyConfig['webCompiler']['url'] = `${SERVER_PROTOCOL}://default:${SERVER_PORT}`; + mixlyConfig['webCompiler']['url'] = `${SERVER_PROTOCOL}//default:${SERVER_PORT}`; mixlyConfig['webSocket']['enabled'] = false; } else if (SERVER_MODE === 'all') { mixlyConfig['webCompiler']['enabled'] = false; - mixlyConfig['webSocket']['url'] = `${SERVER_PROTOCOL}://default:${SERVER_PORT}`; + mixlyConfig['webSocket']['url'] = `${SERVER_PROTOCOL}//default:${SERVER_PORT}`; mixlyConfig['webSocket']['enabled'] = true; } else { mixlyConfig['webCompiler']['enabled'] = false; @@ -67,13 +89,17 @@ fsExtra.writeJSONSync(mixlyConfigPath, mixlyConfig, { spaces: ' ' }); -httpsServer.listen(CLIENT_PORT); -if (httpServer) { - httpServer.listen(SERVER_PORT); +if (CLIENT_PORT === SERVER_PORT) { + staticServer?.listen(CLIENT_PORT); +} else { + staticServer?.listen(CLIENT_PORT); + socketServer?.listen(SERVER_PORT); } + if (CLIENT_PATH) { - console.log(`Static服务器正在运行: https://127.0.0.1:${CLIENT_PORT}`); + console.log(`Static服务器正在运行: ${CLIENT_PROTOCOL}//127.0.0.1:${CLIENT_PORT}`); } + if (SERVER_MODE !== 'static') { - console.log(`Socket.io服务器正在运行: ${SERVER_PROTOCOL}://127.0.0.1:${SERVER_PORT}`); + console.log(`Socket.io服务器正在运行: ${SERVER_PROTOCOL}//127.0.0.1:${SERVER_PORT}`); } \ No newline at end of file diff --git a/webpack.common.cjs b/webpack.common.cjs index 10ff6c1..007a2e4 100644 --- a/webpack.common.cjs +++ b/webpack.common.cjs @@ -9,5 +9,5 @@ module.exports = { path: path.resolve(__dirname, 'dist'), filename: 'bundle.cjs' }, - externals: [nodeExternals()], + externals: [nodeExternals()] }; \ No newline at end of file diff --git a/webpack.nw.cjs b/webpack.nw.cjs new file mode 100644 index 0000000..f98b405 --- /dev/null +++ b/webpack.nw.cjs @@ -0,0 +1,11 @@ +const common = require('./webpack.common.cjs'); +const { merge } = require('webpack-merge'); + + +module.exports = merge(common, { + output: { + path: __dirname, + filename: 'bundle.cjs' + }, + mode: 'production' +});