vendredi 15 avril 2016

Projet NinPi


Présentation

Le projet NinPi est né en 2012 à la suite de la parution de la revue Open Silicium n°5 et plus particulièrement l'article "Développez vos jeux 'Maison' pour Nintendo DS sous GNU/Linux" à la page 69.

Après avoir acheté cette revue, je l'ai régulièrement consulté sans idée de projet mais en sachant que j'aurais un jour la possibilité de la mettre en pratique.

Aujourd'hui je passe à l'action.

Créer un jeu c'est possible, mais est ce qu'il est possible de faire communiquer la DS avec l'extérieur via le wifi ?

Objectif

Donner la possibilité à toute personne qui dispose d'une carte Raspberry Pi, d'une dongle wifi, d'une Nintendo DS et d'un linker de mettre tout ça en relation.

En effet, certains passionnés en robotique sont toujours à la recherche d'une télécommande

Cette étude est purement théorique, car il faudrait disposer d'un linker (ou carte R4) ce qui est actuellement illégal en France.

Niveau de difficulté

Je suis un gros débutant en langage C en python et encore plus dans le monde du linux et j'y suis arrivé à le faire alors... suivez le guide.

A la date de la rédaction de ce tutoriel j'ai 5 jours de langage C et 3 mois de python.

Les différents liens sont tous repris à la fin du tutoriel.

Pour finir, j'ai rédigé ce tutoriel uniquement pour Linux mais il est possible de le faire sous Windows, sauf coté Raspberry.


Coté PC

Etape 1 - l'installation des logiciels

Dans un navigateur internet, il faut rechercher "devkitpro" et vous avez différentes solutions en Français [1] ou en Anglais [2].

Mon PC est sous Ubuntu et j'ai choisi... le [2].

Donc j'ai repris les étapes du sites mais à ma sauce car refaire l'installation 5 fois de suite permet de prendre certaines légèretés avec ce qui est proposé sur le web.

Dans un Terminal
sudo mkdir -p /opt/devkitrpo
J'ai oublié de préciser qu'il faudra faire tout ça avec les privilèges de root. Donc, maintenant nous avons un répertoire /opt/devkitrpo tout frais pour accueillir le projet.

Il faut modifier les droits d'accès à cet emplacement avec :
sudo chmod 777 /opt/devkitpro
Avant de télécharger les fichiers nous allons finir l’arborescence.
sudo mkdir /opt/devkitrpo/libnds
sudo mkdir /opt/devkitrpo/examples
Vous pouvez fermer la console pour l'instant.

Sur le site Web lien[2] vous avez la forme de l'arborescence à venir. Chaque nom de dossier étant un lien hypertexte, je vous invite a télécharger les fichiers :

Au moment de choisir le devkitARM du lien[4] (ci-dessous) je me suis posé la question "est ce que je suis en 64 ou 32 bits ?"

Nouvelle recherche sur le web avec le critère "linux processeur 32 ou 64 bits",. Il est proposé entre autre un site en Français [3]. Je suis en 64 bits.

Pour ma part j'ai donc pris :

[4] devkitARM_r45-x86_64-linux.tar.bz2
[5] libnds-1.5.12.tar.bz2
[6] libfat-nds-1.0.14.tar.bz2
[7] dswifi-0.3.17.tar.bz2
[8] maxmod-nds-1.0.9.tar.bz2
[9] libfilesystem-0.9.12.tar.bz2
[10] default_arm7-0.6.0.tar.bz2
[11] nds-examples-20140401.tar.bz2

C'est fini, j'ai donc tous les fichiers ci-dessus dans "Téléchargements"

Retour dans un Terminal sous les privilèges de root.

