Initial commit
This commit is contained in:
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# built application files
|
||||||
|
*.apk
|
||||||
|
*.ap_
|
||||||
|
|
||||||
|
# files for the dex VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Eclipse project files
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Intellij project files
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
50
AndroidManifest.xml
Normal file
50
AndroidManifest.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="ve.ucv.ciens.ccg.nxtcam"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="10"
|
||||||
|
android:targetSdkVersion="18" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.camera"
|
||||||
|
android:required="true" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
||||||
|
android:screenOrientation="landscape" >
|
||||||
|
<activity
|
||||||
|
android:name="ve.ucv.ciens.ccg.nxtcam.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>
|
||||||
|
<activity
|
||||||
|
android:name="ve.ucv.ciens.ccg.nxtcam.CamActivity"
|
||||||
|
android:label="@string/title_activity_cam"
|
||||||
|
android:parentActivityName="ve.ucv.ciens.ccg.nxtcam.MainActivity" >
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value="ve.ucv.ciens.ccg.nxtcam.MainActivity" />
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
BIN
ic_launcher-web.png
Normal file
BIN
ic_launcher-web.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
BIN
libs/android-support-v4.jar
Normal file
BIN
libs/android-support-v4.jar
Normal file
Binary file not shown.
20
proguard-project.txt
Normal file
20
proguard-project.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# 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 *;
|
||||||
|
#}
|
||||||
14
project.properties
Normal file
14
project.properties
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-18
|
||||||
BIN
res/drawable-hdpi/ic_launcher.png
Normal file
BIN
res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
BIN
res/drawable-mdpi/ic_launcher.png
Normal file
BIN
res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/drawable-xhdpi/ic_launcher.png
Normal file
BIN
res/drawable-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
BIN
res/drawable-xxhdpi/ic_launcher.png
Normal file
BIN
res/drawable-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
13
res/layout/activity_cam.xml
Normal file
13
res/layout/activity_cam.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
tools:context=".CamActivity" >
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
38
res/layout/activity_main.xml
Normal file
38
res/layout/activity_main.xml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
tools:context=".MainActivity" >
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/startButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:text="@string/start_button" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ipAddressField"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@+id/startButton"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:ems="10"
|
||||||
|
android:inputType="text" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignBaseline="@+id/ipAddressField"
|
||||||
|
android:layout_alignBottom="@+id/ipAddressField"
|
||||||
|
android:layout_toLeftOf="@+id/ipAddressField"
|
||||||
|
android:text="@string/ipAddressLabel" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
9
res/menu/cam.xml
Normal file
9
res/menu/cam.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/action_settings"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
9
res/menu/main.xml
Normal file
9
res/menu/main.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/action_settings"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
7
res/values-es/dimens.xml
Normal file
7
res/values-es/dimens.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
16
res/values-es/strings.xml
Normal file
16
res/values-es/strings.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">NxtCAM</string>
|
||||||
|
<string name="action_settings">Settings</string>
|
||||||
|
<string name="hello_world">Hello world!</string>
|
||||||
|
<string name="camera_success">Cámara abierta exitosamente</string>
|
||||||
|
<string name="camera_failure">La cámara no pudo abrirse</string>
|
||||||
|
<string name="get_server_button">Conectar con NxtAR</string>
|
||||||
|
<string name="start_button">Encender cámara</string>
|
||||||
|
<string name="title_activity_cam">CamActivity</string>
|
||||||
|
<string name="ipAddressLabel">Dirección IP de NxtAR</string>
|
||||||
|
<string name="badIpToast">La dirección IP no es válida</string>
|
||||||
|
<string name="emptyIpToast">Rellene el campo de dirección IP</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
20
res/values-es/styles.xml
Normal file
20
res/values-es/styles.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||||
|
<!--
|
||||||
|
Theme customizations available in newer API levels can go in
|
||||||
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Application theme. -->
|
||||||
|
<style name="AppTheme" parent="AppBaseTheme">
|
||||||
|
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
8
res/values-sw600dp/dimens.xml
Normal file
8
res/values-sw600dp/dimens.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||||
|
screen margins) for sw600dp devices (e.g. 7" tablets) here.
|
||||||
|
-->
|
||||||
|
|
||||||
|
</resources>
|
||||||
9
res/values-sw720dp-land/dimens.xml
Normal file
9
res/values-sw720dp-land/dimens.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||||
|
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
|
||||||
|
-->
|
||||||
|
<dimen name="activity_horizontal_margin">128dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
11
res/values-v11/styles.xml
Normal file
11
res/values-v11/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 11+. This theme completely replaces
|
||||||
|
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||||
|
<!-- API 11 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
12
res/values-v14/styles.xml
Normal file
12
res/values-v14/styles.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 14+. This theme completely replaces
|
||||||
|
AppBaseTheme from BOTH res/values/styles.xml and
|
||||||
|
res/values-v11/styles.xml on API 14+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||||
|
<!-- API 14 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
7
res/values/dimens.xml
Normal file
7
res/values/dimens.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
16
res/values/strings.xml
Normal file
16
res/values/strings.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">NxtCAM</string>
|
||||||
|
<string name="action_settings">Settings</string>
|
||||||
|
<string name="hello_world">Hello world!</string>
|
||||||
|
<string name="camera_success">Camera successfully opened</string>
|
||||||
|
<string name="camera_failure">Camera could not be opened</string>
|
||||||
|
<string name="title_activity_cam">CamActivity</string>
|
||||||
|
<string name="get_server_button">Connect with NxtAR</string>
|
||||||
|
<string name="start_button">Start camera</string>
|
||||||
|
<string name="ipAddressLabel">NxtAR IP Address</string>
|
||||||
|
<string name="badIpToast">Invalid IP address</string>
|
||||||
|
<string name="emptyIpToast">Fill out the IP address field</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
20
res/values/styles.xml
Normal file
20
res/values/styles.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||||
|
<!--
|
||||||
|
Theme customizations available in newer API levels can go in
|
||||||
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Application theme. -->
|
||||||
|
<style name="AppTheme" parent="AppBaseTheme">
|
||||||
|
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
129
src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java
Normal file
129
src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam;
|
||||||
|
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.camera.CameraPreview;
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.network.ImageTransferThread;
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.NavUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class CamActivity extends Activity{
|
||||||
|
private final String TAG = "NXTCAM_CAM";
|
||||||
|
private final String CLASS_NAME = MainActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private Camera hwCamera;
|
||||||
|
private CameraPreview cPreview;
|
||||||
|
private CameraSetupTask camSetupTask;
|
||||||
|
private ImageTransferThread imThread;
|
||||||
|
|
||||||
|
/*******************
|
||||||
|
* Android methods *
|
||||||
|
*******************/
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
|
cPreview = new CameraPreview(this, hwCamera);
|
||||||
|
setContentView(cPreview);
|
||||||
|
|
||||||
|
imThread = new ImageTransferThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.cam, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
// This ID represents the Home or Up button. In the case of this
|
||||||
|
// activity, the Up button is shown. Use NavUtils to allow users
|
||||||
|
// to navigate up one level in the application structure. For
|
||||||
|
// more details, see the Navigation pattern on Android Design:
|
||||||
|
//
|
||||||
|
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
|
||||||
|
//
|
||||||
|
NavUtils.navigateUpFromSameTask(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(){
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
camSetupTask = new CameraSetupTask();
|
||||||
|
camSetupTask.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause(){
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
cPreview.removePreviewCallback();
|
||||||
|
cPreview.setCamera(null);
|
||||||
|
releaseCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* My own methods *
|
||||||
|
******************/
|
||||||
|
public void startCameraPreview(){
|
||||||
|
if(hwCamera != null){
|
||||||
|
cPreview.setCamera(hwCamera);
|
||||||
|
}else{
|
||||||
|
Log.wtf(TAG, CLASS_NAME + ".startCameraPreview() :: CAMERA IS NULL!");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseCamera(){
|
||||||
|
if(hwCamera != null){
|
||||||
|
hwCamera.release();
|
||||||
|
hwCamera = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CameraSetupTask extends AsyncTask<Void, Void, Camera>{
|
||||||
|
private final String CLASS_NAME = CameraSetupTask.class.getSimpleName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Camera doInBackground(Void... params) {
|
||||||
|
Camera cam = null;
|
||||||
|
try{
|
||||||
|
cam = Camera.open(0);
|
||||||
|
}catch(Exception e){
|
||||||
|
if(ProjectConstants.DEBUG) Log.e(TAG, CLASS_NAME + ".doInBackground() :: Failed to open the camera.");
|
||||||
|
}
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Camera result) {
|
||||||
|
hwCamera = result;
|
||||||
|
if(result != null){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPostExecute() :: Camera successfully opened");
|
||||||
|
}else{
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPostExecute() :: Camera open failed on background task.");
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.camera_failure, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
startCameraPreview();
|
||||||
|
|
||||||
|
super.onPostExecute(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
131
src/ve/ucv/ciens/ccg/nxtcam/MainActivity.java
Normal file
131
src/ve/ucv/ciens/ccg/nxtcam/MainActivity.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class MainActivity extends Activity {
|
||||||
|
private final String TAG = "NXTCAM_MAIN";
|
||||||
|
private final String CLASS_NAME = MainActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private Button startButton;
|
||||||
|
private TextView ipField;
|
||||||
|
|
||||||
|
private WifiManager wifiManager;
|
||||||
|
private boolean wifiOnByMe;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
startButton = (Button)findViewById(R.id.startButton);
|
||||||
|
startButton.setOnClickListener(startClickListener);
|
||||||
|
|
||||||
|
ipField = (TextView)findViewById(R.id.ipAddressField);
|
||||||
|
|
||||||
|
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
||||||
|
|
||||||
|
if(!wifiManager.isWifiEnabled()) setWifi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(){
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
if(!wifiManager.isWifiEnabled()) setWifi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause(){
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
if(wifiManager.isWifiEnabled() && wifiOnByMe) setWifi(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy(){
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
if(wifiManager.isWifiEnabled() && wifiOnByMe) wifiManager.setWifiEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.main, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startCamActivity(boolean canStart){
|
||||||
|
if(canStart){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".startCamActivity() :: Launching camera activity.");
|
||||||
|
Intent intent = new Intent(this, CamActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}else{
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".startCamActivity() :: Cannot launch camera activity.");
|
||||||
|
Toast.makeText(this, R.string.badIpToast, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setWifi(boolean on){
|
||||||
|
wifiManager.setWifiEnabled(on);
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".ImageTransferThread() :: setting wifi to " + (on ? "on" : "off"));
|
||||||
|
if(on)
|
||||||
|
wifiOnByMe = true;
|
||||||
|
else
|
||||||
|
wifiOnByMe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateIpAddress(){
|
||||||
|
if(ipField.getText().toString().compareTo("") != 0){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "validateIpAddress() :: Launching verification task.");
|
||||||
|
VerifyIpAddressTask verifyIp = new VerifyIpAddressTask();
|
||||||
|
verifyIp.execute(ipField.getText().toString());
|
||||||
|
}else{
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "validateIpAddress() :: Ip address field is empty.");
|
||||||
|
Toast.makeText(this, R.string.emptyIpToast, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final View.OnClickListener startClickListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
validateIpAddress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private class VerifyIpAddressTask extends AsyncTask<String, Void, Boolean>{
|
||||||
|
private final String CLASS_NAME = VerifyIpAddressTask.class.getSimpleName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(String... params) {
|
||||||
|
try{
|
||||||
|
InetAddress.getByName(params[0]);
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "doInBackground() :: IP address is valid.");
|
||||||
|
return true;
|
||||||
|
}catch(UnknownHostException uh){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "doInBackground() :: IP address is not valid.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
startCamActivity(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
54
src/ve/ucv/ciens/ccg/nxtcam/camera/CameraImageMonitor.java
Normal file
54
src/ve/ucv/ciens/ccg/nxtcam/camera/CameraImageMonitor.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.camera;
|
||||||
|
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||||
|
|
||||||
|
public class CameraImageMonitor{
|
||||||
|
private final String TAG = "CAM_MONITOR";
|
||||||
|
private final String CLASS_NAME = CameraImageMonitor.class.getSimpleName();
|
||||||
|
|
||||||
|
private byte[] image;
|
||||||
|
private boolean imgChanged;
|
||||||
|
|
||||||
|
private CameraImageMonitor(){
|
||||||
|
imgChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder{
|
||||||
|
public static final CameraImageMonitor INSTANCE = new CameraImageMonitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CameraImageMonitor getInstance(){
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageData(byte[] image){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".setImageData() :: Copying new image.");
|
||||||
|
synchronized(image){
|
||||||
|
this.image = new byte[image.length];
|
||||||
|
System.arraycopy(image, 0, this.image, 0, image.length);
|
||||||
|
imgChanged = true;
|
||||||
|
image.notifyAll();
|
||||||
|
}
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".setImageData() :: Data copy finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getImageData(){
|
||||||
|
byte[] returnImg;
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Entry point.");
|
||||||
|
synchronized(image){
|
||||||
|
while(!imgChanged){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Waiting for new data.");
|
||||||
|
try{ image.wait(); }catch(InterruptedException ie){}
|
||||||
|
}
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Retrieving new data.");
|
||||||
|
returnImg = image.clone();
|
||||||
|
imgChanged = false;
|
||||||
|
}
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: New data retreived.");
|
||||||
|
return returnImg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean hasChanged(){
|
||||||
|
return imgChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
205
src/ve/ucv/ciens/ccg/nxtcam/camera/CameraPreview.java
Normal file
205
src/ve/ucv/ciens/ccg/nxtcam/camera/CameraPreview.java
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.camera;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.hardware.Camera.Size;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
/** A basic Camera preview class */
|
||||||
|
@SuppressLint("ViewConstructor")
|
||||||
|
public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback, Camera.PreviewCallback {
|
||||||
|
private final String TAG = "SURFVIEW";
|
||||||
|
private final String CLASS_NAME = CameraPreview.class.getSimpleName();
|
||||||
|
|
||||||
|
private Size mPreviewSize;
|
||||||
|
private List<Size> mSupportedPreviewSizes;
|
||||||
|
private CameraImageMonitor camMonitor;
|
||||||
|
private Activity parentActivity;
|
||||||
|
private SurfaceView mSurfaceView;
|
||||||
|
private SurfaceHolder mHolder;
|
||||||
|
private Camera mCamera;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public CameraPreview(Context context, Camera camera){
|
||||||
|
super(context);
|
||||||
|
parentActivity = (Activity)context;
|
||||||
|
|
||||||
|
mSurfaceView = new SurfaceView(context);
|
||||||
|
mHolder = mSurfaceView.getHolder();
|
||||||
|
mHolder.addCallback(this);
|
||||||
|
|
||||||
|
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCamera(Camera camera){
|
||||||
|
mCamera = camera;
|
||||||
|
if(mCamera != null){
|
||||||
|
camMonitor = CameraImageMonitor.getInstance();
|
||||||
|
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void surfaceCreated(SurfaceHolder holder){
|
||||||
|
// The Surface has been created, now tell the camera where to draw the preview.
|
||||||
|
try {
|
||||||
|
if(mCamera != null){
|
||||||
|
mCamera.setPreviewDisplay(holder);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, "Error setting camera preview: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void surfaceDestroyed(SurfaceHolder holder){
|
||||||
|
if(mCamera != null){
|
||||||
|
mCamera.stopPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
|
||||||
|
if(mHolder.getSurface() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
mCamera.stopPreview();
|
||||||
|
}catch (Exception e){ }
|
||||||
|
|
||||||
|
requestLayout();
|
||||||
|
|
||||||
|
Camera.Parameters camParams = mCamera.getParameters();
|
||||||
|
/*Size optimal = getOptimalPreviewSize(camParams.getSupportedPreviewSizes(), w, h);
|
||||||
|
if(ProjectConstants.DEBUG)
|
||||||
|
Log.d(TAG, CLASS_NAME + ".surfaceChanged() :: Preview size set at (" + optimal.width + ", " + optimal.height + ")");*/
|
||||||
|
camParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
|
||||||
|
mCamera.setParameters(camParams);
|
||||||
|
|
||||||
|
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||||
|
android.hardware.Camera.getCameraInfo(0, info);
|
||||||
|
int rotation = parentActivity.getWindowManager().getDefaultDisplay().getRotation();
|
||||||
|
|
||||||
|
int degrees = 0;
|
||||||
|
switch (rotation) {
|
||||||
|
case Surface.ROTATION_0: degrees = 0; break;
|
||||||
|
case Surface.ROTATION_90: degrees = 90; break;
|
||||||
|
case Surface.ROTATION_180: degrees = 180; break;
|
||||||
|
case Surface.ROTATION_270: degrees = 270; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||||
|
result = (info.orientation + degrees) % 360;
|
||||||
|
result = (360 - result) % 360; // compensate the mirror
|
||||||
|
} else { // back-facing
|
||||||
|
result = (info.orientation - degrees + 360) % 360;
|
||||||
|
}
|
||||||
|
mCamera.setDisplayOrientation(result);
|
||||||
|
|
||||||
|
mCamera.setPreviewCallback(this);
|
||||||
|
|
||||||
|
try {
|
||||||
|
mCamera.setPreviewDisplay(mHolder);
|
||||||
|
mCamera.startPreview();
|
||||||
|
|
||||||
|
}catch (Exception e){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".surfaceChanged() :: Error starting camera preview: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreviewFrame(byte[] data, Camera camera){
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPreviewFrame() :: Preview received");
|
||||||
|
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPreviewFrame() :: Frame has" + (camMonitor.hasChanged() ? "" : " not") + " changed.");
|
||||||
|
if(!camMonitor.hasChanged())
|
||||||
|
camMonitor.setImageData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePreviewCallback(){
|
||||||
|
mCamera.setPreviewCallback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
|
||||||
|
final double ASPECT_TOLERANCE = 0.1;
|
||||||
|
double targetRatio = (double) w / h;
|
||||||
|
if (sizes == null) return null;
|
||||||
|
|
||||||
|
Size optimalSize = null;
|
||||||
|
double minDiff = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
int targetHeight = h;
|
||||||
|
|
||||||
|
// Try to find an size match aspect ratio and size
|
||||||
|
for (Size size : sizes) {
|
||||||
|
double ratio = (double) size.width / size.height;
|
||||||
|
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
|
||||||
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||||
|
optimalSize = size;
|
||||||
|
minDiff = Math.abs(size.height - targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot find the one match the aspect ratio, ignore the requirement
|
||||||
|
if (optimalSize == null) {
|
||||||
|
minDiff = Double.MAX_VALUE;
|
||||||
|
for (Size size : sizes) {
|
||||||
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||||
|
optimalSize = size;
|
||||||
|
minDiff = Math.abs(size.height - targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optimalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||||
|
if (changed && getChildCount() > 0) {
|
||||||
|
final View child = getChildAt(0);
|
||||||
|
|
||||||
|
final int width = r - l;
|
||||||
|
final int height = b - t;
|
||||||
|
|
||||||
|
int previewWidth = width;
|
||||||
|
int previewHeight = height;
|
||||||
|
if (mPreviewSize != null) {
|
||||||
|
previewWidth = mPreviewSize.width;
|
||||||
|
previewHeight = mPreviewSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center the child SurfaceView within the parent.
|
||||||
|
if (width * previewHeight > height * previewWidth) {
|
||||||
|
final int scaledChildWidth = previewWidth * height / previewHeight;
|
||||||
|
child.layout((width - scaledChildWidth) / 2, 0,
|
||||||
|
(width + scaledChildWidth) / 2, height);
|
||||||
|
} else {
|
||||||
|
final int scaledChildHeight = previewHeight * width / previewWidth;
|
||||||
|
child.layout(0, (height - scaledChildHeight) / 2,
|
||||||
|
width, (height + scaledChildHeight) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
|
||||||
|
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
|
||||||
|
if (mSupportedPreviewSizes != null) {
|
||||||
|
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
191
src/ve/ucv/ciens/ccg/nxtcam/network/BluetoothManager.java
Normal file
191
src/ve/ucv/ciens/ccg/nxtcam/network/BluetoothManager.java
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothSocket;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class BluetoothManager{
|
||||||
|
private static final UUID SERIAL_PORT_SERVICE_CLASS_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||||
|
private static final String OUI_LEGO = "00:16:53";
|
||||||
|
private static final String TAG = "BTMNGR";
|
||||||
|
|
||||||
|
private boolean connected;
|
||||||
|
private BluetoothAdapter bt_adapter;
|
||||||
|
private BluetoothSocket bt_socket = null;
|
||||||
|
private OutputStream nxt_out_stream = null;
|
||||||
|
private InputStream nxt_in_stream = null;
|
||||||
|
|
||||||
|
private static class SingletonHolder{
|
||||||
|
public static final BluetoothManager INSTANCE = new BluetoothManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BluetoothManager(){
|
||||||
|
connected = false;
|
||||||
|
bt_adapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
bt_socket = null;
|
||||||
|
nxt_in_stream = null;
|
||||||
|
nxt_out_stream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BluetoothManager getInstance(){
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBTSupported(){
|
||||||
|
return bt_adapter != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected(){
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBTEnabled(){
|
||||||
|
return bt_adapter.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableBT(){
|
||||||
|
bt_adapter.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<BluetoothDevice> getPairedDevices(){
|
||||||
|
return bt_adapter.getBondedDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a connection with a NXT device.
|
||||||
|
*
|
||||||
|
* Verifies if the target device is a valid NXT robot by checking agains Lego's OUI.
|
||||||
|
* Also creates the socket and the streams associated with the connection
|
||||||
|
*
|
||||||
|
* @param mac_address The mac address of the target device.
|
||||||
|
* @return true if the connection was established succesfully, otherwise false.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public boolean establishConnection(String mac_address) throws IOException{
|
||||||
|
if (!bt_adapter.isEnabled()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(connected){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(bt_adapter.isEnabled()){
|
||||||
|
if(mac_address == "NONE"){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
if(mac_address.substring(0, 8).compareTo(OUI_LEGO) != 0){
|
||||||
|
Log.d(TAG, "establishConnection() :: Not a Lego MAC. Prefix : " + mac_address.substring(0, 8) + " :: OUI : " + OUI_LEGO);
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
try{
|
||||||
|
Log.d(TAG, "establishConnection() :: Getting device with mac address: " + mac_address);
|
||||||
|
BluetoothDevice nxtDevice = null;
|
||||||
|
nxtDevice = bt_adapter.getRemoteDevice(mac_address);
|
||||||
|
if (nxtDevice == null) {
|
||||||
|
Log.e(TAG, "establishConnection() :: No device found.");
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "establishConnection() :: Opening socket.");
|
||||||
|
bt_socket = nxtDevice.createRfcommSocketToServiceRecord(SERIAL_PORT_SERVICE_CLASS_UUID);
|
||||||
|
Log.d(TAG, "establishConnection() :: Connecting.");
|
||||||
|
bt_socket.connect();
|
||||||
|
|
||||||
|
Log.d(TAG, "establishConnection() :: Opening IO streams.");
|
||||||
|
nxt_in_stream = bt_socket.getInputStream();
|
||||||
|
nxt_out_stream = bt_socket.getOutputStream();
|
||||||
|
|
||||||
|
Log.d(TAG, "establishConnection() :: Connection established.");
|
||||||
|
connected = true;
|
||||||
|
|
||||||
|
}catch(IOException e){
|
||||||
|
Log.e(TAG, "establishConnection() :: Connection failed.");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
connected = false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the active connection if any.
|
||||||
|
*
|
||||||
|
* Additionally clears the socket and the streams associated to said connection.
|
||||||
|
*
|
||||||
|
* @return true if the connection was succesfully closed; false if no connection exists.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public boolean stopConnection() throws IOException{
|
||||||
|
try{
|
||||||
|
if(bt_socket != null){
|
||||||
|
Log.d(TAG, "stopConnection() :: Closing connection.");
|
||||||
|
bt_socket.close();
|
||||||
|
bt_socket = null;
|
||||||
|
nxt_in_stream = null;
|
||||||
|
nxt_out_stream = null;
|
||||||
|
connected = false;
|
||||||
|
Log.d(TAG, "stopConnection() :: Connection closed.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}catch( IOException e){
|
||||||
|
Log.e(TAG, "stopConnection()");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to the NXT robot.
|
||||||
|
*
|
||||||
|
* @param message The data to be sent.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public synchronized void writeMessage(byte[] message) throws IOException{
|
||||||
|
if(connected){
|
||||||
|
try{
|
||||||
|
nxt_out_stream.write(message);
|
||||||
|
nxt_out_stream.flush();
|
||||||
|
}catch(IOException e){
|
||||||
|
Log.e(TAG, "writeMessage()");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a message sent by the NXT robot.
|
||||||
|
*
|
||||||
|
* @return The data received as a byte[] if a valid connection exists, otherwise null.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public synchronized byte[] readMessage(int bytes) throws IOException{
|
||||||
|
if(connected){
|
||||||
|
try{
|
||||||
|
byte[] message = new byte[bytes];
|
||||||
|
for(int i = 0; i < message.length; ++i){
|
||||||
|
message[i] = 0x00;
|
||||||
|
}
|
||||||
|
nxt_in_stream.read(message, 0, bytes);
|
||||||
|
return message;
|
||||||
|
}catch(IOException e){
|
||||||
|
Log.e(TAG, "readMessage()");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
95
src/ve/ucv/ciens/ccg/nxtcam/network/ImageTransferThread.java
Normal file
95
src/ve/ucv/ciens/ccg/nxtcam/network/ImageTransferThread.java
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.camera.CameraImageMonitor;
|
||||||
|
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class ImageTransferThread extends Thread{
|
||||||
|
|
||||||
|
private final String TAG = "IM_THREAD";
|
||||||
|
private final String CLASS_NAME = ImageTransferThread.class.getSimpleName();
|
||||||
|
|
||||||
|
private boolean pause, done, connected;
|
||||||
|
private Object threadPauseMonitor;
|
||||||
|
private CameraImageMonitor camMonitor;
|
||||||
|
private Socket socket;
|
||||||
|
private BufferedWriter writer;
|
||||||
|
private BufferedReader reader;
|
||||||
|
private byte[] image;
|
||||||
|
|
||||||
|
public ImageTransferThread(){
|
||||||
|
pause = false;
|
||||||
|
done = false;
|
||||||
|
connected = false;
|
||||||
|
threadPauseMonitor = new Object();
|
||||||
|
socket = null;
|
||||||
|
writer = null;
|
||||||
|
reader = null;
|
||||||
|
camMonitor = CameraImageMonitor.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(){
|
||||||
|
if(!connected){
|
||||||
|
Log.e(TAG, CLASS_NAME + ".run() :: Not connected to a server. Finishing thread.");
|
||||||
|
}else{
|
||||||
|
while(!done){
|
||||||
|
checkPause();
|
||||||
|
image = camMonitor.getImageData();
|
||||||
|
// TODO: implement image transfer protocol.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connectToServer(String serverIp){
|
||||||
|
try{
|
||||||
|
if(ProjectConstants.DEBUG) Log.i(TAG, CLASS_NAME + ".connectToServer() :: Connecting to the server at " + serverIp);
|
||||||
|
socket = new Socket(InetAddress.getByName(serverIp), ProjectConstants.SERVER_TCP_PORT_1);
|
||||||
|
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||||
|
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
|
connected = true;
|
||||||
|
if(ProjectConstants.DEBUG) Log.i(TAG, CLASS_NAME + ".connectToServer() :: Connection successful.");
|
||||||
|
}catch(IOException io){
|
||||||
|
Log.e(TAG, CLASS_NAME + ".connectToServer() :: Connection failed with message: " + io.getMessage());
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void finish(){
|
||||||
|
done = true;
|
||||||
|
if(ProjectConstants.DEBUG) Log.i(TAG, CLASS_NAME + ".finish() :: Finishing thread.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPause(){
|
||||||
|
synchronized (threadPauseMonitor){
|
||||||
|
while(pause){
|
||||||
|
if(ProjectConstants.DEBUG) Log.d(TAG, CLASS_NAME + ".checkPause() :: Pause requested.");
|
||||||
|
try{ threadPauseMonitor.wait(); }catch(InterruptedException ie){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void pauseThread(){
|
||||||
|
pause = true;
|
||||||
|
if(ProjectConstants.DEBUG) Log.d(TAG, CLASS_NAME + ".pauseThread() :: Pausing thread.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void resumeThread(){
|
||||||
|
if(ProjectConstants.DEBUG) Log.d(TAG, CLASS_NAME + ".resumeThread() :: Resuming thread.");
|
||||||
|
synchronized (threadPauseMonitor) {
|
||||||
|
pause = false;
|
||||||
|
threadPauseMonitor.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected(){
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/ve/ucv/ciens/ccg/nxtcam/network/LCPThread.java
Normal file
12
src/ve/ucv/ciens/ccg/nxtcam/network/LCPThread.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network;
|
||||||
|
|
||||||
|
public class LCPThread extends Thread{
|
||||||
|
|
||||||
|
public LCPThread(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network;
|
||||||
|
|
||||||
|
public class ServiceDiscoveryThread extends Thread {
|
||||||
|
|
||||||
|
public ServiceDiscoveryThread(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network.protocols;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class ImageTransferProtocol{
|
||||||
|
public static enum ProtocolState{
|
||||||
|
SALUTE, IMG_FOLLOWS, SEND_DATA, PAUSED, WAITING, GOODBYE
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final byte MSG_HELLO = (byte)0x89;
|
||||||
|
public static final byte MSG_GOODBYE = (byte)0x90;
|
||||||
|
public static final byte MSG_IMG_DATA = (byte)0x42;
|
||||||
|
public static final byte CMD_IMG_FOLLOWS = (byte)0x10;
|
||||||
|
public static final byte CMD_PAUSE = (byte)0x15;
|
||||||
|
public static final byte CMD_IMG_WAIT = (byte)0x20;
|
||||||
|
public static final byte ACK_SEND_IMG = (byte)0x40;
|
||||||
|
public static final byte ACK_IMG_RCVD = (byte)0x50;
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.network.protocols;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
|
|
||||||
|
public abstract class LegoCommunicationProtocol{
|
||||||
|
/**
|
||||||
|
* Command types. Byte 0;
|
||||||
|
*/
|
||||||
|
private static final byte DIRECT_COMMAND_REPLY = 0x00;
|
||||||
|
private static final byte SYSTEM_COMMAND_REPLY = 0x01;
|
||||||
|
private static final byte DIRECT_COMMAND_NO_REPLY = (byte)0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comand bytes. Byte 1;
|
||||||
|
*/
|
||||||
|
private static final byte GET_FIRMWARE_VERSION = (byte)0x88;
|
||||||
|
private static final byte GET_DEVICE_INFO = (byte)0x9B;
|
||||||
|
private static final byte SET_OUTPUT_STATE = 0x04;
|
||||||
|
private static final byte SET_INPUT_MODE = 0x05;
|
||||||
|
private static final byte GET_OUTPUT_STATE = 0x06;
|
||||||
|
private static final byte GET_INPUT_VALUES = 0x07;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ports for get/setOutputState() and get/setInputMode().
|
||||||
|
*/
|
||||||
|
public static final byte PORT_0 = 0x00;
|
||||||
|
public static final byte PORT_1 = 0x01;
|
||||||
|
public static final byte PORT_2 = 0x02;
|
||||||
|
public static final byte PORT_3 = 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mode bytes for setOutputState().
|
||||||
|
*/
|
||||||
|
public static final byte MOTORON = 0x01;
|
||||||
|
public static final byte BRAKE = 0x02;
|
||||||
|
public static final byte REGULATED = 0x04;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regulation modes for setOutputState().
|
||||||
|
*/
|
||||||
|
public static final byte REGULATION_MODE_IDLE = 0x00;
|
||||||
|
public static final byte REGULATION_MODE_MOTOR_SPEED = 0x01;
|
||||||
|
public static final byte REGULATION_MODE_MOTOR_SYNC = 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run states for setOutputState().
|
||||||
|
*/
|
||||||
|
public static final byte MOTOR_RUN_STATE_IDLE = 0x00;
|
||||||
|
public static final byte MOTOR_RUN_STATE_RAMPUP = 0x10;
|
||||||
|
public static final byte MOTOR_RUN_STATE_RUNNING = 0x20;
|
||||||
|
public static final byte MOTOR_RUN_STATE_RAMPDOWN = 0x40;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sensor types for setInputMode().
|
||||||
|
*/
|
||||||
|
public static final byte NO_SENSOR = 0x00;
|
||||||
|
public static final byte SWITCH = 0x01;
|
||||||
|
public static final byte TEMPERATURE = 0x02;
|
||||||
|
public static final byte REFLECTION = 0x03;
|
||||||
|
public static final byte ANGLE = 0x04;
|
||||||
|
public static final byte LIGHT_ACTIVE = 0x05;
|
||||||
|
public static final byte LIGHT_INACTIVE = 0x06;
|
||||||
|
public static final byte SOUND_DB = 0x07;
|
||||||
|
public static final byte SOUND_DBA = 0x08;
|
||||||
|
public static final byte CUSTOM = 0x09;
|
||||||
|
public static final byte LOWSPEED = 0x0A;
|
||||||
|
public static final byte LOWSPEED_9V = 0x0B;
|
||||||
|
public static final byte NO_OF_SENSOR_TYPES = 0x0C;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sensor modes for setInputMode().
|
||||||
|
*/
|
||||||
|
public static final byte RAWMODE = 0x00;
|
||||||
|
public static final byte BOOLEANMODE = 0x20;
|
||||||
|
public static final byte TRANSITIONCNTMODE = 0x40;
|
||||||
|
public static final byte PERIODCOUNTERMODE = 0x60;
|
||||||
|
public static final byte PCTFULLSCALEMODE = (byte)0x80;
|
||||||
|
public static final byte CELSIUSMODE = (byte)0xA0;
|
||||||
|
public static final byte FARENHEITMODE = (byte)0xC0;
|
||||||
|
public static final byte ANGLESTEPMODE = (byte)0xE0;
|
||||||
|
public static final byte SLOPEMASK = (byte)0x1F;
|
||||||
|
public static final byte MODEMASK = (byte)0xE0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Firmware and protocol version request pdu. Page 11 of appendix 1.
|
||||||
|
*
|
||||||
|
* @return byte[4], the pdu.
|
||||||
|
*/
|
||||||
|
public static byte[] getFirmwareVersion(){
|
||||||
|
byte[] message = new byte[4];
|
||||||
|
message[0] = 0x02;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = SYSTEM_COMMAND_REPLY;
|
||||||
|
message[3] = GET_FIRMWARE_VERSION;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device info request pdu. Page 14 of appendix 1.
|
||||||
|
*
|
||||||
|
* @return byte[4], the pdu.
|
||||||
|
*/
|
||||||
|
public static byte[] getDeviceInfo(){
|
||||||
|
byte[] message = new byte[4];
|
||||||
|
message[0] = 0x02;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = SYSTEM_COMMAND_REPLY;
|
||||||
|
message[3] = GET_DEVICE_INFO;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set motor configuration pdu. Page 6 of appendix 2.
|
||||||
|
*
|
||||||
|
* @param output_port The port in the brick the motor is connected to.
|
||||||
|
* @param power_set_point
|
||||||
|
* @param mode_byte
|
||||||
|
* @param regulation_mode
|
||||||
|
* @param turn_ratio
|
||||||
|
* @param run_state
|
||||||
|
* @return byte[15], the pdu.
|
||||||
|
* @throws InvalidParameterException When any parameter is out of range or is an invalid enum. Ranges defined in appendix 2.
|
||||||
|
*/
|
||||||
|
public static byte[] setOutputState(byte output_port, byte power_set_point, byte mode_byte, byte regulation_mode, byte turn_ratio, byte run_state) throws InvalidParameterException{
|
||||||
|
byte[] message = new byte[15];
|
||||||
|
|
||||||
|
if(output_port < PORT_0 || output_port > PORT_2){
|
||||||
|
throw new InvalidParameterException("Output port out of range.");
|
||||||
|
}
|
||||||
|
if(power_set_point < -100 || power_set_point > 100){
|
||||||
|
throw new InvalidParameterException("Power set point out of range.");
|
||||||
|
}
|
||||||
|
if(turn_ratio < -100 || turn_ratio > 100){
|
||||||
|
throw new InvalidParameterException("Turn ratio out of range.");
|
||||||
|
}
|
||||||
|
if(mode_byte != MOTORON && mode_byte != BRAKE && mode_byte != REGULATED){
|
||||||
|
throw new InvalidParameterException("Invalid mode byte.");
|
||||||
|
}
|
||||||
|
if(regulation_mode != REGULATION_MODE_IDLE && regulation_mode != REGULATION_MODE_MOTOR_SPEED && regulation_mode != REGULATION_MODE_MOTOR_SYNC){
|
||||||
|
throw new InvalidParameterException("Invalid regulation mode.");
|
||||||
|
}
|
||||||
|
if(run_state != MOTOR_RUN_STATE_IDLE && run_state != MOTOR_RUN_STATE_RAMPUP && run_state != MOTOR_RUN_STATE_RUNNING && run_state != MOTOR_RUN_STATE_RAMPDOWN){
|
||||||
|
throw new InvalidParameterException("Invalid run state.");
|
||||||
|
}
|
||||||
|
|
||||||
|
message[0] = 0x0C;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = DIRECT_COMMAND_NO_REPLY;
|
||||||
|
message[3] = SET_OUTPUT_STATE;
|
||||||
|
message[4] = output_port;
|
||||||
|
message[5] = power_set_point;
|
||||||
|
message[6] = mode_byte;
|
||||||
|
message[7] = regulation_mode;
|
||||||
|
message[8] = turn_ratio;
|
||||||
|
message[9] = run_state;
|
||||||
|
message[10] = message[11] = message[12] = message[13] = message[14] = 0x00;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Motor configuration request pdu. Page 8 of appendix 2.
|
||||||
|
*
|
||||||
|
* @param output_port The port in the brick the motor is connected to.
|
||||||
|
* @return byte[5], the pdu.
|
||||||
|
* @throws InvalidParameterException When any parameter is out of range or is an invalid enum. Ranges defined in appendix 2.
|
||||||
|
*/
|
||||||
|
public static byte[] getOutputState(byte output_port) throws InvalidParameterException{
|
||||||
|
byte[] message = new byte[5];
|
||||||
|
|
||||||
|
if(output_port < PORT_0 || output_port > PORT_2){
|
||||||
|
throw new InvalidParameterException("Output port out of range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
message[0] = 0x03;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = DIRECT_COMMAND_REPLY;
|
||||||
|
message[3] = GET_OUTPUT_STATE;
|
||||||
|
message[4] = output_port;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sensor feed request pdu. Page 8 of appendix 2.
|
||||||
|
*
|
||||||
|
* @param input_port The port in the brick the sensor is connected to.
|
||||||
|
* @return byte[5], the pdu.
|
||||||
|
* @throws InvalidParameterException When any parameter is out of range or is an invalid enum. Ranges defined in appendix 2.
|
||||||
|
*/
|
||||||
|
public static byte[] getInputValues(byte input_port) throws InvalidParameterException{
|
||||||
|
byte[] message = new byte[5];
|
||||||
|
|
||||||
|
if(input_port < PORT_0 || input_port > PORT_3){
|
||||||
|
throw new InvalidParameterException("Input port is out of range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
message[0] = 0x03;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = DIRECT_COMMAND_REPLY;
|
||||||
|
message[3] = GET_INPUT_VALUES;
|
||||||
|
message[4] = input_port;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sensor configuration pdu.
|
||||||
|
*
|
||||||
|
* @param input_port The port in the brick the sensor is connected to.
|
||||||
|
* @param sensor_type The sensor to be configured.
|
||||||
|
* @param sensor_mode The configuration to set.
|
||||||
|
* @return byte[7], the pdu.
|
||||||
|
* @throws InvalidParameterException When any parameter is out of range or is an invalid enum. Ranges defined in appendix 2.
|
||||||
|
*/
|
||||||
|
public static byte[] setInputMode(byte input_port, byte sensor_type, byte sensor_mode) throws InvalidParameterException{
|
||||||
|
byte[] message = new byte[7];
|
||||||
|
|
||||||
|
if(input_port < PORT_0 || input_port > PORT_3){
|
||||||
|
throw new InvalidParameterException("Input port is out of range.");
|
||||||
|
}
|
||||||
|
if(sensor_type < 0x00 || sensor_type > 0x0C){
|
||||||
|
throw new InvalidParameterException("Invalid sensor type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
message[0] = 0x05;
|
||||||
|
message[1] = 0x00;
|
||||||
|
message[2] = DIRECT_COMMAND_NO_REPLY;
|
||||||
|
message[3] = SET_INPUT_MODE;
|
||||||
|
message[4] = input_port;
|
||||||
|
message[5] = sensor_type;
|
||||||
|
switch(sensor_mode){
|
||||||
|
case RAWMODE:
|
||||||
|
case BOOLEANMODE:
|
||||||
|
case TRANSITIONCNTMODE:
|
||||||
|
case PERIODCOUNTERMODE:
|
||||||
|
case PCTFULLSCALEMODE:
|
||||||
|
case CELSIUSMODE:
|
||||||
|
case FARENHEITMODE:
|
||||||
|
case ANGLESTEPMODE: // Same case as MODEMASK.
|
||||||
|
case SLOPEMASK:
|
||||||
|
message[6] = sensor_mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/ve/ucv/ciens/ccg/nxtcam/utils/Logger.java
Normal file
32
src/ve/ucv/ciens/ccg/nxtcam/utils/Logger.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public abstract class Logger {
|
||||||
|
public static enum LOG_TYPES{ DEBUG, INFO, WARN, ERROR, VERBOSE, WTF }
|
||||||
|
|
||||||
|
public static void log(LOG_TYPES log_type, String tag, String msg){
|
||||||
|
if(ProjectConstants.DEBUG){
|
||||||
|
switch(log_type){
|
||||||
|
case DEBUG:
|
||||||
|
Log.d(tag, msg);
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
Log.i(tag, msg);
|
||||||
|
break;
|
||||||
|
case WARN:
|
||||||
|
Log.w(tag, msg);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
Log.e(tag, msg);
|
||||||
|
break;
|
||||||
|
case VERBOSE:
|
||||||
|
Log.v(tag, msg);
|
||||||
|
break;
|
||||||
|
case WTF:
|
||||||
|
Log.wtf(tag, msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/ve/ucv/ciens/ccg/nxtcam/utils/ProjectConstants.java
Normal file
9
src/ve/ucv/ciens/ccg/nxtcam/utils/ProjectConstants.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package ve.ucv.ciens.ccg.nxtcam.utils;
|
||||||
|
|
||||||
|
public abstract class ProjectConstants {
|
||||||
|
public static final int SERVER_UDP_PORT = 8889;
|
||||||
|
public static final int SERVER_TCP_PORT_1 = 9989;
|
||||||
|
public static final int SERVER_TCP_PORT_2 = 9990;
|
||||||
|
|
||||||
|
public static final boolean DEBUG = true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user