Package it.cicolella.zway

Source Code of it.cicolella.zway.ZWay

/**
*
* Copyright (c) 2009-2013 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
package it.cicolella.zway;

import it.freedomotic.api.EventTemplate;
import it.freedomotic.api.Protocol;
import it.freedomotic.app.Freedomotic;
import it.freedomotic.events.ProtocolRead;
import it.freedomotic.exceptions.UnableToExecuteException;
import it.freedomotic.objects.EnvObjectLogic;
import it.freedomotic.objects.EnvObjectPersistence;
import it.freedomotic.reactions.Command;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.net.www.http.HttpClient;

/**
*
*
*/
public class ZWay extends Protocol {

    private static final Logger LOG = Logger.getLogger(ZWay.class.getName());
    Map<String, Board> devices = new HashMap<String, Board>();
    private static int BOARD_NUMBER = 1;
    private static int POLLING_TIME = 1000;
    private Socket socket = null;
    private DataOutputStream outputStream = null;
    private BufferedReader inputStream = null;
    private String[] address = null;
    private int SOCKET_TIMEOUT = configuration.getIntProperty("socket-timeout", 1000);
    private String SEND_COMMAND_URL = configuration.getStringProperty("send-command-url", "ZWaveAPI/Run");

    /**
     * Initializations
     */
    public ZWay() {
        super("ZWay", "/zway/zway-manifest.xml");
        setPollingWait(POLLING_TIME);
    }

    private void loadBoards() {
        if (devices == null) {
            devices = new HashMap<String, Board>();
        }
        setDescription("Reading status changes from"); //empty description
        for (int i = 0; i < BOARD_NUMBER; i++) {
            String ipToQuery;
            String autoConfiguration;
            String objectClass;
            String alias;
            int portToQuery;
            ipToQuery = configuration.getTuples().getStringProperty(i, "ip-to-query", "192.168.1.201");
            portToQuery = configuration.getTuples().getIntProperty(i, "port-to-query", 80);
            alias = configuration.getTuples().getStringProperty(i, "alias", "default");
            autoConfiguration = configuration.getTuples().getStringProperty(i, "auto-configuration", "false");
            objectClass = configuration.getTuples().getStringProperty(i, "object.class", "Light");
            Board board = new Board(ipToQuery, portToQuery, alias, autoConfiguration, objectClass);
            // add board object and its alias as key for the hashmap
            devices.put(alias, board);
            setDescription(getDescription() + " " + ipToQuery + ":" + portToQuery + ";");
        }
    }

    /**
     * Connection to boards
     */
    private boolean connect(String address, int port) {

        LOG.info("Trying to connect to ZWay board on address " + address + ':' + port);
        try {
            //TimedSocket is a non-blocking socket with timeout on exception
            socket = TimedSocket.getSocket(address, port, SOCKET_TIMEOUT);
            socket.setSoTimeout(SOCKET_TIMEOUT); //SOCKET_TIMEOUT ms of waiting on socket read/write
            BufferedOutputStream buffOut = new BufferedOutputStream(socket.getOutputStream());
            outputStream = new DataOutputStream(buffOut);
            return true;
        } catch (IOException e) {
            LOG.severe("Unable to connect to host " + address + " on port " + port + " " + e.toString());
            return false;
        }
    }

    private void disconnect() {
        // close streams and socket
        try {
            inputStream.close();
            outputStream.close();
            socket.close();
        } catch (Exception ex) {
            //do nothing. Best effort
        }
    }

    /**
     * Sensor side
     */
    @Override
    public void onStart() {
        super.onStart();
        POLLING_TIME = configuration.getIntProperty("polling-time", 1000);
        BOARD_NUMBER = configuration.getTuples().size();
        setPollingWait(POLLING_TIME);
        loadBoards();
    }

    @Override
    public void onStop() {
        super.onStop();
        //release resources
        devices.clear();
        devices = null;
        setPollingWait(-1); //disable polling
        //display the default description
        setDescription(configuration.getStringProperty("description", "ZWay"));
    }