Se déplacer dans le répertoire "Téléchargements" qui vient d'accueillir les fichiers qui ont été téléchargés.
cd Téléchargements
Il faut distribuer les fichiers au bon endroit :
sudo cp devkitARM_r45-x86_64-linux.tar.bz2 /opt/devkitpro
sudo cp libnds-1.5.12.tar.bz2 /opt/devkitpro/libnds
sudo cp libfat-nds-1.0.14.tar.bz2 /opt/devkitpro/libnds
sudo cp dswifi-0.3.17.tar.bz2 /opt/devkitpro/libnds
sudo cp maxmod-nds-1.0.9.tar.bz2 /opt/devkitpro/libnds
sudo cp libfilesystem-0.9.12.tar.bz2 /opt/devkitpro/libnds
sudo cp default_arm7-0.6.0.tar.bz2 /opt/devkitpro/libnds
sudo cp nds-examples-20140401.tar.bz2 /opt/devkitpro/examples
Les fichiers sont à décompresser :
cd /opt/devkitpro
sudo tar -xjf devkitARM_r45-x86_64-linux.tar.bz2
Petite vérification avec un "ls" , il doit y avoir un dossier devkitARM qui est arrivé.

Il faut poursuivre avec :
cd /opt/devkitpro/libnds
sudo tar -xjf libnds-1.5.12.tar.bz2
sudo tar -xjf libfat-nds-1.0.14.tar.bz2
sudo tar -xjf dswifi-0.3.17.tar.bz2
sudo tar -xjf maxmod-nds-1.0.9.tar.bz2
sudo tar -xjf libfilesystem-0.9.12.tar.bz2
sudo tar -xjf default_arm7-0.6.0.tar.bz2
Par chance il y a des exemples pour commencer à s'amuser.
cd /opt/devkitpro/examples
sudo tar -xjf nds-examples-20140401.tar.bz2
Histoire de conclure l'installation et toujours avec les privilèges de root.
sudo nano /home//.bashrc
A la fin du document il faut coller
export DEVKITPRO=/opt/devkitpro
export DEVKITARM=$DEVKITPRO/devkitARM
Et maintenant comment vous dire que c'est fini... tout simplement en faisant un test.

Petit redémarrage de l'ordinateur, on ne sais jamais.

Toujours dans un Terminal mais sans changer de privilège :
cd /opt/devkitpro/examples/hello_world
lancer un make pour créer le fichier
make
Si pour vous c'est ok, vous avez de la chance car de mon coté GRRRR ! c'est quoi ce message d'erreur ?
XXXXXXX@XXXXXXXXXXX:/opt/devkitpro/examples/nds/hello_world$ make
main.cpp
arm-eabi-g++ -MMD -MP -MF /opt/devkitpro/examples/nds/hello_world/build/main.d -g -Wall -O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -mthumb -mthumb-interwork -I/opt/devkitpro/examples/nds/hello_world/include -I/opt/devkitpro/examples/nds/hello_world/build -I/opt/devkitpro/libnds/include -I/opt/devkitpro/libnds/include -I/opt/devkitpro/examples/nds/hello_world/build -DARM9 -fno-rtti -fno-exceptions -c /opt/devkitpro/examples/nds/hello_world/source/main.cpp -o main.o
/opt/devkitpro/devkitARM/bin/arm-eabi-g++: 1: Syntax error: "(" unexpected
make[1]: *** [main.o] Error 2
make: *** [build] Error 2
XXXXXXX@XXXXXXXXXXX:/opt/devkitpro/examples/nds/hello_world$
Bon en cherchant sur la toile je suis tombé sur [12] qui semble expliquer, qu'il faut changer le fichier devkitARM.

J'ai téléchargé un nouveau devkitARM.

[4] devkitARM_r45-i686-linux.tar.bz2

Dans un Terminal c'est du déjà vue :
cd Téléchargements
sudo cp devkitARM_r45-i686-linux.tar.bz2 /opt/devkitpro
cd /opt/devkitpro
Il faut supprimer le répertoire devkitARM existant ainsi que ses sous répertoires et fichiers
sudo rm -Rf devkitARM
sudo tar -xjf devkitARM_r45-i686-linux.tar.bz2
Nouveau test
cd /opt/devkitpro/examples/hello_world
make
CA MARCHE

J'ai bien un fichier hello_world.nds ainsi qu'un dossier « build » qui a servi lors de la construction du fichier final.

L'émulateur

Un émulateur est une application servant à visualiser un jeu (de DS ou autre). Il vous servira beaucoup pour tester vos jeux, c'est plus pratique que de prendre chaque fois sa DS. Sauf que les émulateurs ne gèrent pas / gèrent mal les fichiers et le Wifi.

