OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 118 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
43 ilm 1
package org.openconcerto.modules.badge;
2
 
3
import java.awt.AWTException;
4
import java.awt.Image;
5
import java.awt.MenuItem;
6
import java.awt.PopupMenu;
7
import java.awt.SystemTray;
8
import java.awt.TrayIcon;
9
import java.awt.event.ActionEvent;
10
import java.awt.event.ActionListener;
11
import java.io.File;
12
import java.io.FileInputStream;
13
import java.io.FileNotFoundException;
14
import java.io.IOException;
15
import java.net.DatagramPacket;
16
import java.net.DatagramSocket;
17
import java.sql.SQLException;
18
import java.sql.Time;
19
import java.text.SimpleDateFormat;
20
import java.util.Calendar;
21
import java.util.Date;
22
import java.util.List;
118 ilm 23
import java.util.Locale;
43 ilm 24
import java.util.Properties;
25
 
26
import javax.swing.ImageIcon;
27
import javax.swing.JFrame;
28
import javax.swing.JOptionPane;
29
import javax.swing.SwingUtilities;
30
 
31
import org.openconcerto.erp.config.ComptaPropsConfiguration;
32
import org.openconcerto.erp.config.ServerFinderPanel;
33
import org.openconcerto.erp.modules.ModuleManager;
85 ilm 34
import org.openconcerto.erp.modules.ModuleVersion;
43 ilm 35
import org.openconcerto.sql.Configuration;
36
import org.openconcerto.sql.element.SQLElement;
37
import org.openconcerto.sql.model.SQLBase;
38
import org.openconcerto.sql.model.SQLRow;
39
import org.openconcerto.sql.model.SQLRowListRSH;
40
import org.openconcerto.sql.model.SQLRowValues;
41
import org.openconcerto.sql.model.SQLSelect;
42
import org.openconcerto.sql.model.SQLTable;
43
import org.openconcerto.sql.model.Where;
44
import org.openconcerto.sql.preferences.SQLPreferences;
45
import org.openconcerto.sql.preferences.UserProps;
46
import org.openconcerto.sql.sqlobject.IComboSelectionItem;
47
import org.openconcerto.utils.ExceptionHandler;
118 ilm 48
import org.openconcerto.utils.i18n.TranslationManager;
43 ilm 49
 
