Archiv rubriky: Linuxové parádičky

Linuxové parádičky obsahují většinou návody na složitější úkony, které jsem pracně dohledal či vymyslel a nerad bych o ně přišel, jsou tedy především pro mě, ale někomu se mohou také hodit. Nezříkda se však setkám s věcmi, které jsou na OS od MS nemyslitelné ale skvělé, to jsou pak parádičky, co to může být? Linux v routeru, Linux v Raspberry PI, který je pořád Linuxem, tak jak jsem s ním zvyklý pracovat či se v něm povrtat na PC, to mi přijde úžasné.

Rozbité Ubuntu

Dnes po dlouhé době a jen krátce. Protože končila podpora verze 13.04, rozhodl jsem se přejít ještě na 13.10 a pak snad skončím na LTS protože můj ThinkPad už není nejnovější zařízení. Po přechodu přestala řada věcí fungovat solidně a disfunkce překročila míru, kterou jsem schopen akceptovat a při běžném použití přehlížet. Vadilo mi zejména zjevné zpomalení, na všechno musím dlouho čekat, první v čem jsem se hrabal bylo plánování výkonu procesoru. Zdálo se, že je to lepší, tak jsem se chtěl pohrabat ještě ve výkonu grafické karty a přidal jsem si Oibaf ppa. To byla velká chyba a systém byl téměř nepoužitelný, ale i z toho se Ubuntu vylízalo. A minulý týden jsem vyřešil i problém se spouštěním a probouzením ze spánku tak, že jsem v nastavení Compizu zakázal OpenGL. Při startu jsem totiž hned po Grubu viděl postupně bělající obrazovku, zato po probuzení zůstala nerozsvícená. Neustálé restarty mi už lezly krkem, a zkoušel jsem všechno, co jsem na diskusích nalezl.

Další drobnost jen na okraj. Odešel mi převodník PS/2 > USB, takže jsem si mohl s klidným srdcem pořídit vyhlídnutou herní myš, která je zdá se perfektní pro můj styl úchopu. Jde o CM Storm Xornet. Nestojí o moc víc, než běžné křápy za 300, kterých jsou obchody s elektronikou plné. Je ergonomicky tvarovaná, extra tlačítka pro prohlížeč, když už Opera není ta pravá Opera s tlačítkovými gesty. Pěkně klouže, můžu měnit DPI, tj. rychlost pohybu kurzoru po obrazovce. Dlouhý měkký kabel a jako třešnička na dortu, která za ty peníze stojí je vypínání senzoru. Musím to ještě pořádně okouknout za jakých podmínek to nastává, ale při přechodu počítače do spánku se vypne senzor, takže se pak nezapne, pokud někdo nebo něco do myši šťouchne náhodou.

Nová sestava

Notebook už mám plný fotek, než se otevře nějaké okno, musím chvíli počkat a dalším počítačům v domácnosti vždycky něco chybí, buď procesor, nebo zase paměť, úložný prostor. Žádný z počítačů prostě není univerzální mašina. To měla napravit nová pracovní stanice/server, byť by měla být co nejlevnější a tedy z běžných desktopových dílů. Sestava postupně vykrystalizovala do podoby:

  • Intel Core i5 4570, čtyřjádro, 3,2 GHz
  • MSI H87M-G43, chipset H87, 6× SATA III, až 64 GB DDR3, 1600 MHz (16 GB moduly ještě ale nejsou, a kdo ví jestli kdy budou)
  • Crucial Ballistix Sport 16 GB, 1600 MHz, 2×8 GB moduly
  • Kingston SSDNow V300, 60GB
  • SEASONIC SSP-550RT, 550W, 80+ GOLD s podporou C6/C7
  • ASUS TA8G1 Second Edition

To je nutný základ za 13 500 Kč. Mašinka šlape pěkně a všechno má hned hotové. Dále se bude rozšiřovat, aby plnil všechny zamýšlené úkoly, o:

  • Crucial Ballistix Sport 16 GB, 1600 MHz, další 2×8 GB moduly
  • Seagate Barracuda 7200.14, 2TB, pro /home, /var, /tmp, a nejspíš i swap
  • Seagate SV35.5, 3TB, (pravděpodobně), čtyři disky do RAID 5, pro fotky a případná videa
  • větrák k diskům
  • UPS

Deska od MSI snad vydrží, vybral jsem si ji kvůli DisplayPortu, optickému výstupu na zvuk. Rozchodil jsem WoL, ale nikde v BIOSu nevidím aktivaci C6/C7 o kterých jsem čítával, že budou deaktivované. Ještě projdu internet, abych si rozšířil obzory. Počítač běží na Ubuntu 13.04 bez zjevných problémů. Rozjel jsem na něm Day of Defeat: Source na, řekl bych, střední detaily přes integrovanou grafiku, kterou jsem při výběru procesoru považoval za plus. Nechtělo se mi dávat další peníze dedikovanou kartu např. spolu s FX-8300, po kterém jsem se také poohlížel, ale nakonec by vyšlo dráž než i5 a měl bych v počítači dvě topná tělesa. Haswell má sice od minulé generace zvýšenou produkci tepla, ale na AMD to ještě nestačí. Poslední co mě trápí je větrák v bedně Asus, je sice připojen na desku třípinem, ale pořád se točí na maximum 3000 rpm, přesto, že jsem mu nastavil v BIOSu 50 % otáček. To ale zřejmě funguje až se čtyřpinem. Nyní se potýkám s TVheadend, který jsem chtěl ze starého počítače přesunout jako první. Problém s USB přímačem Genius je ten, že se stejným firmwarem, jaký mám na notebook, nechce nic přehrát. Zato ten nový dongle z dx.com najednou funguje, když před tím v Debianu nešel. Navíc mi došly konektory k anténě 🙂

Edit: Z větráku v bedně jsem měl před nákupem radost. Nemusel bych ho kupovat zvlášť, ale chtěl jsem vyzkoušet, jak hlučný je počítač bez něj. Tak jsem milý kablík vytáhl a najednou — ticho! Je tišší než můj Thinkpad. Přesunul jsem /tmp na RAMku, návodů se dá najít spousta a dal jsem prozatím 2 GB místa, osmconvert je dosti žravý. Po přikoupení dalších paměťových modulů bude možno přitvrdit. Další opatření pro SSD skýtalo jen trim pro /. Poznámka pro budoucí Já: příště udělat z tvheadend rovnou deb balíčky a pak instalovat! Ušetřím si tím práci.