Sinon il faut avoir une connaissance qui à un ami qui à ...


Coté Raspberry Pi
Etape 2 - Préparation de la Raspberry

Laissons de coté les fichiers nds pour nous pencher sur la préparation de la Raspberry.

Ce tutoriel n'a pas pour objectif de vous faire un projet complet mais bien de vous présenter une méthode.

2-1 installation de A à Z :

1) formatage avec l'image 2015-02-16-raspbian-wheezy.img

2) dans raspi-config
- expand Filesystem
- enable camera -> enable
- advance option
- SSH -> enable
3) passage du clavier de qwerty en azerty
sudo nano /etc/default/keyboard
remplacement de gb par fr

4) redémarrage
sudo reboot
5) mise à jour
sudo apt-get update && sudo apt-get upgrade -y
Avec les cinq premières étapes vous avez une carte Raspberry en état de fonctionner mais pour notre projet il faut poursuivre avec la création d'une borne wifi. [14] et [15] mais j'ai changé les adresses ip en fonction de mon réseau,

6) paramétrage d'une adresse static
sudo nano /etc/network/interfaces
auto lo
 
iface lo inet loopback
iface eth0 inet static
address 192.168.0.65 #adresse de la carte raspberry en filaire
netmask 255.255.255.0
gateway 192.168.0.254 #adresse de la FreeBox
 
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.100.1 #adresse de la carte raspberry en wifi
netmask 255.255.255.0
7) nouvelle mise à jour
sudo apt-get update && sudo apt-get -y upgrade && sudo apt-get -y dist-upgrade && sudo apt-get -y autoremove
8) installation du serveur dhcp et de hostapd qui va créer le point wifi
sudo apt-get install hostapd isc-dhcp-server -y
9) modification du fichier dhcpd.conf
sudo nano /etc/dhcp/dhcpd.conf
Commenter les deux lignes suivantes :
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
donc elles deviennent
#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;
Toujours dans le même fichier dé-commenter la ligne
#authoritative;
après
authoritative;
et pour finir en fin de fichier coller ce qui suit :
subnet 192.168.100.0 netmask 255.255.255.0 {
range 192.168.100.10 192.168.100.50;
option broadcast-address 192.168.100.255;
option routers 192.168.100.1;
default-lease-time 600;
max-lease-time 7200;
};
La partie ci-dessus indique dans la première ligne « subnet » l'adrsse du serveur qui alloue les adresses IP. La deuxième lignes « range » indique la plage des adresses possible donc entre 192.168.100.10 et 192.168.100.50. les deux dernières lignes précisent le temps de réservation d'une adresse IP pour une machine.

9) indication du port utilisée pour la création du wifis
sudo nano /etc/default/isc-dhcp-server
Rechercher la ligne
INTERFACES=""
pour indiquer wlan0
INTERFACES="wlan0"
A ce stade le serveur dchp fonctionne, il faut maintenant créer la borne wifi

10) modification de hostapd.conf pour correspondre à nos besoins
sudo nano /etc/hostapd/hostapd.conf
ctrl_interface=/var/run/hostapd 
############################### 
# Basic Config 
############################### 
macaddr_acl=0 auth_algs=1 
# Most modern wireless drivers in the kernel need driver=nl80211 
driver=rtl871xdrv 
########################## 
# Local configuration... 
########################## 
interface=wlan0 
bridge=br0 
ssid=RaspberryPI_AP 
hw_mode=g 
ieee80211n=1 
channel=1 
auth_algs=1 
wmm_enabled=0
En ce qui me concerne j'avais un problème avec la ligne du driver qui sur une grande partie des tutos est driver=nl80211 alors que pour moi c'est driver=rtl871xdrv

