Singleton unit tesztelése, avagy .NET-ben miért nem 12 hónapból áll az év?

Íme mai vizsgálódásunk tárgya:

public class Calendar
{
  private static Calendar _instance;

  public static Calendar Instance { ... }

  private Calendar() { }

  public string[] GetMonthNames()
  {
    string[] names = DateTimeFormatInfo.CurrentInfo.MonthNames;
    return Sorter.Alphabetically(names);
  }

  // És még sokan mások...
}

Két dolgot mindenképp érdemes ezen az osztályon megfigyelni: van egy GetMonthNames metódusa és követi a Singleton tervezési mintát. A kettő nyilván összefügg, a metódust Calendar.Instance.GetMonthNames() formában lehet meghívni.

Mivel ez egy nagyobb, korosabb kódbázis része, mielőtt nagyobb változtatásokba fogunk, írjunk unit teszteket a GetMonthNames függvényhez. És itt rögtön belefutunk abba a problémába, hogy nem tudjuk izolálni a metódust, bele van drótozva, hogy függ a DateTimeFormatInfo és a Sorter osztályoktól. Az előbbi a .NET Framework része, az utóbbit viszont én találtam ki, ugyanebben a projektben van:

public static class Sorter
{
  public static string[] Alphabetically(string[] values)
  {
    return values.OrderBy(v => v).ToArray();
  }
}

Alakítsuk át, de úgy, hogy a Calendar osztályban lévő 123 másik metódust, és az őket hívó kódot ne kelljen módosítani.

A függőséget írjuk le egy interfésszel, mert azt könnyű lesz mockolni:

public interface ISorter
{
  string[] Alphabetically(string[] values);
}

Implementáljuk úgy, hogy visszavezetjük a már meglévő, static megvalósításra:

public class SorterWrapper : ISorter
{
  public string[] Alphabetically(string[] values) => Sorter.Alphabetically(values);
}

Másként fogalmazva eddig annyit csináltunk, hogy a static implementációt becsomagoltuk egy példányosítható implementációba, amit egy interfésszel is le tudunk írni.

Mivel az eredeti Calendar osztály nyilvános interfészéhez nem akarunk hozzányúlni, vezessünk be újabb osztályt, amit én fantáziadúsan MonthManager-nek neveztem el:

public class MonthManager
{
  private ISorter _sorter;

  public MonthManager(ISorter sorter)
  {
    this._sorter = sorter;
  }

  public string[] GetMonthNames()
  {
    string[] names = DateTimeFormatInfo.CurrentInfo.MonthNames;
    return this._sorter.Alphabetically(names);
  }
}

Ez már egy kiválóan tesztelhető osztály, aminek a függőségét a konstruktoron keresztül meg lehet adni. (Az egyszerűség kedvéért a DateTimeFormatInfo függőséggel itt szándékosan nem foglalkozom.)

Módosítani kell természetesen az eredeti Calendar osztályt is, de szerencsére csak a belső implementációját, a publikus interfésze változatlan marad:

public class Calendar
{
  // Singleton...

  private MonthManager _monthManager;

  private Calendar()
  {
    ISorter sorter = new SorterWrapper();
    this._monthManager = new MonthManager(sorter);  
  }

  public string[] GetMonthNames()
  {
    return this._monthManager.GetMonthNames();
  }
}

Ehhez már könnyen írhatunk teszteket:

public class IdentitySorter : ISorter
{
  public string[] Alphabetically(string[] values) => values;
}

[TestClass]
public class CalendarTests
{
  [TestMethod]
  public void ShouldReturnTwelveMonths()
  {
    MonthManager mgr = new MonthManager(new IdentitySorter());
    string[] months = mgr.GetMonthNames();
    Assert.AreEqual(12, months.Length);
  }
}

Igazán kár, hogy ez a teszt hibát fog jelezni, méghozzá mindig! Látod a hibát?

Nem? Mert nincs is! Ez feature 🙂

A .NET Frameworkben lévő System.Globalization.Calendar osztályt úgy tervezték, hogy mindenféle naptárt le tudjon írni, van is 11 származtatott osztálya, köztük például a GregorianCalendar. Természetesen az egyes naptárak máshogy értelmezhetik a hónap fogalmát és ennek megfelelően más lehet a számuk is. Ennek a támogatását pedig úgy sikerült megoldani, hogy a DateTimeFormatInfo osztály MonthNames tulajdonsága CurrentCulture-tól függetlenül mindig 13 (!) elemű tömböt ad vissza, ami a mi naptárunk esetén a 12 hónap nevét jelenti, a 13. elem pedig egy üres string. Mindezért persze nem a .NET a felelős, így van ez a Win32 API-ban is (lásd LOCALE_SMONTHNAME13 konstans) már jó rég óta.

Mutasd az importjaidat, megmondom, ki vagy

Na jó, azt talán nem, de arra utalhat, hogy mennyire karbantartható a kódod.

Írtál-e már ilyet:

import { SomeClass } from 'somelib';
...
const s = new SomeClass();

Vagy épp ilyet:

import * as someFunc from 'somelib';
...
const s = someFunc();

Ismerős, ugye? Én is rengetegszer írtam le hasonló sorokat, már csak azért is, mert minden könyvtár, library, package README-je pontosan ezt ajánlja. Van ezzel a mintával azonban (legalább) két probléma, ami miatt egy ideje igyekszem kerülni.

Függőségek kezelése

Ha gátlástalanul követed ezt a mintát, egyetlen alkalmazáson belül ugyanazt a sort le fogod írni százszor (vagy még többször). Miért? Mert viszi a kezed a copy-paste. Egyszerű, kényelmes, működik, nem igaz?

Így viszont nagyon nehéz lesz meghatározni, hogy a Te alkalmazásodnak pontosan mire is van szüksége, mitől függ, mi a dependenciája. A kódból mindössze annyi fog látszódni (de csak miután a kedvenc editorod “Find in All Files” funkciójával rákeresel), hogy a te kódod számtalan helyen hivatkozik egy külső csomagra, tehát az a csomag kell neki, függ tőle.

A valóság azonban más: a te alkalmazás logikádnak nem egy csomagra van szüksége, hanem egy funkcióra, egy logikára, amit történetesen egy külső csomagban implementált valaki más. Csakhogy ez most abszolút nem látszik a kódodból.

Íme egy konkrétabb példa a népszerű lodash csomaggal (*):

var _ = require('lodash');

Ez a csomag számtalan segédfüggvényt tartalmaz, szinte kizárt, hogy a te alkalmazásodnak mindegyikre szüksége van. Hogyan derítheted ki, hogy pontosan mit használsz? Rákeresel az összes fájlodban arra, hogy “_”.

De miért érdekes ez?

Például mert előfordulhat, hogy a hivatkozott csomagot le akarod cserélni valami másra. A nyílt forráskódú világban csomagok jönnek, mennek, ma még ez volt a legjobb, holnap már az lesz. Mert a régiben van egy bug, amit a fejlesztője már sosem fog kijavítani, vagy mert csak az új kompatibilis a legújabb Node verzióval, ami meg kell az appod többi részének. Vagy egyszerűen azért, mert frissen akarod tartani az appod kódját, és csak olyan dependenciákat szeretnél, amik körül aktív a közösség.

Szinte biztos, hogy nem fogsz találni egy másik könyvtárt, csomagot, ami API szinten kompatibilis a régivel. Olyanra van szükséged, ami funkció szinten kompatibilis, amit csak akkor tudsz kideríteni, ha pontosan ismered, hogy milyen funkcióra hivatkozol.

Ha ez megvan, akkor már csak az kell, hogy a lehető legkevesebb helyen kelljen átírni a hivatkozást a kódodban.

Ebből rögtön következik is a megoldás: törekedj arra, hogy a külső csomagokra való hivatkozásokat pontosan egyetlen helyen írd le a kódodban, azaz csomagold be őket egy osztályba, ami csak azokat a funkciókat publikálja, amire a te appod épít. Ez a módszer ráadásul olvashatóbbá is tudja tenni a kódodat, például “sha256()” helyett sokkal jobb függvény nevet is ki tudsz találni, igaz?

Ez a módszer nekem nagyon bevált, bár megjegyzem, nem követem fanatikusként, mert a framewörk szintű libek (pl. Angular) csomagolása túl nagy overhead lenne.

Tesztelhetőség

Ha egy osztályod importon keresztül hivatkozik egy másikra, akkor annak az osztálynak a unit tesztelése rémálom lesz, mert a hivatkozott osztály mockolásához a fájl betöltő logikát kell meghekkelni (például Mocking Request-Promise).

A megoldás nem újdonság: DI. Nem csak azt nyerjük vele, hogy könnyebb a tesztelés, de elég ránézni tipikusan a konstruktorra, és messziről látszik, hogy az adott osztály milyen más osztályoktól függ.

TypeScriptben például sokszor importálunk interface-eket csak azért, hogy legyen típus leírónk, ami miatt nagyon el tudnak szaporodni az import sorok, és gyakran nem látszik ránézésre, hogy melyik import hoz be funkcionalitást, és melyik csak típus információt. Ezen is segít a DI, ha törekszünk arra, hogy az importot csak típus leírásokhoz használjuk, minden másra ott a DI.

Mi ebben az újdonság?

Semmi az ég világon. Tényleg. Ennek ellenére mégsem akarnak kipusztulni ezek a kódok. A README-k, tutorialok, cikkek, blogok mindig az egyszerűségre fognak törekedni, olyan példákat fogsz bennük találni, amik segítenek a megértésben, az elindulásban. Nem az a céljuk, hogy vakon kövesd őket egy komolyabb alkalmazásban, ahol neked a karbantarthatóság és fenntarthatóság legalább olyan fontos, mint az egyszerűség. Amikor mégis leírsz egy ilyen sort legközelebb, gondolj arra, hogy ezzel mit veszel a nyakadba.

programming-is-thinking

 

*: A példa kicsit sántít, mert a lodash lehetővé tesz finomabb importokat is, csak épp kevesen használják.

 

Technorati-címkék: ,,

Mi lesz veled, Angular? Gondolatok az Angular Connect 2017 után

Angular Connect WelcomeA héten volt szerencsém részt venni a Londonban rendezett két napos Angular Connect 2017 konferencián, ebben a blog bejegyzésben pedig néhány ott hallott gondolatot és benyomást jegyzek fel részint magamnak emlékeztetőül, részint mert másnak is hasznosak lehetnek.

Az itt leírtak közül több nem szó szerint így hangzott el az előadók szájából, ez már az én kivonatom. A fontosabb előadásokról videófelvétel készült, azok megtekinthetőek a konferencia honlapján, az tekinthető hiteles forrásnak.

Át kell állni Angular@latest-re

Tisztán látszik, hogy a Google nagyon komolyan veszi az Angulart. Nem egyszerűen egy szabadidőben készülő open source projektről van szó, hanem egy olyan technológiáról, amibe azért invesztálnak, mert ők maguk is használják. Az egyik legnagyobb projektjük, a Google Cloud Console több, mint 10 ezer TypeScript és 3 ezer Angular fájlt tartalmaz.

Ez nem újdonság, így volt ez már az AngularJS idején is, ám ebből rögtön két dolog is következik.

Az első, hogy a fejlesztés nem áll meg. Jó elvek szerint készült, és stabil alapokon áll már az Angular, ezért látványos új funkciókkal egyre ritkábban fogunk találkozni, viszont a motorháztető alatt folyamatos fejlesztések történnek minden verzióban. Itt a legfontosabb célterület a teljesítmény, aminek egyik összetevője az első oldalbetöltés ideje (Time To Interactive), a másik pedig az alkalmazás futása közbeni sebesség. Egyik területen sem muzsikál rosszul az Angular már most sem, de a csapat nem állt meg, minden verzióban egyre kisebb a bundle és egyre gyorsabb az app.