Edit 2: Nakonec jsem na /home /var a swap koupil právě SV35.5 3TB. Zatím jen třídím staré fotky, které mám mnohdy duplicitní z různých úložišť pomocí skvělého DIGIKAMu. TVHeadEnd nekdy funguje dva dny ale spíše je třeba kontrolovat funkčnost před nahráváním a to tak, že tvheadend zabiju vypojím USB přijímač a znovu zapojím a zapnu tvheadend. Vše samozřejmě přes skript, jen vypojování je manuální. Zřejmě padá spojení s přijímačem, které už software nerozchodí. Čekám na nové jádro. Dále jsem rozjel tile server pro OSM. Naivně jsem si představoval, že budu mít dlaždice pro MOBAC a databázi, nad kterou běží renderd, ze které budu tahat data v xml pro tvorbu map pro Android. Bohužel jsem po několika týdnech bloumání zjistil, že osm2pgsql tvoří speciální tabulky, vhodné pro vykreslování a pro surová data budu muset zavést druhou databázi. K vytvoření té jsem se však ještě nedostal. Až bude hotovo, napíšu článeček.větrák k diskům

Ubuntu 13.04

Jelikož jsem měl před koncem studia, potřeboval jsem co nejspolehlivější počítač a upgrade na 13.04 nepřipadal v úvahu. Nyní mám už hotovo a tak jako v minulosti jsem se rozhodl povýšit systém, byť jsem měl pochyby, zda to mám dělat. Bohužel jsem tuze prohloupil a zbytečně jsem se obral o funkce, zejména v Nautilu. Jiných chybějících důležitých drobností jsem si ještě nevšiml.
Původně jsem se obával o ovladače mé hloupé grafické karty od Ati, ale protože používám otevřené, vše zatím běží dál. Na co jsem však během dvou měsíců od prvních recenzí zapomněl je ten Nautilus.
První problém nastal, když jsem se chtěl připojit na RaspberryPI přes SSH a prohlédnout si fotky ze sledovací webkamery. Nejde to, pokud používáte Gnome Shell, hlavní nabídka prostě chybí. Stávající záložky na servery nejde měnit. Poklepáním na skript s příznakem spuštění rovnou otevře textový editor, prostě blbost na entou. Dále se network-manager zcela nesmyslně připojuje na školní drátovou síť když jsem doma, ve škole pak na nešifrované místo šifrovaného bezdrátového připojení i přes to, že vše v minulých verzích bylo bez problému. A tím snad výčet skončí, ale zatím mám 13.04 jen dva dny a možná se ještě něco objeví. Nicméně můžu vinit jen sebe, takže pro ostatní: oči na stopky!

Jednoduchý střih videa

Nemnohokráte si natáčím techniku jednotlivců na překážkách běhu na 100~metrů. Vedle běžné rychlosti je pěkné mít i zpomalené záběry. Do této doby jsem používal běžné střižny jako Pitivi nebo OpenShot. Moje instalace Ubuntu je dost rozhašená, třeba vůbec nefunguje Totem a teď se k tomu přidaly oba programy na stříhání. Naštěstí všechno zachraňuje AviDemux, který požívám pro vystříhání krátkých úseků z dlouhého záznamu z kamery na stativu. Nejen, že si vystříhám úseky, můžu je snadno slepit zasebou a to je vlastně vše co potřebuji, žádné přechody, stmívání a další blbinky. Slepené kousky videa následně zpomalím a oba kusy slepím do jednoho tak, že závodníci proběhnou rychle a v druhé části zpomaleně. Takže rozdělím části tvorby videa na body.

Zdroj: dlouhé video ve formátu avi z Pentax K-r.

  • Nastavit značku A na začátek vybraného úseku.
  • Nastavit značku B na začátek vybraného úseku.
  • Uložit daný úsek na disk jen jako kopii video i audio stopy, nedochází tak ke ztrátě kvality.

Zdroj: jednotlivé krátké úseky původního videa.

  • První video otevřít v novém okně.
  • Další videa Připojit (Soubor->Připojit Ctrl+Alt+A)
  • Uložit celou stopu na disk jen jako kopii video i audio stopy, nedochází tak ke ztrátě kvality.
  • Nyní v hlavním menu Video->Snímková frekvence a zvolit nižší, já volím 5~FPS
  • V levém panelu Video namísto Kopie zvolit skutečný obsah kontejneru avi, v mém případě M-JPEG, a to jen proto, aby se jakžtakž zachovala kvalita.
  • Ve volbě Filtry zvolit Resample fps a vrátit hodnotu na původních např. 25~FPS.
  • V hlavním panelu zvolit Audio->Hlavní stopa a tam zvolit Zdroj: Nic. Jinak by pod zpomaleným videem neustále dokola běžel nezpomalený zvuk z původního kousku videa.
  • Nyní to je vše a můžeme zpomalené video uložit na disk.

Je-li třeba slepit videa různých rozlišení:

  • Video nižšího rozlišení otevřít v novém okně.
  • V levém panelu Video namísto Kopie zvolit skutečný obsah kontejneru avi, v mém případě M-JPEG, a to jen proto, aby se jakžtakž zachovala kvalita.
  • Ve volbě Filtry zvolit Add black borders a nastavit rozměry tak, aby se výsledné rozlišení shodovalo s rozměrem většího videa.
  • Uložit video na disk.

Zdroj: běžná a zpomalená stopáž.

  • Jedno video otevřít v novém okně.
  • Druhé či každé další znovu Připojit, jak už bylo popsáno.
  • Uložit jako kopii jsou-li formáty kompatibilní.

Náhledy surových fotek

Nevím jakou měrou to využiju, ale čas od času jistě. Do této doby jsem měl v Nautilu náhledy fotek v RAW jen jako šedivé obdélníky. Když jsem se potřeboval podívat, o kterou akci jde a neměl jsem zrovna spuštěný digikam, naslepo jsem pár fotek otevřel v ufraw a bylo jasno. Proč si život nezpříjemnit, tím, co jsem dnes náhodou nalezl na české diskusi k Ubuntu. Tam najdete odkaz na askubuntu, kde je napsáno, že stačí mít onen ufraw, a pak vytvořit soubor /usr/share/thumbnailers/ufraw.thumbnailer:

nano /usr/share/thumbnailers/ufraw.thumbnailer

