init repository

This commit is contained in:
Zhanpeng Yang 2024-09-11 19:06:44 +08:00
commit 8bc281423e
23 changed files with 6342 additions and 0 deletions

3
.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

36
.gitignore vendored Normal file
View 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
View 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不会以单词形式出现在软件封面上取而代之的是符号()。
- **日期版本号**:用于记录修改项目的当前日期,每天对项目的修改都需要更改日期版本号
## 更新类型
- 新增Features新增功能。可简写为+
- 修复🐞Fixed修复 bug。
- 变更🔄Changed对于某些已存在功能所发生的逻辑变化。
- 优化🚀Refactored性能或结构上的优化并未带来功能的逻辑变化。
- 即将删除❎Deprecated不建议使用 / 在以后的版本中即将删除的功能。
- 删除❌Removed已删除的功能。
- 更新文档 (📝Documentation)
- 更新了依赖🔗Dependency Upgrades

16
Dockerfile Normal file
View 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
View File

@ -0,0 +1,7 @@
## Getting Started
First, run the development server:
```bash
docker compose up
```

6
TODO.md Normal file
View File

@ -0,0 +1,6 @@
## 紧急
- [ ] 加入docker环境启动
## 非紧急
- [ ] 手动输入信息,并提取光谱回传到云服务器
- [ ] 界面美化

8
docker-compose.yaml Normal file
View File

@ -0,0 +1,8 @@
services:
server:
build: ./
container_name: sccs_loca_server
ports:
- 3000:3000
volumes:
- ./:/app

7
jsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

4
next.config.mjs Normal file
View File

@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

17
nodemon.json Normal file
View 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

File diff suppressed because it is too large Load Diff

30
package.json Normal file
View 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
View File

@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

54
server.js Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

BIN
src/app/fonts/GeistVF.woff Normal file

Binary file not shown.

27
src/app/globals.css Normal file
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,5 @@
"use client";
import { io } from "socket.io-client";
export const socket = io();

17
tailwind.config.js Normal file
View 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: [],
};