init repository
This commit is contained in:
commit
8bc281423e
3
.eslintrc.json
Normal file
3
.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
37
CHANGELOG.md
Normal file
37
CHANGELOG.md
Normal file
@ -0,0 +1,37 @@
|
||||
# 更新日志
|
||||
|
||||
## v0.0.1.20240905_base
|
||||
|
||||
### ⭐️Features
|
||||
|
||||
- 利用NEXT.js搭建后端框架
|
||||
- 利用socket.io,融合NEXT.js提供websocket服务,实时推送识别结果。
|
||||
- fork启动子进程进行数据处理,处理结果通过websocket接口显示在前端界面
|
||||
|
||||
|
||||
# 撰写规范
|
||||
## 版本号规则
|
||||
- **主版本号**:当功能模块有较大的变动,比如增加多个模块或者整体架构发生变化。
|
||||
|
||||
- **子版本号**:当功能有一定的增加或变化,比如增加了对权限控制、增加自定义视图等功能
|
||||
|
||||
- **阶段版本号**:一般是 Bug 修复或是一些小的变动,要经常发布修订版,时间间隔不限,修复一个严重的bug即可发布一个修订版
|
||||
|
||||
- **希腊字母版本号**:此版本号用于标注当前版本的软件处于哪个开发阶段,当软件进入到另一个阶段时需要修改此版本号
|
||||
- **Base版**: 此版本表示该软件仅仅是一个假页面链接,通常包括所有的功能和页面布局,但是页面中的功能都没有做完整的实现,只是做为整体网站的一个基础架构。
|
||||
- **Alpha版**: 此版本表示该软件在此阶段主要是以实现软件功能为主,通常只在软件开发者内部交流,一般而言,该版本软件的Bug较多,需要继续修改。
|
||||
- **Beta版**: 该版本相对于α版已有了很大的改进,消除了严重的错误,但还是存在着一些缺陷,需要经过多次测试来进一步消除,此版本主要的修改对像是软件的UI。
|
||||
- **RC版**: 该版本已经相当成熟了,基本上不存在导致错误的BUG,与即将发行的正式版相差无几。
|
||||
- **Release版**: 该版本意味“最终版本”,在前面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户使用的一个版本。该版本有时也称为标准版。一般情况下,Release不会以单词形式出现在软件封面上,取而代之的是符号(R)。
|
||||
|
||||
|
||||
- **日期版本号**:用于记录修改项目的当前日期,每天对项目的修改都需要更改日期版本号
|
||||
## 更新类型
|
||||
- 新增(⭐️Features):新增功能。可简写为+
|
||||
- 修复(🐞Fixed):修复 bug。
|
||||
- 变更(🔄Changed):对于某些已存在功能所发生的逻辑变化。
|
||||
- 优化(🚀Refactored):性能或结构上的优化,并未带来功能的逻辑变化。
|
||||
- 即将删除(❎Deprecated):不建议使用 / 在以后的版本中即将删除的功能。
|
||||
- 删除(❌Removed):已删除的功能。
|
||||
- 更新文档 (📝Documentation)
|
||||
- 更新了依赖(🔗Dependency Upgrades)
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM docker.io/library/node:20.17.0-alpine3.19
|
||||
|
||||
WORKDIR /env
|
||||
COPY package.json ./
|
||||
RUN npm config set registry https://registry.npmmirror.com &&\
|
||||
npm install
|
||||
|
||||
|
||||
|
||||
WORKDIR /app
|
||||
# 指定容器创建时的默认命令。(可以被覆盖)
|
||||
CMD ln -snf /env/node_modules /app &&\
|
||||
npm run dev
|
||||
|
||||
# 声明容器运行时监听的特定网络端口。但不会真的映射到外面
|
||||
EXPOSE 3000
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
docker compose up
|
||||
```
|
6
TODO.md
Normal file
6
TODO.md
Normal file
@ -0,0 +1,6 @@
|
||||
## 紧急
|
||||
- [ ] 加入docker环境启动
|
||||
|
||||
## 非紧急
|
||||
- [ ] 手动输入信息,并提取光谱回传到云服务器
|
||||
- [ ] 界面美化
|
8
docker-compose.yaml
Normal file
8
docker-compose.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
services:
|
||||
server:
|
||||
build: ./
|
||||
container_name: sccs_loca_server
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- ./:/app
|
7
jsconfig.json
Normal file
7
jsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
4
next.config.mjs
Normal file
4
next.config.mjs
Normal file
@ -0,0 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
|
||||
export default nextConfig;
|
17
nodemon.json
Normal file
17
nodemon.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"restartable": "rs",
|
||||
"ignore": [
|
||||
".git",
|
||||
"node_modules/**/node_modules"
|
||||
],
|
||||
"verbose": true,
|
||||
"exec": "node server.js",
|
||||
"watch": [
|
||||
"./"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"RAW_DATA_DIR": "C:/tmp/"
|
||||
},
|
||||
"ext": "js,json"
|
||||
}
|
5887
package-lock.json
generated
Normal file
5887
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
package.json
Normal file
30
package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"build": "next build",
|
||||
"start": "NODE_ENV=production node server.js",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"msgpackr": "^1.11.0",
|
||||
"next": "14.2.8",
|
||||
"pako": "^2.1.0",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"remove": "^0.1.5",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"crossenv": "^0.0.2-security",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.8",
|
||||
"nodemon": "^3.1.4",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
}
|
8
postcss.config.mjs
Normal file
8
postcss.config.mjs
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
54
server.js
Normal file
54
server.js
Normal file
@ -0,0 +1,54 @@
|
||||
import { createServer } from "node:http";
|
||||
import next from "next";
|
||||
import { Server } from "socket.io";
|
||||
import {fork} from "node:child_process"
|
||||
|
||||
const dev = process.env.NODE_ENV !== "production";
|
||||
const hostname = "0.0.0.0";
|
||||
const port = 3000;
|
||||
// when using middleware `hostname` and `port` must be provided below
|
||||
const app = next({ dev, hostname, port });
|
||||
const handler = app.getRequestHandler();
|
||||
|
||||
app.prepare().then(() => {
|
||||
const httpServer = createServer(handler);
|
||||
|
||||
const io = new Server(httpServer);
|
||||
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
console.log("connected")
|
||||
socket.emit("msg","connected")
|
||||
|
||||
io.emit("msg","io.emit");
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// socket_global.emit("msg","socket_global")
|
||||
|
||||
httpServer
|
||||
.once("error", (err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
})
|
||||
.listen(port, () => {
|
||||
console.log(`> Ready on http://${hostname}:${port}`);
|
||||
});
|
||||
|
||||
|
||||
const forked = fork("./src/lib/scanner.js")
|
||||
|
||||
forked.on("message", msg => {
|
||||
console.log("received",msg)
|
||||
io.emit("msg",msg);
|
||||
|
||||
})
|
||||
|
||||
forked.send({ hello: "world" })
|
||||
|
||||
|
||||
});
|
BIN
src/app/favicon.ico
Normal file
BIN
src/app/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
src/app/fonts/GeistMonoVF.woff
Normal file
BIN
src/app/fonts/GeistMonoVF.woff
Normal file
Binary file not shown.
BIN
src/app/fonts/GeistVF.woff
Normal file
BIN
src/app/fonts/GeistVF.woff
Normal file
Binary file not shown.
27
src/app/globals.css
Normal file
27
src/app/globals.css
Normal file
@ -0,0 +1,27 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
}
|
30
src/app/layout.js
Normal file
30
src/app/layout.js
Normal file
@ -0,0 +1,30 @@
|
||||
import localFont from "next/font/local";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = localFont({
|
||||
src: "./fonts/GeistVF.woff",
|
||||
variable: "--font-geist-sans",
|
||||
weight: "100 900",
|
||||
});
|
||||
const geistMono = localFont({
|
||||
src: "./fonts/GeistMonoVF.woff",
|
||||
variable: "--font-geist-mono",
|
||||
weight: "100 900",
|
||||
});
|
||||
|
||||
export const metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
57
src/app/page.js
Normal file
57
src/app/page.js
Normal file
@ -0,0 +1,57 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { socket } from "../lib/socket";
|
||||
|
||||
export default function Home() {
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [transport, setTransport] = useState("N/A");
|
||||
|
||||
const [msg, setMsg] = useState("N/A");
|
||||
|
||||
useEffect(() => {
|
||||
if (socket.connected) {
|
||||
onConnect();
|
||||
}
|
||||
|
||||
function onConnect() {
|
||||
setIsConnected(true);
|
||||
setTransport(socket.io.engine.transport.name);
|
||||
|
||||
console.log("connected")
|
||||
|
||||
socket.io.engine.on("upgrade", (transport) => {
|
||||
setTransport(transport.name);
|
||||
});
|
||||
}
|
||||
|
||||
function onDisconnect() {
|
||||
setIsConnected(false);
|
||||
setTransport("N/A");
|
||||
}
|
||||
|
||||
socket.on("connect", onConnect);
|
||||
socket.on("disconnect", onDisconnect);
|
||||
|
||||
|
||||
socket.on("msg",(msg)=>{
|
||||
console.log("Received",msg)
|
||||
console.log(msg)
|
||||
setMsg(`Temp:${msg.temp},C:${msg.C}`)
|
||||
// socket.emit("hello",`Cilent: ${msg}`)
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.off("connect", onConnect);
|
||||
socket.off("disconnect", onDisconnect);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Status: { isConnected ? "connected" : "disconnected" }</p>
|
||||
<p>Transport: { transport }</p>
|
||||
<p>Transport: { msg }</p>
|
||||
</div>
|
||||
);
|
||||
}
|
86
src/lib/scanner.js
Normal file
86
src/lib/scanner.js
Normal file
@ -0,0 +1,86 @@
|
||||
import * as fs from "node:fs"
|
||||
import * as path from "node:path"
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { unpack, pack } from 'msgpackr';
|
||||
import * as pako from 'pako';
|
||||
|
||||
|
||||
function get_latest_file_path(raw_spectral_data_dir){
|
||||
|
||||
let files=fs.readdirSync(raw_spectral_data_dir)
|
||||
files=files.sort()
|
||||
let latest_name=files.pop()
|
||||
// console.log(latest_name,files.length)
|
||||
return path.resolve(raw_spectral_data_dir,latest_name)
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function main(){
|
||||
try {
|
||||
// process.send("child process started");
|
||||
const raw_spectral_data_dir="C:/tmp/"
|
||||
|
||||
let last_data_file=null
|
||||
let latest_data_file=null
|
||||
let fd_csv=null
|
||||
let fd_bin=null
|
||||
while(true){
|
||||
latest_data_file=get_latest_file_path(raw_spectral_data_dir)
|
||||
|
||||
if (latest_data_file!=last_data_file){
|
||||
|
||||
fd_csv=fs.openSync(latest_data_file)
|
||||
|
||||
fd_bin=fs.openSync(path.format({
|
||||
dir: path.dirname(latest_data_file),
|
||||
name: path.basename(latest_data_file,".csv"),
|
||||
ext: 'bin',
|
||||
}))
|
||||
last_data_file=latest_data_file
|
||||
}
|
||||
|
||||
let last_pointer=fs.statSync(latest_data_file).size
|
||||
|
||||
while(true){
|
||||
const stat=fs.statSync(latest_data_file)
|
||||
if(stat.size>last_pointer){
|
||||
let buffer=Buffer.alloc(stat.size-last_pointer)
|
||||
fs.readSync(fd_csv,buffer,0,stat.size-last_pointer,last_pointer)
|
||||
let info=buffer.toString().split(",")
|
||||
let timeStamp=Number(info[0])
|
||||
let start_pointer=Number(info[1])
|
||||
let length=Number(info[2])
|
||||
let spectral_buffer=Buffer.alloc(length)
|
||||
const spectral_data=fs.readSync(fd_bin,spectral_buffer,0,length,start_pointer)
|
||||
|
||||
|
||||
let upload_data={"spectral_data_bin":spectral_buffer }
|
||||
let upload_data_compressed = pako.gzip(pack(upload_data))
|
||||
|
||||
let response=await fetch("http://127.0.0.1:5000/post", {
|
||||
method: "post",
|
||||
body: upload_data_compressed
|
||||
})
|
||||
let response_data_compressed= await response.arrayBuffer()
|
||||
let response_data=unpack(pako.ungzip(response_data_compressed))
|
||||
// console.log(response_data)
|
||||
|
||||
process.send(response_data);
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}catch (err) {
|
||||
console.error(err.message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
main().then(()=>{
|
||||
// process.send("child process end");
|
||||
})
|
5
src/lib/socket.js
Normal file
5
src/lib/socket.js
Normal file
@ -0,0 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { io } from "socket.io-client";
|
||||
|
||||
export const socket = io();
|
17
tailwind.config.js
Normal file
17
tailwind.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
background: "var(--background)",
|
||||
foreground: "var(--foreground)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
Loading…
Reference in New Issue
Block a user