NB1 – vi presento il mio robot #2 – il codice

Salve Nerdacci,

non mi sono dimenticato di voi e come promesso vi posto la versione del codice attualmente in utilizzo su NB1. Finalmente i sensori mancanti sono arrivati e quindi a breve potrò partire con i test. Ma non perdiamoci in chiacchiere e guardiamo il codice:

const short MOTOROUTPUT1 = 2;
const short MOTOROUTPUT2 = 3;
const short MOTOROUTPUT3 = 4;
const short MOTOROUTPUT4 = 5;
const short SENSORECHO1 = 6;
const short SENSORTRIG1 = 7;
const short SENSORECHO2 = 8;
const short SENSORTRIG2 = 9;
const short POWERBUTTON = 10;
const short SENSORECHO3 = 12;
const short SENSORTRIG3 = 13;
const short IRRECEIVER1 = A2;
const short IRRECEIVER2 = A0;
const short IRRECEIVER3 = A1;
const bool serialdbg = false;
const bool screendbg = true;
int duration,distance;</code>

void setup()
{
 if(serialdbg) Serial.begin(9600);

 //POWER BUTTON
 pinMode(POWERBUTTON, INPUT);

 //MOTOR PINS
 pinMode(MOTOROUTPUT1, OUTPUT);
 pinMode(MOTOROUTPUT2, OUTPUT);
 pinMode(MOTOROUTPUT3, OUTPUT);
 pinMode(MOTOROUTPUT4, OUTPUT);

 //SONIC SENSOR PINS
 pinMode(SENSORTRIG1, OUTPUT);
 pinMode(SENSORTRIG2, OUTPUT);
 pinMode(SENSORTRIG3, OUTPUT);
 pinMode(SENSORECHO1, INPUT);
 pinMode(SENSORECHO2, INPUT);
 pinMode(SENSORECHO3, INPUT);

 //INFRARED SENSOR PINS
 pinMode(IRRECEIVER1, INPUT);
 pinMode(IRRECEIVER2, INPUT);
 pinMode(IRRECEIVER3, INPUT);

 if(screendbg) {
  //OLED DISPLAY SETUP
  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
   u8g.setColorIndex(255); // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
   u8g.setColorIndex(3); // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
   u8g.setColorIndex(1); // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
   u8g.setHiColorByRGB(255, 255, 255);
 }

 u8g.firstPage();
 do {
  initScreen();
 } while ( u8g.nextPage() );
   delay(2000);
 }
}

void initScreen()
{
 u8g.setFont(u8g_font_osb21);
 u8g.drawStr( 40, 22, "NB1");
}

void clearScreen() {}

void draw(short sensor,int value=0) {
 u8g.setFont(u8g_font_osb18);
 u8g.setFontPosTop();
 enum {BufSize=9}; // If a is short use a smaller number, eg 5 or 6
 char buf[BufSize];
 switch (sensor) {
 case 1:
 //front sensor
 u8g.drawFrame(45, 2, 40, 30);
 snprintf (buf, BufSize, "%d", value);
 u8g.drawStr(46, 3, buf);
 break;
 case 2:
 //left sensor
 u8g.drawFrame(2,20,42,30);
 snprintf (buf, BufSize, "%d", value);
 u8g.drawStr( 3, 21, buf);
 break;
 case 3:
 //right sensor
 u8g.drawFrame(86,20,42,30);
 snprintf (buf, BufSize, "%d", value);
 u8g.drawStr(87, 21, buf);
 break;
 case 99:
 //stop
 u8g.drawStr( 40, 22, "Stop");
 break;
 }
}

