Piccolo promemoria ...visto che me lo scordo sempre
Nell'editor vi per selezionare e copiare testo si deve, in modalita' comando, premere v (comparira' la scritta -- VISUAL -- in basso) e si evidenzia il testo da copiare con i tasti freccia
A questo punto si puo' copiare (yank) con il tasto y o cancellare con d
Per incollare il testo precedentemente copiato usa p (paste)
giovedì 29 novembre 2018
Alexa Ask Cli ed Address API
Per installare l'interfaccia di programmazione di Alexa a linea di comando (senza utilizzare gli editor Web online di Alexa ed Aws Lambda) si puo' usare Ask Cli che si installa tramite npm con
npm install -g ask-cli
verra' al termine richiesto di loggardi con la propria user e password su Amazon tramite un finestra di autenticazione web
Nel caso in cui ask risponda con un messaggio di errore del tipo
vuol dire che l'interfaccia Ask Cli non riesce ad auntenticarsi sui server Amazon.
ask new --template --url https://skilltemplates.com/templates.json
(altrimenti se si crea una skill ex novo
ask new --skill-name test --lambda-name test
)
npm install -g ask-cli
verra' al termine richiesto di loggardi con la propria user e password su Amazon tramite un finestra di autenticazione web
Nel caso in cui ask risponda con un messaggio di errore del tipo
InvalidClientTokenId: The security token included in the request is invalid.
La soluzione e' riprocedere con il comando
ask init
(attenzione se non gia' configurato a questo punto verra' chiesto di inserire le proprie credenziali.
Su alcuni SO la procedura funziona senza problemi...in altri casi si deve usare ask init --no-browser a causa di un errore di Unhandled promise rejection)
(attenzione se non gia' configurato a questo punto verra' chiesto di inserire le proprie credenziali.
Su alcuni SO la procedura funziona senza problemi...in altri casi si deve usare ask init --no-browser a causa di un errore di Unhandled promise rejection)
A questo punto si inizia con l'esempio
ask new --template --url https://skilltemplates.com/templates.json
(altrimenti se si crea una skill ex novo
ask new --skill-name test --lambda-name test
)
Dal menu si sceglie Device Location API Starter
si entra quindi nella nuova directory del template e si inserisce
ask deploy
ogni volta che e' stato modificato il codice in locale per effettuare l'upload della skill su Amazon si deve effettuare il deploy. Si puo' effettuare anche un deploy parziale della sola funzione Lambda con
ask lambda upload
Le Address API richiedono una autorizzazione esplicita da parte dell'utente per l'utilizzo. Si deve quindi andare su https://alexa.amazon.it cliccare Le tue Skill, Skill attivate e cercare device-location-api-starter attivare la Skill con l'autorizzazione
a questo punto si e' presentato un problema. La skill era priva di endpoint perche' non e' stata creata la corrispondente funziona Lambda. Ho quindi proceduto a creare una Lambda copiandoci poi sopra il file index.js che ho trovato nel template
----------------------------------------------
/* eslint-disable func-names */
/* eslint-disable no-console */
const Alexa = require('ask-sdk-core');
const APP_NAME = "Location Starter"
const messages = {
NOTIFY_MISSING_PERMISSIONS: 'Please enable device location permissions in the Amazon Alexa app.',
NO_ADDRESS: 'It looks like you don\'t have an address set. You can set your address from the companion app.',
ERROR: 'Uh Oh. Looks like something went wrong.'
};
const DEVICE_LOCATION_PERMISSION = 'read::alexa:device:all:address';
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const speechText = `Hello, welcome to ${APP_NAME}. You can ask about device address by saying what is my location`;
const repromptText = 'What would you like to know?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(repromptText)
.withSimpleCard(APP_NAME, speechText)
.getResponse();
},
};
const DeviceLocationIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'DeviceLocationIntent';
},
async handle(handlerInput) {
const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
try {
const { deviceId } = requestEnvelope.context.System.device;
const deviceAddressServiceClient = serviceClientFactory.getDeviceAddressServiceClient();
const address = await deviceAddressServiceClient.getFullAddress(deviceId);
let response;
if (address == undefined || (address.addressLine1 === null && address.stateOrRegion === null)) {
response = responseBuilder.speak(messages.NO_ADDRESS).getResponse();
return response;
} else {
const completeAddress = `${address.addressLine1}, ${address.stateOrRegion}, ${address.postalCode}`;
const response = `Your complete address is, ${completeAddress}`;
return handlerInput.responseBuilder
.speak(response)
.withSimpleCard(APP_NAME, response)
.getResponse();
}
} catch (error) {
console.log(JSON.stringify(error));
if (error.statusCode == 403) {
return responseBuilder
.speak(messages.NOTIFY_MISSING_PERMISSIONS)
.withAskForPermissionsConsentCard([DEVICE_LOCATION_PERMISSION])
.getResponse();
}
console.log(JSON.stringify(error));
const response = responseBuilder.speak(messages.ERROR).getResponse();
return response;
}
},
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'You can ask for the address';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
},
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
},
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);
return handlerInput.responseBuilder.getResponse();
},
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error handled: ${error.message}`);
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Please say again.')
.reprompt('Sorry, I can\'t understand the command. Please say again.')
.getResponse();
},
};
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
DeviceLocationIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler
)
.addErrorHandlers(ErrorHandler)
.withApiClient(new Alexa.DefaultApiClient())
.lambda();
----------------------------------------------
questo e' il file skill.json. Evidenziato in giallo la richiesta dei permessi
----------------------------------------------
{
"manifest": {
"publishingInformation": {
"locales": {
"en-US": {
"summary": "Sample Short Description",
"examplePhrases": [
"Alexa open location starter",
"Alexa ask location starter about my adrees"
],
"keywords": [
"keyword1",
"keyword2",
"keyword3"
],
"name": "device-location-api-starter",
"description": "Sample Full Description",
"smallIconUri": "https://s3.amazonaws.com/cdn.dabblelab.com/img/skill-template-default-sm.png",
"largeIconUri": "https://s3.amazonaws.com/cdn.dabblelab.com/img/skill-template-default-lg.png"
}
},
"isAvailableWorldwide": true,
"testingInstructions": "No special instructions.",
"category": "EDUCATION_AND_REFERENCE",
"distributionCountries": []
},
"apis": {
"custom": {
"endpoint": {
"sourceDir": "lambda/custom"
}
}
},
"manifestVersion": "1.0",
"permissions": [
{
"name": "alexa::devices:all:address:full:read"
}
],
"privacyAndCompliance": {
"allowsPurchases": false,
"locales": {
"en-US": {
"termsOfUseUrl": "http://dabblelab.com/terms",
"privacyPolicyUrl": "http://dabblelab.com/privacy"
}
},
"isExportCompliant": true,
"containsAds": false,
"isChildDirected": false,
"usesPersonalInfo": false
}
}
}
----------------------------------------------
Di default non viene assunto l'indirizzo del dispositivo con quello configurato nel profilo Amazon. Si deve settare in modo esplicito la posizione nella app sul telefono Alexa Amazon per ogni dispositivo
venerdì 23 novembre 2018
Problemi di Alexa
un po' di problemi con Alexa...alcuni esempi
"funzionale" viene interpretato come "funziona le"
"cfr" (pronunciato ciefferre) viene interpretato come "c'è fede"
"centro" alcune volte viene interpretato come "cento"
"sesto" viene intepretato come "6o"
questi problemi sono debuggabili solo attraverso la Alexa Developer Console tramite il file JSON che traduce il parlato nel file interpretato
"funzionale" viene interpretato come "funziona le"
"cfr" (pronunciato ciefferre) viene interpretato come "c'è fede"
"centro" alcune volte viene interpretato come "cento"
"sesto" viene intepretato come "6o"
questi problemi sono debuggabili solo attraverso la Alexa Developer Console tramite il file JSON che traduce il parlato nel file interpretato
giovedì 22 novembre 2018
Bash script come cgi in Apache
Cosa succede quando scrivi uno script bash che funziona bene e non vuoi convertirlo in Php? Semplice...ritorni indietro di venti anni e lo fai diventare un cgi script
Per prima cosa si devono abilitare gli script CGI in Apache
a2enmod cgi
service apache2 restart
Per prima cosa si devono abilitare gli script CGI in Apache
a2enmod cgi
service apache2 restart
in Debian la directory di default per i CGI e' in /usr/lib/cgi-bin...si copia quindi lo script e lo si rende eseguibile
Per prima cosa c'e' da dire che lo script non deve rispondere in modo arbitrario (per esempio con un semplice testo) ma con un file html altrimenti verranno generati errori del tipo 500 di output non correttamente formattato
In Bash si possono leggere anche le variabile GET passate sulla URL e cio' mediante IFS
Nell'esempio sottostante e' prevista una sola variabile (che corrisponde ad un id numerico) e che e' stata salvata nell'array parm all'indice 1
----------------------------------------------------
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
PATH="/bin:/usr/bin:/usr/opt/bin"
export $PATH
saveIFS=$IFS
IFS='=&'
parm=($QUERY_STRING)
IFS=$saveIFS
stringa="$(xidel --silent --extract "//img/@src" "http://xxxxxxxxxxxx.it/?utf8=true&size=micro&mode=double&idc=${parm[1]}" | grep idraulico | awk 'FNR==1')"
echo '</head>'
echo '<body>'
#echo ${parm[1]}
file="$(basename $stringa)"
echo $file
echo '</body>'
echo '</html>'
exit 0
----------------------------------------------------
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 ..)
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}"
Iscriviti a:
Post (Atom)
FigSpec FS-60CL
A lavoro mi hanno rifilato questo sensore iperspettrale cinese (pushbroom 400-1000 nm con larghezza di banda di 0.5 nm compatibile con DJI M...




