Cú pháp cơ bản của CSS:

Một phần của tài liệu điều khiển giám sát thiết bị qua internet sử dụng pic18f67j60 (Trang 31 - 66)

css_selector_1 {

thuộc_tính_1: giá_trị_của_thuộc_tính_1;

thuộc_tính_2: giá_trị_của_thuộc_tính_2;

thuộc_tính_n: giá_trị_của_thuộc_tính_n; } css_selector_2 { thuộc_tính_1: giá_trị_của_thuộc_tính_1; thuộc_tính_2: giá_trị_của_thuộc_tính_2; ... thuộc_tính_n: giá_trị_của_thuộc_tính_n; } ... css_selector_n { thuộc_tính_1: giá_trị_của_thuộc_tính_1; thuộc_tính_2: giá_trị_của_thuộc_tính_2; ... thuộc_tính_n: giá_trị_của_thuộc_tính_n; } 4.3.2.2. Ví dụ minh họa về mã CSS: body { background: #ffffff;

/* trang Web sẽ có nền màu trắng */

font-family: Verdana; /* font chữ mặc định là Verdana */ color: #ff0000; /* màu chữ mặc định là màu đỏ */ } 4.3.2.3. Thứ tự xếp lớp:

Tùy vào từng cách đặt khác nhau mà mức độ ưu tiên cho các style cũng khác nhau. Mức độ ưu tiên này tuân theo thứ tự sau:

- Style nội tuyến – Style đặt trong từng thẻ HTML riêng biệt.

- Stylet bên trong – Style đặt bên trong cặp thẻ <Head> … </Head>. - Style bên ngoài – Style đặt trong các file riêng có đuôi “.css”. - Style theo mặc định của trình duyệt.

4.3.3. CSS có tính kế thừa và tính kết hợp

4.3.3.1. Tính kế thừa:

Giả sử rằng ở đầu file styleshet.css khai báo cho Body có các thuộc tính sau: Body{

Font:Arial, Verdana; Background:#FF6600; }

Nhưng trong trường hợp muốn khai báo cho các đối tượng nhỏ hơn nằm trong đó như Sidebar: #sidebar{ With:300px; Padding:10px; Font:Tahoma,Verdana; }

Sau đoạn khai báo này thì Sidebar sẽ có thuộc tính: #sidebar{

background:#FF6600; with:300px;

padding: 10px;

font: Tohoma, Verdana; }

Như vậy, Sidebar đã kế thừa thuộc tính background của Body, và trong đó thuộc tính font là Tahoma đã đè lên thuộc tính font Arial ở lần khai báo trước.

4.3.3.2. Tính kết hợp:

Có thể định nghĩa nhiều CSS cùng một thuộc tính thay vì phải định nghĩa riêng lẻ từng cái một.

Ví dụ:

h1, h2,h3,h4{

Font-family: Tahoma,arial; Color:#D4D4D4;

}

Thay cho việc định nghĩa riêng biệt cho từng cái: h1{ Font-family: Tahoma,arial; Color: #D4D4D4; } h2{ Font-family: Tahoma,arial; Color:#D4D4D4; } ……… h4{ Font-family: Tahoma,arial; Color:#D4D4D4; } 4.4. Kỹ thuật AJAX

AJAX, viết tắt từ Asynchronous JavaScript and XML (JavaScript và XML không đồng bộ), là bộ công cụ cho phép tăng tốc độ ứng dụng web bằng cách cắt nhỏ dữ liệu và chỉ hiển thị những gì cần thiết, thay vì tải đi tải lại toàn bộ trang web. AJAX không phải một công nghệ đơn lẻ mà là sự kết hợp một nhóm công nghệ với nhau. Trong đó, HTML và CSS đóng vai hiển thị dữ liệu, mô hình DOM trình bày thông tin động, đối tượng XMLHttpRequest trao đổi dữ liệu không đồng bộ với máy chủ web, còn XML là định dạng chủ yếu cho dữ liệu truyền.

sự hợp lệ của thông tin, sửa đổi bộ nhớ, sau đó gửi lại một trang HTML hoàn chỉnh tới máy khách. Tuy nhiên, phương pháp này khá bất tiện và mất thời gian. Để khắc phục hạn chế trên, các chuyên gia phát triển giới thiệu hình thức trung gian - cơ chế xử lý AJAX - giữa máy khách và máy chủ. Điều này giống như việc tăng thêm một lớp giữa cho ứng dụng để giảm quá trình "đi lại" của thông tin và giảm thời gian phản ứng. Thay vì tải lại (refresh) toàn bộ một trang, nó chỉ nạp những thông tin được thay đổi, còn giữ nguyên các phần khác. Vì thế, khi duyệt một trang hỗ trợ AJAX, người sử dụng không bao giờ nhìn thấy một cửa sổ trắng (blank) và biểu tượng đồng hồ cát - dấu hiệu cho thấy máy chủ đang thực hiện nhiệm vụ. Ví dụ, trong một website ảnh, với ứng dụng truyền thống, toàn bộ trang chứa các ảnh sẽ phải mở lại từ đầu nếu có một thay đổi nào đó trên trang. Còn khi áp dụng AJAX, DHTML chỉ thay thế đoạn tiêu đề và phần vừa chỉnh sửa, do vậy tạo nên các giao dịch trơn tru, nhanh chóng.

Hình 22: Tương tác đồng bộ trong ứng dụng web truyền thống (trên) và dị bộ trong ứng dụng AJAX.

4.4.1. Ưu điểm

- Trong nhiều trường hợp, các trang web chứa rất nhiều nội dung thông thường trong trang. Nếu sử dụng các phương pháp truyền thống, những nội dụng đó sẽ phải nạp lại toàn bộ với từng yêu cầu. Tuy nhiên, nếu sử dụng Ajax, một ứng dụng web có thể chỉ yêu cầu cho các nội dung cần thiết phải cập nhật, do đó giảm lượng lớn băng thông và thời gian nạp lại trang. (adsbygoogle = window.adsbygoogle || []).push({});

- Việc dùng các yêu cầu không đồng bộ (asynchronous request) cho phép giao

diện người dùng của ứng dụng hiển thị trên trình duyệt giúp người dùng trải nghiệm sự

tương tác cao, với nhiều phần riêng lẻ.

- Việc sử dụng Ajax có thể làm giảm các kết nối đến server, do các script và các style sheet chỉ phải yêu cầu một lần.

4.4.2. Nhược điểm

- Các trang web được tạo động không được ghi vào bộ lưu lịch sử lướt web của trình duyệt, do đó nút "back" (quay lui) của trình duyệt sẽ mất tác dụng quay lại trang thái trước đó của trang sử dụng Ajax, thay vào đó sẽ quay lại trang web trước đó mà người dùng ghé thăm.

- Bất kỳ người dùng nào có trình duyệt không hỗ trợ Ajax hay JavaScript, hoặc đơn giản là đã bị vô hiệu hóa JavaScript, sẽ đương nhiên không thể sử dụng Ajax.

- Việc thiếu các chuẩn cơ bản của Ajax đồng nghĩa với việc không có nhiều sự chọn lựa thực tiễn tốt nhất để kiểm tra các ứng dụng Ajax. Các công cụ kiểm thử cho Ajax thường không hiểu các mô hình sự kiện, mô hình dữ liệu và giao thức của Ajax.

CHƯƠNG 5. TCP/IP STACK

5.1. Cấu trúc của TCP/IP Stack

TCP/IP Stack là ứng dụng của Microchip để tạo một Webserver nhúng, hoặc các giao thức giao tiếp Enthernet hiện hành. Bao gồm các giao thức truyền dữ liệu TCP, UDP. Và hỗ trợ các module khác như: IP, ICMP, DHCP, ARP và DNS.

TCP/IP cũng có các Module sử dụng cho lớp ứng dụng như: HTTP cho Web, SMTP cho gửi và nhận Email, SNMP cho giao thức trạng thái và điều khiển. Telnet cho điều khiển từ xa, TFTP.

Hình 23: Cấu trúc của Stack.

Ngoài những module chính giống như cấu trúc TCP/IP tham khảo thì Microchip đưa thêm vào Stack 2 module mới đó là StackTask và ARPTask. StackTask quản lý sự vận hành và tất cả các module của Stack. Trong khi đó, ARPTask quản lý các dịch vụ của lớp ARP ( Address Resolution Protocol).

5.2. Hoạt động của TCP/IP Stack

TCP/IP Stack hoạt động gần giống cấu trúc của hệ điều hành thời gian thực, tức là các nhiệm vụ sẽ được chia thành các tác vụ ( ở đây là TCP, UDP, Ping,…). Tất cả hoạt động của TCP/IP sẽ được một đồng hồ chung quản lí theo Time Split. Tức là có một Timer hệ thống (Timer1), cứ 1 khoảng thời gian ngắn sẽ ngắt (gọi là 1 TICK), khi bị ngắt, hệ thống sẽ treo lại, ngữ cảnh của tất cả các tác vụ được bộ lập lịch lôi ra, xem xét tác vụ nào được chạy theo kiểu chia sẻ thời gian (vì không có mức ưu tiên cho tác vụ). Sau đó cho phép tác vụ đó chiếm quyền thực thi của CPU. Đến TICK tiếp theo, hệ thống lại treo lại, và lại lôi ngữ cảnh ra, cứ tiếp tục như vậy mãi.

Với cơ chế hoạt động này, vi điều khiển được coi như một lúc có thể vừa thực hiện TCP, vừa thực hiện UDP, Ping,…vừa có thể là Server và Client cùng một lúc.

Vì vậy, PIC nếu được thiết lập ở chế độ TCP Server/Client sẽ hoạt động đồng thời cả 2 hoạt động này. Server lắng nghe kết nối từ Client nào đó trên mạng. Còn Client thì gửi lệnh mở cổng kết nối tới một Server nào đó cũng ở trên mạng, mà ta có thể xác lập được.

Vì vậy, hoạt động của các tác vụ là độc lập với nhau, không chịu ảnh hưởng lẫn nhau.

5.2.1. Các file cần thiết

- Main file: Lập trình trên file này.

- ARP.c và ARP.h: Các file này được sử dụng bởi Stack để xác định địa chỉ MAC kết hợp với địa chỉ IP.

- Delay.c và Delay.h: Những file này dùng để tạo độ trễ (delay) cho các hàm trong Stack.

- Physical layer files: Những file này dùng để cho phép một lớp vật lý cụ thể. - Helpers.c và Helpers.h: Các file này sẽ giải thích các hàm sử dụng trong Stack. - IP.c và IP.h: Các file này cung cấp các chức năng của lớp IP cho Stack.

- StackTsk.c và StackTsk.h –Các file này chứa code để khởi tạo Stack và thực hiện các hàm callback để cho Stack chạy.

- Tick.c và Tick.h: Các file này tạo ra một bộ đếm thời gian để thực hiện một số chức năng thời gian trong Stack.

- TCPIPConfig.h: Thiết lập cấu hình cho phần mềm.

- MAC.h: Cung cấp các macro và cấu trúc liên quan đến phần cứng của lớp MAC.

- TCPIP.h: Là file đính kèm trong Stack. Main file phải đính kèm file này.

5.2.2. Cấu trúc APP_CONFIG (adsbygoogle = window.adsbygoogle || []).push({});

Hầu hết các biến của ứng dụng liên quan của Stack được lưu trữ trong cấu trúc APP_CONFIG. Chúng bao gồm địa chỉ, cờ, chuỗi tên NBNS/SSID. Ta sẽ phải khai báo cho cấu trúc này và khởi tạo những giá trị mặc định của nó được định nghĩa trong file TCPIPConfig.h.

5.2.3. Main file

5.2.3.1. Khởi tạo

Đầu tiên, cần khởi tạo phần cứng như oscillators, LEDs, LCDs, PPS pins…

Sau đó, ta sẽ gọi các hàm khởi tạo từ thư viện. Đầu tiên là hàm TickInt(), nó khởi tạo tick timer để quản lý việc định thời của Stack. Sau đó là các hàm khởi tạo được thêm vào theo yêu cầu khởi tạo mà phần cứng yêu cầu. ví dụ như MPFSInt() để khởi tạo một cổng SPI (Serial Peripheral Interface Bus) để kết nối với thiết bị lưu trữ bộ nhớ để lưu trang web.

Khi phần cứng được khởi tạo, ta có thể cấu hình cho Stack. Hầu hết các biết của ứng dụng liên quan của Stack được lưu trong cấu trúc AppConfig. Lúc này ta có thể khởi tạo cấu trúc AppConfig theo những giá trị ta chọn.

Kết thúc khởi tạo Stack bằng việc gọi hàm StackInt(). Hàm này sẽ tự động khởi tạo các hàm cho firmware của các giao thức nếu chúng được định nghĩa trong file TCPIPConfig.h (ví dụ: TCPInit() cho TCP protocol, HTTPInt() cho HTTP hoặc HTTP2…).

5.2.3.2 Vòng lặp chính (main loop)

Khi chương trình được khởi tạo, ta sẽ tạo một vòng lặp vô hạn để thực hiện các nhiệm vụ của ứng dụng. Trong vòng lặp có hai hàm phải được gọi thường xuyên là StackTask() và StackApplications.

Hàm StackTask sẽ được gọi ở bất kỳ thời điểm nào khi Stack yêu cầu và sẽ điều khiển sự truyền nhận các gói dữ liệu.

Hàm StackApplications sẽ gọi những module ứng dụng được gọi. Ví dụ nếu sử dụng HTTP2 server, StackApplications sẽ tự động gọi hàm HTTPServer để thực hiện bất kỳ nhiệm vụ nào của HTTP đang được đợi.

Trong vòng lặp chính, ta có thể hỏi vòng cho bất kỳ sự thay đổi I/O nào và gọi bất kỳ một nhiệm vụ đặc biệt của ứng dụng mà bạn thực hiện. Để tránh tràn bộ đệm

trong phần cứng hoặc vi phạm sự định thời của giao thức, ta sẽ thực hiện các nhiệm vụ trong hàm callback với các trigger định thời cơ sở.

Ta sẽ phải gọi hàm StackTask mỗi khi gọi hàm StackApplications.

5.3. Các module của Stack và APIs

Microchip TCP/IP Stack bao gồm rất nhiều module. Để sử dụng được bất kì một module nào ta phải nắm rõ mục đích của nó và APIs.

5.3.1. Announce

Module này làm cho việc phát hiện ra thiết bị trở nên dễ dàng bằng việc truyền một tin nhắn UDP trên cổng 30303 bất kỳ khi nào địa chỉ IP thay đổi. Cổng được sử dụng bởi module Announce có thể được thay đổi được bằng cách sửa ở marco trong file Announce.c

#define ANNOUNCE_PORT 30303

Giao thức Announce được thiết kế để sử dụng cho phần mềm Ethernet Device Discoverer và MCHPDetect trên máy tính.

Module Announce bao gồm 2 hàm:

- AnnounceIP: AnnounceIP mở 1 socket UDP và truyền 1 gói tin đến cổng 30303. Nếu máy tính nằm trong cùng 1 subnet và tiện ích đang tìm kiếm 1 gói tin trên cổng UDP thì nó sẽ nhận gói tin này. Module này có nhiệm vụ thông báo việc thay đổi IP của mạch. Tin nhắn được hiển thị bằng phần mềm MCHPDetect.exe.

Cú pháp: void AnnounceIP();

- DiscoveryTask: Hàm này được sử dụng liên tục để lắng nghe tin nhắn trên cổng Announe. Các tin nhắn có thể gửi bằng cách sử dụng công cụ Microchip Device Discoverer.

Cú pháp: void DiscoveryTask();

Các hàm trên chỉ nên được truy cập bởi chính Stack. Ứng dụng không nên gọi các hàm trên và thay đổi các biến.

5.3.2. HTTP2 server

Module HTTP2 web server và file MPFS2 liên quan của nó cho phép mạch hoạt động như một webserver. Nó tạo ra một phương pháp đơn giản để hiển thị thông tin trạng thái và điều khiển các ứng dụng bằng cách sử dụng một trình duyệt web thông

Ba thành phần chính phục vụ cho module HTTP2 web server là: web pages, phần mềm MPFS2.exe và hai file nguồn CustomHTTPApp.c và HTTPPrint.h.

Hình 25: Sơ đồ khối Web pages (adsbygoogle = window.adsbygoogle || []).push({});

Bao gồm tất cả file HTML và ảnh kèm theo, CSS Stylesheets, các file JavaScript cần thiết để hiển thị một trang web.

Phần mềm MPFS2

- Phần mềm này được cung cấp bởi Microchip, các trang web được gói lại thành

một định dạng và lưu trữ trong bộ nhớ chương trình flash nội hoặc bộ nhớ ngoài. Chương trình này sẽ tìm các biến động trong các trang web và tự động cập nhật các biến này trong file HTTPPrint.h.

- Nếu bộ nhớ ngoài được sử dụng, phần mềm MPFS2 sẽ tạo ra một file BIN và

có thể tải trực tiếp lên mạch. Còn nếu dữ liệu được lưu trong bộ nhớ chương trình flash thì phần mềm MPFS2 sẽ tạo ra một file đuôi .c và được chèn vào project.

- Khi các biến động được thêm vào hoặc bỏ đi, phần mềm MPFS2 sẽ cập nhật

cho file HTTPPrint.h. Sau đó ta phải dịch lại project để đảm bảo các biến mới đã được thêm vào project.

Hình 26: Phần mềm MPFS2

File CustomHTTPApp.c

Thực hiện các ứng dụng của web. Nó mô tả đầu ra cho các biến động ( thông qua hàm callbacks HTTPPrint_varname), phân tích dữ liệu được gửi thông qua trang web forms.htm ( sử dụng 2 hàm HTTPExecuteGet và HTTPExecutePost) và xác nhận thông tin truy cập ( bằng hàm HTTPAuthenticate).

File HTTPPrint.h

File này được tạo tự động bởi phần mềm MPFS2. Nó định nghĩa tất cả các biến động và tạo ra một mối liên hệ giữa các biến trong trang web và hàm callbacks HTTPPrint_varname liên quan trong file CustomHTTPApp.c.

Module HTTP2 web server bao gồm các tính năng sau:

5.3.2.1. HTTP2 Dynamic Variables

Một trong những tính năng cơ bản nhất là cập nhật cái thông tin trạng thái của mạch đến người sử dụng thông qua giao diện web. Các lệnh trong mã HTML sẽ thông báo cho server thực hiện các hàm callbacks tại thời điểm đó.

Để tạo ra một biến động, chỉ cần đặt tên của biến bên trong một cặp ký tự (~) trong mã nguồn các trang web HTML (ví dụ: ~ myVariable ~). Khi ta chạy chương

trình MPFS2 để tạo ra các trang web, nó sẽ tự động định nghĩa những biến này trong file HTTPPrint.h. Ví dụ: sử dụng biến động builddate, mã HTML là:

<div class="examplebox code">~builddate~</div>

Hàm callback liên quan trong file CustomHTTPApp.c sẽ in giá trị lên trang web: void HTTPPrint_builddate(void)

{

TCPPutROMString(sktHTTP,(ROM void*)__DATE__);

}

5.3.2.2. HTTP2 Form Processing

Nhiều ứng dụng cần lấy dữ liệu từ người sử dụng. Một phương pháp thông thường sử dụng web forms.htm. web forms sử dụng 2 phương pháp GET và POST và HTTP2 web server hỗ trợ cả 2 phương pháp này.

- Phương pháp GET

• Phương pháp GET sẽ gán dữ liệu vào cuối URL. Dữ liệu này sẽ đứng

sau dấu chấm hỏi (?) ở trên thanh địa chỉ của trình duyệt. (Ví dụ:

http://mchpboard/form.htm?led1=0&led2=1&led3=0). Dữ liệu được gửi bằng phương pháp GET sẽ tự động được giải mã và được lưu trong biến mảng curHTTP.data. Vì dữ liệu này được lưu trong bộ nhớ, cho nên nó được giới hạn bởi kích thước của biến mảng curHTTP.data, mặc định là 100 bytes.

• Hàm callback HTTPExecuteGet sẽ xử lý dữ liệu này và thực hiện một số (adsbygoogle = window.adsbygoogle || []).push({});

nhiệm vụ cần thiết. Hai hàm HTTPGetArg và HTTPGetROMArg giúp dễ dàng lấy dữ liệu cho quá trình xử lý.

- Phương pháp POST

• Phương pháp POST truyền dữ liệu sau khi các header yêu cầu đã được

gửi. Dữ liệu không được hiển thị trong thanh địa chỉ của trình duyệt như phương pháp GET mà chỉ được nhìn thấy bởi một công cụ bắt gói tin.

Một phần của tài liệu điều khiển giám sát thiết bị qua internet sử dụng pic18f67j60 (Trang 31 - 66)