Ehhez az kell, hogy nagyon sok energiát öljön a fejlesztőcsapat abba, hogy a fordító egyre okosabb legyen. Csak egy példa: a Build Optimizer a TypeScript fordító sajátosságait és képességeit kihasználva tovább pofozza a kódot annak érdekében, hogy a minification még hatékonyabb legyen. Olyan trükköket csinál a kód variálásával, amivel egy átlagos projektben egy átlagos fejlesztő biztosan nem foglalkozna, Google méretekben viszont már sokat számít, mi pedig élvezhetjük a sok munka és kutatás eredményeit.

A második következménye annak, hogy a Google komolyan használja az Angulart, hogy a folyamatos upgrade-nek egyszerűnek kell lennie. A fejlesztő csapat szerint az Angular API stabil, nem várhatók breaking change-ek, a v4-ről v5-re történő átállás például a legtöbb projektnél egyszerű verzió szám átírás a package.json-ban, és máris új fordítót kap az app és gyorsabban fog futni. A Google alkalmazásainak eddig 25%-át migrálták át Angularra.

Adott tehát egy olyan keretrendszer, ami minden verzióban egyre hatékonyabb lesz, és a készítők szerint nem lesz nehéz az átállás az újabb verziókra. Tegyük még hozzá azt a tényt, hogy az Angular fejlesztők száma már meghaladja az AngularJS fejlesztők számát, és hogy az AngularJS-be valószínűleg már sokáig nem fog invesztálni a Google és máris ott tartunk, hogy az élő projekteket célszerű átmigrálni Angularra, és folyamatosan frissíteni a legújabb verzióra, azaz most v5-re.

Upgrade, de hogyan?

Angular upgradeKérdés, hogy mit kezdjünk a meglévő AngularJS kódbázissal, hogyan vigyük át Angularra?

Hogy upgrade vagy újraírás a jó megoldás, arra nincs egyértelmű, minden esetre működő válasz. A hivatalos álláspont szerint meg kell vizsgálni a kódbázis sajátosságait és a jövőbeli várható üzleti elvárásokat, és ezeknek a fényében kell dönteni. Ez egyáltalán nem új és nem meglepő.

Nincs meglepetés sajnos azzal kapcsolatban sem, hogy az upgrade-et hogyan érdemes kivitelezni. Nincs varázsszer, az ngUpgrade "az" eszköz, legfeljebb azt lehet variálni, hogy milyen lépésben haladunk. Ha az alkalmazásunk több "oldalból" áll, akkor érdemes lehet route-onként haladni.

Összességében tehát az upgrade területén nincs más lehetőségünk, mint időt allokálni rá, és végigcsinálni. Itt szerintem a legtöbb projektben nem a mérnöki, hanem a menedzsment oldal fogja a nehézséget jelenteni.

Mit kezdjünk a nagy kódbázissal?

BazelA folyamatosan bővülő kódbázis egyre nagyobb kihívást jelent. Növekszik a repository mérete, növekszik a fordítási idő, egyre több csapat dolgozik ugyanazon a kódon, egyre nagyobb problémát okoz a függőségek kezelése. Mit lehet tenni?

A Google és a Facebook a monorepo híve, az alkalmazások és a library-k egyetlen nagy repository-ban vannak, míg az Amazonnál és a Netflixnél a microrepository-ban hisznek, ott minden független egymástól. Bármelyiket is valljuk, a választás feltételekhez kötött.

A Google részben nyilvánossá tette a saját fejlesztésű build eszközét, a Bazelt, aminek az erőssége, hogy a kód módosításai után csak azt fordítja újra, amire kihatással lehet. Ha nincs publikus API változás, akkor csak az adott komponenst, ha van, akkor pedig azokat, amik arra épülnek. Így elérték, hogy az edit-and-refresh élmény 2 másodperc alatt legyen. Ehhez persze az is kellett, hogy a kódot okosan szervezzék. Átlagosan náluk 1 package-ben 1 Angular modul van, 1 modul pedig átlagosan 1.5 komponenst tartalmaz. Ezzel nem csak azt nyerik, hogy gyors a build, hanem azt is, hogy tiszták az interfészek és dokumentáltak a függőségek.

Továbbá érdemes megnézni, hogy az Angular.io webhely buildeléséhez milyen megoldásokat választottak, és abból mit tudunk felhasználni. Ez az Angular alkalmazás náluk az állatorvosi ló, sok benchmark erre vonatkozik.

DRY vagy PRY?

A Don’t Repeat Yourself elv szerint üldözni kell minden kód duplikációt, ha valahol ismétlődő kódot találunk, akkor azt azonnal refaktorálnunk kell.

Ám ha ezt túl korán tesszük meg, lábon lőhetjük magunkat. A közös kódrészlet függőséget jelent, az interfésze contractként kezelendő, aminek a változásait csak megfelelő körültekintéssel és kommunikációval lehet elvégezni.

Ha van megbízható CI infrastruktúránk és jó teszt lefedettségünk, akkor ez költséges, de nem kockázatos. Kiszervezzük a közös kódot egy saját package-be, és ha bármi változik a package-ben, akkor újrafordítunk minden olyan alkalmazást és package-et, ami arra épül és újra is teszteljük azokat.

Ám ha nem vagyunk ilyen szerencsés helyzetben, akkor a túl korán alkalmazott DRY nem csak költséges, de kockázatos is lehet. Amíg tehát egy kódrészlet gyakran változik, addig inkább a Please Repeat Yourself (PRY) elvet érdemes követni, és csak a stabilizálódott kódokat kiszervezni közös helyre.

Mielőtt azonban vallást váltunk és elkezdjük követni a PRY elvet, érdemes feltenni magunknak a kérdést: vajon vissza fogunk-e térni később, és refaktoráljuk-e a már stabil kódrészletünket, vagy a jól működő dolgokhoz általában nem nyúlunk?

Zárójelben jegyzem meg, hogy a build eszközeink (TypeScript compiler, Angular compiler, Build Optimizer, minifier, Webpack stb.) nagyon agresszíven törekszenek a duplikáció kiszűrésére, “mutatványos környezetben” (production) tehát nem nagy a veszteség.

Hogyan teszteljünk nagy kódbázist?

CucumberA tesztelés terén nem tartogatott meglepetéseket a konferencia. Volt ugyan egy előadás a SerenityJS-ről, ami nem a Protractorban megszokott Page Objects elvet követi, hanem a Screenplay Patternt, de engem nem győzött meg.

Egyrészt azért, mert szerintem a Page Object módszert is lehet úgy használni, hogy a felsorolt problémákat elkerülje (kód mérete, olvashatósága, duplikációk stb.), másrészt pedig azért, mert nem látom, hogy ez miért jobb, mint a jól bevált Gherkin-Cucumber páros.

Ami viszont fontos – bár nem új – gondolat az előadásból, hogy a teszteket igenis tervezni kell. A jól megtervezett teszt esetekből lesznek a jól megtervezett teszt implementációk, azaz a karbantartható teszt kód.

Mi várható 2018-ban?

A fordító és a runtime folyamatos fejlesztésén kívül az Angular csapat természetesen újabb funkciókkal is bővíti a keretrendszert, amiből a PWA, az Angular Universal és az Angular Elements kapott nagyobb teret a konferencián.

PWA

PWAA PWA, vagy teljes nevén Progressive Web Apps, a legújabb (?) név arra a jelenségre, hogy webes technológiákkal készített és az interneten hosztolt programkód olyan felhasználói élményt nyújtson, mint egy telepített, vastag kliens alkalmazás. Technológiai szinten az újdonságot a Service Worker jelenti, ami biztosítja az offline működés feltételeit. Ezt a komponenst az Angular csapat becsomagolta egy @angular/service-worker package-be, ami lehetővé teszi, hogy nagyon kényelmesen készítsünk Angularral PWA-t. A CLI 1.6 bétájában már megjelenik a –service-worker kapcsoló, későbbi verziókban pedig várható, hogy ez lesz az alapértelmezett, tehát érdemes készülni rá.

A PWA nem egy fekete-fehér terület, vannak hátrányai (például verzió frissítés), ami miatt egyáltalán nem biztos, hogy minden esetben megéri használni. Érdemes viszont megismerkedni vele és szem előtt tartani mint lehetőséget (és mint biztonsági tényezőt is), mert jelentősen növelhetjük vele a felhasználói élményt.

Angular Universal

Angular Universal

A 4.0 verziótól már az Angular részeként elérhető Angular Universal célja, hogy platform és eszköz támogatást adjon szerver oldali HTML renderelés megvalósításához. A feladat nem csak annyi, hogy a backendről érkező HTML sztringet beszúrunk a weboldal közepére, hanem támogatni kell a kereső motorokat és az oldalról tartalmat kiollózó egyéb alkalmazásokat (pl. Facebook, Slack), miközben többféle stratégiát (pl. statikus renderelés fordításkor) is kell tudnia támogatni.

Olyan környezetben, ahol a teljesítmény problémákat okoz, érdemes megismerkedni a fogalommal és az Angularos megvalósítással.

Angular Elements

Angular LabsA szoftverfejlesztés egyik problémája, hogy általában le kell tenni a voksunkat valamelyik keretrendszer mellett, és utána annak a szabályai szerint kell játszanunk. Különösen bosszantó ez egy olyan környezetben, mint a web, ahol mindegy, hogy milyen kliens oldali platformot választunk, végül mezei HTML és JavaScript kód fog futni a böngészőben, miközben az egyes keretrendszerek között nincs, vagy csak nagyon körülményes az átjárás.

Ezen a problémán próbál segíteni az egyelőre csak az Angular Labs részeként elérhető Angular Elements, aminek az a célja, hogy a Custom Elements szabvány lehetőségeit felhasználva úgy csomagolja be az Angularos komponenseinket, hogy más keretrendszerek számára standard HTML elementnek tűnjenek. A kezdeményezés még nagyon gyerekcipőben jár, jövőre lehet belőle valami, mindenesetre üdítő látvány, hogy az Angular csapat nem zárkózik be, nyitott más platformok felé, és támogatni akarja a library fejlesztőket.

Ezek voltak a visszatérő témák, de ezeken kívül még sok más terület is terítékre került: forms, animations, DevKit, Schematics, ABC, Query, DI, aria, internationalization, flex layout, security, burnout, VR – szerencsére a videók mind megtekinthetők a Youtube-on. Mindkét nap keynote-tal kezdődött, érdemes megnézni őket.

Ráadásként az Angular csapat egy ígéretet is tett: kigyomlálják a Github repóban található közel 2000 issue-t és több, mint 300 PR-t. Külön embert vettek fel erre 🙂

 

Technorati-címkék: ,,,

Hogyan nyerhetné vissza a BKK a bizalmamat?

Az elmúlt két hétben alig telt el nap anélkül, hogy ne derült volna ki valami újabb “érdekesség” a BKK új, online, elektronikus jegyértékesítési rendszerével kapcsolatban. Sokan, sokféleképpen elmondták már, hogy a rendszer fejlesztői milyen szakmai és kommunikációs hibákat követtek el, azt azonban egyetlen cikkben sem láttam vitatni, hogy elektronikus jegyértékesítési rendszerre szükség van.

Az elkövetett “bakik” azonban jelentősen megingatták a felhasználói bizalmat mind a szolgáltatóban, mind pedig az elkészült rendszerben, ami elég érdekes patthelyzethez vezetett: mind a szolgáltatónak, mind pedig a felhasználóknak érdekük lenne használni egy ilyen rendszert, de nem ezt.

