THIẾT KẾ PHẦN MỀM TRÊN PC

Một phần của tài liệu hệ thống giữ xe sử dụng thẻ chip (Trang 51)

3.8.1 Giới thiệu tổng quan

3.8.1.2 Ngôn ngữ sử dụng

Để lập trình phần mềm trên máy vi tính, ta chọn ngôn ngữ C#. Lý do chọn ngôn ngữ C#:

Ngôn ngữ C# khá đơn giản, chỉ khoảng hơn 80 từ khóa và hơn mười mấy kiểu dữ liệu được dựng sẵn.

Với sự trợ giúp của bộ phần mềm Microsoft Visual Studio 2008 thì việc lập trình truyền nhận dữ liệu với vi điều khiển trở nên đơn giản hơn.

Lập trình điều khiển và nhận hình ảnh từ camera được hỗ trợ nhiều nhờ các thư viện và các lớp được định nghĩa sẵn.

Thiết kế giao diện dễ dàng với nhiều công cụ hỗ trợ sẵn từ phần mềm Microsoft Visual Studio 2008.

Kết nối, xử lý cơ sở dữ liệu nhanh chóng và mạnh mẽ.

3.8.1.3 Cơ sở dữ liệu

a. Giới thiệu

Để quản lý cơ sở dữ liệu dùng cho hệ thống ta dùng cơ sở dữ liệu SQL với phiên bản SQLExpress 2008.

SQLExpress là bộ công cụ quản lý cơ sở dữ liệu miễn phí của Microsoft.

Để có thể quản lý cơ sở dữ liệu một cách trực quan hơn thì cần thêm công cụ SQL Server Managerment Studio Express. Đây cũng là một công cụ miễn phí của Microsoft.

Lý do ta chọn hệ cơ sở dữ liệu SQL là vì đây là hệ cơ sở dữ liệu rất phổ biến, có thể hoạt động được với nhiều phiên bản các hệ điều hành. Ngoài ra tốc độ truy nhập dữ liệu cũng rất nhanh.

b. Phân tích cơ sở dữ liệu

Để lưu lại tất cả các hoạt động liên quan trong quá trình hệ thống làm việc, ta cần phải lưu lại không ít dữ liệu. Việc quản lý và xử lý dữ liệu sẽ nhanh hơn nếu ta biết lựa chọn các dữ liệu nên lưu hay không nên lưu.

Những dữ liệu cần thiết phải quản lý:

 Dữ liệu thẻ giữ xe

 Dữ liệu xe ra vào bãi giữ xe

 Dữ liệu người dùng

 Dữ liệu các máy trong hệ thống

* Dữ liệu thẻ giữ xe

Dữ liệu thẻ giữ xe quan trọng nhất là mã số của thẻ. Ngoài ra để tiện cho việc quản lý của người sử dụng thì dữ liệu về ngày cập nhật thẻ hay đăng ký thẻ với hệ thống cũng là dữ liệu nên lưu lại.

Để lưu lại dữ liệu thẻ giữ xe ta tạo một bảng trong cơ sở dữ liệu với các trường cần thiết như: chỉ mục, mã cơ sở, mã số thẻ, ngày đăng ký.

Bảng 3.1 Bảng dữ liệu thẻ

Trường Kiểu dữ liệu Chức năng

ID Integer Chỉ mục

Site_Code Integer Mã cơ sở

Card_ID Integer Mã số thẻ

Add_Date Varchar(50) Ngày đăng ký

Chỉ mục là số thứ tự không trùng lặp của từng thẻ. Chỉ mục là một số nguyên không âm. Vậy ta chọn kiểu dữ liệu Integer cho trường chỉ mục và cho trường này tự tăng.

Site_Code là trường lưu mã cơ sở của thẻ. Mã cơ sở của thẻ là con số có 8 bit (1 byte), nghĩa là có 255 (không tính số 0) số Site_Code có thể có. Ở đây ta cũng chọn kiểu dữ liệu Integer cho trường này.