void loop() {
 //dichiarazione variabili
 int distance;

 //Serial.println("--------------------------------------------");
 while (!proximityChk(1)) {
  if ((!irCheck(2)) && (!irCheck(3))) {
   if(serialdbg) Serial.println("move forward");
   moveForward();
  } else break;
 }
 //se nb1 è circondato
 if (proximityChk(2) && proximityChk(3)) {
  //eseguo retromarcia
  while (proximityChk(2) && proximityChk(3)) {
   if(serialdbg) Serial.println("move backward");
   moveBackward();
  }
  if ((!proximityChk(2)) && (!irCheck(2))) {
  if(serialdbg) Serial.println("turn left");
  turnLeft();
 } //altrimenti controllo se a destra è libero
 else {
 //mi giro a destra
  if ((!proximityChk(3)) && (!irCheck(3))) {
   if(serialdbg) Serial.println("turn right");
   turnRight();
   }
  }
 } else { //altrimenti controllo per convenzione a sinistra
 //se a sinistra è libero mi giro a sinistra
 if (!proximityChk(2)){
  if(serialdbg) Serial.println("turn left");
  turnLeft();
 } //altrimenti controllo se a destra è libero
 else {
 //mi giro a destra
  if (!proximityChk(3)) {
   if(serialdbg) Serial.println("turn right");
   turnRight();
  }
 }
}
}

 boolean irCheck(short irSensor) {
 switch (irSensor) {
 case 1:
 if(serialdbg) Serial.println(" - fotodiodo inferiore -");
 if(digitalRead(IRRECEIVER1)==HIGH) return true;
 break;
 case 2:
 if(serialdbg) Serial.println(" - fotodiodo di sinistra -");
 if(digitalRead(IRRECEIVER2)==LOW) return true;
 break;
 case 3:
 if(serialdbg) Serial.println(" - fotodiodo di destra -");
 if(digitalRead(IRRECEIVER3)==LOW) return true;
 break;
 }
 return false;
 }

boolean proximityChk(short sensor) {
 if(serialdbg) Serial.print("controllo sensore ");
 if(serialdbg) Serial.println(sensor);
 switch (sensor) {
 case 1:
 //front sensor
 //imposto il segnale del trigger basso per 2microseconds
 digitalWrite(SENSORTRIG1, LOW);
 delayMicroseconds(2);
 //imposto il segnale del trigger alto per 10microseconds
 digitalWrite(SENSORTRIG1, HIGH);
 delayMicroseconds(10);
 //imposto il segnale del trigger basso fino a nuova condizione
 digitalWrite(SENSORTRIG1, LOW);
 duration = pulseIn(SENSORECHO1, HIGH);
 break;
 case 2:
 //left sensor
 //imposto il segnale del trigger basso per 2microseconds
 digitalWrite(SENSORTRIG2, LOW);
 delayMicroseconds(2);
 //imposto il segnale del trigger alto per 10microseconds
 digitalWrite(SENSORTRIG2, HIGH);
 delayMicroseconds(10);
 //imposto il segnale del trigger basso fino a nuova condizione
 digitalWrite(SENSORTRIG2, LOW);
 duration = pulseIn(SENSORECHO2, HIGH);
 break;
 case 3:
 //right sensor
 //imposto il segnale del trigger basso per 2microseconds
 digitalWrite(SENSORTRIG3, LOW);
 delayMicroseconds(2);
 //imposto il segnale del trigger alto per 10microseconds
 digitalWrite(SENSORTRIG3, HIGH);
 delayMicroseconds(10);
 //imposto il segnale del trigger basso fino a nuova condizione
 digitalWrite(SENSORTRIG3, LOW);
 duration = pulseIn(SENSORECHO3, HIGH);;
 break;
 }

 //Calculate the distance (in cm) based on the speed of sound.
 distance = duration / 58;
 if(serialdbg) Serial.print("distanza: ");
 if(serialdbg) Serial.println(distance);

 if((distance>=0)&&(screendbg)) {
 u8g.firstPage();
 do {
 draw(sensor,distance);
 }
 while ( u8g.nextPage() );
 }

 //se la distanza dall'ostacolo è uguale o superiore a 15cm proseguo
 if (distance >= 15) {
 return false;
 }
 else return true;
}