Adott tehát a feladat, ki kell mászni erről a mélypontról, mindannyiunk érdekében. Te hogyan tennéd? Ha te lennél a BKK-nál az a most frissen kinevezett, új vezető, akinek sikerre kell vinnie az elektronikus jegyértékesítési rendszert, te mit csinálnál? Utasként, felhasználóként, mit várnál el a BKK-tól, hogy bátran használni merd a rendszert? Informatikusként, szoftverfejlesztőként, IT biztonsági szakemberként mi kellene neked ahhoz, hogy megbízz egy új rendszerben?

Eljátszottam a gondolattal, hogy ha én kerülnék ilyen kihívás elé, én milyen irányba vinném a projektet. Tettem mindezt úgy, hogy a mostani rendszerről a sajtóban megjelenteken kívül semmit sem tudok: nem ismerem a követelményeket, az anyagi kereteket, a jogi korlátokat, az integrációs igényeket, ezért ezeket figyelembe se tudtam venni. Minden döntésnek vannak hátrányai, az egyszerűség kedvéért itt csak az előnyökre térek ki.

További károk megelőzése

Felbontanám a szerződést a T-Systems-szel, és az erről szóló dokumentumokat nyilvánossá tenném. Miért? A mostani rendszer fabatkát sem ér, és a fejlesztő cég elveszítette szavahihetőségét: nincs az a felhasználó, aki szívesen használná, vagy aki elhinné, hogy a fejlesztő “megerősítette”, és most már biztonságos. Egy új, tiszta lappal induló projektben ez csak ballaszt.

Megsemmisíteném a jelenlegi adatbázist, méghozzá egy IT biztonsági cég felügyeletével, akiknek az igazolását nyilvánossá tenném. Miért? Egyrészt nincs rá szükség egy tiszta lappal induló új rendszernél, másrészt nagyjából 1 napnyi felhasználási adat van benne, amit simán hagynék veszni, de leginkább azért, hogy elejét vegyem azoknak a vádaknak, hogy továbbra is innen szivárog ki személyes adat. Meg aztán úgyis van róla backup a dark weben 🙂

Közreműködő IT biztonsági cégként egy olyat választanék, aki nem mamut és akit a hazai szakma elismer. Legalább három IT biztonsági konferencia van hazánkban minden évben, bőven lehet választani a felvonuló cégek közül.

Új alapok

Az új rendszert kezdettől fogva a Kerckhoff elvet követve fejleszteném. Miért? A Kerckhoff elv szerint a rendszer csak akkor lehet biztonságos, ha egy támadó a titkosítási kulcson kívül a rendszer összes paraméterét ismerheti. És miért ne ismerhetné bárki, hiszen ez egy közpénzből fejlesztett, nagyon érzékeny személyes adatokat kezelő, közérdekű rendszer.

Nyilvánossá tenném a forráskódot és minden dokumentációt. Miért? Egyrészt mert ebben az országban nagyon sokan tudnának értékesen hozzátenni a projekthez, másrészt mert a transzparencia hatalmas erő. Kockázatos, de bátor tett lenne, ha a fejlesztőcsapat kiállna, és azt mondaná: íme, erre költöttük a pénzeteket. Mi hiszünk abban, hogy ez így jó, de tessék, nézzétek meg minden részletét, és szóljatok hozzá, kíváncsiak vagyunk a véleményetekre. Fontos, hogy a nyílt forráskód, nem jelenti a demokratikus döntéshozatalt. A szakmai döntésekért valakiknek vállalniuk kell a felelősséget, nem lehet azt mondani, hogy a “tömeg megszavazta”. Viszont hiszek abban, hogy a jótanácsot meghallgatni illik, de megfogadni nem feltétlenül kell.

Egy szakmai műhelyre bíznám a fejlesztést, nem egy multira. Miért? Még ha feltételezzük is, hogy ugyanaz a szakmai kompetencia megvan mindkét esetben, a motiváció lényegesen eltérő a két esetben. Nagyon sokat számít, hogy a projekt résztvevői pontosan mit akarnak elérni: egy jól működő, általuk is használt, a felhasználók elégedettségére törekvő rendszert akarnak készíteni, vagy más az elsődleges cél.

Arcokat tennék a projekt mellé. Miért? Az összes sikeres projekt, amit eddig láttam, részben annak köszönheti az eredményeit, hogy valaki vagy valakik a saját gyereküknek érezték. Akinek ott a neve, az arca, az elérhetősége és a felelőssége, az teljesen máshogy áll a projekthez, mint egy sokadik, névtelen alvállalkozó. És természetesen a felhasználói oldal is máshogy áll hozzájuk.

Iteratívvá tenném a fejlesztést. Miért? Ma már nagyon maradi megközelítés azt gondolni, hogy egy szoftver projekt az átadásakor készen van. Mindig jönnek visszajelzések, mindig találunk hibákat, mindig lehet javítani az alkalmazáson.

Continuous integration, continuous delivery és automatizált tesztelés. Miért? Egyszerűen nélkülözhetetlen az iteratív fejlesztéshez, pont.

Publikálnám a roadmapet. Miért? A roadmap mutatja, hogy mit szeretne még elérni a csapat, mi mindenre gondoltak még, és milyen irányba megy a fejlesztés. Bár minden roadmap változik, a felhasználói oldal számára mégis tervezhetőséget biztosít. Különösen, ha ez egy valóban élő dokumentum, aminek a változásait a fejlesztők el is magyarázzák (akár szóban, online meeting formájában).

Operations

A kódot felhő szolgáltatónál, serverless alapokon futtatnám. Miért? A felhő mellett számos érv van, ennél a projektnél talán az a legfontosabb, hogy ne csak jól skálázódó és biztonságos legyen, de egyszerűen és olcsón üzemeltethető is. Erre ma szerintem a serverless a legjobb megoldás.

Ops a BKK-nál. Miért? A rendszer a BKK ügyfeleinek személyes adatait kezeli, tehát a BKK-nak kell felelnie értük. Fontos az is, hogy a rendszer zavartalan működése a BKK számára a legfontosabb, ezért a közvetlen üzemeltetés a legpraktikusabb. Serverless környezetben a szolgáltató számos monitorozási lehetőséget és automatikus skálázást ad, miközben nagyon jól definiálható, hogy ki férhet hozzá a tárolt adatokhoz.

Biztonság

Federált authentikáció. Miért? A felhasználók azonosítása nem kis feladat, ha nem kell megcsinálni, azzal csak nyer a projekt. Arról nem is beszélve, hogy nem egyszerű jól megcsinálni, komoly felelősség. Ráadásul, ha figyelembe vesszük a projekt célközönségét is, akkor az is elképzelhető, hogy egy magyarország.hu + Google + Facebook hármas szinte mindenkit lefed.

Activity log a saját tevékenységeimről. Miért? A rendszerben megvan, hogy ki, mikor, milyen tranzakciókat hajtott végre. Annak a lehetősége, hogy a felhasználók a saját tevékenységeiket így visszakövethetik, számos félreértést eloszlat.

GDPR megfelelőség. Miért? Nem csak azért, mert 2018. májusától úgyis kötelező, hanem azért is, mert egyszerűen tisztává teszi a képet: mindenki láthatja, hogy a rendszer milyen adatokat tárol róla és kérheti azok törlését.

Security review, nyilvános dokumentációval. Miért? Szinte minden security review-n kiderül valami, amire a fejlesztők nem gondoltak, és amivel jobbá lehet tenni a rendszert.

Béta teszt időszak. Miért? Nehéz elsőre jót alkotni, kellenek a korai visszajelzések, az életszerű adatok. Ez a teszt lehet akár zártkörű, meghívásos is, még az is jobb, mint azonnal nekifutni a nagyközönségnek.

Bug bounty program. Miért? Erről az utóbbi időben sokat írtak, nem szeretném ragozni: tiszta és megéri.

Felkutatnám a más országokban létező elektronikus jegy megoldásokat. Miért? Nem lepődnék meg, ha az derülne ki, hogy a létező megoldások sem garantálják, hogy az elektronikus jegyek biztosan nem hamisíthatóak. Lehet, hogy az is elég, ha nagyobb munka hamisítani, mint megvenni.

Ráadás

Közzétenném az adatokat anonimizált formában. Miért? Ebben a rendszerben nagy mennyiségű adat gyűlik össze, a hasonló rendszerek kutatásával foglalkozó szakemberek számára ez nagyon hasznos és értékes adatforrás. Ennek az adatbázisnak az elemzésével a közlekedést meghatározó döntések születhetnek.

 

Nektek ez így elég lenne, ilyen körülmények között ti bíznátok egy új rendszerben? Mit hagytam ki?

 

.

Miért gyengíted a jelszavamat?

Nem tudom, ki hogy van vele, én nem szeretem sűrűn változtatni a jelszavaimat. Egyszerűen azért, mert macerás, viszi az időmet. A szolgáltatásokat használni szeretem, nem a beállításaikkal bíbelődni. Ennek ellenére – részben az utóbbi időszakban közzétett ellopott jelszó adatbázisoknak köszönhetően – rászoktattam magam, hogy a korábbiaknál gyakrabban cseréljem a jelszavaimat.

Az ilyenkor szokásos ajánlás, hogy a jelszó legyen komplex, és ne használjuk több helyen. Számomra komplex az, ami elég hosszú, van benne kisbetű, nagybetű, szám és még valamilyen speciális karakter is. Csakhogy nem kevés olyan weboldal van, ami ezt nem engedi beállítani.

Íme az egyik:

Aegon

Én ezt nem értem, miért nem használhatok ékezetes karaktereket? Csak nem varchar van az adatbázisban nvarchar helyett? Miért nem használhatok extra karaktereket, talán SQL injectiontől féltek? Gondoltam megkérdezem:

Aegon-Twitter

Valószínűleg rossz csatornán tettem, a Twitter fiókjukat évek óta nem frissítették, és a jelek szerint nem is olvassák. Vagy csak fittyet hánynak rá.

Persze nem ők az egyetlenek, a Nemzeti Útdíjfizetési Szolgáltató is hasonló cipőben jár:

NemzetiUtdij-Twitter

Sőt! Ők nem mondják meg, hogy mit nem tartalmazhat a jelszó, egyszerűen csak “Nem megfelelő formátum” hibaüzenetet írnak ki. Twitteren nem találtam meg őket, de megírtam nekik a kérdésemet, és alig 17 nap alatt válaszoltak is egy 5 (!) oldalas levéllel, amiből a következőket tudtam meg:

“Tárgy: Autópálya használati díj fizetésének ellenőrzése”

Ajjaj, szerintem nem, de ezen lépjünk túl. Kaptam Iktatószámot is, úgy látszik azért komolyan vesznek.

“Tisztelt Balássy György!
Társaságunkhoz intézett megkeresését köszönjük.”

Eddig minden rendben, piros pont a két-s-ipszilonért.

“Tájékoztatjuk, hogy a jelszó csupán az angol abc kis- és nagybetűiből állhat, valamint számokból.”

Ezen pattogok én is.

“Fontos, hogy egységes karakterek legyenek megadhatóak, hiszen vannak külföldi ügyfeleink, akik nem feltétlen rendelkeznek magyar billentyűzettel, ezáltal pl.: ékezettel.
A belépést és regisztrációt mindenki számára elérhetővé kell tennünk, ami az angol abc használatával valósul meg.”

Álljunk meg egy szóra. Nem úgy van ez, hogy én választok magamnak jelszót, amit azután én a saját kezemmel, a saját billentyűzetemmel gépelek be? Amilyen karaktert nem tartalmaz a billentyűzetem, azt nyilván nem fogom és ezért nem is akarom beírni, de amit tartalmaz, azt nagyon szeretném. Orosz karakter például biztosan nem lesz a jelszavamban, de csak azért nem, mert én úgy akarom.