Card_ID là mã số thẻ. Mã số thẻ là con số có 16 bit (2 byte), nghĩa là có 65535 (không tính số 0) số Card_ID có thể có. Ta cũng chọn kiểu dữ liệu Integer cho trường này.

Riêng trường ngày đăng ký, ta cũng có thể chọn kiểu datetime (kiểu ngày tháng) nhưng việc xử lý dạng này trong quá trình lập trình thì trở nên phức tạp hơn là sử dụng kiểu dữ liệu chuỗi. Dữ liệu ngày tháng lưu trong cơ sở dữ liệu ta lưu lại không phải ở dạng ngày tháng như ngày/tháng/năm mà ta lưu lại ngày tháng bằng một con số gọi là Tick. Đây là con số đổi từ dạng ngày tháng sang dạng số nguyên (kiểu long) lớn hơn kiểu dữ liệu integer. Nên ta cũng không thể sử dụng kiểu dữ liệu integer cho trường này được mà ta sẽ sử dụng kiểu dữ liệu chuỗi varchar với độ dài là 50 ký tự.

Như vậy, từ mã cơ sở và mã thẻ thì ta có thể tính được có tất cả 255*65535 = 16711425 thẻ có thể có. Giá trị lớn nhất của trường chỉ mục này là 2147483647. Nghĩa là số dòng dữ liệu tối đa trong bảng dữ liệu thẻ có thể lên đến 2147483647, đáp ứng được cho số lượng thẻ cần lưu.

* Dữ liệu xe ra vào bãi giữ xe

Trong quá trình hoạt động, ta cần lưu lại các xe ra vào bãi giữ xe, để biết được xe nào đang gửi giữ, xe nào gửi bằng thẻ nào… Ngoài ra còn phải lưu lại thời điểm ra vào của xe các xe được gửi, xe được gửi bởi máy nào và nhân viên nào trực lúc đó. Đó là những thông tin hết sức cần thiết nếu muốn hệ thống được bảo mật. Các trường cần thiết ở bảng dữ liệu xe ra vào bãi giữ xe:

Bảng 3.2 Bảng dữ liệu xe ra vào bãi giữ xe

Trường Kiểu dữ liệu Chức năng

ID Integer Chỉ mục

PCID Varchar(10) Tên máy tính

Site_Code Integer Mã cơ sở

Card_ID Integer Mã số thẻ

Enter_Time Varchar(50) Thời gian vào bãi xe Leave_Time Varchar(50) Thời gian ra bãi xe

User_ID Varchar(10) Tên nhân viên trực ca

Trường chỉ mục ở bảng dữ liệu này cũng không thể thiếu, nó giúp cho việc xác định các dòng dữ liệu nhằm mục đích cập nhật dữ liệu được từ phần mềm. Trường này có kiểu dữ liệu Integer.

Trường Site_Code và Card_ID cũng cùng chức năng như trong bảng dữ liệu thẻ giữ xe. Nó giúp lưu lại dữ liệu của thẻ và được thiết lập kiểu dữ liệu là Varchar(50).

Các trường PCID, DVID, Enter_Time, Leave_Time, User_ID có cùng kiểu dữ liệu Varchar và có độ dài 10 ký tự, riêng Enter_Time và Leave_Time là hai trường lưu giá trị thời gian dạng Tick nên có độ dài 50.

Như vậy cũng như ở bảng Dữ liệu thẻ giữ xe, dòng chỉ mục quyết định số lượng tối đa các dòng dữ liệu có trong bảng. Dòng chỉ mục được định kiểu dữ liệu Integer nên cũng có giá trị lớn nhất là 2147483647.

c. Bảng dữ liệu người dùng

Dữ liệu người dùng cũng cần thiết phải quản lý. Đây là những dữ liệu dùng để đăng nhập vào phần mềm. Ta dùng những dữ liệu này để phân biệt các nhân viên với nhau và từ đó phân quyền được cho nhân viên đó để sử dụng đúng các chức năng trên phần mềm.