a do něj vložit:
[Thumbnailer Entry]
Exec=/usr/bin/ufraw-batch --embedded-image --out-type=png --size=%s %u --overwrite --silent --output=%o
MimeType=image/x-3fr;image/x-adobe-dng;image/x-arw;image/x-bay;image/x-canon-cr2;image/x-canon-crw;image/x-cap;image/x-cr2;image/x-crw;image/x-dcr;image/x-dcraw;image/x-dcs;image/x-dng;image/x-drf;image/x-eip;image/x-erf;image/x-fff;image/x-fuji-raf;image/x-iiq;image/x-k25;image/x-kdc;image/x-mef;image/x-minolta-mrw;image/x-mos;image/x-mrw;image/x-nef;image/x-nikon-nef;image/x-nrw;image/x-olympus-orf;image/x-orf;image/x-panasonic-raw;image/x-pef;image/x-pentax-pef;image/x-ptx;image/x-pxn;image/x-r3d;image/x-raf;image/x-raw;image/x-rw2;image/x-rwl;image/x-rwz;image/x-sigma-x3f;image/x-sony-arw;image/x-sony-sr2;image/x-sony-srf;image/x-sr2;image/x-srf;image/x-x3f;

A je to, díky.

OSM a Python

Protože mám doma Raspberry PI, přirostl mi k srdci programovací jazyk Python. Při psaní je nutné dodržovat odsazování vnořených bloků, čímž je na druhou stranu možné zbavit se nepraktického závorkování a středníků na konci řádku. Syntaxe má také blíž k běžnému jazyku, a v neposlední řadě jsme zbaveni nutného kompilování a následného spouštění ve speciálním editoru.
Napsat program v Pythonu tedy není nijak těžké, dnes zveřejním k libovolnému užití kód, který používám k vytváření mapy na základě OSM do svého Androida. Původně byl vytvořen v Qt, které mám také velmi rád, ale postupně se mi na tak malém projektu přestala líbit složitost úprav a neustálé kompilování. Tvorba zabrala několik dlouhých nocí, než byl program vyladěn a urychlen z původní hodiny a půl běhu na 17 minut. V Pythonu se díky využití jeho základních struktur čas zkrátil dokonce na deset minut, ale pak jsme přidával další kontroly a vylepšováky, což běh o nějakou dobu protáhne. Protože jde o moje dítko a piplání mi zabralo nějaký čas, nejprve jsem jej zveřejňovat nechtěl, ale pak jsem si řekl, že s Linuxem měl taky kdosi spoustu práce… Stejně si myslím (mám tady jeden), že existují mnohem sofistikovanější skripty, které procházejí přímo databázi. Tu já ale k dispozici nemám, přestože jsem na stránky umístil reklamu, za měsíc lidé naklikali asi 5 Kč a za to si server nepořídím. Skript funguje jednoduše, nechá si pomocí osmconvert převést PBF do XML formátu, ten přelouská, najde relace s trasami KČT a přesype vybrané tagy z relace na všechny cesty, které jsou jejími členy. výsledek opět vrátí do osmconvert, který tedy musí ležet vedle skriptu, a ten jej převede zpět do PBF tak, aby se maximálně šetřilo místo na mém zaplněném disku osobního počítače.
Vytvořené mapy už je jiná záležitost, která zahrnuje všehovšudy jeden příkaz do osmosis, ale o tom třeba jindy.

#!/usr/bin/python
# -*- coding: utf-8 -*-

__author__="Speirs"

import sys, re, subprocess

#nodes = subprocess.Popen(["./osmconvert", "--drop-relations", "--drop-ways", sys.argv[1]], stdout=subprocess.PIPE)
#ways = subprocess.Popen(["./osmconvert", "--drop-relations", "--drop-nodes", sys.argv[1]], stdout=subprocess.PIPE)
mapFile = subprocess.Popen(["./osmconvert", sys.argv[1]], stdout=subprocess.PIPE)
relations = subprocess.Popen(["./osmconvert", "--drop-nodes", "--drop-ways", sys.argv[1]], stdout=subprocess.PIPE)

nodeStart = re.compile('\s*<node id="(\d+)" lat="([0-9.]*)" lon="([0-9.]*)"')
nodeEnd = re.compile('\s*</node>')
wayStart = re.compile('\s*<way id="(\d+)"\s')
wayEnd = re.compile('\s*</way>')
relationStart = re.compile('\s*<relation id="(\d+)"')
relationEnd = re.compile('\s*</relation>')

nodeID = re.compile( '\s*<nd ref="(\d+)"')
hikeRoute = re.compile('\s*<tag k=\"route\" v=\"(hiking|foot)\"')
kctRoute = re.compile('\s*<tag k=\"kct_.+\" v=\"')
bikeRoute = re.compile('\s*<tag k=\"route\" v=\"(bicycle|mtb)\"')
tag = re.compile('\s*<tag k=\"(.+)\" v=\"(.+)\"')
member = re.compile('\s*<member type="(.+)" ref="(.+)"\s')

stack = []
wayTags = {}

def compare(a, b):
        return cmp(int(a), int(b))
        
def combine(i, l):
	for key, value in l.items():
		if (key in ('name', 'ref')) and (key in wayTags[i]):
			if value not in wayTags[i][key].split(','):
				wayTags[i][key] = wayTags[i][key] + ',' + value
		else:
			wayTags[i][key] = value
        
def printTag(key, value):
        print '\t\t<tag k="{}" v="{}"/>'.format(key, value)
        