11) indiquer à hostpad l'emplacement de son fichier de conf
sudo nano /etc/default/hostapd
Remplacer la ligne
#DAEMON_CONF=""
par
DAEMON_CONF="/etc/hostapd/hostapd.conf"
12) la même modification mais ailleurs
sudo nano /etc/init.d/hospapd
Remplacer également la ligne
#DAEMON_CONF=""
par
DAEMON_CONF="/etc/hostapd/hostapd.conf"
13) Préciser le type d'IP
sudo nano /etc/sysctl.conf
en fin de document coller :
net.ipv4.ip_forward=1
14)
sudo sh -c "echo 1>/proc/sys/net/ipv4/ip_forward"
15) mise à jour du driver pour accepter le « rtl871xdrv »
wget http://adafruit-download.s3.amazonaws.com/adafruit_hostapd_14128.zip
unzip adafruit_hostapd_14128.zip 
sudo mv /usr/sbin/hostapd /usr/sbin/hostapd.ORIG 
sudo mv hostapd /usr/sbin 
sudo chmod 755 /usr/sbin/hostapd
Lancer au démarrage du nano ordinateur les deux services
sudo update-rc.d hostapd enable
sudo update-rc.d isc-dhcp-server enable
Sur un smartphone, il doit y avoir un wifi libre (sans clé WEP ou WAP) au nom de RaspberryPI_AP quivient d'apparaître.

Une nintendo DS ne supporte pas le wap elle accepte uniquement le wep d'ou la création de cette borne sans sécurité.

Je sais que coté sécurité ce n'est pas bien, il faudra régler ça un jour...

2-2 premier test

Sur le PC, dans un Terminal se connecter en ssh à la Raspberry

Il faut (dans mon cas) ouvrir deux consoles terminal l'une à coté de l'autre afin d'avoir sur l'une la connexion en ssh avec la raspberry(terminal 1) et l'autre pour passer des commandes en local (terminal 2)

terminal 1 :
ssh pi@<192.168.0.65>
L'adresse IP est dans mon cas imposée par le point 6) ci-dessus et le mot de passe est raspberry si vous n'avez rien changé.

Création d'un dossier ninpi pour le projet

terminal 1 :
mkdir ninpi
terminal 1 :
cd ninpi
terminal 1 :
sudo nano /home/pi/ninpi/test_led.py
copier/coller le code

terminal 1 :
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Une LED branchée à la pin 18 clignote

import RPi.GPIO as GPIO  # bibliothèque pour utiliser les GPIO
import time              # bibliothèque pour gestion du temps

GPIO.setmode(GPIO.BCM)   # mode de numérotation des pins
GPIO.setup(18,GPIO.OUT)  # la pin 18 réglée en sortie (output)
GPIO.setup(23,GPIO.OUT)  # la pin 18 réglée en sortie (output)

while True:     # boucle répétée jusqu'à l'interruption du programme
    GPIO.output(18,GPIO.HIGH)   # sortie au niveau logique haut (3.3 V)
    GPIO.output(23,GPIO.LOW)    # sortie au niveau logique bas (0 V)
    time.sleep(1)               # on ne change rien pendant 1 seconde
    GPIO.output(18,GPIO.LOW)    # sortie au niveau logique bas (0 V)
    GPIO.output(23,GPIO.HIGH)    # sortie au niveau logique bas (0 V)
    time.sleep(1)               # on ne change rien pendant 1 seconde
Fermer et enregistrer Sur la Plaque d'essai il faut [16] placer la led et la résistance sur le GPIO18,

Toujours en SSH

terminal 1 :
sudo python /home/pi/ninpi/test_led.py
C'est l'habituel clignotement de led

Pour arrêter

terminal 1 -> ctrl+c

2-3 travail sur les sockets

Il est possible de demander à un programme de surveiller des ports afin que deux ordinateurs distants ou deux programmes sur une même machine puissent communiquer [17] et [18].

C'est exactement ce dont nous avons besoin.

Nouveau programme

terminal 1 :
sudo nano /home/pi/ninpi/test_socket.py
terminal 1 :
#!/usr/bin/env python

import socket
import sys

HOST = ''   # Symbolic name, meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket created'

#Bind socket to local host and port
try:
    s.bind((HOST, PORT))
except socket.error as msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print 'Socket bind complete'

#Start listening on socket
s.listen(10)

print 'Socket now listening'

#now keep talking with the client
while 1:
    #wait to accept a connection - blocking call
    conn, addr = s.accept()
    print 'Connected with ' + addr[0] + ':' + str(addr[1])

s.close()
Fermer et enregistrer

