Subversion Repositories HomeAutomation

Rev

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

  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. }
  397.