dimanche 25 septembre 2011

Matériel : Augmenter la portée réception du RFXCOM

     Problème avec mon RFXCOM ethernet, mes murs sont ferraillés tous les 10cm, ce qui brouille les transmissions radio. Certaines sondes OREGON ne sont donc pas "visibles".

J'ai donc décidé d'augmenter la portée en achetant une antenne complémentaire que j'accrocherai par la suite sur le mur extérieur (En attendant, elle reste près du tableau éléctrique).


Antenne 433mhz (achetée chez BricoTruc 30 euros) + un adaptateur RCA vers BNC.









Et le résultat est meilleur, je capte maintenant toutes les sondes OREGON, reste à faire des tests de portée.

mardi 30 août 2011

Ajax, Struts2 et JSP





Notre page de paramètres est prête, sauf que le look'n feel n'est pas au rendez-vous. L'idée étant d'avoir un tableau (joli) qui permet de filtrer, ajouter, trier des enregistrements de manière simple.


En cherchant un peu, voici sur quoi je suis tombé : 


http://code.google.com/p/struts2-jquery/wiki/EditGrid#Simple_Edit

Plugin JQuery (Ajax) compatible Struts2, et plus particulièrement cette EditGrid qui fait tout toute seule (enfin presque).


Mise en place : 


 1) Tout d'abord, il faut tirer avec Maven la dépendance sur ce Plugin, direction fichier pom :


<dependency>
<groupId>com.jgeppert.struts2.jquery</groupId>
<artifactId>struts2-jquery-grid-plugin</artifactId>
<version>3.1.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>


 2) Import dans le Head des JSP des tags nécessaires au chargement de JQuery et de ce plugin.


<sj:head locale="fr" jqueryui="true" defaultIndicator="myDefaultIndicator" jquerytheme="ui-darkness"/>



3) Ajout du composant Grid dans la JSP de base appelée parameter.jsp soumise sur parameterAction


   <s:url id="remoteurl" action="parameterJQueryAction"/>
    <s:url id="editurl" action="parameterEditAction"/>
    <sjg:grid
    id="gridedittable"
   
    dataType="json"
    href="%{remoteurl}"
    pager="true"
    navigator="true"
   
    navigatorSearchOptions="{sopt:['eq','ne','lt','gt']}"
    navigatorAddOptions="{height:200,width:400,reloadAfterSubmit:true}"
    navigatorEditOptions="{height:200,width:400,reloadAfterSubmit:false}"
    navigatorEdit="false"
    navigatorView="false"
    navigatorDelete="true"
    navigatorDeleteOptions="{height:200,width:400,reloadAfterSubmit:true}"
    navigatorExtraButtons="{
    seperator: { 
    title : 'seperator'  
    }, 
    hide : { 
    title : 'Show/Hide', 
    icon: 'ui-icon-wrench', 
    topic: 'showcolumns'
    },
    alert : { 
    title : 'Alert', 
    onclick: function(){ alert('Grid Button clicked!') }
    }
    }"
    gridModel="gridModel"
    rowList="10,15,20"
    rowNum="10"
    editurl="%{editurl}"
    editinline="true"
    onSelectRowTopics="rowselect"
    onEditInlineSuccessTopics="oneditsuccess"
    viewrecords="true"
    >
    <sjg:gridColumn name="id" index="id" title="ID" width="30" formatter="integer" editable="false" sortable="false" search="true" searchoptions="{sopt:['eq','ne','lt','gt']}"/>
    <sjg:gridColumn name="cle" index="cle" title="Cle" width="250" editable="true" edittype="text" sortable="true" search="false"/>
    <sjg:gridColumn name="valeur" index="valeur" width="250" editable="true" edittype="text" title="Valeur" sortable="false" hidden="false"/>
    <sjg:gridColumn name="commentaire" index="commentaire" editable="true" edittype="text" width="250" title="Commentaire" sortable="false" hidden="false"/>
    </sjg:grid>