Các dữ liệu cần thiết phải lưu như: tên nhân viên, mã số thẻ dùng để đăng nhập, loại nhân viên.

Bảng 3.3 Bảng dữ liệu người dùng

Trường Kiểu dữ liệu Chức năng

ID Integer Chỉ mục

Card_ID Varchar(50) Mã thẻ (bao gồm cả mã cơ sở và mã thẻ)

User_Type Integer Mã loại nhân viên

Trường chỉ mục cũng không thể thiếu và cũng có chức năng như trong hai bảng dữ liệu trên. Trường Full_Name và Card_ID có kiểu dữ liệu Varchar độ dài 50. Ở đây Card_ID có kiểu dữ liệu khác với Card_ID ở hai bảng dữ liệu trên và chức năng cũng không giống với hai bảng trên. Card_ID ở bảng dữ liệu này lưu lại cả mã cơ sở và mã thẻ nên ta dùng kiểu dữ liệu Varchar để lưu.

User_Type là trường chỉ mã loại nhân viên, nó giúp lưu lại loại của nhân viên ấy. Nhờ trường này mà phần mềm có thể nhận biết và phân quyền cho nhân viên.

d. Bảng dữ liệu các máy trong hệ thống

Đây là bảng dữ liệu lưu lại thông tin các máy tính hoạt động trong hệ thống. Đây là thông tin phụ giúp cho nhân viên quản lý được thông tin gửi xe. Tuy vậy nó ta cũng cần nó vì sẽ tiện hơn nhiều nếu ta phân biệt được các máy trong toàn hệ thống.

Bảng 3.4 Bảng dữ liệu các máy trong hệ thống

Trường Kiểu dữ liệu Chức năng

ID Integer Chỉ mục

PCID Varchar(50) Mã máy

PC_Name Varchar(50) Tên máy

Trường ID cũng có chức năng như trong các bảng dữ liệu khác. Trường PCID và PC_Name nhằm lưu lại mã số của máy và tên của máy tính. Nên ta chọn kiểu dữ liệu chuỗi ký tự Varchar cho hai trường này với độ dài là 50.

3.8.3 Giao diện chương trình

Hình 3.36 Giao diện phần mềm trên PC

3.8.4 Thiết kế chi tiết

Sau đây là thiết kế chi tiết của một số module quan trọng:

3.8.4.2 Module Khởi động

a. Chức năng

Chức năng của module này là khai báo các thư viện, khai báo biến và khởi tạo giá trị của các biến.

b. Lưu đồ chi tiết

Hình 3.37 Lưu đồ chi tiết module khởi động

c. Đoạn code chính yếu

using System; using System.Drawing; using System.IO; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Drawing.Imaging; using DirectShowLib; using System.Xml; using System.Threading; using System.Data; using System.Data.SqlClient;

privatebool db_check = false;

privateCapture[] cam = newCapture[4] { null, null, null, null }; string char_test_module = "w";

privateint[] device = newint[4] { -1, -1, -1, -1 };

privatebool[] device_bussy = new bool[4] { false, false, false, false

}; //false: free, true: bussy

privatebool[] working_device = newbool[2]{false,false};

privatestring[] device_working = new string[2] { "dv001", "dv002"

};

privatestring[,] arr_user_id = newstring[2,3] { {"","",""}, {"","",""

}};

privatebyte[] btn_function = newbyte[4]{8,7,8,7}; //chua ma so chuc nang nut an

privatebyte[] btn_function_previous = newbyte[4] { 3, 0, 3, 0 };

//chua ma so chuc nang nut an cu~

privatebool[] wait_msg_card_not_leave = newbool[2]{false,false}; privatebool[] wait_msg_card_not_enter = newbool[2] { false, false

};