def hikingRoute(l):
	wayIds = []
	tags = {}
	kctKeys = ('kct_red', 'kct_blue', 'kct_green', 'kct_yellow')
	kctValues = ('major', 'local', 'peak', 'learning', 'ruin', 'spring', 'horse', 'bicycle', 'ski', 'wheelchair', 'interesting_object')

	for line in l:
		t = tag.match(line)
		m = member.match(line)
		if m:
			if m.group(1) == 'way':
				wayIds.append(m.group(2))
    		elif t:
    			if t.group(1) in kctKeys:
    				kct = t.group(1).split('_')
    				typ = t.group(2).split(';')
    				tags[t.group(1)] = typ[0]
    				tags['osmc'] = 'yes'
    				tags['osmc_color'] = kct[1]
    				if typ[0] in ('major', 'local', 'peak', 'learning', 'ruin', 'spring', 'horse', 'wheelchair', 'interesting_object'):
    					tags['osmc_background'] = 'white'
    				elif typ[0] == 'bicycle':
    					tags['osmc_background'] = 'yellow'
    				elif typ[0] == 'ski':
    					tags['osmc_background'] = 'orange' 					
    					
    				if typ[0] in ('major', 'bicycle', 'ski'):
    					tags['osmc_foreground'] = kct[1] + '_bar'
    				elif typ[0]== 'peak':
    					tags['osmc_foreground'] = kct[1] + '_triangle'
    				elif typ[0] == 'local':
    					tags['osmc_foreground'] = kct[1] + '_corner'
    				elif typ[0] == 'interesting_object':
    					tags['osmc_foreground'] = kct[1] + '_turned_T'
    				elif typ[0] == 'ruin':
    					tags['osmc_foreground'] = kct[1] + '_L'    					
    				elif typ[0] == 'spring':
    					tags['osmc_foreground'] = kct[1] + '_bowl'
    				elif typ[0] == 'horse':
    					tags['osmc_foreground'] = kct[1] + '_dot'
    				elif typ[0] == 'wheelchair':
    					tags['osmc_foreground'] = kct[1] + '_wheelchair'
    				elif typ[0] == 'learning':
    					tags['osmc_foreground'] = kct[1] + '_backslash'
    				
    	for i in wayIds:
    		if i in wayTags:
    			combine(i, tags)
    			#wayTags[i].update(tags)
    		else:
    			wayTags[i] = {}
    			for key, value in tags.items():
    				wayTags[i][key] = value
    	
    	tags.clear()
    	del wayIds[:]
    			
def bikingRoute(l):
	wayIds = []
	tags = {}
	for line in l:		
		t = tag.match(line)
		m = member.match(line)
		if m:
			if m.group(1) == 'way':
				wayIds.append(m.group(2))
    		elif t:
    			if t.group(1) in ('network', 'ref', 'route'):
    				tags[t.group(1)] = t.group(2)
    	
    	for i in wayIds:
    		if i in wayTags:
    			combine(i, tags)
    			#wayTags[i].update(tags)
    		else:
    			wayTags[i] = {}
    			for key, value in tags.items():
    				wayTags[i][key] = value
    	tags.clear()
    	del wayIds[:]

flag = 0
for line in relations.stdout:
	relS = relationStart.match(line)		
    	relE = relationEnd.match(line)
    	hikeR = kctRoute.match(line)
    	bikeR = bikeRoute.match(line)
    	if relS:
    	   	flag = -1
    	elif relE:
    		if flag == 1:
    			hikingRoute(stack)
    		elif flag == 2:
    			bikingRoute(stack)    		
    		del stack[:]
    		flag = 0
    	elif hikeR:
    		flag = 1
    		stack.append(line)
    	elif bikeR:
    		flag = 2
    		stack.append(line)
    	elif flag != 0:    		
    		stack.append(line)
	
id = -1
h = 0
b = 0
for line in mapFile.stdout:
	s = wayStart.match(line)
	e = wayEnd.match(line)
	hi = kctRoute.match(line)
	bi = bikeRoute.match(line)
	if s:
		id = s.group(1)
	elif hi:
		h = 1
	elif bi:
		b = 1
	elif e:
		if id != -1:
			if id in wayTags:
				for key, value in wayTags[id].items():
					if h == 0 and (value in ('major', 'local', 'peak', 'learning', 'ruin', 'spring', 'horse', 'wheelchair', 'interesting_object')):
						printTag('route', 'hiking')
						h = 1
					elif key == 'route' and value == 'bicycle':
						b = 1
					elif b == 0 and value == 'bicycle':
						printTag('route', 'bicycle')
						b = 1
					printTag(key, value)
				del wayTags[id]
				h = 0
				b = 0
		id = -1
	print line.rstrip()
	
	
exit(0)

Přidám ještě druhou upravenou verzi, která umí vytvořit turistické značky pro Slovensko, ale hlavní změna spočívá v duplikaci cest. Jednoduše vezme všechny body z původní cesty a vytvoří novou cestu pouze s tagy turistických značek. Tím se zbavím několika problémů naráz. Interní vzhled Locusu používá takové značky, že najednou může cesta nést jen jednu barvu. Dále jediný Locus má opravenou nesmyslnou chybu, při které vyhledávač tag pro renderování odsouhlasí libovolnou dvojici klíč-hodnota, kterou najde. Takže měla-li cesta najednou kct_red=major i kct_green=learning, v c:geo se bez ostychu vykreslily ikonky, jako by šlo o kct_red=learning. Výsledný soubor nabyde na velikosti jen o pár MB. Při zpracování výsledného souboru je třeba v osmosis použít –sort, protože id u cest nejsou seřazena.

#!/usr/bin/python
# -*- coding: utf-8 -*-

__author__="Speirs"

import sys, re, subprocess
from datetime import datetime

#nodes = subprocess.Popen(["./osmconvert", "--drop-relations", "--drop-ways", sys.argv[1]], stdout=subprocess.PIPE)
#ways = subprocess.Popen(["./osmconvert", "--drop-relations", "--drop-nodes", sys.argv[1]], stdout=subprocess.PIPE)
mapFile = subprocess.Popen(["./osmconvert", sys.argv[1]], stdout=subprocess.PIPE)
relations = subprocess.Popen(["./osmconvert", "--drop-nodes", "--drop-ways", sys.argv[1]], stdout=subprocess.PIPE)

nodeStart = re.compile('\s*')
wayStart = re.compile('\s*')
relationStart = re.compile('\s*')

