first commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
ui
|
2
server/.gitignore
vendored
Normal file
2
server/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.idea
|
||||
node_modules
|
79
server/app.js
Normal file
79
server/app.js
Normal file
@ -0,0 +1,79 @@
|
||||
const express = require('express')
|
||||
// 创建 express 的服务器实例
|
||||
const app = express()
|
||||
const mqtt = require('mqtt');
|
||||
// 创建 MQTT 客户端实例
|
||||
const client = mqtt.connect('mqtt://82.156.1.111:40000', {
|
||||
clientId: 'web_collector',
|
||||
username: 'xin',
|
||||
password: 'irishk'
|
||||
});
|
||||
global.MqttClient=client;
|
||||
// 引入body-parser
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({extended:false}))
|
||||
var session=require("express-session")
|
||||
app.use(
|
||||
session({
|
||||
secret: 'iris',
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
})
|
||||
)
|
||||
// write your code here...
|
||||
const userRouter = require('./router/user')
|
||||
const mqqtRouter=require('./router/mqtt_router');
|
||||
const devinfoRouter=require('./router/devinfo')
|
||||
|
||||
app.use((req, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
|
||||
res.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
next();
|
||||
});
|
||||
//const repairrouter=require('./router/task')
|
||||
app.use('/public', userRouter)
|
||||
app.use('/mqtt', mqqtRouter)
|
||||
app.use('/devinfo', devinfoRouter)
|
||||
//app.use(express.static(__dirname+"/html"))
|
||||
//app.use('/task', taskrouter)
|
||||
app.use('/', (req, res,next)=>{
|
||||
if (req.session.islogin!=true)
|
||||
{
|
||||
|
||||
// res.send("need login");
|
||||
// return;
|
||||
}
|
||||
|
||||
next()
|
||||
})
|
||||
// app.use('/task', taskrouterinside)
|
||||
// app.use('/repair', taskrouter)
|
||||
app.use('/api/home1', (req, res)=>{
|
||||
|
||||
res.send("welcome to iris");
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
// 调用 app.listen 方法,指定端口号并启动web服务器
|
||||
app.listen(1000, function () {
|
||||
console.log('api server running at http://127.0.0.1:1000')
|
||||
})
|
||||
|
||||
const schedule = require('node-schedule');
|
||||
const taskforupdate=require('./comman/frpclinet')
|
||||
|
||||
|
||||
|
||||
const scheduleCronstyle = ()=>{
|
||||
//每分钟的第30秒定时执行一次:
|
||||
schedule.scheduleJob('* 30 * * * *',()=>{
|
||||
console.log('scheduleCronstyle:' + new Date());
|
||||
taskforupdate.getfrpserver();
|
||||
});
|
||||
}
|
||||
taskforupdate.getfrpserver();
|
||||
scheduleCronstyle();
|
204
server/comman/db.js
Normal file
204
server/comman/db.js
Normal file
@ -0,0 +1,204 @@
|
||||
const mysql = require('mysql')
|
||||
|
||||
const db = mysql.createPool({
|
||||
host: '127.0.0.1',
|
||||
user: 'root',
|
||||
password: '',
|
||||
database: 'remotemqtt',
|
||||
})
|
||||
let queryacy = function( sql, values ) {
|
||||
// 返回一个 Promise
|
||||
return new Promise(( resolve, reject ) => {
|
||||
db.getConnection(function(err, connection) {
|
||||
if (err) {
|
||||
reject( err )
|
||||
} else {
|
||||
connection.query(sql, values, ( err, rows) => {
|
||||
|
||||
if ( err ) {
|
||||
reject( err )
|
||||
} else {
|
||||
resolve( rows )
|
||||
}
|
||||
// 结束会话
|
||||
//console.log(sql);
|
||||
connection.release()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// const sqlite3 = require('sqlite3').verbose()
|
||||
// //打开或者创建一个数据库
|
||||
|
||||
|
||||
// var db = new sqlite3.Database(
|
||||
// './db.sqlite3',
|
||||
// sqlite3.OPEN_READWRITE,
|
||||
// function (err) {
|
||||
// if (err) {
|
||||
// return console.log(err.message)
|
||||
// }
|
||||
|
||||
// }
|
||||
// )
|
||||
// resetpath=async function(path)
|
||||
// {
|
||||
|
||||
// db = new sqlite3.Database(
|
||||
// path,
|
||||
// sqlite3.OPEN_READWRITE,
|
||||
// function (err) {
|
||||
// if (err) {
|
||||
// return console.log(err.message)
|
||||
// }
|
||||
// console.log('connect database successfully')
|
||||
// }
|
||||
// )
|
||||
// db.run("CREATE TABLE IF NOT EXISTS remoteswitch (\
|
||||
// `AUTOID` INTEGER PRIMARY KEY AUTOINCREMENT,\
|
||||
// `id` tinytext NOT NULL,\
|
||||
// `type` tinytext NOT NULL,\
|
||||
// `tips` text NOT NULL,\
|
||||
// `other` text NOT NULL,\
|
||||
// `switch1` tinyint(1) NOT NULL,\
|
||||
// `switch2` tinyint(1) NOT NULL,\
|
||||
// `switch3` tinyint(1) NOT NULL,\
|
||||
// `switch4` tinyint(1) NOT NULL,\
|
||||
// `is4G` tinyint(1) NOT NULL,\
|
||||
// `device` tinytext DEFAULT NULL)",(err)=>{console.log(err);
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// // db.query=db.run
|
||||
// //如果不存在 remoteswitch 表则创建 并打印创建成功 如果错误则打印错误
|
||||
|
||||
// function ConvertoKeyValue(data)
|
||||
// {
|
||||
|
||||
// let fields = [];
|
||||
// let fields1 = [];
|
||||
// let fields2 = [];
|
||||
// for (let key in data) {
|
||||
// // 如果值是字符串,需要用引号包裹
|
||||
// let value = typeof data[key] === 'string' ? `'${data[key]}'` : data[key];
|
||||
// fields1.push(key);
|
||||
// fields2.push( value);
|
||||
|
||||
// }
|
||||
|
||||
// fields.push(fields1.join(","))
|
||||
// fields.push(fields2.join(","))
|
||||
// return fields
|
||||
// }
|
||||
// function ConvertoKeyEQValue(data)
|
||||
// {
|
||||
|
||||
// let fields = [];
|
||||
|
||||
// for (let key in data) {
|
||||
// // 如果值是字符串,需要用引号包裹
|
||||
// let value = typeof data[key] === 'string' ? `'${data[key]}'` : data[key];
|
||||
// fields.push(key+"="+value);
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// return fields.join(",")
|
||||
// }
|
||||
|
||||
db.query("CREATE TABLE IF NOT EXISTS remoteswitch (\
|
||||
AUTOID INT AUTO_INCREMENT PRIMARY KEY,\
|
||||
id TINYTEXT NOT NULL,\
|
||||
type TINYTEXT NOT NULL,\
|
||||
tips TEXT NOT NULL,\
|
||||
other TEXT NOT NULL,\
|
||||
switch1 TINYINT(1) NOT NULL,\
|
||||
switch2 TINYINT(1) NOT NULL,\
|
||||
switch3 TINYINT(1) NOT NULL,\
|
||||
switch4 TINYINT(1) NOT NULL,\
|
||||
is4G TINYINT(1) NOT NULL,\
|
||||
device TINYTEXT DEFAULT NULL\
|
||||
)",(err)=>{;
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
// db.all("CREATE TABLE IF NOT EXISTS remoteswitch1 (\
|
||||
// `AUTOID` INTEGER PRIMARY KEY AUTOINCREMENT,\
|
||||
// `id` tinytext NOT NULL,\
|
||||
// `type` tinytext NOT NULL,\
|
||||
// `tips` text NOT NULL,\
|
||||
// `other` text NOT NULL,\
|
||||
// `switch1` tinyint(1) NOT NULL,\
|
||||
// `switch2` tinyint(1) NOT NULL,\
|
||||
// `switch3` tinyint(1) NOT NULL,\
|
||||
// `switch4` tinyint(1) NOT NULL,\
|
||||
// `is4G` tinyint(1) NOT NULL,\
|
||||
// `device` tinytext DEFAULT NULL)",(err)=>{console.log(err);
|
||||
// })
|
||||
|
||||
|
||||
// let init=async function()
|
||||
// {
|
||||
// db.run("CREATE TABLE IF NOT EXISTS remoteswitch (\
|
||||
// `AUTOID` INTEGER PRIMARY KEY AUTOINCREMENT,\
|
||||
// `id` tinytext NOT NULL,\
|
||||
// `type` tinytext NOT NULL,\
|
||||
// `tips` text NOT NULL,\
|
||||
// `other` text NOT NULL,\
|
||||
// `switch1` tinyint(1) NOT NULL,\
|
||||
// `switch2` tinyint(1) NOT NULL,\
|
||||
// `switch3` tinyint(1) NOT NULL,\
|
||||
// `switch4` tinyint(1) NOT NULL,\
|
||||
// `is4G` tinyint(1) NOT NULL,\
|
||||
// `device` tinytext DEFAULT NULL)",(err)=>{console.log(err);
|
||||
// console.log("remoteswitch table created")})
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// let queryacy = function( sql, values ) {
|
||||
// // 返回一个 Promise
|
||||
// return new Promise(( resolve, reject ) => {
|
||||
// db.getConnection(function(err, connection) {
|
||||
// if (err) {
|
||||
// reject( err )
|
||||
// } else {
|
||||
// connection.query(sql, values, ( err, rows) => {
|
||||
|
||||
// if ( err ) {
|
||||
// reject( err )
|
||||
// } else {
|
||||
// resolve( rows )
|
||||
// }
|
||||
// // 结束会话
|
||||
// //console.log(sql);
|
||||
// connection.release()
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
// db.resetpath=resetpath
|
||||
// db.query=db.all
|
||||
db.queryacy= queryacy
|
||||
// db.init=init
|
||||
// db.ConvertoKeyValue=ConvertoKeyValue
|
||||
// db.ConvertoKeyEQValue=ConvertoKeyEQValue
|
||||
module.exports = db
|
458
server/comman/frpclinet.js
Normal file
458
server/comman/frpclinet.js
Normal file
@ -0,0 +1,458 @@
|
||||
const frpserveraxios=require('axios');
|
||||
const herader = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization':"Basic YWRtaW46bGljYWhr"
|
||||
}
|
||||
const db=require("../comman/db")
|
||||
const mywebsocket=require("./tstws")
|
||||
exports.getfrpserver=getfrpserver
|
||||
|
||||
|
||||
function createdfrpdb( )
|
||||
{
|
||||
const createTableQuery = `
|
||||
CREATE TABLE IF NOT EXISTS frpinfo (
|
||||
autoid BIGINT NOT NULL AUTO_INCREMENT,
|
||||
id VARCHAR(255) NOT NULL,
|
||||
remote_port INT NOT NULL,
|
||||
serial VARCHAR(255) NOT NULL,
|
||||
last_online DATETIME NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (autoid)
|
||||
) ENGINE = InnoDB;
|
||||
`;
|
||||
|
||||
db.query(createTableQuery, function (error, results, fields) {
|
||||
// if (error) throw error;
|
||||
// console.log('Table created or already exists.');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async function insertfrpinfo(data)
|
||||
{
|
||||
|
||||
var insertdata={id:data.nameup,serial:data.serial,name:data.name}
|
||||
|
||||
if(data.status=="online")
|
||||
{
|
||||
insertdata.remote_port=data.conf.remote_port
|
||||
insertdata.last_online=data.nowtime
|
||||
|
||||
}else
|
||||
{
|
||||
insertdata.remote_port=0
|
||||
}
|
||||
//查看看id是否存在
|
||||
let sql="SELECT * FROM `frpinfo` WHERE `id`=?"
|
||||
let result=await db.queryacy(sql,data.nameup)
|
||||
if(result.length==0)
|
||||
{
|
||||
sql="INSERT INTO `frpinfo` SET ?"
|
||||
if(insertdata.remote_port==0)
|
||||
{
|
||||
insertdata.last_online=new Date("2000-01-01").toLocaleString()
|
||||
}
|
||||
|
||||
await db.queryacy(sql,insertdata)
|
||||
//console.log("inserted")
|
||||
}else
|
||||
{
|
||||
//如果remote_port为0 删除emote_port
|
||||
if(insertdata.remote_port==0)
|
||||
{
|
||||
delete insertdata.remote_port
|
||||
}
|
||||
sql="UPDATE `frpinfo` SET ? WHERE `id`='"+data.nameup+"'"
|
||||
await db.queryacy(sql,[insertdata])
|
||||
// console.log("updated")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function createdFileInfodb( )
|
||||
{
|
||||
const createTableQuery = 'CREATE TABLE IF NOT EXISTS filebrowerinfo (\
|
||||
`autoid` INT NOT NULL AUTO_INCREMENT,\
|
||||
`name` VARCHAR(255) NOT NULL,\
|
||||
remote_port VARCHAR(255) NOT NULL,\
|
||||
`lasttime` DATETIME NOT NULL,\
|
||||
`sppercent` INT NOT NULL,\
|
||||
`sptotal` FLOAT NOT NULL,\
|
||||
mountedon VARCHAR(255) NOT NULL,\
|
||||
PRIMARY KEY (`autoid`)\
|
||||
) ENGINE = InnoDB;\
|
||||
';
|
||||
|
||||
db.query(createTableQuery, function (error, results, fields) {
|
||||
if (error) throw error;
|
||||
console.log('Table created or already exists.');
|
||||
});
|
||||
}
|
||||
// createdFileInfodb();
|
||||
// createdfrpdb();
|
||||
// getfrpserver();
|
||||
let devlistname=[]
|
||||
async function getfrpserver()
|
||||
{
|
||||
devlistname=[];
|
||||
createdFileInfodb();
|
||||
createdfrpdb();
|
||||
|
||||
sql='SELECT * FROM `filebrowerinfo` WHERE 1'
|
||||
let result=await db.queryacy(sql)
|
||||
// console.log(result)
|
||||
for (var i=0;i<result.length;i++)
|
||||
{
|
||||
devlistname.push(result[i].name)
|
||||
}
|
||||
|
||||
|
||||
var aaa=await frpserveraxios.get('http://106.75.72.40:7500/api/proxy/tcp',{headers:herader})
|
||||
nowtime=new Date()
|
||||
nowtime=nowtime.toLocaleString()
|
||||
aaa=aaa.data.proxies;
|
||||
for (var i=0;i<aaa.length;i++)
|
||||
{
|
||||
|
||||
if(aaa[i].name.endsWith('_data'))
|
||||
{
|
||||
var data=aaa[i]
|
||||
//console.log(aaa[i].name)
|
||||
//去除后缀
|
||||
var name=aaa[i].name.replace('_data','')
|
||||
//console.log(name)
|
||||
name=name.toUpperCase()
|
||||
var list=name.split('_')
|
||||
var serial=list[list.length-1]
|
||||
data.serial=serial
|
||||
data.nowtime=nowtime
|
||||
|
||||
data.nameup=name
|
||||
if (data.name=="TowerIS2_2006_data")
|
||||
{
|
||||
//将data.nameup 从devlistname中删除
|
||||
console.log("delete TowerIS2_2006_data")
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (data.conf!=null && devlistname.includes(data.nameup))
|
||||
{
|
||||
//将data.nameup 从devlistname中删除
|
||||
let index=devlistname.indexOf(data.nameup)
|
||||
devlistname.splice(index,1)
|
||||
console.log("delete "+data.nameup)
|
||||
console.log(devlistname);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(data.nameup=="NOCONFIG")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// console.log(data.name)
|
||||
//年月日时分秒
|
||||
insertfrpinfo(data);
|
||||
//插入数据库 构建object
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(name.startsWith('TowerIS2'.toUpperCase()))
|
||||
{
|
||||
//将name转换为大写
|
||||
|
||||
await dealwithIS2(data)
|
||||
}
|
||||
if(name.startsWith('TOWER_ISIF')||name.startsWith('TOWER_OSIF'))
|
||||
{
|
||||
//将name转换为大写
|
||||
|
||||
await dealwithISIF(data)
|
||||
}
|
||||
if(name.startsWith('ASD_S'))
|
||||
{
|
||||
//将name转换为大写
|
||||
|
||||
await dealwithASD(data)
|
||||
}
|
||||
// // console.log("name:"+name+"\tserial:"+i+" "+name.startsWith('TOWER_OSIF'))
|
||||
|
||||
// if(name.startsWith('TOWER_OSIF'))
|
||||
// {
|
||||
// await dealwithISIF(data)
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
console.log(devlistname)
|
||||
console.log("done")
|
||||
}
|
||||
|
||||
async function dealwithIS2(data)
|
||||
{
|
||||
// console.log(data)
|
||||
|
||||
// console.log("im IS2 my serial is:"+data.serial+"\tmy name is:"+data.nameup)
|
||||
await panduanshebei(data)
|
||||
|
||||
}
|
||||
|
||||
async function dealwithISIF(data)
|
||||
{
|
||||
// console.log("im ISIF my serial is:"+data.serial+"\tmy name is:"+data.nameup)
|
||||
|
||||
await panduanshebei(data)
|
||||
|
||||
}
|
||||
async function dealwithASD(data)
|
||||
{
|
||||
// console.log("im OSIF my serial is:"+data.serial+"\tmy name is:"+data.nameup)
|
||||
await panduanshebei(data)
|
||||
}
|
||||
|
||||
async function insettofilebrowerinfo(data)
|
||||
{
|
||||
let sql="SELECT * FROM `filebrowerinfo` WHERE `name`='"+data.name+"'"
|
||||
let result=await db.queryacy(sql)
|
||||
if(result.length==0)
|
||||
{
|
||||
sql="INSERT INTO `filebrowerinfo` SET ?"
|
||||
await db.queryacy(sql,data)
|
||||
}else
|
||||
{
|
||||
sql="UPDATE `filebrowerinfo` SET ? WHERE `name`='"+data.name+"'"
|
||||
await db.queryacy(sql,data)
|
||||
}
|
||||
}
|
||||
async function panduanshebei(data)
|
||||
{
|
||||
if(data.conf!=null)
|
||||
{
|
||||
let frpret=await getdevicelastdatatime(data.conf)
|
||||
let timelast= frpret.timelast
|
||||
|
||||
let dataforinsert=
|
||||
|
||||
{
|
||||
name:data.nameup,
|
||||
lasttime:frpret.lasttimedata,
|
||||
sppercent:frpret.space.percent,
|
||||
sptotal:frpret.space.total/1024/1024+"GB",
|
||||
remote_port:"http://106.75.72.40:"+data.conf.remote_port,
|
||||
mountedon:frpret.space.mountedon
|
||||
|
||||
}
|
||||
|
||||
if (timelast<24.5)
|
||||
{
|
||||
console.log(data.name+"\t数据正常 "+timelast+"小时内新的日期文件创建");
|
||||
await insettofilebrowerinfo(dataforinsert)
|
||||
|
||||
|
||||
|
||||
}else if(timelast==100000)
|
||||
{
|
||||
console.log("\x1b[33m"+data.name+"\t数据管理页面无法打开 请检查设备是否正常连接 \x1b[0m");
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("\x1b[31m"+data.name+"\t严重错误 数据异常"+timelast+"小时内没有新的日期文件创建 \x1b[0m");
|
||||
await insettofilebrowerinfo(dataforinsert)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
|
||||
console.log("\x1b[33m"+ data.name+"\t设备未连接 \x1b[0m")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async function getdevicelastdatatime(device)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var ret={
|
||||
timelast:100000,
|
||||
space:{
|
||||
percent:0,
|
||||
total:0,
|
||||
mountedon:" "
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(device)
|
||||
let port=device.remote_port;
|
||||
let logaddress="http://106.75.72.40:"+port+"/api/login"
|
||||
let passbody={
|
||||
"username":"admin",
|
||||
"password":"licahk"
|
||||
}
|
||||
|
||||
|
||||
let loginkey="";
|
||||
try {
|
||||
loginkey = await frpserveraxios.post(logaddress, passbody);
|
||||
// 请求成功的处理逻辑
|
||||
} catch (error) {
|
||||
loginkey= 'ECONNRESET';
|
||||
// 请求失败的处理逻辑
|
||||
if (error.code === 'ECONNRESET') {
|
||||
// 处理 socket hang up 错误
|
||||
|
||||
} else {
|
||||
// 其他类型的错误处理
|
||||
|
||||
}
|
||||
}
|
||||
if(loginkey=='ECONNRESET')
|
||||
{
|
||||
ret.timelast=100000
|
||||
return ret
|
||||
}
|
||||
|
||||
//let loginkey=await frpserveraxios.post(logaddress,passbody).catch((err)=>{console.log(err)})
|
||||
loginkey=loginkey.data;
|
||||
let dataaddress="http://106.75.72.40:"+port+"/api/resources";
|
||||
let datainfo=await frpserveraxios.get(dataaddress,{headers:{'X-Auth':loginkey}});
|
||||
datainfo=datainfo.data;
|
||||
//console.log(datainfo);
|
||||
filelist=datainfo.items;
|
||||
let diff=100000;
|
||||
filelist.forEach(file => {
|
||||
|
||||
if(file.path.toUpperCase()=="DATA")
|
||||
{
|
||||
|
||||
let filemodtime=file.modified
|
||||
//计算与当前时间的差值 modified 举例2024-07-12T05:00:40.664988617+08:00
|
||||
let now=new Date()
|
||||
let nowtime=now.getTime()
|
||||
|
||||
let filetime=new Date(filemodtime)
|
||||
ret.lasttimedata=filetime.toLocaleString();
|
||||
let filetime1=filetime.getTime()
|
||||
|
||||
diff=nowtime-filetime1
|
||||
diff=diff/1000/3600
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
ret.timelast=diff
|
||||
|
||||
if(port==13012)
|
||||
{
|
||||
ret.space.percent=0
|
||||
ret.space.total=0
|
||||
}
|
||||
|
||||
|
||||
var wsaddres="ws://106.75.72.40:"+port+"/api/command/?auth="+loginkey;
|
||||
var message="df /dev/mmcblk1p1"
|
||||
var aa=await mywebsocket.runinws(message,wsaddres)
|
||||
let commandret=aa[0].toString()
|
||||
if(commandret=="error")
|
||||
{
|
||||
ret.space.percent=0
|
||||
ret.space.total=0
|
||||
}
|
||||
else if(commandret=="Command not allowed.")
|
||||
{
|
||||
console.log("Command not allowed")
|
||||
console.log("\x1b[31m"+device.proxy_name +" need allow df in filebrowser\x1b[0m")
|
||||
}
|
||||
else
|
||||
{
|
||||
if(aa.length==1)
|
||||
{
|
||||
let cc=aa[0].toString()
|
||||
let bb=cc.split(":")
|
||||
if(bb.length==3)
|
||||
{
|
||||
if (bb[2].trim()==" No such file or directory".trim())
|
||||
{
|
||||
console.log("No such file or directory")
|
||||
ret.space.percent=0
|
||||
ret.space.total=0
|
||||
ret.space.mountedon="No SD card"
|
||||
//return ret
|
||||
}
|
||||
}
|
||||
console.log("error")
|
||||
aa.push(Buffer.from("udev aa bb"))
|
||||
}
|
||||
let data=aa[1].toString()
|
||||
let space=data.split(" ")
|
||||
//移除space中的空格
|
||||
space=space.filter(function(s) {
|
||||
return s && s.trim();
|
||||
});
|
||||
|
||||
|
||||
|
||||
if(space[0]=="udev")
|
||||
{
|
||||
message="df /home"
|
||||
aa=await mywebsocket.runinws(message,wsaddres)
|
||||
data=aa[1].toString()
|
||||
space=data.split(" ")
|
||||
space=space.filter(function(s) {
|
||||
return s && s.trim();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ret.space.percent=space[4]
|
||||
ret.space.total=space[1]
|
||||
if(ret.space.mountedon!="No SD card")
|
||||
ret.space.mountedon=space[5]
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// runinws("df /dev/mmcblk1p1","ws://106.75.72.40:30012/api/command/?auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJsb2NhbGUiOiJ6aC1jbiIsInZpZXdNb2RlIjoibGlzdCIsInNpbmdsZUNsaWNrIjpmYWxzZSwicGVybSI6eyJhZG1pbiI6dHJ1ZSwiZXhlY3V0ZSI6dHJ1ZSwiY3JlYXRlIjp0cnVlLCJyZW5hbWUiOnRydWUsIm1vZGlmeSI6dHJ1ZSwiZGVsZXRlIjp0cnVlLCJzaGFyZSI6dHJ1ZSwiZG93bmxvYWQiOnRydWV9LCJjb21tYW5kcyI6WyJkZiJdLCJsb2NrUGFzc3dvcmQiOmZhbHNlLCJoaWRlRG90ZmlsZXMiOmZhbHNlfSwiZXhwIjoxNzIxMDM3MjE0LCJpYXQiOjE3MjEwMzAwMTQsImlzcyI6IkZpbGUgQnJvd3NlciJ9.YNDbRregnpkZw6UFS0EJjX0DcCFQQoFmnCCusyFzstQ" )
|
158
server/comman/mqqtclinet.js
Normal file
158
server/comman/mqqtclinet.js
Normal file
@ -0,0 +1,158 @@
|
||||
const mqtt = require('mqtt');
|
||||
const db=require("./db")
|
||||
// db.resetpath("../db.sqlite3")
|
||||
|
||||
// 创建 MQTT 客户端实例
|
||||
const client = mqtt.connect('mqtt://82.156.1.111:40000', {
|
||||
clientId: 'web_collectorserver',
|
||||
username: 'xin',
|
||||
password: 'irishk'
|
||||
});
|
||||
client.subscribe("topic_who_is_here_back");
|
||||
// 定义事件处理程序
|
||||
client.on('connect', () => {
|
||||
console.log('MQTT client connected');
|
||||
client.subscribe('my/topic');
|
||||
});
|
||||
function converjsontokeyvalue(data)
|
||||
{
|
||||
|
||||
let fields = [];
|
||||
let fields1 = [];
|
||||
let fields2 = [];
|
||||
for (let key in data) {
|
||||
// 如果值是字符串,需要用引号包裹
|
||||
let value = typeof data[key] === 'string' ? `'${data[key]}'` : data[key];
|
||||
fields1.push(key);
|
||||
fields2.push( value);
|
||||
|
||||
}
|
||||
|
||||
fields.push(fields1.join(","))
|
||||
fields.push(fields2.join(","))
|
||||
return fields
|
||||
}
|
||||
function converjsontokeyequalvalue(data)
|
||||
{
|
||||
|
||||
let fields = [];
|
||||
|
||||
for (let key in data) {
|
||||
// 如果值是字符串,需要用引号包裹
|
||||
let value = typeof data[key] === 'string' ? `'${data[key]}'` : data[key];
|
||||
fields.push(key+"="+value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return fields.join(",")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
client.on('message', async (topic, message) => {
|
||||
if (topic==="topic_who_is_here_back")
|
||||
{
|
||||
var data=JSON.parse(message.toString())
|
||||
data.switch1=data.st[0];
|
||||
data.switch2=data.st[1];
|
||||
data.switch3=data.st[2];
|
||||
data.switch4=data.st[3];
|
||||
if (data.switch1===undefined)
|
||||
{
|
||||
data.switch1=true
|
||||
}
|
||||
if (data.switch2===undefined)
|
||||
{
|
||||
data.switch2=true
|
||||
}
|
||||
if (data.switch3===undefined)
|
||||
{
|
||||
data.switch3=true
|
||||
}
|
||||
if (data.switch4===undefined)
|
||||
{
|
||||
data.switch4=true
|
||||
}
|
||||
if (data.id.split("_")[1]==="4G")
|
||||
{
|
||||
data.is4G=true
|
||||
}else
|
||||
{
|
||||
data.is4G=false
|
||||
}
|
||||
data.device="nothing"
|
||||
delete data.st;
|
||||
|
||||
let sql="SELECT * FROM `remoteswitch` WHERE `id`=?"
|
||||
|
||||
|
||||
|
||||
db.query(sql,data.id,function(err, rows){
|
||||
if (1)
|
||||
{
|
||||
|
||||
}
|
||||
var result=rows
|
||||
|
||||
if (result.length===0)
|
||||
{
|
||||
|
||||
console.log(data)
|
||||
sql="insert into `remoteswitch` ( "+converjsontokeyvalue(data)[0]+" ) values ("+converjsontokeyvalue(data)[1]+")"
|
||||
console.log(sql)
|
||||
db.query(sql,(err,result)=>{
|
||||
console.log(err)
|
||||
console.log("insert ok")
|
||||
})
|
||||
}else
|
||||
{
|
||||
|
||||
sql='update `remoteswitch` set '+converjsontokeyequalvalue(data)+' where id=?'
|
||||
console.log(sql)
|
||||
db.query(sql,[data.id],(err,result)=>{
|
||||
console.log(err)
|
||||
console.log("update ok")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
//console.log(aaa)
|
||||
|
||||
|
||||
}
|
||||
|
||||
// console.log('Received message:', topic, message.toString());
|
||||
});
|
||||
|
||||
client.on('reconnect', () => {
|
||||
console.log('MQTT client reconnected');
|
||||
});
|
||||
|
||||
client.on('offline', () => {
|
||||
console.log('MQTT client offline');
|
||||
});
|
||||
|
||||
client.on('error', (err) => {
|
||||
console.error('MQTT client error:', err);
|
||||
});
|
||||
|
||||
// 在退出时关闭客户端连接
|
||||
process.on('SIGINT', () => {
|
||||
console.log('Exiting...');
|
||||
client.end(() => {
|
||||
console.log('MQTT client disconnected');
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
function getdevicemqtt() {
|
||||
client.publish('topic_who_is_here', 'who is here');
|
||||
}
|
||||
|
||||
exports.getdevicemqtt=getdevicemqtt
|
59
server/comman/mqqthttp.js
Normal file
59
server/comman/mqqthttp.js
Normal file
@ -0,0 +1,59 @@
|
||||
const axios=require("./mqttaxios");
|
||||
|
||||
async function queryDeviceStatus(deviceId) {
|
||||
try {
|
||||
const response = await axios.get('/api/v4/clients/', {
|
||||
params: {
|
||||
clientid: deviceId
|
||||
}
|
||||
});
|
||||
//cl console.log(response)
|
||||
const clients = response.data.data;
|
||||
if (clients.length > 0) {
|
||||
|
||||
console.log(clients[0].connected);
|
||||
console.log("on working");
|
||||
return clients[0].connected;
|
||||
} else {
|
||||
|
||||
console.log("not on working");
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function queryalldeviceonline() {
|
||||
const listofcliensidonline=new Array();
|
||||
try {
|
||||
const response = await axios.get('/api/v4/clients/');
|
||||
//cl console.log(response)
|
||||
const clients = response.data.data;
|
||||
|
||||
for (item in clients)
|
||||
{
|
||||
// console.log(clients[item])
|
||||
listofcliensidonline.push(clients[item].clientid);
|
||||
}
|
||||
|
||||
console.log(listofcliensidonline)
|
||||
return listofcliensidonline;
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return listofcliensidonline;
|
||||
}
|
||||
}
|
||||
|
||||
function queryDeviceStatus(clientid,list)
|
||||
{
|
||||
return list.includes(clientid);
|
||||
|
||||
|
||||
}
|
||||
|
||||
exports.queryalldeviceonline=queryalldeviceonline;
|
||||
//queryalldeviceonline()
|
10
server/comman/mqttaxios.js
Normal file
10
server/comman/mqttaxios.js
Normal file
@ -0,0 +1,10 @@
|
||||
const myaxios = require('axios');
|
||||
myaxios.defaults.baseURL = 'http://82.156.1.111:18083';
|
||||
const mqtusername = 'admin';
|
||||
const mqtpassword = 'licahk';
|
||||
const input = mqtusername+":"+mqtpassword;
|
||||
const token = Buffer.from(input).toString('base64');
|
||||
//console.log(token);
|
||||
myaxios.defaults.headers.common['Authorization'] = 'Basic ' + token;
|
||||
|
||||
module.exports = myaxios
|
7
server/comman/mqttclinet.js
Normal file
7
server/comman/mqttclinet.js
Normal file
@ -0,0 +1,7 @@
|
||||
const mqtt = require('mqtt');
|
||||
const db=require("../comman/db")
|
||||
const client = mqtt.connect('mqtt://82.156.1.111:40000', {
|
||||
clientId: 'web_collector',
|
||||
username: 'xin',
|
||||
password: 'irishk'
|
||||
});
|
46
server/comman/tstws.js
Normal file
46
server/comman/tstws.js
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
const WebSocket = require('ws');
|
||||
|
||||
|
||||
|
||||
async function sendMessageAndWaitForResponse(addres, message) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = new WebSocket(addres);
|
||||
buffarr=[];
|
||||
socket.on('open', () => {
|
||||
socket.send(message);
|
||||
});
|
||||
|
||||
// 监听服务器返回的消息
|
||||
function messageHandler(response) {
|
||||
// 在这里处理服务器返回的消息
|
||||
// 可以根据需要解析 JSON 或其他处理
|
||||
buffarr.push(response)
|
||||
socket.off('error',errorHandler)
|
||||
|
||||
}
|
||||
function errorHandler(err)
|
||||
{
|
||||
console.log(err)
|
||||
buffarr.push(Buffer.from("error"))
|
||||
resolve(buffarr);
|
||||
}
|
||||
|
||||
socket.on('error',errorHandler);
|
||||
// 监听服务器返回的消息
|
||||
socket.on('message', messageHandler);
|
||||
|
||||
// 处理连接关闭情况
|
||||
socket.on('close', () => {
|
||||
resolve(buffarr);
|
||||
});
|
||||
});
|
||||
}
|
||||
async function runinws( message,addres){
|
||||
let aa=await sendMessageAndWaitForResponse(addres,message)
|
||||
|
||||
return aa
|
||||
|
||||
// console.log(aa[1].toString())
|
||||
}
|
||||
exports.runinws=runinws
|
BIN
server/db.sqlite3
Normal file
BIN
server/db.sqlite3
Normal file
Binary file not shown.
BIN
server/mqtt/db.sqlite3
Normal file
BIN
server/mqtt/db.sqlite3
Normal file
Binary file not shown.
4405
server/package-lock.json
generated
Normal file
4405
server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
server/package.json
Normal file
21
server/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "ars-server",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.3.4",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.20.1",
|
||||
"debug": "~2.6.9",
|
||||
"express": "^4.19.2",
|
||||
"express-session": "^1.17.3",
|
||||
"mqtt": "^4.3.7",
|
||||
"mysql": "^2.18.1",
|
||||
"node-schedule": "^2.1.1",
|
||||
"sqlite3": "^5.1.7",
|
||||
"ws": "^8.18.0"
|
||||
}
|
||||
}
|
8
server/public/stylesheets/style.css
Normal file
8
server/public/stylesheets/style.css
Normal file
@ -0,0 +1,8 @@
|
||||
body {
|
||||
padding: 50px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00B7FF;
|
||||
}
|
6
server/router/devinfo.js
Normal file
6
server/router/devinfo.js
Normal file
@ -0,0 +1,6 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
const devinfoHandler = require('../router_handler/devinof_handle')
|
||||
|
||||
router.get('/getfilelistinfo', devinfoHandler.getfilelistinfo)
|
||||
module.exports = router;
|
9
server/router/index.js
Normal file
9
server/router/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
res.render('index', { title: 'Express' });
|
||||
});
|
||||
|
||||
module.exports = router;
|
9
server/router/mqtt_router.js
Normal file
9
server/router/mqtt_router.js
Normal file
@ -0,0 +1,9 @@
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const mqttHandler = require('../router_handler/mqtt_router_handle')
|
||||
|
||||
router.post('/getSwitchStat', mqttHandler.getSwitchStat)
|
||||
router.get('/getSwitchList', mqttHandler.getSwitchList)
|
||||
|
||||
router.get('/SetSwitch', mqttHandler.SetSwitch)
|
||||
module.exports = router
|
13
server/router/user.js
Normal file
13
server/router/user.js
Normal file
@ -0,0 +1,13 @@
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
|
||||
// 导入用户路由处理函数模块
|
||||
const userHandler = require('../router_handler/user')
|
||||
|
||||
// 注册新用户
|
||||
router.post('/reguser', userHandler.regUser)
|
||||
// 登录
|
||||
router.post('/login', userHandler.login)
|
||||
router.get('/logout', userHandler.logout)
|
||||
|
||||
module.exports = router
|
9
server/router_handler/devinof_handle.js
Normal file
9
server/router_handler/devinof_handle.js
Normal file
@ -0,0 +1,9 @@
|
||||
const db=require("../comman/db")
|
||||
|
||||
exports.getfilelistinfo=(req, res) => {
|
||||
sql='SELECT d.*, i.last_online FROM filebrowerinfo d JOIN frpinfo i ON d.name = i.id;'
|
||||
db.query(sql,(err,result)=>{
|
||||
res.send(result);
|
||||
})
|
||||
|
||||
}
|
152
server/router_handler/mqtt_router_handle.js
Normal file
152
server/router_handler/mqtt_router_handle.js
Normal file
@ -0,0 +1,152 @@
|
||||
|
||||
const db=require("../comman/db")
|
||||
const mqttserver=require("../comman/mqqthttp")
|
||||
const {log} = require("debug");
|
||||
exports.getSwitchStat=(req, res) => {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
exports.getSwitchList= async (req, res) => {
|
||||
|
||||
|
||||
let listonline=await mqttserver.queryalldeviceonline()
|
||||
|
||||
|
||||
|
||||
sql='SELECT * FROM `remoteswitch` WHERE 1'
|
||||
db.query(sql,(err,result)=>{
|
||||
|
||||
let devicelist=new Array()
|
||||
|
||||
for(rowindex in result) {
|
||||
// console.log(result)
|
||||
|
||||
Data={
|
||||
|
||||
ID: rowindex,
|
||||
SwitchID:result[rowindex].id,
|
||||
Type:result[rowindex].type,
|
||||
Detail:result[rowindex].tips,
|
||||
SwitchData: [
|
||||
{ Stat: result[rowindex].switch1===1?true:false, ID: 1},
|
||||
{ Stat: result[rowindex].switch2===1?true:false, ID: 2},
|
||||
{ Stat: result[rowindex].switch3===1?true:false, ID: 3},
|
||||
{Stat: result[rowindex].switch4===1?true:false, ID: 4}
|
||||
|
||||
]
|
||||
}
|
||||
if (listonline.includes(result[rowindex].id))
|
||||
{
|
||||
Data.isonline=true;
|
||||
}else
|
||||
{
|
||||
continue
|
||||
Data.isonline=false;
|
||||
}
|
||||
|
||||
//res.send(Data);
|
||||
|
||||
devicelist.push(Data);
|
||||
|
||||
|
||||
}
|
||||
//console.log(devicelist)
|
||||
backdata={
|
||||
|
||||
devicelist:devicelist
|
||||
}
|
||||
res.send(backdata);
|
||||
// console.log(devicelist[0].SwitchData)
|
||||
|
||||
// res.send("sdfsdfsdf");
|
||||
// res.send(devicelist);
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
exports.SetSwitch=async (req, res) => {
|
||||
|
||||
|
||||
|
||||
req.body=req.query
|
||||
//console.log(req)
|
||||
|
||||
|
||||
|
||||
Data={
|
||||
id:req.body.Data.SwitchID,
|
||||
sid:req.body.Data.number,
|
||||
st:(req.body.Data.stat==="true"?1:0)
|
||||
}
|
||||
|
||||
//console.log("data send")
|
||||
// console.log(Data)
|
||||
let mqttclient = global.MqttClient
|
||||
mqttclient.publish("remoteShutter",JSON.stringify(Data));
|
||||
message= await waitForMessage("remoteShuttersend")
|
||||
message=JSON.parse(message)
|
||||
// console.log("message send")
|
||||
// console.log(message)
|
||||
Data=req.body.Data
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
Data.SwitchData[i]=message.st[i]
|
||||
}
|
||||
delete Data.number
|
||||
backdata={
|
||||
index:req.body.index,
|
||||
|
||||
Data://Data
|
||||
{
|
||||
|
||||
ID: req.body.Data.ID,
|
||||
SwitchID:message.id,
|
||||
Type:req.body.Data.Type,
|
||||
Detail:req.body.Data.Detail,
|
||||
isonline:true,
|
||||
SwitchData: [
|
||||
{ Stat: message.st[0], ID: 1},
|
||||
{ Stat: message.st[1], ID: 2},
|
||||
{ Stat: message.st[2], ID: 3},
|
||||
{Stat: message.st[3], ID: 4}
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
console.log(backdata.Data)
|
||||
res.send(backdata);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function waitForMessage(topic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let client = global.MqttClient
|
||||
client.subscribe(topic, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
client.on('message', (t, message) => {
|
||||
if (t === topic) {
|
||||
client.unsubscribe(topic);
|
||||
resolve(message.toString());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
100
server/router_handler/user.js
Normal file
100
server/router_handler/user.js
Normal file
@ -0,0 +1,100 @@
|
||||
var db = require("../comman/db.js")
|
||||
const bcrypt = require('bcryptjs')
|
||||
/**
|
||||
* 在这里定义和用户相关的路由处理函数,供 /router/user.js 模块进行调用
|
||||
*/
|
||||
|
||||
// 注册用户的处理函数
|
||||
exports.regUser = (req, res) => {
|
||||
var data = req.body;
|
||||
if (data.Username == "" || data.Name == "" || data.Password == "") {
|
||||
return res.send("传入数据非法")
|
||||
}
|
||||
const sqlStr = 'select * from employeelist where Username=?'
|
||||
//res.setHeader("refresh","3; url=../index.html")
|
||||
|
||||
db.query(sqlStr, data.Username, (err, result) => {
|
||||
if (err) {
|
||||
return res.send(err)
|
||||
}
|
||||
if (result.length > 0) {
|
||||
res.setHeader("refresh", "3; url=../html/register.html")
|
||||
return res.send("用户已存在 请更换用户名")
|
||||
|
||||
}
|
||||
delete data.configPassword
|
||||
data.Password = bcrypt.hashSync(data.Password, 10)
|
||||
data.Acess = 0
|
||||
data.Pic = null
|
||||
console.log(data);
|
||||
const sql = "insert into employeelist set ?";
|
||||
db.query(sql, data, (err, result) => {
|
||||
console.log(result);
|
||||
console.log(err)
|
||||
res.setHeader("refresh", "3; url=../index.html")
|
||||
res.send('reguser OK')
|
||||
});
|
||||
// res.setHeader('refresh:3; url=../index.html')
|
||||
|
||||
//res.render('new.html')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 登录的处理函数
|
||||
exports.login = (req, res) => {
|
||||
|
||||
const userinfo = req.body
|
||||
// 定义 SQL 语句
|
||||
const sql = `select * from employeelist where Username=?`
|
||||
// 执行 SQL 语句,根据用户名查询用户的信息
|
||||
db.query(sql, userinfo.Username, (err, results) => {
|
||||
// 执行 SQL 语句失败
|
||||
if (err) return res.send(err)
|
||||
// 执行 SQL 语句成功,但是获取到的数据条数不等于 1
|
||||
if (results.length !== 1) {
|
||||
res.setHeader("refresh", "3; url=../html/login.html")
|
||||
return res.send('登录失败!')
|
||||
}
|
||||
|
||||
// TODO:判断密码是否正确
|
||||
const compareResult = bcrypt.compareSync(userinfo.Password, results[0].Password)
|
||||
if (!compareResult) {
|
||||
res.setHeader("refresh", "3; url=../html/login.html")
|
||||
return res.send('登录失败!')
|
||||
}
|
||||
|
||||
// TODO:在服务器端生成 Token 的字符串
|
||||
req.session.username=userinfo.Username;
|
||||
req.session.islogin = true;
|
||||
if (userinfo.Username=="renlixin"){
|
||||
req.session.isadmin=true;
|
||||
}else
|
||||
{
|
||||
req.session.isadmin=false;
|
||||
}
|
||||
|
||||
var message = {
|
||||
|
||||
|
||||
message: "login ok"
|
||||
}
|
||||
res.setHeader("refresh", "3; url=../index.html")
|
||||
res.send(message.message)
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
exports.logout = (req, res) => {
|
||||
req.session.islogin = false;
|
||||
req.session.destroy();
|
||||
res.setHeader("refresh", "3; url=../html/login.html")
|
||||
res.send('logout ok')
|
||||
|
||||
}
|
24
ui2/.gitignore
vendored
Normal file
24
ui2/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
3
ui2/.vscode/extensions.json
vendored
Normal file
3
ui2/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
5
ui2/README.md
Normal file
5
ui2/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Vue 3 + TypeScript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
13
ui2/index.html
Normal file
13
ui2/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
1357
ui2/package-lock.json
generated
Normal file
1357
ui2/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
ui2/package.json
Normal file
22
ui2/package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "ui2",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.2",
|
||||
"vue": "^3.4.31"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arco-design/web-vue": "^2.55.3",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.3.4",
|
||||
"vue-tsc": "^2.0.24"
|
||||
}
|
||||
}
|
1
ui2/public/vite.svg
Normal file
1
ui2/public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
15
ui2/src/App.vue
Normal file
15
ui2/src/App.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<script setup >
|
||||
import devinfoshow from './components/devinfoshow.vue'
|
||||
import devinfoMain from './components/devinfoMain.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<!-- <devinfoshow name="devinfoshow" /> -->
|
||||
<devinfo-main></devinfo-main>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
1
ui2/src/assets/vue.svg
Normal file
1
ui2/src/assets/vue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
41
ui2/src/components/HelloWorld.vue
Normal file
41
ui2/src/components/HelloWorld.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps<{ msg: string }>()
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<div class="card">
|
||||
<button type="button" @click="count++">count is {{ count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test HMR
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Check out
|
||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
||||
>create-vue</a
|
||||
>, the official Vue + Vite starter
|
||||
</p>
|
||||
<p>
|
||||
Learn more about IDE Support for Vue in the
|
||||
<a
|
||||
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
|
||||
target="_blank"
|
||||
>Vue Docs Scaling up Guide</a
|
||||
>.
|
||||
</p>
|
||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
94
ui2/src/components/devinfoMain.vue
Normal file
94
ui2/src/components/devinfoMain.vue
Normal file
@ -0,0 +1,94 @@
|
||||
<template>
|
||||
|
||||
<a-carousel
|
||||
style="width: 100vw;height:100vh;"
|
||||
:default-current="1"
|
||||
:auto-play="{ interval: 5000}"
|
||||
indicator-type="line"
|
||||
show-arrow="always"
|
||||
arrow-class="color:red !important;"
|
||||
>
|
||||
<a-carousel-item v-for="(item,index) in datalist" :key="index">
|
||||
<devinfoshow :devinfo="item"></devinfoshow>
|
||||
</a-carousel-item>
|
||||
</a-carousel>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import devinfoshow from './devinfoshow.vue'
|
||||
import axios from 'axios';
|
||||
export default {
|
||||
name: 'DevinfoMain',
|
||||
components: {
|
||||
devinfoshow
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
datalist: []
|
||||
// Your component's data goes here
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.onloaddata();
|
||||
//每隔1分钟刷新一次
|
||||
setInterval(() => {
|
||||
this.onloaddata();
|
||||
}, 60000);
|
||||
},
|
||||
methods: {
|
||||
// Your component's methods go here
|
||||
async onloaddata() {
|
||||
const data=await axios.get('devinfo/getfilelistinfo');
|
||||
let datalist=data.data;
|
||||
|
||||
//每9个数据为一组 不足的不补齐
|
||||
|
||||
let newdatalist=[];
|
||||
let temp=[];
|
||||
|
||||
for(let i=0;i<datalist.length;i++)
|
||||
{
|
||||
|
||||
const datestr=datalist[i].last_online
|
||||
//如果上次时间距离现在超过1天则显示红色
|
||||
let lasttime=new Date(datestr);
|
||||
let nowtime=new Date();
|
||||
datalist[i].from_last_online_time=(nowtime-lasttime)/60000;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(let i=0;i<datalist.length;i++){
|
||||
if(i%9==0&&i!=0){
|
||||
newdatalist.push(temp);
|
||||
temp=[];
|
||||
}
|
||||
temp.push(datalist[i]);
|
||||
}
|
||||
newdatalist.push(temp);
|
||||
this.datalist=newdatalist;
|
||||
// console.log(newdatalist);
|
||||
}
|
||||
}
|
||||
// Your component's JavaScript logic goes here
|
||||
}
|
||||
</script>
|
||||
|
||||
<style >
|
||||
/* Your component's CSS styles go here */
|
||||
.arco-carousel-arrow > div > svg {
|
||||
color: rgb(0, 255, 132) !important;
|
||||
font-size: 20px;
|
||||
width: 100px !important;
|
||||
height: 100px !important;
|
||||
}
|
||||
.arco-carousel-arrow-right {
|
||||
width: 100px !important;
|
||||
}
|
||||
.arco-carousel-arrow-left {
|
||||
width: 100px !important;
|
||||
}
|
||||
</style>
|
117
ui2/src/components/devinfoshow.vue
Normal file
117
ui2/src/components/devinfoshow.vue
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'devinfoshow',
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
props: {
|
||||
devinfo: {
|
||||
|
||||
type: Array,
|
||||
required: true,
|
||||
default:()=>[{
|
||||
name: "设备序列号",
|
||||
status: "在线",
|
||||
lasttime: "2021-10-10 10:10:10",
|
||||
sppercent:10,
|
||||
sptotal:100,
|
||||
mountedon:"No SD card",
|
||||
|
||||
}]
|
||||
}
|
||||
// Your component's props go here
|
||||
},
|
||||
methods: {
|
||||
panduansd(dev){
|
||||
if(dev.mountedon=="/"||dev.mountedon=="No SD card"){
|
||||
return "red"
|
||||
}else{
|
||||
return "black"
|
||||
}
|
||||
},
|
||||
paduanshijian(dev){
|
||||
let datestr=dev.lasttime;
|
||||
//如果上次时间距离现在超过1天则显示红色
|
||||
let lasttime=new Date(datestr);
|
||||
let nowtime=new Date();
|
||||
if((nowtime-lasttime)>1000*60*60*24){
|
||||
return "red"
|
||||
}else{
|
||||
return "black"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Your component's methods go here
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
|
||||
<a-card :bordered="false" :style="{ width: '100vw',margin:'auto' }" :hoverable="true">
|
||||
<a-card-grid
|
||||
v-for="(dev, index) in devinfo"
|
||||
:key="index"
|
||||
:hoverable="index % 2 === 0"
|
||||
|
||||
:style="{ width: '32%',height: '31vh',margin: '10px', background: paduanshijian(dev)==='red'?'#FFCCCC':'#CCFFCC'}"
|
||||
|
||||
>
|
||||
<a-card
|
||||
class="card-demo"
|
||||
:title="dev.name"
|
||||
:bordered="false"
|
||||
|
||||
|
||||
>
|
||||
<template #extra>
|
||||
<a-link :href="dev.remote_port" target="_blank">查看数据</a-link>
|
||||
</template>
|
||||
<p :style="{ margin: 0,color:dev.from_last_online_time>30?'red':'green'}">
|
||||
设备状态:{{ dev.from_last_online_time>30?'离线'+dev.from_last_online_time+'分钟':'在线' }}
|
||||
</p>
|
||||
<p :style="{ margin: 0 ,color:paduanshijian(dev)}">
|
||||
最新文件时间:{{ dev.lasttime }}
|
||||
</p>
|
||||
|
||||
<template #actions>
|
||||
|
||||
</template>
|
||||
</a-card>
|
||||
<p style="bottom: 0px; position: absolute; width: 100%; border-top: 1px solid #e8e8e8;margin-bottom: 0px;min-height: 10% "
|
||||
:style="{background:panduansd(dev)==='red'?'#FFCCCC':'#CCFFCC'}">
|
||||
|
||||
|
||||
<a-row class="grid-demo" :gutter="24" >
|
||||
<a-col :span="14">
|
||||
<div> SD: {{ dev.sptotal }}GB <a-progress :style="{ width: '60%' }" :percent="dev.sppercent/100" color="green" :status="dev.sppercent>90?'danger':'normal'"/></div>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<div :style="{color:panduansd(dev)}">挂载路径:{{dev.mountedon }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
</p>
|
||||
</a-card-grid>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* Your component's CSS styles go here */
|
||||
h1 {
|
||||
color: blue;
|
||||
}
|
||||
.card-demo {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
15
ui2/src/main.ts
Normal file
15
ui2/src/main.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import axios from 'axios'
|
||||
|
||||
import ArcoVue from '@arco-design/web-vue';
|
||||
|
||||
import '@arco-design/web-vue/dist/arco.css';
|
||||
|
||||
console.log(window.location.hostname);
|
||||
axios.defaults.baseURL = "http://"+window.location.hostname+":1000";
|
||||
|
||||
const app=createApp(App);
|
||||
app.use(ArcoVue);
|
||||
app.mount('#app');
|
80
ui2/src/style.css
Normal file
80
ui2/src/style.css
Normal file
@ -0,0 +1,80 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
margin: 0 ;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
1
ui2/src/vite-env.d.ts
vendored
Normal file
1
ui2/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
27
ui2/tsconfig.app.json
Normal file
27
ui2/tsconfig.app.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
11
ui2/tsconfig.json
Normal file
11
ui2/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
13
ui2/tsconfig.node.json
Normal file
13
ui2/tsconfig.node.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
10
ui2/vite.config.ts
Normal file
10
ui2/vite.config.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
server:{
|
||||
host:'0.0.0.0'
|
||||
},
|
||||
})
|
Reference in New Issue
Block a user