Commit 16940052 authored by Andrey Filippov's avatar Andrey Filippov

initial commit

parents
Pipeline #1222 canceled with stages
.directory
/.settings
/.buildpath
/.project
/.classpath
project.properties
*.kate-swp
attic
bin
gen
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.elphel.sensorserver"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/sensor_server_icon"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SensorServer</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.source=1.6
Copy contents of this version-controlled directory to the project root
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:textSize="100sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SensorServer</string>
<string name="action_settings">Settings</string>
</resources>
/*
**
** MainActivity.java - top class of the SensorServer
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** MainActivity.java 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
package com.elphel.sensorserver;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import android.app.Activity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;
public class MainActivity extends Activity {
private static String TAG = "ServerSocket-MAIN";
private Server server = null;
private TextView text;
private SensorsUpdate sensorsUpdate = new SensorsUpdate(this);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sensorsUpdate.start();
server = new Server(this, sensorsUpdate);
setContentView(R.layout.activity_main);
server.start();
}
@Override
protected void onPause() {
super.onPause();
sensorsUpdate.pause();
if (server != null) {
server.stop();
server = null;
}
}
@Override
protected void onResume() {
super.onResume();
String ip = "???";
try {
WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
Log.i(TAG,"wifiInfo = " + wifiInfo.toString());
int ipInt = wifiInfo.getIpAddress();
Log.i(TAG,"wifiIP = " + String.format("0x%x", ipInt));
ip = InetAddress.getByAddress(
ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array())
.getHostAddress();
} catch (UnknownHostException e) {
Log.d(TAG,"UnknownHostException:" + e.getMessage());
} catch (Exception e1) {
Log.d(TAG,"Exception:" + e1.getMessage());
}
text = new TextView(this);
text.setText("Server WiFi address/port:\n"+ip+":"+server.getPort());
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30.0f);
setContentView(text);
sensorsUpdate.resume();
if (server == null) {
server = new Server(this, sensorsUpdate);
server.start();
}
}
}
/*
**
** SensorsUpdate.java - Update sesnors data to be served through embedded HTTP server
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** SensorsUpdate.java 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
package com.elphel.sensorserver;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
public class SensorsUpdate implements SensorEventListener{
private static String TAG = "SENSORS";
private final Activity activity;
private SensorManager sensorManager;
private final float[] accelerometerReading = new float[3];
private final float[] magnetometerReading = new float[3];
private final float[] rotationMatrix = new float[9];
// private final float[] orientationAngles = new float[3];
// private final float[] mMagnetometerReading = new float[3];
private final float[] mOrientationAngles = new float[3];
public SensorsUpdate (Activity activity) {
this.activity = activity;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
// Log.e(TAG,"onSensorChanged:" + event.toString());
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
System.arraycopy(event.values, 0, accelerometerReading,
0, accelerometerReading.length);
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
System.arraycopy(event.values, 0, magnetometerReading,
0, magnetometerReading.length);
}
}
public void start() {
sensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
Log.i(TAG,"start()");
}
public void resume() {
Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (accelerometer != null) {
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
Log.i(TAG,"accelerometer is NOT null");
} else {
Log.e(TAG,"accelerometer is null");
}
Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (magneticField != null) {
sensorManager.registerListener(this, magneticField,
SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
Log.i(TAG,"magneticField is NOT null");
} else {
Log.e(TAG,"magneticField is null");
}
Log.e(TAG,"resume() done");
}
public void pause() {
sensorManager.unregisterListener(this);
}
private void updateOrientationAngles() {
// Update rotation matrix, which is needed to update orientation angles.
Log.e(TAG,"updateOrientationAngles()");
SensorManager.getRotationMatrix(rotationMatrix, null,
//' accelerometerReading, mMagnetometerReading);
accelerometerReading, magnetometerReading);
// "mRotationMatrix" now has up-to-date information.
SensorManager.getOrientation(rotationMatrix, mOrientationAngles);
// "mOrientationAngles" now has up-to-date information.
}
public float [] getOrientation() {
updateOrientationAngles(); // todo: synchronize
return mOrientationAngles;
}
}
/*
**
** Server.java - Send sensor data using HTTP embedded server
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** Server.java 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
package com.elphel.sensorserver;
import java.io.BufferedReader;
import java.io.IOException;
//import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.IllegalBlockingModeException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.StringTokenizer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
public class Server {
private static String TAG = "ServerSocket";
private static int PORT = 8123;
private ServerSocket server = null;
private Runnable thconn;
// private final SensorsUpdate sensorsUpdate;
public Server (
final Activity activity,
final SensorsUpdate sensorsUpdate
) {
// this.sensorsUpdate = sensorsUpdate;
thconn = new Runnable() {
@Override
public void run() {
try {
server = new ServerSocket(PORT);
} catch (IOException e1) {
// TODO Auto-generated catch block
Log.d(TAG,"Failed to create ServerSocket on port " + PORT+", " + e1.toString());
return;
}
while (true) {
Socket clientSocket = null;
try {
clientSocket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
ArrayList<String> header = getHeader(reader);
Log.d(TAG,"header:\n" + header.toString());
HashMap<String,String> qmap = parseRequest(header);
if (qmap != null) {
Log.d(TAG,"qmap:\n" + qmap.toString());
} else {
Log.d(TAG,"Header parsing failed");
}
} catch (IOException e) {
Log.d(TAG,"IOException:" + e.getMessage());
return;
} catch (SecurityException e) {
Log.d(TAG,"SecurityException:" + e.getMessage());
return;
} catch (IllegalBlockingModeException e) {
Log.d(TAG,"IllegalBlockingModeException:" + e.getMessage());
return;
} catch (Exception e) {
Log.d(TAG,"Exception:" + e.toString());
return;
}
Log.d(TAG,"Request over");
float [] orientationAngles = sensorsUpdate.getOrientation();
// Date today = new Date();
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + // today+"\r\n"+
orientationDegreeXml(orientationAngles);
// String.format("<p>azimuth=%f</p>\r\n<p>pitch=%f</p>\r\n<p>roll=%f</p>\r\n",
// orientationAngles[0],orientationAngles[1],orientationAngles[2]);
try {
clientSocket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
Log.i(TAG,"Response sent:"+httpResponse.replace("\r"," ").replace("\n"," "));
} catch (UnsupportedEncodingException e) {
Log.d(TAG,"UnsupportedEncodingException:" + e.toString());
} catch (IOException e) {
Log.d(TAG,"IOException while sending request:" + e.toString());
}
try {
clientSocket.close();
} catch (IOException e) {
Log.d(TAG,"IOException while closing clientSocket:" + e.toString());
}
// Log.d(TAG,"Response done:"+httpResponse);
}
}
};
}
/**
* Reads request header from the socket
* @param reader BufferedReader of the socket
* @return AddayList<String> of the header lines
* @throws IOException
*/
private ArrayList<String> getHeader (BufferedReader reader) throws IOException {
ArrayList <String> header = new ArrayList<String>();
String line = reader.readLine();
while (!line.isEmpty()) {
header.add(line);
line = reader.readLine();
}
return header;
}
/**
* Parses request querry string fromthe header of the GET request
* @param header - request header as an ArrayList<String> of the header lines
* @return HashMap of strings:
* key == "?" - everything before the "?", starting with "/"
* other keys are passed parameters, value == "" if there is no "="
*/
private HashMap<String,String> parseRequest(ArrayList<String> header){
HashMap<String,String> qmap = new HashMap<String,String>();
for (String line:header) {
StringTokenizer tokens = new StringTokenizer(line, " ");
if ((tokens.countTokens() >=3 ) && (tokens.nextToken().equals("GET"))){
String querry = tokens.nextToken();
StringTokenizer qparts = new StringTokenizer(querry, "?");
qmap.put("?", qparts.nextToken());
if (qparts.hasMoreTokens()) {
String qstr = qparts.nextToken();
StringTokenizer pairs = new StringTokenizer(qstr, "&");
for (int i = pairs.countTokens(); i > 0; i--) {
StringTokenizer kv = new StringTokenizer(pairs.nextToken(), "=");
if (kv.countTokens()>0) {
String k = kv.nextToken();
String v = "";
if (kv.hasMoreTokens()) v = kv.nextToken();
qmap.put(k, v);
}
}
}
return qmap;
}
}
return null;
}
public void start() {
if (server == null) {
new Thread(thconn).start();
}
}
public void stop() {
if (server != null) {
try {
server.close();
server = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String orientationDegreeXml(float [] orientationAngles) {
float [] oad = new float[orientationAngles.length];
for (int i = 0; i < oad.length; i++) {
oad[i] = orientationAngles[i]*180/ (float)Math.PI;
}
return orientationXml(oad);
}
@SuppressLint("DefaultLocale")
private String orientationXml(float [] orientationAngles) {
return String.format(
"<?xml version=\"1.0\"?>\r\n"+
"<orientationAngles>\r\n"+
"<azimuth>%f</azimuth>\r\n"+
"<pitch>%f</pitch>\r\n"+
"<roll>%f</roll>\r\n"+
"<date>%s</date>\r\n"+
"</orientationAngles>\r\n",
orientationAngles[0],orientationAngles[1],orientationAngles[2], new Date());
}
public int getPort() {
return PORT;
}
/*
private SensorManager sensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrix(rotationMatrix, null,
accelerometerReading, magnetometerReading);
// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
SensorManager.getOrientation(rotationMatrix, orientationAngles);
*/
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment