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
lunedì 19 novembre 2018
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();
}));
}
--------------------------------------------------------------------
--------------------------------------------------------------------
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": []
}
}
}
---------------------------------------------------------------------------
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');
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
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",
npm install --save-dev electron
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
il file di lancio di Electron e' index.js ed ha una forma del tipo
----------------------------------
const { app, BrowserWindow } = require('electron')
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
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
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)
(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
mercoledì 24 ottobre 2018
TL-WR802N come client WiFi
Ho preso un Tp-Link TL-WR802N per connettere dei dispositivi dotati di sola Ethernet ad una rete Wifi
Acceso per la prima volta ci si deve connettere alla rete WiFi creata dal Tp-Link ....la password e' il minuscolo codice numerico ad 8 cifre sull'adesivo sul retro del dispositivo in prossimita' dei codici a barre. Si accede all'interfaccia web con la coppia admin/admin
A questo punto la cosa migliore e' aggiornare il firmware scaricando l'aggiornamento dal sito da questo sito https://www.tp-link.com/uk/download/TL-WR802N.html. Attenzione alla versione (nel mio caso V4) ed al fatto che il firmware esiste in versione EU e US (per decidere il firmware giusto guardare sull'interfaccia Web)
A questo punto si va in Easy Setup e si imposta la modalita' Client
Si imposta la rete WiFi a cui si vuole accedere
Acceso per la prima volta ci si deve connettere alla rete WiFi creata dal Tp-Link ....la password e' il minuscolo codice numerico ad 8 cifre sull'adesivo sul retro del dispositivo in prossimita' dei codici a barre. Si accede all'interfaccia web con la coppia admin/admin
A questo punto la cosa migliore e' aggiornare il firmware scaricando l'aggiornamento dal sito da questo sito https://www.tp-link.com/uk/download/TL-WR802N.html. Attenzione alla versione (nel mio caso V4) ed al fatto che il firmware esiste in versione EU e US (per decidere il firmware giusto guardare sull'interfaccia Web)
A questo punto si va in Easy Setup e si imposta la modalita' Client
riavviare il dispositivo. Una volta connesso alla rete WiFi in modo corretto il led verde smette di lampeggiare
venerdì 19 ottobre 2018
NoDogSplash captive portal in OpenWRT
Aggiornamento
questo e' la risposta degli sviluppatori
First of all, almost all operating systems on both mobile and laptop/desktop now support the defacto standard Captive Portal Detection (CPD) function designed to facilitate a secure and consistent login to captive portals. This by default uses a cut down browser that is very restricted for security purposes.
What you are seeing on Android is the CPD browser blocking iframes.
On your laptop you will be using your normal browser.
---------------------------------------------------------------------------
Il mio scopo e' quello di far girare NoDogSplash captive portal su GL.iNet AR150 con firmware OpenWRT Stock in modo che la pagina di benvenuto (nel linguaggio di NoDog e' la splash page) mostri contenuti ripresi da un sito web esterno e che sia quindi dinamica
Per prima cosa devo precisare che il firmware stable dell'AR150 monta una versione di NoDogSplash abbastanza vecchiotta ovvero la 0.9_beta9.9.9-5 (ho provato a montare anche il firmware in testing ma le cose migliorano di poco perche' opkg installa la 1.0.2.1)
Per creare il portale captivo ho tolto il WPA all'AP e poi usata la seguente configurazione
In pratica ho aggiunto alle regole di firewalle la possibilita' per utenti non autenticati di poter
raggiungere il sito 150.217.xxx.xxx su porta 80
---------------------------------------------------------------------------------
config instance
# Set to 1 to enable nodogsplash
option enabled 1
# Use plain configuration file as well
#option config '/etc/nodogsplash/nodogsplash.conf'
option network 'lan'
option gatewayname 'OpenWrt Nodogsplash'
option maxclients '250'
option idletimeout '1200'
#option redirecturl 'http://c1p81.altervista.org/montecatini/'
#qoption authenticateimmediately 'yes'
# Your router may have several interfaces, and you
# probably want to keep them private from the network/gatewayinterface.
# If so, you should block the entire subnets on those interfaces, e.g.:
list authenticated_users 'block to 192.168.0.0/16'
list authenticated_users 'block to 10.0.0.0/8'
# Typical ports you will probably want to open up.
list authenticated_users 'allow tcp port 22'
list authenticated_users 'allow tcp port 53'
list authenticated_users 'allow udp port 53'
list authenticated_users 'allow tcp port 80'
list authenticated_users 'allow tcp port 443'
# For preauthenticated users to resolve IP addresses in their
# initial request not using the router itself as a DNS server,
list preauthenticated_users 'allow tcp port 53'
list preauthenticated_users 'allow udp port 53'
llst preauthenticated_users 'allow tpc port 80 to 150.217.xxx.xxx'
# Allow ports for SSH/Telnet/DNS/DHCP/HTTP/HTTPS
list users_to_router 'allow tcp port 22'
list users_to_router 'allow tcp port 23'
list users_to_router 'allow tcp port 53'
list users_to_router 'allow udp port 53'
list users_to_router 'allow udp port 67'
list users_to_router 'allow tcp port 80'
list users_to_router 'allow tcp port 443'
# See https://github.com/nodogsplash for a full list of available options.
----------------------------------------------------------------
in seguito ho modificato lo splash.html come
l'idea e' quella di avere un iframe nel quale visualizzare la pagina derivante
dal sito esterno all'interno della pagina statica splash.html
-----------------------------------------------------------------
<html>
<head>
<title>$gatewayname Entry</title>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
</head>
<body bgcolor="#DDDDDD" text="#000000">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td align="center"><h2>Luca $gatewayname</h2></td>
</tr>
<tr>
<td align="center">
<iframe height="710" width="720" src="http://150.217.73.108"></iframe>
</td>
</tr>
<tr>
<td align="center" height="120">
<!--
A client is authenticated by requesting the page $authtarget.
So, href to it here, with an img or link text the user can click on.
Also, note that any images you reference must reside in the
subdirectory that is the value of $imagesdir (default: "images").
-->
<a href="$authtarget">
<!--<img src="$imagesdir/splash.jpg" width="71" height="49" border="0"
alt="Click to enter" title="Click to enter">-->
<img src="http://c1p81.altervista.org/montecatini/img/logo_strong.jpg">
<img src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
</a>
</td>
</tr>
</table>
<form method='GET' action='$authaction'>
<input type='hidden' name='tok' value='$tok'>
<input type='hidden' name='redir' value='$redir'>
<input type='submit' value='Click Here to Enter'>
</form>
</body>
</html>
---------------------------------------------------------------------
la cosa divertente e' che tutto funziona perfettamente se mi collego da portatile con Chrome
mentre la stessa pagina vista dal telefono (Android 9) viene visualizzata cosi'
Una soluzione potrebbe essere la modalita' Forwarding Authentication Service (FAS) (che in pratica reindirizza il login su un server esterno dovre peraltro potrebbe girare anche Php) ma non sembra funzionare (anche perche' tutti i tutorial sono per NoDogSplash 2....)
questo e' la risposta degli sviluppatori
First of all, almost all operating systems on both mobile and laptop/desktop now support the defacto standard Captive Portal Detection (CPD) function designed to facilitate a secure and consistent login to captive portals. This by default uses a cut down browser that is very restricted for security purposes.
What you are seeing on Android is the CPD browser blocking iframes.
On your laptop you will be using your normal browser.
---------------------------------------------------------------------------
Il mio scopo e' quello di far girare NoDogSplash captive portal su GL.iNet AR150 con firmware OpenWRT Stock in modo che la pagina di benvenuto (nel linguaggio di NoDog e' la splash page) mostri contenuti ripresi da un sito web esterno e che sia quindi dinamica
Per prima cosa devo precisare che il firmware stable dell'AR150 monta una versione di NoDogSplash abbastanza vecchiotta ovvero la 0.9_beta9.9.9-5 (ho provato a montare anche il firmware in testing ma le cose migliorano di poco perche' opkg installa la 1.0.2.1)
Per creare il portale captivo ho tolto il WPA all'AP e poi usata la seguente configurazione
In pratica ho aggiunto alle regole di firewalle la possibilita' per utenti non autenticati di poter
raggiungere il sito 150.217.xxx.xxx su porta 80
---------------------------------------------------------------------------------
config instance
# Set to 1 to enable nodogsplash
option enabled 1
# Use plain configuration file as well
#option config '/etc/nodogsplash/nodogsplash.conf'
option network 'lan'
option gatewayname 'OpenWrt Nodogsplash'
option maxclients '250'
option idletimeout '1200'
#option redirecturl 'http://c1p81.altervista.org/montecatini/'
#qoption authenticateimmediately 'yes'
# Your router may have several interfaces, and you
# probably want to keep them private from the network/gatewayinterface.
# If so, you should block the entire subnets on those interfaces, e.g.:
list authenticated_users 'block to 192.168.0.0/16'
list authenticated_users 'block to 10.0.0.0/8'
# Typical ports you will probably want to open up.
list authenticated_users 'allow tcp port 22'
list authenticated_users 'allow tcp port 53'
list authenticated_users 'allow udp port 53'
list authenticated_users 'allow tcp port 80'
list authenticated_users 'allow tcp port 443'
# For preauthenticated users to resolve IP addresses in their
# initial request not using the router itself as a DNS server,
list preauthenticated_users 'allow tcp port 53'
list preauthenticated_users 'allow udp port 53'
llst preauthenticated_users 'allow tpc port 80 to 150.217.xxx.xxx'
# Allow ports for SSH/Telnet/DNS/DHCP/HTTP/HTTPS
list users_to_router 'allow tcp port 22'
list users_to_router 'allow tcp port 23'
list users_to_router 'allow tcp port 53'
list users_to_router 'allow udp port 53'
list users_to_router 'allow udp port 67'
list users_to_router 'allow tcp port 80'
list users_to_router 'allow tcp port 443'
# See https://github.com/nodogsplash for a full list of available options.
----------------------------------------------------------------
in seguito ho modificato lo splash.html come
l'idea e' quella di avere un iframe nel quale visualizzare la pagina derivante
dal sito esterno all'interno della pagina statica splash.html
-----------------------------------------------------------------
<html>
<head>
<title>$gatewayname Entry</title>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
</head>
<body bgcolor="#DDDDDD" text="#000000">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td align="center"><h2>Luca $gatewayname</h2></td>
</tr>
<tr>
<td align="center">
<iframe height="710" width="720" src="http://150.217.73.108"></iframe>
</td>
</tr>
<tr>
<td align="center" height="120">
<!--
A client is authenticated by requesting the page $authtarget.
So, href to it here, with an img or link text the user can click on.
Also, note that any images you reference must reside in the
subdirectory that is the value of $imagesdir (default: "images").
-->
<a href="$authtarget">
<!--<img src="$imagesdir/splash.jpg" width="71" height="49" border="0"
alt="Click to enter" title="Click to enter">-->
<img src="http://c1p81.altervista.org/montecatini/img/logo_strong.jpg">
<img src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
</a>
</td>
</tr>
</table>
<form method='GET' action='$authaction'>
<input type='hidden' name='tok' value='$tok'>
<input type='hidden' name='redir' value='$redir'>
<input type='submit' value='Click Here to Enter'>
</form>
</body>
</html>
---------------------------------------------------------------------
la cosa divertente e' che tutto funziona perfettamente se mi collego da portatile con Chrome
mentre la stessa pagina vista dal telefono (Android 9) viene visualizzata cosi'
Una soluzione potrebbe essere la modalita' Forwarding Authentication Service (FAS) (che in pratica reindirizza il login su un server esterno dovre peraltro potrebbe girare anche Php) ma non sembra funzionare (anche perche' tutti i tutorial sono per NoDogSplash 2....)
Iscriviti a:
Post (Atom)
Feature Matching OpenCv
Il problema e' il seguente: trovare le differenze tra le due foto. Le due immagini sono state riprese a distanza di oltre un anno ed il ...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...