Quello che segue è il diagramma di flusso dei file e delle logiche utilizzate nel sistema di HotSpot Mikrotik
Archivi per categoria: programmazione
Una visione informatica del concepimento
- Una cellula umana contiene 75MByte di informazione genetica
- Uno spermatozoo contiene la metà, cioè 37.5MByte
- Un mL di sperma contiene 100 milioni di spermatozoi
- In media l'eiaculazione dura circa 5 secondi e contiene circa 2.24mL di sperma
- questo significa che nella produzione del membro di un uomo è di 37.5MByte X 100.000.000 X 2.24/5 = 1,687,500,000,000,000 byte al secondo, cioè 1,6875 terabyte al secondo
In altre parole un ovulo femminile sopporta un attacco di tipo DDoS a 1,5 terabyte al secondo e permette il passaggio di un solo pacchetto di informazione. Questo fa della donna il miglior firewall hardware del mondo.
La cattiva notizia è che quel pacchetto che lascia passare fa impallare il sistema per nove mesi circa e consuma risorse di sistema per altri 20/25 anni.
Fonte Facebook, profilo di Claudio Marchiondelli
HTMLTemplateProRenderer, un modulo di templating per Mojolicious
Per creare siti web il linguaggio di "programmazione" si chiama HTML ma questo permette di scrivere solo pagine statiche nel senso di pagine che non cambiano il contenuto nel tempo a meno che qualcuno non vada a mano a cambiare il codice HTML.
Per creare siti che cambiano dinamicamente il loro contenuto è necessario integrare l'HTML con un "programma" che, eseguito ogni volta che qualcuno richiama la pagina, genera l'HTML di volta in volta creando nuovi contenuti.
Ma per lasciare separato il ruolo del programmatore da quello che scrive pagina HTML esistono dei sistemi, detti Template, per cui viene creata una pagina HTML "scheletro" su cui, di volta in volta, il programma inserisce i contenuti dinamici.
Diciamo che voglio visualizzare in una pagina la temperatura all'esterno. Possiamo scrivere una cosa tipo:
"Ciao. In questo momento fuori ci sono xxx gradi"
e dare questo in pasto ad un programma che sostituisce al segnaposto "xxx" il valore attuale preso in qualche modo di modo che, ogni volta che qualcuno chiama questa pagina web, il programma prende il template che abbiamo scritto sopra, si ricava la temperatura esterna da un qualche apparato, mette il valore al posto delle "xxx" e ritorna il testo completo al browser dell'utente.
Qualche anno fa avevo contribuito alla scrittura di alcuni pezzi per il sistema di templating HTML::Template::Pro
e creato un'estensione modulare a plugin per questo modulo chiamata HTML::Template::Pro::Extension.
Questi moduli permettono di usare dei segnaposto tipo %nome%, %cognome%, %temperatura% che poi vengono sostituite con i relativi valori reali passati dal programma.
Dato che in questa torrida estate mi sto divertendo un po' a giocherellare con Mojolicious, un framework per applicazioni web in tempo reale che ovviamente ha un suo sistema di templating per integrare codice HTML e codice generato dinamicamente, mi sono detto, perchè non creare un modulo per integrare Mojolicious con HTML::Template::Pro e ::::::Extension?
E cosi è nato Mojolicious::Plugin::HTMLTemplateProRenderer che integra appunto in Mojolicious questi due sistemi di templating.
Per cui, ora è possibile scrive codice come questo
[code lang="perl"] use Mojolicious::Lite;plugin 'HTMLTemplateProRenderer';
get '/hello/#cometichiami' => sub{
my $c = shift;
$c->render('hello', handler => 'tmpl');
}
__DATA__
@@ hello.html.tmpl
Ciao %cometichiami%
[/code]
e vedere sul browser un bel saluto 🙂
Il modulo è stato citato anche nel "What's new on CPAN" di Luglio 2014 su perltricks.
RB750UP in un ambiente a rete elettrica discontinua
La routerboard Mikrotik RB750UP è un router/switch a 5 porte con delle caratteristiche molto interessanti. Oltre ad avere all'interno il RouterOS, con tutte le sue mirabolanti caratteristiche, possiede anche una peculiarità aggiuntiva.
Oltre ad essere alimentabile via POE (occhio, passivo e quindi non 802.3af) ossia tramite alimentazione su cavo LAN, ha le porte dalle 2 alla 5 che sono delle porte POE-injector ossia possono alimentare a loro volta 4 apparati POE fino ad un massimo di assorbimento per porta di 1 A.
Questo, aggiunto alla possibilità di monitorare il carico di assorbimento di corrente e il voltaggio su ogni singola porta, oltre alla possibilità di creare degli script di automazione, ne fa lo strumento ideale per ambienti dove la corrente a 220V non è sempre disponibile come, ad esempio, sugli impianti di pubblica illuminazione.
Una RB750UP unita a un sistema tampone di batterie permette, alla necessità, di spegnere eventualmente apparati superflui al fine di aumentare la durata di uptime del sistema qualora la 220V non fosse disponibile per lungo tempo.
Lo scopo dello sviluppo che è stato fatto in casa Micso dal sottoscritto era quello di definire una tensione di soglia Vbatalert delle batterie e una Vbatoff e iniziare a spegnere gli apparati alimentati dalla RB750UP se la tensione fosse stata compresa tra questi due valori lasciando la sola RB750UP accesa per valori di tensione minori di Vbatoff.
Vediamo come è stato pensata e sviluppata questa soluzione analizzando in dettaglio i due script creati per l'occasione per carpirne le logiche di funzionamento.
Il primo script chiamato PoeControl, spegne e accende le porte ethernet dell'RB750Up a comando. Esso riceve
- un parametro PoePort che indica il numero della porta dello switch su cui si vuole cambiare lo stato dell'alimentazione POE e, se questo valore è 0 (zero), agisce su tutte le porte,
- un parametro PoeMode che può essere "auto-on" per accendere l'apparato collegato a questa porta o "off" per spegnerlo
- un parametro PoeDelay per ritardare le operazioni sulle porte se PoePort è pari a 0.
:global PoeMode
:global PoeDelay
:local ptr
:local from
:local to
:local step[/code]
Il parametro PoeDelay è utile, ad esempio, in fase di accensione delle porte in modo che gli apparati non vengono accesi tutti contemporaneamente ma con un ritardo di, ad esempio, 10 secondi l'uno dall'altro al fine di non avere picchi di corrente richiesti sulla batteria tampone.
La tua ora di programmazione
Mentre in Italia.... non lo so cosa si sta facendo in Italia, indipendentemente dall'argomento.
Ma negli Stati Uniti ritengono che imparare a programmare un computer, un cellulare, un robot, una stazione spaziale, sia una cosa importante per il benessere della nazione.
Ecco perchè hanno messo in campo il progetto "The Hour of Code" che, tramite filmati pubblicitari, introduttivi e un modo di programmare tramite pezzi di puzzle e aiutati dagli Angry Birds propongono di farti passare un'ora a comprendere le basi della programmazione aiutanto l'angry bird di turno a raggiungere il maialino cattivo.
Attivate i sottotitoli in italiano.
Ora, già guardando, il video mi immagino, una versione italiana, con Napolitano, Enrico Letta e Gigi D'Alessio che ti incitano a programmare... ridicolo.
Sia che tu sia un programmatore, un operaio, un autista di bus, uno studente, divertiti, nella prossima ora a imparare a programmare con "The Hour of Code" e condividi quante linee di codice sei riuscito a scrivere.
Realizzare l'inimmaginabile con Arduino
Arduino è una piattaforma hardware e software opensource per la semplice realizzazione di progetti elettronici. Masimo Banzi è uno degli ideatori della piattaforma nata in Italia, a Ivrea.
In questo video Massimo spiega la filosofia alla base della piattaforma Arduino e alcuni esempi tra le innumerevoli applicazioni già realizzate dalla comunità come la pianta che invia i tweet sul suo stato di salute.
Guardatelo, sottotitolato in italiano, e fatevi venire anche voi la voglia di realizzare qualcosa con Arduino.
Micso Conference Center
Ricordate l' esperimento di webconference che ho fatto un po' di tempo fa? Beh, il tempo ha dato i suoi frutti.
Dall'unione di questo modulo creato ex-novo con quest'altro modulo, rigorosamente in Perl, ecco a voi il Micso Conference Center, nuovo prodottino di casa Micso.
Stiamo decidendo se utilizzare "centro" alla british o all'american maniera ma, per il resto, il prodotto c'è tutto.
RadioMobile, un modulo Perl per interfacciarsi ai file .net
Ho appena rilasciato su CPAN un modulo Perl per interfacciarsi ai file .net del programma di simulazione di propagazione elettromagnetica Radio Mobile.
Attualmente il modulo fa un'unica cosa, legge un file .net creato da Radio Mobile e ne analizza tutte le informazioni creando un modello ad oggetti del file. Questo modello ad oggetti può essere usato, ad esempio, per inserire le informazioni in esso contenute in un database.
Per esempio, questo pezzo di codice,
[code lang="perl"] use RadioMobile;my $rm = new RadioMobile();
$rm->file('net1.net');
$rm->parse;
my $header = $rm->header;
my $units = $rm->units;
foreach my $idxUnit (0..$header->unitCount-1) {
my $unit = $units->at($idxUnit);
printf("%s at lon %s and lat %s\n", $unit->name,
$unit->lon, $unit->lat);
}
[/code]
produce come risultato roba di questo genere
[code]Unit 1 at lon 43.4223 and lat 13.4353
Unit 2 at lon 43.43242 and lat 13.4244
Unit 3 at lon 0 and lat 0
Unit 4 at lon 0 and lat 0
Unit 5 at lon 0 and lat 0
Unit 6 at lon 0 and lat 0
Unit 7 at lon 0 and lat 0
Unit 8 at lon 0 and lat 0
Unit 9 at lon 0 and lat 0
Unit 10 at lon 0 and lat 0
[/code]
Quanto prima, in una prossima versione, vedrò di realizzare la "magia" opposta ossia, da informazioni, caricate ad esempio da un database, andare a creare un file .net ex-novo, da dare poi in pasto a Radio Mobile.
Struttura del file .net di Radio Mobile
I risultati di un sabato pomeriggio passato a studiare la struttura del file binario .net del software di simulazione di propagazione delle onde elettromagnetiche Radio Mobile in cui sono racchiuse tutti i punti e le caratteristiche elettromagnetiche di ogni apparato che poi vengono usate da questo software per generare le simulazioni di copertura.
Per questo studio ho usato un file binario di esempio guardandolo con un xxd e di un file .bas di Visual Basic che si trova sul forum di supporto del programma.
Purtroppo il file .bas fa riferimento a file .net nella versione 2000 e 3000 mentre i file generati dalle ultime versioni di Radio Mobile mostrano come numero di versione 4000.
Scrivo qui le mie conclusioni e le parti ancora ignote che spero prima o poi di colmare.
Il file inizia con una struttura di intestazione formata da 10 byte
[code lang="perl"]# HEADER STRUCTURE - Len 10 bytes# VERSION ([f] single-precision float - VB Single type - 4 bytes),
# NETWORK ELEMENTS ([s] signed short - VB Integer type - 2 bytes),
# UNIT ELEMENTS ([s] signed short - VB Integer type - 2 bytes),
# SYSTEM ELEMENTS ([s] signed short - VB Integer type - 2 bytes),[/code]
dove, tra parentesi, ho trascritto la struttura come vista dalla funziona pack/unpack di Perl e, di seguito, come vista dal Visual Basic.
Usando un po' di codice e, in particolare queste righe
[code lang="perl"]my $HeaderLen = 10;my $HeaderPack = 'fsss';
my @HeaderItems = qw/version networkCount unitCount systemCount/;
struct( HeaderType => { map {$_ => '$'} @HeaderItems } );
# read and unpack the header
my @struct = unpack($HeaderPack,$f->get_bytes($HeaderLen));
my $header = new HeaderType(map {$HeaderItems[$_] => $struct[$_]} (0..@HeaderItems-1));
print Data::Dumper::Dumper($header);[/code]
dove $f è un oggetto della classe File::Binary che punta a un file .net aperto in lettura, si ottiene la seguente struttura autoesplicativa
[code lang="perl"]$VAR1 = bless( {'HeaderType::systemCount' => 25,
'HeaderType::version' => '4000',
'HeaderType::unitCount' => 200,
'HeaderType::networkCount' => 50
}, 'HeaderType' );[/code]
che indica appunto il numero di versione e lo spazio assegnato e utilizabile per i network, i punti (unit) e i tipi di sistemi (system) gestibili da questo file .net.
Proseguendo nella lettura del file binario, subito dopo, si trova, ripetuta tante volte per quante sono il numero di punti nel file, la seguente struttura lunga 44 bytes
[code lang="perl"]# UNIT STRUCTURE - Len 44 bytes</pre># LON ([f] single-precision float - VB Single type - 4 bytes),
# LAT ([f] single-precision float - VB Single type - 4 bytes),
# H ([f] single-precision float - VB Single type - 4 bytes),
# ENABLED ([s] signed short - VB Integer type - 2 bytes),
# TRANSPARENT ([s] signed short - VB Integer type - 2 bytes),
# FORECOLOR ([l] signed long - VB Integer type - 4 bytes),
# BACKCOLOR ([l] signed long - VB Integer type - 4 bytes),
# NAME ([A] ASCII string - VB String*20 - 20 bytes),[/code]
quindi segue la definizione dei system, con la seguente struttura, lunga 50 byte
[code lang="perl"]# SYSTEM STRUCTURE - Len 50 bytes# TX ([f] single-precision float - VB Single type - 4 bytes),
# RX ([f] single-precision float - VB Single type - 4 bytes),
# LOSS ([f] single-precision float - VB Single type - 4 bytes),
# ANT ([f] single-precision float - VB Single type - 4 bytes),
# H ([f] single-precision float - VB Single type - 4 bytes),
# NAME ([A] ASCII string - VB String*30 - 30 bytes),[/code]
ripetuta tante volte per il numero di system definiti nell'header.
Dopo di questo il file .bas riportava di due strutture di byte di forma matriciale bidimensionale di dimensione pari al prodotto tra il numero di unità e quello di reti. Io ne ho trovate invece, nella versione 4000, tre. Il file VB identifica la prima come net_role e la seconda come net_system. Probabilmente identificano in che network è situata ogni unit e con che sistema radio. Ovviamente è da investigare.
Subito dopo arriva la definizione dei network con una struttura di 72 byte
[code lang="perl"]# NET STRUCTURE - Len 72 bytes# MINFX ([f] single-precision float - VB Single type - 4 bytes),
# MAXFX ([f] single-precision float - VB Single type - 4 bytes),
# POL ([s] signed short - VB Integer type - 2 bytes),
# EPS ([f] single-precision float - VB Single type - 4 bytes),
# SGM ([f] single-precision float - VB Single type - 4 bytes),
# ENS ([f] single-precision float - VB Single type - 4 bytes),
# CLIMATE ([s] signed short - VB Integer type - 2 bytes),
# MDVAR ([s] signed short - VB Integer type - 2 bytes),
# TIME ([f] single-precision float - VB Single type - 4 bytes),
# LOCATION ([f] single-precision float - VB Single type - 4 bytes),
# SITUATION ([f] single-precision float - VB Single type - 4 bytes),
# HOPS ([s] signed short - VB Integer type - 2 bytes),
# TOPOLOGY ([s] signed short - VB Integer type - 2 bytes),
# NAME ([A] ASCII string - VB String*30 - 30 bytes),[/code]
ripetuta tante volte per quanti network sono definiti nell'header.
Segue quindi una struttura denominata Coverage che, sostanzialmente contiene i parametri della finestra "Single Polar Radio Coverage" di Radio Mobile.
La struttura, lunga 74 byte è cosi fatta
[code lang="perl"]# COVERAGE STRUCTURE - Len 74 bytes# DMAX ([f] single-precision float - VB Single type - 4 bytes),
# THMIN ([f] single-precision float - VB Single type - 4 bytes),
# THMAX ([f] single-precision float - VB Single type - 4 bytes),
# THINC ([f] single-precision float - VB Single type - 4 bytes),
# ANTAZT ([f] single-precision float - VB Single type - 4 bytes),
# FILE ([A] ASCII string - VB String*20 - 20 bytes),
# TRESHOLD ([s] signed short - VB Integer type - 2 bytes),
# LEVEL ([f] single-precision float - VB Single type - 4 bytes),
# AREA ([S] unsigned short - VB Boolean - 2 bytes, non credo bool)
# CAREA ([l] signed long - VB Integer type - 4 bytes),
# CONTOUR ([S] unsigned short - VB Boolean - 2 bytes)
# CCONTOUR ([l] signed long - VB Integer type - 4 bytes),
# VHS ([f] single-precision float - VB Single type - 4 bytes),
# VHT ([f] single-precision float - VB Single type - 4 bytes),
# DMIN ([f] single-precision float - VB Single type - 4 bytes),
# VCOL ([l] signed long - VB Integer type - 4 bytes),[/code]
e probabilmente è qui, per la gestione delle copertura in batch. Segue infine un signed-short di 2 byte con la lunghezza di una stringa che contiene il percorso al file .map che segue subito dopo e, successivamente a questa stringa, si entra in un loop finchè non finisce il file o i successivi 2 byte non sono zero, in cui si legge un signed-short di 2 byte che contiene la lunghezza della successiva stringa che contiene il percorso ad ogni singola picture da aprire all'apertura del file .net.
Indi, almeno per il file VB, c'è il caricamento di una matrice di single di grandezza pari al prodotto tra il numero di unità e quello di reti, quindi un elenco che identifica le icone di ogni unit, di tipo byte e di lunghezza uguale al numero di unit e, per finire, delle lineLossPerMeter di tipo single di lunghezza pari al numero di system.
Il problema con quest'ultima parte è che, a parte non aver identificato bene le strutture, e questo è da fare, ma il fatto è che, mentre per il file VB, il file .net dovrebbe essere finito, nella realtà c'è dell'altra roba, tra cui un percorso ad fantomatico file landheight.dat che sembra pure roba obsoleda.
C'è ancora da studiare ma ovviamente, se qualcuno ne sa più di me, si faccia avanti.
Usare DynDns con RouterOs
Lo script sotto permette, a chi ha una routerboard Mikrotik o un sistema con caricato RouterOs di aggiornare gli indirizzi del proprio account su DynDns.org.
Lo script, per essere configurato, necessità del nome host da aggiornare, dello username e password del proprio account su DynDns e dell'interfaccia su cui vi è l'indirizzo dinamicamente assegnato dal provider.
Lo script seguente, se eseguito, aggiorna la propria configurazione
[code lang="bash"]:global ddnsuser "YOUR_USERNAME":global ddnspass "YOUR_PASSWORD"
:global ddnshost "YOUR.DOMAIN.EXT"
:global ddnsinterface "THE_INTERFACE"
:global ddnsip [ /ip address get [/ip address find interface=$ddnsinterface] address ]
:global ddnslastip
:if ([:len [/interface find name=$ddnsinterface]] = 0 ) do={ :log info "DDNS: No interface named $ddnsinterface, please check configuration." }
:if ([ :typeof $ddnslastip ] = "nothing" ) do={ :global ddnslastip 0.0.0.0/0 }
:if ([ :typeof $ddnsip ] = "nothing" ) do={
:log info ("DDNS: No ip address present on " . $ddnsinterface . ", please check.")
} else={
:if ($ddnsip != $ddnslastip) do={
:log info "DDNS: Sending UPDATE!"
:local ddnsip1 [:pick $ddnsip 0 [:find $ddnsip "/"] ];
:local str "/nic/update?hostname=$ddnshost&myip=$ddnsip1";
/tool fetch address=members.dyndns.org src-path=$str mode=http user=$ddnsuser password=$ddnspass dst-path=("/DynDNS.".$ddnshost)
:delay 1
:local str [/file find name="DynDNS.$ddnshost"];
/file remove $str
:global ddnslastip $ddnsip
} else={
:log info "DDNS: No changes necessary."
}
}[/code]
Questo script può, ovviamente essere eseguito automaticamente, ogni ora o anche meno, usando lo scheduler.
Riporto qui sotto, per comodità, i comandi da incollare in una finestra del terminale del winbox, che aggiungono lo script sopra e uno scheduler che esegue lo script ogni 10 minuti
[code lang="bash"]/system scriptadd name="DynDNS update" policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive source="\
:global ddnsuser \"YOUR_USERNAME\"\r\
\n:global ddnspass \"YOUR_PASSWORD\"\r\
\n:global ddnshost \"YOUR.DOMAIN.EXT\"\r\
\n:global ddnsinterface \"THE_INTERFACE\"\r\
\n:global ddnsip [ /ip address get [/ip address find interface=\$ddnsinter\
face] address ]\r\
\n:global ddnslastip\r\
\n:if ([:len [/interface find name=\$ddnsinterface]] = 0 ) do={ :log info \
\"DDNS: No interface named \$ddnsinterface, please check configuration.\" \
}\r\
\n:if ([ :typeof \$ddnslastip ] = \"nothing\" ) do={ :global ddnslastip 0.\
0.0.0/0 }\r\
\n:if ([ :typeof \$ddnsip ] = \"nothing\" ) do={\r\
\n:log info (\"DDNS: No ip address present on \" . \$ddnsinterface . \", p\
lease check.\")\r\
\n} else={\r\
\n :if (\$ddnsip != \$ddnslastip) do={\r\
\n :log info \"DDNS: Sending UPDATE!\"\r\
\n\t:local ddnsip1 [:pick \$ddnsip 0 [:find \$ddnsip \"/\"] ];\r\
\n\t:local str \"/nic/update\?hostname=\$ddnshost&myip=\$ddnsip1\";\r\
\n /tool fetch address=members.dyndns.org src-path=\$str mode=http user\
=\$ddnsuser password=\$ddnspass dst-path=(\"/DynDNS.\".\$ddnshost)\r\
\n :delay 1\r\
\n :local str [/file find name=\"DynDNS.\$ddnshost\"];\r\
\n /file remove \$str\r\
\n :global ddnslastip \$ddnsip\r\
\n } else={ \r\
\n :log info \"DDNS: No changes necessary.\"\r\
\n }\r\
\n}"
/system scheduler
add comment="" disabled=no interval=1h name="Schedule DynDNS Update" \
on-event="/system script run \"DynDNS update\"" policy=\
reboot,read,write,policy,test,password,sniff,sensitive start-time=startup
[/code]