nodeID = re.compile( '\s*'.format(key, value)
        
def hikingRoute(l):
	wayIds = []
	tags = {}
	kctKeys = ('kct_red', 'kct_blue', 'kct_green', 'kct_yellow')
	kctValues = ('major', 'local', 'peak', 'learning', 'ruin', 'spring', 'horse', 'bicycle', 'ski', 'wheelchair', 'interesting_object')

	for line in l:
		t = tag.match(line)
		m = member.match(line)
		if m:
			if m.group(1) == 'way':
				wayIds.append(long(m.group(2)))
    		elif t:
    			if t.group(1) in kctKeys:
    				kct = t.group(1).split('_')
    				typ = t.group(2).split(';')
    				tags[t.group(1)] = typ[0]
    				tags['osmc'] = 'yes'
    				tags['osmc_color'] = kct[1]
    				if typ[0] in ('major', 'local', 'peak', 'learning', 'ruin', 'spring', 'horse', 'wheelchair', 'interesting_object'):
    					tags['osmc_background'] = 'white'
    				elif typ[0] == 'bicycle':
    					tags['osmc_background'] = 'yellow'
    				elif typ[0] == 'ski':
    					tags['osmc_background'] = 'orange' 					
    					
    				if typ[0] in ('major', 'bicycle', 'ski'):
    					tags['osmc_foreground'] = kct[1] + '_bar'
    				elif typ[0]== 'peak':
    					tags['osmc_foreground'] = kct[1] + '_triangle'
    				elif typ[0] == 'local':
    					tags['osmc_foreground'] = kct[1] + '_corner'
    				elif typ[0] == 'interesting_object':
    					tags['osmc_foreground'] = kct[1] + '_turned_T'
    				elif typ[0] == 'ruin':
    					tags['osmc_foreground'] = kct[1] + '_L'    					
    				elif typ[0] == 'spring':
    					tags['osmc_foreground'] = kct[1] + '_bowl'
    				elif typ[0] == 'horse':
    					tags['osmc_foreground'] = kct[1] + '_dot'
    				elif typ[0] == 'wheelchair':
    					tags['osmc_foreground'] = kct[1] + '_wheelchair'
    				elif typ[0] == 'learning':
    					tags['osmc_foreground'] = kct[1] + '_backslash'
    			elif t.group(1) in ('network', 'ref', 'route'):
    				tags[t.group(1)] = t.group(2)
    				
    	for i in wayIds:
    		if i in wayTags:
    			wayTags[i].append(tags.copy())
    		else:
    			wayTags[i] = []
    			wayTags[i].append(tags.copy())
    	tags.clear()
    	del wayIds[:]

def hikeRoute(l):
	wayIds = []
	tags = {}
	kstKeys = ('red', 'blue', 'green', 'yellow')
	kstValues = ('major', 'local', 'peak', 'education', 'ruin', 'spring', 'interesting_object')
	barva = ''
	symbol = ''

	for line in l:
		t = tag.match(line)
		m = member.match(line)
		
		if m:
			if m.group(1) == 'way':
				wayIds.append(long(m.group(2)))
    		elif t:
    			if t.group(1) in ('colour'):
    				tags['osmc'] = 'yes'
    				barva = t.group(2)
    				tags['osmc_color'] = t.group(2)
    			elif t.group(1) in ('network', 'ref', 'route'):
    				tags[t.group(1)] = t.group(2)    			
    			elif t.group(1) in ('symbol'):
    				if t.group(2) in kstValues:
    					tags['osmc_background'] = 'white'
    					symbol = t.group(2)
    					
    	if barva == '' or symbol == '':
    		tags.clear()
    		del wayIds[:]
    		return
    		
    	
    	if symbol == 'educational':
    		tags['kct_'+barva] = 'learning'
    	else:
    		tags['kct_'+barva] = symbol
    		
    	if symbol == 'major':
    		tags['osmc_foreground'] = barva + '_bar'
    	elif symbol == 'peak':
    		tags['osmc_foreground'] = barva + '_triangle'
    	elif symbol == 'local':
    		tags['osmc_foreground'] = barva + '_corner'
    	elif symbol == 'interesting_object':
    		tags['osmc_foreground'] = barva + '_turned_T'
    	elif symbol == 'ruin':
    		tags['osmc_foreground'] = barva + '_L'    					
    	elif symbol == 'spring':
    		tags['osmc_foreground'] = barva + '_bowl'
    	elif symbol == 'roundtrip':
    		tags['osmc_foreground'] = barva + '_dot'
    	elif symbol == 'education':
    		tags['osmc_foreground'] = barva + '_backslash'
    				
    	for i in wayIds:
    		if i in wayTags:
    			wayTags[i].append(tags.copy())
    		else:
    			wayTags[i] = []
    			wayTags[i].append(tags.copy())
    	tags.clear()
    	del wayIds[:]
    	
def bikingRoute(l):
	wayIds = []
	tags = {}
	for line in l:		
		t = tag.match(line)
		m = member.match(line)
		if m:
			if m.group(1) == 'way':
				wayIds.append(long(m.group(2)))
    		elif t:
    			if t.group(1) in ('network', 'ref', 'route'):
    				tags[t.group(1)] = t.group(2)
    	
    	for i in wayIds:
    		if i in wayTags:
    			wayTags[i].append(tags.copy())
    		else:
    			wayTags[i] = []
    			wayTags[i].append(tags.copy())
    	tags.clear()
    	del wayIds[:]

flag = 0
for line in relations.stdout:
	relS = relationStart.match(line)		
    	relE = relationEnd.match(line)
    	hikeR = kctRoute.match(line)
    	kstR = kstRoute.match(line)
    	bikeR = bikeRoute.match(line)
    	if relS:
    	   	flag = -1
    	elif relE:
    		if flag == 1:
    			hikingRoute(stack)
    		elif flag == 2:
    			bikingRoute(stack)
    		elif flag == 3:
    			hikeRoute(stack)
    		del stack[:]
    		flag = 0
    	elif hikeR:
    		flag = 1
    		stack.append(line)
    	elif bikeR:
    		flag = 2
    		stack.append(line)
    	elif kstR:
    		flag = 3
    		stack.append(line)
    	elif flag != 0:    		
    		stack.append(line)
	
id = -1
nid = 50000000000
del stack[:]
datum = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

for line in mapFile.stdout:
	s = wayStart.match(line)
	e = wayEnd.match(line)
	n = nodeID.match(line)
	if s:
		id = long(s.group(1))
	elif n and id != -1:
		stack.append(line)
	elif e and id != -1:
		if id in wayTags:
			for i in wayTags[id]:
				print '\t'
				print '\t'.format(nid, datum)
				for li in stack:
					print li.rstrip()			
				for key, value in i.items():
					printTag(key, value)
				nid += 1
			del wayTags[id]
		del stack[:]
		id = -1
	print line.rstrip()
	
exit(0)

PPA repozitáře pro Ubuntu

To je velmi užitečná věc, zejména během přidávání nové funkcionality, zejména nějaké stěžejní, nechci čekat, než se software dostane do repozitáře distribuce. Instalovat si jednorázový balík je také otrava. A tak tu je přídavný repozitář spravovaný tvůrci aplikace nebo jinými nadšenci. Dneska jsem ale doplatil na novou verzi xbmc z jejich Unstable repozitáře, který jsem si přidal ve chvíli šachování s PVR pluginy a já chtěl verzi Eden (12), ta už je nějakou dobu s námi, a já jsem si bohužel repozitář nechal zapnutý. Dnes jsem na to doplatil, když mi televize vypověděla službu. Díky článečku jsem odstranil unstable, přidal stable, přeinstaloval a pustil si televizi, a možná tenhle odkaz někomu ušetří tři čtvrtě hodiny hledání, jak se vrátit k nižší verzi přes aptitude.

sudo add-apt-repository ppa:someppa/ppa
sudo add-apt-repository --remove ppa:someppa/ppa

Geocaching na Linuxu

Dnes jsem se zabýval hromadnou správou položek pro Geocaching. Vždycky jsem si do telefonu stahoval jen omezené množství před plánovanou výpravou. Přesto jsem téměř nikdy listingy nečetl dopředu (nicméně po nálezu jsem to napravil). Navíc se často vyrazilo do hodiny po rozhodnutí o odjezdu. Buďto jsem si nestihl keše stáhnout, ale i když jsem je měl, sem tam nešla krabička vyhledat, protože jsem neměl staženo dost informací či nastal jiný problém způsobený chabou přípravou. Po návratu jsem litoval, že chybělo tak málo, nebo jsem něco přešel.
Od těch dob se na mě nabaluje další software. Začal jsem přispívat do OSM, v telefonu jsem nainstaloval Locus následně i Pro verzi, c:geo, v počítači JOSM, gpxview (ještě digikam na geotaging fotek). Bylo na čase podpořit i geocaching, který mě k mapování pro OSM přivedl. Po dlouhém hledání jsem objevil alespoň jednoho správce databáze pro Linux a to OpenCacheManager. Ten se spoléhá na vnější zdroj dat, takže k dolování Geocaching.com jsem zvolil geotoad, který je naprosto skvělý. Je intuitivní a není třeba nic vysvětlovat, snad jen, že „country“ je CZ a „state“ se vyhledá pomocí řetězce „CZ/.*“. Sami vyzkoušejte. Vydolovaná data přesunu do OCM, kde můžu řešit mysterky a multiny, uložit finálové souřadnice do databáze, či jen jednoduše slučovat další a další výcucy z geotoad. Keše pak můžu filtrovat a pak exportovat do souboru gpx. Ten lze jednoduše importovat do c:geo. S Locusem je práce o trochu složitější, ale jistě se vyplatí. Locus je připraven na PQ, ve které údajně dostanete soubor s detaily keší a druhý s případnými waypointy k nim. Musím tedy svůj export přizpůsobit, jinak by se nám každý waypoint povaloval v mapě samostatně a nebyl by se svojí keší nijak spojen. To není složité, stačí zvolit Export do GPX (Ctrl + S). Soubor export.gpx exportujte BEZ Child waypoints (v Options). Po dokončení exportu proveďte ještě jeden, tentokrát soubor pojmenujte na export-wpts.gpx a exportujte S Child waypoints. Spusťte následující skript, který odvede zbytek práce.
pq.sh

#!/bin/bash
comm -3 export.gpx export-wpts.gpx | sed '1,+2d' > diff.gpx
echo '<gpx>' | cat - diff.gpx > export-wpts.gpx
rm diff.gpx

Zřejmě není zcela korektní, že chybí hlavička, ale import funguje korektně. Proč jsem se vůbec snažil o import do Locus? Mělo by tam fungovat hlášení POI, už se mi totiž stalo, že jsem v turistickém zápalu přešel ráno na rychlo stažené keše 🙂 Locus mě na to doufám upozorní. Nyní máme dva soubory, které já osobně označím v Nautilu (jsou pěkně vedle sebe). Před tím, než zvolím odeslat přes Bluetooth z kontextové nabídky, zajdu v Locusu do kategorie Data/Body, ve které mám kategorii pro keše. Stisknu tlačítko nástrojů a zvolím Import, pakliže již mám ve podsložce /bluetooth stejně pojmenované soubory, dlouhým podržením je, díky bohu mohu přímo v Locus, smažu (dochází k úpravě názvů při odesílání, pokud je v cílové složce soubor stejného názvu). (EDIT: Vyzkoušeno odeslat oba soubory přes BT komprimovaně v zipu. Je to jen otázka jedné volby v odesílacím dialogu. Locus si s tím poradí a není třeba tak často soubor mazat, protože nedochází ke změně v názvu gpx souborů.) Z Nautilu potvrdím odeslání a pak již importuji soubor export.gpx, Locus se postará o druhý soubor automaticky. Nechám smazat stará data v kategorii, protože vše shromažďuji v OCM.

Automatizovaný příjem snímků NOAA

Nejprve byla anténa QFH, pak softwarové rádio s čipsetem Realtek RTL2832U, pak byl software na ovládání rádia zvaný gqrx, který je založený na gnuradio a pak tu byl uživatel, který musel čekat, až přiletí satelit, čekat čtvrt hodiny a sehnat několik příkazů na vytvoření obrázku pomocí programu wxtoimg. Uživatele to přestalo bavit a tak si napsal skript, který sám sestaví obrázek a nahraje jej na web server. Pak ale musel napsat skript, který ty obrázky seřadí podle data pořízení. Jenže ani to mu moc nepomohlo a nezbylo nic jiného, než přemýšlet jak automatizovat úplně všechno. První problém bylo sehnat čas příletu družice na viditelnou část oblohy. Z GPredict se nějak viditelně vydolovat nedal. Díky dobré duši, která implementovala GPredict do jazyka PHP a zveřejnila kód se dala první část odškrtnout. Zdrojové kódy stáhnete zde. Predict.php všechno zařizuje, pro vaše potřeby využijte souboru visible_passes.php ve složce examples. Tento soubor si jen poupravte dle svých potřeb. Já potřeboval čas příletu a dobu, po kterou satelit zůstává na viditelné části oblohy. Tento skript neběží na webserveru, je volán cronem vždy po 4. hodině ranní, kdy začíná první část přeletů viditelných od nás a zkontroluje přelety na dalších 24 hodin. Zatím běží na klasickém PC, běh na Raspberry Pi ještě vyzkouším. Pokud skript neběží, možná jsem udělal chybu zde při úpravách, ale je téměř samovysvětlující, takže není problém jej opravit/předělat podle svých potřeb.

noaa.php

<?php
/**
 * This is an example of how to use Predict for determining upcoming visible
 * passes of the International Space Station.  Please read the inline comments
 * for details.
 *
 * Run this from the root checkout, not from examples, or the include paths
 * will not work.
 */

require_once 'Predict.php';
require_once 'Predict/Sat.php';
require_once 'Predict/QTH.php';
require_once 'Predict/Time.php';
require_once 'Predict/TLE.php';

function sortByAos($a, $b) {
   if ($a[2] == $b[2]) {
        return 0;
    }
    return ($a[2] < $b[2]) ? -1 : 1;
}
// Track execution time of this script
$start = microtime(true);

// The observer or groundstation is called QTH in ham radio terms
$predict  = new Predict();
$qth      = new Predict_QTH();
$qth->alt = 300; // Altitude in meters

// Munich, example east of the meridian
$qth->lat = 48.1505; // Lat North
$qth->lon = 11.5809; // Lon East

// The iss.tle file is the first 3 lines of
// http://celestrak.com/NORAD/elements/stations.txt
// Make sure you update this content, it goes out of date within a day or two
exec("wget http://celestrak.com/NORAD/elements/weather.txt -O ~USERNAME/.wxtoimg/weather.txt");
$tleFile = file('http://celestrak.com/NORAD/elements/noaa.txt'); // Load up the NOAA from celestrak
$indexes = array(19, 18, 15);
$list = array();

foreach ($indexes as $index){
	$index *= 3;  //3 rows for satellite
	$tle     = new Predict_TLE(substr($tleFile[$index], 5, 2), $tleFile[$index+1], $tleFile[$index+2]); // Instantiate it
	$sat     = new Predict_Sat($tle); // Load up the satellite data
	$now     = Predict_Time::get_current_daynum(); // get the current time as Julian Date (daynum)

	// You can modify some preferences in Predict(), the defaults are below
	//
	 $predict->minEle     = 0; // Minimum elevation for a pass
	 $predict->timeRes    = 5; // Pass details: time resolution in seconds
	 $predict->numEntries = 10; // Pass details: number of entries per pass
	 $predict->threshold  = 90; // Twilight threshold (sun must be at this lat or lower)

	// Get the passes and filter visible only, takes about 4 seconds for 10 days
	$results  = $predict->get_passes($sat, $qth, $now, 1);
	$filtered = $predict->filterVisiblePasses($results);

	$zone   = 'Europe/Berlin'; // Pacific time zone
	$format = 'H:i mdy';         // Time format from PHP's date() function
	$epoch  = 'U';

	// Format the output similar to the heavens-above.com website
	//echo "<tr><td>Sat\t<td>AOS\t<td>ELE\t<td>LOS\t</tr>";
	foreach ($filtered as $pass) {
	    if (round($pass->max_el) < 17){
	       continue;
	    }
	    $list[] = array($pass->satname, Predict_Time::daynum2readable($pass->aos, $zone, $format), Predict_Time::daynum2readable($pass->aos, $zone, $epoch), Predict_Time::daynum2readable($pass->los, $zone, $epoch), round($pass->max_el));
	}
}

//delete the pass with worse max elevation from overlaping ones
usort($list, 'sortByAos');
$i=0;
while ($i < (sizeOf($list)-1)){
	if ($list[$i][3] >= $list[$i+1][2]) {
		if ($list[$i][4] > $list[$i+1][4]){
			array_splice($list, $i+1, 1);
		} else {
			array_splice($list, $i, 1);
		}		
		continue;
	}
	$i++;
}

//echo $wake_date > /sys/class/rtc/rtc0/wakealarm

foreach ($list as $pass) {
    $cmd = "echo \"cd /home/USERNAME && ./apt ".$pass[0]. " ";
    $cmd .= $pass[3] - $pass[2] - 60;
    $cmd .= "\" | at -m ";
    $cmd .= "\"". $pass[1] . " +1 minute\"\n";
    
    exec($cmd);
    //echo $cmd;
}
//echo "Execution time:  " . number_format((microtime(true) - $start) * 1000, 2) . "ms\n"; 
exit;

Zde vidíte, že php skript stáhnete TLE pro sebe a wxtoimg, Predict vypočítá potřebné časy, které php zapíše do příkazu at. At spustí mnou připravený skript, který zaznamená vysílání ze satelitu a přechroupe záznam do podoby obrázku. Ten nahraje na webovou prezentaci meteostanice pomocí nástroje curl. Nezapomeňte upravit username.
Bash skript původně zpracovával nahrávky z gqrx, z této doby pochází ta skvělá konstrukce na čtení datového razítka na začátku skriptu. Využívá programu rtl_fm z balíčku od osmocom. Dále tam najdete sox (třeba nainstalovat) pro práci se zvukovým záznamem a samozřejmě WXtotImg (také doinstalovat).

apt.sh

#!/bin/bash

bandwidth=150k
login='LOGIN:PASSWORD'

#Freq +- 0.006 ?
case $1 in
15)freq=137.54M;;
17)freq=137.5M;;
18)freq=137.9065M;;
19)freq=137.092M;;
*)exit 1;;
esac