void moveForward() {
 if(irCheck(1)) {
  digitalWrite(MOTOROUTPUT1, LOW);
  digitalWrite(MOTOROUTPUT2, HIGH);
  digitalWrite(MOTOROUTPUT3, HIGH);
  digitalWrite(MOTOROUTPUT4, LOW);
 }
}

 void moveBackward(){
  stop();
  //startPlayback(sample1, sizeof(sample1));
  digitalWrite(MOTOROUTPUT1, HIGH);
  digitalWrite(MOTOROUTPUT2, LOW);
  digitalWrite(MOTOROUTPUT3, LOW);
  digitalWrite(MOTOROUTPUT4, HIGH);
  delay(1000);
 }

 void turnLeft() {
  moveBackward();
  //startPlayback(sample2, sizeof(sample2));
  digitalWrite(MOTOROUTPUT1, LOW);
  digitalWrite(MOTOROUTPUT2, HIGH);
  digitalWrite(MOTOROUTPUT3, LOW);
  digitalWrite(MOTOROUTPUT4, LOW);
  delay(2000);
 }

 void turnRight(){
  moveBackward();
  //startPlayback(sample3, sizeof(sample3));
  digitalWrite(MOTOROUTPUT1, LOW);
  digitalWrite(MOTOROUTPUT2, LOW);
  digitalWrite(MOTOROUTPUT3, HIGH);
  digitalWrite(MOTOROUTPUT4, LOW);
  delay(2000);
 }

 void sharpLeft(){
  //startPlayback(sample3, sizeof(sample3));
  digitalWrite(MOTOROUTPUT1, LOW);
  digitalWrite(MOTOROUTPUT2, HIGH);
  digitalWrite(MOTOROUTPUT3, LOW);
  digitalWrite(MOTOROUTPUT4, HIGH);
  delay(2000);
 }

 void sharpRight(){
  //startPlayback(sample3, sizeof(sample3));
  digitalWrite(MOTOROUTPUT1, HIGH);
  digitalWrite(MOTOROUTPUT2, LOW);
  digitalWrite(MOTOROUTPUT3, HIGH);
  digitalWrite(MOTOROUTPUT4, LOW);
  delay(2000);
 }

 void stop() {
  digitalWrite(MOTOROUTPUT1, LOW);
  digitalWrite(MOTOROUTPUT2, LOW);
  digitalWrite(MOTOROUTPUT3, LOW);
  digitalWrite(MOTOROUTPUT4, LOW);
 }

a presto!

Annunci

NB1 – vi presento il mio robot #1 – lo schema – giorno 11227

Salve Nerdacci,

oggi vi presento la mia creaturina NB1.

Ancora non è terminato poichè devono arrivare un paio di sensori e devo collegare il tester della batteria Li-Po. Presto caricherò un video sul mio canale nel quale farò una dimostrazione delle potenzialità di NB1.

Eccovi lo schema:

nb1_schem

  • Accensione – Sono presenti 2 tasti: uno dedicato al reset che può essere utilizzato per rinizializzare il programma. Il secondo è un tasto che viene letto ad ogni ciclo della funzione loop e che permette di fermare il robot in qualsiasi momento.
  • Movimento – Come potete vedere dallo schema il robot ha 2 motori pilotati da un l239D al quale è possibile eventualmente collegare un’alimentazione supplementare nel caso i motori richiedano una tensione superiore.
  • Rilevamento ostacoli – I sensori ad ultrasuoni HC-SR04 sono montati a 90° uno rispetto all’altro rispettivamente a sinistra(2), avanti(1) e destra(3). Questi permettono di valutare in tempo reale i macro-ostacoli posti nelle 3 posizioni. Un ruolo altrettanto importante è svolto dai sensori IR posti a 45° rispetto a quelli ad ultrasuoni e servono a controllare eventuali ostacoli in fase di rotazione (essendo la base del robot squadrata).
  • Visualizzazione dati sensori – In coda al robot c’è uno schermo OLED  128*96 sul quale compare in tempo reale l’immagine del sensore interrogato e il valore rilevato dal robot in modo da interpretare ed eventualmente fare debug su eventuali comportamenti anomali.

Presto farò un articolo con il codice che ho utilizzato per NB1 e qualche foto.

A presto!

Urban Terror 4.3 Dedicated Server – facciamo un po’ di chiarezza

urt42_engine_150

Salve Nerdacci,

oggi affrontiamo un tema un po più divertente ma che può diventare noioso nel giro di pochi minuti se non viene gestito nel modo giusto.

Come avrete capito dal titolo parliamo del server dedicato (nello specifico su windows ma poco cambia su Linux) di UT.

Questo articolo verte a fare un po di chiarezza sulle guide che girano online per configurare il server che dicono tutto e niente.