Toujours avec la raspberry en SSH

terminal 1 :
sudo python /home/pi/ninpi/server.py
Socket created
Socket bind complete
Socket now listening
Ouvrir un deuxième terminal sur le pc et placer les deux fenêtres de terminal l'une à coté de l'autre pour voir les échanges.

Changement de terminal

terminal 2 :
telnet <192.168.0.65> 8888
sur la fenêtre terminal SSH de la raspberry doit apparaître une nouvelle ligne.

terminal 1 :
sudo python /home/pi/ninpi/server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:47758
Attention il faut sortir proprement sinon il faudra changer le port d'écoute à chaque clôture du programme.

Pour sortir de telnet

terminal 2 : ctrl+altgr+]

terminal 2 -> ctrl+z

Puis

terminal 1 -> ctrl+c

2-2 utilisation des sockets et GPIO

Pour rendre plus attractif le projet j'ai rajouté une deuxième led avec sa résistance sur le GPIO 23 (borne 16)

Petite fusion des deux scripts python pour allumer l'une ou l'autre des leds en fonction des demandes. Le Programme ninpi.py va attendre quatre commandes possible via les lettres a,b,c ou d

terminal 1 :
sudo nano /home/pi/ninpi/ninpi.py
terminal 1 :
#!/usr/bin/env python
# coding: utf-8

import socket
import sys
import RPi.GPIO as GPIO  # bibliothèque pour utiliser les GPIO

HOST = ''   # Symbolic name, meaning all available interfaces
PORT = 5555 # Arbitrary non-privileged port

GPIO.setmode(GPIO.BCM)   # mode de numérotation des pins
GPIO.setup(18,GPIO.OUT)  # la pin 18 réglée en sortie (output)
GPIO.setup(23,GPIO.OUT)  # la pin 18 réglée en sortie (output)
GPIO.setwarnings(False)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'

#Bind socket to local host and port
try:
    s.bind((HOST, PORT))
except socket.error as msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print 'Socket bind complete'

#Start listening on socket
s.listen(10)
print 'Socket now listening'

while 1:
    #wait to accept a connection - blocking call
    conn, addr = s.accept()
    print 'Connected with ' + addr[0] + ':' + str(addr[1])
    while 1:
        #Receiving from client
        data = conn.recv(2048)
        print 'data '+data
        if data == "a":
            GPIO.output(23,GPIO.HIGH)   # sortie au niveau logique haut (3.3 V)
        elif data == "b":
            GPIO.output(23,GPIO.LOW)   # sortie au niveau logique haut (3.3 V)
        else:
            break
s.close()
GPIO.cleanup()
Je n'ai jamais réussi à faire clignoter les leds depuis un appel telnet car il y a l'encodage UTF-8 à respecter.

Il faut faut donc passer par un programme client.py

terminal 1 :
sudo nano /home/pi/ninpi/client.py
terminal 1 :
#!/usr/bin/env python
# coding: utf-8
 
import socket
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("", 8888))
 
file_name = raw_input(">> ") # utilisez raw_input() pour les anciennes versions python
s.send(file_name.encode())
Il faut passer les deux consoles terminal sur la raspberry

terminal 2 :
ssh pi@<162.168.0.65>
Encore le mot de passe raspberry

terminal 1 :
sudo python /home/pi/ninpi/ninpi.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:47758
terminal 2 :
sudo python /home/pi/ninpi/ninpi.py
Je vous laisse jouer et fermer les programmes.

Etape 3 – Test du Wifi avec les fichier nds

Il faut ramener le terminal 2 sur le pc.

terminal 2 :
exit
Pour faire communiquer le programme nds avec la raspberry, nous allons utiliser le wifi. Comme par hasard dans les exemples il y en a trois justement qui traite de cette partie.

terminal 2 :
cd /opt/devkitrpo/examples/dswifi/autoconnect
terminal 2 :
make
Là, encore une fois, si votre ami qui est illégal avec son linker a de la chance :
Simple Wifi Connection Demo

Connecting via WFC Data ...

Connected