    @Override
    protected void onRun() {
        Set<String> keySet = devices.keySet();
        String objectAddress;
        if (keySet.size() > 0) {
            for (String key : keySet) {
                try {
                    Board board = devices.get(key);
                    try {
                        // retrieve a list of configured objects with "zway" protocol
                        ArrayList<EnvObjectLogic> objectsList = EnvObjectPersistence.getObjectByProtocol("zway");
                        if (objectsList.size() > 0) {
                            for (Iterator it = objectsList.iterator(); it.hasNext();) {
                                EnvObjectLogic object = (EnvObjectLogic) it.next();
                                // read status for each object
                                readStatus(board, object);
                                System.out.println("Object address:" + object.getPojo().getPhisicalAddress() + " type:" + object.getPojo().getType());
                            }
                        }
                    } catch (MalformedURLException ex) {
                        Logger.getLogger(ZWay.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(ZWay.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } catch (UnableToExecuteException ex) {
                    Logger.getLogger(ZWay.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        try {
            Thread.sleep(POLLING_TIME);
        } catch (InterruptedException ex) {
            Logger.getLogger(ZWay.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Actuator side
     */
    @Override
    public void onCommand(Command c) throws UnableToExecuteException {
        //get connection paramentes address:port from received freedomotic command
        String delimiter = configuration.getProperty("address-delimiter");
        address = c.getProperty("address").split(delimiter); // in the format IP:PORT:ID:INSTANCE
        Board board = (Board) devices.get(address[0]);
        String ip_board = board.getIpAddress();
        int port_board = board.getPort();
        //connect to the ethernet board
        boolean connected = false;
        try {
            connected = connect(ip_board, port_board);
        } catch (ArrayIndexOutOfBoundsException outEx) {
            LOG.severe("The object address '" + c.getProperty("address") + "' is not properly formatted. Check it!");
            throw new UnableToExecuteException();
        } catch (NumberFormatException numberFormatException) {
            LOG.severe(port_board + " is not a valid ethernet port to connect to");
            throw new UnableToExecuteException();
        }
        if (connected) {
            String message = createCommandMessage(c);
            String expectedReply = c.getProperty("expected-reply");
            try {
                String reply = sendToBoard(message);
                if ((reply != null) && (!reply.equals(expectedReply))) {
                    //TODO: implement reply check
                }
            } catch (IOException iOException) {
                setDescription("Unable to send the message to host " + address[0] + " on port " + address[1]);
                LOG.severe("Unable to send the message to host " + address[0] + " on port " + address[1]);
                throw new UnableToExecuteException();
            } finally {
                disconnect();
            }
        } else {
            throw new UnableToExecuteException();
        }
    }

    public void readStatus(Board board, EnvObjectLogic object) throws UnableToExecuteException, MalformedURLException, IOException {

        String delimiter = configuration.getProperty("address-delimiter");
        String addressComponents[] = object.getPojo().getPhisicalAddress().split(delimiter);
        String deviceAddress = addressComponents[1];
        String deviceInstance = addressComponents[2];
        String objectType = addressComponents[3];
        String type[] = objectType.split(".");
       
        // sends an update status request .Get() method
        String path = "http://" + board.getIpAddress() + ":" + board.getPort() + "/" + SEND_COMMAND_URL + "/devices[" + deviceAddress + "].instances[" + deviceInstance + "]."
                + configuration.getProperty(objectType) + ".Get()";
        URL url = new URL(path);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.flush();
        wr.close();

        // reads a sensor value
        path = "http://" + board.getIpAddress() + ":" + board.getPort() + "/" + SEND_COMMAND_URL + "/devices[" + deviceAddress + "].instances[" + deviceInstance + "]."
                + configuration.getProperty(objectType);
        url = new URL(path);
        connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        wr = new DataOutputStream(connection.getOutputStream());
        wr.flush();
        wr.close();
        BufferedReader br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
        String output = null;
        String readValue = "";
        while ((output = br.readLine()) != null) {
            readValue += output;
        }
        System.out.println(Float.parseFloat(readValue));
        //building the event
        ProtocolRead event = new ProtocolRead(this, "zway", board.getAlias() + delimiter + deviceAddress + delimiter + deviceInstance + delimiter + objectType);
        //adding some optional information to the event
        event.addProperty("read.value", String.valueOf(Float.parseFloat(readValue)));
        event.addProperty("object.type", objectType);
        //publishes the event on the messaging bus
        this.notifyEvent(event);

        connection.disconnect();

    }

    private String sendToBoard(String message) throws IOException {
        String receivedReply = null;
        String line = null;
        if (outputStream != null) {
            outputStream.writeBytes(message);
            outputStream.flush();
            inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            try {
                while ((line = inputStream.readLine()) != null) {
                    receivedReply = receivedReply + line; // read device reply
                }
            } catch (IOException iOException) {
                throw new IOException();
            }
        }
        return receivedReply;
    }

    // create command message to send to the board
    // this part must be changed to reflect the board protocol
    public String createCommandMessage(Command c) {
        String message = null;
        String page = null;
        String command = null;
        Integer objectID = 0;
        Integer instanceID = 0;

        objectID = Integer.parseInt(address[1]);
        instanceID = Integer.parseInt(address[2]);
        command = c.getProperty("command");
        page = "/" + SEND_COMMAND_URL + "/" + "devices[" + objectID + "].instances[" + instanceID + "]." + command;

        // http request sending to the board
        message = "POST " + page + " HTTP/1.1\r\n\r\n";
        LOG.info("Sending " + message);
        //LOG.info("Unix timestamp " + getUnixTimeStamp() + "\n");
        return (message);
    }

    @Override
    protected boolean canExecute(Command c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void onEvent(EventTemplate event) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    // retrieve a key from value in the hashmap
    public static Object getKeyFromValue(Map hm, Object value) {
        for (Object o : hm.keySet()) {
            if (hm.get(o).equals(value)) {
                return o;
            }
        }
        return null;
    }

    private int getUnixTimeStamp() {
        Date date = new Date();
        int iTimeStamp = (int) (date.getTime() * .001);
        return iTimeStamp;
    }
}
TOP

Related Classes of it.cicolella.zway.ZWay

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.