En bleu, l'action qui permet de peupler la table et renvoyer sur parameter.jsp,
En vert, l'action qui permet le CRUD sur les objets (Create, Retrieve, Update, Delete)

4) Config struts, on retrouve nos 3 actions : 

      A) La première consiste à afficher la page des paramètres (depuis le menu)



                <action name="parameterAction" class="parameterAction">
<result name="success">WEB-INF/jsp/panel/parameter.jsp</result>
</action>


      B) La seconde permet de peupler notre grille, elle est peuplée via une requête AJAX.


<action name="parameterJQueryAction" class="parameterAction">
<result name="success" type="json" />
</action>


     C) La dernière permet de réaliser le CRUD


<action name="parameterEditAction" class="parameterEditAction">
<result name="success">WEB-INF/jsp/panel/parameter.jsp</result>
</action>

5) Détail de l'action parameterAction


package com.homeautomate.ihm.actions;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.SessionAware;


import com.homeautomate.bean.parameter.Parameter;


public class ParameterAction extends AbstractAction implements SessionAware {


private static final long serialVersionUID = 5078264277068533593L;
private static final Log log = LogFactory.getLog(JQueryAction.class);


private List<Parameter> gridModel;
private List<Parameter> myParameters;
private Integer rows = 0;
private Integer page = 0;
private Integer total = 0;
private Integer record = 0;
private String sord;
private String sidx;
private String searchField;
private String searchString;
private String searchOper;
private boolean loadonce = false;
private Map<String, Object> session;


@Override
public String execute() {
log.debug("Page " + getPage() + " Rows " + getRows()
+ " Sorting Order " + getSord() + " Index Row :" + getSidx());
log.debug("Search :" + searchField + " " + searchOper + " "
+ searchString);


Object list = session.get("mylist");
if (list != null) {
myParameters = (List<Parameter>) list;
} else {
log.debug("Build new List");
myParameters = getParameterManager().getDao().list(Parameter.class);
}


if (getSord() != null && getSord().equalsIgnoreCase("asc")) {
Collections.sort(myParameters);
}
if (getSord() != null && getSord().equalsIgnoreCase("desc")) {
Collections.sort(myParameters);
Collections.reverse(myParameters);
}


setRecord(myParameters.size());


int to = (getRows() * getPage());
int from = to - getRows();


if (to > getRecord())
to = getRecord();


if (loadonce) {
setGridModel(myParameters);
} else {
System.out.println(searchString);
if (searchString != null && searchOper != null) {
try {
int id = Integer.parseInt(searchString);
if (searchOper.equalsIgnoreCase("eq")) {
log.debug("search id equals " + id);
List<Parameter> cList = new ArrayList<Parameter>();
cList.add(getParameterManager().getDao().findById(
Parameter.class, id));
setGridModel(cList);
} else if (searchOper.equalsIgnoreCase("ne")) {
log.debug("search id not " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
} else if (searchOper.equalsIgnoreCase("lt")) {
log.debug("search id lesser then " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
} else if (searchOper.equalsIgnoreCase("gt")) {
log.debug("search id greater then " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
}
} catch (NumberFormatException e) {
searchString = null;
}


} else {
setGridModel(getParameterManager().getDao().list(
Parameter.class));
}
}


setTotal((int) Math.ceil((double) getRecord() / (double) getRows()));


session.put("mylist", myParameters);


return SUCCESS;
}


public String getJSON() {
return execute();
}


/**
* @return how many rows we want to have into the grid
*/
public Integer getRows() {
return rows;
}


/**
* @param rows
*            how many rows we want to have into the grid
*/
public void setRows(Integer rows) {
this.rows = rows;
}


/**
* @return current page of the query
*/
public Integer getPage() {
return page;
}


/**
* @param page
*            current page of the query
*/
public void setPage(Integer page) {
this.page = page;
}


/**
* @return total pages for the query
*/
public Integer getTotal() {
return total;
}


/**
* @param total
*            total pages for the query
*/
public void setTotal(Integer total) {
this.total = total;
}


/**
* @return total number of records for the query. e.g. select count(*) from
*         table
*/
public Integer getRecord() {
return record;
}


/**
* @param record
*            total number of records for the query. e.g. select count(*)
*            from table
*/
public void setRecord(Integer record) {


this.record = record;


if (this.record > 0 && this.rows > 0) {
this.total = (int) Math.ceil((double) this.record
/ (double) this.rows);
} else {
this.total = 0;
}
}


/**
* @return an collection that contains the actual data
*/
public List<Parameter> getGridModel() {
return gridModel;
}


/**
* @param gridModel
*            an collection that contains the actual data
*/
public void setGridModel(List<Parameter> gridModel) {
this.gridModel = gridModel;
}


/**
* @return sorting order
*/
public String getSord() {
return sord;
}


/**
* @param sord
*            sorting order
*/
public void setSord(String sord) {
this.sord = sord;
}


/**
* @return get index row - i.e. user click to sort.
*/
public String getSidx() {
return sidx;
}


/**
* @param sidx
*            get index row - i.e. user click to sort.
*/
public void setSidx(String sidx) {
this.sidx = sidx;
}


public void setSearchField(String searchField) {
this.searchField = searchField;
}


public void setSearchString(String searchString) {
this.searchString = searchString;
}


public void setSearchOper(String searchOper) {
this.searchOper = searchOper;
}


public void setLoadonce(boolean loadonce) {
this.loadonce = loadonce;
}


public void setSession(Map<String, Object> session) {
this.session = session;
}


}

5) Détail de l'action parameterEditAction

package com.homeautomate.ihm.actions;

import com.homeautomate.bean.parameter.Parameter;
import com.homeautomate.dao.IParameterDao;

public class ParameterEditAction extends AbstractAction {

/**
*/
private static final long serialVersionUID = -7217313678052619367L;

private String oper;
private String id;
private String cle;
private String valeur;
private String commentaire;
private IParameterDao parameterDao;

@Override
public String execute() throws Exception {
Parameter parameter;
if (oper.equalsIgnoreCase("add")) {
parameter = new Parameter();
parameter.setCle(cle);
parameter.setCommentaire(commentaire);
parameter.setValeur(valeur);
parameterDao.save(parameter);
} else if (oper.equalsIgnoreCase("edit")) {
parameter = parameterDao.findById(Parameter.class,
Integer.parseInt(id));
parameter.setCle(cle);
parameter.setCommentaire(commentaire);
parameter.setValeur(valeur);
parameterDao.update(parameter);
} else if (oper.equalsIgnoreCase("del")) {
parameter = parameterDao.findById(Parameter.class,
Integer.parseInt(id));
parameterDao.delete(parameter);
}
return SUCCESS;
}

public IParameterDao getParameterDao() {
return parameterDao;
}

public void setParameterDao(IParameterDao parameterDao) {
this.parameterDao = parameterDao;
}

public String getOper() {
return oper;
}

public void setOper(String oper) {
this.oper = oper;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getCle() {
return cle;
}

public void setCle(String cle) {
this.cle = cle;
}

public String getValeur() {
return valeur;
}

public void setValeur(String valeur) {
this.valeur = valeur;
}

public String getCommentaire() {
return commentaire;
}

public void setCommentaire(String commentaire) {
this.commentaire = commentaire;
}
}


On va donc créer 2 classes Actions pour tous les objets persistés de notre application (Au moins pour ceux à modifier et afficher sous format tableau)

Au passage, d'autres thèmes sont dispos, il suffit de les modifier dans le tag du Head.

Aperçus : 





vendredi 26 août 2011

Lien Actions Struts & Spring

Dans la partie Actions Struts, on va injecter des managers standards (JdbManager, I18NManager, ParameterManager, VocalManager & SystemManager).

Pour cela il faut indiquer à Struts que l'on utilise Spring, facile ! Dans le fichier struts.xml, il faut ajouter cette variable : 

<constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" />

indiquant à Struts d'aller chercher les Actions dans la conf Spring.

Et dans la configuration Spring, on peut alors déclarer nos actions de cette manière :

Ici je déclare une action "ParameterAction" pointant sur la classe concrète de l'action, je n'oublie pas d'indiquer l'action parente qui contiendra tous mes managers standards, ainsi toutes les actions les posséderont par héritage.

<bean id="parameterAction" class="com.homeautomate.ihm.actions.ParameterAction"  parent="abstractAction">
</bean>


<bean id="abstractAction" class="com.homeautomate.ihm.actions.AbstractAction" abstract="true" >
<property name="jdbManager" ref="jdbManager" />
<property name="parameterManager" ref="parameterManager" />
<property name="vocalManager" ref="vocalManager" />
<property name="i18nManager" ref="i18NManager" />
<property name="systemManager" ref="systemManager" />
</bean>



Petit tour dans la configuration Struts : 

<action name="parameterAction" class="parameterAction">
<result name="success">WEB-INF/jsp/panel/parameter.jsp</result>
</action>



Que va-t-il se passer lorsque j'accéderai à l'action ParamAction ?
              
1) Struts va aller chercher le bean parameterAction dans la conf Spring,
2) Spring va fournir le singleton et injecter automatiquement à la classe parente les managers standard.
3) Struts execute le corps de l'action
4) Struts trappe le retour de l'action (ex: Success) et recherche la jsp à afficher.

