giovedì 22 novembre 2018

Xidel

Xidel e' un comodo programma a linea di comando che permette di estrarre informazioni da un file HTML. Non esiste nei repository di Debian ma il pacchetto .deb puo' essere comodo scaricato da questo link http://www.videlibri.de/xidel.html

Nell'esempio sottostante viene richiamata una pagina html da cui estrarre un link (che varia in modo non predefinito) in modo automatico

in pratica xidel richiama il file dall'indirizzo xxxxx.wp, estrae tutti gli HRef incontrati, si estraggono solo quelli che hanno la stringa "filename", poi con awk si prende solo il primo della lista e con sed si eliminano dei caratteri (in questo caso ..)


#!/bin/bash
cd "$(dirname "$0")";

stringa="$(xidel --silent --extract "//a/@href" xxxxxxxxxxxx.wp | grep filename | awk 'FNR==1' | sed 's/..//')"
echo "${stringa}"

martedì 20 novembre 2018

Estrarre dati da un XML a linea di comando

Per estrarre dati in modo semplice da un XML una soluzione puo' essere xml_grep
Questo comando e' incluso nel pacchetto Debian xml-twig-tools

si procede quindi con

apt-get install xml-twig-tools

supponiamo di avere un XML tipo

---------------
<?xml version='1.0' encoding='UTF-8'?>
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
  <identifier>XXXXXX</identifier>
  <sender>XXXXXX</sender>
  <sent>2018-11-14T15:24:00+01:00</sent>
  <status>Actual</status>
  <msgType>Alert</msgType>
  <scope>Public</scope>
  <note>XXXXXXX</note>
  <info>
    <category>Met</category>
    <event>XXXXX</event>
............
---------------
e che si voglia estrarre il contenuto di <note>
si puo' usare la semplice sintassi

xml_grep 'note' test.xml --text_only

lunedì 19 novembre 2018

Scheletro di progetto NodeJS

I comandi di base per creare un progetto NodeJS

mkdir test
cd test
npm init --yes
npm install request --save (viene installato via npm il modulo "request" nella subdir /node_modules)

si crea quindi il file del programma (per esempio app.js) e si lo si mette in esecuzione con 
node app.js

HTTP Async request in Alexa

Per fare interagire Alexa con server esterni la cosa piu' semplice e' usare il modulo http perche' e' un built-in e non necessita di supporto esterno. Si dichiara l'uso all'inizio della Lambda function

--------------------------------------------------------------------
const Alexa = require('ask-sdk');
var http = require('http'); 
--------------------------------------------------------------------

si crea poi una funzione di richiesta http. Attenzione: questa funzione e' di tipo asincrono e si deve inserire la Promise per fare in modo che il risultato entri nello scope della funzione principale
--------------------------------------------------------------------
function httpGet() {
  return new Promise(((resolve, reject) => {
    var options = {
        host: '80.211.xxxx,xxxx',  //solo ip o nome dominio ..niente http od https prima
        port: 80,
        path: '/dpc.php',
        method: 'GET',
    };
    
    const request = http.request(options, (response) => {
      response.setEncoding('utf8');
      let returnData = '';

      response.on('data', (chunk) => {
        returnData += chunk;
      });

      response.on('end', () => {
        resolve(returnData);
        console.log("returnData "+returnData);
      });

      response.on('error', (error) => {
        reject(error);
      });
    });
    request.end();
  }));
}
--------------------------------------------------------------------

Il custom intent che deve gestire la funzione asincrona sopra indicata deve essere modificato ponendo async nell'handler e deve aspettare il ritorno della funzione httpGet prima di procedere in modo da popolare in modo corretto la variabile response
--------------------------------------------------------------------
const geo = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (request.type === 'IntentRequest'
        && request.intent.name === 'geo');
  },
  
  
  async handle(handlerInput) {
  const response = await httpGet();

  const { intent } = handlerInput.requestEnvelope.request;
  const activity = intent.slots.luogo.value;
  var speechOutput = response;


  if (activity == "firenze")
      {
        //speechOutput = "firenze si trova in toscana";
      }
  
  if (activity == "milano")
      {
        speechOutput = "milano si trova in lombardia"
      }
  

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .getResponse();
  },
};
--------------------------------------------------------------------

mercoledì 14 novembre 2018

Alexa Skills



Per usare Alexa Skill in Europa si deve usare la zona AWS denominata Ireland

Per creare un custom intent in lambda NodeJS che legga le variabili passate da Alexa ASK si procede cosi

il modello prevede un custom intent di nome geo che ha uno slot  (ovvero una variabile) di nome luogo
---------------------------------------------------------------------------
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "geografia",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": [
                        "aiuto "
                    ]
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "geo",
                    "slots": [
                        {
                            "name": "luogo",
                            "type": "AMAZON.City"
                        }
                    ],
                    "samples": [
                        "dimmi dove si trova {luogo}",
                        "dimmi dove è {luogo}"
                    ]
                }
            ],
            "types": []
        }
    }
}
---------------------------------------------------------------------------

