/* * This file is part of the Remote Sensor Actuator Interface (ReSAI). * * Copyright(c) Andreas Kipp, Frederic Siepmann * http://opensource.cit-ec.de/projects/resai * * This file may be licensed under the terms of of the * GNU Lesser General Public License Version 3 (the ``LGPL''), * or (at your option) any later version. * * Software distributed under the License is distributed * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either * express or implied. See the LGPL for the specific language * governing rights and limitations. * * You should have received a copy of the LGPL along with this * program. If not, go to http://www.gnu.org/licenses/lgpl.html * or write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The development of this software was supported by the * Excellence Cluster EXC 277 Cognitive Interaction Technology. * The Excellence Cluster EXC 277 is a grant of the Deutsche * Forschungsgemeinschaft (DFG) in the context of the German * Excellence Initiative. * */ /** * Main activity to control login and communication with ReSAI. * * @author akipp */ package de.unibi.airobots.resaidroid; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import de.unibi.airobots.resaidroid.communication.Communicator; import de.unibi.airobots.resaidroid.communication.XmppConnection; import de.unibi.airobots.resaidroid.constants.Constants.Commands; import de.unibi.airobots.resaidroid.constants.Constants.Properties; import de.unibi.airobots.resaidroid.constants.ReturnCodes; import de.unibi.airobots.resaidroid.constants.ServerConfig; import de.unibi.airobots.resaidroid.helper.EasyDialog; import de.unibi.airobots.resaidroid.helper.TimeConverter; public class ReSAIDroid extends Activity { private static final String TAG = "ReSAIDroid"; private FileInputStream fis; private FileOutputStream fos; private EditText txtServerIp; private EditText txtServerHostName; private EditText txtServerName; private EditText txtServerPort; private EditText txtLogin; private EditText txtPassword; private TextView lblStatus; private Button btnConnect; final Handler messageHandler = new Handler(); private Message mIn; private PacketListener packetListener; protected TabComponentMap cm; protected String component = ""; private Communicator com = new XmppConnection(); /** * Called when the activity is first created. Initialize the layout and * create listener for the buttons. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.startup); Resources res = getResources(); cm = new TabComponentMap(res); component = cm.getComponent(TAG); packetListener = new MyPacketListener(); txtServerIp = (EditText) findViewById(R.id.txtServerIp); txtServerHostName = (EditText) findViewById(R.id.txtServerHostName); txtServerName = (EditText) findViewById(R.id.txtServerName); txtServerPort = (EditText) findViewById(R.id.txtServerPort); txtLogin = (EditText) findViewById(R.id.txtLogin); txtPassword = (EditText) findViewById(R.id.txtPassword); lblStatus = (TextView) findViewById(R.id.lblStatus); readConfig(); btnConnect = (Button) findViewById(R.id.btnConnect); btnConnect.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setGUIAccess(false); EasyDialog.startProgressDialog(ReSAIDroid.this, "Connecting to Server"); writeConfig(); readConfig(); Log.i(TAG, "RECEIPIENT: " + ServerConfig.RECIPIENT_FULL); try { com.connect(txtServerIp.getText().toString(), Integer .parseInt(txtServerPort.getText() .toString())); Log.i(TAG, "Connected..."); com.login(txtLogin.getText().toString(), // + "@" + txtServerHostName.getText().toString(), txtPassword.getText().toString()); Log.i(TAG, "Logged in with " + txtLogin.getText().toString()); ServerConfig.RECIPIENT_FULL = txtServerName.getText() + "@" + txtServerHostName.getText(); if (com.isConnected() && com.isLoggedIn()) { addStatusMessage("Connected to XMPP Server."); EasyDialog .changeProgressDialogMessage("Creating PacketHandler"); createPacketHandler(); addStatusMessage("PacketHandler created."); connectToReSAI(); addStatusMessage("Connecting to ReSAI."); EasyDialog .changeProgressDialogMessage("Connecting to ReSAI"); } else { addStatusMessage("Not connected to XMPP Server."); EasyDialog.dismissProgressDialog(); setGUIAccess(true); } } catch (NumberFormatException e) { addStatusMessage("NumberFormatException: " + e.getMessage()); EasyDialog.dismissProgressDialog(); setGUIAccess(true); } } }); } @Override protected void onResume() { super.onResume(); if (com.isConnectedToReSAI()) { com.startBeacon(); Intent intent = new Intent(getApplicationContext(), TabManager.class); startActivityForResult(intent, 1); } else { setGUIAccess(true); } getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); removePacketHandler(); } @Override public void onBackPressed() { super.onBackPressed(); if (com.isConnected()) { com.disconnect(); } finish(); } /** * Handle return from tab activities. */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (resultCode) { case ReturnCodes.NOT_CONNECTED: addStatusMessage("Client seems to be disconnected."); EasyDialog.showInfoDialog(this, "Client seems to be disconnected."); setGUIAccess(true); break; case ReturnCodes.BACK_PRESSED: EasyDialog.showInfoDialog(this, "Back pressed, disconnecting."); addStatusMessage("Back pressed, disconnecting."); setGUIAccess(true); break; case Activity.RESULT_OK: addStatusMessage("Disconnected"); EasyDialog.showInfoDialog(this, "Successfully disconnected."); setGUIAccess(true); break; case ReturnCodes.SERVER_NOT_RESPONDING: addStatusMessage("Disconnected"); EasyDialog.showInfoDialog(this, "Server is not responding."); setGUIAccess(true); break; default: } } /** * Writes configuration parameters to the configuration file * */ private void writeConfig() { Log.i(TAG, "WRITING CONFIG..."); try { fos = openFileOutput(ServerConfig.CONFIGFILE, Context.MODE_PRIVATE); fos.write((Properties.SERVER_IP.name() + "=" + txtServerIp.getText().toString() + "\n").getBytes()); fos.write((Properties.SERVER_HOSTNAME.name() + "=" + txtServerHostName.getText().toString() + "\n").getBytes()); fos.write((Properties.SERVER_NAME.name() + "=" + txtServerName.getText().toString() + "\n").getBytes()); fos.write((Properties.SERVER_PORT.name() + "=" + txtServerPort.getText().toString() + "\n").getBytes()); fos.write((Properties.ACCOUNT.name() + "=" + txtLogin.getText().toString() + "\n").getBytes()); fos.write((Properties.PASSWORD.name() + "=" + txtPassword.getText().toString() + "\n").getBytes()); fos.close(); } catch (IOException e) { addStatusMessage("IOException: " + e.getMessage()); } Log.i(TAG, "WRITING CONFIG...done"); } /** * Reads the configuration file and fills the corresponding text boxes * */ private void readConfig() { Log.i(TAG, "read configuration from file..."); try { fis = openFileInput(ServerConfig.CONFIGFILE); byte[] byteArray = new byte[102400]; int bytesRead = 0; while ((bytesRead = fis.read(byteArray)) != -1) { String configLine = new String(byteArray, 0, bytesRead); String[] configLines = configLine.split("\n"); for (String singleLine : configLines) { String[] config = singleLine.split("="); if (config.length != 0) { if (config[0].equals(Properties.SERVER_IP.name())) txtServerIp.setText(config[1]); if (config[0].equals(Properties.SERVER_HOSTNAME.name())) txtServerHostName.setText(config[1]); if (config[0].equals(Properties.SERVER_NAME.name())) txtServerName.setText(config[1]); if (config[0].equals(Properties.SERVER_PORT.name())) txtServerPort.setText(config[1]); if (config[0].equals(Properties.ACCOUNT.name())) txtLogin.setText(config[1]); if (config[0].equals(Properties.PASSWORD.name())) txtPassword.setText(config[1]); } } ServerConfig.RECIPIENT = txtServerName.getText().toString(); ServerConfig.RECIPIENT_FULL = ServerConfig.RECIPIENT + "@" + ServerConfig.HOSTNAME; Log.i(TAG, "Created RECIPIENT_FULL: " + ServerConfig.RECIPIENT_FULL); return; } } catch (IOException e) { addStatusMessage("IOException: " + e.getMessage()); } Log.i(TAG, "SETTING DEFAULT VALUES..."); // SETTING DEFAULT VALUES txtServerIp.setText(ServerConfig.SERVERIP); txtServerHostName.setText(ServerConfig.HOSTNAME); txtServerName.setText(ServerConfig.RECIPIENT); txtServerPort.setText(String.valueOf(ServerConfig.SERVERPORT)); txtLogin.setText(ServerConfig.CLIENTNAME); txtPassword.setText(ServerConfig.CLIENTPASSWORD); ServerConfig.RECIPIENT_FULL = ServerConfig.RECIPIENT + "@" + ServerConfig.HOSTNAME; } /** * Send connect message to ReSAI server. */ private void connectToReSAI() { if (com.isConnected()) { Log.i(TAG, "SENDING SERVER REQUEST"); HashMap propertiesToSend = new HashMap(); propertiesToSend.put(Properties.CMD.name(), Commands.connect.name()); //TODO SERIALIZABLE propertiesToSend.put("TAG","ReSAIServerThread"); com.sendMessage(ServerConfig.RECIPIENT_FULL, propertiesToSend,"Calling ReSAI Server..."); Log.i(TAG, "SENDING SERVER REQUEST ...DONE"); messageHandler.removeCallbacks(ConnectionChecker); messageHandler.postDelayed(ConnectionChecker, 10000); } else { addStatusMessage("Not Connected to XMPP Server"); } } private void removePacketHandler() { com.removeListener(packetListener); } /** * Create a PacketHandler for receiving packets from ReSAI server. */ private void createPacketHandler() { PacketFilter filter = new PacketTypeFilter(Message.class); XmppConnection.addListener(packetListener, filter); } /** * Add a status message with timestamp. * * @param message * message to be added to lblStatus. */ private void addStatusMessage(String message) { if (message != null) { lblStatus.append("\n" + TimeConverter.toTime(System.currentTimeMillis()) + ": " + message); } } /** * Runnable that checks if ReSAI server answers to connection attempt. */ private Runnable ConnectionChecker = new Runnable() { public void run() { if (!com.isConnectedToReSAI()) { addStatusMessage("ReSAI not answering."); EasyDialog.showInfoDialog(ReSAIDroid.this, "ReSAI seems unreachable."); } EasyDialog.dismissProgressDialog(); setGUIAccess(true); } }; /** * Activate / Deactivate GUI elements on connecting * * @param access * true if elements can be changed */ private void setGUIAccess(boolean access) { btnConnect.setEnabled(access); txtServerIp.setEnabled(access); txtServerPort.setEnabled(access); txtLogin.setEnabled(access); txtPassword.setEnabled(access); txtServerHostName.setEnabled(access); txtServerName.setEnabled(access); } /** * Private class for implementing own PacketListener. * Only processes messages for a given TAG. * @author akipp * */ private class MyPacketListener implements PacketListener { public void processPacket(Packet packet) { if (packet instanceof Message) { Log.i(TAG,"PackageListener is RECEIVING Message"); mIn = (Message) packet; if (mIn.getProperty(Properties.CONNECTED.name()) != null) { if (mIn.getProperty(Properties.CONNECTED.name()) .equals("true")) { messageHandler.post(new Runnable() { public void run() { Log.i(TAG,"#### CONNECTED"); addStatusMessage("ReSAI connected"); com.setConnectedToReSAI(true); messageHandler .removeCallbacks(ConnectionChecker); EasyDialog.dismissProgressDialog(); Intent intent = new Intent( getApplicationContext(), TabManager.class); com.startBeacon(); startActivityForResult(intent, 1); } }); } else { Log.i(TAG,"### WRONG VALUE"); } } else { Log.i(TAG,"### NOT CONNECTED"); } } } } }