feat: 初始化Node.js 4G短信网关项目
- 实现AT指令通信和4G模组管理 - 支持PDU模式短信接收和发送 - 长短信自动合并功能 - 多通道推送支持(钉钉/飞书/Telegram等) - 管理员短信远程控制 - RESTful API接口 - 完整的日志系统
This commit is contained in:
+209
@@ -0,0 +1,209 @@
|
||||
import express from 'express';
|
||||
import basicAuth from 'express-basic-auth';
|
||||
import logger from './logger.js';
|
||||
|
||||
class APIServer {
|
||||
constructor(config, modem, smsProcessor) {
|
||||
this.config = config;
|
||||
this.modem = modem;
|
||||
this.smsProcessor = smsProcessor;
|
||||
this.app = express();
|
||||
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
}
|
||||
|
||||
setupMiddleware() {
|
||||
// JSON解析
|
||||
this.app.use(express.json());
|
||||
|
||||
// HTTP Basic认证
|
||||
const users = {};
|
||||
users[this.config.api.auth.username] = this.config.api.auth.password;
|
||||
|
||||
this.app.use(basicAuth({
|
||||
users,
|
||||
challenge: true,
|
||||
realm: 'SMS Gateway'
|
||||
}));
|
||||
|
||||
// 请求日志
|
||||
this.app.use((req, res, next) => {
|
||||
logger.info(`${req.method} ${req.path}`);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
setupRoutes() {
|
||||
// 状态查询
|
||||
this.app.get('/api/status', async (req, res) => {
|
||||
try {
|
||||
const signal = await this.modem.getSignalQuality();
|
||||
const operator = await this.modem.getOperator();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
ready: this.modem.ready,
|
||||
model: this.modem.modelInfo,
|
||||
signal,
|
||||
operator,
|
||||
uptime: process.uptime()
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('查询状态失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 发送短信
|
||||
this.app.post('/api/sms/send', async (req, res) => {
|
||||
try {
|
||||
const { phone, message } = req.body;
|
||||
|
||||
if (!phone || !message) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '缺少必要参数: phone, message'
|
||||
});
|
||||
}
|
||||
|
||||
const success = await this.modem.sendSMS(phone, message);
|
||||
|
||||
res.json({
|
||||
success,
|
||||
message: success ? '短信发送成功' : '短信发送失败'
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('发送短信失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 查询信号强度
|
||||
this.app.get('/api/modem/signal', async (req, res) => {
|
||||
try {
|
||||
const signal = await this.modem.getSignalQuality();
|
||||
res.json({
|
||||
success: true,
|
||||
data: signal
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('查询信号失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 查询模组信息
|
||||
this.app.get('/api/modem/info', async (req, res) => {
|
||||
try {
|
||||
const iccid = await this.modem.getICCID();
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
model: this.modem.modelInfo,
|
||||
iccid,
|
||||
ready: this.modem.ready
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('查询模组信息失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 发送AT命令
|
||||
this.app.post('/api/modem/at', async (req, res) => {
|
||||
try {
|
||||
const { command } = req.body;
|
||||
|
||||
if (!command) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '缺少必要参数: command'
|
||||
});
|
||||
}
|
||||
|
||||
const response = await this.modem.sendATCommand(command, 5000);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
command,
|
||||
response
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('发送AT命令失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取日志
|
||||
this.app.get('/api/logs', (req, res) => {
|
||||
try {
|
||||
const logs = logger.getBuffer().getAll();
|
||||
res.json({
|
||||
success: true,
|
||||
data: logs
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('获取日志失败:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 健康检查
|
||||
this.app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
uptime: process.uptime()
|
||||
});
|
||||
});
|
||||
|
||||
// 404处理
|
||||
this.app.use((req, res) => {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
error: 'Not Found'
|
||||
});
|
||||
});
|
||||
|
||||
// 错误处理
|
||||
this.app.use((err, req, res, next) => {
|
||||
logger.error('API错误:', err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: err.message
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
start() {
|
||||
const port = this.config.api.port;
|
||||
this.app.listen(port, () => {
|
||||
logger.info(`API服务器已启动,监听端口: ${port}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default APIServer;
|
||||
Reference in New Issue
Block a user