“Továbbá attól, hogy nem adható meg ékezet és speciális karakter, még nem lesz gyengébb a jelszó.”

Ez egyszerűen nem igaz (feltételezve, hogy ugyanazt értjük “gyengébb” alatt).  Fejtegethetnénk itt most a problématér méretét, ki is próbálhatnánk L0phtCrackkel vagy John the Ripperrel, hogy kinek van igaza, de mivel a levél írójától sem várom el, hogy ilyen eszközökkel rendelkezzen, nézzünk inkább néhány kevésbé tudományos eszközt a Google találati listájáról, amik megmondják, hogy szerintük a különböző jelszavakat mennyi ideig tart feltörni:

 

“almafa”

“álmáfá”

“álmáfá!”

https://howsecureismypassword.net/

8 ms

1 perc

5 óra

https://password.kaspersky.com/

9 perc

3 óra

2 nap

http://www.passwordmeter.com/

5% – Very Weak

45% – Good

60% – Strong

http://random-ize.com/how-long-to-hack-pass/

kevesebb, mint 1 másodperc

13 másodperc

12 perc 57 másodperc

http://password-checker.online-domain-tools.com/

3 másodperc

1 nap

2 év

A számok pontosak? Valószínűleg nem, sőt még az arányaik sem azonosak. Az viszont tisztán látszik, hogy nem azonos nagyságrendben mozognak az egyes oszlopokban szereplő értékek.

“Javasolhatjuk továbbá, hogy szíveskedjen nagybetűt használni, ez még inkább növeli a jelszó erősségét.”

Mihez képest? Az angol abc kis- és nagybetűihez, valamint a számokhoz képest? Azt már használok, köszönöm.

A levél további 4 és fél oldala arról szól, hogy a fogyasztóvédelmi törvény szerint mit tehetek és hova fordulhatok, ha nem vagyok elégedett: ügyfélszolgálat, e-ügyfélszolgálat, levelezési cím, személyes ügyintézés, békéltető testület, bíróság stb. Egyébként ISO 9001, ISO 14001, BS OHSAS 18001, Certified IQNet Management System minősítésekről árulkodik még a levél.

A jó hír az, hogy itt legalább hosszú jelszót be tudok írni, amivel azért van lehetőségem elfogadható erősségű jelszót megadni, még ha nem is használhatom azt, amelyiket én szeretném. Nagyságrenddel rosszabbak azok az oldalak, ahol a jelszó hossza korlátozott.

Ezzel együtt az ilyen korlátozások bennem azt a gyanút ébresztik, hogy valami nem stimmel az oldal jelszó kezelése környékén, hiszen a hash algoritmusoknak nem szokott problémát okozni pár ékezet, aposztróf vagy felkiáltójel.

Mit tegyünk ezekkel a weboldalakkal?

 

Technorati-címkék: ,

Ötdimenziós tárgyak nyomtatása 3D nyomtatóval

Pontosan 5 évvel ez előtt ezen a napon vált online elérhetővé a British Journal of Psychology 49. évadának 1. száma, amelyben Lionel Penrose és fia, Roger Penrose Impossible Objects címmel publikált egy cikket olyan tárgyakról, amelyek szerintük nem létezhetnek. Ezek közül talán a Penrose-háromszög a legismertebb:

5d-penrose-triangle

A cikk eredetije jóval korábban, 1958-ban jelent meg, és az azóta eltelt több, mint 50 év alatt a tudomány sokat fejlődött. Mai tudásunkkal már kijelenthetjük, hogy Penrose-ék tévedtek, ezek a tárgyak igenis létezhetnek, a modern 3D nyomtatási technológia segítségével mi magunk is létrehozhatjuk őket.

Első lépésként egy modellre lesz szükségünk, amit ki tudunk nyomtatni. Itt jön az első probléma, ugyanis a hagyományos térbeli rajzoló alkalmazások maximum három dimenzióval tudnak megbirkózni, márpedig itt nekünk többre lesz szükségünk. Azaz felejtsük is el rögtön a SketchUpot, a Blendert, az AutoCADet, a Mayat, TInkercadet stb., hiszen ezek csak 3D-ben tudnak gondolkodni.

Az egyetlen lehetséges megoldás (legalábbis én másról nem tudok), hogy a modellünket kódban írjuk le, amire szerencsére létezik már bevált, és elterjedt megoldás, az OpenSCAD. Kiváló eszköz! Aki csak egy kicsit is vonzódik a programozáshoz, annak csak ajánlani tudom, hogy így írja le a 3D modelljeit. Mivel itt kóddal dolgozunk, nem korlátoz minket a háromdimenziós tér, bátran használhatunk olyan transzformációkat, amik további dimenziókba viszik a modellünket. Amire szükségünk lesz, az a to5d() metódus, ami az OpenSCAD CheatSheeten a Transformations csoportban található:

5d-openscad

Ha így sikerült elkészíteni az ötdimenziós modellünket, jöhet is a nyomtatás, aminek első lépése az STL modell szeletelése. Én ehhez leggyakrabban Curat szoktam használni, mert számomra nagyon átlátható a felülete. Sajnos talán pont az átláthatóság miatt számos opció nincs kivezetve az alap felhasználói felületre, hanem csak az Expert config ablakban érhető el:

5d-cura-expert-config

Sőt, az ötdimenziós nyomtatás még ide sincs alapból kivezetve, de a figyelmesebb szemlélők észrevehetik, hogy míg a legtöbb szöveg egymástól függőlegesen egészséges távolságra van elhelyezve, addig a Black Magic kategóriában nagyon össze vannak zsúfolva a sorok. Ennek az az oka, hogy ha bepipáljuk az első két opciót, akkor megjelenik egy harmadik Enable more dimensions néven, pipáljuk be ezt is:

5d-cura-black-magic-settings

Ez után már nem lesz gond az OpenSCAD-ből exportált 5D STL fájl megnyitása, amit azután a szokásos módon nyomtathatunk. Íme, nekem így sikerült a Penrose-háromszög:

5d-triangle

Íme egy másik fénykép, együtt egy 3D tárggyal:

5d-triangle-with-pencil

A képet a telefonommal, vaku nélkül készítettem, az élek egyenetlensége pedig a hobbi kategóriás nyomtatóm tökéletlenségének az eredménye.

Az első “lehetetlen” tárgyam létrehozása után következő lépésként a svéd Oscar Reutersvärd kockákból felépített háromszögét nyomtattam ki, amit ő eredetileg így képzelt el (Forrás: Wikipedia):

5d-reutersvard-triangle

Ennek az OpenSCAD modellje egyébként még egyszerűbb, hiszen csak kilenc darab kockát kell létrehozni. Miután ez megvan, megnyithatjuk a modellt Curaban:

5d-cura-preview

Az előnézeti képen jobb oldalon, alulról a második kockánál látszik egy világosabb sárga rész, amit nem tudok megmagyarázni. Szerencsére csak a kép renderelése hibás, a nyomtatás simán ment, íme az eredmény:

5d-cubes

A lehetetlen objektumok kapcsán eszembe jutott M.C. Escher híres képe a végtelen lépcsőházról, ezért elkészítettem annak is a modelljét, így mutat Curaban:

5d-cura-stairs

Amint elkészül vele a nyomtató, feltöltöm a fotót.

A fenti példákból is látszik, hogy a 3D nyomtató már nem csak háromdimenziós tárgyak nyomtatására használható, ne ragadjatok le a 3D-nél!

 

Technorati-címkék:

3D nyomtatás: 15 modell, 15 tapasztalat

Egy hónappal ez előtt a LogMeIn jóvoltából szerencsés tulajdonosa lettem egy 3D nyomtatónak. Mivel a konkrét típus kiválasztása is az én feladatom volt, vásárlás előtt alaposan körbejártam a témát, így azzal a gondolattal állhattam neki a 3D nyomtatásnak, hogy tudomány ide vagy oda, a sikeres nyomtatáshoz leginkább bizony szerencse kell. A 2D és a 3D nyomtatás egyszerűsége és megbízhatósága között ugyanis ég és föld a különbség. Minden nyomtatás tartogat magában nehézséget, meglepetést és tanulságot is. Rendszerint többet, mint amire számítanánk.

1. “Okay”

A gyártó útmutatásait követve elsőként azt a modellt nyomtattam ki, ami a nyomtatóval érkezett:

okay-hand

A dolog pofonegyszerűnek tűnt, mert a modellből készített GCODE fájl rajta volt a nyomtatóhoz kapott SD kártyán, nem kellett semmilyen paramétert állítani, gyakorlatilag csak a Print gombot kellett megnyomni. Gondoltam ha a nyomtató hardverileg rendben van és jól van betöltve a nyomtatószál, akkor ennek sikerülnie kell.

“Szinte” sikerült is, ez lett belőle:

okay-hand-printed

Hát majdnem ugyanaz. Történt ugyanis, hogy nagyjából félórányi nyomtatás után egy finom pattanást követően elmozdult a tárgy a tárgyasztalon, onnan kezdve pedig kuka az egész.

Tanulság:

  • A tárgyasztal tapadása az egyik legfontosabb tényező a sikeres nyomtatáshoz, mégis mindenki küzd ezzel. Vannak házi módszerek, drága felületek, de igazán 100%-os, egyszerűen használható, jól tapadó, de könnyen eltávolítható megoldás nincs (legalábbis én nem tudok róla).
  • A nyomtatóval együtt vásároltam a tárgyasztalra egy üveglapot, hogy biztosan sík legyen a felület, a szintezés ugyanis a másik kritikus tényező a sikeres nyomtatáshoz. Elméletileg ez a tapadáson is segíthet, ám azt nem szabad elfelejteni, hogy lefogja egy kicsit a tárgyasztal fűtését. Az én nyomtatómhoz üveglap nélkül másoknak bevált a 60°C-os tárgyasztal, nekem viszont biztos több kell az üveglap miatt. A későbbiekben 70°C-os tárgyasztallal nyomtattam, és jobbak lettek az eredmények.

2. Kalibrációs kocka

Második kísérletként a nyomtató precizitását próbáltam ki egy sima kalibrációs kocka segítségével, ami ilyen bonyolult:

calibration-cube

Egy pontosan 20×20×20 milliméteres kockát akartam nyomtatni, ami nem tűnik nehéz feladatnak. A nyomtatás igen jónak indult, ám végül csak ez lett belőle:

calibration-cube-printed

Az ok ugyanaz: a tárgy elmozdult a tárgyasztalon.

Ezzel együtt a nyomtatás nem volt teljesen hiábavaló, mert ebből is tanultam két dolgot:

  • Ez a nyomtató meglepően pontos. Hagyományos kézi sublerrel mérve a kocka alapjai 20,0 × 20,0 milliméteresek. A második tizedesjegynél biztosan van eltérés, de az már nekem belefér.
  • Nem élhetek hajlakk nélkül!

3. Kábelvezető

A 3D nyomtató tulajdonosok előszeretettel nyomtatnak 3D nyomtató alkatrészeket. Vagy azért, hogy tuningolják a nyomtatójukat, vagy azért, hogy valami problémát küszöböljenek ki. Az én esetemben az utóbbi fordult elő, a mozgó tárgyasztalhoz vezető kábel ugyanis előszeretettel akadt be a nyomtató vázának egyik merev sarkába. Persze nem én voltam az első, aki ezt tapasztalta, van már rá megoldás a Thingiverse-en:

cable-protector

Letöltöttem, és alig pár perc alatt sikeresen ki is nyomtattam:

cable-protector-printed