privatebool[] wait_msg_card_not_exist = newbool[2] { false, false

};

privatebool[] wait_msg_card_has_error = newbool[2] { false, false

};

privatebool[] wait_msg_logout = new bool[2] { false, false }; privatebool wait_check_module_connect = false;

privatebool[] device_need_reset = newbool[2] { true, true }; privatestring[] btn_function_string = new string[20] {

/*0*/"Đổi chiều làn xe", /*1*/"",

/*1 the nay chua gui xe*/"Đồng ý", /*3 khong chuc nang (disabled)*/"", /*4*/"Đóng thông báo",

/*6 the nay xay ra loi trong qua khu...*/"Không hiện nữa", /*7*/"Chọn nhân viên",

/*8*/"Đăng nhập", /*9*/"",

/*10 dang xuat phien lam viec*/"Tôi muốn đăng xuất", /*11*/"", /*12*/"", /*13*/"", /*14*/"", /*15*/"", /*16*/"", /*17*/"", /*18*/"", /*19*/"", };

privatestring img_dir; privatestring pc_id = ""; constint VIDEODEVICE = 0; constint VIDEOWIDTH = 640; constint VIDEOHEIGHT = 480;

constint VIDEOBITSPERPIXEL = 5;

3.8.4.3 Module kiểm tra kết nối

a. Chức năng

Module kiểm tra kết nối có vai trò rất quan trọng. Trong module này có hai chức năng chức là kiểm tra kết nối giữa phần mềm với cơ sở dữ liệu SQL và kiểm tra kết nối giữa phần mềm với module.

Do phần mềm hoạt động đều cần phải có hai kết nối này luôn sẵn sàng, nên ngoài việc gọi module này sau bước khởi động thì trong lúc hoạt động cũng nên luôn phải kiểm tra kết nối bằng cách thường xuyên gọi module này.

b. Lưu đồ chi tiết

c. Đoạn code chính yếu