ip     : xxx.xxx.xxx.xxx
gateway: xxx.xxx.xxx.xxx
mask   : xxx.xxx.xxx.xxx
dns1   : xxx.xxx.xxx.xxx
dns2   : xxx.xxx.xxx.xxx
Sinon
Simple Wifi Connection Demo

Connecting via WFC Data ...

Failed to connect!
Bon c'est vraiment un parcours du combattant cette histoire.

Nouvelle recherche sur le net avec les mots cléfs : WFC_connect devkitpro failed

Après une lecture d'une quinzaine de site, apparaît que le devkitpro ne supporte pas le chiffrement WPA. Son mode de sécurité est le WEP non le WPA.

Donc retour sur

terminal 2 :
cd /opt/devkitrpo/examples/dswifi/ap_search
terminal 2 :
make
Récupérer le fichier nds pour scanner les réseaux wifi qui sont a proximité

Etape 4 – Le projet NinPi global

Petit rappel de l'objectif de ce tutoriel : pouvoir faire clignoter une led sur la raspberry en fonction du bouton utilisé sur la Nintendo.

Création du répertoire ninpi pour accueillir les fichiers et dossier indispensable à la création du ninpi.nds

Dernière recherche sur le net concernant les sockets et le langage c [19]

terminal 2 :
sudo mkdir -p /opt/devkitrpo/ninpi
terminal 2 :
sudo mv /opt/devkitpro/examples/dswifi/httpget /opt/devkitrpo/ninpi
pour renommer le fichier

terminal 2 :
sudo mv /opt/devkitrpo/ninpi/source/httpget.c /opt/devkitrpo/ninpi/source/ninpi.c
terminal 2 :
sudo nano /opt/devkitrpo/ninpi/source/ninpi.c
Modifier le code comme suit :

terminal 2 :

#include 
#include 
#include 

#include 
#include 

#include 
#include 

#include 

//DECLARATION DE LA FONCTION QUI SERA UTILISEE APRES
//POUR EVITER UNE ERREUR DE COMPILATION
void getHttp(char* request, int my_socket);
    
//---------------------------------------------------------------------------------
Wifi_AccessPoint* findAP(void){
//---------------------------------------------------------------------------------
    int selected = 0;  
    int i;
    int count = 0, displaytop = 0;

    static Wifi_AccessPoint ap;

    Wifi_ScanMode(); //this allows us to search for APs

    int pressed = 0;
    do {
        scanKeys();

        //find out how many APs there are in the area
        count = Wifi_GetNumAP();


        consoleClear();

        iprintf("%d APs detected\n\n", count);

        int displayend = displaytop + 10;
        if (displayend > count) displayend = count;

        //display the APs to the user
        for(i = displaytop; i < displayend; i++) {
            Wifi_AccessPoint ap;

            Wifi_GetAPData(i, &ap);

            // display the name of the AP
            iprintf("%s %.29s\n  Wep:%s Sig:%i\n",
                i == selected ? "*" : " ",
                ap.ssid,
                ap.flags & WFLAG_APDATA_WEP ? "Yes " : "No ",
                ap.rssi * 100 / 0xD0);
        }

        pressed = keysDown();
        //move the selection asterick
        if(pressed & KEY_UP) {
            selected--;
            if(selected < 0) {
                selected = 0;
            }
            if(selected= count) {
                selected = count - 1;
            }
            displaytop = selected - 9;
            if (displaytop<0) displaytop = 0;
        }
        swiWaitForVBlank();
    } while(!(pressed & KEY_A));

    //user has made a choice so grab the ap and return it
    Wifi_GetAPData(selected, &ap);

    return ≈
}

//---------------------------------------------------------------------------------
void keyPressed(int c){
//---------------------------------------------------------------------------------
    if(c > 0) iprintf("%c",c);
}

