Il arrive, parfois, en cours de debug avec Delphi, de faire des évaluations avec CTRL+F7, du genre MonDataset.FieldByName('TOTO').AsString pour savoir sur quelles données on travaille. C'est facile, mais "un peu laborieux", surtout si le dataset en question contient beaucoup de données.
A regarder le problème de plus prêt, on remarque qu'il se pose à chaque fois que l'on a un objet "complexe", c'est à dire que sa classe est issue d'un lignée de dérivation plus ou moins longue.
En fait l'inspecteur d'objet de Delphi, n'est pas vraiment un inspecteur de TObject (il ne donne pas l'héritage ou la taille de la classe de l'instance). Il s'agit d'un inspecteur de TPersistent, c'est tout. Pas d'info concernant les données de TComponent, de TWinControl ou de n'importe quelle classe descendant de TPersistent.
Runtime Delphi Inspector est une librairie capable de me fournir un inspecteur d'objet à l'exécution. Cet inspecteur d'objet est personnalisable en fonction de la classe de l'objet à inspecter. Par exemple, l'inspecteur de TDataset contient un DBGrid capable d'afficher les données du TDataset à afficher. Une fenêtre d'inspecteur se compose de plusieurs onglets, associés à chaque niveau d'héritage.
Pour télécharger cette librairie : RtInspector
samedi 14 juin 2008
Delphi Runtime Inspector
mercredi 21 mai 2008
Le 68000 et les périphériques 6800.
Le 68000 représentait un changement majeur dans la gamme de processeur motorola. En effet un processeur 16 bits à 8 mhz, c'était largement plus rapide que le 6800, un processeur 8 bits, principal processeur de la marque. En effet il existait uniquement des versions à 1, 1.5 et 2 mhz. Il était doté d'une gamme de contrôleurs de périphériques variés comme le PIA 6821 (2 ports parallèles 8 bits) ou le ACIA 6850 (un port série). Les fréquences d'horloges maximums pour ces contrôleurs étaient alignés sur celles du 6800.
Les concepteurs du 68000 ont doté de la possibilité de se "ralentir" en générant un signal d'horloge qui dure 10 cycles d'horloge. L'objectif était de pouvoir utiliser les contrôleurs du 6800, soit pour une raison de coût, soit pour bénéficier dès la sortie du processeur de toute une gamme de contrôleurs.
De nombreux micro-ordinateurs grand public ont bénéficiés de cette caractéristique, comme le mac d'apple qui contenait un VIA 6522 ou l'atari ST qui avaient deux ACIA 6850.
De delphi à linux, programmation des timers
Le composant TTimer sous delphi est un composant capable de faire un appel régulier et répétitif à une procédure utilisateur.
Le délai entre les appels est réglable. Le principe de fonctionnement est simple : il s'agit de créer une fenêtre non visible, associée à une procédure de fenêtre (wndproc) capable de gérer le message WM_TIMER. En initialise les appels ensuite avec une api praticulière de windows. Le noyau Windows va,à partir de là, envoyer régulièrement un message WM_TIMER à cette fenêtre.
Ceci étant vu, je vais vous proposer maintenant de reproduire ce type de comportement sur linux.
Ce système peut quand à lui répondre à des signaux extérieur à l'application. Ces signaux peuvent être détournés par le programme vers une fonction de gestion. Si le programme ne le fait pas, le noyau tue l'application. C'est ainsi que fonctionne CTRL+C qui envoie à l'application courante un SIGINT, le signal d'arrêt du programme. Si le programme n'a pas de gestion particulière de ce signal, le noyau va effectivement stopper le programme. Si le programme gère ce signal, le programmeur devra prévoir une stratégie de sortie.
Revenons au timer. Il existe un signal SIGALRM qui est envoyé régulièrement par le noyau à une application. Ce signal sera envoyé sur demande de l'application. Bien entendu, comme tout signal, s'il n'est pas géré par l'application, il provoquera l'arrêt du programme. Si on le détourne vers une fonction, cette fonction sera appelée régulièrement.
Voici un exemple de source C sur l'utilisation des alarmes sous linux:
/*
=============================================================================
Name : timer.c
Author : OT
Description : Comment coder l'équivalent du TTimer de delphi en c sous linux ?
=============================================================================
*/
#include stdio.h>
#include stdlib.h>
#include signal.h>
#include sys/types.h>
#include unistd.h>
#include errno.h>
#include sys/wait.h>
void evenementTimer() {
printf("Top timer\n");
alarm(1);
}
int main(void) {
signal(SIGALRM, evenementTimer);
alarm(1);
// c'est mal de faire une attente active....
for (;;) {
}
}
Le bus I2C et la télévision
Dans un précédent article j'avais fait une brève présentation du bus I2C. Je vais vous présenter
maintenant quelques composants I2C utilisés en télévision. Il s'agit juste d'une liste très courte, le nombre de composants I2C est en effet très important.
Cela veut dire que toutes ces fonctions sont contrôlables par un microprocesseur ou par un pc.
STV942x : contrôleur OSD (incrustation vidéo)
TDA933x : processeur vidéo (contrôle de luminance et chrominance, balayage vertical 50,60,100 et 120 hertz, balayage horizontal)
SAA5243/45 : décodeur télétexte
SAA9055P : décodeur numérique SECAM
SAA9062/63/64 : contrôleur de déviation
SAB3035/36/37 : syntonisateur
SAA9068 : contrôle du PIP (picture in picture)
TDA8405 : contrôleur son stéréo
TDA8440 : commutateur audio / video
TDA8461 : Décodeur PAL/NTSC
jeudi 8 mai 2008
Google, webservices et cartographie
Google webservices et cartographie
L'api la plus connue de google maps est la librairie javascript qui permet de faire du mashup avec leurs cartes. Il existe toutefois d'autres possibilitées pour exploiter leurs données. On peut facilement géolocaliser une adresse postale et la convertir en coordonnées géographiques.
Une simple requete http GET suffit :
http://maps.google.com/maps/geo?q=2+rue+victor+hugo+26000+valence+fr&output=csv&key=placer ici votre clé google maps api
Le format de retour est un fichier csv d'une ligne et de 4 colonnes
La colonne 1 correspond à un code retour d'erreur ou de succès
| Code statut de la requète | Description |
| (200) G_GEO_SUCCESS | Aucune erreur ne s'est produite. L'adresse a été analysée avec succès et ses coordonnées GPS (Latitude, Longitude) ont été retournées. |
| (400) G_GEO_BAD_REQUEST | La demande n'a pu être analysée avec succès. |
| (500) G_GEO_SERVER_ERROR | La demande n'a pu être traitée avec succès. La raison exacte de l'échec est inconnue. |
| (601) G_GEO_MISSING_QUERY | Le paramètre "q" de la requète HTTP est manquant ou n'a aucune valeur. Pour les demandes de "géocodage", cela signifie qu'une adresse vide a été indiquée dans la requète. Pour les demandes de directions, cela signifie qu'aucune question n'a été indiquée dans la requète. |
| (601) G_GEO_MISSING_ADDRESS | Synonyme de G_GEO_MISSING_QUERY. |
| (602) G_GEO_UNKNOWN_ADDRESS | Aucun lieu géographique correspondant à l'adresse indiquée n'a pu être trouvé. Cela peut être dû au fait que l'adresse est relativement nouvelle, ou qu'elle est peut être incorrecte. |
| (603) G_GEO_UNAVAILABLE_ADDRESS | Les coordonnées GPS (Latitude, Longitude) pour l'adresse donnée ou l'itinéraire demandé n'ont pu être retournées pour des raisons légales ou contractuelles. |
| (604) G_GEO_UNKNOWN_DIRECTIONS | GDirections n'a pas pu calculer d'itinéraire entre les points mentionnés dans la requète. Soit parce qu'il n'y a aucun itinéraire disponible entre les deux points, soit parce que nous ne disposons pas des données couvrant cette région. |
| (610) G_GEO_BAD_KEY | La clef indiquée est invalide ou n'est pas attribuée au domaine pour lequel elle a été donnée. |
| (620) G_GEO_TOO_MANY_QUERIES | Le nombre de requètes, pour la clef donnée, a dépassé le quota des demandes autorisées pour une période de 24 heure. |
La deuxième est un code de précision (de 1 à 8)
Si vous faite une demande sur une ville, sans nom de rue vous aurez une valeur plus faible que si vous demander aussi une rue
| Code | Description |
| 0 | Localisation impossible. |
| 1 | Niveau d'exactitude : Pays. |
| 2 | Niveau d'exactitude : Région (état, province, préfecture, etc.). |
| 3 | Niveau d'exactitude : Région secondaire(comté, municipalité, etc.). |
| 4 | Niveau d'exactitude : Ville (ville, village). |
| 5 | Niveau d'exactitude : Code (code postal). |
| 6 | Niveau d'exactitude : Rue. |
| 7 | Niveau d'exactitude : Intersection. |
| 8 | Niveau d'exactitude : Adresse. |
La troisième est la latitude
La dernière est la longitude
Une variante permet de récupérer une fichier xml. Il suffit de changer csv par xml dans la requete. On a alors quelques informations complémentaires
comme la région et le département.
dimanche 4 mai 2008
Les processeurs coldfire
La famille des processeurs coldfire a été conçue par motorola. Il s'agit d'une puce de type risc dont le jeu d'instruction est inspirée du 68000. D'ailleur le tout premier coldfire etait compatible avec le 68040. Les coldfires suivant contenaient un jeu d'instruction simplifié par rapport à l'original.
Il existe de nombreuses variantes de ce processeur. Le 5407 contient des périphériques de base comme des ports parallèles, séries et I2C. D'autres versions plus avancées contiennent des périphériques PCI, USB, ethernet et bus CAN. On trouve aussi de nombreux outils libres comme gcc ou le Coldfire Emulator. On peut aussi faire fonctionner linux dessus.
uCLinux et Coldfire
Coldfire Emulator
Le bus I2C
Le bus I2C ( Inter Integrated Circuit ) a été inventé par Philips semiconductors pour simplifier l'interconnection de dispositifs électroniques controlés par un micro-controleur. Son usage initial était les domaines de l'électronique grand public comme la télévision, la vidéo ou le son.
Il s'agit d'un bus série, ce qui explique que la partie électrique est très simple, puisque que l'on a un signal d'horloge et un signal données/adresses. Le nombre d'adresses est 127 ce qui semble peu, mais reste suffisant pour la plupart des applications.
De nos jours ce bus est présent dans les pc pour le contrôle de carte TV par exemple (le tuner). On le trouve aussi dans de nombreux micro-contrôleurs.
Télécharger des objets
![]()
Après le téléchargement de fichiers numériques, voici comment télécharger des objets physiques. Non, il ne s'agit pas d'une forme avancée de site de vente, qui viendrait vous livrer en moins de 30 minutes, mais d'un projet de université de Cornell pour la réalisation d'une imprimante 3D. L'aspect intérressant c'est que tous les plans et schémas de réalisation sont téléchargeables sur leur site en "open source". La documentation et les exemples de réalisations sont fournis.
à voir
fab@home
dimanche 6 avril 2008
Tableau blanc sur linux
Johnny Chung Lee a présenté il y a quelques temps un système de tableau blanc constitué d'un PC, un vidéo projecteur et une wiimote. Il utilise simplement le capteur infrarouge de la wiimote pour détecter la position d'un crayon électronique basé sur une simple LED infrarouge. L'exemple de programme qu'il donne est écrit en c# sur windows. Depuis une version basée sur linux est apparue. Elle utilise les librairies bluez et python xlib.
Pour lancer le programme il suffit d'executer la commande python whiteboard.py.
L'utilisation est triviale, puisque l'on commence par calibrer en cliquant avec le crayon infrarouge aux quatres coins de l'écran projeté. Une fois cette opération faite, le crayon se comporte comme une souris.
Les sources se trouvent sur http://sourceforge.net/projects/wiiwhiteboard/
Il existe un portage en java : http://www.uweschmidt.org/wiimote-whiteboard
En cas de problème avec la pile bluetooth il faut la réinitialiser en lançant la commande /etc/init.d/bluetooth restart
jeudi 3 avril 2008
Programmation USB sous linux
La carte k8055 de velleman est une carte d'interface usb dotée de 8 sorties numériques (bufferisées par un ULN2803), de 5 entrées numériques, de 2 entrées analogiques et de 2 sorties analogiques basées sur un générateur PWM. Le microcontroleur qui régente tout ça est un PIC 16C745.
Il existe un programme de commande sous linux qui m'a permis d'aller explorer la programmation USB sur ce système. Ce programme se base sur la librairie libusb qui remonte au niveau utilisateur les fonctions de gestion USB.
Les sources sont suffisaments documentés pour comprendre facilement comment cela fonctionne.
Pour en savoir plus :
Confusions
Je constate que bien souvent, dans la presse ou sur internet, la notion d'urbanisation s'accompagne de tout un tas de sigles du style SOA, BPM, BPEL, bus logiciels, webservices, business intelligence, etc....en fait représentant des technologies ou des notions purement liés à l'informatique. C'est oublier un peu vite, me semble t-il qu'un bon projet d'urbanisation doit commencer par décrire le métier pour lequel l'informaticien travaille. Quand je dis métier, ce n'est pas encore les spécifications fonctionnelles, mais bien le métier, c'est à dire ce que les autres gens font de leur journées pour gagner leur vie. Dans cet univers là, l'ordinateur n'existe pas, ce qui, j'en conviens peut paraitre suréaliste pour l'informaticien lambda.
Au départ il s'agit simplement de décrire le système d'information, c'est à dire quelles sont les informations manipulés par les gens du métier. Cela ne veut pas dire que toutes ces informations vont se retrouver dans un ordinateur. Il va falloir faire des choix en fonction de la faisabilité ou du coût (ou des deux).
C'est ensuite que l'on commence à parler de spécifications fonctionnelles, lorsque justement on sait ce qui va être informatisé ou sur ce qui l'est déjà. Quand j'emploi le futur, c'est aussi parce que dans le monde réel, les gens ont des projets, une entreprise peut faire des choix stratégiques. Il est important aussi de penser à cela, à l'évolution du métier.
Ce n'est qu'après cela que l'on peut commencer à se poser des questions liés au système informatique.
Les spécifications fonctionnelles ne doivent normalement contenir aucune notion d'informatique, ce n'est pas encore le moment. Ce n'est qu'une partie de la description du métier.
La notion de système informatique apparait vaguement avec
Embarquer
Non, ce billet ne concerne pas l'informatique embarqué, mais la sérieuse tendance de java à embarquer d'autres langages. Depuis la spec JSR223, l'univers des interpréteurs embarqués dans Java explose. En peut en effet faire fonctionner du javascript, groovy, php, python, ruby et donc aussi les frameworks qui vont avec, ce qui permet de voir la naissance de projets comme JRuby On Rail. Mais quel est donc l'intérêt de faire ceci ? Tous d'abord cela permet de bénéficier de la jvm et de la longue expérience d'optimisation et de compilation à la volée accumulée depuis 10 ans. Mais surtout cela permet de faciliter les phases d'intégration, voir d'urbanisation autour d'applications implémentées avec des langages différents. J2EE sait très bien faire. On peut par exemple ainsi avoir des sites commerciaux en php relié a des ERP écrit en java.
Tous cela ouvre des perspectives...
lundi 3 mars 2008
SIMCAD
Au début des années 90, la revue elektor a publié le schéma d'une carte à base de 80c31 facile à construire (CI simple face), destinée à faire de l'expérimentation. Elle était équipée d'une RAM de 32ko et d'une EPROM de 32ko contenant un minuscule moniteur permettant de connecter la carte à un PC via un port série.
La carte peut faire fonctionner le 8052AH Basic. Elle peut aussi programmer une eprom.
Le soft livré comprenait un assembleur et un soft de transfert. Tout est écrit en turbo pascal. J'ai pu le recompiler avec freepascal sous linux sans trop de modifications. La plus grosse partie des modifs concerne le port série et quelques unes sur le soft d'assemblage. En tout cas ma carte fonctionne toujours aussi bien après avoir pris la poussière pendant quelques années.
mardi 26 février 2008
L'ERP opensource vu par Apache
Les projets de la fondation Apache ont ceci de particulier que leur licence permet une grande permissivité et une grande possibilité d'intégration dans d'autre projets. Il existe un projet particulièrement intérressant qui est OfBiz. Il s'agit d'une librairie destinée à la réalisation de logiciels de gestion et de site de e-commerce. Elle a permis le lancement de nombreux projets d'ERP opens-source comme Neogia ou OpenTabs.
à voir :
OFBiz
OpenTabs
Neogia
Hello BCEL
Voici un autre exemple de programme autour de BCEL. Il s'agit d'un générateur de classe "Hello World". Ce programme instancie et appel ensuite la méthode qui va bien pour afficher le message "Hello World"
import org.apache.bcel.generic.*;
import org.apache.bcel.*;
import java.io.*;
public class FabriqueDeClasseHelloWorld implements Constants {
private InstructionFactory fabriquePourInstructions;
private ConstantPoolGen listeDesConstantesDeLaNouvelleClasse;
private ClassGen classeAConstruire;
// nom de la nouvelle classe à créer
static private String classNameTarget() {
return "HelloWorld3";
}
public FabriqueDeClasseHelloWorld() {
classeAConstruire = new ClassGen(classNameTarget(), "java.lang.Object",
classNameTarget()+".java", ACC_PUBLIC | ACC_SUPER, new String[] {});
listeDesConstantesDeLaNouvelleClasse = classeAConstruire
.getConstantPool();
fabriquePourInstructions = new InstructionFactory(classeAConstruire,
listeDesConstantesDeLaNouvelleClasse);
}
public void create(OutputStream out) throws IOException {
creationDuConstructeur();
creationMethodeMain();
classeAConstruire.getJavaClass().dump(out);
}
private void creationDuConstructeur() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS,
new String[] {}, "", classNameTarget(), il,
listeDesConstantesDeLaNouvelleClasse);
InstructionHandle ih_0 = il.append(fabriquePourInstructions.createLoad(Type.OBJECT, 0));
System.out.println(ih_0.getInstruction().getName());
InstructionHandle ins2 = il.append(fabriquePourInstructions.createInvoke(
"java.lang.Object", "", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
System.out.println(ins2.getInstruction().getName());
InstructionHandle ih_4 = il.append(fabriquePourInstructions.createReturn(Type.VOID));
System.out.println(ih_4.getInstruction().getName());
method.setMaxStack();
method.setMaxLocals();
classeAConstruire.addMethod(method.getMethod());
il.dispose();
}
private void creationMethodeMain() {
System.out.println("\nListe des instructions de la méthode main");
InstructionList il = new InstructionList();
// on rajoute une méthode main sans paramètre
MethodGen method = new MethodGen(ACC_PUBLIC | ACC_STATIC, Type.VOID,
Type.NO_ARGS, new String[] {}, "main", classNameTarget(), il,
listeDesConstantesDeLaNouvelleClasse);
InstructionHandle ins1 = il.append(fabriquePourInstructions.createFieldAccess(
"java.lang.System", "err",
new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
System.out.println(ins1.getInstruction().getName());
InstructionHandle ins2 = il.append(new PUSH(
listeDesConstantesDeLaNouvelleClasse,
"Hello world sur la sortie erreur!"));
System.out.println(ins2.getInstruction().getName());
InstructionHandle ins3 = il.append(fabriquePourInstructions.createInvoke(
"java.io.PrintStream", "println", Type.VOID,
new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
System.out.println(ins3.getInstruction().getName());
InstructionHandle ins4 = il.append(fabriquePourInstructions.createReturn(Type.VOID));
System.out.println(ins4.getInstruction().getName());
method.setMaxStack();
method.setMaxLocals();
// on rajoute la nouvelle méthode à la classe
classeAConstruire.addMethod(method.getMethod());
il.dispose();
}
public static void main(String[] args) throws Exception {
FabriqueDeClasseHelloWorld creator = new FabriqueDeClasseHelloWorld();
// on doit avoir un répertoire build ou se trouve les .class fabriqués
creator.create(new FileOutputStream("build/" + classNameTarget()
+ ".class"));
/*
* attention, pour que cette partie fonctionne il faut que le répertoire
* build se trouve dans le classpath
*/
// on récupère la classe que l'on vient de créer
Class cls = Class.forName(classNameTarget());
// on fait une instance de cette classe
Object obj = cls.newInstance();
// l'unique méthode est le main. On fait un appel sur ce main
obj.getClass().getMethods()[0].invoke(obj);
}
}
lundi 25 février 2008
Hello Spring
Hello World Spring
Le framework Spring implémente le design pattern IoC (inversion de contrôle). Le petit exemple qui va suivre a pour but de donner un petit exemple simple d'utilisation de cette API.
Tout d'abord on souhaite réaliser une application qui affiche "Hello World". On souhaite que cette application soit le plus paramétrable possible. En fait elle doit permettre d'afficher "Hello World" sur une sortie quelconque.
Il s'agit donc de rendre la sortie générique.
La première implémentation se ferait à l'aide de deux classes :
Pour commencer, la classe application
package net.olivier_thebault;
import net.olivier_thebault.screen.Screen;
public class HelloWorld {
public Screen scr=new Screen();
public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorld();
helloWorld.scr.show("Hello world !!!");
}
}
puis une classe d'affichage :
package net.olivier_thebault.screen;
public class Screen {
public void show(String text){
System.out.println(text);
}
}
Dans cet exemple, la classe application ne connait pas la méthode d'affichage, elle sait juste qu'il existe une classe Screen. Le problème est si l'on souhaite modifier la sortie, on doit créer une nouvelle classe d'affichage, NewScreen par exemple et modifier le programme principal en conséquence. Dans un cas simple, comme celui-ci, cela n'est pas très difficile, mais imaginons simplement, que l'on est plusieurs instances de Screen, donc plusieurs appels à new Screen(), la modification du programme serait alors beaucoup plus longue et accidentogène.
En plus ce ça il faudrait recompiler l'application.
Je vais alors faire une petite modification pour mieux séparer l'affichage du programme : rajouter une interface. En fait il s'agit d'établir un contrat entre la classe principale et la classe d'affichage. Cela aura pour avantage d'externaliser la liaison entre les deux classes
On obtient alors ceci pour l'interface :
package net.olivier_thebault;
public interface IScreen {
public abstract void show(String text);
}
et ceci pour les deux autres classes :
package net.olivier_thebault;
import net.olivier_thebault.screen.Screen;
public class HelloWorld {
public IScreen scr=new Screen();
public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorld();
helloWorld.scr.show("Hello world !!!");
}
}
package net.olivier_thebault.screen;
import net.olivier_thebault.IScreen;
public class Screen implements IScreen {
/* (non-Javadoc)
* @see net.olivier_thebault.screen.IScreen#show(java.lang.String)
*/
public void show(String text){
System.out.println(text);
}
}
Cela va nous permettre d'externaliser complétement la référence à la classe Screen, en introduisant une nouvelle classe. Pour commencer le champ "scr" va être initialisé par le constructeur
package net.olivier_thebault;
public class HelloWorld {
public IScreen scr;
public void hello(){
scr.show("Hello world !!!");
}
public HelloWorld(IScreen scr){
this.scr = scr;
}
}
De fait il n'existe plus aucune référence au constructeur et à la classe Screen. De plus cette classe ne sera plus la classe principale du programme, elle perd sa méthode main au profit d'une méthode Hello
La classe principale sera désormais :
package net.olivier_thebault;
import net.olivier_thebault.screen.Screen;
public class HelloMain {
public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorld(new Screen());
helloWorld.hello();
}
}
D'accord, tout ce qui est fait pour le moment est de déplacer le problème vers une nouvelle classe, ce qui a tendance à complexifier la solution, qui en plus est partielle. Il est donc temps d'améliorer et simplifier tout ça. C'est à que Spring peut rendre les choses plus confortable. Pour commencer il faut créer un fichier de configuration dont le rôle est de préciser quel est l'instance à passer à HelloWorld au moment de sa construction.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="Hello" class="net.olivier_thebault.HelloWorld">
<constructor-arg>
<bean class="net.olivier_thebault.screen.Screen" />
</constructor-arg>
</bean>
</beans>
L'important ici se situe dans la balise bean. Id précise le nom que spring va donner à la classe. Ce nom va servir ensuite au moment de l'appel au constructeur. On précise ensuite, grace à la balise "constructor-arg" la classe implémentant l'interface IScreen. Spring va automatiquement créer l'instance qui va bien. C'est ici que l'on trouve le seul lien entre l'application et la classe d'affichage. Ce qui veut dire que l'on peut modifier l'application uniquement par paramétrage sans recompiler.
Le programme principal devient alors ceci :
package net.olivier_thebault;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
public class HelloSpring {
public static void main(String[] args) {
// on récupère le fichier de configuration
Resource is = new FileSystemResource("config.xml");
// à partir du fichier de config on récupère une factory qui va permettre de construire
// les beans.
BeanFactory factory = new XmlBeanFactory(is);
// Le constructeur passe par spring
HelloWorld hello=(HelloWorld)factory.getBean("Hello");
hello.hello();
}
}
Voici donc un petit exemple d'Ioc via Spring. Spring permet de faire beaucoup plus de choses, de gérer les singletons, les transactions ou de créer des applications selon le modèle MVC. Il peut aussi s'interfacer avec struts ou hibernate.
dimanche 10 février 2008
le module PIC-WEB

La société olimex commercialise un petit nano serveur web expérimental basé sur le micro-contrôleur PIC 18F452 de Microchip. Ce module comprend une interface Ethernet 10Mbit construit autour d'un ENC28J60, un port RS232 pour le paramétrage, un port ICSP pour la programmation, un bouton poussoir utilisateur, une résistance ajustable pour une entrée analogique, une thermistance et un port d'extension comprenant quelques connections au microcontroleur. L'alimentation peut se faire en continu ou alternatif. La carte contient un pont de graetz, un régulateur 5V et 3.3V.
Coté logiciel une petit démo est embarqué, l'adresse IP par défaut est 192.168.0.30. Le port RS232 est paramétré à 19200 bps, 8 bits de données, pas de parité, 1 bit de stop, contrôle de flux matériel. Pour accéder au menu de paramétrage, il faut tenir enfoncé le poussoir utilisateur tout en déclenchant un reset. On peut alors changer l'adresse IP, se baser sur un DHCP, télécharger des pages via xmodem. On peut aussi télécharger ces pages via FTP. La page de démo du serveur HTTP est un simple contrôle d'une des leds de la carte et d'une broche du microcontroleur. Il permet aussi de
lire la température ambiante et de voir la valeur de réglage de la résistance ajustable.
Bien entendu on peut très bien refaire tout le logiciel embarqué, et reprogrammer la carte selon ses besoins. L'interface ICSP permet de la faire à l'aide du logiciel de microchip MPLAB. La programmation peut se faire en assembleur ou en C avec le compilateur MCC18. Toute la partie logiciel de cette carte utilise la pile TCP/IP fourni par le constructeur du PIC.
dimanche 3 février 2008
BCEL
BCEL est une librairie java qui fait partie du projet apache. Cette librairie permet de manipuler, modifier des classes java ou créer des classes jva compilés (.class). On pourrait très bien à partir de cette librairie créer un compilateur pour une jvm ou rajouter un mécanisme de persistance à la volée à des pojos qui n'en possèdent pas.
Voici un petit exemple simple qui montre comment rajouter une méthode sur une classe :
import org.apache.bcel.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
/**
* Cette classe est capable de s'automodifier Elle implémente l'interface
* Constants qui contient toutes les constantes nécessaire à bcel, y compris les
* instructions assembleurs de la jvm
*
* @author olivier THEBAULT
*
*/
public class ClassModifier implements Constants {
private JavaClass clazz;
private ClassGen classGen;
private ConstantPoolGen cp;
/**
* Constructeur
*
* @param clazz
* le nom de la classe à modifier
* @throws ClassNotFoundException
*/
public ClassModifier(String clazz) throws ClassNotFoundException {
this.clazz = Repository.lookupClass(clazz);
this.classGen = new ClassGen(this.clazz);
this.cp = this.classGen.getConstantPool();
}
/**
* main de test - la classe à modifier est ClassModifier
*
* @param args
*/
public static void main(String args[]) {
ClassModifier modifier;
try {
modifier = new ClassModifier("ClassModifier");
modifier.start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void start() {
if (this.clazz != null) {
// on liste les méthodes de la classe avant d'en ajouter une
Method[] methods = classGen.getJavaClass().getMethods();
System.out.println("*** Avant d'ajouter une méthode ***");
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
// la méthode à rajouter devra comporter une liste d'instructions
// dans le cas présent, cette liste est vide
InstructionList il = new InstructionList();
// on construit la nouvelle méthode, elle est publique et statique
MethodGen laMethodeARajouter = new MethodGen(ACC_PUBLIC
| ACC_STATIC,
Type.VOID, // elle retourne void
Type.NO_ARGS, // elle n'a pas de paramètres
new String[] {}, // Sa liste de nom de paramètres est de
// fait vide
"nouvelleMethode", // elle s'appelle "nouvelleMethode"
clazz.getClassName(),// c'est une méthode de la classe "clazz"
il, // sa liste d'instructions est il
cp);
// on ajoute la méthode "nouvelleMethode" à la classe
classGen.addMethod(laMethodeARajouter.getMethod());
// on liste les méthodes après en avoir ajouté une
methods = classGen.getJavaClass().getMethods();
System.out.println("\n*** Liste des méthodes après ajout ***\n");
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
} else
throw new RuntimeException("Class file is null!");
}
}
Pour en savoir plus : BCEL
dimanche 27 janvier 2008
Web 3.0

Juste pour rire, peut-être que ce sera la nouvelle désignation marketing pour ce genre de technologie ayant trait au web, je veux parler des nano serveurs.
De quoi s'agit-il ?
En fait l'objectif est d'embarquer dans un objet quelconque un serveur web complet, pour faire de la gestion d'automatisme par exemple. Cela peut aussi servir à créer des objets pour geek.
On peut trouver sur le web de nombreuses expérimentations là dessus. Les techno employés sont souvent à base de micro-controleur PIC car la société Microchip a publié les sources d'une pile IP pour ses processeurs.
Les plus élaborés contiennent une connection ethernet, les plus simple une liaison SLIP sur RS232 comme le webACE
Un autre, simple à cabler est le wwwpic2. Il est basé sur un PIC16F84.
On trouve aussi des variantes dotés d'un port ISA pour connecter une carte ethernet ou des cartes à base d'autres microcontroleurs.
Le système dans tout ça....surement pas de système multi-tâche 32 bits. Les processeurs PIC sont des processeurs 8 bits, le nano serveur historique était basé sur un 12C509, qui est un 8 bits à 4 mhz doté d'une mémoire programme de 1k mot....
Les langages de programmation utilisés sont souvent l'assembleur, parfois le C. Il esiste même une version version qui fonctionne sur une javacard
On trouve aussi des produits commerciaux comme la carte picoweb
Afficher la pile d'appel
Il est très informatif d'avoir en cas de problème la pile d'appel lié à une exception. En java elle est particulièrement détaillée et permet de repérer rapidement la source du bug. Par contre il est tout aussi interressant de l'avoir en cas de fonctionnement normal, pour savoir par exemple quel est l'origine d'un appel à une méthode qui est appelée par un grand nombre d'autres méthodes. Vous allez me dire, qu'il suffit de poser un point d'arrêt et le tour est joué....sauf que cela n'est pas toujours possible.
Voici une technique pour s'en passer. Elle se base sur le fait que la classe "Exception" a pour ancêtre "Throwable" qui n'est pas encore une exception, mais qui a le mérite de fournir toutes les informations nécessaires concernant la pile d'appel.
Voici un exemple simple :
public class Pile {
private static void appel2(){
Throwable th=new Throwable();
th.printStackTrace();
}
private static void appel1(){
appel2();
}
public static void main(String[] args) {
appel1();
}
}
qui retourne comme résultat :
java.lang.Throwable
at Pile.appel2(Pile.java:5)
at Pile.appel1(Pile.java:10)
at Pile.main(Pile.java:14)
La méthode "printStackTrace()" est un affichage préformaté sur la console des informations de la pile d'appel. On peut bien sur récupérer auprès de l'objet "th" toutes les informations séparément.
CreateProcess en delphi
Le lancement d'un processus à partir d'une application delphi s'appuie sur l'api windows CreateProcess. En dehors de ça rien ne particulier, Delphi sait très bien gérer ce genre d'appel.
procedure Exec(exe : String);
var
StartInfo : TStartupInfo;
ProcInfo : TProcessInformation;
CreateOK : Boolean;
begin
FillChar(StartInfo,SizeOf(TStartupInfo),#0);
FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
StartInfo.cb := SizeOf(TStartupInfo);
CreateOK := CreateProcess(PChar(exe),nil, nil, nil,False,
CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
nil, nil, StartInfo, ProcInfo);
end;
Create process en c#
Pour changer je vais faire une petite série "hello world" concernant uniquement le lancement de processus. Le premier de la série sera sous windows avec c#. Rien de bien magique, le framework dotnet fourni une classe "Process" qui permet de faire facilement ce genre d'opération.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void exec(string exe)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = exe;
proc.Start();
}
static void Main(string[] args)
{
exec("calc");
}
}
}
Un singleton en Delphi
Le source suivant présente comment réaliser un objet singleton en Delphi. Lorsque l'on appel le constructeur d'un objet, le compilateur fait un appel à NewInstance pour récupérer un pointeur sur l'objet instancié. Dans le cas présent au premier appel on fait effectivement cet appel. Dans les cas suivant on retourne toujours la même instance.
unit uSingleton;
interface
type
TSingleton=class
public
class function NewInstance: TObject; override;
end;
implementation
var
fSingleton:TSingleton;
{ TSingleton }
class function TSingleton.NewInstance: TObject;
begin
if assigned(fSingleton) then
result:=fSingleton
else
begin
result:=inherited NewInstance;
fSingleton:=TSingleton(result);
end;
end;
end.
Phonétisation en java
Phonétisation en java
Les techniques de phonétisation sont nombreuses et posent de nombreux problèmes liés
aux différentes langues humaines. Les applications sont, quand à elles bien connues.
On peut citer la recherche documentaire, la synthèse vocale ou les applications d'analyse
de langage naturel.
Il existe, entre autre, trois algorithmes courant pour la phonétisation : le soundex,
le métaphone et le double métaphone. Le soundex est plutôt spécialisé pour l'anglais et
est issue de brevet déposés en 1918 et 1922.
Le métaphone a été conçue pour répondre aux limitations du soundex. Le double métaphone
est un perfectionnement du métaphone. Il est capable de travailler avec les langues slaves,
germaniques, celtiques, grec, français, Italien, espagnol et chinois entre autres.
Il existe une implémentation des ces algorithmes en java dans la librairie Apache commons.
Elle fait aussi partie du sdk Google Androïd.
Voici un petit exemple de programme java utilisant cette librairie. On se rend bien compte
que le résultat est encore approximatif. En effet il trouve que "bière" et "beer" se prononce
à peu près pareil, mais pas "fin" et "faim".
import org.apache.commons.codec.language.DoubleMetaphone;
public class Codec1 {
public static void main(String[] args) {
DoubleMetaphone dm=new DoubleMetaphone();
System.out.println(dm.doubleMetaphone("bière"));
System.out.println(dm.doubleMetaphone("beer"));
System.out.println(dm.doubleMetaphone("faim",false));
System.out.println(dm.doubleMetaphone("fin",false));
}
}
jeudi 24 janvier 2008
Hello World Ant
c'est pas le premier avril, mais j'ai pas pu résister à présenter ce script fort complexe, c'est pour ant et cela affiche "Hello World"....
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello World" default="hello" basedir=".">
<target name="hello">
<echo message="Hello World !" />
</target>
</project>
jeudi 17 janvier 2008
Faites vos lampes triodes vous-même
Je suis tombé sur ce site par hazard et c'est le travail d'un très bon bricoleur. Un radio am qui se fabrique ses propres tubes.
Il présente une petite vidéo de 17minutes concernant sa fabrication.
F2FO
Vraiment impressionnant !
mardi 15 janvier 2008
Hello world OpenGL
Voici un petit programme pour linux qui montre comment dessiner la théière de l'Utah. Il est remarquable de constater que de nombreuses API 3D ou applications de dessin 3D ont une primitive capable de dessiner cet objet de référence.
Pour linux il faut au préalable avoir installé la librairie glut.
Le source est très simple :
#include
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
// on dessine une théière
glutWireTeapot(0.5);
}
int main(int argc, char** argv)
{
// initialisation
glutInit(&argc,argv);
// Initialisation de l'affichage et de la fenêtre
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(0,0);
// définition du titre
glutCreateWindow("théière");
// la procédure d'affichage sera appelée en callback
glutDisplayFunc(display);
// on attend la fin
glutMainLoop();}
pour la compilation il faut lancer la ligne suivante :
gcc -o teapot teapot.c -lglut -lGLU -lGL -lXmu -lXi -lXext -lX11 -lm
lundi 14 janvier 2008
Le protocole IP et la couche physique
Le protocole IP en tant que couche réseau ne définie pas de couche physique. En fait il est conçue pour pouvoir être monté sur toutes sorte de couches physiques : réseaux ethernet, modem, ATM, etc....
Il est alors tout à fait possible d'implémenter IP sur une couche physique composé de pigeons voyageurs, comme l'expose le RFC 1149.
Une implémentation de ce genre de réseau existe : http://www.blug.linux.no/rfc1149/ Les sources sont fournis.
dimanche 13 janvier 2008
wiimote
La console Nitendo Wii introduit une nouvelle forme d'interface homme/machine. Ce qui est très intérressant avec cette console est que sa manette, la wiimote, est dotée d'une interface Bluetooth, ce qui a permis à de nombreux développeurs d'expérimenter autour de cette technologie.
On peut par exemple visiter ce site, WiinRemote, qui explique comment connecter sa wiimote à un pc windows et développer des applications avec Delphi.
Une application originale est de transformer un habituel tableau blanc en tablette électronique.
Je ne sais pas si cela vous est arrivé au cours d'une réunion d'avoir fait un joli schéma sur un tableau blanc, mais cela est souvent dommage d'avoir à reprendre à la main le résultat d'une réflexion. Avec le projet wiiwhiteboard, on peut espérer pouvoir conserver ce genre de document, voir via un menu intégré, l'archiver, le lier à un agenda ou l'envoyer par mail.
Avoir aussi :
http://www.wiili.org/index.php/How_To:_BlueSoleil
http://www.cs.cmu.edu/~johnny/projects/wii/
Les exemples de code fournis sont en C# ou en delphi.
Le "hello world" de wiiwhiteboard :