filename=`date -u +%Y%m%d-%H%M%S`.s16
timeout $2 /usr/local/bin/rtl_fm -f $freq -s $bandwidth > $filename
#timeout $2 /usr/local/bin/rtl_sdr $filename.bin -f $freq -s 1.8e6
if [ $? -ne 124 ]; then
	rm $filename
	exit 1
fi

if [ ! -f $filename ]; then
	echo "Soubor $filename neexistuje."
	exit 2
fi

#set variables 
date=`echo $filename | cut -d- -f1`
time=`echo $filename | cut -d- -f2 | cut -d. -f1`
year=`echo $date | cut -c1-4`
month=`echo $date | cut -c5-6`
day=`echo $date | cut -c7-8`
hour=`echo $time | cut -c1-2`
minute=`echo $time | cut -c3-4`
second=`echo $time | cut -c5-6`

output=$year$month$day$hour$minute$second.wav
hvc=noaa$1-$year$month$day-$hour$minute$second-hvc.png
no=noaa$1-$year$month$day-$hour$minute$second-no.png
mcir=noaa$1-$year$month$day-$hour$minute$second-mcir.png
tmp=noaatmp.wav
map=map.png
thumbnail=noaa.png

#QTH
lat=48.1505
lon=11.5809
ele=300
#dawn=7
#dusk=17
#day/night is determined by python script

