• Nem Talált Eredményt

fejezet - SD kártya olvasó .NET Gadgeteer használatával

használatával

10. fejezet - SD kártya olvasó .NET Gadgeteer használatával

10.1. A feladat célja

A feladat célja megismertetni a .NET Gadgeteer eszköz SD kártya olvasójának működését. A feladathoz szükség lesz a FEZ Spider panelre, SD kártya olvasó modulra, nyomógombra és a T35-ös kijelzőre.

A program az elindulást követően egy gombnyomásra vár. A gombnyomás következtében, amennyiben van az SD kártya olvasó modulban kártya, kilistázza a fájlokat. A forráskódban lehetőség van különféle fájltípusok szűrésére is.

10.2. A projekt létrehozása

Első lépésként nyissunk meg a Visual Studio 2010-et, majd hozzunk létre egy új .NET Gadgeteer Application-t:

Fájl→New→Project→Visual C# / Gadgeteer

Adjunk nevet a projektnek, mondjuk „SD_card_reader”, illetve egy elérési utat. Az „OK” gomb megnyomása után a következő képernyő fog megjelenni:

10.1. ábra - A Visual Studio 2010 új .NET Gadgeteer projekt

A program alapértelmezés szerint a FEZ Hydra panelt rakja ki, ezt le kell cserélnünk a Spider-re, hiszen azzal dolgozunk. Töröljük ki a Hydrát és a bal oldali toolbox alján lévő „Gadgeteer Mainboards” kategóriából válasszuk a FEZ Spider-t.

A toolbox GHI Electronics kategóriájából húzzuk a képernyőre a következő elemeket:

Button Display_T35 SDCard UsbClientDP

A Spider alaplapjára kattintsunk jobb egérrel, majd a „Connect all modules”-ra. Az összekapcsolt panelünknek így kell kinéznie:

10.2. ábra - az összekötött rendszer

10.3. A program megírása

Az alapértelmezetten létrejön egy Program.cs nevű fájl, amibe a fejlesztőkörnyezet automatikusan egy programkódot generál. A kommentezést nyugodtan töröljük ki, a generált kód a következőképpen néz ki:

namespace SD_card_reader {

public partial class Program {

void ProgramStarted() {

Debug.Print("Program Started");

} } }

A Program nevű osztály az alkalmazás főosztálya, ezen belül a ProgramStarted() függvény indul el elsőként.

Futtatásnál, a Debug.Print("Program Started") utasítás hatására a kimeneti ablakban (output window) megjelenik a felirat. A Program.cs fájlban találhatunk további sorokat. Ezek különböző osztálykönyvtár referenciák, amiket az alkalmazás használni fog. A példakódban külön nem jelöltem.

SD kártya olvasó .NET Gadgeteer használatával

Futtassuk a projektet! Ehhez az USB kliensbe (piros modul, ami az 1. portba van illesztve) csatlakoztassuk az USB kábel megfelelő végét, majd a másikat a PC egyik USB portjába. Az F5 gomb megnyomása után a program lefordul (build) és az eszközre feltöltődik (deploy). Amennyiben az előbbi folyamatok hiba nélkül lefutottak, a kimeneti ablakban megjelenik a "Program Started" felirat. A kijelző képernyője fekete és az alapértelmezés szerinti gyári információkat írja ki (verzió, felbontás). Ennek az az oka, hogy még nincs használatban a modul.

Egészítsük ki a programot, hogy az elindulást követően egy üzenet jelezze a felhasználó számára a működéssel kapcsolatos teendőket! Ehhez először helyezzünk el két változót a ProgramStarted() függvény előtti sorokba:

private Text txtMessage;

private Text txtResults;

A Text változó szöveges objektum tárolására alkalmas, amit a megjelenítő felület ki tud rajzolni. A txtMessage fogja tartalmazni az instrukciót. Előre gondolkodva, a txtResult majd a kilistázott fájlokat fogja megjeleníteni.

Folytatólagosan (a ProgramStarted() függvény után) hozzunk létre egy privát visszatérés nélküli függvényt:

SetupWindow(). Ez fog felelni a kezdőképernyő beállításáért. Illesszük be a következő kódrészletet:

private void SetupWindow() {

Window window = display.WPFWindow;

Font baseFont = Resources.GetFont(Resources.FontResources.NinaB);

Canvas canvas = new Canvas(); objektumot. Ez fogja a képernyőt képviselni. Ez egy WPF ablak lesz, ami lehetővé teszi a rajzolást. A következő sorban létrehozunk egy Font típust. Ez tartalmazza a szövegmegjelenítési információkat, ami alapján az egyes szövegek megjelenítésre kerülnek. Ehhez az erőforrásokból (Resources) le kell kérnünk az adott karakter típust, ami jelen esetben a NinaB.

A Canvas az az objektum, amire a tényleges kirajzolás történni fog, azaz olyan, mint egy vászon. Ahhoz, hogy a program tudja használni, hozzá kell csatolni a megjelenítő felülethez, ezt hajtja végre a window.child = canvas utasítás.

Az előbb definiáltunk két Text változót. Ezeket létre is kell hozni. A konstruktor mindkét esetben ugyanúgy fog kinézni: new Text(baseFont, string.Empty). Tehát megadjuk, hogy milyen kartertípust használjon, valamint egy üres szöveget. Amint létrejött a txtResults változó, hozzáadjuk a vászonhoz. A canvas.Children.Add(txtResults) ezt hajtja végre. A megjelenítést tudjuk pozícionálni. A következő két sor beállítja a bal felső saroktól számított pozíciót a le, illetve bal irányokban. Ezt nem a példányon, hanem a Canvas osztály segítségével tesszük. A txtMessage létrehozása és beállítása hasonló módon történik. A különbség az, hogy fix szélességet állítunk be, illetve bekapcsoljuk a hosszú sorok tördelése opciót (wrap). Természetesen az előző szöveg alá pozícionáljuk.

Hívjuk meg ezt a függvényt a ProgramStarted() metódusból. Amennyiben futtatjuk a programot, a következő képet kell látnunk a kijelzőn:

10.3. ábra - a kezdőképernyő

A következő lépésben írjuk meg a gombnyomás lekezeléséért felelős programrészt. Ehhez a ProgramStarted() függvényen belül, a SetupWindow() sor alá írjuk be a következőt:

button.ButtonPressed += new Button.ButtonEventHandler(button_ButtonPressed);

A button változón keresztül érhetjük el a panelhez fizikailag csatlakoztatott gombot. Ez rendelkezik egy ButtonPressed, azaz egy gomb megnyomva eseménnyel. Erre az eseményre való feliratkozást valósítja meg a fenti kódrészlet. Érdemes úgy csinálni, hogy beírjuk a += karakterekig, majd két darab tab gombot nyomunk.

Így a környezet legenerálja a kód többi részét, valamint az eseményt kezelő függvényt (button_buttonPressed).

A program további részében az SD kártyáról való beolvasást kell megoldani. Ennek úgy kell működnie, hogy vagy minden fájltípust kiír, vagy pedig előre meghatározott kiterjesztéseket vizsgál. A feldolgozás folyamatábrája a következő:

10.4. ábra - a beolvasás folyamatábrája

SD kártya olvasó .NET Gadgeteer használatával

Hozzuk létre a következő két függvényt:

private string[] GetFiles(string[] extensions, bool recursive) {

GT.StorageDevice storage = sdCard.GetStorageDevice();

for (int i = 0; i < extensions.Length; i++) {

if((extensions[i])[0] != '.')

extensions[i] = '.' + extensions[i];

}

ArrayList list = new ArrayList();

DirectoryTraversal(storage, null, extensions, recursive, list);

return (string[])list.ToArray(typeof(string));

}

private void DirectoryTraversal(GT.StorageDevice storage, string path,

A 10.3. ábrán felvázolt folyamat megvalósítását végzi a két függvény.

GetFiles:

Ez a függvény valósítja meg a fájlok keresését. A bemenő paraméterei: egy string tömb, ami kiterjesztéseket tartalmaz (vagy * karaktert, ha minden fájltípus érdekel), a másik pedig egy logikai változó, ami az alkönyvtárak bejárásának engedélyezését jelzi.

Első lépésként létrehozunk egy StorageDevice típusú változót, amin keresztül a csatlakoztatott SD kártyához hozzáférünk. Egy for ciklussal végigmegyünk a kiterjesztéseken és leellenőrizzük a helyes formátumot (legyen előtte pont). Létrehozunk egy listát, amibe a kritériumoknak megfelelő fájlok nevei fognak kerülni. Meghívjuk a directoryTraversal függvényt, ami a tényleges listafeltöltést végzi. Végül ezt a listát string tömbbé konvertálva visszatérési értékként visszaadjuk.

DirectoryTraversal:

A függvény visszatérés nélküli, a paraméterei: egy storage példány, amivel hozzáférünk a kártyához; egy elérési út, ahol a fájlkeresést végezzük; a kiterjesztés tömb; az alkönyvtárban való keresést engedélyező logikai változó;

valamint a lista, amibe a fájlok nevei kerülnek.

Első lépésben egy files nevű változóba az átadott elérési út alapján lekérjük a fájlok listáját. Ez nem fogja tartalmazni a könyvtárakat, illetve null paraméterre a gyökérkönyvtárban keres.Végig kell nézni az összes fájlt és meg kell állapítani, hogy a kiterjesztésük benne van-e az extensions tömbben. Ehhez egy foreach ciklust használunk, ami minden elemen végigmegy. Az egyes elemekre a következő vizsgálatokat végezzük el:

SD kártya olvasó .NET Gadgeteer használatával

Ha az összes kiterjesztésű fájlt listázni akarjuk (.*), akkor mindenképpen hozzáadjuk a fájlt a listához. Ellenkező esetben végigmegyünk a kiterjesztés tömb minden elemén, és megnézzük, hogy az aktuálisan vizsgált fájl kiterjesztése benne van-e. A fájlok kiterjesztését egy beépített függvény segítségével elérhetjük, így nem kell külön string művelettel előállítani: System.IO.Path.GetExtension(fileName). Amennyiben benne volt a kiterjesztés, akkor a fájlt hozzáadjuk a listához, ha nem, vesszük a következő fájlt és kezdődik elölről a vizsgálat.

Végezetül, megvizsgáljuk az alkönyvtárakban való keresés lehetőségét. Ha ezt engedélyeztük, akkor lekérjük az aktuális elérési útban lévő könyvtárakat. Ezeken egyenként végigmenve rekurziót hajtunk végre, azaz meghívjuk a DirectoryTraversal függvényt. Az előzőleg átadott paramétereket használjuk fel újra, annyi kivétellel, hogy a path változó helyére a ciklusban lévő aktuális könyvtár elérési útját adjuk meg. Így az újrahívás után, már nem a gyökérben, hanem abban fog keresni. Belátható, hogy ha mély könyvtárstruktúra van kialakítva, akkor a rekurzió miatt hosszú ideig is eltarthat az összes fájl listázása. A fenti algoritmuson ezért még lehetne optimalizálni, pl. a kiterjesztés vizsgálatnál egy új logikai változót bevezetve csak egyszer kellene megvizsgálni, hogy minden típust keresünk-e. Ugyanis egy logikai változó értékének eldöntése jóval gyorsabb, mint két string összehasonlítása. A másik dolog, hogy minden fájlnál–amennyiben csak bizonyos kiterjesztésekre vagyunk kíváncsiak–, végig megyünka tömb összes elemén. Ennek a problémának a megoldását az olvasóra bízom, amennyiben érdekli!

Most már megvannak a keresést végző programrészek is. Még két dologra van szükségünk, hogy teljes legyen a program. Létre kell hoznunk egy tömböt, amibe a kiterjesztések kerülnek, valamint biztosítani kell, hogy a gomb megnyomására a fenti függvények működésbe lépjenek. Tehát vegyük fel a következő változót:

private string[] fileExtension = {"txt,pdf"}; //"*"

Ez fogja tartalmazni a már említett fájl kiterjesztéseket, ami alapján a listázást végezzük. Tartalmazhat csak egy

* karaktert is, ekkor, mint már említettem, minden kiírásra kerül a képernyőre. A button_ButtonPressed függvénybe helyezzük el a következő kódrészletet:

if (sdCard.IsCardMounted) {

Elsőként megvizsgáljuk, hogy az SD kártya használatra kész állapotban van-e. Erre szolgál az IsCardMounted változója.Ha nincs, akkor nincs mit vizsgálni. Ellenkező esetben egy textFiles nevű változóba lekérjük a fájlokat a már megírt GetFiles függvénnyel. A korábban létrehozott és képernyőhöz csatolt Text típusú txtResult változó szövegének beállítjuk a megtalált fájlok számát. A következő lépésben létrehozunk ez új string típusú változót, amibe összefűzzük vesszővel elválasztva a fájlokat. Az utolsó if feltételben megvizsgáljuk van-e találat.

Amennyiben igen, akkor az utolsó vesszőt eltávolítjuk. Végezetül a txtMessage változó szövegét beállítjuk az imént összefűzött string-re. Így minden szükséges adat most már megjelenik a képernyőn. Optimalizálásképpen, a fileList string helyett lehetne StringBuilder-t használni.

Az elkészült programról néhány kép működés közben:

10.5. ábra - csak txt-re keresés

10.6. ábra - minden fájlra keresés

SD kártya olvasó .NET Gadgeteer használatával

10.7. ábra - nincs találat

10.4. A teljes forráskód

using System;

using Microsoft.SPOT;

using Microsoft.SPOT.Presentation;

using Microsoft.SPOT.Presentation.Controls;

using Microsoft.SPOT.Presentation.Media;

using GT = Gadgeteer;

using GTM = Gadgeteer.Modules;

using Gadgeteer.Modules.GHIElectronics;

using System.Collections;

namespace SD_card_reader {

public partial class Program {

private Text txtMessage;

private Text txtResults;

private string[] fileExtension = {"txt,pdf"}; //"*"

void ProgramStarted() {

Debug.Print("Program Started");

SetupWindow();

button.ButtonPressed += new

Button.ButtonEventHandler(button_ButtonPressed);

}

private void SetupWindow() {

Window window = display.WPFWindow;

Font baseFont = Resources.GetFont(Resources.FontResources.NinaB);

private void button_ButtonPressed(Button sender,

Button.ButtonState state)

private void DirectoryTraversal(GT.StorageDevice storage, string path,

SD kártya olvasó .NET Gadgeteer használatával

{

if System.IO.Path.GetExtension(fileName).ToLower()==

extension.ToLower())

list.Add(fileName);

} } }

if (recursive) {

var directories = storage.ListDirectories(path);

foreach (var directoryName in directories) directoryTraversal(storage,

directoryName, extensions, recursive, list);

} } } }

10.5. Felkészülést segítő kérdések

1. Milyen eszközök szükségesek a kártyaolvasó elkészítéséhez, mi a szerepük?

2. Hogyan történik a könyvtárak rekurzív feltérképezése?

3. A feldolgozás milyen lépésekből áll?

10.6. Felhasznált irodalom

1. Simon Monk: GettingStartedwith .NETGadgeteer, 2012 O’Reilly Media, ISBN: 978-1-449-32823-8 2. GusIssa: .NETGadgeteerUltimateGuide, 2011, GHI Electronics

3. Nicolas Villar, James Scott, Steve Hodges, KerryHammil, and Colin Miller: .NETGadgeteer: A Platform forcustomDevices, 2012 Springer Berlin Heidelberg, ISBN:978-3-642-31204-5

4. http://10rem.net/blog/2012/03/13/setting-up-ethernet-on-the-net-gadgeteer

http://my.safaribooksonline.com/book/-/9781449330682/4dot-web-messenger/id2837110

5. http://10rem.net/blog/2011/10/24/getting-started-with-the-net-gadgeteer---part-1-background-setup-and-hello-world

6. http://www.netmf.com/gadgeteer/

7. http://www.w3schools.com/tags/ref_httpmethods.asp 8. http://www.w3.org/TR/html401/interact/forms.html

Irodalomjegyzék

[1] Xilinx Inc. (weblink: http://www.xilinx.com)

[2] Xilinx Spartan-3E FPGA Family Data Sheet Xilinx Inc., DS312 2012-10-29 (weblink:

http://www.xilinx.com/support/documentation/data_sheets/ds312.pdf)

[3] Digilent Diigiillentt Basys2 Board Refference Manuall Digilent, Inc., Doc: 502-155, 2010-11-11