Ezen a képen, ilyen brutálisan felnagyítva (az eredeti kb. 3 × 1 cm) nem tűnik valami szépnek, a valóságban azonban egészen rendben van. Tökéletesen illeszkedik, és ami még fontosabb, tökéletesen működik is.

Ez volt az első sikeres nyomtatásom, és persze ebből is tanultam:

  • A 3D nyomtatással valóban meg lehet oldani valós problémákat, viszonylag gyorsan. Persze ezt a modellt valakinek el kellett készítenie, de már rengeteg modell érhető el a neten, és nagyon jó esély van rá, hogy a te problémádba más már belefutott, és rajzolt hozzá egy modellt. Lelőhelyekből nekem legjobban a Thingiverse jött be, de sokan a YouMagine-re esküsznek, míg mások az Instructablest preferálják. Persze rengeteg ilyen gyűjtemény oldal van.
  • A sikeres nyomtatás egyik oka, hogy végre nem volt gondom a tárgyasztal tapadásával. Egyrészt mert 70°C-ra fűtöttem, másrészt mert követve az egyik legjobb népi praktikát, hajlakkot fújtam rá nyomtatás előtt. Igen, kutya közönséges hajlakkot. Soha nem gondoltam volna korábban, de Garnier Fructis Extra Strong hajlakk van az asztalomon, és nem csak, hogy minden nap használom, de nem tudok nélküle élni! (Kérem ezt a mondatot senki ne ragadja ki a környezetéből.) Annyira jól működik, hogy meleg tárgyasztalról le se tudom vésni az eredményt, meg kell várnom, amíg lehűl a nyomtató, akkor viszont egy jól irányzott pofonnal simán lejön.

Na, itt tart ma a 3D nyomtatás: hajlakk és pofon kell a sikerhez (vö. a 2D nyomtatás mennyire sima ügy ehhez képest).

4. Szintező csavar

Megörülve a sikeres nyomtatásnak, és megmámorosodva a nyomtató tuning “képességeimtől”, következőként ezt a modellt nyomtattam ki:

thumbwheel

Ilyen lett az eredmény:

thumbwheel-printed

Ez egy kézzel tekergethető csavar anya, ami jelentősen egyszerűsítheti a tárgyasztal szintezését, különösen, ha önzáró anya kerül bele.

A nyomtatás a korábbiak alapján már sima ügy volt, de emlékezetes:

  • Azt hittem, szét fog esni a nyomtató, annyira rázkódott a modell szélén lévő apró kiszögellések nyomtatása közben. Elsőre nagyon meglepett, de azóta más modellnél is találkoztam vele, és eddig minden rendben van.
  • Az ennyire apró részletek nem lesznek tökéletesek, hiába állítom 0.1 mm-re a rétegvastagságot. Itt főként a felületből “vésett” számokra és rovátkákra gondolok, amiket a nyomtató nem kimar, hanem a következő réteggel körberajzol. Bár olvashatóan látszanak a számok és a jelölések, a számok vonalának a vastagsága nem egyenletes – de persze ez csak közelről megnézve látszik.
  • A modellnek a tárgyasztallal érintkező része igen minimálisan, de kicsit “szétfolyik”.
  • Ilyen rücskös szélű modellnél nem célszerű karimát (brim) nyomtatni, mert nem lehet szépen leválasztani.
  • A fém csavar tökéletesen illeszkedik a műanyagba, pontosabban alig tudtam belepasszírozni, de utána nagyon jól szorul. Ehhez biztosan a tervező kitartó kísérletezése kellett, de a végeredmény nagyon jó. Mindenféle ragasztó nélkül jól kombinálható a műanyag és a fém.

5. Lehetetlen fecskefarok csapolás

Ennyi tisztán praktikus nyomtatás után a választásom egy szórakoztató modellre esett, ami a hagyományos fecskefarok csapolásnak egy lehetetlennek tűnő változata:

impossible-dovetail

Nekem nem volt bátorságom nyomtatószálat cserélni, ezért egyféle anyagból nyomtattam ki a modell két felét:

impossible_dovetail_parts

Amik tökéletesen illeszkednek:

impossible_dovetail_assembled

Elégedett vagyok az eredménnyel, pontos, és pont annyira laza, amennyire kell.

De:

  • Majdnem letörtem a modell egyik sarkát, miközben próbáltam lefeszegetni a tárgyasztalról, annyira jól fogta a hajlakk. Azóta nem feszegetek semmit, inkább várok, amíg lehűl a tárgyasztal.
  • A felső képen látszik, hogy nem tökéletes a tárgy teteje. Úgy állítottam be a szeletelő programot, hogy 10% legyen a modell kitöltése, azaz ne legyen tömör, mert itt nem szükséges akkora szilárdság, viszont így gyorsabb lesz a nyomtatás, és kevesebb nyomtatószálat használ. Arra viszont nem gondoltam, hogy ha az üreges modellt nem fedem be elég vízszintes réteggel, akkor ott be lehet látni, nem lesz tökéletes a fedés. Ezt okozhatja az, hogy a nyomtatófej nem nyom elég nyomtatószálat (under extrusion), aminek a módosítása viszont a modell minden részére kihatna, ezért inkább azt a megoldást választottam, hogy a következő nyomtatásoknál emeltem az alsó és felső rétegek számát (Bottom/Top thickness beállítás Cura-ban).

6. Microsoft Band töltő

Ennyire kísérletezés után ideje volt valami mindennapi használati tárgyat is nyomtatni, így rögtön felcsillant a szemem, amikor megláttam ezt a modellt (a képet a Microsoft 3D Builderéből fotóztam, ami egy egészen jó program):

band-stand

Ez egy dokkoló, amibe beleteheti az ember tölteni a Microsoft Band típusú okosóráját. Mivel a modell hátulja tartalmaz közvetlen alátámasztás nélküli vízszintes felületeket, ezért úgy döntöttem, hogy támaszanyagot fogok nyomtatni. Ilyen lett az eredmény:

band-stand-printed

Tanulságok:

  • A támaszanyag lutri. Lehet, hogy nem is kellene (ennél a modellnél talán elhagyható lett volna), de ez sajnos csak nyomtatás után derül ki. Modelltől függően néha nagyon egyszerű eltávolítani, néha viszont nagyon macerás. Itt például nekem ezt az üreget teljesen meg kellett tisztítanom, hogy be tudja fogadni a töltő csatlakozóját, és ez a kicsi, íves felületek miatt nagyon nehéz volt, majdnem addig tartott, mint a nyomtatás.
  • A ferde felületek lépcsősek lesznek, még akkor is, ha nagyon kicsi rétegvastagsággal nyomtat az ember. Ezt lehet csiszolni, ABS-nél acetonozni, vagy csak simán el lehet viselni. Indusztriális dizájn. Ki tudja, a látszó beton és a dekor rozsda után lehet, hogy ez lesz a következő trend. A lényeg, hogy számítani kell rá. Ennél a modellnél elvileg meg lehet azt tenni, hogy elforgatom úgy, hogy ne az alja, hanem a teteje legyen párhuzamos a tárgyasztallal, így az aljára kerülnek a lépcsők (persze akkor sok támaszanyag kell alulra).

7. Gombfoci

Erre azért vagyok büszke, mert ez volt az első, amikor nem csak letöltöttem valamit, hanem nulláról megalkottam, kinyomtattam, majd fel is töltöttem, hogy mások is használhassák. Ez az ultrabonyolult test egy gombfoci játékos:

button-soccer

A 3D modellt SketchUpban rajzoltam, amit már korábban is használtam asztalosmunkák modellezésére, mert pontosan lehet vele rajzolni (megadhatók a méretek). Letölthető hozzá egy SketchUp STL nevű plugin, ami képes a modellből STL fájlt generálni, amit már a 3D nyomtatós szeletelő programok ismernek, így a tervezéstől a nyomtatásig végigvihető a folyamat, és végül a folyamat minden fájlját fel lehet tölteni a Thingiverse-re.

Persze ez sem ment simán:

  • A SketchUp hátránya, hogy nagyon kis méreteknél néha bénázik. Ezt a programot eredetileg építészeknek tervezték, márpedig ők nagyon ritkán akarnak tizedmilliméteres pontosságot. Ennél a modellnél az lett volna az egyik feladat, hogy lekerekítsem a felső sarkot kb. fél milliméterrel, és bár ezt egy csiszolópapírral sokkal egyszerűbb megcsinálni, úgy gondoltam, hogy belerajzolom a modellbe, hogy dokumentálva legyen. Ezen a feladaton a SketchUp Follow Me eszköze látványosan elbukott, szétesett a modell. Fórumok szerint ilyenkor a bevált gyakorlat a modell ezerszeres felnagyítása, majd kicsinyítése.
  • Nyomtatás után a belső méretek, a lyukak némileg kisebbek lesznek. Ez ismert tény a 3D nyomtatás világában, olvastam már róla, hogy talán orvosolni is lehet, itt nekem annyira nem volt kritikus, hogy a belső és a külső méret is pontos legyen.
  • Rajzolni nagyon szeretek SketchUpban, de egy modellt módosítani nagyon nem, mert nehézkesnek találom. Bár már korábban is belefutottam az OpenSCADbe, Gömöri Zoli felhívta rá a figyelmemet, hogy lehet, hogy jobban járok, ha rajzolgatás helyett inkább programkóddal írom le a modellt. És valóban, rászánva egy fél napot a tanulásra, mára sok esetben az OpenSCAD tűnik jobb megközelítésnek az egyszerű módosíthatósága miatt. A modellek testreszabhatósága a Thingiverse-en pedig briliáns ötlet!

Időközben készítettem még egy gombfoci modellt, akinek kapusra van szüksége, innen tudja letölteni.

8. Nyomtatószál csipesz

Van 5 percem, mit is nyomtassak? Biszbaszt:

filament-clip

Persze meg tudom magyarázni: olvastam róla, hogy probléma lehet abból, ha a nyomtatószál fellazul a tekercsen, ez a kis mütyür pedig ezt segít elkerülni. Kinyomtatva ilyen lett:

filement-clip-printed

A végeredmény jó, működik, az anyag meglepően rugalmas.

A tanulság pedig az, hogy a képen is látható karima (brim) nem jó ilyen kicsi dolgokhoz, a tutaj (raft) sokkal könnyebben és szebben leszedhető.

9. Billog

A 3D nyomtató tökéletesen alkalmas felesleges dolgok nyomtatására, például készíthetünk vele Valentin napra nyomdát, amivel a pirítósunkat billogozhatjuk meg:

toast

Ezt viszonylag nagy, 0.3 mm-es rétegvastagsággal nyomtattam, arra számítva, hogy majd igen csúnya lesz (ami ennél a felhasználásnál belefér), de végül egészen jó lett az eredmény. Ez valószínűleg a modell egyszerűségének köszönhető, hiszen nincsenek benne hidak és ferde felületek.

10. Raspberry Pi doboz

A Thingiverse-en rengeteg dizájnt találhatunk kedvenc Raspberry Pi-nk becsomagolására, én végül ezt választottam a szerelhetősége és a felszerelhetősége miatt:

raspberry-pi-case

A modell több részből áll, külön kell nyomtatni az alját és a tetejét. Bele lehet csavarozni a panelt, és végül össze lehet csavarozni a két oldalt.

