diff options
37 files changed, 994 insertions, 201 deletions
diff --git a/Software/Android_Studio/ColorCapture/app/build.gradle b/Software/Android_Studio/ColorCapture/app/build.gradle index 83ed47583..6f56df4f6 100644 --- a/Software/Android_Studio/ColorCapture/app/build.gradle +++ b/Software/Android_Studio/ColorCapture/app/build.gradle @@ -21,10 +21,20 @@ android { } } buildTypes { + + debug { + buildConfigField "String", "WEB_SERVICE_ADDRESS", "\"http://192.168.1.86:45455/api/\"" + buildConfigField "String", "WEB_SERVICE_APP_ID", "\"Tdf793i4ughsiduf8749509237885ehgfdlkghlT\"" + } + release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + + buildConfigField "String", "WEB_SERVICE_ADDRESS", "\"http://twinetcc.azurewebsites.net/api/\"" + buildConfigField "String", "WEB_SERVICE_APP_ID", "\"Tdf793i4ughsiduf8749509237885ehgfdlkghlT\"" } + } dataBinding { @@ -67,4 +77,9 @@ dependencies { annotationProcessor 'com.google.dagger:dagger-android-processor:2.11' annotationProcessor 'com.google.dagger:dagger-compiler:2.11' compile 'com.yanzhenjie.zbar:zbar:1.0.0' + compile 'com.squareup.retrofit2:retrofit:2.3.0' + compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + compile 'com.squareup.retrofit2:converter-gson:2.1.0' + implementation 'com.github.yoanngoular:bitmapconverter:0.2.0' + } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/AndroidManifest.xml b/Software/Android_Studio/ColorCapture/app/src/main/AndroidManifest.xml index df39e776f..a03d65975 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/AndroidManifest.xml +++ b/Software/Android_Studio/ColorCapture/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="com.twine.colorcapture"> <uses-permission android:name="android.permission.CAMERA" /> + <uses-permission android:name="android.permission.INTERNET" /> <uses-feature android:name="android.hardware.camera" diff --git a/Software/Android_Studio/ColorCapture/app/src/main/cpp/ColorCaptureLib/ColorCaptureLib.cpp b/Software/Android_Studio/ColorCapture/app/src/main/cpp/ColorCaptureLib/ColorCaptureLib.cpp index 3a97b4911..7437923f2 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/cpp/ColorCaptureLib/ColorCaptureLib.cpp +++ b/Software/Android_Studio/ColorCapture/app/src/main/cpp/ColorCaptureLib/ColorCaptureLib.cpp @@ -733,13 +733,14 @@ vector<Point> ColorCaptureLib::GetArcusVertices(Mat image) aruco::DetectorParameters* params = new aruco::DetectorParameters(); params->cornerRefinementMethod = aruco::CORNER_REFINE_SUBPIX; params->perspectiveRemovePixelPerCell = 50; + params->minDistanceToBorder = 0; Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_4X4_50); aruco::detectMarkers(image, dictionary, corners, ids, &(*params)); if (corners.size() == 4) { - aruco::drawDetectedMarkers(image, corners, ids); + //aruco::drawDetectedMarkers(image, corners, ids); vertices = { diff --git a/Software/Android_Studio/ColorCapture/app/src/main/cpp/native-lib.cpp b/Software/Android_Studio/ColorCapture/app/src/main/cpp/native-lib.cpp index 62d702b7f..c2bee04e8 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/cpp/native-lib.cpp +++ b/Software/Android_Studio/ColorCapture/app/src/main/cpp/native-lib.cpp @@ -8,47 +8,67 @@ using namespace cv; -enum RotateFlags { +enum RotateFlags +{ ROTATE_90DEG_CLOCKWISE = 0, //Rotate 90 degrees clockwise ROTATE_180DEG = 1, //Rotate 180 degrees clockwise ROTATE_90_DEFCOUNTERCLOCKWISEDEG = 2, //Rotate 270 degrees clockwise }; -void rot90(cv::Mat &matImage, int rotflag) { +void rot90(cv::Mat &matImage, int rotflag) +{ //1=CW, 2=CCW, 3=180 - if (rotflag == 1) { + if (rotflag == 1) + { transpose(matImage, matImage); flip(matImage, matImage, 1); //transpose+flip(1)=CW - } else if (rotflag == 2) { + } + else if (rotflag == 2) + { transpose(matImage, matImage); flip(matImage, matImage, 0); //transpose+flip(0)=CCW - } else if (rotflag == 3) { + } + else if (rotflag == 3) + { flip(matImage, matImage, -1); //flip(-1)=180 - } else if (rotflag != 0) { //if not 0,1,2,3: + } + else if (rotflag != 0) + { //if not 0,1,2,3: cout << "Unknown rotation flag(" << rotflag << ")" << endl; } } extern "C" JNIEXPORT jboolean JNICALL Java_com_twine_colorcapture_opencv_ImageProcessor_ProcessImage( - JNIEnv *env, jobject instance, jint frameWidth, - jint frameHeight, jint correctedWidth, jint correctedHeight, jbyteArray NV21FrameData, - jintArray outPixels, jintArray wrapedOutPixels) { - jbyte *pNV21FrameData = env->GetByteArrayElements(NV21FrameData, 0); - jint *poutPixels = env->GetIntArrayElements(outPixels, 0); - jint *pwrapedPixels = env->GetIntArrayElements(wrapedOutPixels, 0); + JNIEnv *env, + jobject instance, + jint frameWidth, + jint frameHeight, + jint sampleWidth, + jint sampleHeight, + jint histogramMethod, + jdouble similarityTolerance, + jboolean enableDoubleChecking, + jbyteArray frameData, + jintArray frameOutPixels, + jintArray sampleOutPixels) +{ + + jbyte *pFrameData = env->GetByteArrayElements(frameData, 0); + jint *pFrameOutPixels = env->GetIntArrayElements(frameOutPixels, 0); + jint *pSampleOutPixels = env->GetIntArrayElements(sampleOutPixels, 0); - //// jboolean has_result = jboolean(false); - try { + try + { ColorCaptureLib capture; Mat yuv(frameHeight + frameHeight / 2, frameWidth, CV_8UC1, - (unsigned char *) pNV21FrameData); + (unsigned char *) pFrameData); Mat rgb; - Mat result(frameWidth, frameHeight, CV_8UC4, (unsigned char *) poutPixels); + Mat result(frameWidth, frameHeight, CV_8UC4, (unsigned char *) pFrameOutPixels); cvtColor(yuv, rgb, COLOR_YUV2RGB_NV21); Mat gray; @@ -56,82 +76,65 @@ Java_com_twine_colorcapture_opencv_ImageProcessor_ProcessImage( cvtColor(rgb, gray, CV_RGB2GRAY); cv::Laplacian(gray, dst, CV_64F); - cv::Scalar mu, sigma; - cv::meanStdDev(dst, mu, sigma); - - double focusMeasure = sigma.val[0] * sigma.val[0]; +// cv::Scalar mu, sigma; +// cv::meanStdDev(dst, mu, sigma); - __android_log_print(ANDROID_LOG_ERROR, "FOCUS", "\n Focus measure is %f \n", focusMeasure); +// double focusMeasure = sigma.val[0] * sigma.val[0]; +// +// __android_log_print(ANDROID_LOG_ERROR, "FOCUS", "\n Focus measure is %f \n", focusMeasure); rot90(rgb, ROTATE_180DEG); - //resize(src, dst, dst.size(), 0, 0, interpolation); - -/* Point2f src_center(rgb.cols / 2.0F, rgb.rows / 2.0F); - Mat rot_mat = getRotationMatrix2D(src_center, -90, 1.0); - warpAffine(rgb, rgb, rot_mat, rgb.size());*/ - vector<Point> vertices = capture.GetArcusVertices(rgb); - for (size_t i = 0; i < vertices.size(); i++) { - circle(rgb, vertices[i], 2, CV_RGB(0, 0, 255), -1); - } + int w = sampleWidth; + int h = sampleHeight; - int w = correctedWidth; - int h = correctedHeight; + Mat sampleMat(h, w, CV_8UC4, (unsigned char *) pSampleOutPixels); - Mat wraped(h, w, CV_8UC4, (unsigned char *) pwrapedPixels); + if (vertices.size() == 4) + { + Mat detectedMat = capture.ApplyHomography(rgb, vertices, Size(w, h)); - if (vertices.size() == 4) { + bool passed_double_checking = true; - has_result = jboolean(true); + if (enableDoubleChecking) + { + vertices = capture.GetArcusVertices(detectedMat); + if (vertices.size() == 4) + { + passed_double_checking = true; + } + else + { + passed_double_checking = false; + } + } - Mat m = capture.ApplyHomography(rgb, vertices, Size(w, h)); + if (passed_double_checking) + { + has_result = jboolean(true); + } - //Draw Blocks! - BhBlocks b(m, w / 10, h / 11); - b.drawBlocks(m, Scalar(255, 0, 0), 1); - - cvtColor(m, wraped, COLOR_RGB2BGRA); - m.release(); + cvtColor(detectedMat, sampleMat, COLOR_RGB2BGRA); + detectedMat.release(); } cvtColor(rgb, result, COLOR_RGB2BGRA); -/* vector<Point> vertices = capture.GetQRVertices4(image); - - for (size_t i = 0; i < vertices.size(); i++) - { - circle(image, vertices[i], 2, CV_RGB(0, 0, 255), -1); - } - - int w = 330; - int h = 300; - int columns = 11; - int rows = 10; - - if (vertices.size() == 4) - { - capture.ApplyHomography(image, vertices, Size(w, h)); - BhBlocks b(image, w / columns, h / rows); - b.drawBlocks(image, Scalar(0, 0, 0), 1); - }*/ - - - jsize size = env->GetArrayLength(outPixels); - - env->ReleaseByteArrayElements(NV21FrameData, pNV21FrameData, 0); - env->ReleaseIntArrayElements(outPixels, poutPixels, 0); - env->ReleaseIntArrayElements(wrapedOutPixels, pwrapedPixels, 0); + env->ReleaseByteArrayElements(frameData, pFrameData, 0); + env->ReleaseIntArrayElements(frameOutPixels, pFrameOutPixels, 0); + env->ReleaseIntArrayElements(sampleOutPixels, pSampleOutPixels, 0); yuv.release(); rgb.release(); result.release(); - wraped.release(); + sampleMat.release(); dst.release(); gray.release(); } - catch (Exception ex) { + catch (Exception ex) + { env->ThrowNew(env->FindClass("java/lang/NullPointerException"), ex.what()); } return has_result; diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/App.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/App.java index d703526e2..335b4fe52 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/App.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/App.java @@ -7,6 +7,7 @@ import android.content.Context; import com.twine.colorcapture.dagger.ApplicationComponent; import com.twine.colorcapture.dagger.ApplicationModule; import com.twine.colorcapture.dagger.DaggerApplicationComponent; +import com.twine.colorcapture.web.WebApiFactory; import net.danlew.android.joda.JodaTimeAndroid; @@ -53,7 +54,7 @@ public class App extends Application //TangoDB.init(); //MessageFactory.init(); - //WebApiFactory.init("http://10.0.2.2:45455/api/"); + WebApiFactory.init(BuildConfig.WEB_SERVICE_ADDRESS); Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/AnimationsHelper.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/AnimationsHelper.java index a5faab0d1..f19571b06 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/AnimationsHelper.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/AnimationsHelper.java @@ -6,6 +6,8 @@ import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.ScaleAnimation; +import java.io.IOException; + /** * Contains helper methods related to animations. */ @@ -34,7 +36,16 @@ public class AnimationsHelper @Override public void onAnimationEnd(Animation animation) { - if (onCompleted != null) onCompleted.invoke(); + if (onCompleted != null) + { + try + { + onCompleted.invoke(); + } catch (IOException e) + { + e.printStackTrace(); + } + } } @Override diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/IAction.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/IAction.java index 5766f6cf3..35cf21cc4 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/IAction.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/IAction.java @@ -1,5 +1,7 @@ package com.twine.colorcapture.core; +import java.io.IOException; + /** * Represents an void Action delegate. */ @@ -8,5 +10,5 @@ public interface IAction /** * Invokes the action. */ - void invoke(); + void invoke() throws IOException; } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/Task.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/Task.java index 2858fbc3c..407de37d3 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/Task.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/core/Task.java @@ -2,33 +2,72 @@ package com.twine.colorcapture.core; import android.os.AsyncTask; -public class Task extends AsyncTask<String, Integer, String> { +import java.io.IOException; + +public class Task extends AsyncTask<String, Integer, String> +{ private IAction action; private IAction continueWithAction; + private IAction1<Exception> errorAction; + private boolean hasError; + private Exception error; + - public Task(IAction action) { + public Task(IAction action) + { this.action = action; } - public Task(IAction action, IAction continueWithAction) { + public Task(IAction action, IAction continueWithAction) + { this.action = action; this.continueWithAction = continueWithAction; } + public Task(IAction action, IAction continueWithAction, IAction1<Exception> errorAction) + { + this.action = action; + this.continueWithAction = continueWithAction; + this.errorAction = errorAction; + } + @Override - protected String doInBackground(String... strings) { - action.invoke(); + protected String doInBackground(String... strings) + { + try + { + action.invoke(); + } catch (Exception ex) + { + hasError = true; + error = ex; + } return null; } @Override - protected void onPostExecute(String s) { + protected void onPostExecute(String s) + { super.onPostExecute(s); - if (continueWithAction != null) + if (continueWithAction != null && !hasError) + { + try + { + continueWithAction.invoke(); + } catch (IOException e) + { + e.printStackTrace(); + } + } + + if (hasError) { - continueWithAction.invoke(); + if (errorAction != null) + { + errorAction.invoke(error); + } } } @@ -42,6 +81,7 @@ public class Task extends AsyncTask<String, Integer, String> { private Task task; private IAction action; private IAction continueWithAction; + private IAction1<Exception> errorAction; public TaskBuilder setAction(IAction action) { @@ -55,9 +95,15 @@ public class Task extends AsyncTask<String, Integer, String> { return this; } + public TaskBuilder setError(IAction1<Exception> action) + { + this.errorAction = action; + return this; + } + public Task build() { - return new Task(action,continueWithAction); + return new Task(action, continueWithAction, errorAction); } } } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ApplicationComponent.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ApplicationComponent.java index 7f97483b6..f52f30a53 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ApplicationComponent.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ApplicationComponent.java @@ -5,7 +5,6 @@ import com.twine.colorcapture.views.capture.CaptureFragment; import com.twine.colorcapture.views.mycolors.MyColorsFragment; import com.twine.colorcapture.views.loading.LoadingActivity; import com.twine.colorcapture.views.main.MainActivity; -import com.twine.colorcapture.views.main.MainActivityVM; import javax.inject.Singleton; @@ -16,7 +15,7 @@ import dagger.Component; */ @Singleton -@Component(modules = {ApplicationModule.class, ViewModelsModule.class, EventBusModule.class, NotificationModule.class, NavigationModule.class}) +@Component(modules = {ApplicationModule.class, ViewModelsModule.class, EventBusModule.class, NotificationModule.class, NavigationModule.class, WebModule.class}) public interface ApplicationComponent { void inject(MainActivity view); diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ViewModelsModule.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ViewModelsModule.java index 1a017a7fc..188089553 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ViewModelsModule.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/ViewModelsModule.java @@ -8,6 +8,8 @@ import com.twine.colorcapture.views.capture.CaptureFragmentVM; import com.twine.colorcapture.views.loading.LoadingActivityVM; import com.twine.colorcapture.views.mycolors.MyColorsFragmentVM; import com.twine.colorcapture.views.main.MainActivityVM; +import com.twine.colorcapture.web.ITCCService; +import com.twine.colorcapture.web.IWebServiceAPI; import javax.inject.Singleton; @@ -21,33 +23,33 @@ import dagger.Provides; @Module public class ViewModelsModule { - + @Provides @Singleton public MainActivityVM provideMainActivityVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider) { return new MainActivityVM(eventBus, notificationProvider, navigationProvider); } - + @Provides @Singleton - public LoadingActivityVM provideLoadingFragmentVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider) + public LoadingActivityVM provideLoadingFragmentVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider, ITCCService tccService) { - return new LoadingActivityVM(eventBus, notificationProvider, navigationProvider); + return new LoadingActivityVM(eventBus, notificationProvider, navigationProvider, tccService); } - + @Provides @Singleton public MyColorsFragmentVM provideMyColorsFragmentVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider) { return new MyColorsFragmentVM(navigationProvider); } - + @Provides @Singleton - public CaptureFragmentVM provideCaptureFragmentVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider) + public CaptureFragmentVM provideCaptureFragmentVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider, ITCCService tccService) { - return new CaptureFragmentVM(); + return new CaptureFragmentVM(tccService, navigationProvider); } @Provides diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/WebModule.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/WebModule.java new file mode 100644 index 000000000..755f7b19c --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/dagger/WebModule.java @@ -0,0 +1,29 @@ +package com.twine.colorcapture.dagger; + +import com.twine.colorcapture.web.ITCCService; +import com.twine.colorcapture.web.IWebServiceAPI; +import com.twine.colorcapture.web.TCCService; +import com.twine.colorcapture.web.WebApiFactory; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class WebModule +{ + @Provides + @Singleton + public IWebServiceAPI providerWebServiceAPI() + { + return WebApiFactory.getWebServiceApi(); + } + + @Provides + @Singleton + public ITCCService provideTCCService(IWebServiceAPI webServiceAPI) + { + return new TCCService(webServiceAPI); + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/opencv/ImageProcessor.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/opencv/ImageProcessor.java index 373f1009a..49f61c7a3 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/opencv/ImageProcessor.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/opencv/ImageProcessor.java @@ -2,5 +2,14 @@ package com.twine.colorcapture.opencv; public class ImageProcessor { - public native boolean ProcessImage(int width, int height,int correctedWidth,int correctedHeight, byte[] NV21FrameData, int[] pixels,int[] wpixels); + public native boolean ProcessImage(int frameWidth, + int frameHeight, + int sampleWidth, + int sampleHeight, + int histogramMethod, + double similarityTolerance, + boolean enableDoubleChecking, + byte[] frameData, + int[] frameOutPixels, + int[] sampleOutPixels); } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/utils/BitmapUtils.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/utils/BitmapUtils.java new file mode 100644 index 000000000..7f53974b8 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/utils/BitmapUtils.java @@ -0,0 +1,25 @@ +package com.twine.colorcapture.utils; + +import android.graphics.Bitmap; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; + +public class BitmapUtils +{ + public static byte[] getBitmapBytes(Bitmap bitmap) + { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); + byte[] byteArray = stream.toByteArray(); + return byteArray; + } + + public static String getBitmapBase64String(Bitmap bitmap) + { + byte[] data = getBitmapBytes(bitmap); + String encoded = Base64.encodeToString(data, Base64.DEFAULT); + return encoded; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/capture/CaptureFragmentVM.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/capture/CaptureFragmentVM.java index b434b9dfb..3f173c530 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/capture/CaptureFragmentVM.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/capture/CaptureFragmentVM.java @@ -2,43 +2,61 @@ package com.twine.colorcapture.views.capture; import android.graphics.Bitmap; import android.util.Log; -import android.util.Size; import com.twine.colorcapture.core.Task.TaskBuilder; import com.twine.colorcapture.mvvm.ViewModelBase; +import com.twine.colorcapture.navigation.INavigationProvider; import com.twine.colorcapture.opencv.ImageProcessor; import com.twine.colorcapture.views.capture.ICaptureFragment.ICaptureFragmentListener; +import com.twine.colorcapture.web.ITCCService; +import com.twine.colorcapture.web.messages.DefinitionResponse; +import com.twine.colorcapture.web.messages.DetectionResponse; import com.yanzhenjie.zbar.Image; import com.yanzhenjie.zbar.ImageScanner; import com.yanzhenjie.zbar.Symbol; import com.yanzhenjie.zbar.SymbolSet; +import java.io.IOException; + public class CaptureFragmentVM extends ViewModelBase<ICaptureFragment> implements ICaptureFragmentListener { + private ImageProcessor processor; private Bitmap frameBitmap = null; - private Bitmap correctedBitmap = null; + private Bitmap sampleBitmap = null; private int[] framePixels = null; - private int[] correctedPixels = null; + private int[] samplePixels = null; private int previewWidth; private int previewHeight; private boolean isProcessing; private byte[] frameData; private String barcode; - private Size correctedSize = new Size(300, 330); //The desired cropped rectified bitmap. - - public CaptureFragmentVM() + private ITCCService tccService; + private DefinitionResponse definition; + private INavigationProvider navigationProvider; + + public CaptureFragmentVM(ITCCService tccService, INavigationProvider navigationProvider) { + this.navigationProvider = navigationProvider; + this.tccService = tccService; processor = new ImageProcessor(); + + try + { + definition = tccService.getDefinition(); + } catch (IOException e) + { + e.printStackTrace(); + } } - + @Override protected void onViewAttached(ICaptureFragment view) { super.onViewAttached(view); view.setListener(this); } - + @SuppressWarnings("SuspiciousNameCombination") @Override public void onFrameAvailable(byte[] frame) @@ -46,60 +64,74 @@ public class CaptureFragmentVM extends ViewModelBase<ICaptureFragment> implement if (!isProcessing) { isProcessing = true; - + frameData = frame; - + new TaskBuilder() .setAction(() -> { isProcessing = true; - - processor.ProcessImage( + + boolean detected = processor.ProcessImage( previewWidth, previewHeight, - correctedSize.getWidth(), - correctedSize.getHeight(), + definition.getSampleWidth(), + definition.getSampleHeight(), + definition.getHistogramMethod(), + definition.getSimilarityTolerance(), + definition.isEnableDoubleChecking(), frameData, framePixels, - correctedPixels); - + samplePixels); + frameBitmap.setPixels(framePixels, 0, previewHeight, 0, 0, previewHeight, previewWidth); - correctedBitmap.setPixels(correctedPixels, 0, correctedSize.getWidth(), 0, 0, correctedSize.getWidth(), correctedSize.getHeight()); - - - Log.d("BARCODE", "scanning barcode..."); - ImageScanner scanner = new ImageScanner(); - Image img = new Image(frameBitmap.getWidth(), frameBitmap.getHeight(), "RGB4"); - img.setData(framePixels); - int result = scanner.scanImage(img.convert("Y800")); - - if (result != 0) + + if (detected) { - Log.d("BARCODE", "Got positive result..."); - - String text = null; - - SymbolSet symSet = scanner.getResults(); - for (Symbol sym : symSet) - text = sym.getData(); - - - barcode = text; - - Log.d("BARCODE", "Barcode text is: " + text); + sampleBitmap.setPixels(samplePixels, 0, definition.getSampleWidth(), 0, 0, definition.getSampleWidth(), definition.getSampleHeight()); + + Log.d("BARCODE", "scanning barcode..."); + ImageScanner scanner = new ImageScanner(); + Image img = new Image(frameBitmap.getWidth(), frameBitmap.getHeight(), "RGB4"); + img.setData(framePixels); + int result = scanner.scanImage(img.convert("Y800")); + + if (result != 0) + { + Log.d("BARCODE", "Got positive result..."); + + String text = null; + + SymbolSet symSet = scanner.getResults(); + for (Symbol sym : symSet) + text = sym.getData(); + + + barcode = text; + + Log.d("BARCODE", "Barcode text is: " + text); + + DetectionResponse response = tccService.detect(sampleBitmap,barcode); + DetectionResponse a = response; + } } - + }) .setContinueWith(() -> { - view.onFrameResult(frameBitmap, correctedBitmap, barcode); + view.onFrameResult(frameBitmap, sampleBitmap, barcode); + isProcessing = false; + }) + .setError((ex) -> + { isProcessing = false; + ex.printStackTrace(); }) .build() .start(); } } - + @SuppressWarnings("SuspiciousNameCombination") @Override public void onPreviewSettingsAvailable(int previewWidth, int previewHeight) @@ -107,8 +139,8 @@ public class CaptureFragmentVM extends ViewModelBase<ICaptureFragment> implement this.previewWidth = previewWidth; this.previewHeight = previewHeight; frameBitmap = Bitmap.createBitmap(previewHeight, previewWidth, Bitmap.Config.ARGB_8888); - correctedBitmap = Bitmap.createBitmap(correctedSize.getWidth(), correctedSize.getHeight(), Bitmap.Config.ARGB_8888); + sampleBitmap = Bitmap.createBitmap(definition.getSampleWidth(), definition.getSampleHeight(), Bitmap.Config.ARGB_8888); framePixels = new int[previewWidth * previewHeight]; - correctedPixels = new int[correctedSize.getWidth() * correctedSize.getHeight()]; + samplePixels = new int[definition.getSampleWidth() * definition.getSampleHeight()]; } } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/loading/LoadingActivityVM.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/loading/LoadingActivityVM.java index a7a3affff..8cf9c1ef6 100644 --- a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/loading/LoadingActivityVM.java +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/views/loading/LoadingActivityVM.java @@ -1,9 +1,12 @@ package com.twine.colorcapture.views.loading; +import android.annotation.SuppressLint; import android.os.CountDownTimer; import android.os.Handler; +import android.util.Log; import com.squareup.otto.Bus; +import com.twine.colorcapture.BuildConfig; import com.twine.colorcapture.core.Task; import com.twine.colorcapture.mvvm.DependencyProperty; import com.twine.colorcapture.mvvm.ViewModelBase; @@ -11,42 +14,63 @@ import com.twine.colorcapture.navigation.INavigationProvider; import com.twine.colorcapture.navigation.NavigationActivity; import com.twine.colorcapture.navigation.NavigationFragment; import com.twine.colorcapture.notification.INotificationProvider; +import com.twine.colorcapture.web.ITCCService; +import com.twine.colorcapture.web.IWebServiceAPI; +import com.twine.colorcapture.web.WebApiFactory; +import com.twine.colorcapture.web.messages.DefinitionRequest; +import com.twine.colorcapture.web.messages.DefinitionResponse; +import com.twine.colorcapture.web.messages.LoginRequest; +import com.twine.colorcapture.web.messages.LoginResponse; + +import java.io.IOException; import javax.inject.Inject; +import io.reactivex.disposables.Disposable; + public class LoadingActivityVM extends ViewModelBase<ILoadingActivity> { private INavigationProvider navigationProvider; + private ITCCService tccService; + private boolean initialized; public DependencyProperty<Integer> loadingProgress; - + + @Inject - public LoadingActivityVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider) + public LoadingActivityVM(Bus eventBus, INotificationProvider notificationProvider, INavigationProvider navigationProvider, ITCCService tccService) { + this.tccService = tccService; this.navigationProvider = navigationProvider; loadingProgress = new DependencyProperty<>(0); } - + @Override protected void onViewAttached(ILoadingActivity view) { super.onViewAttached(view); + init(); + } - new Task.TaskBuilder().setAction(() -> + private void init() + { + if (!initialized) { - try + new Task.TaskBuilder().setAction(() -> { - Thread.sleep(5000); - } catch (InterruptedException e) + tccService.getDefinition(); + }).setContinueWith(() -> { - e.printStackTrace(); - } - + initialized = true; + navigationProvider.navigateTo(NavigationActivity.Main, true); - }).setContinueWith(() -> + }).setError((ex) -> + { + new Handler().postDelayed(this::init,5000); + }).build().start(); + } + else { - - navigationProvider.navigateTo(NavigationActivity.Main,true); - - }).build().start(); + navigationProvider.navigateTo(NavigationActivity.Main, true); + } } } diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/ITCCService.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/ITCCService.java new file mode 100644 index 000000000..065faf106 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/ITCCService.java @@ -0,0 +1,16 @@ +package com.twine.colorcapture.web; + +import android.graphics.Bitmap; + +import com.twine.colorcapture.web.messages.DefinitionResponse; +import com.twine.colorcapture.web.messages.DetectionRequest; +import com.twine.colorcapture.web.messages.DetectionResponse; + +import java.io.IOException; + +public interface ITCCService +{ + DefinitionResponse getDefinition() throws IOException; + + DetectionResponse detect(Bitmap bitmap, String barcode) throws IOException; +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/IWebServiceAPI.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/IWebServiceAPI.java new file mode 100644 index 000000000..6fa84c556 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/IWebServiceAPI.java @@ -0,0 +1,25 @@ +package com.twine.colorcapture.web; + +import com.twine.colorcapture.web.messages.DefinitionRequest; +import com.twine.colorcapture.web.messages.DefinitionResponse; +import com.twine.colorcapture.web.messages.DetectionRequest; +import com.twine.colorcapture.web.messages.DetectionResponse; +import com.twine.colorcapture.web.messages.LoginRequest; +import com.twine.colorcapture.web.messages.LoginResponse; + +import io.reactivex.Observable; +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.POST; + +public interface IWebServiceAPI +{ + @POST("ColorDetection/Login") + Call<LoginResponse> login(@Body LoginRequest request); + + @POST("ColorDetection/GetDefinition") + Call<DefinitionResponse> getDefinition(@Body DefinitionRequest request); + + @POST("ColorDetection/Detect") + Call<DetectionResponse> detect(@Body DetectionRequest request); +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/TCCService.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/TCCService.java new file mode 100644 index 000000000..98000f3dd --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/TCCService.java @@ -0,0 +1,76 @@ +package com.twine.colorcapture.web; + +import android.graphics.Bitmap; +import android.util.Base64; + +import com.twine.colorcapture.BuildConfig; +import com.twine.colorcapture.utils.BitmapUtils; +import com.twine.colorcapture.web.messages.DefinitionRequest; +import com.twine.colorcapture.web.messages.DefinitionResponse; +import com.twine.colorcapture.web.messages.DetectionRequest; +import com.twine.colorcapture.web.messages.DetectionResponse; +import com.twine.colorcapture.web.messages.LoginRequest; +import com.twine.colorcapture.web.messages.LoginResponse; + +import java.io.IOException; + +import javax.inject.Inject; + +public class TCCService implements ITCCService +{ + private DefinitionResponse definition; + private IWebServiceAPI webAPI; + private LoginResponse loginResponse; + + @Inject + public TCCService(IWebServiceAPI webServiceAPI) + { + this.webAPI = webServiceAPI; + } + + @Override + public DefinitionResponse getDefinition() throws IOException + { + ensureAuthenticated(); + + if (definition == null) + { + definition = webAPI.getDefinition(new DefinitionRequest()).execute().body(); + } + + return definition; + } + + @Override + public DetectionResponse detect(Bitmap bitmap, String barcode) throws IOException + { + ensureAuthenticated(); + + DetectionRequest request = new DetectionRequest(); + + request.setBitmapString(BitmapUtils.getBitmapBase64String(bitmap)); + request.setBarcode(barcode); + + DetectionResponse response = webAPI.detect(request).execute().body(); + + return response; + } + + private void ensureAuthenticated() throws IOException + { + if (loginResponse == null) + { + login(); + } + } + + private LoginResponse login() throws IOException + { + LoginRequest request = new LoginRequest(); + request.setAppId(BuildConfig.WEB_SERVICE_APP_ID); + request.setDeviceId("1234"); + loginResponse = webAPI.login(request).execute().body(); + WebApiFactory.setAuthenticationToken(loginResponse.getAccessToken()); + return loginResponse; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/WebApiFactory.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/WebApiFactory.java new file mode 100644 index 000000000..3aeaccd14 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/WebApiFactory.java @@ -0,0 +1,101 @@ +package com.twine.colorcapture.web; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + + +/** + * Represents the system restful api factory. + */ +public class WebApiFactory +{ + private static String baseUrl; + private static String accessToken; + + + /** + * Initializes the remote base url. + * + * @param base_url the base url + */ + public static void init(String base_url) + { + baseUrl = base_url; + } + + /** + * Gets synchronization api. + * + * @return the synchronization api + */ + public static IWebServiceAPI getWebServiceApi() + { + return createAPI(IWebServiceAPI.class, 60); + } + + /** + * Creates the specified API interface instance. + * @param cls + * @param timeout + * @param <T> + * @return + */ + private static <T> T createAPI(Class<?> cls, int timeout) + { + OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); + httpClient.addInterceptor(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException + { + Request request; + + if (accessToken != null) + { + request = chain.request().newBuilder().addHeader("Authorization", accessToken).build(); + } + else + { + request = chain.request().newBuilder().build(); + } + return chain.proceed(request); + } + }); + + httpClient.readTimeout(timeout, TimeUnit.SECONDS); + httpClient.writeTimeout(timeout, TimeUnit.SECONDS); + + Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE) + .setLenient() + .setDateFormat("yyyy-MM-dd") + .create(); + + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(baseUrl) + +// .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create(gson)) + .client(httpClient.build()) + .build(); + + return (T) retrofit.create(cls); + } + + public static void setAuthenticationToken(String authenticationToken) + { + accessToken = authenticationToken; + } +} + diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionRequest.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionRequest.java new file mode 100644 index 000000000..2847847b2 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionRequest.java @@ -0,0 +1,5 @@ +package com.twine.colorcapture.web.messages; + +public class DefinitionRequest +{ +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionResponse.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionResponse.java new file mode 100644 index 000000000..2dde27e09 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DefinitionResponse.java @@ -0,0 +1,105 @@ +package com.twine.colorcapture.web.messages; + +public class DefinitionResponse +{ + private String templateString; + private int sampleWidth; + private int sampleHeight; + private int cameraWidth; + private int cameraHeight; + private int histogramMethod; + private double similarityTolerance; + private boolean enableDoubleChecking; + private boolean enforceBarcodeDetection; + + public String getTemplateString() + { + return templateString; + } + + public void setTemplateString(String templateString) + { + this.templateString = templateString; + } + + public int getSampleWidth() + { + return sampleWidth; + } + + public void setSampleWidth(int sampleWidth) + { + this.sampleWidth = sampleWidth; + } + + public int getSampleHeight() + { + return sampleHeight; + } + + public void setSampleHeight(int sampleHeight) + { + this.sampleHeight = sampleHeight; + } + + public int getCameraWidth() + { + return cameraWidth; + } + + public void setCameraWidth(int cameraWidth) + { + this.cameraWidth = cameraWidth; + } + + public int getCameraHeight() + { + return cameraHeight; + } + + public void setCameraHeight(int cameraHeight) + { + this.cameraHeight = cameraHeight; + } + + public int getHistogramMethod() + { + return histogramMethod; + } + + public void setHistogramMethod(int histogramMethod) + { + this.histogramMethod = histogramMethod; + } + + + public double getSimilarityTolerance() + { + return similarityTolerance; + } + + public void setSimilarityTolerance(double similarityTolerance) + { + this.similarityTolerance = similarityTolerance; + } + + public boolean isEnableDoubleChecking() + { + return enableDoubleChecking; + } + + public void setEnableDoubleChecking(boolean enableDoubleChecking) + { + this.enableDoubleChecking = enableDoubleChecking; + } + + public boolean isEnforceBarcodeDetection() + { + return enforceBarcodeDetection; + } + + public void setEnforceBarcodeDetection(boolean enforceBarcodeDetection) + { + this.enforceBarcodeDetection = enforceBarcodeDetection; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionColor.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionColor.java new file mode 100644 index 000000000..05e2d2c9f --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionColor.java @@ -0,0 +1,38 @@ +package com.twine.colorcapture.web.messages; + +public class DetectionColor +{ + private int r; + private int g; + private int b; + + public int getR() + { + return r; + } + + public void setR(int r) + { + this.r = r; + } + + public int getG() + { + return g; + } + + public void setG(int g) + { + this.g = g; + } + + public int getB() + { + return b; + } + + public void setB(int b) + { + this.b = b; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionRequest.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionRequest.java new file mode 100644 index 000000000..5686a6947 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionRequest.java @@ -0,0 +1,27 @@ +package com.twine.colorcapture.web.messages; + +public class DetectionRequest +{ + private String bitmapString; + private String barcode; + + public String getBitmapString() + { + return bitmapString; + } + + public void setBitmapString(String bitmapString) + { + this.bitmapString = bitmapString; + } + + public String getBarcode() + { + return barcode; + } + + public void setBarcode(String barcode) + { + this.barcode = barcode; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionResponse.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionResponse.java new file mode 100644 index 000000000..2e33a04b5 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/DetectionResponse.java @@ -0,0 +1,27 @@ +package com.twine.colorcapture.web.messages; + +public class DetectionResponse +{ + private DetectionColor rawColor; + private DetectionColor processedColor; + + public DetectionColor getRawColor() + { + return rawColor; + } + + public void setRawColor(DetectionColor rawColor) + { + this.rawColor = rawColor; + } + + public DetectionColor getProcessedColor() + { + return processedColor; + } + + public void setProcessedColor(DetectionColor processedColor) + { + this.processedColor = processedColor; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginRequest.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginRequest.java new file mode 100644 index 000000000..c49dcafe8 --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginRequest.java @@ -0,0 +1,49 @@ +package com.twine.colorcapture.web.messages; + +public class LoginRequest +{ + private String appId; + private String device; + private String deviceId; + private String osVersion; + + public String getAppId() + { + return appId; + } + + public void setAppId(String appId) + { + this.appId = appId; + } + + public String getDevice() + { + return device; + } + + public void setDevice(String device) + { + this.device = device; + } + + public String getDeviceId() + { + return deviceId; + } + + public void setDeviceId(String deviceId) + { + this.deviceId = deviceId; + } + + public String getOsVersion() + { + return osVersion; + } + + public void setOsVersion(String osVersion) + { + this.osVersion = osVersion; + } +} diff --git a/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginResponse.java b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginResponse.java new file mode 100644 index 000000000..4c719f32e --- /dev/null +++ b/Software/Android_Studio/ColorCapture/app/src/main/java/com/twine/colorcapture/web/messages/LoginResponse.java @@ -0,0 +1,16 @@ +package com.twine.colorcapture.web.messages; + +public class LoginResponse +{ + private String accessToken; + + public String getAccessToken() + { + return accessToken; + } + + public void setAccessToken(String accessToken) + { + this.accessToken = accessToken; + } +} diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/App_Start/WebApiConfig.cs b/Software/Visual_Studio/TCC/Tango.TCC.Service/App_Start/WebApiConfig.cs index a7e994f9c..f3519205b 100644 --- a/Software/Visual_Studio/TCC/Tango.TCC.Service/App_Start/WebApiConfig.cs +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/App_Start/WebApiConfig.cs @@ -16,7 +16,7 @@ namespace Tango.TCC.Service config.Routes.MapHttpRoute( name: "DefaultApi", - routeTemplate: "api/{controller}/{id}", + routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/Controllers/ColorDetectionController.cs b/Software/Visual_Studio/TCC/Tango.TCC.Service/Controllers/ColorDetectionController.cs index 0c4111189..eb4600788 100644 --- a/Software/Visual_Studio/TCC/Tango.TCC.Service/Controllers/ColorDetectionController.cs +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/Controllers/ColorDetectionController.cs @@ -1,28 +1,52 @@ using Google.Protobuf; using System; using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Security.Authentication; using System.Web.Http; using Tango.PMR.TCC; using Tango.TCC.BL; using Tango.TCC.BL.Web; +using Tango.TCC.Service.Filters; +using Tango.TCC.Service.Security; using Tango.Web.Controllers; +using Tango.Web.Security; namespace Tango.TCC.Service.Controllers { - public class ColorDetectionController : TangoController + public class ColorDetectionController : TangoController<TokenObject> { [HttpPost] public LoginResponse Login(LoginRequest request) { - return new LoginResponse(); + LoginResponse response = new LoginResponse(); + + if (request.AppID == TCCServiceConfig.APP_ID) + { + response.AccessToken = WebToken<TokenObject>.CreateNew(TCCServiceConfig.JWT_TOKEN_SECRET, new TokenObject() + { + DeviceID = request.DeviceID, + }).AccessToken; + } + else + { + throw new AuthenticationException("Invalid application ID provided."); + } + + return response; } + [JwtTokenFilter] [HttpPost] public DefinitionResponse GetDefinition(DefinitionRequest request) { + String s = RequestToken.Object.DeviceID; + return new DefinitionResponse() { TemplateString = TCCServiceConfig.TEMPLATE_STRING, @@ -42,6 +66,26 @@ namespace Tango.TCC.Service.Controllers { byte[] bitmapBytes = Convert.FromBase64String(request.BitmapString); + using (MemoryStream ms = new MemoryStream(bitmapBytes)) + { + using (Bitmap bmp = new Bitmap(ms)) + { + if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) + { + using (Bitmap bmp24 = bmp.ConvertTo24Bit()) + { + using (MemoryStream outms = new MemoryStream()) + { + bmp24.Save(outms, ImageFormat.Bmp); + bitmapBytes = outms.ToArray(); + + String base64 = Convert.ToBase64String(bitmapBytes); + } + } + } + } + } + using (ColorDetector detector = new ColorDetector()) { var output = detector.Detect(new DetectionInput() diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/Filters/JwtTokenFilter.cs b/Software/Visual_Studio/TCC/Tango.TCC.Service/Filters/JwtTokenFilter.cs new file mode 100644 index 000000000..d68a11ac3 --- /dev/null +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/Filters/JwtTokenFilter.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Security.Authentication; +using System.Web; +using System.Web.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Filters; +using Tango.Transport.Web; +using Tango.Web.Security; + +namespace Tango.TCC.Service.Filters +{ + public class JwtTokenFilter : ActionFilterAttribute + { + public bool AllowExpired { get; private set; } + + public JwtTokenFilter() + { + + } + + public JwtTokenFilter(bool allowExpired) + { + AllowExpired = allowExpired; + } + + public override void OnActionExecuting(HttpActionContext actionContext) + { + var authorizationHeader = actionContext.Request.Headers.Authorization; + + if (authorizationHeader != null) + { + try + { + WebToken.Validate(TCCServiceConfig.JWT_TOKEN_SECRET, authorizationHeader.Parameter != null ? authorizationHeader.Parameter : authorizationHeader.ToString()); + } + catch (JWT.TokenExpiredException) + { + if (!AllowExpired) + { + throw new TokenExpiredException("Token expired."); + } + } + catch (JWT.SignatureVerificationException) + { + throw new InvalidTokenException("Invalid token."); + } + } + else + { + throw new AuthenticationException("No token specified."); + } + + base.OnActionExecuting(actionContext); + } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/Security/TokenObject.cs b/Software/Visual_Studio/TCC/Tango.TCC.Service/Security/TokenObject.cs new file mode 100644 index 000000000..545688451 --- /dev/null +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/Security/TokenObject.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Tango.TCC.Service.Security +{ + public class TokenObject + { + public String DeviceID { get; set; } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/Tango.TCC.Service.csproj b/Software/Visual_Studio/TCC/Tango.TCC.Service/Tango.TCC.Service.csproj index 78e13e6d4..f5ec44630 100644 --- a/Software/Visual_Studio/TCC/Tango.TCC.Service/Tango.TCC.Service.csproj +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/Tango.TCC.Service.csproj @@ -55,6 +55,9 @@ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <HintPath>..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath> </Reference> + <Reference Include="JWT, Version=5.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\..\packages\JWT.5.0.0\lib\net46\JWT.dll</HintPath> + </Reference> <Reference Include="Microsoft.CSharp" /> <Reference Include="System" /> <Reference Include="System.Data" /> @@ -194,10 +197,12 @@ <Compile Include="Controllers\ColorDetectionController.cs" /> <Compile Include="Controllers\HomeController.cs" /> <Compile Include="Controllers\ValuesController.cs" /> + <Compile Include="Filters\JwtTokenFilter.cs" /> <Compile Include="Global.asax.cs"> <DependentUpon>Global.asax</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Security\TokenObject.cs" /> <Compile Include="TCCServiceConfig.cs" /> </ItemGroup> <ItemGroup> @@ -261,6 +266,10 @@ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> <Name>Tango.PMR</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Transport\Tango.Transport.csproj"> + <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> + <Name>Tango.Transport</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Web\Tango.Web.csproj"> <Project>{5001990f-977b-48ff-b217-0236a5022ad8}</Project> <Name>Tango.Web</Name> @@ -309,8 +318,7 @@ <Error Condition="!Exists('..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.0\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.0\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" /> </Target> <PropertyGroup> - <PostBuildEvent> - </PostBuildEvent> + <PostBuildEvent>del $(TargetDir)Tango.TCC.CardDetector.dll</PostBuildEvent> </PropertyGroup> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/Web.config b/Software/Visual_Studio/TCC/Tango.TCC.Service/Web.config index 291a5baec..9ef7bc67d 100644 --- a/Software/Visual_Studio/TCC/Tango.TCC.Service/Web.config +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/Web.config @@ -29,7 +29,7 @@ <add key="CARD_COLUMNS" value="10" /> <add key="CARD_ROWS" value="11" /> - <add key="CARD_TARGET_INDEX" value="99" /> + <add key="CARD_TARGET_INDEX" value="89" /> <add key="TEMPLATE_STRING" value="PUT TEMPLATE STRING HERE!" /> <add key="SAMPLE_WIDTH" value="300" /> <add key="SAMPLE_HEIGHT" value="330" /> @@ -44,7 +44,9 @@ </appSettings> <system.web> - <compilation debug="true" targetFramework="4.6.1" /> + <compilation debug="true" targetFramework="4.6.1"> + + </compilation> <httpRuntime targetFramework="4.6.1" maxRequestLength="4096" /> <httpModules> <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" /> diff --git a/Software/Visual_Studio/TCC/Tango.TCC.Service/packages.config b/Software/Visual_Studio/TCC/Tango.TCC.Service/packages.config index 115c40d26..39d7af46a 100644 --- a/Software/Visual_Studio/TCC/Tango.TCC.Service/packages.config +++ b/Software/Visual_Studio/TCC/Tango.TCC.Service/packages.config @@ -5,6 +5,7 @@ <package id="EntityFramework" version="6.2.0" targetFramework="net461" /> <package id="Google.Protobuf" version="3.4.1" targetFramework="net461" /> <package id="jQuery" version="3.3.1" targetFramework="net461" /> + <package id="JWT" version="5.0.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights" version="2.5.1" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.Agent.Intercept" version="2.4.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.DependencyCollector" version="2.5.1" targetFramework="net461" /> diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/BitmapExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/BitmapExtensions.cs index 3cca605e9..34e3d9ea2 100644 --- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/BitmapExtensions.cs +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/BitmapExtensions.cs @@ -20,5 +20,13 @@ public static class BitmapExtensions var encParams = new EncoderParameters() { Param = new[] { new EncoderParameter(Encoder.Quality, quality) } }; bitmap.Save(filePath, encoder, encParams); } + + public static Bitmap ConvertTo24Bit(this Bitmap bitmap) + { + var bmp = new Bitmap(bitmap.Width, bitmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + using (var gr = Graphics.FromImage(bmp)) + gr.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height)); + return bmp; + } } diff --git a/Software/Visual_Studio/Tango.UnitTesting/MachineService/MachineStudio_Controller_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/MachineService/MachineStudio_Controller_TST.cs index d4585388a..e30cd6d77 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/MachineService/MachineStudio_Controller_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/MachineService/MachineStudio_Controller_TST.cs @@ -22,14 +22,14 @@ namespace Tango.UnitTesting.MachineService IWebTransportClient client = new WebTransportClient(); - var res1 = client.PostJson<LoginRequest, LoginResponse>($"{address}/api/MachineStudio/Login", new LoginRequest() - { - Email = "TestUser@twine-s.com", - Password = "ASJH_asdjkl1234", - Version = "1.0.0.0" - }).Result; + //var res1 = client.PostJson<LoginRequest, LoginResponse>($"{address}/api/MachineStudio/Login", new LoginRequest() + //{ + // Email = "TestUser@twine-s.com", + // Password = "ASJH_asdjkl1234", + // Version = "1.0.0.0" + //}).Result; - String token = res1.AccessToken; + String token = "1234"; client.AuthenticationToken = token; var res2 = client.PostJson<CheckForUpdatesRequest, CheckForUpdatesResponse>($"{address}/api/MachineStudio/CheckForUpdates", new CheckForUpdatesRequest() diff --git a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs index 32cc3f83c..5d96a7249 100644 --- a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs +++ b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs @@ -109,11 +109,11 @@ namespace Tango.Web.Controllers var authorizationHeader = request.Headers.Authorization; - if (authorizationHeader != null && authorizationHeader.Parameter != null) + if (authorizationHeader != null) { try { - RequestToken = WebToken<T>.FromToken(authorizationHeader.Parameter); + RequestToken = WebToken<T>.FromToken(authorizationHeader.Parameter != null ? authorizationHeader.Parameter : authorizationHeader.ToString()); } catch (Exception ex) { diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 399ca9aa7..2dc6e80b2 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -124,8 +124,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.MachineStudio.Updater EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.ILMerge.UI", "Utilities\Tango.ILMerge.UI\Tango.ILMerge.UI.csproj", "{9A477128-25A1-4B27-AAAB-7421F8ED2B9D}" EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Tango.Stubs.Installer", "Utilities\Tango.Stubs.Installer\Tango.Stubs.Installer.vdproj", "{6B399B28-83AE-4AD2-8438-25799B65086F}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Embroidery", "Embroidery", "{34839F9A-61D3-4ED3-B3F7-7DA3424CB0B6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libEmbroidery", "Embroidery\project-files\visualstudio\libEmbroideryVS2008.vcxproj", "{BD30C7BD-9230-4ED7-B581-11F14041909D}" @@ -2272,31 +2270,6 @@ Global {9A477128-25A1-4B27-AAAB-7421F8ED2B9D}.Release|x64.Build.0 = Release|Any CPU {9A477128-25A1-4B27-AAAB-7421F8ED2B9D}.Release|x86.ActiveCfg = Release|Any CPU {9A477128-25A1-4B27-AAAB-7421F8ED2B9D}.Release|x86.Build.0 = Release|Any CPU - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|Any CPU.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|Any CPU.Build.0 = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|ARM.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|ARM.Build.0 = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|ARM64.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|ARM64.Build.0 = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|x64.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|x64.Build.0 = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|x86.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.AppVeyor|x86.Build.0 = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.Debug|Any CPU.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.Debug|ARM.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.Debug|ARM64.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.Debug|x64.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.Debug|x86.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.DefaultBuild|Any CPU.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.DefaultBuild|ARM.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.DefaultBuild|ARM64.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.DefaultBuild|x64.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.DefaultBuild|x86.ActiveCfg = Debug - {6B399B28-83AE-4AD2-8438-25799B65086F}.Release|Any CPU.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.Release|ARM.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.Release|ARM64.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.Release|x64.ActiveCfg = Release - {6B399B28-83AE-4AD2-8438-25799B65086F}.Release|x86.ActiveCfg = Release {BD30C7BD-9230-4ED7-B581-11F14041909D}.AppVeyor|Any CPU.ActiveCfg = Release|Win32 {BD30C7BD-9230-4ED7-B581-11F14041909D}.AppVeyor|Any CPU.Build.0 = Release|Win32 {BD30C7BD-9230-4ED7-B581-11F14041909D}.AppVeyor|ARM.ActiveCfg = Release|Win32 @@ -5302,7 +5275,6 @@ Global {FC337A7F-1214-41D8-9992-78092A3B961E} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} {844787CE-F409-4F18-BCCC-F3809ECB86F3} = {57DF2A95-5DDD-4830-A4AF-B484B59C7C2B} {9A477128-25A1-4B27-AAAB-7421F8ED2B9D} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} - {6B399B28-83AE-4AD2-8438-25799B65086F} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {BD30C7BD-9230-4ED7-B581-11F14041909D} = {34839F9A-61D3-4ED3-B3F7-7DA3424CB0B6} {0565AEEC-ED1B-4F0E-A277-D33F852207BC} = {34839F9A-61D3-4ED3-B3F7-7DA3424CB0B6} {69DB0564-268C-4B3C-B5D6-A3CDC7D14EAE} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} @@ -5366,12 +5338,12 @@ Global {B0EFE7A0-7039-4DC4-8B39-465E521299F6} = {3D750293-C243-48F6-9112-A6B3FF650C0D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - BuildVersion_UseGlobalSettings = False - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs - BuildVersion_StartDate = 2000/1/1 - BuildVersion_UpdateFileVersion = False - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_UpdateFileVersion = False + BuildVersion_StartDate = 2000/1/1 + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_UseGlobalSettings = False EndGlobalSection EndGlobal |