//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
    Wifi_InitDefault(false);
    
    consoleDemoInit();

    Keyboard* kb = keyboardDemoInit();
    kb->OnKeyPressed = keyPressed;

    while(1) {
        int status = ASSOCSTATUS_DISCONNECTED;

        consoleClear();
        consoleSetWindow(NULL, 0,0,32,24);

        Wifi_AccessPoint* ap = findAP();

        consoleClear();
        consoleSetWindow(NULL, 0,0,32,24);

        iprintf("Connecting to %s\n", ap->ssid);

        //this tells the wifi lib to use dhcp for everything
        Wifi_SetIP(0,0,0,0,0);    
        char wepkey[64];
        int wepmode = WEPMODE_NONE;
        if (ap->flags & WFLAG_APDATA_WEP) {
            iprintf("Enter Wep Key\n");
            while (wepmode == WEPMODE_NONE) {
                scanf("%s",wepkey);
                if (strlen(wepkey)==13) {
                    wepmode = WEPMODE_128BIT;
                } else if (strlen(wepkey) == 5) {
                    wepmode = WEPMODE_40BIT;
                } else {
                    iprintf("Invalid key!\n");
                }
            }
            Wifi_ConnectAP(ap, wepmode, 0, (u8*)wepkey);
        } else {
            Wifi_ConnectAP(ap, WEPMODE_NONE, 0, 0);
        }
        consoleClear();
        while(status != ASSOCSTATUS_ASSOCIATED && status != ASSOCSTATUS_CANNOTCONNECT) {

            status = Wifi_AssocStatus();
            int len = strlen(ASSOCSTATUS_STRINGS[status]);
            iprintf("\x1b[0;0H\x1b[K");
            iprintf("\x1b[0;%dH%s", (32-len)/2,ASSOCSTATUS_STRINGS[status]);

            scanKeys();

            if(keysDown() & KEY_B) break;
            
            swiWaitForVBlank();
        }

        if(status == ASSOCSTATUS_ASSOCIATED) {
            u32 ip = Wifi_GetIP();
            //AFFICHAGE ADRESSE IP
            iprintf("\nip: [%i.%i.%i.%i]\n", (ip ) & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF);

    // Find the IP address of the server, with gethostbyname
    struct hostent * myhost = gethostbyname( "192.168.100.1" );
    iprintf("Found IP Address!\n");
 
    // Create a TCP socket
    int my_socket;
    my_socket = socket( AF_INET, SOCK_STREAM, 0 );
    iprintf("Created Socket!\n");

    // Tell the socket to connect to the IP address we found, on port 80 (HTTP)
    struct sockaddr_in sain;
    sain.sin_family = AF_INET;
    sain.sin_port = htons(5555);
    sain.sin_addr.s_addr= *( (unsigned long *)(myhost->h_addr_list[0]) );
    connect( my_socket,(struct sockaddr *)&sain, sizeof(sain) );
    iprintf("Connected to server!\n");

            while(1)
            {
                //TOUT VA BIEN, BOUCLE INFINI
                char * request;
                    
                scanKeys();
                int pressed = keysDown();
                // SI BOUTTON A
                if(pressed&KEY_A)
                {
                    getHttp("a",my_socket);
                }
                // SI BOUTTON B
                if(pressed&KEY_B)
                {
                    getHttp("b",my_socket);
                }
                if(pressed&KEY_X)
                {
                    getHttp("x",my_socket);
                }
                // SI BOUTTON B
                if(pressed&KEY_Y)
                {
                    getHttp("y",my_socket);
                }
                //RAFRAICHISSEMNT ECRAN
                consoleClear();
                swiWaitForVBlank();
            }
        } else {
            iprintf("\nConnection failed!\n");
        }
    }
        iprintf("Other side closed connection!");
        int my_socket;
        // good practice to shutdown the socket.
    shutdown(my_socket,0);
        
        // remove the socket.
    closesocket(my_socket);
    return 0;
}

//---------------------------------------------------------------------------------
void getHttp(char* request, int my_socket) {
//---------------------------------------------------------------------------------

    // send our request
    send( my_socket, request, strlen(request), 0 );
    iprintf("Sent our request : %c \n",request );

    // Print incoming data
    iprintf("Printing incoming data:\n");

   // int recvd_len;
   // char incoming_buffer[256];

    //while( ( recvd_len = recv( my_socket, incoming_buffer, 255, 0 ) ) != 0 ) { // if recv returns 0, the socket has been closed.
       // if(recvd_len>0) { // data was received!
     //       incoming_buffer[recvd_len] = 0; // null-terminate
       //     iprintf(incoming_buffer);
    //    }
    //}

}
terminal 2 :
cd /opt/devkitrpo/ninpi/
terminal 2 :
make
Récupérer le fichier ninpi.nds pour le mettre dans… l'émulateur !!!