il custom intent deve intercettare una richiesta di tipo IntentRequest e di nome geo
le righe in azzurro servono a leggere la variabile luogo che e' passata da ASK (via JSON) e la mettono nella variabile JS ac
---------------------------------------------------------------------------
const geo = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (request.type === 'IntentRequest'
        && request.intent.name === 'geo');
  },
  handle(handlerInput) {
    

  const { intent } = handlerInput.requestEnvelope.request;
  const ac = intent.slots.luogo.value;
  var speechOutput = "  ";
  
  if (ac == "firenze")
      {
        speechOutput = "firenze si trova in toscana"
      }
  
  if (ac == "milano")
      {
        speechOutput = "milano si trova in lombardia"
      }
  

  console.log(ac);

    //const speechOutput = activity;

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .getResponse();
  },
};
---------------------------------------------------------------------------

i messaggi di console.log si leggono si Amazon CloudWatch Logs.Dalla finestra della funzione di Lambda in alto ci sono i tab Configurazione e Monitoraggio..si clicca Monitoraggio e poi visualizza log in CloudWatch



Per fare interagire Alexa con informazioni derivanti da un server esterno mediante richieste http
(lo script test.php e' semplicemente un echo("stringa");

---------------------------------------------------------------------------

var http = require('http'); 

http.get('http://80.211.xxx,xxx/test.php', (resp) => {
  let data = '';

  resp.on('data', (chunk) => {
    data += chunk;
  });

  // The whole response has been received. Print out the result.
  resp.on('end', () => {
    //console.log(JSON.parse(data).explanation);
    console.log(data);
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});
---------------------------------------------------------------------------

martedì 13 novembre 2018

OpenWRT su GL.Inet MT300N-V2

Rispetto al GL.Inet AR150  montare OpenWRT su  MT300N-V2 e' leggermente differente


Si parte impostantdo il portatile su 192.168.1.2. Si inserisce il cavo Ethernet su  LAN del M300, si preme in tasto reset e si connette l'alimentazione USB. Dopo 3 secondi (o quando il led rosso non lampeggia piu') si lascia il tasto reset e ci si connette al 192.168.1.1 e si effettua l'upload del firmware openwrt-18.06.0-ramips-mt76x8-gl-mt300n-v2-squashfs-sysupgrade.bin

A questo punto c'e' la differenza con AR150. Non viene attivata di default l'access point per cui si deve continuare la configurazione mantenendo collegato il cavo Ethernet sulla porta LAN e dopo il reboot si deve usare LuCi all'indirizzo 192.168.1.1

venerdì 26 ottobre 2018

ElectronJS

Un paio di anni fa avevo scritto una web app che, finita e pronta per entrare in produzione, non e' mai stata rilasciata....adesso voglio vedere di trasformarla in una applicazione desktop con ElectronJS


Si crea una directory ed una volta entrati in questa si digita

npm init

a questo punto vengono richieste delle informazioni (come il package name, la version e cosi' via) al termine delle quali viene creato il file package.json

si deve modificare il package.json con le indicazioni di start che puntano ad electron
---------------
{ "name": "tua-app", 
"version": "0.1.0", "
main": "index.js", 
"scripts": 
     { "start": "electron ." } 
}
---------------

a questo punto si installa Electron 

npm install --save-dev electron

il file di lancio di Electron e' index.js ed ha una forma del tipo
----------------------------------
const { app, BrowserWindow } = require('electron')
 function createWindow () {
 // Crea la finestra del browser 
 win = new BrowserWindow({ width: 800, height: 600 }) 
// e viene caricato il file index.html dell' app. 
win.loadFile('index.html') 
app.on('ready', createWindow)
------------------------
a questo punto ho inserito la web app che avevo scritto un paio di anni fa nella directory (con tutti gli stessi file che avevo sul web server) ed e' bastato inviare il comando

npm start

per avere la web app come un programma che gira in locale.
A questo punto sarebbe carino avere la applicazione in un pacchetto (in modo che sia un eseguibile come un altro per l'utente finale) e cio' si ha con electron packager

npm install -g electron-packager

electron-packager .  (attenzione al punto)

si creera' una subdir con il file in formato eseguibile ed una directory (bastera' distribuire il contenuto della directory in uno zip .. nel mio caso triage-electron-darwin-x64). In questo modo il codice e' pero' completamente leggibile. Puo' essere piu' comodo (non sicuro perche' comunque si riesce a leggere in ogni caso ma non in modo semplice) digitare il comando

electron-packager .  --asar

questo comando invece crea pacchetti per tutti i sistemi operativi suppportati

electron-packager .  --all

si puo' anche indicare una icona con lo switch --icon=assets/icons/png/1024x1024.png

fatto 30 faccciamo 31 ovvero l'installer per l'applicazione (nello specifico per Mac)

npm install electron-installer-dmg -g
(al momento della scrittura di questo post, nonostante la procedura sia corretta, non riesco a creare il dmg perche' su Mac ho un problema sulle dipendenze di una libreria che non si compila

Red Edge con Sentinel 2

Volevo migliorare un po' quanto provato qui piu' che altro per avere una migliore risoluzione spaziale. Ho provato con Sentinel 2 (...