sox -r $bandwidth -c 1 -L $filename $tmp
sox $tmp $output rate 11025

touch -r $filename $output

/usr/local/bin/wxmap -T "NOAA $1" -L"$lat/$lon/$ele" -G /home/USERNAME/.wxtoimg -p 0 -l 0 -od "$day $month $year $hour:$minute:$second" $map

/usr/local/bin/wxtoimg -c -e MCIR -m $map -t "NOAA $1" -o $output $mcir
/usr/bin/curl -T $mcir ftp://ftp.server/ --user $login

if [ $? -eq 0 ]; then
	convert $mcir -resize 25% $thumbnail
	/usr/bin/curl -T $thumbnail ftp://ftp.server/ --user $login
	
	/usr/local/bin/wxtoimg -c -e NO -m $map -A -t "NOAA $1" -o $output $no
	/usr/bin/curl -T $no ftp://ftp.server/ --user $login
	
	#hourt=`echo $hour | sed 's/^0//'`
	python ./sun.py
	if [ $? -eq 1 ]; then
		/usr/local/bin/wxtoimg -c -e HVC -m $map -A -K -t "NOAA $1" -o $output $hvc
		/usr/bin/curl -T $hvc ftp://ftp.server/ --user $login
		rm $hvc
	fi	
	rm $no $mcir $thumbnail $output
