Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
15 arune 1
/*
2
 * File created by Jimmy
3
 * at 2003-sep-06 14:38:08
4
 */
5
package Macbeth.Modules.modGenRoomControl;
6
 
7
import javax.swing.*;
8
import java.awt.*;
9
import java.awt.event.*;
10
import java.util.Iterator;
11
import java.util.HashMap;
12
 
13
import Macbeth.System.*;
14
import Macbeth.Utilities.UByte;
15
import Macbeth.Utilities.MySystem;
16
import Macbeth.Utilities.DataRepository;
17
import Macbeth.XML.XMLDataHandler;
18
 
19
/**
20
 * A Macbeth module that allows the user to turn on/off
21
 * lamps connected to the RoomControl ARNE node, which
22
 * is assumed to be connected to the ARNE bus. The ARNE
23
 * Macbeth module is required as well of course, or else
24
 * this module won't be able to communicate with the
25
 * RoomControl node.
26
 * @author Jimmy, arune
27
 * TODO: ska man testa om node-firendlyname existerar nar man laddar in dem?
28
 */
29
public class modGenRoomControl extends MbModule implements MbModuleGUI {
30
 
31
    //A GUI for our module.
32
    private GUI gui;
33
    //Is our GUI currently visible or not?
34
    private boolean guiVisible = false;
35
    //A list of known room objects.
36
    private HashMap roomObjects;
37
 
38
    /**
39
     * Creates a new instance of modRoomControl.
40
     */
41
    public modGenRoomControl() {
42
        //construct MbModule
43
        super();
44
        roomObjects = new HashMap(32);
45
        gui = new GUI();
46
        //we depend on the RemoteControl-module
47
        addDependency("RemoteControl");
48
        //we depend on the ARNE-module
49
        addDependency("ARNE");
50
        //register our packet data handler
51
        setPacketDataHandler(new PacketDataHandler());
52
        //we have a html-interface, so lets register it
53
        setHTMLInterface(new HTMLInterface());
54
    }
55
 
56
    /**
57
     * Gets the name of the component.
58
     * @return The name of the component.
59
     */
60
    public String name() {
61
        return "GenRoomControl";
62
    }
63
 
64
    /**
65
     * Gets the description of the component.
66
     * @return The description of the component.
67
     */
68
    public String description() {
69
        return "Controls any on/off-thing via the ARNE bus";
70
    }
71
 
72
    /**
73
     * This method sets default values on all _required_ data
74
     * fields in the data repository.
75
     */
76
    protected void initDataFields() {
77
        //this module doesn't require any data fields
78
    }
79
 
80
    /**
81
     * Starts up this module.
82
     */
83
    public void startup() throws MbStartupException {
84
        //start up MbModule
85
        super.startup();
86
 
87
        //get all room objects from the data repository
88
        DataRepository.DataList list = dataRepository.getList("roomobjects");
89
        if (list!=null) {
90
            Iterator items = list.items();
91
            while (items.hasNext()) {
92
                DataRepository.DataListItem item = (DataRepository.DataListItem)items.next();
93
                String name = (String)item.getField("name");
94
                String address = (String)item.getField("nodename");
95
 
96
                String bytes = (String)item.getField("byte");
97
                String[] bytearray = bytes.split(",");
98
                UByte[] b = new UByte[bytearray.length];
99
                for (int i = 0; i < bytearray.length; i++) {
100
                    b[i] = UByte.parseUByte(bytearray[i]);
101
                }
102
                //UByte b = UByte.parseUByte((String)item.getField("byte"));
103
 
104
                boolean pub = ((String)item.getField("public")).equals("true");
105
                String remotebtn = item.containsField("remotebutton") ? (String)item.getField("remotebutton") : "";
106
                roomObjects.put(name, new GenRoomObject(name, address, b, remotebtn, pub));
107
            }
108
        }
109
        //no room objects found in data repository
110
        else {
111
            _info.println("roomobjects-list is missing. no room objects defined!");
112
        }
113
 
114
        //if we have any room objects
115
        if (!roomObjects.isEmpty()) {
116
            //lets send requests for their remote control buttons
117
            MbPacket p = new MbPacket();
118
            p.setDestination(new MbLocation("self", "RemoteControl"));
119
            Iterator it = roomObjects.keySet().iterator();
120
            while (it.hasNext()) {
121
                String key = (String) it.next();
122
                GenRoomObject o = (GenRoomObject) roomObjects.get(key);
123
                if (o != null) {
124
                    p.appendContents("  <buttonrequest button=\"" + o.remoteButton + "\" module=\"" + name() + "\" />");
125
                }
126
            }
127
            sendPacket(p);
128
        }
129
    }
130
 
131
    /**
132
     * Shuts down this module.
133
     */
134
    public void shutdown() {
135
        //shut down MbModule
136
        super.shutdown();
137
    }
138
 
139
    /**
140
     * A HTML-interface for this module.
141
     */
142
    private class HTMLInterface implements MbHTMLInterface {
143
        /**
144
         * Retreives the full code for your HTML-page. This is
145
         * formatted as plain text and must be valid HTML-code.
146
         * @return Full HTML-code for the page.
147
         * TODO: remove? redo? ta bort toggle? bor inte funkar alls om name anvamns
148
         */
149
        public String getHTMLPage() {
150
            String s = "<html><body>" + MySystem.lineBreak;
151
            s += "<h1>Room Control module</h1>" + MySystem.lineBreak;
152
            s += "<p>This module controls any on/off-node connected to ARNE bus.</p>" + MySystem.lineBreak;
153
            s += "<h2>Controls:</h2>";
154
            s += "<center><p><table border=\"1\" cellpadding=\"3\" cellspacing=\"0\">";
155
            Iterator it = roomObjects.keySet().iterator();
156
            while (it.hasNext()) {
157
                GenRoomObject o = (GenRoomObject)roomObjects.get(it.next());
158
                if (o!=null) {
159
                    if (o.displHTML) {      //if display this object (configured in modGenRoomControl.xml)
160
                        s += "<tr><td>" + o.name + "</td><td>[<a href=\"toggle:" + o.name + "\">toggle</a>]</td><td>[<a href=\"on:" + o.name + "\">ON</a>]</td><td>[<a href=\"off:" + o.name + "\">OFF</a>]</td></tr></tr>";
161
                    }
162
                }
163
            }
164
            s += "</table></center>";
165
            s += "</body></html>";
166
            return s;
167
        }
168
 
169
        /**
170
         * This method is invoked when a link is pressed on your
171
         * HTML-page.
172
         * @param href The href-attribute of the link.
173
         */
174
        public void linkPressed(String href) {
175
            String[] s = href.split(":");
176
            if (s.length >= 2) {
177
                /*  Ex: "toggle:Window lamp"
178
                    this means we should toggle the Window lamp. */
179
                if (s[0].equals("toggle")) {
180
                    GenRoomObject o = (GenRoomObject) roomObjects.get(s[1]);
181
                    if (o != null) {
182
                        toggleRoomObject(o.address, o.byteValue);
183
                    }
184
                }
185
                /*  Ex: "on:Window lamp"
186
                    this means we should turn ON the Window lamp. */
187
                else if (s[0].equals("on")) {
188
                    GenRoomObject o = (GenRoomObject) roomObjects.get(s[1]);
189
                    if (o != null) {
190
                        setRoomObject(o.address, o.byteValue ,true);
191
                    }
192
                }
193
                /*  Ex: "off:Window lamp"
194
                    this means we should turn OFF the Window lamp. */
195
                else if (s[0].equals("off")) {
196
                    GenRoomObject o = (GenRoomObject) roomObjects.get(s[1]);
197
                    if (o != null) {
198
                        setRoomObject(o.address, o.byteValue, false);
199
                    }
200
                }
201
            }
202
        }
203
    }
204
 
205
    /**
206
     * Takes care of XML-data found in incoming packets.
207
     */
208
    private class PacketDataHandler implements XMLDataHandler {
209
        /**
210
         * Called when start of a new element is found in the XML-data.
211
         * Ex: <name attr1="value1" attr2="value2">
212
         * Element name would then be "name" and attribute list
213
         * would contain "value1" and "value2" mapped to the attribute
214
         * names "attr1" and "attr2".
215
         * @param element The name of the element.
216
         * @param attributes The element attributes.
217
         */
218
        public void XMLstartElement(String element, HashMap attributes) {
219
            /**
220
             * Ex: <remotecontrol button="NUMERIC4" state="DOWN" />
221
             * This is a notification from the remote control module
222
             * about one of our requested remote control buttons have
223
             * been pressed.
224
             */
225
            if (element.equals("remotecontrol") && attributes.containsKey("button") && attributes.containsKey("state")) {
226
                String state = (String)attributes.get("state");
227
                String button = (String)attributes.get("button");
228
 
229
                //find all room objects that are associated with this remote button
230
                Iterator it = roomObjects.values().iterator();
231
                while (it.hasNext()) {
232
                    GenRoomObject o = (GenRoomObject)it.next();
233
                    if (o.remoteButton.equals(button)) {
234
                        //toggle all such room objects
235
                        sendRoomObject(o.address, o.byteValue, state);
236
                    }
237
                }
238
            }
239
        }
240
 
241
        public void XMLendElement(String element) {}
242
        public void XMLelementData(String data) {}
243
        public void XMLdocumentStart() {}
244
        public void XMLdocumentEnd() {}
245
    }
246
 
247
    /**
248
     *
249
     * @param address
250
     * @param value
251
     * @param state
252
     */
253
    private void sendRoomObject(String address, UByte[] value, String state) {
254
        int iState = 0;
255
 
256
        if (state.equals("DOWN")) {
257
            iState = 240;
258
        }
259
        else if (state.equals("UP")) {
260
            iState = 0;
261
        }
262
        else if (state.equals("ON")) {
263
            iState = 1;
264
        }
265
        else if (state.equals("OFF")) {
266
            iState = 2;
267
        }
268
 
269
        //create a packet and address it to the ARNE module
270
        MbPacket p = new MbPacket();
271
        p.setDestination(new MbLocation("self", "ARNE"));
272
        //ARNE packet in XML-format
273
        String contentValueData = "";
274
        for (int i = 0; i < value.length; i++)
275
        {
276
            contentValueData = contentValueData + "<byte id=\"" + (i+2) + "\" value=\"" + Integer.toString(value[i].shortValue()) + "\"/>";
277
        }
278
        int arneBytes = value.length+1;
279
        p.setContents("<arnepacket bytes=\"" + arneBytes + "\" destnode=\"" + address + "\">" + //destnode -  address
280
                "<byte id=\"1\" value=\"" + Integer.toString(iState) + "\"/>" +
281
                contentValueData +
282
                "</arnepacket>");
283
        sendPacket(p);
284
 
285
    }
286
 
287
    /**
288
     * Toggles a room object (=lamp) by telling the RoomControl node
289
     * to toggle a specific output.
290
     * @param address
291
     * @param value The object to toggle (0 is first one).
292
     */
293
    private void toggleRoomObject(String address, UByte[] value) {
294
        //create a packet and address it to the ARNE module
295
        MbPacket p = new MbPacket();
296
        p.setDestination(new MbLocation("self", "ARNE"));
297
        //ARNE packet in XML-format
298
        String contentValueData = "";
299
        for (int i = 0; i < value.length; i++)
300
        {
301
            contentValueData = contentValueData + "<byte id=\"" + (i+2) + "\" value=\"" + Integer.toString(value[i].shortValue()) + "\"/>";
302
        }      
303
        int arneBytes = value.length+1;
304
        p.setContents("<arnepacket bytes=\"" + arneBytes + "\" destnode=\"" + address +"\">" +
305
                "<byte id=\"1\" value=\"240\"/>" +
306
                contentValueData +
307
                "</arnepacket>");
308
        sendPacket(p);
309
    }
310
 
311
    /**
312
     * Sets the state of a room object (=lamp) by telling the RoomControl
313
     * node either to turn on or to turn off the specified output.
314
     * @param address
315
     * @param value object whose state you want to set (0 is first one).
316
     * @param state The new state of the object. ON=true, OFF=false.
317
     */
318
    private void setRoomObject(String address, UByte[] value, boolean state) {
319
        //create a packet and address it to the ARNE module
320
        MbPacket p = new MbPacket();
321
        p.setDestination(new MbLocation("self", "ARNE"));
322
        //ARNE packet in XML-format
323
        String contentValueData = "";
324
        for (int i = 0; i < value.length; i++)
325
        {
326
            contentValueData = contentValueData + "<byte id=\"" + (i+2) + "\" value=\"" + Integer.toString(value[i].shortValue()) + "\"/>";
327
        }      
328
        int arneBytes = value.length+1;
329
        p.setContents("<arnepacket bytes=\"" + arneBytes + "\" destnode=\"" + address + "\">" +
330
                "<byte id=\"1\" value=\"" + (state==true ? "01" : "02") + "\"/>" +
331
                contentValueData +
332
                "</arnepacket>");
333
        sendPacket(p);
334
    }
335
 
336
    /**
337
     * Will be called when our GUI should be shown.
338
     */
339
    public void renderGUI(Container drawArea) {
340
        gui.render(drawArea);
341
    }
342
 
343
    /**
344
     * A class for our GUI.
345
     */
346
    private class GUI implements ActionListener {
347
        private JButton[]   btnLampButtons;
348
 
349
        public void render(Container renderArea) {
350
            Iterator it = roomObjects.keySet().iterator();
351
            int i=0;
352
 
353
            while (it.hasNext()) {
354
                GenRoomObject o = (GenRoomObject)roomObjects.get(it.next());
355
                if (o!=null) {
356
                    if (o.displHTML) {
357
                        i++;
358
                    }
359
                }
360
            }
361
            if (i > 0) {
362
                renderArea.setLayout(new GridLayout(i, 1));
363
                btnLampButtons = new JButton[i];
364
                it = roomObjects.keySet().iterator();
365
                i=0;
366
                while (it.hasNext()) {
367
                    GenRoomObject o = (GenRoomObject)roomObjects.get(it.next());
368
                    if (o!=null) {
369
                        if (o.displHTML) {
370
                            btnLampButtons[i] = new JButton(o.name);
371
                            btnLampButtons[i].setActionCommand("roomobject:" + o.name);
372
                            btnLampButtons[i].addActionListener(this);
373
                            renderArea.add(btnLampButtons[i]);
374
                            i++;
375
                        }
376
                    }
377
                }
378
            }
379
        }
380
 
381
        public void actionPerformed(ActionEvent e) {
382
            //was this a room object-button press?
383
            if (e.getActionCommand().startsWith("roomobject:")) {
384
                //split its actioncommand to find out which lamp it was for
385
                String[] tokens = e.getActionCommand().split("roomobject:");
386
                //try to find a room object with this name
387
                GenRoomObject o = (GenRoomObject)roomObjects.get(tokens[1]);
388
                //if found
389
                if (o!=null) {
390
                    //toggle corresponding room object
391
                    toggleRoomObject(o.address, o.byteValue);
392
                }
393
            }
394
        }
395
    }
396
}