Pochi e semplici passi:

  1. Download ed estrazione del file di gioco
  2. Creazione e modifica di un collegamento all’eseguibile del server dedicato
  3. Creazione dei file cfg necessari allo scopo

Passo 1 nulla da aggiungere


Passo 2 – Creiamo un collegamento al file “Quake3-UrT-Ded.exe” (chiamatelo come volete) e modificatene le Proprietà come segue:

Destinazione (Target per la versione inglese di windows) : “<path_di_installazione>\Quake3-UrT-Ded.exe” +exec server.cfg


Passo 3 – I file necessari allo scopo vanno da un minimo di uno (il server.cfg appunto) ed un massimo di 3 (nel mio caso)

Per iniziare va benissimo rinominare il file nella sottocartella q3ut4 che si chiama server_example.cfg in server.cfg

Il secondo file che bisogna editare per effettuare il mapcycle, ovvero la rotazione delle mappe, è mapcycle_example.txt. Questo file contiene una lista “brutale” delle mappe al quale però può essere affiancata una serie di parametri come l’esempio sotto:

//***mapcycle.txt***
ut4_turnpike
{
g_motd "qualche messaggio"
g_gametype 4
timelimit 20
}
ut4_riyadh
{
g_motd "qualche messaggio"
g_gametype 4
timelimit 20
}
ut4_commune
{
g_motd "qualche messaggio"
g_gametype 7
g_hotpotato 1
g_flagreturntime 10
capturelimit 5
g_friendlyfire 0
g_maxteamkills 10
}
ut4_elgin
{
g_motd "qualche messaggio"
g_gametype 4
timelimit 20
}
ut4_kingpin
{
g_gametype 4
timelimit 20
}
ut4_subway
{
g_motd "qualche messaggio"
g_gametype 8
timelimit 20
}
ut4_tombs
{
g_gametype 4
timelimit 20
}
ut4_swim
{
g_gametype 4
timelimit 20
}
//ut4_casa
//ut4_bohemia
//ut4_kingdom
//ut4_abbey
//ut4_cascade
//ut4_prague
//ut4_mandolin
//ut4_uptown
//ut4_algiers
//ut4_austria
//ut4_oildepot
//ut4_ghosttown
//ut4_harbortown
//ut4_prominence
//ut4_ramelle
//ut4_raiders
//ut4_sanc
//ut4_eagle
//ut4_suburbs
//ut4_thingley

Con la tecnica della modifica del link sopra questa rotazione verrà caricata automaticamente. Se volte cambiare mappa nel corso del gioco potete scrivere sulla console del server “cyclemap” oppure nella console del client “\rcon cyclemap“.

Il terzo file è facoltativo e vi permette di inserire i bot nelle vostre partite (ATTENZIONE! non tutte le mappe permettono la creazione di bot). Sempre nella stessa cartella create il file bots.txt (o come volete chiamarlo voi) con il seguente contenuto:

//***bots.txt***

addbot C ockroach 5 Blue 76 =lvl5=C ockroach
addbot Cheetah 5 Blue 56 =lvl5=Cheetah
addbot Cobra 5 Blue 45 =lvl5=Cobra
addbot Penguin 5 Blue 89 =lvl5=Penguin
addbot Puma 5 Blue 89 =lvl5=Puma
addbot Tiger 5 Blue 89 =lv5=Tiger

Ovviamente se volete aggiungere altri bot basta ricopiare le righe stando attenti a due particolari:

  1. Il nickname(=lvlx=XXXX non deve essere mai ripetuto)
  2. Il nome del bot (quello subito dopo il comando addbot) deve appartenetre a quelli elencati qui sotto:
  • boa
  • cheetah
  • chicken
  • cobra
  • c ockroach (<== space between the C and the O added to pass BB filters)
  • cougar
  • goose
  • mantis
  • penguin
  • puma
  • python
  • raven
  • scarab
  • scorpion
  • tiger
  • widow

Una volta creato il file ci basterà effettuare 2 semplici operazioni:

  1. inserire questa linea nel nostro file server.cfg: set bot_enable “1”
  2. eseguire durante la partita il comando “exec bots.cfg” dalla console del server oppure “\rcon exec bots.cfg” dalla console del client.

Credo di aver detto tutto…Se così non fosse scrivetemi nei commenti =)

A presto!