50
public class BadgeListener implements Runnable {
51
    private static final int UDP_PORT = 1470;
118 ilm 52
    private String doorIp;
43 ilm 53
    private int relai;
54
 
55
    protected TrayIcon trayIcon;
56
 
57
    public BadgeListener() {
118 ilm 58
 
59
    }
60
 
61
    public void init(String id) {
153 ilm 62
        // TODO use HeadlessGestion
118 ilm 63
        TranslationManager.getInstance().addTranslationStreamFromClass(BadgeListener.class);
64
        TranslationManager.getInstance().setLocale(Locale.FRANCE);
43 ilm 65
        final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create(true);
66
        if (conf == null) {
67
            ServerFinderPanel.main(new String[0]);
68
            return;
69
        }
70
 
71
        Configuration.setInstance(conf);
153 ilm 72
        conf.getUserManager().setCurrentUserID(2);
43 ilm 73
 
74
        try {
75
            conf.getBase();
76
            // create table if necessary
77
            SQLPreferences.getPrefTable(conf.getRoot());
78
        } catch (Exception e) {
79
            ExceptionHandler.die("Erreur de connexion à la base de données", e);
80
            // since we're not in the EDT, the previous call doesn't block,
81
            // so return (it won't quit the VM since a dialog is displaying)
82
            return;
83
        }
84
        try {
85
            final File moduleDir = new File("Modules");
86
            moduleDir.mkdir();
87
            ModuleManager.getInstance().addFactories(moduleDir);
88
        } catch (Throwable e) {
89
            ExceptionHandler.handle("Erreur d'accès aux modules", e);
90
        }
91
 
92
        int selectedSociete = UserProps.getInstance().getLastSocieteID();
118 ilm 93
        if (id != null) {
94
            try {
95
                selectedSociete = Integer.valueOf(id);
96
            } catch (Exception e) {
97
                e.printStackTrace();
98
            }
99
        }
100
 
43 ilm 101
        if (selectedSociete < SQLRow.MIN_VALID_ID) {
102
            final SQLElement elem = conf.getDirectory().getElement(conf.getRoot().getTable("SOCIETE_COMMON"));
103
            final List<IComboSelectionItem> comboItems = elem.getComboRequest().getComboItems();
104
            if (comboItems.size() > 0)
105
                selectedSociete = comboItems.get(0).getId();
106
            else
107
                throw new IllegalStateException("No " + elem + " found");
108
        }
118 ilm 109
        System.err.println("BadgeListener.init() societe " + selectedSociete);
43 ilm 110
        conf.setUpSocieteDataBaseConnexion(selectedSociete);
111
    }
112
 
113
    private PopupMenu createTrayMenu() {
114
        ActionListener exitListener = new ActionListener() {
115
            public void actionPerformed(ActionEvent e) {
116
                System.out.println("Bye from the tray");
117
                System.exit(0);
118
            }
119
        };
120
 
121
        ActionListener executeListener = new ActionListener() {
122
            public void actionPerformed(ActionEvent e) {
118 ilm 123
                openDoor(4);
43 ilm 124
            }
125
        };
126
 
127
        PopupMenu menu = new PopupMenu();
128
        MenuItem execItem = new MenuItem("Ouvrir la porte");
129
        execItem.addActionListener(executeListener);
130
        menu.add(execItem);
131
 
132
        MenuItem exitItem = new MenuItem("Quitter");
133
        exitItem.addActionListener(exitListener);
134
        menu.add(exitItem);
135
        return menu;
136
    }
137
 
138
    private TrayIcon createTrayIcon() {
139
        Image image = new ImageIcon(this.getClass().getResource("badge.png")).getImage();
140
        PopupMenu popup = createTrayMenu();
141
        TrayIcon ti = new TrayIcon(image, "Service de badge", popup);
142
        ti.setImageAutoSize(true);
143
        return ti;
144
    }
145
 
146
    /**
147
     * @param args
148
     */
149
    public static void main(String[] args) {
150
 
151
        BadgeListener bl = new BadgeListener();
152
        bl.readConfiguration();
153
        bl.initUI();
154
        bl.startDaemon();
155
 
156
    }
157
 
158
    public void startDaemon() {
159
        Thread t = new Thread(this);
160
        t.setName("UDP Listener");
161
        t.start();
162
    }
163
 
164
    public void initUI() {
165
        SwingUtilities.invokeLater(new Runnable() {
166
 
167
            @Override
168
            public void run() {
169
                if (!SystemTray.isSupported()) {
118 ilm 170
                    try {
171
                        JOptionPane.showMessageDialog(new JFrame(), "System tray not supported on this platform");
172
                    } catch (Exception e) {
173
                        System.out.println("System tray not supported on this platform");
174
                    }
175
                } else {
176
                    try {
177
                        final SystemTray sysTray = SystemTray.getSystemTray();
178
                        trayIcon = createTrayIcon();
179
                        sysTray.add(trayIcon);
180
                        displayMessage("Service de badge", "Ecoute sur port " + UDP_PORT);
181
                    } catch (AWTException e) {
182
                        System.out.println("Unable to add icon to the system tray");
183
                    }
43 ilm 184
                }
185
 
186
            }
187
        });
188
 
189
    }
190
 
191
    public void readConfiguration() {
192
        final Properties props = new Properties();
193
        final File file = new File("badge.properties");
194
        System.out.println("Reading from: " + file.getAbsolutePath());
195
        try {
196
            final FileInputStream inStream = new FileInputStream(file);
197
            props.load(inStream);
118 ilm 198
            this.doorIp = props.getProperty("ip").trim();
43 ilm 199
            this.relai = Integer.parseInt(props.getProperty("relai", "1"));
200
            inStream.close();
201
        } catch (FileNotFoundException e) {
202
            JOptionPane.showMessageDialog(new JFrame(), "Fichier manquant\n" + file.getAbsolutePath());
203
        } catch (IOException e) {
204
            JOptionPane.showMessageDialog(new JFrame(), e.getMessage());
205
        }
118 ilm 206
        System.err.println("BadgeListener.readConfiguration() door ip : " + doorIp + ", index :" + relai);
43 ilm 207
 
118 ilm 208
        init(props.getProperty("idSociete"));
43 ilm 209
    }
210
 
211
    @Override
212
    public void run() {
213
        while (true) {
214
            DatagramSocket serverSocket = null;
215
 
216
            try {
217
                final byte[] receiveData = new byte[1024];
218
                serverSocket = new DatagramSocket(UDP_PORT);
219
 
220
                while (true) {
221
                    final DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
222
                    serverSocket.receive(receivePacket);
223
                    final String sentence = new String(receivePacket.getData()).trim();
118 ilm 224
                    cardIdReceived(sentence);
43 ilm 225
                }
226
            } catch (Throwable e) {
227
                e.printStackTrace();
118 ilm 228
                displayError("Erreur", (e == null) ? "" : e.getMessage());
43 ilm 229
            } finally {
230
                if (serverSocket != null) {
231
                    serverSocket.close();
232
                }
233
            }
234
            try {
235
                System.out.println("Waiting 10s");
236
                Thread.sleep(10 * 1000);
237
            } catch (InterruptedException e) {
238
                System.err.println(e.getMessage());
239
            }
240
        }
241
    }
242
 
118 ilm 243
    public void cardIdReceived(final String sentence) {
244
        System.err.println("BadgeListener.cardIdReceived() " + sentence);
245
        if (isBadgeAllowed(sentence)) {
246
            boolean b = openDoor(4);
247
            if (b) {
248
                displayMessage("Ouverture", "Ouverture de la porte OK");
249
            } else {
250
                displayError("Erreur", "Impossible d'ouvrir la porte");
251
            }
252
 
253
        } else {
254
            displayMessage("Carte refusée", "Carte " + sentence + " non acceptée");
255
        }
256
    }
257
 
258
    public void displayMessage(String title, String txt) {
259
        if (trayIcon != null) {
260
            trayIcon.displayMessage(title, txt, TrayIcon.MessageType.INFO);
261
        } else {
262
            System.out.println("[INFO]  " + title + " : " + txt);
263
        }
264
    }
265
 
266
    public void displayError(String title, String txt) {
267
        if (trayIcon != null) {
268
            trayIcon.displayMessage(title, txt, TrayIcon.MessageType.ERROR);
269
        } else {
270
            System.out.println("[ERROR] " + title + " : " + txt);
271
        }
272
 
273
    }
274
 
43 ilm 275
    public boolean isBadgeAllowed(String cardNumber) {
276
        SQLBase base = Configuration.getInstance().getBase();
277
        SQLSelect sel = new SQLSelect(base);
153 ilm 278
        // FIXME use SQLElement
43 ilm 279
        SQLTable tableAdh = Configuration.getInstance().getRoot().findTable("ADHERENT");
280
        sel.addSelectStar(tableAdh);
281
        sel.setWhere(new Where(tableAdh.getField("NUMERO_CARTE"), "=", cardNumber));
282
        List<SQLRow> list = (List<SQLRow>) base.getDataSource().execute(sel.asString(), SQLRowListRSH.createFromSelect(sel));
283
 
284
        String motif = "";
153 ilm 285
        // FIXME use actual module installed in the DB (MAYBE init() the ModuleManager)
85 ilm 286
        Boolean onlyAdmin = ModuleManager.getInstance().getFactories().get("org.openconcerto.modules.badge").get(new ModuleVersion(1, 0)).getSQLPreferences(tableAdh.getDBRoot())
287
                .getBoolean(Module.ENTREE_PREF, false);
43 ilm 288
        boolean allow = false;
289
        SQLRow adh = null;
290
        // Aucun adhérent assigné à cette carte
291
        if (list == null || list.isEmpty()) {
292
            motif = "Aucun adhérent associé à la carte " + cardNumber;
293
            System.err.println(motif);
294
 
295
        } else if (list.size() > 1) {
296
            motif = list.size() + " adhérents sont liés à la même carte " + cardNumber;
297
            System.err.println(motif);
298
            Thread.dumpStack();
299
        } else {
300
 
301
            for (SQLRow sqlRow : list) {
302
 
303
                adh = sqlRow;
304
 
305
                // Admin toujours autorisé
306
                if (sqlRow.getBoolean("ADMIN")) {
307
                    allow = true;
308
                    motif = "Administrateur toujours autorisé";
65 ilm 309
                    break;
43 ilm 310
                }
311
 
79 ilm 312
                if (onlyAdmin) {
313
                    motif = "Seul les membres administrateurs sont autorisés!";
314
                    break;
315
                }
316
 
43 ilm 317
                if (!sqlRow.getBoolean("ACTIF")) {
318
                    motif = "La carte de l'adhérent n'est pas active dans sa fiche";
65 ilm 319
                    break;
43 ilm 320
                }
321
 
322
                Calendar cal = Calendar.getInstance();
65 ilm 323
                final Date d = cal.getTime();
324
                final Calendar dateValidite = sqlRow.getDate("DATE_VALIDITE_INSCRIPTION");
43 ilm 325
 
65 ilm 326
                if (dateValidite != null && dateValidite.before(cal)) {
43 ilm 327
                    motif = "La date d'autorisation est expirée";
65 ilm 328
                    break;
43 ilm 329
                }
330
 
331
                SQLRow rowPlage = sqlRow.getForeignRow("ID_PLAGE_HORAIRE");
332
 
333
                if (rowPlage != null) {
334
                    Time time = new Time(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
335
                    SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE");
336
                    String day = dateFormat.format(d).toUpperCase();
337
                    {
338
                        Time d1 = (Time) rowPlage.getObject("DEBUT_1_" + day);
339
                        Time f1 = (Time) rowPlage.getObject("FIN_1_" + day);
340
                        if (d1 != null && f1 != null) {
341
                            if (time.after(d1) && time.before(f1)) {
342
                                allow = true;
343
                                motif = "Autorisé sur la plage " + rowPlage.getString("NOM") + " 1";
344
                                break;
345
                            }
346
                        }
347
                    }
348
                    {
349
                        Time d1 = (Time) rowPlage.getObject("DEBUT_2_" + day);
350
                        Time f1 = (Time) rowPlage.getObject("FIN_2_" + day);
351
 
352
                        if (d1 != null && f1 != null) {
353
                            if (time.after(d1) && time.before(f1)) {
354
                                allow = true;
355
                                motif = "Autorisé sur la plage " + rowPlage.getString("NOM") + " 2";
356
                                break;
357
                            }
358
                        }
359
                    }
360
 
361
                    {
362
                        Time d1 = (Time) rowPlage.getObject("DEBUT_3_" + day);
363
                        Time f1 = (Time) rowPlage.getObject("FIN_3_" + day);
364
 
365
                        if (d1 != null && f1 != null) {
366
                            if (time.after(d1) && time.before(f1)) {
367
                                allow = true;
368
                                motif = "Autorisé sur la plage " + rowPlage.getString("NOM") + " 3";
369
                                break;
370
                            }
371
                        }
372
                    }
373
                    motif = "Non autorisé sur la plage horaire " + rowPlage.getString("NOM");
374
                } else {
375
                    motif = "Aucune plage horaire associée";
376
                }
377
            }
378
        }
379
 
380
        // Création de l'entrée dans la table
381
        SQLTable tableEntree = Configuration.getInstance().getRoot().findTable("ENTREE");
382
        SQLRowValues rowVals = new SQLRowValues(tableEntree);
383
        rowVals.put("DATE", new Date());
384
        rowVals.put("NUMERO_CARTE", cardNumber);
385
        rowVals.put("ACCEPTE", allow);
386
        rowVals.put("MOTIF", motif);
387
 
388
        if (adh != null) {
389
            rowVals.put("ADHERENT", adh.getString("NOM") + " " + adh.getString("PRENOM"));
390
        }
391
        try {
392
            rowVals.commit();
393
        } catch (SQLException exn) {
394
            exn.printStackTrace();
395
        }
396
        return allow;
397
    }
398
 
118 ilm 399
    public boolean openDoor(int seconds) {
400
        final Relai r = new Relai(doorIp, relai);
401
        try {
402
            r.pulse(seconds);
403
            return true;
404
        } catch (Throwable ex) {
405
            return false;
406
        }
407
    }
408
 
409
    public String getDoorIp() {
410
        return doorIp;
411
    }
43 ilm 412
}