RFID 智能公交刷卡系统,包含车载终端、后台管理系统、卡片管理、交易结算等全套解决方案。
一、系统架构
RFID智能公交系统/
├── BusTerminal/ # 车载终端(C# + RFID读写器)
│ ├── BusTerminal.csproj
│ ├── Program.cs
│ ├── MainForm.cs
│ ├── RFIDReader.cs ★ RFID核心读写
│ ├── PaymentProcessor.cs # 支付处理
│ ├── DataSync.cs # 数据同步
│ └── Hardware/
│ ├── DisplayController.cs
│ ├── VoiceController.cs
│ └── PrinterController.cs
├── ManagementSystem/ # 后台管理系统
│ ├── ManagementSystem.csproj
│ ├── Program.cs
│ ├── MainForm.cs
│ ├── CardManagement.cs # 卡片管理
│ ├── TransactionQuery.cs # 交易查询
│ ├── ReportGenerator.cs # 报表生成
│ └── SystemConfig.cs # 系统配置
├── Database/ # 数据库层
│ ├── DatabaseManager.cs
│ ├── CardRepository.cs
│ ├── TransactionRepository.cs
│ └── BusRepository.cs
├── Models/ # 数据模型
│ ├── Card.cs
│ ├── Transaction.cs
│ ├── Bus.cs
│ └── Station.cs
├── Communication/ # 通信层
│ ├── SerialCommunication.cs
│ ├── TcpCommunication.cs
│ └── GprsCommunication.cs
└── Utils/ # 工具类
├── Encryption.cs
├── Logger.cs
└── Validator.cs
二、核心代码实现
1. 车载终端主程序 (BusTerminal/Program.cs)
using System;
using System.Windows.Forms;
using BusTerminal.Hardware;
namespace BusTerminal
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// 初始化硬件
HardwareManager.Initialize();
Application.Run(new MainForm());
}
}
public static class HardwareManager
{
public static RFIDReader RfidReader { get; private set; }
public static DisplayController Display { get; private set; }
public static VoiceController Voice { get; private set; }
public static PrinterController Printer { get; private set; }
public static void Initialize()
{
try
{
RfidReader = new RFIDReader();
Display = new DisplayController();
Voice = new VoiceController();
Printer = new PrinterController();
// 初始化成功提示
Voice.Play("系统初始化成功");
Display.ShowMessage("欢迎使用智能公交系统", "请刷卡...");
}
catch (Exception ex)
{
MessageBox.Show($"硬件初始化失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
2. 车载终端主界面 (BusTerminal/MainForm.cs)
using System;
using System.Drawing;
using System.Windows.Forms;
using BusTerminal.Hardware;
using BusTerminal.Database;
using BusTerminal.Models;
namespace BusTerminal
{
public partial class MainForm : Form
{
private PaymentProcessor paymentProcessor;
private DataSync dataSync;
private Timer statusTimer;
// 当前状态
private bool isOnline = true;
private decimal currentBalance = 0;
private string currentCardNo = "";
private Bus currentBus;
public MainForm()
{
InitializeComponent();
InitializeSystem();
}
private void InitializeComponent()
{
this.Text = "智能公交刷卡终端";
this.Size = new Size(800, 600);
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
// 顶部状态栏
Panel statusPanel = new Panel
{
Dock = DockStyle.Top,
Height = 60,
BackColor = Color.DarkBlue
};
lblBusInfo = new Label
{
Text = "公交车: 未设置",
ForeColor = Color.White,
Font = new Font("微软雅黑", 12, FontStyle.Bold),
Location = new Point(10, 15),
Size = new Size(300, 30)
};
lblNetworkStatus = new Label
{
Text = "网络: 在线",
ForeColor = Color.Lime,
Font = new Font("微软雅黑", 10),
Location = new Point(500, 15),
Size = new Size(100, 25)
};
lblTime = new Label
{
Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
ForeColor = Color.White,
Font = new Font("微软雅黑", 10),
Location = new Point(650, 15),
Size = new Size(150, 25)
};
statusPanel.Controls.Add(lblBusInfo);
statusPanel.Controls.Add(lblNetworkStatus);
statusPanel.Controls.Add(lblTime);
// 主显示区域
Panel mainPanel = new Panel
{
Dock = DockStyle.Fill,
BackColor = Color.Black
};
// 刷卡区域
GroupBox gbSwipeArea = new GroupBox
{
Text = "刷卡区域",
Location = new Point(20, 20),
Size = new Size(400, 300),
ForeColor = Color.White,
Font = new Font("微软雅黑", 10)
};
picRFID = new PictureBox
{
Image = Properties.Resources.RFID_Icon,
Location = new Point(150, 50),
Size = new Size(100, 100),
SizeMode = PictureBoxSizeMode.StretchImage
};
lblSwipePrompt = new Label
{
Text = "请将卡片靠近感应区",
ForeColor = Color.Yellow,
Font = new Font("微软雅黑", 14, FontStyle.Bold),
Location = new Point(50, 180),
Size = new Size(300, 30),
TextAlign = ContentAlignment.MiddleCenter
};
gbSwipeArea.Controls.Add(picRFID);
gbSwipeArea.Controls.Add(lblSwipePrompt);
// 交易信息区域
GroupBox gbTransaction = new GroupBox
{
Text = "交易信息",
Location = new Point(440, 20),
Size = new Size(320, 300),
ForeColor = Color.White,
Font = new Font("微软雅黑", 10)
};
lblCardNo = new Label
{
Text = "卡号: --",
ForeColor = Color.White,
Font = new Font("微软雅黑", 12),
Location = new Point(20, 40),
Size = new Size(280, 25)
};
lblCardHolder = new Label
{
Text = "持卡人: --",
ForeColor = Color.White,
Font = new Font("微软雅黑", 12),
Location = new Point(20, 80),
Size = new Size(280, 25)
};
lblBalance = new Label
{
Text = "余额: --",
ForeColor = Color.White,
Font = new Font("微软雅黑", 12),
Location = new Point(20, 120),
Size = new Size(280, 25)
};
lblAmount = new Label
{
Text = "扣费: --",
ForeColor = Color.Yellow,
Font = new Font("微软雅黑", 12, FontStyle.Bold),
Location = new Point(20, 160),
Size = new Size(280, 25)
};
lblResult = new Label
{
Text = "等待刷卡...",
ForeColor = Color.Lime,
Font = new Font("微软雅黑", 14, FontStyle.Bold),
Location = new Point(20, 220),
Size = new Size(280, 30),
TextAlign = ContentAlignment.MiddleCenter
};
gbTransaction.Controls.Add(lblCardNo);
gbTransaction.Controls.Add(lblCardHolder);
gbTransaction.Controls.Add(lblBalance);
gbTransaction.Controls.Add(lblAmount);
gbTransaction.Controls.Add(lblResult);
// 底部控制按钮
Panel controlPanel = new Panel
{
Dock = DockStyle.Bottom,
Height = 80,
BackColor = Color.DarkGray
};
btnSettings = new Button
{
Text = "系统设置",
Location = new Point(20, 20),
Size = new Size(100, 40),
BackColor = Color.LightGray
};
btnSettings.Click += BtnSettings_Click;
btnSync = new Button
{
Text = "数据同步",
Location = new Point(140, 20),
Size = new Size(100, 40),
BackColor = Color.LightGray
};
btnSync.Click += BtnSync_Click;
btnHistory = new Button
{
Text = "交易历史",
Location = new Point(260, 20),
Size = new Size(100, 40),
BackColor = Color.LightGray
};
btnHistory.Click += BtnHistory_Click;
btnExit = new Button
{
Text = "退出",
Location = new Point(650, 20),
Size = new Size(100, 40),
BackColor = Color.LightCoral
};
btnExit.Click += BtnExit_Click;
controlPanel.Controls.Add(btnSettings);
controlPanel.Controls.Add(btnSync);
controlPanel.Controls.Add(btnHistory);
controlPanel.Controls.Add(btnExit);
// 添加到窗体
this.Controls.Add(statusPanel);
this.Controls.Add(mainPanel);
this.Controls.Add(controlPanel);
mainPanel.Controls.Add(gbSwipeArea);
mainPanel.Controls.Add(gbTransaction);
}
private void InitializeSystem()
{
// 初始化支付处理器
paymentProcessor = new PaymentProcessor();
paymentProcessor.PaymentCompleted += PaymentProcessor_PaymentCompleted;
paymentProcessor.PaymentFailed += PaymentProcessor_PaymentFailed;
// 初始化数据同步
dataSync = new DataSync();
// 启动状态更新定时器
statusTimer = new Timer { Interval = 1000 };
statusTimer.Tick += StatusTimer_Tick;
statusTimer.Start();
// 设置RFID读卡器回调
HardwareManager.RfidReader.CardDetected += RfidReader_CardDetected;
// 加载公交车信息
LoadBusInfo();
}
#region 事件处理
private void RfidReader_CardDetected(object sender, CardDetectedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => RfidReader_CardDetected(sender, e)));
return;
}
currentCardNo = e.CardNumber;
ProcessPayment(currentCardNo);
}
private void ProcessPayment(string cardNo)
{
try
{
// 显示卡号
lblCardNo.Text = $"卡号: {cardNo}";
lblSwipePrompt.Text = "正在处理...";
lblResult.Text = "处理中...";
lblResult.ForeColor = Color.Yellow;
// 处理支付
var result = paymentProcessor.ProcessPayment(cardNo, currentBus.BusId);
if (result.Success)
{
// 显示交易信息
lblCardHolder.Text = $"持卡人: {result.CardHolder}";
lblBalance.Text = $"余额: ¥{result.Balance:F2}";
lblAmount.Text = $"扣费: ¥{result.Amount:F2}";
lblResult.Text = "支付成功!";
lblResult.ForeColor = Color.Lime;
// 语音播报
HardwareManager.Voice.Play($"支付成功,余额{result.Balance:F2}元");
// 打印小票
PrintReceipt(result);
// 更新显示
UpdateDisplay("支付成功", Color.Lime);
}
else
{
lblResult.Text = $"支付失败: {result.Message}";
lblResult.ForeColor = Color.Red;
HardwareManager.Voice.Play($"支付失败,{result.Message}");
UpdateDisplay("支付失败", Color.Red);
}
}
catch (Exception ex)
{
lblResult.Text = $"系统错误: {ex.Message}";
lblResult.ForeColor = Color.Red;
HardwareManager.Voice.Play("系统错误");
}
}
private void PaymentProcessor_PaymentCompleted(object sender, PaymentResult result)
{
// 支付完成处理
LogTransaction(result);
}
private void PaymentProcessor_PaymentFailed(object sender, string reason)
{
// 支付失败处理
HardwareManager.Display.ShowMessage("支付失败", reason);
}
private void StatusTimer_Tick(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// 检查网络连接
bool online = CheckNetworkConnection();
if (online != isOnline)
{
isOnline = online;
lblNetworkStatus.Text = isOnline ? "网络: 在线" : "网络: 离线";
lblNetworkStatus.ForeColor = isOnline ? Color.Lime : Color.Red;
}
}
private void BtnSettings_Click(object sender, EventArgs e)
{
using (SettingsForm form = new SettingsForm())
{
if (form.ShowDialog() == DialogResult.OK)
{
LoadBusInfo();
}
}
}
private void BtnSync_Click(object sender, EventArgs e)
{
SyncData();
}
private void BtnHistory_Click(object sender, EventArgs e)
{
using (HistoryForm form = new HistoryForm())
{
form.ShowDialog();
}
}
private void BtnExit_Click(object sender, EventArgs e)
{
if (MessageBox.Show("确定要退出系统吗?", "确认退出",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
Application.Exit();
}
}
#endregion
#region 辅助方法
private void LoadBusInfo()
{
// 从配置文件加载公交车信息
currentBus = new Bus
{
BusId = Properties.Settings.Default.BusId,
BusNumber = Properties.Settings.Default.BusNumber,
Route = Properties.Settings.Default.Route
};
lblBusInfo.Text = $"公交车: {currentBus.BusNumber} ({currentBus.Route})";
}
private bool CheckNetworkConnection()
{
try
{
// 简单的网络检查
using (var client = new System.Net.WebClient())
{
client.DownloadString("http://www.baidu.com");
return true;
}
}
catch
{
return false;
}
}
private void SyncData()
{
lblResult.Text = "正在同步数据...";
lblResult.ForeColor = Color.Yellow;
try
{
dataSync.SyncTransactions();
lblResult.Text = "数据同步完成";
lblResult.ForeColor = Color.Lime;
HardwareManager.Voice.Play("数据同步完成");
}
catch (Exception ex)
{
lblResult.Text = $"同步失败: {ex.Message}";
lblResult.ForeColor = Color.Red;
}
}
private void LogTransaction(PaymentResult result)
{
// 记录交易日志
string log = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} | 卡号:{result.CardNo} | 金额:{result.Amount:F2} | 余额:{result.Balance:F2}";
System.IO.File.AppendAllText("transactions.log", log + Environment.NewLine);
}
private void PrintReceipt(PaymentResult result)
{
string receipt = $@"
================================
智能公交刷卡凭证
================================
交易时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}
公交车号: {currentBus.BusNumber}
线路: {currentBus.Route}
卡号: {result.CardNo}
持卡人: {result.CardHolder}
扣费金额: ¥{result.Amount:F2}
剩余余额: ¥{result.Balance:F2}
================================
";
HardwareManager.Printer.Print(receipt);
}
private void UpdateDisplay(string message, Color color)
{
lblSwipePrompt.Text = message;
lblSwipePrompt.ForeColor = color;
}
#endregion
// 控件声明
private Label lblBusInfo;
private Label lblNetworkStatus;
private Label lblTime;
private PictureBox picRFID;
private Label lblSwipePrompt;
private Label lblCardNo;
private Label lblCardHolder;
private Label lblBalance;
private Label lblAmount;
private Label lblResult;
private Button btnSettings;
private Button btnSync;
private Button btnHistory;
private Button btnExit;
}
}
3. RFID 读写器核心类 (BusTerminal/RFIDReader.cs)
using System;
using System.IO.Ports;
using System.Threading;
using System.Text;
using BusTerminal.Utils;
namespace BusTerminal.Hardware
{
public class RFIDReader
{
public event EventHandler<CardDetectedEventArgs> CardDetected;
private SerialPort serialPort;
private Timer readTimer;
private bool isReading = false;
private string lastCardNo = "";
public RFIDReader()
{
InitializeSerialPort();
InitializeTimer();
}
private void InitializeSerialPort()
{
serialPort = new SerialPort
{
PortName = Properties.Settings.Default.RfidPort,
BaudRate = 9600,
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One,
ReadTimeout = 1000,
WriteTimeout = 1000
};
serialPort.DataReceived += SerialPort_DataReceived;
}
private void InitializeTimer()
{
readTimer = new Timer { Interval = 500 };
readTimer.Tick += ReadTimer_Tick;
}
public bool Connect()
{
try
{
if (!serialPort.IsOpen)
{
serialPort.Open();
readTimer.Start();
Logger.Info("RFID读卡器连接成功");
return true;
}
return true;
}
catch (Exception ex)
{
Logger.Error($"RFID读卡器连接失败: {ex.Message}");
return false;
}
}
public void Disconnect()
{
try
{
readTimer.Stop();
if (serialPort.IsOpen)
{
serialPort.Close();
}
Logger.Info("RFID读卡器已断开");
}
catch (Exception ex)
{
Logger.Error($"断开RFID读卡器失败: {ex.Message}");
}
}
private void ReadTimer_Tick(object sender, EventArgs e)
{
if (!isReading)
{
SendReadCommand();
}
}
private void SendReadCommand()
{
try
{
isReading = true;
byte[] command = { 0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 };
serialPort.Write(command, 0, command.Length);
}
catch (Exception ex)
{
Logger.Error($"发送读卡命令失败: {ex.Message}");
}
finally
{
isReading = false;
}
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] buffer = new byte[serialPort.BytesToRead];
serialPort.Read(buffer, 0, buffer.Length);
string cardNo = ParseCardNumber(buffer);
if (!string.IsNullOrEmpty(cardNo) && cardNo != lastCardNo)
{
lastCardNo = cardNo;
CardDetected?.Invoke(this, new CardDetectedEventArgs(cardNo));
// 防重复触发,延迟2秒
Thread.Sleep(2000);
lastCardNo = "";
}
}
catch (Exception ex)
{
Logger.Error($"处理RFID数据失败: {ex.Message}");
}
}
private string ParseCardNumber(byte[] data)
{
if (data.Length < 8) return "";
// 根据RFID读卡器协议解析卡号
// 这里假设卡号在数据的特定位置
StringBuilder sb = new StringBuilder();
for (int i = 4; i < 8; i++)
{
sb.Append(data[i].ToString("X2"));
}
return sb.ToString();
}
public bool WriteCard(string cardNo, decimal amount)
{
try
{
// 写卡命令
byte[] command = BuildWriteCommand(cardNo, amount);
serialPort.Write(command, 0, command.Length);
return true;
}
catch (Exception ex)
{
Logger.Error($"写卡失败: {ex.Message}");
return false;
}
}
private byte[] BuildWriteCommand(string cardNo, decimal amount)
{
// 构建写卡命令(根据具体RFID读卡器协议)
byte[] command = new byte[16];
command[0] = 0xAA; // 起始字节
command[1] = 0xBB; // 命令字
// ... 其他参数
return command;
}
}
public class CardDetectedEventArgs : EventArgs
{
public string CardNumber { get; private set; }
public CardDetectedEventArgs(string cardNumber)
{
CardNumber = cardNumber;
}
}
}
4. 支付处理器 (BusTerminal/PaymentProcessor.cs)
using System;
using System.Data;
using BusTerminal.Database;
using BusTerminal.Models;
using BusTerminal.Utils;
namespace BusTerminal
{
public class PaymentProcessor
{
public event EventHandler<PaymentResult> PaymentCompleted;
public event EventHandler<string> PaymentFailed;
private DatabaseManager database;
private decimal baseFare = 2.00m; // 基础票价
public PaymentProcessor()
{
database = new DatabaseManager();
}
public PaymentResult ProcessPayment(string cardNo, int busId)
{
PaymentResult result = new PaymentResult();
try
{
// 1. 验证卡片
Card card = database.GetCard(cardNo);
if (card == null)
{
result.Success = false;
result.Message = "卡片不存在";
PaymentFailed?.Invoke(this, result.Message);
return result;
}
// 2. 检查卡片状态
if (!card.IsActive)
{
result.Success = false;
result.Message = "卡片已停用";
PaymentFailed?.Invoke(this, result.Message);
return result;
}
// 3. 检查余额
decimal fare = CalculateFare(card, busId);
if (card.Balance < fare)
{
result.Success = false;
result.Message = "余额不足";
PaymentFailed?.Invoke(this, result.Message);
return result;
}
// 4. 扣费
decimal newBalance = card.Balance - fare;
bool updateSuccess = database.UpdateCardBalance(cardNo, newBalance);
if (!updateSuccess)
{
result.Success = false;
result.Message = "扣费失败";
PaymentFailed?.Invoke(this, result.Message);
return result;
}
// 5. 记录交易
Transaction transaction = new Transaction
{
CardNo = cardNo,
BusId = busId,
Amount = fare,
Balance = newBalance,
TransactionTime = DateTime.Now,
Result = "成功"
};
database.AddTransaction(transaction);
// 6. 返回结果
result.Success = true;
result.CardNo = cardNo;
result.CardHolder = card.HolderName;
result.Amount = fare;
result.Balance = newBalance;
result.Message = "支付成功";
PaymentCompleted?.Invoke(this, result);
return result;
}
catch (Exception ex)
{
result.Success = false;
result.Message = $"系统错误: {ex.Message}";
PaymentFailed?.Invoke(this, result.Message);
return result;
}
}
private decimal CalculateFare(Card card, int busId)
{
decimal fare = baseFare;
// 根据卡类型调整票价
switch (card.CardType)
{
case CardType.Student:
fare *= 0.5m; // 学生卡半价
break;
case CardType.Senior:
fare *= 0.3m; // 老年卡3折
break;
case CardType.VIP:
fare *= 0.8m; // VIP卡8折
break;
}
// 根据线路调整票价
// 这里可以根据busId查询线路信息,调整票价
return fare;
}
public bool RechargeCard(string cardNo, decimal amount)
{
try
{
Card card = database.GetCard(cardNo);
if (card == null) return false;
decimal newBalance = card.Balance + amount;
return database.UpdateCardBalance(cardNo, newBalance);
}
catch
{
return false;
}
}
}
public class PaymentResult
{
public bool Success { get; set; }
public string CardNo { get; set; }
public string CardHolder { get; set; }
public decimal Amount { get; set; }
public decimal Balance { get; set; }
public string Message { get; set; }
}
}
5. 数据库管理 (Database/DatabaseManager.cs)
using System;
using System.Data;
using System.Data.SQLite;
using BusTerminal.Models;
namespace BusTerminal.Database
{
public class DatabaseManager
{
private string connectionString = "Data Source=busterminal.db;Version=3;";
public DatabaseManager()
{
InitializeDatabase();
}
private void InitializeDatabase()
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
// 创建卡片表
string createCardTable = @"
CREATE TABLE IF NOT EXISTS Cards (
CardNo TEXT PRIMARY KEY,
HolderName TEXT NOT NULL,
CardType INTEGER NOT NULL,
Balance DECIMAL(10,2) NOT NULL DEFAULT 0,
IsActive INTEGER NOT NULL DEFAULT 1,
IssueDate DATETIME NOT NULL,
ExpiryDate DATETIME NOT NULL
)";
// 创建交易表
string createTransactionTable = @"
CREATE TABLE IF NOT EXISTS Transactions (
TransactionId INTEGER PRIMARY KEY AUTOINCREMENT,
CardNo TEXT NOT NULL,
BusId INTEGER NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
Balance DECIMAL(10,2) NOT NULL,
TransactionTime DATETIME NOT NULL,
Result TEXT NOT NULL,
FOREIGN KEY (CardNo) REFERENCES Cards(CardNo)
)";
// 创建公交车表
string createBusTable = @"
CREATE TABLE IF NOT EXISTS Buses (
BusId INTEGER PRIMARY KEY AUTOINCREMENT,
BusNumber TEXT NOT NULL UNIQUE,
Route TEXT NOT NULL,
DriverName TEXT,
IsActive INTEGER DEFAULT 1
)";
using (SQLiteCommand cmd = new SQLiteCommand(createCardTable, conn))
{
cmd.ExecuteNonQuery();
}
using (SQLiteCommand cmd = new SQLiteCommand(createTransactionTable, conn))
{
cmd.ExecuteNonQuery();
}
using (SQLiteCommand cmd = new SQLiteCommand(createBusTable, conn))
{
cmd.ExecuteNonQuery();
}
}
}
public Card GetCard(string cardNo)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
string sql = "SELECT * FROM Cards WHERE CardNo = @CardNo";
using (SQLiteCommand cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@CardNo", cardNo);
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return new Card
{
CardNo = reader["CardNo"].ToString(),
HolderName = reader["HolderName"].ToString(),
CardType = (CardType)Convert.ToInt32(reader["CardType"]),
Balance = Convert.ToDecimal(reader["Balance"]),
IsActive = Convert.ToBoolean(reader["IsActive"]),
IssueDate = Convert.ToDateTime(reader["IssueDate"]),
ExpiryDate = Convert.ToDateTime(reader["ExpiryDate"])
};
}
}
}
}
return null;
}
public bool UpdateCardBalance(string cardNo, decimal newBalance)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
string sql = "UPDATE Cards SET Balance = @Balance WHERE CardNo = @CardNo";
using (SQLiteCommand cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@Balance", newBalance);
cmd.Parameters.AddWithValue("@CardNo", cardNo);
return cmd.ExecuteNonQuery() > 0;
}
}
}
public void AddTransaction(Transaction transaction)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
string sql = @"
INSERT INTO Transactions (CardNo, BusId, Amount, Balance, TransactionTime, Result)
VALUES (@CardNo, @BusId, @Amount, @Balance, @TransactionTime, @Result)";
using (SQLiteCommand cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@CardNo", transaction.CardNo);
cmd.Parameters.AddWithValue("@BusId", transaction.BusId);
cmd.Parameters.AddWithValue("@Amount", transaction.Amount);
cmd.Parameters.AddWithValue("@Balance", transaction.Balance);
cmd.Parameters.AddWithValue("@TransactionTime", transaction.TransactionTime);
cmd.Parameters.AddWithValue("@Result", transaction.Result);
cmd.ExecuteNonQuery();
}
}
}
public DataTable GetTransactions(DateTime startDate, DateTime endDate, string cardNo = "")
{
DataTable dt = new DataTable();
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
string sql = @"
SELECT t.*, c.HolderName, b.BusNumber, b.Route
FROM Transactions t
LEFT JOIN Cards c ON t.CardNo = c.CardNo
LEFT JOIN Buses b ON t.BusId = b.BusId
WHERE t.TransactionTime BETWEEN @StartDate AND @EndDate";
if (!string.IsNullOrEmpty(cardNo))
{
sql += " AND t.CardNo = @CardNo";
}
sql += " ORDER BY t.TransactionTime DESC";
using (SQLiteCommand cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@StartDate", startDate);
cmd.Parameters.AddWithValue("@EndDate", endDate);
if (!string.IsNullOrEmpty(cardNo))
{
cmd.Parameters.AddWithValue("@CardNo", cardNo);
}
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
return dt;
}
public bool AddCard(Card card)
{
try
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
string sql = @"
INSERT INTO Cards (CardNo, HolderName, CardType, Balance, IsActive, IssueDate, ExpiryDate)
VALUES (@CardNo, @HolderName, @CardType, @Balance, @IsActive, @IssueDate, @ExpiryDate)";
using (SQLiteCommand cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@CardNo", card.CardNo);
cmd.Parameters.AddWithValue("@HolderName", card.HolderName);
cmd.Parameters.AddWithValue("@CardType", (int)card.CardType);
cmd.Parameters.AddWithValue("@Balance", card.Balance);
cmd.Parameters.AddWithValue("@IsActive", card.IsActive);
cmd.Parameters.AddWithValue("@IssueDate", card.IssueDate);
cmd.Parameters.AddWithValue("@ExpiryDate", card.ExpiryDate);
return cmd.ExecuteNonQuery() > 0;
}
}
}
catch
{
return false;
}
}
}
}
6. 后台管理系统 (ManagementSystem/MainForm.cs)
using System;
using System.Drawing;
using System.Windows.Forms;
using ManagementSystem.CardManagement;
using ManagementSystem.TransactionQuery;
using ManagementSystem.Reports;
namespace ManagementSystem
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.Text = "智能公交管理系统";
this.Size = new Size(1200, 800);
this.StartPosition = FormStartPosition.CenterScreen;
// 菜单栏
MenuStrip menuStrip = new MenuStrip();
ToolStripMenuItem systemMenu = new ToolStripMenuItem("系统管理");
systemMenu.DropDownItems.Add("用户管理", null, UserManagement_Click);
systemMenu.DropDownItems.Add("角色管理", null, RoleManagement_Click);
systemMenu.DropDownItems.Add("权限设置", null, PermissionSettings_Click);
systemMenu.DropDownItems.Add(new ToolStripSeparator());
systemMenu.DropDownItems.Add("系统设置", null, SystemSettings_Click);
ToolStripMenuItem cardMenu = new ToolStripMenuItem("卡片管理");
cardMenu.DropDownItems.Add("发卡登记", null, IssueCard_Click);
cardMenu.DropDownItems.Add("卡片充值", null, RechargeCard_Click);
cardMenu.DropDownItems.Add("卡片挂失", null, ReportLoss_Click);
cardMenu.DropDownItems.Add("卡片解挂", null, UnlockCard_Click);
cardMenu.DropDownItems.Add("卡片注销", null, CancelCard_Click);
ToolStripMenuItem queryMenu = new ToolStripMenuItem("查询统计");
queryMenu.DropDownItems.Add("交易查询", null, TransactionQuery_Click);
queryMenu.DropDownItems.Add("充值查询", null, RechargeQuery_Click);
queryMenu.DropDownItems.Add("日报表", null, DailyReport_Click);
queryMenu.DropDownItems.Add("月报表", null, MonthlyReport_Click);
queryMenu.DropDownItems.Add("年报表", null, YearlyReport_Click);
ToolStripMenuItem busMenu = new ToolStripMenuItem("车辆管理");
busMenu.DropDownItems.Add("车辆信息", null, BusInfo_Click);
busMenu.DropDownItems.Add("线路管理", null, RouteManagement_Click);
busMenu.DropDownItems.Add("司机管理", null, DriverManagement_Click);
menuStrip.Items.AddRange(new ToolStripItem[] { systemMenu, cardMenu, queryMenu, busMenu });
// 主界面布局
TabControl tabControl = new TabControl
{
Dock = DockStyle.Fill
};
// 仪表盘标签页
TabPage dashboardTab = new TabPage("仪表盘");
CreateDashboardTab(dashboardTab);
// 快速操作标签页
TabPage quickActionsTab = new TabPage("快速操作");
CreateQuickActionsTab(quickActionsTab);
tabControl.TabPages.Add(dashboardTab);
tabControl.TabPages.Add(quickActionsTab);
this.Controls.Add(menuStrip);
this.Controls.Add(tabControl);
}
private void CreateDashboardTab(TabPage tab)
{
// 统计卡片
Panel statsPanel = new Panel
{
Dock = DockStyle.Top,
Height = 120
};
// 今日交易笔数
CreateStatCard(statsPanel, "今日交易笔数", "1,234", Color.Blue, 10, 10);
// 今日交易金额
CreateStatCard(statsPanel, "今日交易金额", "¥2,468.00", Color.Green, 220, 10);
// 活跃卡片数
CreateStatCard(statsPanel, "活跃卡片数", "5,678", Color.Orange, 430, 10);
// 在线车辆数
CreateStatCard(statsPanel, "在线车辆数", "45/50", Color.Purple, 640, 10);
// 图表区域
Panel chartPanel = new Panel
{
Dock = DockStyle.Fill
};
// 交易趋势图
Label lblChart = new Label
{
Text = "交易趋势图(最近7天)",
Location = new Point(10, 10),
Size = new Size(200, 30),
Font = new Font("微软雅黑", 12, FontStyle.Bold)
};
// 这里可以集成图表控件,如Chart控件
PictureBox chartPlaceholder = new PictureBox
{
Location = new Point(10, 50),
Size = new Size(800, 400),
BorderStyle = BorderStyle.FixedSingle,
BackColor = Color.White
};
chartPanel.Controls.Add(lblChart);
chartPanel.Controls.Add(chartPlaceholder);
tab.Controls.Add(statsPanel);
tab.Controls.Add(chartPanel);
}
private void CreateStatCard(Panel parent, string title, string value, Color color, int x, int y)
{
Panel card = new Panel
{
Location = new Point(x, y),
Size = new Size(200, 100),
BorderStyle = BorderStyle.FixedSingle,
BackColor = Color.White
};
Label lblTitle = new Label
{
Text = title,
Location = new Point(10, 10),
Size = new Size(180, 20),
ForeColor = Color.Gray
};
Label lblValue = new Label
{
Text = value,
Location = new Point(10, 40),
Size = new Size(180, 40),
Font = new Font("微软雅黑", 20, FontStyle.Bold),
ForeColor = color
};
card.Controls.Add(lblTitle);
card.Controls.Add(lblValue);
parent.Controls.Add(card);
}
private void CreateQuickActionsTab(TabPage tab)
{
FlowLayoutPanel flowPanel = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
FlowDirection = FlowDirection.LeftToRight,
WrapContents = true,
Padding = new Padding(20)
};
string[] actions = {
"发卡登记", "卡片充值", "卡片挂失", "卡片解挂",
"交易查询", "充值查询", "日报表", "月报表",
"车辆信息", "线路管理", "司机管理", "系统设置"
};
foreach (string action in actions)
{
Button btn = new Button
{
Text = action,
Size = new Size(120, 80),
Margin = new Padding(10),
Font = new Font("微软雅黑", 10),
BackColor = Color.LightBlue,
FlatStyle = FlatStyle.Flat
};
btn.Click += (s, e) => QuickAction_Click(action);
flowPanel.Controls.Add(btn);
}
tab.Controls.Add(flowPanel);
}
#region 事件处理
private void QuickAction_Click(string action)
{
switch (action)
{
case "发卡登记":
using (IssueCardForm form = new IssueCardForm())
{
form.ShowDialog();
}
break;
case "卡片充值":
using (RechargeCardForm form = new RechargeCardForm())
{
form.ShowDialog();
}
break;
case "交易查询":
using (TransactionQueryForm form = new TransactionQueryForm())
{
form.ShowDialog();
}
break;
case "车辆信息":
using (BusInfoForm form = new BusInfoForm())
{
form.ShowDialog();
}
break;
// 其他操作...
}
}
private void IssueCard_Click(object sender, EventArgs e)
{
using (IssueCardForm form = new IssueCardForm())
{
form.ShowDialog();
}
}
private void RechargeCard_Click(object sender, EventArgs e)
{
using (RechargeCardForm form = new RechargeCardForm())
{
form.ShowDialog();
}
}
private void TransactionQuery_Click(object sender, EventArgs e)
{
using (TransactionQueryForm form = new TransactionQueryForm())
{
form.ShowDialog();
}
}
private void SystemSettings_Click(object sender, EventArgs e)
{
using (SystemSettingsForm form = new SystemSettingsForm())
{
form.ShowDialog();
}
}
#endregion
}
}
7. 数据模型 (Models/Card.cs)
using System;
namespace BusTerminal.Models
{
public enum CardType
{
Regular = 0, // 普通卡
Student = 1, // 学生卡
Senior = 2, // 老年卡
VIP = 3, // VIP卡
Staff = 4 // 员工卡
}
public class Card
{
public string CardNo { get; set; }
public string HolderName { get; set; }
public CardType CardType { get; set; }
public decimal Balance { get; set; }
public bool IsActive { get; set; }
public DateTime IssueDate { get; set; }
public DateTime ExpiryDate { get; set; }
public Card()
{
IsActive = true;
IssueDate = DateTime.Now;
ExpiryDate = DateTime.Now.AddYears(5); // 默认5年有效期
Balance = 0;
}
public string GetCardTypeName()
{
switch (CardType)
{
case CardType.Regular: return "普通卡";
case CardType.Student: return "学生卡";
case CardType.Senior: return "老年卡";
case CardType.VIP: return "VIP卡";
case CardType.Staff: return "员工卡";
default: return "未知";
}
}
public bool IsExpired()
{
return DateTime.Now > ExpiryDate;
}
public bool HasInsufficientBalance(decimal fare)
{
return Balance < fare;
}
}
public class Transaction
{
public int TransactionId { get; set; }
public string CardNo { get; set; }
public int BusId { get; set; }
public decimal Amount { get; set; }
public decimal Balance { get; set; }
public DateTime TransactionTime { get; set; }
public string Result { get; set; }
}
public class Bus
{
public int BusId { get; set; }
public string BusNumber { get; set; }
public string Route { get; set; }
public string DriverName { get; set; }
public bool IsActive { get; set; }
}
public class Station
{
public int StationId { get; set; }
public string StationName { get; set; }
public string Address { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
}
8. 项目文件 (BusTerminal/BusTerminal.csproj)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{YOUR-PROJECT-GUID}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>BusTerminal</RootNamespace>
<AssemblyName>BusTerminal</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Drawing" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data.SQLite">
<HintPath>..\packages\System.Data.SQLite.Core.1.0.117\lib\net472\System.Data.SQLite.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="MainForm.cs" />
<Compile Include="MainForm.Designer.cs" />
<Compile Include="RFIDReader.cs" />
<Compile Include="PaymentProcessor.cs" />
<Compile Include="DataSync.cs" />
<Compile Include="Hardware\DisplayController.cs" />
<Compile Include="Hardware\VoiceController.cs" />
<Compile Include="Hardware\PrinterController.cs" />
<Compile Include="Database\DatabaseManager.cs" />
<Compile Include="Database\CardRepository.cs" />
<Compile Include="Database\TransactionRepository.cs" />
<Compile Include="Models\Card.cs" />
<Compile Include="Models\Transaction.cs" />
<Compile Include="Models\Bus.cs" />
<Compile Include="Models\Station.cs" />
<Compile Include="Utils\Encryption.cs" />
<Compile Include="Utils\Logger.cs" />
<Compile Include="Utils\Validator.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
参考代码 基于RFID的智能公交刷卡系统 www.youwenfan.com/contentcsv/112065.html
三、系统功能说明
1. 核心功能模块
| 模块 |
功能描述 |
| 车载终端 |
RFID刷卡、支付处理、语音播报、小票打印 |
| 卡片管理 |
发卡、充值、挂失、解挂、注销 |
| 交易处理 |
实时扣费、余额检查、交易记录 |
| 数据同步 |
离线交易上传、黑名单同步 |
| 报表统计 |
日报表、月报表、年报表 |
| 系统管理 |
用户权限、车辆管理、线路管理 |
2. RFID卡片类型
| 卡片类型 |
折扣 |
适用人群 |
| 普通卡 |
无折扣 |
普通乘客 |
| 学生卡 |
5折 |
在校学生 |
| 老年卡 |
3折 |
65岁以上老人 |
| VIP卡 |
8折 |
VIP客户 |
| 员工卡 |
免费 |
公交员工 |
3. 硬件配置清单
| 设备 |
型号 |
数量 |
| RFID读卡器 |
RC522/PN532 |
1台 |
| 显示屏 |
7寸LCD触摸屏 |
1个 |
| 语音模块 |
SYN6288 |
1个 |
| 热敏打印机 |
58mm热敏打印机 |
1个 |
| 工控主板 |
Raspberry Pi/Intel NUC |
1个 |
| 电源模块 |
12V/5A稳压电源 |
1个 |
4. 通信协议
// RFID读卡器通信协议示例
public class RfidProtocol
{
// 读卡命令
public static byte[] ReadCardCommand = { 0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 写卡命令
public static byte[] WriteCardCommand = { 0xAA, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 解析卡号
public static string ParseCardNumber(byte[] response)
{
if (response.Length >= 8)
{
return BitConverter.ToString(response, 4, 4).Replace("-", "");
}
return "";
}
}
5. 安全措施
- 数据加密:所有敏感数据使用AES加密
- 通信安全:HTTPS/SSL加密传输
- 防重复刷卡:同一卡片2秒内不能重复刷卡
- 黑名单机制:挂失卡片立即加入黑名单
- 交易验证:双重验证确保交易完整性
6. 部署建议
- 车载终端:安装在公交车上,通过4G/5G网络连接服务器
- 后台服务器:部署在云端或本地机房,提供API服务
- 数据库:使用MySQL/PostgreSQL集群,确保数据安全
- 监控系统:实时监控终端状态和交易情况