package at.bakery.kippen.client.activity;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.concurrent.Semaphore;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.util.Log;
import at.bakery.kippen.common.AbstractData;
import at.bakery.kippen.common.json.JSONDataSerializer;
public class NetworkingTask extends Thread implements INetworking {
private Socket socket;
private OutputStream oos;
private AbstractData txPackets;
private Semaphore flush = new Semaphore(0);
private Semaphore wait = new Semaphore(1);
private String host;
private int port;
private String clientId;
private WifiManager wifiMan;
private WifiConfiguration wifiConf;
// singleton instance
private static NetworkingTask instance;
protected static void setup(String host, int port, WifiManager wifiMan, WifiConfiguration wifiConf) {
instance = new NetworkingTask(host, port, wifiMan, wifiConf);
}
public static NetworkingTask getInstance() {
if(instance == null) {
Log.e("KIPPEN", "It is likely that you failed setup IP and port, using default localhost:8080");
throw new RuntimeException("You forgot to properly setup the NetworkingTask! Call setup(...)!");
}
return instance;
}
private NetworkingTask(String host, int port, WifiManager wifiMan, WifiConfiguration wifiConf) {
this.host = host;
this.port = port;
this.wifiMan = wifiMan;
this.wifiConf = wifiConf;
}
@Override
public void sendPacket(AbstractData packets) {
try {
wait.acquire();
} catch (InterruptedException e) {}
this.txPackets = packets;
flush.release();
}
private boolean quit = false;
private void resetSocket() {
try {
socket.close();
} catch(Exception ex) {
Log.e("KIPPEN", "Failed to close socket, ignoring, but leaking");
} finally {
socket = null;
}
}
public void quit() {
quit = true;
resetSocket();
}
@Override
public void run() {
while(!quit) {
try {
Thread.sleep(10);
} catch(Exception ex) {}
try {
flush.acquire();
} catch (InterruptedException e1) {}
if(socket == null) {
try {
boolean wifiStatus = false;
wifiStatus = wifiMan.enableNetwork(wifiMan.addNetwork(wifiConf), true);
wifiStatus &= wifiMan.reconnect();
if(wifiStatus) {
// store the client id (MAC) for re-use
clientId = wifiMan.getConnectionInfo().getMacAddress();
socket = new Socket(InetAddress.getByName(host), port);
oos = socket.getOutputStream();
} else {
Log.e("KIPPEN", "The device was not able to connect to the host network. Please check your AP and client-side wifi configurations! Quit for now ...");
}
} catch (Exception ex) {
Log.e("KIPPEN", "Failed to open socket", ex);
resetSocket();
}
}
// send packets and reset TX
if(txPackets == null) continue;
try {
// set clientId
txPackets.setClientId(clientId);
txPackets.setTimestamp(System.currentTimeMillis());
// JSON serialize and send packet
byte[] serData = JSONDataSerializer.serialize(txPackets);
oos.write(serData);
Log.d("SENDING", "sent data " + txPackets);
} catch(Exception ex) {
Log.e("KIPPEN", "Failed to send packets", ex);
resetSocket();
}
wait.release();
}
}
}