/**
*
* Copyright (c) 2009-2016 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 com.freedomotic.plugins.devices.tcw122bcm;
import com.freedomotic.api.EventTemplate;
import com.freedomotic.api.Protocol;
import com.freedomotic.app.Freedomotic;
import com.freedomotic.events.ProtocolRead;
import com.freedomotic.exceptions.UnableToExecuteException;
import com.freedomotic.reactions.Command;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.codec.binary.Base64;
public class Tcw122bcm extends Protocol {
private static final Logger LOG = Logger.getLogger(Tcw122bcm.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 int SNMP_PORT = configuration.getIntProperty("snmp-port", 161);
private String SNMP_COMMUNITY = configuration.getStringProperty("snmp-community", "public");
private String SNMP_OID = configuration.getStringProperty("snmp-oid", "1.3.6.1.4.38783");
private String D1_VALUE = configuration.getStringProperty("digital-input1-value", "3.1.0");
private String D2_VALUE = configuration.getStringProperty("digital-input2-value", "3.2.0");
private String R1_STATE = configuration.getStringProperty("r1", "3.3.0");
private String R2_STATE = configuration.getStringProperty("r2", "3.5.0");
private String A1_VALUE = configuration.getStringProperty("analog-input1-value", "3.7.0");
private String A2_VALUE = configuration.getStringProperty("analog2-input2-value", "3.8.0");
private String T1_VALUE = configuration.getStringProperty("temperature1-value", "3.9.0");
private String T2_VALUE = configuration.getStringProperty("temperature2-value", "3.10.0");
private String H1_VALUE = configuration.getStringProperty("humidity1-value", "3.11.0");
private String H2_VALUE = configuration.getStringProperty("humidity2-value", "3.12.0");
private String HTTP_AUTHENTICATION = configuration.getStringProperty("http-authentication", "true");
private String USERNAME = configuration.getStringProperty("username", "admin");
private String PASSWORD = configuration.getStringProperty("password", "admin");
/**
* Initializations
*/
public Tcw122bcm() {
super("TCW122B-CM", "/tcw122bcm/tcw122bcm-manifest.xml");
setPollingWait(POLLING_TIME);
}
// load boards data from file manifest tcw122bcm.xml
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 alias;
String relayObjectTemplate;
String temperatureObjectTemplate;
String humidityObjectTemplate;
int portNumber;
alias = configuration.getTuples().getStringProperty(i, "alias", "default");
relayObjectTemplate = configuration.getTuples().getStringProperty(i, "relay-template", "light");
temperatureObjectTemplate = configuration.getTuples().getStringProperty(i, "temperature-template", "thermostat");
humidityObjectTemplate = configuration.getTuples().getStringProperty(i, "relay-humidity", "hygrometer");
ipToQuery = configuration.getTuples().getStringProperty(i, "ip-to-query", "192.168.1.201");
portNumber = configuration.getTuples().getIntProperty(i, "port-number", 80);
Board board = new Board(alias, ipToQuery, portNumber, "2000", "2000", "2000", "2000", "2000", "2000", "2000", "2000", "2000", "2000",
relayObjectTemplate, temperatureObjectTemplate, humidityObjectTemplate);
devices.put(alias, board);
setDescription(getDescription() + " " + ipToQuery);
}
}
/*
* Sensor side
*/
@Override
public void onStart() {
POLLING_TIME = configuration.getIntProperty("polling-time", 1000);
// number of configured boards in manifest file
BOARD_NUMBER = configuration.getTuples().size();
setPollingWait(POLLING_TIME);
loadBoards();
}
@Override
public void onStop() {
//release resources
devices.clear();
devices = null;
setPollingWait(-1); //disable polling
//display the default description
setDescription(configuration.getStringProperty("description", "TCW122B-CM"));
}
@Override
protected void onRun() {
Set keys = devices.keySet();
Iterator keyIter = keys.iterator();
while (keyIter.hasNext()) {
String alias = (String) keyIter.next();
Board board = (Board) devices.get(alias);
evaluateDiff(board);
}
try {
Thread.sleep(POLLING_TIME);
} catch (InterruptedException ex) {
Logger.getLogger(Tcw122bcm.class.getName()).log(Level.SEVERE, null, ex);
}
}
// }
private void sendEvent(String objectAddress, String eventProperty, String eventValue, String objectTemplate) {
ProtocolRead event = new ProtocolRead(this, "tcw122bcm", objectAddress);
event.addProperty(eventProperty, eventValue);
//publish the event on the messaging bus
this.notifyEvent(event);
}
// this method sends a Freedomotic event only if there is any change in input values or relays
// @param board
// board object to evaluate
// @return
// no value
private void evaluateDiff(Board board) {
//String address = board.getIpAddress() + ":" + board.getPortNumber();
//String address = board.getAlias();
String value = null;
MYSNMP snmpRequest = new MYSNMP();
//temperature1
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + T1_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getTemperature1())) {
sendEvent(address + ":T1", "sensor.temperature", value, board.getTemperatureObjectTemplate());
board.setTemperature1(value);
}
//temperature2
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + T2_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getTemperature2())) {
sendEvent(address + ":T2", "sensor.temperature", value, board.getTemperatureObjectTemplate());
board.setTemperature2(value);
}
//humidity1
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + H1_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getHumidity1())) {
sendEvent(address + ":H1", "sensor.humidity", value, board.getHumidityObjectTemplate());
board.setHumidity1(value);
}
//humidity2
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + H2_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getHumidity2())) {
sendEvent(address + ":H2", "sensor.humidity", value, board.getHumidityObjectTemplate());
board.setHumidity2(value);
}
//digital input 1
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + D1_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getDigitalInput1())) {
sendEvent(address + ":D1", "digital.input.value", value, "default");
board.setDigitalInput1(value);
}
//digital input 2
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + D2_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getDigitalInput2())) {
sendEvent(address + ":D2", "digital.input.value", value, "default");
board.setDigitalInput2(value);
}
//analog input 1
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + A1_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getAnalogInput1())) {
sendEvent(address + ":A1", "analog.input.value", value, "default");
board.setAnalogInput1(value);
}
//analog input 2
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + A2_VALUE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getAnalogInput2())) {
sendEvent(address + ":A2", "analog.input.value", value, "default");
board.setAnalogInput2(value);
}
//relay1 state
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + R1_STATE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getRelay1())) {
sendEvent(address + ":R1", "relay.state", value, board.getRelayObjectTemplate());
board.setRelay1(value);
}
//relay2 state
value = snmpRequest.SNMP_GET(board.getIpAddress(), SNMP_PORT, SNMP_OID + "." + R2_STATE, SNMP_COMMUNITY);
if (!value.equalsIgnoreCase(board.getRelay2())) {
sendEvent(address + ":R2", "relay.state", value, board.getRelayObjectTemplate());
board.setRelay2(value);
}
}
/**
* Actuator side
*/
@Override
public void onCommand(Command c) throws UnableToExecuteException {
String delimiter = configuration.getProperty("address-delimiter");
Integer control = 0;
address = c.getProperty("address").split(delimiter);
//retrieve the board handle from alias key
Board board = (Board) devices.get(address[0]);
String hostname = board.getIpAddress();
int hostport = board.getPortNumber();
String relay = address[1].toLowerCase();
//convert control
if (c.getProperty("control").equalsIgnoreCase("ON")) {
control = 1;
}
if (c.getProperty("control").equalsIgnoreCase("OFF")) {
control = 0;
}
// call the method for changing relay status
changeRelayStatus(hostname, hostport, relay, control);
}
// This method changes the relay status using http commands
// If set in the configuration file it uses the http authentication
// @param hostname
// TCW122B-CM ip address
// @param hostport
// TCW122B-CM tcp port (default value 80)
// @param relayNumber
// relay number - allowed values 1,2
// @param control
// action to perform - allowed value 0 (off), 1 (on)
// @return
// no value
private void changeRelayStatus(String hostname, int hostport, String relayNumber, int control) {
try {
String authString = USERNAME + ":" + PASSWORD;
//System.out.println("auth string: " + authString);
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
//System.out.println("Base64 encoded auth string: " + authStringEnc); //FOR DEBUG
//Create a URL for the desired page
URL url = new URL("http://" + hostname + ":" + hostport + "/?" + relayNumber + "=" + control);
LOG.info("Freedomotic sends the command " + url);
URLConnection urlConnection = url.openConnection();
// if required set the authentication
if (HTTP_AUTHENTICATION.equalsIgnoreCase("true")) {
urlConnection.setRequestProperty("Authorization", "Basic " + authStringEnc);
}
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
StringBuffer sb = new StringBuffer();
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
String result = sb.toString();
} catch (MalformedURLException e) {
LOG.severe("Change relay status malformed URL " + e.toString());
} catch (IOException e) {
LOG.severe("Change relay status IOexception" + e.toString());
}
}
@Override
protected boolean canExecute(Command c) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
protected void onEvent(EventTemplate event) {
throw new UnsupportedOperationException("Not supported yet.");
}
public static Object getKeyFromValue(Map hm, Object value) {
for (Object o : hm.keySet()) {
if (hm.get(o).equals(value)) {
return o;
}
}
return null;
}
}