privatevoid check_sql_conecttion() { string new_server;

try { new_server = get_xml_node("server", "connect_db"); } catch { new_server = "null"; }

sqlcon = new SqlConnection("Data Source=" + new_server +

";Initial Catalog=db_htgx;User ID=htgx;Password=123"); bool sqlcon_check = false;

while (db_check == false) { try

{ lbx_notice.Items.Insert(0, "[!] Đang kiểm tra kết nối với cơ

sở dữ liệu.");

sqlcon = newSqlConnection("Data Source=" + new_server + ";Initial Catalog=db_htgx;User ID=htgx;Password=123");

//if (open_sql_con() == false) check_module_connection();

sqlcon.Open(); //sqlcon.Close();

lbx_notice.Items.Insert(0, "[!] Kết nối thành công với cơ sở

dữ liệu.");

save_xml_node("server", "connect_db", new_server); db_check = true; }

catch

{ lbx_notice.Items.Insert(0, "[x] Kết nối thất bại với cơ sở dữ

liệu.");

new_server =

Microsoft.VisualBasic.Interaction.InputBox("Kết nối cơ sở dữ liệu thất

bại từ máy chủ: " + new_server + "\nNhập tên hoặc IP máy chủ mới:",

if (new_server.Length==0)new_server = "null"; } } }

privatevoid reset_com(string com) { serialPort1.Close();

serialPort1.PortName = com; try

{ serialPort1.Open();

lbx_notice.Items.Insert(0, "[!] Kết nối thành công cổng: " + com);

wait_check_module_connect = true;

serialPort1.Write(get_xml_node("char","serialport")); } catch

{ lbx_notice.Items.Insert(0, "[x] Kết nối thất bại cổng: " + com); byte tmp = (byte)(byte.Parse(com.Substring(com.Length - 1))+1);

if (tmp > 5) tmp = 1;

lbx_notice.Items.Insert(0, "[!] Đang tự kiểm tra kết nối qua

cổng COM" + tmp.ToString());

now_com = "COM" + tmp.ToString(); timer_test_com.Enabled = true; } }

privatebool check_module_connection() { try

{ serialPort1.Open();

serialPort1.Write(char_test_module); }

catch { lbx_notice.Items.Insert(0, "[x] Không kết nối được với

cổng COM"); }

returntrue; }

if (time_wait_module_response > 3) { time_wait_module_response = 0; wait_check_module_connect = false;

lbx_notice.Items.Insert(0, "[x] Module không phản hồi, vui

lòng kiểm tra lại dây kết nối!"); byte tmp =

(byte)(byte.Parse(now_com.Substring(now_com.Length - 1)) + 1); if (tmp > 5) tmp = 1;

lbx_notice.Items.Insert(0, "[!] Đang tự kiểm tra kết nối qua

cổng COM" + tmp.ToString());

now_com = "COM" + tmp.ToString(); timer_test_com.Enabled = true; } }

3.8.4.4 Module Đăng nhập hệ thống

a. Chức năng

Sau khi kiểm tra các kết nối thành công, công đoạn tiếp theo bắt người dùng đăng nhập hệ thống. Nhưng trước khi đăng nhập cần cần lấy danh sách các nhân viên trong hệ thống. Việc lấy sẵn danh sách nhằm dễ dàng kiểm tra đăng nhập và để đưa danh sách tên nhân viên vào danh sách chọn đăng nhập.

Dữ liệu vào: mã số thẻ được quét, tên nhân viên được chọn. Dữ liệu ra: đăng nhập thành công hay thất bại.

Từ dữ liệu ra mà chương trình cho phép sử dụng phần mềm hoặc vẫn bắt người dùng đăng nhập.

b. Lưu đồ chi tiết

Hình 3.39 Lưu đồ chi tiết module đăng nhập

c. Đoạn code chính yếu

privatevoid get_user_list() { string sql_cmd; SqlCommand cmd;

SqlDataReader sqlReader;

sql_cmd = "SELECT * FROM tbuser ORDER BY id"; cmd = newSqlCommand(sql_cmd, sqlcon);

//if (open_sql_con() == false) check_module_connection();

close_sql_con(); open_sql_con();

sqlReader = cmd.ExecuteReader(); byte i = 0;

while (sqlReader.Read())

{ user_list[i, 0] = sqlReader["full_name"].ToString(); user_list[i, 1] = sqlReader["user_id"].ToString(); user_list[i, 2] = sqlReader["card_id"].ToString(); user_list[i, 3] = sqlReader["user_type"].ToString(); i++; }

//if (close_sql_con() == false) check_module_connection();

cbx_user_list_1.Items.Clear(); cbx_user_list_2.Items.Clear(); for (byte j = 0; j < i; j++)

{ cbx_user_list_1.Items.Add(newKeyValueData(user_list[j, 0], user_list[j, 1], user_list[j, 2],user_list[j,3]));

cbx_user_list_2.Items.Add(newKeyValueData(user_list[j, 0], user_list[j, 1], user_list[j, 2], user_list[j, 3])); }

cbx_user_list_1.SelectedIndex = 0; cbx_user_list_2.SelectedIndex = 0; } if (device_id == 0) { KeyValueData k; k = (KeyValueData)cbx_user_list_1.SelectedItem; if (txt_user_card_id_1.Text == k.CardId ) { txt_user_card_id_1.Text = ""; pn_login_1.Visible = false;

btn_function[0] = 3; btn_function[1] = 0; arr_user_id[0,0] = k.CardId; arr_user_id[0, 1] = k.UserType; arr_user_id[0, 2] = k.Text; lbl_full_name_1.Text = cbx_user_list_1.Text; if (k.UserType == "0") admin_tool(true); } reset_camera(0); btn_pop(0); } if (device_id == 1) { KeyValueData k; k = (KeyValueData)cbx_user_list_2.SelectedItem; if (txt_user_card_id_2.Text == k.CardId) { txt_user_card_id_2.Text = ""; pn_login_2.Visible = false; btn_function[2] = 3; btn_function[3] = 0; arr_user_id[1,0] = k.CardId; arr_user_id[1, 1] = k.UserType; arr_user_id[1, 2] = k.Text; lbl_full_name_2.Text = cbx_user_list_2.Text; if (k.UserType == "0") admin_tool(true); }

3.8.4.5 Module Đăng ký thẻ

a. Chức năng

Chức năng của module này là đăng ký thẻ giữ xe với hệ thống. Mục đích của việc đăng ký thẻ là nhằm kiểm soát thẻ giữ xe. Chỉ những thẻ giữ xe đã được đăng ký với hệ thống thì mới có thể sử dụng được. Còn những thẻ khác nếu không đăng ký thì

Module này chỉ được gọi khi phần mềm đang ở công đoạn thêm thẻ mới, khi đó mã số thẻ đọc được từ đầu đọc sẽ được gửi tới để đăng ký thẻ. Những thẻ đã được sử dụng thì không được đăng ký lại. Những thẻ đã dùng làm thẻ nhân viên thì cũng không thể đăng ký được.

b. Lưu đồ chi tiết

c. Đoạn code chính yếu

if (checkBox1.Checked)

{ for (byte i = 0; i < 10; i++) {

if ((my_data_receive.site_code.ToString() + my_data_receive.card_id.ToString()) == user_list[i, 2]) { card_not_free = true;

break; } }

if (check_exist_card(my_data_receive.site_code, my_data_receive.card_id) == true) card_not_free = true; if (card_not_free == false)

{ add_card(my_data_receive.site_code, my_data_receive.card_id, now());

load_list_card();

lbx_notice.Items.Insert(0, "[!] Thêm thành công thẻ:

"+my_data_receive.site_code.ToString()+my_data_receive.card_id.ToStr

ing()); }

else {

MessageBox.Show("Không thể dùng thẻ này, vì nó đã

3.8.4.6 Module Thực thi lệnh nút ấn

a. Chức năng

Module này có chức năng là thực hiện những lệnh tương ứng với các nút ấn. Do mỗi thời điểm khác nhau thì nhiệm vụ của các nút ấn trên board điều khiển là khác nên việc xác định nhiệm vụ của từng nút là rất quan trọng.

Mặc khác ở board điều khiển có đến hai cặp nút ấn, nên cần phải kết hợp thêm xác định nút ấn ấy thuộc làn xe nào để thực thi lệnh phần mềm cho làn xe tương ứng ấy.

Tín hiệu vào: làn xe cần thực thi lệnh, nút ấn cần thực thi lệnh, mã lệnh của nút ấn ấy.

c. Đoạn code chính yếu

privatevoid btn_control(byte btn_id) { byte device_id = 0; switch (btn_id) { case 0: device_id = 0; break; case 1: device_id = 0; break; case 2: device_id = 1; break; case 3: device_id = 1; break; } switch (btn_function[btn_id]) { case 0: switch_direction(device_id); break; case 1: undo_function(device_id); break; case 2: break; case 3: accept_card_not_enter(device_id);

break; case 4: close_msg(device_id); break; case 5: accept_card_not_leave(device_id); break; case 6: break; case 7: if (device_id == 0) { if (cbx_user_list_1.SelectedIndex == cbx_user_list_1.Items.Count - 1) { cbx_user_list_1.SelectedIndex = 0; } else { cbx_user_list_1.SelectedIndex = cbx_user_list_1.SelectedIndex + 1; } } if (device_id == 1) { if (cbx_user_list_2.SelectedIndex == cbx_user_list_2.Items.Count - 1) { cbx_user_list_2.SelectedIndex = 0; } else { cbx_user_list_2.SelectedIndex =

Một phần của tài liệu hệ thống giữ xe sử dụng thẻ chip (Trang 51)