/**
* Classe ServeurX10
*
* Classe pour recevoir des commandes X10 via un socket en recevant un objet de type DataX10.
*
* Ce programme Java utilise l'utilitaire BottleRoket (br) pour
* contrôler les éléments X10 via un module FireCracker (CM17A)
*
* D'autres utilitaires (uc, rf et pl) seront ajoutés dans les laboratoires à venir
*
* Gestion de l'information 247-616-SH
* Hiver 2014
*
* @author Jordan Careau-Beaulieu
* @version Feb 3 2014
*/
import java.io.*;
import java.net.*;
import java.util.*;
import DataX10.*;
import DataBaseX10.*;
public class ServeurX10 implements Runnable
{
// Constante pour le nombre d'octets du tampon mémoire du mini-serveur
final static int NB_OCTETS = 1000;
// Référence vers l'objet ServerSocket
ServerSocket _ssServeur;
// Référence vers l'objet Thread
Thread _tService;
public static void main(String[] sArgs)
{
int nPort;
try
{
nPort = Integer.parseInt(sArgs[0]);
}
catch(Exception e)
{
System.out.println("Port 2222 will be used.");
nPort = 2222;
}
ServeurX10 server = new ServeurX10(nPort); //Création d'un objet ServeurX10
}
/* Constructeur de l'objet ServeurX10
* @param nPort port sur lequel le serveur écoutera
*/
public ServeurX10(int nPort)
{
try
{
// Création du mini-serveur au port spécifié
// Le miniserveur a un tampon mémoire de NB_OCTETS octets
_ssServeur = new ServerSocket(nPort, NB_OCTETS);
// Création et démarrage de la tâche d'écoute du miniserveur
// sur le port 2222
_tService = new Thread(this);
_tService.start();
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
/* Thread qui obtient les données du client et qui exécute les commandes
*/
public void run()
{
while(_tService != null)
{
try
{
// Le mini-serveur attend une connexion réseau...
System.out.println("Attente d'une connexion au serveur...");
Socket sConnexion = _ssServeur.accept();
// Ce message est affiché si une connexion est établie
System.out.println("Connexion au serveur établie!");
// Récupère la requête du client... (flux de données)
InputStream isIn = sConnexion.getInputStream();
ObjectInputStream oisIn = new ObjectInputStream(isIn);
DataX10 dx10Commande = new DataX10();
dx10Commande = (DataX10) oisIn.readObject();
System.out.println("Requête : " + dx10Commande);
String sReponse = ""; // String de reponse du serveur
/// Traitement de la commande
try
{
String sCommande; // String pour la commande a envoyer
// Si c'est l'Utilitaire br
if(dx10Commande.getUtilitaire().equals("br"))
{
// Teste de la commande, si la commands est
// ALL_ON/OFF ou LAMPS_ON/OFF on retire le key code
if( (dx10Commande.getCommandCode().equals("ALL_ON")) ||
(dx10Commande.getCommandCode().equals("ALL_OFF")) ||
(dx10Commande.getCommandCode().equals("LAMPS_ON")) ||
(dx10Commande.getCommandCode().equals("LAMPS_OFF")) )
{
dx10Commande.setKeyCode("");
}
// Construction de la commande à envoyer
sCommande = dx10Commande.getHouseCode();
sCommande += dx10Commande.getKeyCode();
sCommande += " ";
sCommande += dx10Commande.getCommandCode();
sCommande += " ";
sCommande += dx10Commande.getOptions();
System.out.println("Commande: br " + sCommande);
// Lancement de br
Process br = Runtime.getRuntime().exec("br " + sCommande);
// Traitement de la sortie de la commande exécutée
BufferedReader brDirectory = new BufferedReader(
new InputStreamReader(
br.getInputStream()));
BufferedReader brErrDirectory = new BufferedReader(
new InputStreamReader(
br.getErrorStream()));
System.out.println("Reponse de br:");
String sBRRetour;
while((sBRRetour = brDirectory.readLine()) != null)
{
sReponse += sBRRetour;
sReponse += "\n";
System.out.println(sBRRetour);
}
}
// Valeurs pour l'envoi de UC, RF et PL
char cSOH = '~';
char cInterface;
char cHouseCode = (char)(dx10Commande.getHouseCode().charAt(0)-17);
char cKeyCode = (char)((Integer.parseInt(dx10Commande.getKeyCode())-1)+48);
char cCommandCode = 0;
char cChecksum = 0;
// Si c'est l'utilitaire uc
if(dx10Commande.getUtilitaire().equals("uc"))
{
// Interface UC
cInterface = '0';
cCommandCode = buildCommandCode(dx10Commande, cCommandCode);
cChecksum = calculateChecksum(cInterface, cHouseCode, cKeyCode, cCommandCode);
buildAndSendPacket(cSOH, cInterface, cHouseCode, cKeyCode, cCommandCode, cChecksum);
}
// Si c'est l'utilitaire rf
else if(dx10Commande.getUtilitaire().equals("rf"))
{
// Interface RF
cInterface = '1';
cCommandCode = buildCommandCode(dx10Commande, cCommandCode);
cChecksum = calculateChecksum(cInterface, cHouseCode, cKeyCode, cCommandCode);
buildAndSendPacket(cSOH, cInterface, cHouseCode, cKeyCode, cCommandCode, cChecksum);
}
// Si c'est l'utilitaire pl
else if(dx10Commande.getUtilitaire().equals("pl"))
{
// Interface RF
cInterface = '2';
cCommandCode = buildCommandCode(dx10Commande, cCommandCode);
cChecksum = calculateChecksum(cInterface, cHouseCode, cKeyCode, cCommandCode);
buildAndSendPacket(cSOH, cInterface, cHouseCode, cKeyCode, cCommandCode, cChecksum);
}
}
catch(Exception e)
{
System.out.println(e.toString());
}
// Si la réponse ou les options sont vides,
// on place un espace pour la compatiblilité avec
// le serveur SQL
if(sReponse.equals(""))
{
dx10Commande.setMessage(" ");
}
else
{
dx10Commande.setMessage(sReponse);
}
if(dx10Commande.getOptions().equals(""))
{
dx10Commande.setOptions(" ");
}
// Si la commande viens du pc avec br
if(dx10Commande.getUtilitaire().equals("br"))
{
/// Ecriture de la base de donnée
DBX10 dbX10 = new DBX10();
// Connexion à la base de donnée
dbX10.connexion("localhost", 3306, "X10", dx10Commande.getID(), dx10Commande.getPassword());
// Écriture dans la base de donnée
dbX10.ecrireDataX10("Actions", dx10Commande);
// Fermeture de la connexion à la base de donnée
dbX10.fermeture();
}
// Réponse du serveur au client... (flux de données)
OutputStream osOut = sConnexion.getOutputStream();
ObjectOutputStream oosOut = new ObjectOutputStream(osOut);
System.out.println(dx10Commande.getMessage());
System.out.println("sReponse: " + sReponse);
oosOut.writeObject(dx10Commande);
// Fermeture des objets de flux de données
oosOut.close();
osOut.close();
oisIn.close();
isIn.close();
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
/**
* Methode qui détermine quel octet placer dans cCommandCode
* selon la commands
* @param dx10 Objet DataX10 qui contient le command code
* @param commandCode charactère où placer l'octet
* @return référence vers l'octet du command code
*/
private char buildCommandCode(DataX10 dx10, char commandCode)
{
// Construction du command code
if(dx10.getCommandCode().equals("ON"))
commandCode = '0';
else if(dx10.getCommandCode().equals("OFF"))
commandCode = '1';
else if(dx10.getCommandCode().equals("ALL_ON"))
commandCode = '2';
else if(dx10.getCommandCode().equals("ALL_OFF"))
commandCode = '3';
else if(dx10.getCommandCode().equals("LAMPS_ON"))
commandCode = '4';
else if(dx10.getCommandCode().equals("LAMPS_OFF"))
commandCode = '5';
else if(dx10.getCommandCode().equals("BRIGHT"))
commandCode = '6';
else if(dx10.getCommandCode().equals("DIM"))
commandCode = '7';
return commandCode;
}
/**
* Calcule le checksum de la trame
* @param cInterface // L'octet de l'interface de la trame
* @param cHouseCode // L'octet du house code de la trame
* @param cKeyCode // L'octet du key code de la trame
* @param cCommandCode // L'octet du command code de la trame
* @return Le checksum en char de la trame
*/
private char calculateChecksum(char cInterface, char cHouseCode,
char cKeyCode, char cCommandCode)
{
char checksum = (char) (cInterface + cHouseCode + cKeyCode + cCommandCode);
if(checksum > 0x7F)
checksum -= 0x7F;
return checksum;
}
/**
* Batit et envoie la trame sur le port série
* @param cSOH
* @param cInterface
* @param cHouseCode
* @param cKeyCode
* @param cCommandCode
* @param cChecksum
*/
private void buildAndSendPacket(char cSOH, char cInterface, char cHouseCode,
char cKeyCode, char cCommandCode, char cChecksum)
{
String sPacket = "";
sPacket += cSOH;
sPacket += cInterface;
sPacket += cHouseCode;
sPacket += cKeyCode;
sPacket += cCommandCode;
sPacket += cChecksum;
System.out.println(sPacket);
FileOutputStream fosFichier;
DataOutputStream dosDonnees;
try
{
// Initialise la source de données
fosFichier = new FileOutputStream("command.txt");
// Initialise le flux de données
dosDonnees = new DataOutputStream(fosFichier);
// Écrit les 6 octets dans le fichier
dosDonnees.write(sPacket.getBytes());
// Fermeture du flux et de la source
dosDonnees.close();
fosFichier.close();
// Exécution d'un programme natif à partir d'un programme Java
// Propriétées générales de l'application courante (dont le répertoire courant)
Properties ps = System.getProperties();
// Construction de la commande pour envoi sur COM1 (/dev/ttyS0)
sPacket = "cat " + ps.getProperty("user.dir") + "/command.txt >" +
"/dev/ttyPSC1";
String[] sCmd = { "/bin/bash", "-c", sPacket };
// Affiche la commande sur le terminal
System.out.println(sCmd[0] + " " + sCmd[1] + " " + sCmd[2]);
// Exécution de la commande
Process p = Runtime.getRuntime().exec(sCmd);
// Traitement de la sortie de la commande exécutée
} catch(Exception e) {
e.printStackTrace();
}
}
}