Upgrade from Ubuntu 14.04 to 16.04 … considerazioni

Salve a tutti nerdacci,

oggi vi voglio parlare di un aggiornamento recente che ho dovuto affrontare su una macchina che ospita un server lamp basata su ubuntu 14.04, mysql 5.5.53 , php  5.5.9 e apache 2.4.7.

L’obbiettivo era di far avanzare una delle due macchine gemelle con ubuntu 14.04 alla 16.04. Ma passiamo alla ciccia! Lanciando il comando ‘sudo do-release-upgrade‘ ho avviato l’aggiornamento che è durato circa 30 minuti e durante il quale ho risposto ad alcune domande che delle interfaccine user friendly mi hanno posto.

La situazione attuale è la seguente:

  • Ubuntu 16.04
  • Mysql 5.7.16
  • PHP 7.0.8
  • Apache 2.4.18

Al momento le due macchine gemelle non sono più tali a causa dell’aggiornamento sopra e verranno allineate solamente una volta terminati i test.

Tutto questo per aiutarvi ancora una volta nel caso vi trovaste nella medesima situazione. La prima considerazione da fare è sul PHP7. Appena aggiornato mi sono accorto con il comando ‘php -m‘ che alcuni moduli non erano presenti nella nuova installazione. Il primo ad esempio è il curl ed essendo il mio portale pieno di chiamate ajax nel quale vengono effettuate numerose curl, ho provveduto ad installarlo con il comando ‘sudo apt-get install php-curl‘. Ovviamente il comando vale per tutti i moduli che non doveste trovare come quelli che vi elenco di seguito.

Vi allego una lista dei moduli che ho dovuto installare (segnati con un asterisco*) nella nuova versione:

PHP5 PHP7
bcmath bcmath*
bz2 bz2*
calendar calendar
Core Core
ctype ctype
curl curl*
date date
dba dba*
dom dom
ereg ereg*
exif exif
fileinfo fileinfo
filter filter
ftp ftp
gd gd
gettext gettext
hash hash
iconv iconv
json json
libxml libxml
mbstring mbstring
mcrypt
mhash
mysql mysql
mysqli mysqli
openssl openssl
pcntl pcntl
pcre pcre
PDO PDO
pdo_mysql pdo_mysql
Phar Phar
posix posix
readline readline
Reflection Reflection
session session
shmop shmop
SimpleXML SimpleXML
soap soap*
sockets sockets
SPL SPL
standard standard
sysvmsg sysvmsg
sysvsem sysvsem
sysvshm sysvshm
tokenizer tokenizer
wddx wddx
xml xml
xmlreader xmlreader
xmlwriter xmlwriter
xsl
Zend OPcache Zend OPcache
zip zip*
zlib zlib

Riguardo a mysql non c’è molto da dire. Il Wizard effettua dei controlli sulle tabelle e procede automaticamente con degli ALTER TABLE che sistemano eventuali problematiche che nel mio caso non hanno avuto alcun impatto.

Apache mantiene tutti le configurazioni precedentemente applicate come ad esempio virtualhost, directory e moduli configurati.

Spero di esservi stato di aiuto e se dovessi incontrare ostacoli nel corso dei test provvederò ad intregrare l’articolo.

A presto NERDACCI!

Arduino Micro – Irrigatore con soil moisture sensor FC-28

Salve Nerdacci,

oggi parliamo dell’ultimo progettino di elettronica a cui ho lavorato nelle ultime 2 settimane ovvero il mini irrigatore automatico con arduino micro.

soil_m_fb

Le parti in blu le ho stampate con la solidoodle 2 pro per poter avvitare la pompa in una vasca (l’anello)  e adattarer la cannuccia a quest’ultima.

Vi mostro subito lo schema  elaborato con fritzing:

soil_m_schem

Lo schema mostra chiaramente un transistor pnp come switch per attivare e disattivare la pompa (M1).

Sulla destra invece i due componenti (4,5) che sono rispettivamente il regolatore di sensibilità che permette di tarare la giusta umidità sotto la quale la nostra piantina dovrà essere innaffiata e di seguito il sensore che verrà posizionato nel terreno.

Nella foto è possibile notare la presenza di un 7805 che ho utilizzato per portare la tensione della batteria ricaricabile da 9V a 5V.