Sur la raspberry

terminal 1 :
sudo nano /home/pi/ninpi/ninpi.py
terminal 1 :
#!/usr/bin/env python 
# coding: utf-8 
 
import socket 
import sys 
import RPi.GPIO as GPIO # bibliothèque pour utiliser les GPIO 
 
HOST = '' # Symbolic name, meaning all available interfaces 
PORT = 5555 # Arbitrary non-privileged port 
 
GPIO.setmode(GPIO.BCM) # mode de numérotation des pins 
GPIO.setup(18,GPIO.OUT) # la pin 18 réglée en sortie (output) 
GPIO.setup(23,GPIO.OUT) # la pin 18 réglée en sortie (output) 
GPIO.setwarnings(False) 
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
print 'Socket created' 
 
#Bind socket to local host and port 
try: 
   s.bind((HOST, PORT)) 
except socket.error as msg: 
   print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
   sys.exit() 
 
print 'Socket bind complete' 
 
#Start listening on socket 
s.listen(10) 
print 'Socket now listening' 
while 1: 
   #wait to accept a connection - blocking call 
   conn, addr = s.accept() 
   print 'Connected with ' + addr[0] + ':' + str(addr[1]) 
   while 1: 
      #Receiving from client 
      data = conn.recv(2048) 
      print 'data '+data 
      if data == "a": 
         GPIO.output(18,GPIO.HIGH) # sortie au niveau logique haut (3.3 V) 
      elif data == "b": 
         GPIO.output(18,GPIO.LOW) # sortie au niveau logique haut (3.3 V) 
      elif data == "x": 
         GPIO.output(23,GPIO.HIGH) # sortie au niveau logique haut (3.3 V) 
      elif data == "y": 
         GPIO.output(23,GPIO.LOW) # sortie au niveau logique haut (3.3 V) 
      else: 
         break 
      reply = 'OK pour ' + data 
      conn.sendall(reply) 
 
s.close() 
GPIO.cleanup()
terminal 1 :
sudo python /ninpi/ninpi.py
Conclusion :

Vous l'aurez compris, il n'y a pas une installation simplifiée et idéale. En vous indiquant mes déboires et mes questionnements, j'espère vous avoir guidé sur la piste de votre configuration.

Je vais donc maintenant ouvrir un projet de robot : le NinPiBot

Liens externes :
[1] https://openclassrooms.com/courses/programmez-sur-votre-nintendo-ds
[2] http://devkitpro.org/wiki/Getting_Started/devkitARM
[3] http://lea-linux.org/documentations/Trucs:Savoir_processeur_64_bits_ou_32_bits
[4] https://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r45/
[5] https://sourceforge.net/projects/devkitpro/files/libnds/1.5.12/
[6] https://sourceforge.net/projects/devkitpro/files/libfat/1.0.14/
[7] https://sourceforge.net/projects/devkitpro/files/dswifi/0.3.17/
[8] https://sourceforge.net/projects/devkitpro/files/maxmod/
[9] https://sourceforge.net/projects/devkitpro/files/filesystem/0.9.12/
[10] https://sourceforge.net/projects/devkitpro/files/default%20arm7/0.6.0/
[11] https://sourceforge.net/projects/devkitpro/files/examples/nds/
[12] https://devkitpro.org/viewtopic.php?f=2&t=2391
[13] http://blog.idleman.fr/tutoriel-02-brancher-et-installer-le-raspberry-pi/
[14] https://learn.adafruit.com/setting-up-a-raspberry-pi-as-a-wifi-access-point/install-software
[15] http://www.instructables.com/id/How-to-make-a-WiFi-Access-Point-out-of-a-Raspberry/
[16] http://www.geekland-leblog.fr/faire-clignote-une-led-en-python/
[17] http://apprendre-python.com/page-reseaux-sockets-python-port
[18] http://www.binarytides.com/python-socket-server-code-example/
[19] https://www.debian-fr.org/t/socket-en-c-client-serveur-tout-simple/3448