A “projekt” végére itt is okosabb lettem:

  • Rettenetesen sokáig tartott a nyomtatás, mivel gyakorlatilag tömör lett a végeredmény. Nem tanulmányoztam alaposan a modellt nyomtatás előtt, viszont a korábbiak alapján elég sok vízszintes réteget állítottam be. A nagy, egybefüggő vízszintes felületek nyomtatása sok időt vett igénybe. Simán lehetett volna kevesebb vízszintes réteget nyomtatni, ez a modell elbírta volna.
  • Amit viszont alig viselt el, az a falak feszegetése. Amikor ugyanis le akartam szedni az eredményt a tárgyasztalról, persze a függőlegesen álló falaknál fogtam meg, és ott kezdtem ráncigálni, ami kis híján a rétegek szétválásához vezetett. Az ilyen vékony falaknál erre vigyázni kell.
  • Legközelebb alaposan megnézem, hogy a modell tervezője milyen csavarokat ajánl. Ha nem metrikusakat, akkor inkább keresek másik modellt, mert nagyon nehéz az inchben megadott méretekhez hasonlót találni.

11. Malac

Ez az ülő röfi ajándékba készült:

piggy

Ilyen lett kb. 35 percnyi nyomtatás után, 0.3 mm rétegvastagsággal:

piggy-printed

Ezen a fotón megint csúnyábbnak tűnik az eredmény, mint a valóságban, hiszen ott sokkal kisebb a tárgy. A rétegek nem lettek ennyire zavaróak, bár az igaz, hogy a 0.3 mm ilyen íves tárgynál már túl sok. A malac elején látható bajusz és szakáll támaszanyag akart lenni az orra alá, de egyrészt nem sikerült rendesen kinyomtatni, másrészt feleslegesnek is bizonyult.

12. Imbuszkulcs tartó

A következő kísérlet majdnem teljes kudarc lett. Ezt a modellt akartam kinyomtatni, ami egy praktikus tároló imbuszkulcsok számára:

hex-key-holder

A korábbiakból tanulva itt már óvatosabb voltam, és alaposabban szemügyre vettem a modellt nyomtatás előtt.

Bár a Thingiverse-en számtalan fotó bizonyítja, hogy ez egy használható modell, amikor én Cura-ban megnyitottam, olyan aprónak tűnt, hogy rögtön gyanússá vált. A hozzászólásokat elolvasva hamar kiderült, hogy ez másnak is probléma, és az oka az, hogy a szerző amerikai mértékrendszerben dolgozott, azaz a modellben a méretek nem milliméterben, hanem inchben vannak. Szerencsére ezt könnyű orvosolni, a szeletelő programban simán felnagyítottam a modellt 25.4-szeresére, és máris jónak látszott a méret.

Ezután azonban tovább vizsgálódtam, és a rétegek ellenőrzésekor kiderült, hogy a Cura a modellen lévő lyukakból mindössze hármat vett észre. Betöltöttem a modellt más szeletelő programba, ám ott is hasonló eredményt kaptam. Mivel a fotók nagyon meggyőzőek voltak az oldalon, egy kicsit bíztam benne, hogy csak a szeletelő programok megjelenítése hibás, ezért próbaként kinyomtattam pár réteget, és így nagyon hamar egyértelművé vált, hogy nem a megjelenítéssel van gond, hanem a modellel.

Ez időnként előfordul, és szerencsére vannak javítási lehetőségek. A Microsoft 3D Builder programja megnyitás után automatikusan felkínálja a modell javítását, de használhatjuk a Netfabb által készített, és Microsoft Azure-ban futó Model Repair Service-t is. Sajnos ebben az esetben egyik sem segített, a modell hibás maradt, így nem maradt más lehetőségem, mint hogy szomorúan lemondtam a nyomtatásról.

Előtte azonban még megírtam a tapasztalataimat egy kommentben a szerzőnek, illetve a többi Thingiverse felhasználónak, hogy másnak ne kelljen ugyanezt az utat végigküzdenie. Alig telt el pár nap, és jött az alábbi válasz a szerzőtől:

“Fixed the issues many of you were speaking about. I was using a slicer software with a repair feature built in, so I was overlooking the issue. Everything should be good now. Uploaded the print in MM too. Thanks for all the feedback. Let me know if you have any more issues. ”

Azaz hallgatva a visszajelzésekre utánajárt a problémának, kijavította, és feltette a modellt olyan formában, hogy az többeknek hasznos legyen. Az is kiderül a hozzászólásból, hogy a szerzőnek azért nem tűnt fel a hibás modell, mert az ő szeletelő programja automatikusan javította azt. Tehát neki nem volt semmi gondja, hagyhatta volna az egészet úgy, ahogy neki jó, de ő mégis vette a fáradságot, és feltöltötte a javított verziót is, mert mások csak azt tudják használni. Ez a hozzáállás nagyon tetszik!

Ismét felcsillant a remény, hogy ezt is sikerül kinyomtatni!

13. Menő Manó

Gyerekkorom nagy kedvence, az olasz Osvaldo Cavandoli alkotása; amikor megláttam, nem tudtam ellenállni neki:

la-linea

Lekicsinyítettem a modellt, és alig 20 perc alatt el is készült:

la-linea-printed

Ennek a nyomtatásnak két tanulsága volt:

  • A PLA ilyen méretekben meglepően rugalmas.
  • Aki ezt meglátja az asztalomon, rögtön beleszeret a 3D nyomtatásba 🙂

14. Villáskulcs tartó

Ez a nyomtatás is a másik hobbimhoz kapcsolódik, ugyanis némi bosszankodás után arra jutottam, hogy kellene egy normális tartó a villáskulcsaim számára, és ehhez találtam ezt a modellt:

wrench-organizer-printed

Így néz ki a modell:

wrench-organizer

A nyomtatás gyönyörűen sikerült, minden részletével meg voltam elégedve. Aztán belepróbáltam a legnagyobb villáskulcsomat a legnagyobb helyre, és csodák csodája szépen bele is passzolt. Sőt, igazából még lötyögött is egy kicsit, ezért áttettem a mellette lévő helyre. Na ezt nem kellett volna. Ott ugyanis már feszült, és egy pillanat alatt el is tört a modell. A legkisebb erőltetéstől kitört a fésű foga.

A dolog nyitja igen egyszerű. Úgy nyomtattam a tárgyat, ahogy a modellben szerepelt, nem forgattam semerre. A 3D nyomtatásnál a rétegek közötti tapadás viszonylag gyenge, azaz ha van megfelelő erő, akkor a rétegek szétválaszthatóak. Ennél a modellnél a vízszintes alap és a függőleges “fogak” találkozásánál nagyon kicsi a felület (különösen, ha nem tömör a nyomtatás), és ahhoz képest nagyon nagy az erőkar. Mindenféle erőlködés nélkül, ujjal ki lehet törögetni a fogakat.

Így, ebben a formában ez a tárgy nagyon szép, ám teljesen használhatatlan lett. Amint lesz egy kis időm, újra meg fogom próbálni, ám ezúttal elforgatom majd a modellt, és az oldalára állítva fogom nyomtatni.

15. Könyök

Egy másik házi projekt kapcsán felmerült az igény, hogy össze kellene tudni kapcsolni három darab 16 milliméteres fém csövet, például műanyag sarkokkal, ezért megterveztem hozzá ezt a modellt:

elbow

A modell SketchUpban készült, és már ott sokat tanultam azzal kapcsolatban, hogy egy hengert milyen nehéz jó helyen megfogni, és a térben pontosan forgatni.

Számítottam rá, hogy a hengerek belső átmérője a nyomtatás után kicsit kisebb lesz, mint a modellben, ezért különböző méretű kicsi hengerek próba nyomtatásával kísérleteztem ki a megfelelő méretet. Ez a módszer bevált, merem ajánlani. Azt azonban elfelejtettem, hogy a modell sajátosságaiból adódóan a háromféle lyuk biztosan nem lesz azonos méretű. A függőlegesen álló hengert nagyon pontosan tudja nyomtatni a gép, hiszen az rétegenként egy fekvő kört jelent, ami nem probléma. Nem úgy a másik két hengert, ott ugyanis sok, pontosan pozícionált rétegnek kell kiadnia a henger álló kör metszetét, ami sikerülhet jól, de szinte biztosan nem lesz tökéletes. És akkor még arról nem is beszéltem, hogy a behajló részeken valamennyi anyag lógás is várható. Magyarul aki lyukakat ilyen helyzetben nyomtat, az számítson torzulásra.

Ráadásul ennél a modellnél is előjön a rétegek közötti tapadás problémája. Ha a vízszintes lyukak mérete nem tökéletes (például anyag belógás miatt), és valaki mégis beleerőlteti az eredetileg pontosan illeszkedő csövet, akkor előfordulhat, hogy ez a sarok idom eltörik, pontosabban a rétegek mentén szétnyílik. (Lehet tippelni, honnan tudom.)

+1 Sarok profil

Ezt a formát “megrendelésre” nyomtattam:

Cura-fail-1

Látszólag igen egyszerű modell, de itt is előjön ám az előbb említett pontos lyuk nyomtatás probléma. Azonban ami miatt idevettem a tapasztalatok közé, az nem is ez, hanem hogy még ez a nagyon egyszerű, nagyon sík modell is képes elromlani. Ez lett belőle ugyanis Cura-ban:

Cura-fail-2

Észreveszed-e a hibát?

Igen, ott a bal oldali függőleges részen van egy kis kitüremkedés. Nem sok, de az a fél milliméter pont elég ahhoz, hogy az a felület ne legyen sík, és esetleg ahhoz is pont elég, hogy túl nagy legyen a kinyomtatott tárgy. Fogalmam sincs, hogy az a dudor minek köszönhető, a Cura egyszerűen odateszi, szerinte az oda kell. A Slic3r jelen esetben jobb munkát végez:

Cura-fail-3

Alaposan meg kell tehát vizsgálni a szeletelés eredményét, még nyomtatás előtt, mert a legváratlanabb helyeken bukkanhatnak fel hibát.

 

A 3D nyomtatás érdekes dolog, nincs két egyforma feladat, és mindegyikből tanul az ember. Néha nagyon bosszantó, hogy valami nem sikerül se elsőre, se másodikra, az viszont remek érzés, amikor kezedbe veheted azt, ami az előbb még csak a képernyőn létezett.

 

Technorati-címkék:

BKK Futár Microsoft Bandre – service és webtile (3. rész)

A Microsoft Band programozási lehetőségeinek és a BKK Futár API-jának a megismerése után el kellett döntenem, hogyan is szeretnék menetrendi adatokat megjeleníteni a Banden. Végül a webtile mellett döntöttem, leginkább azért, mert az SDK-s megoldás egy folyamatosan futó mobil alkalmazást igényelt volna.

A webtile korlátja, hogy sajnos nem tudjuk befolyásolni, mikor frissüljön, ezért nem álmodozhatunk olyan megoldásról, ami relatív időpontokat használ. Le kell tehát mondanunk a “3 perc múlva indul” stílusú, azonnal érthető megjelenítésről, helyette abszolút időpontokat használhatunk, azaz például “indulás 11:23-kor”. Ez nem annyira szép, de nem óriási probléma, hiszen a Band elsődleges képernyője (Me Tile) mindig a pontos időt mutatja, egy ilyen bonyolult kivonást pedig rá merek bízni a felhasználóra.

A nagyobb probléma, hogy ezzel megszűnik a “következő indulás” fogalma, hiszen a frissítési időközön belül akár több indulás is lehet, és előfordulhat, hogy egy vagy több már múltbeli lesz, mikor a felhasználó rápillant a csempére. Erre nem tudtam jobb megoldást kitalálni, mint hogy több indulási időpontot jelenítek meg, amiből majd a felhasználó némi humán komparálással kiválasztja, hogy melyik a legközelebbi. Egyébként is terveztem, hogy célszerű lenne több időpontot megmutatni, hiszen előfordulhat, hogy a nem a következő buszt, hanem csak a következő utánit szeretném elérni, mert túl messze van a megálló. A sajnálatos szépséghiba, hogy a listában jó eséllyel lesz múltbeli időpont is.

Az adatforrás