Il codice (che potete arricchire ulteriormente e scrivere nei commenti) è il seguente (molto banale):


int sm = 0;

void setup() {

Serial.begin(9600);

pinMode(3,OUTPUT);

pinMode(4,INPUT);

pinMode(2,INPUT);

}

void loop() {

sm = analogRead(2);

Serial.println(sm);

if(digitalRead(4)==HIGH) { digitalWrite(3,HIGH); } else digitalWrite(3,LOW);

delay(1000);

}

Spero di esservi stato utile e scrivetemi se avete apportato delle migliorie =)

A presto!

IBM ILOG REST API – PHP/CURL to JSON – GET RULES

Salve Nerdacci!
Oggi voglio dare una perla di codice per recuperare le rules (regole) di ILOG
dal proprio server in formato json con la classe CURL di PHP.

public function actionILOGCurl()
{
 if(!extension_loaded ( "cURL" )) return false;
 $baseurl = "ilog_address:ilog_port";
 $username = "username";
 $password = "password";
 $url = "http://".$username.":".$password."@".$baseurl."/apiauth/ruleapps?parts=all";
 $handle = curl_init();
 curl_setopt($handle, CURLOPT_URL, $url);
 $headers = array('accept: text/json');
 curl_setopt($handle, CURLOPT_FOLLOWLOCATION, TRUE);
 curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
 curl_setopt($handle, CURLOPT_TIMEOUT, 5);
 curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);
 curl_setopt($handle, CURLOPT_SSLVERSION,3);
 curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
 curl_setopt($handle, CURLOPT_POSTREDIR, 3);
 curl_setopt($handle, CURLOPT_HTTPHEADER, $headers );
 $response = curl_exec($handle);
 error_log($response);
 curl_close($handle);

 header("Content-type: text/json");
 echo $response;
}

Non commento il codice perchè parla da sè.
Mi raccomando modificate $baseurl, $username e $password e in bocca al lupo.
Il codice è stra-testato quindi non abbiate paura e spero di esservi stato utile.
Ovviamente una volta nel formato json potete parsarlo con jquery/javascript e
formattarlo in una tabella HTML.

Alla prossima!

Free analytics platform – Piwik

Buonasera nerdacci,

ho avuto modo di installare e testare per un lungo periodo di tempo Piwik.

Devo dire che sono molto soddisfatto e vorrei descrivere la mia esperienza.

Nello specifico ho inserito Piwik per monitorare un portale intranet sviluppato con Yii 1.1.17. Per integrare Piwik in Yii (per chi non lo sapesse) bisogna inserire il codice qui sotto (con le dovute modifiche) nel file contenuto nella <root di Yii>/protected/views/layouts/main.php (possibilmente nel tag <head>)

var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u=web_server_address;
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', 1]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();

L’altro file che potrebbe essere utile editare  è /var/www/html/piwik/config/config.ini.php

[database]
host = "address_or_name";
username = "username";
password = "password";
dbname = "dbname";
tables_prefix = "opzionale";

[General]
salt = "lasciate_quello_di_default";
trusted_hosts[] = "server_abilitato_a_inviare_statistiche_1";
trusted_hosts[] = "server_abilitato_a_inviare_statistiche_n";

A questo punto potete accedere alla console di piwik all’indirizzo:

<web_server_address>/piwik/index.php

e seguire il wizard di installazione che vi guiderà a configurare la piattaforma.

Una volta installato possiamo cominciare ad aggiungere i nostri website come in foto

piwik_1

Ogni volta che qualcuno accede al vostro sito verranno inviate le informazioni al vostro piwik il quale collezionerà i dati e vi permetterà di visualizzarli sotto forma di dashboard personalizzabili.

 

Nel caso doveste dimenticare la password di root potete cambiarla con un trick direttamente sul db con questa query:

UPDATE `piwik_user` SET `password` = MD5( ‘changeMe’ ), `token_auth` = MD5( CONCAT(‘admin’, password)) WHERE `login` = ‘admin’ AND superuser_access = 1

ricordandovi di modificare i campi in base alle vostre necessità.

Spero di esservi stato utile e come al solito fatemi sapere se la vostra esperienza è stata positiva.

A presto