Concrètement le contenu de ParamAction (qui rappel, ne fait que remplir une liste de tous les paramètres contenus dans une table depuis la méthode POJO execute() )

package com.homeautomate.ihm.actions;

import java.util.List;

import com.homeautomate.bean.parameter.Parameter;
import com.opensymphony.xwork2.Action;

public class ParameterAction extends AbstractAction {

List<Parameter> parameters;
/**
*/
private static final long serialVersionUID = -8464535536069893165L;

@Override
public String execute() throws Exception {
parameters = getParameterManager().getDao().list(Parameter.class);
return Action.SUCCESS;
}

public List<Parameter> getParameters() {
return parameters;
}

public void setParameters(List<Parameter> parameters) {
this.parameters = parameters;
}
}

                           
On remarque ici, l'utilisation de getParameterManager().getDao().list(Clazz) qui permet de récupérer tous les enregs de la base.

Côté JSP : c'est tout simple : 

Pour afficher les données récupérée, Struts utilise OGNL (Parcoureur de Graph), pour résumer, Struts place le contenu de l'action dans une pile (Stack), l'objet parameters (notre liste de parametres) y est placée.

Si j'ai besoins d'un attribut d'un paramètre, il suffit d'indiquer le nom de l'attribut dans un tag struts, ex : 

// Tag itérator indiquant que l'on va itérer sur les élements de l'objet parameters présent dans la pile

<s:iterator value="parameters">
<tbody>
<tr>
// Ici on indique que l'on souhaite afficher l'id de l'élement courant.
<td><s:property value="id"/></td>
<td><s:property value="cle"/></td>
<td> <s:property value="valeur"/></td>
<td> <s:property value="commentaire"/></td>
</tr>
</tbody>
</s:iterator>

Struts inspecte donc chaque objet présent dans la pile.

Résultat 



Il ne restera donc plus qu'à ajouter les boutons modifier/delete/ajouter.

Pour démarrer le HomeAutomate depuis la GUI, il est nécessaire d'ajouter le démarrage du StartupServlet dans le fichier web.xml et c'est tout.

<servlet>
<servlet-name>StartupServlet</servlet-name>
<servlet-class>com.homeautomate.startup.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>