A leendő webtile-t természetesen el kell látni adatokkal, azaz szükséges hozzá egy GET-en elérhető szerviz. Bár ahogy az előző részben láttuk, létezik BKK Futár API, az sajnos nem tudja az adatokat pont olyan formában szolgáltatni, amire nekünk szükségünk van. Az eltérések:

  • A Futár API az indulási időpontokat epochtól eltelt másodpercben adja meg, azaz egy bazi nagy, igen barátságtalan számként. Ezt sajnos a webtile nem tudja emberileg fogyasztható formátumra konvertálni.
  • Az API-ban van predictedArrivalTime, arrivalTime és departureTime mező is, és változó, hogy mikor melyik van kitöltve, vagy melyiket érdemes használni. Dokumentáció híján csak tippelni tudok, melyik mit jelent, de a tapasztalat az, hogy a predicted csak a már közeledő járműveknél van kitöltve (tipikusan a következő vagy esetleg a következő kettő), és ez a legpontosabb. A sima arrivalTime szinte mindig ki van töltve, kivéve végállomásoknál, ahol csak a departureTime jelenik meg.
  • Az API hívás sikerességét nem (vagy nem csak?) a HTTP status code, hanem a HTTP válaszban lévő több mező értéke együttesen írja le, amit webtile esetén nem tudunk vizsgálni.
  • A Futár API-tól a következő indulások objektum tömbként kérhetők le, azonban egyik lehetséges webtile layout sem tudja azokat praktikusan megjeleníteni. Sokkal jobb lenne egy vesszővel elválasztott string, például “10:45, 10:56, 11:07”, de ilyen adat átalakításra a webtile nem képes.

Ezen problémák miatt végül úgy döntöttem, hogy készítek egy saját webszervizt, ami adatokkal fogja táplálni Bandit. Tekintve, hogy viszonylag primitív logikáról van szó, ellenben van benne JSON matatás rendesen, és mostanában elsősorban JavaScriptben dolgozom, egy Node.js-es szolgáltatást készítettem. Webszerver frameworkként Hapi-t, a Futár API hívásához pedig a request-promise NPM package-et választottam, mert ezeket már ismertem korábban.

Mivel a webtile nem paraméterezhető, nem láttam értelmét olyan szolgáltatást készítésének, amit bárki, bármilyen járat indulásainak lekérésére használhat. Ez nagyban egyszerűsítette a dolgomat, mert így a KoviBuszból kikeresett megálló azonosítókat én bizony simán beledrótoztam a forráskódba. Az én szervizem, az én megállóim. Persze a forráskódot kitettem Githubra, hogy bárki barkácsolhasson magának hasonlót, vagy még jobbat:

github-logo

 https://github.com/balassy/band-futar-tile

Íme néhány érdekesebb pont a kódból:

  • A webszerviz kódja az src mappában található, a webtile által hívott végpont pedig azon belül a next-ride mappában.
  • Azon belül a service.js hívja a Futár API-t a paraméterként kapott megálló azonosítóval.
  • A service.js-t a controller.js hívja, átadva neki a keresett megállók azonosítóit.
  • A gulpfile.js az urbanjs-tools nevű NPM package-t használja statikus kódelemzésre, ami nagyon kényelmessé teszi az ESLint és az ES6 használatát.
  • A forráskódot Visual Studio Code-dal írtam, erre utalnak a .vscode, typings mappák és a tsd.json fájl. (Igen, a typings mappát nem kellene betenni a repoba, de így sokkal kényelmesebb volt.)
  • A projektet pillanatok alatt sikerült bekötnöm Travisbe és AppVeyorba, ezek beállításai találhatók a .travis.yml és az appveyor.yml fájlokban. Ezek az ingyenes online build környezetek segítettek a forráskód folyamatos karbantartásában, mindkettőt csak ajánlani tudom.

Hosting környezetnek természetesen Azure-t választottam, mert piszkosul egyszerű egy Githubon tárolt web alkalmazás continuous deploymentjét összelőni. Most amint felküldök egy kód módosítást a Githubra, lefut a build Travisben és települ is ki automatikusan az Azure-os webszerverre. Ez az automatizmus még egy ilyen egyszerű alkalmazás esetén is óriási segítség fejlesztés közben.

A webtile

A webtile elkészítéséhez az első részben is említett varázslót használtam. Úgy döntöttem, hogy ez egyes járatok adatait külön page-en fogom megjeleníteni (Multiple page tile), azon belül egy a Scrolling text wrap (MSBand_ScrollingText) elrendezés bizonyult legpraktikusabbnak az ismeretlen hosszúságú szöveg megjelenítésére. Ezt így mutatja a varázsló (az 59-es villamos következő indulásai a Vas Gereben utcai megállóból):

band-webtile-wizard-preview-1

Jelenleg a szerviz az engem leginkább érdeklő három járat adatait adja vissza, ezek mind külön page-et kaptak, utánuk pedig egy negyedik oldalra az utolsó frissítés időpontját tettem. Ez hibakereséshez lehet jó, a szerviz a válasz JSON egyik property-jében visszaadja, hogy mikor kérte le utoljára az adatokat a Futár API-tól, így könnyű volt megjeleníteni:

band-webtile-wizard-preview-2

A varázsló által generált webtile-t nem közvetlenül telepítettem Bandira, hanem letöltöttem, kicsomagoltam (mert valójában egy ZIP fájl), és módosítottam rajta (a végeredmény megtalálható a a webtile/manifest.json fájlban):

  • Kijavítottam azokat az apró hibákat, amiket a webes varázslóban egyszerűen nem sikerült.
  • Beállítottam a refreshIntervalMinutes tulajdonság értékét 15-re, ami negyedórás frissítési időközt jelent, ennél sűrűbben nem is lehet.
  • Beállítottam a version és a versionString tulajdonságokat, és minden újabb kísérletnél inkrementáltam őket, hogy biztosan észrevegye a Microsoft Health alkalmazás, hogy újabb verziót akarok telepíteni.
  • Beállítottam a name, description, author, organization és contactEmail tulajdonságok értékeit, hogy azok kulturáltan jelenjenek meg telepítéskor.

Jelenleg a webszerviz HTTP 500 status code-dal tér vissza, ha valami nem sikerül szerver oldalon, de erősen gondolkodom rajta, hogy hibakeresési célzattal minden ilyen esetben HTTP 200 OK-val térjek vissza, és a hiba leírását adjam vissza a válaszban, hogy azt könnyen meg lehessen jeleníteni a Banden.

A végeredmény

Örömmel tölt el, hogy az elkészült megoldás működik, a Futár API-tól kapott adatok megjelennek, és a megoldás nem bonyolult.

band-futar-tile

band-futar-page

band-futar-update-page

A Futár igazi értéke abban van, hogy nem csak egy sima menetrend, hanem (elméletileg legalábbis) valós idejű adatokat tartalmaz, azaz az aktuális forgalmi helyzetet tükrözi. Sajnos a webtile legjobb esetben is negyedórás frissítési időköze ezt a remek lehetőséget tökéletesen megöli, ami már kevésbé örvendetes, hiszen így az esetek nagy részében “csak” a menetrendi adatokat látom, ami Tokióban minden bizonnyal tökéletesen működne, Budapesten még nem 100%-os. Mivel engem leggyakrabban egy villamosmegálló és egy buszvégállomás indulási időpontjai érdekelnek, számomra egészen jól használható a végeredmény.

Te milyen adatokat látnál szívesen az órádon?

 

Technorati-címkék: ,

BKK Futár Microsoft Bandre – a BKK Futár API (2. rész)

Ahogy az előző részben említettem, azt tűztem ki célul, hogy a BKK Futártól kapott aktuális tömegközlekedési információkat okosórán, konkrétan Microsoft Banden jelenítem meg. A Band programozási lehetőségeinek áttekintése után ebben a részben először nézzük meg azt, hogy a BKK Futár adatait hogyan érhetjük el.

A BKK Futár API

A Budapesti Közlekedése Központ honlapján igen haladó módon létezik egy Fejlesztőknek szóló oldal, ahol gyorsan kiderült, hogy nem rám gondoltak. A BKK megközelítése az, hogy a menetrendi információkat bizonyos időközönként publikálják az oldalukon egy kb. 28 MB-os ZIP fájlban. Értem én, hogy a ZIP-ben GTFS, azaz General Transit Feed Specification formátumban vannak az adatok, ami igen elterjedt, hiszen a G csak udvariasságból General és nem Google, meg hogy így könnyű feltölteni a Mapsre és hogy sűrűn frissítik, ez tényleg szép, csak nekem éppen most pont nem jó.

A következő utam a BKK Futár oldalára vezetett, ahol minden bevezető nélkül egy interaktív térképet találhatunk, ami már sokkal érdekesebb, hiszen ez teljesen friss adatokkal dolgozik. Irány a fejlesztőknek szóló leírás: F12. Nem is kellett sokáig keresgélni a Firebugban, hogy ráleljek erre a kérésre (kattints a teljes méretű képért):

ms-band-4-futar-api

Ebből az egyetlen kérésből több dolog is kiderült:

  • Létezik API, sőt már az URL-jét is tudom. Kellene dokumentáció, amiből kiderül, hogy milyen végpontok vannak.
  • Az API verziózottnak tűnik, ami általában jó hír. Kellene dokumentáció, amiből kiderül, hogy milyen verziók léteznek.
  • Az API hívásához lehet, hogy kell API kulcs. Kellene dokumentáció, amiből kiderül, honnan lesz API kulcsom.
  • Lehet, hogy van throttling, legalábbis a data.limitExceeded mező erre utal. Kellene dokumentáció, amiből kiderül, hogy mennyi az annyi.
  • Státusz információ van bőven: a HTTP státusz kódon kívül a válaszban is van egy status, egy code, és egy text mező, sőt (és ez a fenti képen nem látszik) a szerver még egy X-BKK-Status fejlécet is visszaküld “OK” értékkel. Kellene egy dokumentáció, amiből kiderül, hogy melyik kell nekem.

Ez elég volt ahhoz, hogy elinduljak, de minden jel arra utalt, hogy nagy hasznát venném bármiféle további dokumentációnak.

Neki is álltam óriási lelkesedéssel, keresgéltem a BKK oldalán, a Bingben, de sajnos az összes Google-fu tudásom is kevésnek bizonyult, nem találtam hivatalos leírást. (Aki ismer ilyet, kérem küldje el nekem, köszönöm.)

Találtam viszont több nem hivatalos forrást is:

  • Létezik egy Index Fórum “A BKV GTFS adatbázisa” címmel, ahonnan számomra az derült ki, hogy a nép szenved a GTFS-től és egy barátságosabb API-t szeretne.
  • Az Apiary oldalán találtam egy dokumentációt BKK FUTÁR Utazástervező API címmel. Sajnos nem tűnik hivatalosnak, használhatónak viszont annál inkább.
  • Nádai Gábor (alias Mefi) nevén találtam egy Github repót KoviBusz néven, ami egy adott busz következő indulási idejét mutatja az API-t felhasználva. A kód Node.js-ben készült, és egy barátságos fájlban JSON formátumban tartalmazza a megállókat.

Járatinformációk

Az Apiary dokumentáció és a Firebug böngészése közben világossá vált, hogy nekem az Arrivals and Departures for Stop (nem is olyan nehéz egy API-t jól elnevezni, igaz?) API-ra van szükségem, amit így kell meghívni:

GET http://futar.bkk.hu/bkk-utvonaltervezo-api/ws/otp/api/where/arrivals-and-departures-for-stop.json?stopId&onlyDepartures&minutesBefore&minutesAfter