fi

rm $tmp $filename $map

exit 0

Pro určení zda je den či noc používám ne zcela přesný výpočet místního hvězdného času a jeho porovnání vypočteného času východu a západu Slunce, opět hvězdného. To vše kvůli senzoru 4, který se odesílá až hodinu po východu Slunce, zde je ještě prostor pro vylepšení.
sun.py

#!/usr/bin/python

from datetime import datetime
import time
import math

def days_between(d1, d2):
    return (d2 - d1).days + (d2 - d1).seconds/84600.0
    
def echo_time(t):
    print (math.modf(t)[1])+math.ceil((math.modf(t)[0])*60)/100

#QTH
lat = math.radians(48.1505)
lon = math.radians(11.5809)
ele = 300
utcoffset = 1

#Twilight
now = datetime.utcnow()
equinox = datetime.strptime("03-20", "%m-%d")
equinox = equinox.replace(now.year)

if days_between(equinox, now) < 0:
	equinox = equinox.replace(now.year - 1)

d = days_between(equinox, now)
lamb = math.radians(360.0/365.2422 * d)
print "Lambda=", math.degrees(lamb), "d=", d

beta = 0.0
epsilon = math.radians(23.5)

delta = math.asin(math.sin(lamb)*math.sin(epsilon))
alfa = math.acos(math.cos(lamb)/math.sqrt(1-math.pow(math.sin(lamb)*math.sin(epsilon),2)))
if math.sin(lamb)*math.cos(epsilon)/math.sqrt(1-math.pow(math.sin(lamb)*math.sin(epsilon),2)) < 0:
	alfa = 2*math.pi - alfa

ts = math.acos(-math.tan(lat)*math.tan(delta))
if ts>math.pi:
	t1 = ts
	t2 = 2.0*math.pi - ts	
else:
	t1 = 2.0*math.pi - ts
	t2 = ts
	
t1 = math.degrees(t1)
t2 = math.degrees(t2)
while t1 > 360:
    t1 -= 360
while t2 > 360:
    t2 -= 360
print alfa
riselst = t1+math.degrees(alfa)
dawnlst = t2+math.degrees(alfa)
while riselst > 360:
    riselst -= 360
while dawnlst > 360:
    dawnlst -= 360

print "rise in angle",
echo_time(t1/15.0)
print "in LST",
echo_time(riselst/15.0)
print "set in angle",
echo_time(t2/15.0)
print "in LST",
echo_time(dawnlst/15.0)
	
#JD
r=now.year
m=now.month
d=now.day + (now.hour+(now.minute+now.second/60)/60)/24
if m > 2:
    r = r - 1
    m = m + 12
JD = 1720994.5 + 365.25*r + r/400.0 +- r/100.0 + 30.6*(m+1) + d + 2.0
print "JD=",JD

#JD best
unix = time.time()
J = 2440587.5 + unix/86400.0
T = (J - 2451545.0) / 36525.0
TT = 64.184 + 59.0 * T - 51.2 * math.pow(T,2) - 67.1 * math.pow(T,3) - 16.4 * math.pow(T,4)
JTT = J + TT / 86400.0
d = JTT - 2451545.0
print "JD=",JTT
print d

# Sidereal time
J2k = datetime.strptime("2000-01-01 12:00 UTC", "%Y-%m-%d %H:%M %Z")
#d = days_between(J2k, now)
print d

GMST = 280.46061837 + 360.98564736629 * d
while GMST > 360:
    GMST -= 360
LMST = 280.46061837 + 360.98564736629 * d + math.degrees(lon)
while LMST > 360:
    LMST -= 360
print "GMST",
echo_time(GMST/15.0)
print "LMST",
echo_time(LMST/15.0)

if LMST > riselst or LMST < dawnlst:
    print "Day"
    exit(1)
else:
    print "Night"
    exit(2)

t = GMST + math.degrees(lon) + 1.00273790935*(now.hour+now.minute/60 - 1)
print "t=",
echo_time(t/15.0)

h = math.degrees(math.asin(math.sin(delta)*math.sin(lat)+math.cos(delta)*math.cos(math.radians(LMST))*math.cos(lat)))
print "h=", h, "d=",
echo_time(math.degrees(delta))

ADS-B na RTL SDR

Přesunul jsem RTL krabičku z testování na osobním počítači do mého Debianího serveru. Na Debianu mají příznivci softwarového radia balíky gnuradio už předkompilované, zkompilovat jsem ovladače z v4l podle článku na wiki.ubuntu.cz, věnujícímu se právě těmto televizním krabičkám a dále zkompiloval balíčky rtl_sdr, mezi nimiž je i rtl_tcp. Můžu tedy ovládat softwarové rádio přes síť z jiného počítače například mým oblíbeným gqrx. Protože zajímavým zdrojem radiem přenášených dat jsou letadla, pátral jsem, jak si udělat vlastní flightradar24.com s pomocí rtl_adsb a dlouho nic nenašel. Až na blogu G4VXE jsem narazil na referenci k programu dump1090 a ten funguje velmi pěkně. Dokonce chytám data v pásmu 1 GHz stále na tu všesměrovku pro 137 MHz, nicméně dosah není nijak závratný. Postup je snadný:

git clone git://github.com/antirez/dump1090.git

cd dump1090
make

A spustíme v pěkném přehledovém zobrazení příkazem

./dump1090 --interactive

Získám informace z letadel do vzdálenosti 200 km, spíše však méně, víc uvidím s lépe naladěnou anténou.