// CIS 35 Java programming Thursday night class // Instructor: Dr. Khaja // Student: Isaac Cruz // Project: house alarm // // filename: alarm.java // // This project is an example of a house alarm, sensors are interface // through a microcontroller, then get sent to the serial port. It uses // java's comm api. // // This program demonstrates uses of SerialPort, InputStream, OutputStream, // TextFields, Buttons, Dialogs, Choice, Panels, Layouts, Drawings. // It also demonstrates uses of password field using asterisk to replace // typed characters. // // The blinking red/green dot on the screen shows that the computer is // polling the alarm hardware panel. This serves as the heartbeat of // the system. // // Future expansion will allow to dial a phone number and relay // a pre-recorded message over the phone in case of intrusion or fire. // import java.awt.*; // needed for graphics drawing import java.awt.event.*; // needed for button, serial, events import java.io.*; // needed for input/output to serial import javax.comm.*; // needed for serial port rs-232 //////////////////////////////////////////////////////////////// // class alarm, the main class of the whole program, see each // method for comments. //////////////////////////////////////////////////////////////// public class alarm extends FrameWithExit implements ActionListener, SerialPortEventListener { private SerialPort port; // serial port private CommPortIdentifier ID; // "COM 2" private InputStream in; // serial input stream private OutputStream out; // serial output stream private TextField tfFrontDoor = new TextField(10); private TextField tfGarageDoor = new TextField(10); private TextField tfBackDoor = new TextField(10); private TextField tfKitchenDoor = new TextField(10); private TextField tfEmailAddress = new TextField("djj@jps.net"); private TextField tfPassword = new TextField(); private String password = "joshua"; // current password private Choice choPhone_Contact = new Choice(); private Button btArmDisarm = new Button("Disarm"); private Button btReset = new Button("Reset"); private MessageDialog dialog; // dialog to tell if password is correct private boolean poll = true; private boolean open = false; // flag to mark if any door is open private boolean arm = false; // flag to mark if alarm is active private boolean buzzer_on = false; // flag to mark if buzzer is on private boolean ok_to_send = true; // flag to mark if ok to poll public static int active_byte = 0x41; // second byte to signal alarm ////////////////////////////////////////////////////////////////////// // alarm() - constructor for the class, do the following: // 1) creates panel to hold textfields, buttons, list, and labels // 2) added listener for buttons and serial port // 3) initialized serial port to 1200 baud, no parity, 8 databits // 1 stop bits, no flowcontrol, it also ask the serial port // to notify program if data is available on the serial port // 4) sends char 'G' to microcontroller initially, this signals // the microcrontroller to execute program at address 0x2000 // inside the microcontroller. ////////////////////////////////////////////////////////////////////// public alarm() { setTitle("House alarm demo"); // panel p1 to hold labels and text fields Panel p1 = new Panel(); p1.setLayout(new GridLayout(7,2)); // set text field to non editable tfFrontDoor.setEditable(false); tfGarageDoor.setEditable(false); tfBackDoor.setEditable(false); tfKitchenDoor.setEditable(false); // add labels and text fields to p p1.add(new Label("Front door")); p1.add(tfFrontDoor); p1.add(new Label("Garage door")); p1.add(tfGarageDoor); p1.add(new Label("Back door")); p1.add(tfBackDoor); p1.add(new Label("Kitchen door")); p1.add(tfKitchenDoor); p1.add(new Label("E-mail status to:")); p1.add(tfEmailAddress); p1.add(new Label("In case of alarm, dial:")); p1.add(choPhone_Contact); p1.add(new Label("Password to disarm:")); p1.add(tfPassword); tfPassword.setEchoChar('*'); // initialize choice items choPhone_Contact.add("Friends"); choPhone_Contact.add("Police"); choPhone_Contact.add("Fire Department"); choPhone_Contact.add("Alarm Company"); // panel for buttons Panel p2 = new Panel(); p2.setLayout(new FlowLayout()); p2.add(btArmDisarm); p2.add(btReset); // panel for instructions Panel p3 = new Panel(); p3.setLayout(new GridLayout(8,1)); p3.add(new Label("To set alarm active, press disarm button")); p3.add(new Label("To deactivate alarm, type password ")); p3.add(new Label("and press arm button.")); p3.add(new Label("Everytime the dot changes color,")); p3.add(new Label("it polls the alarm panel and serves as a")); p3.add(new Label("heartbeat of the system.")); p3.add(new Label(" ")); p3.add(new Label("Alarm demo by Isaac Cruz 12/15/99")); // set layout setLayout(new GridLayout(2,2)); // add panel, buttons, instructions to the frame add(p1); add(p2); add(p3); // register listener btArmDisarm.addActionListener(this); btReset.addActionListener(this); // create a dialog box dialog = new MessageDialog(this, "Error", true); // initial value for doors tfFrontDoor.setText("Close"); tfGarageDoor.setText("Close"); tfBackDoor.setText("Close"); tfKitchenDoor.setText("Close"); // setup serial port try { ID = CommPortIdentifier.getPortIdentifier("COM2"); port = (SerialPort) ID.open("alarm", 1000); in = port.getInputStream(); out = port.getOutputStream(); port.addEventListener(this); port.notifyOnDataAvailable(true); port.setSerialPortParams(1200, port.DATABITS_8, port.STOPBITS_1, port.PARITY_NONE); port.setFlowControlMode(port.FLOWCONTROL_NONE); } catch (Exception e) {} try { out.write(0x47); // send init symbol 'G' to microcontroller } catch (IOException e) {} } ////////////////////////////////////////////////////////////////////// // serialEvent() - gets called when data arrives at the serial port // it thens read the first byte and check if it is an 'S' meaning // synchronize byte, if it is then it reads the second byte, which is // the status of all sensors, whether they are open or closed. It // then called update_status passing parameter the data of the sensors ////////////////////////////////////////////////////////////////////// public void serialEvent(SerialPortEvent e) { int data = 0; switch(e.getEventType()) { case SerialPortEvent.DATA_AVAILABLE: try { while (in.available() > 0) { data = in.read(); if ('S' == (char) data) { data = in.read(); update_status(data); } } } catch (IOException ev) {} break; } }// end of alarm() constructor //////////////////////////////////////////////////////////////////////// // update_status(int s) - parameter s is the status of all the sensors // it isolates each bit and check if it is set or cleared, it then // updates each textfield of each door to open or close. It also checks // if the alarm is active and any door is open, if it is then it sets // the buzzer signal on (byte 0x4f). It updates the screen by calling // repaint, and set the flag to send char to microcontroller to true //////////////////////////////////////////////////////////////////////// public void update_status(int s) { int temp = s; open = false; // assume all doors close int sensor = temp & 0x01; // isolate bit 1 if (sensor == 0x01) tfFrontDoor.setText("Close"); else { tfFrontDoor.setText("Open"); open = true; } sensor = temp & 0x02; // isolate bit 2 if (sensor == 0x02) tfGarageDoor.setText("Close"); else { tfGarageDoor.setText("Open"); open = true; } sensor = temp & 0x04; if (sensor == 0x04) tfBackDoor.setText("Close"); else { tfBackDoor.setText("Open"); open = true; } sensor = temp & 0x08; if (sensor == 0x08) tfKitchenDoor.setText("Close"); else { tfKitchenDoor.setText("Open"); open = true; } if (!buzzer_on) { if (arm && open) buzzer_on = true; } if (buzzer_on) active_byte = 0x4f; // sound alarm else active_byte = 0x41; // any byte other than 0x4f repaint(); // draw blinking red/green circle for polling ok_to_send = true; // send synch byte to microcontroller } //////////////////////////////////////////////////////////////////////// // actionPerformed() - get the status of buttons // // button "Disarm" if clicked will set the alarm active and change // the label to "Arm". If clicked while alarm is active, will check // the password textfield and if match will make the alarm inactive. // // button "Reset" if clicked will check password textfield and if // match will make the alarm inactive. //////////////////////////////////////////////////////////////////////// public void actionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); if (e.getSource() instanceof Button) { if ("Arm".equals(actionCommand)) { if (password.equals(tfPassword.getText().trim())) { btArmDisarm.setLabel("Disarm"); tfPassword.setText(""); arm = false; buzzer_on = false; } else { dialog.setMessage("password does not match, alarm is active"); dialog.pack(); dialog.setVisible(true); arm = true; } } else if ("Disarm".equals(actionCommand)) { btArmDisarm.setLabel("Arm"); arm = true; } else if ("Reset".equals(actionCommand)) { if (password.equals(tfPassword.getText().trim())) { btArmDisarm.setLabel("Disarm"); tfPassword.setText(""); arm = false; buzzer_on = false; } else { dialog.setMessage("password does not match, alarm is active"); dialog.pack(); dialog.setVisible(true); arm = true; } } } } ////////////////////////////////////////////////////////////////////// // poll_alarm() - will write 2 bytes to microcontroller, the first // byte must be a 'S' (0x53) to signal synchronize byte, the second // byte will signal if buzzer will be on or off. Buzzer on (0x4f) // Buzzer off, any byte other than (0x4f). // This method will also set ok_to_send to false. ///////////////////////////////////////////////////////////////////// public void poll_alarm() { try { out.write(0x53); out.write(active_byte); ok_to_send = false; // wait until we receive data } catch (IOException e) {} } ////////////////////////////////////////////////////////////////////// // paint() - updates the dot to red/green color to signifies that the // program is communicating with the microcontroller. ////////////////////////////////////////////////////////////////////// public void paint(Graphics g) { poll = !poll; if(poll) g.setColor(Color.red); else g.setColor(Color.green); g.fillOval(400,300,15,15); } //////////////////////////////////////////////////////////////////////// // main() - creates a new object alarm // checks if ok to send, if it is then send 2 bytes to // the microcontroller. /////////////////////////////////////////////////////////////////////// public static void main(String[] args) { alarm f = new alarm(); f.setSize(500,500); f.setVisible(true); while(true) { if (f.ok_to_send) f.poll_alarm(); } } //////////////////////////////////////////////////////////////////////// // MessageDialog - class to create a dialog box, use to tell user if // password match or not, the user must click the ok // button to continue the program. //////////////////////////////////////////////////////////////////////// class MessageDialog extends Dialog implements ActionListener { private Label lblMessage; private Button btOk; public MessageDialog(Frame parent, String title, boolean modal) { super(parent, title, modal); // create panel to hold button Panel p = new Panel(); p.setLayout(new FlowLayout(FlowLayout.RIGHT)); p.add(btOk = new Button("Ok")); // place label and panel in dialog setLayout(new BorderLayout()); add("Center", lblMessage = new Label()); add("South", p); // register listener btOk.addActionListener(this); } // respond to button action public void actionPerformed(ActionEvent e) { setVisible(false); } public void setMessage(String message) { lblMessage.setText(message); } } }