Ahol:

  • A stopId a megálló azonosítója, például BKK_F00945.
  • Az onlyDepartures paramétert true-ra állítva megadhatjuk, hogy csak az indulások érdekelnek.
  • A doksi szerint a minutesBefore-ral lekérdezhetjük a korábban elment járatokat, ami Marty McFly számára kétségkívül egy hasznos funkció, nálam 0 lesz, az biztos.
  • A minutesAfter-rel pedig azt állíthatjuk be, hogy hány percre előre szeretnénk lekérni az érkező és induló járatokat.

Következő lépésként megálló azonosítóra volt szükségem. Ehhez legjobb forrásnak a Mefi KoviBusz oldala bizonyult, ami térképen kirajzolja az összes megállót, csak rá kell bökni valamelyikre, és Firebugban máris látszódik az azonosítója. A József Nádor tér például F00979.

GET-es API-ról lévén szó, ezt könnyen ki is próbálhatjuk, csak tegyük a megálló azonosítója elé a BKK_ előtagot, és írjuk be a címet a böngésző címsorába:

http://futar.bkk.hu/bkk-utvonaltervezo-api/ws/otp/api/where/arrivals-and-departures-for-stop.json?stopId=BKK_F00979

Íme a szervertől kapott válasz, ahogy azt a Chrome mutatja:

ms-band-5-futar-api-response

Kiemeltem néhány érdekességet:

  • A dátumok és időpontok igen barátságtalanok: nem csak hogy epochtól számított számként jönnek, de hol másodpercben, hol milliszekundumban vannak kifejezve. És akkor az időzónákról még nem is beszéltünk.
  • A következő indulásoknál megjelenik a predictedArrivalTime tulajdonság, sőt létezik predictedDepartureTime is. Végállomásoknál indulási oldalon egyik sincs, csak departureTime.
  • Ebben a megállóban két járat is megáll, a 16-os és a 105-ös. Mi a stop azonosítóját tudjuk, ahhoz tartoznak stopTime-ok, ahhoz trip-ek és végül ahhoz route-ok.

Erős nézés módszerével meglett tehát az API, amiből kinyerhetőek az adatok, már csak össze kell kötnünk a Banddel.

 

(Folytatás következik…)

 

Technorati-címkék: ,

BKK Futár Microsoft Bandre (1. rész)

ms-band-1Nem rég szerencsés tulajdonosa lettem egy Microsoft Bandnek, és természetesen legjobban arra voltam kíváncsi, hogyan készíthetek rá saját alkalmazást. Első célul azt tűztem ki, hogy a BKK Futártól származó információkat fogom rajta megjeleníteni, hiszen milyen jó lenne, hogy amikor kilépek a lakásból csak ránézek az órámra, és rögtön látom, hogy mikor jön a következő buszom. Bandiban van GPS, a telefonon keresztül kilát az internetre, így első körben ez a feladat megvalósíthatónak látszott.

Korlátlan lehetőségek fejlesztőknek

A Microsoft Band “For Developers” oldalára ellátogatva gyorsan fel tudjuk mérni, hogy fejlesztőként háromféle irányból támadhatjuk meg ezt az eszközt.

A Band SDK-t felhasználva készíthetünk egy Windows, Android vagy iOS alkalmazást, ami képes kommunikálni a Band-del. Van szép PDF dokumentáció sok példakóddal, sőt még design guidelines-t is kapunk. A telefonon futó alkalmazás eléri a szenzorokat, új csempéket, azon belül pedig oldalakat és UI vezérlőket tud megjeleníteni.

Készítethetünk Web Tile-t, amihez még különösebb fejlesztői tudás sem kell. Egy böngészőben futó varázsló segítségével kiválaszthatjuk, hogy milyen URL-ről érkező adatokat milyen formában szeretnénk megjeleníteni. A web tile JSON vagy RSS adatokat tud letölteni és megmutatni, sőt még arra is képes, hogy ha a letöltött adatok megfelelnek az általunk megadott feltételnek, akkor a Band megjelenít egy értesítést. Ezek a lehetséges elrendezések:

ms-band-2-tile-layouts

Az elkészült Web Tile-t a készítő feltöltheti egy galériába, ahonnan bárki két kattintással letöltheti azt a telefonjára, majd onnan a Bandjére.

A harmadik lehetőség a Microsoft Health Cloud API használata, ahol egy szép REST API-n keresztül kérhetünk le adatokat a felhasználóról és edzéseiről. Az API kevés végpontot tartalmaz, de ezek sok adatot tudnak visszaadni:

ms-band-3-swagger

A korlátlan lehetőségei korlátai

Első körben tehát el kell döntenünk, hogy hogyan akarjuk megközelíteni a problémát: SDK-val, Web Tile-lal vagy felhős API-val.

SDK

Az első lehetőség az SDK, ami a dokumentáció alapján nagyon izgalmasnak tűnik, de fontos megérteni, hogy

nem a Bandre írjuk az alkalmazást.

Készítünk egy telefonos vagy Windowsos alkalmazást, ami használja a Bandet, de nem a Banden fut. Nincs új projekt típus a Visual Studioban, sőt még azt sem mondhatjuk el, hogy a Banden is Windows 10 futna, mert nem (még). Az alkalmazásunk szempontjából a Band leginkább egy érintőkijelzőre hasonlít, amiben vannak egyéb szenzorok is.

Ez sajnos rögtön magával hozza azt a korlátozást is, hogy a telefonos alkalmazás tudja elérni a Bandet, nem pedig a karperec a telefonos alkalmazást. Tehát készíthetünk egy olyan mobil appot, ami elkéri a Bandtől a pulzusszámunkat vagy a napi kalória fogyasztásunkat, de azt nem lehet megoldani (még), hogy az óránkon kezdeményezzünk bármit, mert a telefonos alkalmazás nélkül a Banden sem történik semmi. Azaz a telefonos alkalmazásnak mindig futnia kell, ami például Windows Phone-on egyelőre csak elég korlátozottan oldható meg (ebben a Windows 10 és a DeviceUseTrigger tud segíteni). Kivétel ez alól a Cortana, mert a Bandről indított hangvezérléssel lehet alkalmazást aktiválni a telefonon, de nálunk ugye nincs Cortana.

A második erős korlátozás a UI. Nem elég, hogy kicsi a képernyő, a felhasználható vezérlők  listája is elég rövid:

  • Egyszerű vezérlők:
    • TextBlock
    • WrappedTextBlock
    • Icon
    • Barcode
    • TextButton
    • FilledButton
  • Konténer vezérlők:
    • FlowPanel
    • ScrollFlowPanel
    • FilledPanel

A jó hír, hogy van gomb, de ne feledjük, hogy csak akkor ér valamit, ha a hozzá tartozó eseménykezelőt tartalmazó telefonos alkalmazás fut éppen.

A rossz hír, hogy gyakorlatilag nincsenek input vezérlők, se szövegdoboz, se lista, semmi. Pedig a Banden még mini billentyűzet is van, hiszen SMS-ekre tudunk onnan válaszolni, ez azonban jelenleg nem érhető el más alkalmazások számára. Arról se álmodjunk, hogy akkor majd mi megoldjuk egyszerű vezérlőkből, ugyanis azokból maximum 10 lehet egy oldalon (page-en).

Ezek után az, hogy a vezérlőkre a számukkal kell hivatkozni, és a gomb eseménykezelőt nem is a gombhoz, hanem az egész csempéhez (lényegében az alkalmazáshoz) kapcsoljuk, és a kódban kell megvizsgálni, hogy melyik gombra nyomott a felhasználó, már nem is tűnik komoly korlátozásnak.

A szenzorok között vannak olyanok (nem mind, de például a szívritmus), amit a felhasználó tudta nélkül nem lehet kiolvasni. Ez a gyakorlatban azt jelenti, hogy az alkalmazásnak először egy GetCurrentUserConsent() függvényt kell hívnia, ami feldob egy engedélykérő ablakot, ahol a felhasználó eldöntheti, hogy az app olvashatja-e azt a szenzort vagy nem. Ez rögtön meghatározza, hogy olyan alkalmazást kell írnunk, amihez tartozik felhasználói felület, azaz háttérben futó windows service-ek és headless IoT alkalmazások kizárva. Nem barkácsolhatunk olyan ventillátort, ami Bluetooth-on keresztül közvetlenül a Bandről olvassa a szívverésemet, és ha magas szívritmust érzékel, bekapcsol, mert a kijelző nélküli ventillátor nem tud engedélyt kérni a HeartRate szenzor olvasásához. Mindenképpen szükségünk van a telefonra az engedélyezés miatt.

Web Tile

A Web Tile egyszerűen elkészíthető és praktikus megoldás például hírportálok információinak megjelenítésére: csak rákötöm a meglévő RSS feedre és már készen is van. Érdemes azonban átgondolni, hogy valóban a meglévő JSON-os végpont vagy RSS feed a legoptimálisabb-e a Band számára, mert a kijelző mérete korlátos, és a web tile nem képes a letöltött adatokon semmilyen formázást elvégezni. A varázslóban csak azt tudjuk megmondani, hogy a szervertől kapott JSON válasz egyes property-jei melyik TextBlockokban jelenjenek meg. Ha a szöveg túl hosszú, nem fog kiférni (kivéve a görgethető elrendezés esetén), hanem egyszerűen levágódik. A legbonyolultabb művelet a sztring összefűzés (több property megjelenítése egy TextBlockban), de arról ne is álmodjunk, hogy számot fogunk dátummá konvertálni, vagy kiszámoljuk az eltelt időt két időpont között.

Ahogy a fenti képen is látszik, a varázsló felkínálja, hogy válasszunk a 6 előre definiált oldalrendezés közül. Más lehetőségünk nincs, ezek valamelyikén (vagy több oldalon) kell elrendeznünk a megjeleníteni kívánt információkat. A hatból 3 elrendezés képes képet megjeleníteni, ezek azonban csak kis méretű, átlátszó hátterű, fehér ikonok lehetnek, amik már a tile telepítésekor rendelkezésre állnak. Arra például nincs lehetőségünk, hogy fotót vagy szerverről letöltött képet jelenítsünk meg (például árfolyamok alakulása on-demand rajzolva). Jó hír viszont, hogy a csomagba tehetünk több ikont, és meghatározhatjuk, hogy feltételtől függően melyik jelenjen meg (például különböző időjárás ikonok).

Érdemes egyébként elolvasni a web tile specifikációt, mert a varázsló csak a fontosabb paramétereket állítja be, nem kérdez rá mindenre. Az egyik ilyen kimaradó paraméter a refreshIntervalMinutes, amivel azt állíthatjuk be, hogy milyen gyakran frissüljön a csempe. Ennek az értéke alapértelmezés szerint 30 perc, de akár 15 percre is állíthatjuk (sűrűbbre nem). Ehhez nevezzük át a varázsló által generált .webtile fájlt .zip-re, csomagoljuk ki, majd módosítsuk a benne található manifest.json fájlt.

Sajnos a gyakorlatban azt tapasztaltam (és a StackOverflow szerint nem vagyok ezzel egyedül), hogy az adatok néha a megadottnál jóval ritkábban frissülnek, nálam volt olyan, hogy 3 óra is eltelt két frissítés között. A sikeres frissítéshez a HTTP válasznak 200 OK-val kell visszatérnie, és a szokásos kliens oldali gyorsítótárazási módszerek itt is bezavarhatnak.

A web tile által hívott URL fix és csak GET lehet, tehát ne is álmodozzunk például arról, hogy majd így küldjük fel az UV szenzor által mért értékeket.

 

Ezek alapján szerintetek hogy lenne a legpraktikusabb megvalósítani a BKK Futárt Microsoft Bandre?

 

(Folytatás következik…)

 

Technorati-címkék: ,