diff options
| author | Roy Ben Shabat <roy@twine-s.com> | 2017-11-08 21:47:25 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2017-11-08 21:47:25 +0200 |
| commit | 6626d0227c28c0a9f990e08c431e8b80739ea58d (patch) | |
| tree | 23e5fe5d6b258618d7ae2fe7a23b4762e0750534 | |
| parent | d615c26b41af480dae0bf478133c9333c319a6ce (diff) | |
| download | Tango-6626d0227c28c0a9f990e08c431e8b80739ea58d.tar.gz Tango-6626d0227c28c0a9f990e08c431e8b80739ea58d.zip | |
Working on integration !!
46 files changed, 1233 insertions, 82 deletions
diff --git a/Software/Android-Studio/Tango.Integration/.gitignore b/Software/Android-Studio/Tango.Integration/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/.gitignore @@ -0,0 +1 @@ +/build diff --git a/Software/Android-Studio/Tango.Integration/build.gradle b/Software/Android-Studio/Tango.Integration/build.gradle new file mode 100644 index 000000000..dc482d641 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/build.gradle @@ -0,0 +1,46 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 26 + buildToolsVersion "26.0.1" + + + defaultConfig { + minSdkVersion 22 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + dexOptions { + preDexLibraries = false + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:26.1.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' + compile globalDependencies.rxJavaAndroid + compile globalDependencies.rxJava + compile globalDependencies.logging + compile globalDependencies.dagger + compile globalDependencies.daggerAndroid + implementation project(':Tango.PMR') +} diff --git a/Software/Android-Studio/Tango.Integration/proguard-rules.pro b/Software/Android-Studio/Tango.Integration/proguard-rules.pro new file mode 100644 index 000000000..a0eef131a --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\Roy\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/Software/Android-Studio/Tango.Integration/src/androidTest/java/com/twine/tango/integration/ExampleInstrumentedTest.java b/Software/Android-Studio/Tango.Integration/src/androidTest/java/com/twine/tango/integration/ExampleInstrumentedTest.java new file mode 100644 index 000000000..52db49c5f --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/androidTest/java/com/twine/tango/integration/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.twine.tango.integration; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.twine.tango.integration.test", appContext.getPackageName()); + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/AndroidManifest.xml b/Software/Android-Studio/Tango.Integration/src/main/AndroidManifest.xml new file mode 100644 index 000000000..b57dcb665 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.twine.tango.integration"> + + <uses-permission android:name="android.permission.INTERNET"/> + +</manifest> diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/SerialAdapter.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/SerialAdapter.java new file mode 100644 index 000000000..5224a0729 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/SerialAdapter.java @@ -0,0 +1,20 @@ +package com.twine.tango.integration.adapters; + +import java.io.IOException; + +import io.reactivex.Observable; + +/** + * Created by Roy on 11/8/2017. + */ + +public interface SerialAdapter { + + void setAddress(String address); + String getAddress(); + void open() throws IOException; + void close() throws IOException; + void write(byte[] data) throws IOException; + Observable<byte[]> registerReceiveListener(); + boolean getIsOpen(); +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/TcpAdapter.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/TcpAdapter.java new file mode 100644 index 000000000..3858b2c5f --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/adapters/TcpAdapter.java @@ -0,0 +1,92 @@ +package com.twine.tango.integration.adapters; + +import android.os.SystemClock; +import com.elvishew.xlog.XLog; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import io.reactivex.Observable; +import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Roy on 11/8/2017. + */ + +public class TcpAdapter implements SerialAdapter { + + private Socket socket; + private String address; + private boolean isOpen; + private static final int port = 9999; + private Thread receiveThread; + private PublishSubject<byte[]> subject; + + public TcpAdapter(String address) { + this.address = address; + } + + @Override + public void setAddress(String address) { + this.address = address; + } + + @Override + public String getAddress() { + return this.address; + } + + @Override + public void open() throws IOException { + socket = new Socket(address, port); + isOpen = true; + receiveThread = new Thread(this::receiveThreadMethod); + receiveThread.start(); + } + + @Override + public void close() throws IOException { + socket.close(); + isOpen = false; + } + + @Override + public void write(byte[] data) throws IOException { + socket.getOutputStream().write(data); + } + + @Override + public Observable<byte[]> registerReceiveListener() { + subject = PublishSubject.create(); + return subject.observeOn(Schedulers.io()); + } + + @Override + public boolean getIsOpen() { + return isOpen; + } + + private void receiveThreadMethod() { + while (isOpen) { + + try { + + InputStream stream = socket.getInputStream(); + + if (stream.available() > 0) + { + byte[] data = new byte[stream.available()]; + int read = stream.read(data); + if (subject != null && read > 0) subject.onNext(data); + } + + } catch (Exception e) { + isOpen = false; + XLog.e(e); + if (subject != null) subject.onError(e); + } + + SystemClock.sleep(10); + } + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperator.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperator.java new file mode 100644 index 000000000..826a7a476 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperator.java @@ -0,0 +1,244 @@ +package com.twine.tango.integration.machine; + +import android.os.SystemClock; +import com.elvishew.xlog.XLog; +import com.google.protobuf.GeneratedMessageV3; +import com.google.protobuf.InvalidProtocolBufferException; +import com.twine.tango.integration.adapters.SerialAdapter; +import com.twine.tango.pmr.MessageFactory; +import com.twine.tango.pmr.TangoMessage; +import com.twine.tango.pmr.common.MessageContainerOuterClass.MessageContainer; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Locale; +import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; + +import javax.inject.Inject; + +import io.reactivex.Observable; +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Roy on 11/8/2017. + */ + +public class MachineOperator implements MachineOperatorInterface { + + private SerialAdapter channel; + private Calendar calendar; + private DateFormat dateFormatter; + private ConcurrentLinkedQueue<RequestMessage> requestsQueue; + private List<RequestMessage> pendingRequests; + private ConcurrentLinkedQueue<ResponseMessage> responsesQueue; + private PublishSubject<byte[]> receiveDataSubject; + private Thread pushThread; + private Thread pullThread; + private boolean isConnected; + private Scheduler ioScheduler; + private Scheduler uiScheduler; + + @Inject + public MachineOperator(SerialAdapter channel) { + + ioScheduler = Schedulers.io(); + uiScheduler = AndroidSchedulers.mainThread(); + calendar = Calendar.getInstance(); + dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS", Locale.US); + requestsQueue = new ConcurrentLinkedQueue<>(); + pendingRequests = new ArrayList<>(); + responsesQueue = new ConcurrentLinkedQueue<>(); + + setCommunicationChannel(channel); + + connect().subscribe(); + } + + private void setCommunicationChannel(SerialAdapter channel) { + if (channel.getIsOpen()) { + try { + channel.close(); + } catch (IOException e) { + XLog.e(e); + } + } + + boolean reconnect = false; + + if (isConnected) { + reconnect = true; + disconnect(); + } + + this.channel = channel; + this.channel.registerReceiveListener().subscribe((data) -> + { + + try { + MessageContainer container = MessageContainer.parseFrom(data); + + RequestMessage pendingRequest = Observable.fromIterable(pendingRequests).filter(x -> x.getToken().equals(container.getToken())).blockingFirst(null); + + if (pendingRequest != null) { + pendingRequests.remove(pendingRequest); + responsesQueue.add(new ResponseMessage(pendingRequest.getSubject(), pendingRequest.getResponseClass(), data)); + } else { + XLog.w("Could not find matching request for response: %s", container.getType().toString()); + } + } catch (InvalidProtocolBufferException e) { + XLog.e(e); + } + + if (receiveDataSubject != null) + { + receiveDataSubject.onNext(data); + } + + }); + + if (reconnect) { + connect(); + } + } + + public <Request extends GeneratedMessageV3, Response extends GeneratedMessageV3> Observable<Response> send(TangoMessage<Request> message, Class<Response> className) { + + PublishSubject<Response> subject = PublishSubject.create(); + requestsQueue.add(new RequestMessage<>(subject, message, className, UUID.randomUUID().toString(), calendar.getTime())); + return subject.subscribeOn(ioScheduler).observeOn(uiScheduler); + } + + + @Override + public Observable connect() { + + return Observable.create((x) -> + { + try { + channel.open(); + isConnected = true; + startThreads(); + x.onComplete(); + } catch (Exception e) { + XLog.e("Could not connect to Tango machine.", e); + x.onError(e); + } + + }).subscribeOn(ioScheduler).observeOn(uiScheduler); + + } + + @Override + public Observable disconnect() { + + return Observable.create((x) -> + { + try { + channel.close(); + isConnected = false; + x.onComplete(); + stopThreads(); + } catch (Exception e) { + XLog.e("Could not disconnect from Tango machine.", e); + x.onError(e); + } + + }).subscribeOn(ioScheduler).observeOn(uiScheduler); + + } + + private void startThreads() { + pushThread = new Thread(this::pushThreadMethod, "Push Thread"); + pushThread.start(); + + pullThread = new Thread(this::pullThreadMethod, "Pull Thread"); + pullThread.start(); + } + + private void stopThreads() { + isConnected = false; + pullThread.interrupt(); + pushThread.interrupt(); + } + + public void writeData(byte[] data) + { + try { + channel.write(data); + } catch (IOException e) { + XLog.e(e); + } + } + + @Override + public Observable<byte[]> receiveData() { + receiveDataSubject = PublishSubject.create(); + return receiveDataSubject.observeOn(uiScheduler).subscribeOn(ioScheduler); + } + + private void pushThreadMethod() { + + while (isConnected) { + + if (requestsQueue.size() > 0) { + RequestMessage request = requestsQueue.poll(); + if (request != null) { + pendingRequests.add(request); + try { + channel.write(request.getMessage().toBytes()); + } catch (IOException e) { + isConnected = false; + XLog.e(e); + } + } + } + + SystemClock.sleep(10); + } + } + + private void pullThreadMethod() { + while (isConnected) { + + if (responsesQueue.size() > 0) { + ResponseMessage response = responsesQueue.poll(); + if (response != null) { + + try { + TangoMessage message = MessageFactory.parseContainer(response.getData(), response.getResponseClass()); + response.getSubject().onNext(message); + response.getSubject().onComplete(); + } catch (Exception e) { + response.getSubject().onError(e); + XLog.e("Could not parse response.", e); + } + + } + } + + SystemClock.sleep(10); + } + } + + private void postRequest(RequestMessage request) { + +// SystemClock.sleep(5000); +// +// TangoMessage<Job> jobTangoMessage = MessageFactory.createContainer(Job.class); +// +// jobTangoMessage.setMessage(Job.newBuilder().setName("Result Job").build()); +// +// XLog.d("Posting result for request: %s TIME: %s", request.token, dateFormatter.format(request.dateTime)); +// +// request.subject.onNext(jobTangoMessage.getMessage()); +// +// request.subject.onComplete(); + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperatorInterface.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperatorInterface.java new file mode 100644 index 000000000..39e7e31d7 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MachineOperatorInterface.java @@ -0,0 +1,19 @@ +package com.twine.tango.integration.machine; + +import com.google.protobuf.GeneratedMessageV3; +import com.twine.tango.pmr.TangoMessage; + +import io.reactivex.Observable; + +/** + * Created by Roy on 11/8/2017. + */ + +public interface MachineOperatorInterface { + + <Request extends GeneratedMessageV3, Response extends GeneratedMessageV3> Observable<Response> send(TangoMessage<Request> message,Class<Response> className); + Observable connect(); + Observable disconnect(); + void writeData(byte[] data); + Observable<byte[]> receiveData(); +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MessageBase.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MessageBase.java new file mode 100644 index 000000000..c34e3653a --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/MessageBase.java @@ -0,0 +1,24 @@ +package com.twine.tango.integration.machine; + +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Roy on 11/8/2017. + */ + +public class MessageBase { + + private PublishSubject subject; + + public PublishSubject getSubject() { + return subject; + } + + public void setSubject(PublishSubject subject) { + this.subject = subject; + } + + public MessageBase(PublishSubject subject) { + this.subject = subject; + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/RequestMessage.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/RequestMessage.java new file mode 100644 index 000000000..dde1ff765 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/RequestMessage.java @@ -0,0 +1,59 @@ +package com.twine.tango.integration.machine; + +import com.google.protobuf.GeneratedMessageV3; +import com.twine.tango.pmr.TangoMessage; + +import java.util.Date; + +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Roy on 11/8/2017. + */ +public class RequestMessage<T extends GeneratedMessageV3,Response extends GeneratedMessageV3> extends MessageBase { + + private String token; + private Date dateTime; + private TangoMessage<T> message; + private Class<Response> responseClass; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Date getDateTime() { + return dateTime; + } + + public void setDateTime(Date dateTime) { + this.dateTime = dateTime; + } + + public TangoMessage<T> getMessage() { + return message; + } + + public void setMessage(TangoMessage<T> message) { + this.message = message; + } + + public Class<Response> getResponseClass() { + return responseClass; + } + + public void setResponseClass(Class<Response> responseClass) { + this.responseClass = responseClass; + } + + public RequestMessage(PublishSubject subject, TangoMessage<T> message, Class<Response> responseClass, String token, Date time) { + super(subject); + this.message = message; + this.token = token; + this.dateTime = time; + this.responseClass = responseClass; + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/ResponseMessage.java b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/ResponseMessage.java new file mode 100644 index 000000000..13de24286 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/java/com/twine/tango/integration/machine/ResponseMessage.java @@ -0,0 +1,37 @@ +package com.twine.tango.integration.machine; + +import com.twine.tango.pmr.TangoMessage; + +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Roy on 11/8/2017. + */ + +public class ResponseMessage extends MessageBase { + + private byte[] data; + private Class<?> responseClass; + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public Class<?> getResponseClass() { + return responseClass; + } + + public void setResponseClass(Class<?> responseClass) { + this.responseClass = responseClass; + } + + public ResponseMessage(PublishSubject subject, Class<?> responseClass, byte[] data) { + super(subject); + this.data = data; + this.responseClass = responseClass; + } +} diff --git a/Software/Android-Studio/Tango.Integration/src/main/res/values/strings.xml b/Software/Android-Studio/Tango.Integration/src/main/res/values/strings.xml new file mode 100644 index 000000000..58ea29ec7 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ +<resources> + <string name="app_name">Tango.Integration</string> +</resources> diff --git a/Software/Android-Studio/Tango.Integration/src/test/java/com/twine/tango/integration/ExampleUnitTest.java b/Software/Android-Studio/Tango.Integration/src/test/java/com/twine/tango/integration/ExampleUnitTest.java new file mode 100644 index 000000000..3bba564e2 --- /dev/null +++ b/Software/Android-Studio/Tango.Integration/src/test/java/com/twine/tango/integration/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.twine.tango.integration; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +}
\ No newline at end of file diff --git a/Software/Android-Studio/Tango.Models/src/main/java/com/twine/tango/models/stubs/Stub.java b/Software/Android-Studio/Tango.Models/src/main/java/com/twine/tango/models/stubs/Stub.java deleted file mode 100644 index 397c4b4e4..000000000 --- a/Software/Android-Studio/Tango.Models/src/main/java/com/twine/tango/models/stubs/Stub.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.twine.tango.models.stubs; - -import android.databinding.BaseObservable; -import android.databinding.Bindable; -import com.twine.tango.models.BR; - -/** - * Created by Roy on 11/7/2017. - */ - -public class Stub extends BaseObservable { - - private String name; - private String description; - - @Bindable - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - notifyPropertyChanged(BR.name); - } - - @Bindable - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - notifyPropertyChanged(BR.description); - } -} diff --git a/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/MessageFactory.java b/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/MessageFactory.java index 2d33ed4db..f8f49c010 100644 --- a/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/MessageFactory.java +++ b/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/MessageFactory.java @@ -44,7 +44,8 @@ public class MessageFactory { * @param <T> Type of expected inner message. * @return New instance of {@link TangoMessage}. */ - public static <T extends com.google.protobuf.GeneratedMessageV3> TangoMessage<T> parseContainer(byte[] data, Class<T> typeName) { + @SuppressWarnings("unchecked") + public static <T extends com.google.protobuf.GeneratedMessageV3> TangoMessage<T> parseContainer(byte[] data, Class<?> typeName) { try { MessageContainer container = MessageContainer.parseFrom(data); Parser<T> parser = (Parser<T>) typeName.getMethod("parser").invoke(null); diff --git a/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/common/MessageContainerOuterClass.java b/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/common/MessageContainerOuterClass.java index 6e6a3df01..24e2fc7f9 100644 --- a/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/common/MessageContainerOuterClass.java +++ b/Software/Android-Studio/Tango.PMR/src/main/java/com/twine/tango/pmr/common/MessageContainerOuterClass.java @@ -28,7 +28,17 @@ public final class MessageContainerOuterClass { com.twine.tango.pmr.common.MessageTypeOuterClass.MessageType getType(); /** - * <code>bytes Data = 2;</code> + * <code>string Token = 2;</code> + */ + java.lang.String getToken(); + /** + * <code>string Token = 2;</code> + */ + com.google.protobuf.ByteString + getTokenBytes(); + + /** + * <code>bytes Data = 3;</code> */ com.google.protobuf.ByteString getData(); } @@ -46,6 +56,7 @@ public final class MessageContainerOuterClass { } private MessageContainer() { type_ = 0; + token_ = ""; data_ = com.google.protobuf.ByteString.EMPTY; } @@ -84,6 +95,12 @@ public final class MessageContainerOuterClass { break; } case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + token_ = s; + break; + } + case 26: { data_ = input.readBytes(); break; @@ -128,10 +145,44 @@ public final class MessageContainerOuterClass { return result == null ? com.twine.tango.pmr.common.MessageTypeOuterClass.MessageType.UNRECOGNIZED : result; } - public static final int DATA_FIELD_NUMBER = 2; + public static final int TOKEN_FIELD_NUMBER = 2; + private volatile java.lang.Object token_; + /** + * <code>string Token = 2;</code> + */ + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } + } + /** + * <code>string Token = 2;</code> + */ + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DATA_FIELD_NUMBER = 3; private com.google.protobuf.ByteString data_; /** - * <code>bytes Data = 2;</code> + * <code>bytes Data = 3;</code> */ public com.google.protobuf.ByteString getData() { return data_; @@ -152,8 +203,11 @@ public final class MessageContainerOuterClass { if (type_ != com.twine.tango.pmr.common.MessageTypeOuterClass.MessageType.RGB.getNumber()) { output.writeEnum(1, type_); } + if (!getTokenBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, token_); + } if (!data_.isEmpty()) { - output.writeBytes(2, data_); + output.writeBytes(3, data_); } unknownFields.writeTo(output); } @@ -167,9 +221,12 @@ public final class MessageContainerOuterClass { size += com.google.protobuf.CodedOutputStream .computeEnumSize(1, type_); } + if (!getTokenBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, token_); + } if (!data_.isEmpty()) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, data_); + .computeBytesSize(3, data_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -188,6 +245,8 @@ public final class MessageContainerOuterClass { boolean result = true; result = result && type_ == other.type_; + result = result && getToken() + .equals(other.getToken()); result = result && getData() .equals(other.getData()); result = result && unknownFields.equals(other.unknownFields); @@ -203,6 +262,8 @@ public final class MessageContainerOuterClass { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TYPE_FIELD_NUMBER; hash = (53 * hash) + type_; + hash = (37 * hash) + TOKEN_FIELD_NUMBER; + hash = (53 * hash) + getToken().hashCode(); hash = (37 * hash) + DATA_FIELD_NUMBER; hash = (53 * hash) + getData().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); @@ -336,6 +397,8 @@ public final class MessageContainerOuterClass { super.clear(); type_ = 0; + token_ = ""; + data_ = com.google.protobuf.ByteString.EMPTY; return this; @@ -361,6 +424,7 @@ public final class MessageContainerOuterClass { public com.twine.tango.pmr.common.MessageContainerOuterClass.MessageContainer buildPartial() { com.twine.tango.pmr.common.MessageContainerOuterClass.MessageContainer result = new com.twine.tango.pmr.common.MessageContainerOuterClass.MessageContainer(this); result.type_ = type_; + result.token_ = token_; result.data_ = data_; onBuilt(); return result; @@ -406,6 +470,10 @@ public final class MessageContainerOuterClass { if (other.type_ != 0) { setTypeValue(other.getTypeValue()); } + if (!other.getToken().isEmpty()) { + token_ = other.token_; + onChanged(); + } if (other.getData() != com.google.protobuf.ByteString.EMPTY) { setData(other.getData()); } @@ -480,15 +548,84 @@ public final class MessageContainerOuterClass { return this; } + private java.lang.Object token_ = ""; + /** + * <code>string Token = 2;</code> + */ + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * <code>string Token = 2;</code> + */ + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * <code>string Token = 2;</code> + */ + public Builder setToken( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + token_ = value; + onChanged(); + return this; + } + /** + * <code>string Token = 2;</code> + */ + public Builder clearToken() { + + token_ = getDefaultInstance().getToken(); + onChanged(); + return this; + } + /** + * <code>string Token = 2;</code> + */ + public Builder setTokenBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + token_ = value; + onChanged(); + return this; + } + private com.google.protobuf.ByteString data_ = com.google.protobuf.ByteString.EMPTY; /** - * <code>bytes Data = 2;</code> + * <code>bytes Data = 3;</code> */ public com.google.protobuf.ByteString getData() { return data_; } /** - * <code>bytes Data = 2;</code> + * <code>bytes Data = 3;</code> */ public Builder setData(com.google.protobuf.ByteString value) { if (value == null) { @@ -500,7 +637,7 @@ public final class MessageContainerOuterClass { return this; } /** - * <code>bytes Data = 2;</code> + * <code>bytes Data = 3;</code> */ public Builder clearData() { @@ -572,10 +709,10 @@ public final class MessageContainerOuterClass { static { java.lang.String[] descriptorData = { "\n\026MessageContainer.proto\022\020Tango.PMR.Comm" + - "on\032\021MessageType.proto\"M\n\020MessageContaine" + + "on\032\021MessageType.proto\"\\\n\020MessageContaine" + "r\022+\n\004Type\030\001 \001(\0162\035.Tango.PMR.Common.Messa" + - "geType\022\014\n\004Data\030\002 \001(\014B\034\n\032com.twine.tango." + - "pmr.commonb\006proto3" + "geType\022\r\n\005Token\030\002 \001(\t\022\014\n\004Data\030\003 \001(\014B\034\n\032c" + + "om.twine.tango.pmr.commonb\006proto3" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { @@ -595,7 +732,7 @@ public final class MessageContainerOuterClass { internal_static_Tango_PMR_Common_MessageContainer_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_Tango_PMR_Common_MessageContainer_descriptor, - new java.lang.String[] { "Type", "Data", }); + new java.lang.String[] { "Type", "Token", "Data", }); com.twine.tango.pmr.common.MessageTypeOuterClass.getDescriptor(); } diff --git a/Software/Android-Studio/Tango.Stubs.UI/build.gradle b/Software/Android-Studio/Tango.Stubs.UI/build.gradle index 3dbe0dcd8..880cbd631 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/build.gradle +++ b/Software/Android-Studio/Tango.Stubs.UI/build.gradle @@ -48,8 +48,8 @@ dependencies { androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' //Extensions compile 'io.reactivex.rxjava2:rxjava:2.1.2' - compile 'com.google.dagger:dagger:2.11' - compile 'com.google.dagger:dagger-android:2.11' + compile globalDependencies.dagger + compile globalDependencies.daggerAndroid compile 'com.squareup:otto:1.3.8' compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.2.0' compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.2.0' @@ -60,4 +60,6 @@ dependencies { annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0' compile project(path: ':Tango.SharedUI') implementation project(':Tango.Models') + implementation project(':Tango.Stubs') + implementation project(':Tango.Integration') } diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/AndroidManifest.xml b/Software/Android-Studio/Tango.Stubs.UI/src/main/AndroidManifest.xml index 172ff0b37..d609ad25d 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/AndroidManifest.xml +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.twine.tango.stubs.ui"> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <application android:name=".App" android:allowBackup="true" diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/App.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/App.java index 95363bd4c..e01ccf695 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/App.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/App.java @@ -2,11 +2,24 @@ package com.twine.tango.stubs.ui; import android.app.Application; import android.content.Context; +import android.os.Environment; +import com.elvishew.xlog.LogConfiguration; +import com.elvishew.xlog.LogLevel; +import com.elvishew.xlog.XLog; +import com.elvishew.xlog.formatter.message.object.ObjectFormatter; +import com.elvishew.xlog.printer.AndroidPrinter; +import com.elvishew.xlog.printer.Printer; +import com.elvishew.xlog.printer.file.FilePrinter; +import com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy; +import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator; +import com.google.protobuf.GeneratedMessageV3; import com.twine.tango.stubs.ui.dagger.ApplicationComponent; import com.twine.tango.stubs.ui.dagger.ApplicationModule; import com.twine.tango.stubs.ui.dagger.DaggerApplicationComponent; +import java.io.File; + /** * Created by Roy on 11/6/2017. */ @@ -20,8 +33,7 @@ public class App extends Application { return appComponent; } - protected ApplicationComponent initDagger(App application) - { + protected ApplicationComponent initDagger(App application) { return DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(application)).build(); } @@ -30,15 +42,33 @@ public class App extends Application { super.onCreate(); appComponent = initDagger(this); context = getApplicationContext(); + + LogConfiguration config = new LogConfiguration.Builder() + .logLevel(LogLevel.ALL) + .tag("Tango") + .t() + .st(2) + .b() + .addObjectFormatter(GeneratedMessageV3.class, msg -> msg.toString()).build(); + + File sdcard = Environment.getExternalStorageDirectory(); + File dir = new File(sdcard.getAbsolutePath() + "/twine/tango/logs"); + boolean b = dir.mkdirs(); + + Printer androidPrinter = new AndroidPrinter(); + Printer filePrinter = new FilePrinter.Builder(dir.getPath()) + .fileNameGenerator(new DateFileNameGenerator()) + .backupStrategy(new FileSizeBackupStrategy(1024 * 1024)) + .build(); + + XLog.init(config, androidPrinter, filePrinter); } - public static ApplicationComponent getComponent() - { - return ((App)context).getAppComponent(); + public static ApplicationComponent getComponent() { + return ((App) context).getAppComponent(); } - public static Context getContext() - { + public static Context getContext() { return context; } } diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/Events/StubSelectedEvent.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/Events/StubSelectedEvent.java index 095971534..349251dd4 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/Events/StubSelectedEvent.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/Events/StubSelectedEvent.java @@ -1,6 +1,6 @@ package com.twine.tango.stubs.ui.Events; -import com.twine.tango.models.stubs.Stub; +import com.twine.tango.stubs.Stub; /** * Created by Roy on 11/7/2017. diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ApplicationComponent.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ApplicationComponent.java index 70eb8d8c3..f567591e5 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ApplicationComponent.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ApplicationComponent.java @@ -16,7 +16,7 @@ import dagger.Component; */ @Singleton -@Component(modules = {ApplicationModule.class, ViewModelsModule.class, EventBusModule.class, NotificationModule.class}) +@Component(modules = {ApplicationModule.class, ViewModelsModule.class, EventBusModule.class, NotificationModule.class, IntegrationModule.class}) public interface ApplicationComponent { void inject(MainActivity view); diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/IntegrationModule.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/IntegrationModule.java new file mode 100644 index 000000000..130c5661c --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/IntegrationModule.java @@ -0,0 +1,28 @@ +package com.twine.tango.stubs.ui.dagger; + +import com.twine.tango.integration.adapters.SerialAdapter; +import com.twine.tango.integration.adapters.TcpAdapter; +import com.twine.tango.integration.machine.MachineOperator; +import com.twine.tango.integration.machine.MachineOperatorInterface; +import javax.inject.Singleton; +import dagger.Module; +import dagger.Provides; + +/** + * Created by Roy on 11/8/2017. + */ + +@Module +public class IntegrationModule { + + @Provides + @Singleton + public MachineOperatorInterface provideMachineOperator(SerialAdapter serialAdapter) { + return new MachineOperator(serialAdapter); + } + + @Provides + public SerialAdapter provideSerialAdapter() { + return new TcpAdapter("10.0.2.2"); + } +} diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ViewModelsModule.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ViewModelsModule.java index f684e2015..b146db02d 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ViewModelsModule.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/dagger/ViewModelsModule.java @@ -1,6 +1,7 @@ package com.twine.tango.stubs.ui.dagger; import com.squareup.otto.Bus; +import com.twine.tango.integration.machine.MachineOperatorInterface; import com.twine.tango.sharedui.notifications.NotificationProvider; import com.twine.tango.stubs.ui.views.login.LoginFragment; import com.twine.tango.stubs.ui.views.login.LoginFragmentVM; @@ -47,7 +48,7 @@ public class ViewModelsModule { @Provides @Singleton - public StubActivityVM provideStubActivityVM(Bus eventBus, NotificationProvider notificationProvider) { - return new StubActivityVM(eventBus, notificationProvider); + public StubActivityVM provideStubActivityVM(Bus eventBus, NotificationProvider notificationProvider, MachineOperatorInterface machineOperator) { + return new StubActivityVM(eventBus, notificationProvider, machineOperator); } } diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stub/StubActivityVM.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stub/StubActivityVM.java index 16fc1eafc..428cbc045 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stub/StubActivityVM.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stub/StubActivityVM.java @@ -2,7 +2,9 @@ package com.twine.tango.stubs.ui.views.stub; import com.squareup.otto.Bus; import com.squareup.otto.Subscribe; -import com.twine.tango.models.stubs.Stub; +import com.twine.tango.integration.machine.MachineOperatorInterface; +import com.twine.tango.sharedui.mvvm.RelayCommand; +import com.twine.tango.stubs.Stub; import com.twine.tango.sharedui.mvvm.DependencyProperty; import com.twine.tango.sharedui.mvvm.ViewModelBase; import com.twine.tango.sharedui.notifications.NotificationProvider; @@ -18,18 +20,21 @@ public class StubActivityVM extends ViewModelBase<StubActivityContract> { private Bus eventBus; private NotificationProvider notificationProvider; + private MachineOperatorInterface machineOperator; public DependencyProperty<Stub> stub; - public DependencyProperty<String> ss; + public RelayCommand runCommand; @Inject - public StubActivityVM(Bus eventBus, NotificationProvider notificationProvider) { + public StubActivityVM(Bus eventBus, NotificationProvider notificationProvider, MachineOperatorInterface machineOperator) { stub = new DependencyProperty<>(); - ss = new DependencyProperty<>("Hi ROy"); this.eventBus = eventBus; + this.machineOperator = machineOperator; this.notificationProvider = notificationProvider; this.eventBus.register(this); + + runCommand = new RelayCommand(this::runSelectedStub); } @Subscribe @@ -37,4 +42,10 @@ public class StubActivityVM extends ViewModelBase<StubActivityContract> { stub.set(e.getStub()); } + + private void runSelectedStub() + { + stub.get().setMachineOperator(machineOperator); + stub.get().run(); + } } diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityContract.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityContract.java index fb189be32..52bfaa36f 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityContract.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityContract.java @@ -1,6 +1,5 @@ package com.twine.tango.stubs.ui.views.stubs; -import com.twine.tango.models.stubs.Stub; import com.twine.tango.sharedui.mvvm.ViewContract; /** diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityVM.java b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityVM.java index a22684698..ac4a8d6a9 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityVM.java +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/java/com/twine/tango/stubs/ui/views/stubs/StubsActivityVM.java @@ -8,8 +8,8 @@ import android.view.View; import android.widget.AdapterView; import com.squareup.otto.Bus; -import com.squareup.otto.Subscribe; -import com.twine.tango.models.stubs.Stub; +import com.twine.tango.sharedui.mvvm.RelayCommand; +import com.twine.tango.stubs.Stub; import com.twine.tango.sharedui.mvvm.FieldUtils; import com.twine.tango.sharedui.mvvm.ViewModelBase; import com.twine.tango.stubs.ui.BR; @@ -43,12 +43,7 @@ public class StubsActivityVM extends ViewModelBase<StubsActivityContract> { selectedStub = new ObservableField<>(); selectedStubIndex = FieldUtils.toField(FieldUtils.toObservable(selectedStub).map(stub -> stubs.indexOf(stub))); - for (int i = 0; i < 20; i++) { - Stub s = new Stub(); - s.setName("Stub " + i); - s.setDescription("Description " + i); - stubs.add(s); - } + stubs.addAll(Stub.getAllStubs()); } public void onStubSelected(AdapterView<?> adapterView, View view, int i, long l) { diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stub.xml b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stub.xml index fb9891f69..0db72ee5b 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stub.xml +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stub.xml @@ -45,14 +45,14 @@ android:id="@+id/textView3" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Stub Name" + android:text="@{vm.stub.name}" android:textSize="18sp" /> <TextView android:id="@+id/textView4" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Description" /> + android:text="@{vm.stub.description}" /> </LinearLayout> </LinearLayout> </RelativeLayout> @@ -129,7 +129,8 @@ android:layout_alignParentEnd="true" android:layout_alignParentTop="true" android:tint="@color/colorPlay" - bind:srcCompat="@drawable/ic_play" /> + bind:srcCompat="@drawable/ic_play" + android:command="@{vm.runCommand}" /> <ImageButton android:id="@+id/imageButton2" diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stubs.xml b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stubs.xml index bb0598073..20fc4aae7 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stubs.xml +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/activity_stubs.xml @@ -22,7 +22,7 @@ android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:onItemClick="@{vm::onStubSelected}" - android:selectedItemPosition="@{vm.selectedStubIndex}" + android:selectedItemPosition="@{safeUnbox(vm.selectedStubIndex)}" android:choiceMode="singleChoice" app:items="@{vm.stubs}" app:itemBinding="@{vm.stubBinding}"/> diff --git a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/stubs_listview_item.xml b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/stubs_listview_item.xml index 62edcb607..5696acdf3 100644 --- a/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/stubs_listview_item.xml +++ b/Software/Android-Studio/Tango.Stubs.UI/src/main/res/layout/stubs_listview_item.xml @@ -5,7 +5,7 @@ <data> <variable name="stub" - type="com.twine.tango.models.stubs.Stub"/> + type="com.twine.tango.stubs.Stub"/> </data> <LinearLayout diff --git a/Software/Android-Studio/Tango.Stubs/.gitignore b/Software/Android-Studio/Tango.Stubs/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/.gitignore @@ -0,0 +1 @@ +/build diff --git a/Software/Android-Studio/Tango.Stubs/build.gradle b/Software/Android-Studio/Tango.Stubs/build.gradle new file mode 100644 index 000000000..05d5c6962 --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/build.gradle @@ -0,0 +1,43 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 26 + buildToolsVersion "26.0.1" + + + defaultConfig { + minSdkVersion 22 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + dataBinding { + enabled = true + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:26.1.0' + compile globalDependencies.logging + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' + implementation project(':Tango.Integration') + compile project(path: ':Tango.PMR') +} diff --git a/Software/Android-Studio/Tango.Stubs/proguard-rules.pro b/Software/Android-Studio/Tango.Stubs/proguard-rules.pro new file mode 100644 index 000000000..a0eef131a --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\Roy\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/Software/Android-Studio/Tango.Stubs/src/androidTest/java/com/twine/tango/stubs/ExampleInstrumentedTest.java b/Software/Android-Studio/Tango.Stubs/src/androidTest/java/com/twine/tango/stubs/ExampleInstrumentedTest.java new file mode 100644 index 000000000..b8283f5e3 --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/androidTest/java/com/twine/tango/stubs/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.twine.tango.stubs; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.twine.tango.stubs.test", appContext.getPackageName()); + } +} diff --git a/Software/Android-Studio/Tango.Stubs/src/main/AndroidManifest.xml b/Software/Android-Studio/Tango.Stubs/src/main/AndroidManifest.xml new file mode 100644 index 000000000..9e51ae77e --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.twine.tango.stubs" /> diff --git a/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/Stub.java b/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/Stub.java new file mode 100644 index 000000000..329114e50 --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/Stub.java @@ -0,0 +1,55 @@ +package com.twine.tango.stubs; + +import android.databinding.BaseObservable; +import android.databinding.Bindable; + +import com.twine.tango.integration.machine.MachineOperatorInterface; +import com.twine.tango.stubs.machine.basic_communication; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Roy on 11/7/2017. + */ + +public abstract class Stub extends BaseObservable { + + private String name; + private String description; + private MachineOperatorInterface machineOperator; + + public MachineOperatorInterface getMachineOperator() { + return machineOperator; + } + + public void setMachineOperator(MachineOperatorInterface machineOperator) { + this.machineOperator = machineOperator; + } + + @Bindable + public String getName() { + return name; + } + + @Bindable + public String getDescription() { + return description; + } + + public Stub(String name, String description) { + this.name = name; + this.description = description; + } + + public abstract void run(); + + + public static List<Stub> getAllStubs() + { + List<Stub> stubs = new ArrayList<>(); + + stubs.add(new basic_communication()); + + return stubs; + } +} diff --git a/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/machine/basic_communication.java b/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/machine/basic_communication.java new file mode 100644 index 000000000..4633421de --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/main/java/com/twine/tango/stubs/machine/basic_communication.java @@ -0,0 +1,35 @@ +package com.twine.tango.stubs.machine; + +import com.elvishew.xlog.XLog; +import com.twine.tango.stubs.Stub; + +/** + * Created by Roy on 11/8/2017. + */ + +public class basic_communication extends Stub { + + + public basic_communication() { + super("Basic Communication", "Open the serial port and send a test string"); + } + + @Override + public void run() { + +// for (int i = 0; i < 20; i++) { +// machine.send(MessageFactory.createContainer(Job.class), Job.class).subscribe((job) -> +// { +// String name = job.getName(); +// }); +// } + + getMachineOperator().receiveData().subscribe((data) -> + { + XLog.i(new String(data)); + }); + + String test = "This is a test..."; + getMachineOperator().writeData(test.getBytes()); + } +} diff --git a/Software/Android-Studio/Tango.Stubs/src/main/res/values/strings.xml b/Software/Android-Studio/Tango.Stubs/src/main/res/values/strings.xml new file mode 100644 index 000000000..62b1a5fd0 --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ +<resources> + <string name="app_name">Tango.Stubs</string> +</resources> diff --git a/Software/Android-Studio/Tango.Stubs/src/test/java/com/twine/tango/stubs/ExampleUnitTest.java b/Software/Android-Studio/Tango.Stubs/src/test/java/com/twine/tango/stubs/ExampleUnitTest.java new file mode 100644 index 000000000..d111c04aa --- /dev/null +++ b/Software/Android-Studio/Tango.Stubs/src/test/java/com/twine/tango/stubs/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.twine.tango.stubs; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +}
\ No newline at end of file diff --git a/Software/Android-Studio/build.gradle b/Software/Android-Studio/build.gradle index 0e2d08bbb..81ab73c7f 100644 --- a/Software/Android-Studio/build.gradle +++ b/Software/Android-Studio/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - + repositories { google() jcenter() @@ -22,6 +22,17 @@ allprojects { } } +ext { + //Support Libraries dependencies + globalDependencies = [ + logging : 'com.elvishew:xlog:1.4.0', + rxJavaAndroid: 'io.reactivex.rxjava2:rxandroid:2.0.1', + rxJava : 'io.reactivex.rxjava2:rxjava:2.1.5', + dagger : 'com.google.dagger:dagger:2.11', + daggerAndroid: 'com.google.dagger:dagger-android:2.11', + ] +} + task clean(type: Delete) { delete rootProject.buildDir } diff --git a/Software/Android-Studio/settings.gradle b/Software/Android-Studio/settings.gradle index 4a207ac0e..741bbf8c1 100644 --- a/Software/Android-Studio/settings.gradle +++ b/Software/Android-Studio/settings.gradle @@ -1 +1 @@ -include ':app', ':Tango.PMR', ':Tango.BL', ':Tango.Stubs.UI', ':Tango.Core', ':Tango.SharedUI', ':Tango.DAL', ':Tango.Models' +include ':app', ':Tango.PMR', ':Tango.BL', ':Tango.Stubs.UI', ':Tango.Core', ':Tango.SharedUI', ':Tango.DAL', ':Tango.Models', ':Tango.Stubs', ':Tango.Integration' diff --git a/Software/Graphics/database.png b/Software/Graphics/database.png Binary files differnew file mode 100644 index 000000000..4263288e8 --- /dev/null +++ b/Software/Graphics/database.png diff --git a/Software/Graphics/database.svg b/Software/Graphics/database.svg new file mode 100644 index 000000000..6dfb37069 --- /dev/null +++ b/Software/Graphics/database.svg @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 57 57" style="enable-background:new 0 0 57 57;" xml:space="preserve"> +<g> + <g> + <path style="fill:#545E73;" d="M49.455,8L49.455,8C48.724,3.538,38.281,0,25.5,0S2.276,3.538,1.545,8l0,0H1.5v0.5V20v0.5V21v11 + v0.5V33v12h0.045c0.731,4.461,11.175,8,23.955,8s23.224-3.539,23.955-8H49.5V33v-0.5V32V21v-0.5V20V8.5V8H49.455z"/> + <g> + <path style="fill:#38454F;" d="M25.5,41c-13.255,0-24-3.806-24-8.5V45h0.045c0.731,4.461,11.175,8,23.955,8 + s23.224-3.539,23.955-8H49.5V32.5C49.5,37.194,38.755,41,25.5,41z"/> + <path style="fill:#38454F;" d="M1.5,32v0.5c0-0.168,0.018-0.334,0.045-0.5H1.5z"/> + <path style="fill:#38454F;" d="M49.455,32c0.027,0.166,0.045,0.332,0.045,0.5V32H49.455z"/> + </g> + <g> + <path style="fill:#556080;" d="M25.5,29c-13.255,0-24-3.806-24-8.5V33h0.045c0.731,4.461,11.175,8,23.955,8 + s23.224-3.539,23.955-8H49.5V20.5C49.5,25.194,38.755,29,25.5,29z"/> + <path style="fill:#556080;" d="M1.5,20v0.5c0-0.168,0.018-0.334,0.045-0.5H1.5z"/> + <path style="fill:#556080;" d="M49.455,20c0.027,0.166,0.045,0.332,0.045,0.5V20H49.455z"/> + </g> + <ellipse style="fill:#91BAE1;" cx="25.5" cy="8.5" rx="24" ry="8.5"/> + <g> + <path style="fill:#8697CB;" d="M25.5,17c-13.255,0-24-3.806-24-8.5V21h0.045c0.731,4.461,11.175,8,23.955,8 + s23.224-3.539,23.955-8H49.5V8.5C49.5,13.194,38.755,17,25.5,17z"/> + <path style="fill:#8697CB;" d="M1.5,8v0.5c0-0.168,0.018-0.334,0.045-0.5H1.5z"/> + <path style="fill:#8697CB;" d="M49.455,8C49.482,8.166,49.5,8.332,49.5,8.5V8H49.455z"/> + </g> + </g> + <g> + <path style="fill:#BDC3C7;" d="M55.5,43.846l-1.444-0.278c-2.143-0.412-3.125-2.916-1.835-4.675l0.907-1.236l-1.958-1.958 + l-1.217,0.825c-1.806,1.224-4.272,0.148-4.604-2.008L45.115,33h-2.769l-0.359,1.865c-0.403,2.096-2.818,3.096-4.585,1.899 + l-1.572-1.065l-1.958,1.958l0.907,1.236c1.29,1.76,0.308,4.263-1.835,4.675L31.5,43.846v2.769l1.515,0.233 + c2.157,0.332,3.232,2.797,2.008,4.604l-0.825,1.217l1.958,1.958l1.236-0.907c1.76-1.29,4.263-0.308,4.675,1.835L42.346,57h2.769 + l0.164-1.066c0.339-2.204,2.896-3.263,4.694-1.944l0.869,0.638l1.958-1.958l-0.825-1.217c-1.224-1.806-0.148-4.272,2.008-4.604 + l1.515-0.233V43.846z"/> + <g> + <circle style="fill:#FFFFFF;" cx="43.5" cy="45" r="4"/> + <path style="fill:#ECF0F1;" d="M43.5,50c-2.757,0-5-2.243-5-5s2.243-5,5-5s5,2.243,5,5S46.257,50,43.5,50z M43.5,42 + c-1.654,0-3,1.346-3,3s1.346,3,3,3s3-1.346,3-3S45.154,42,43.5,42z"/> + </g> + </g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/Software/Graphics/stubs.png b/Software/Graphics/stubs.png Binary files differnew file mode 100644 index 000000000..5d6249d61 --- /dev/null +++ b/Software/Graphics/stubs.png diff --git a/Software/Graphics/stubs.svg b/Software/Graphics/stubs.svg new file mode 100644 index 000000000..800acead5 --- /dev/null +++ b/Software/Graphics/stubs.svg @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 504.123 504.123" style="enable-background:new 0 0 504.123 504.123;" xml:space="preserve"> +<path style="fill:#415F6F;" d="M486.006,355.446l18.117-10.24c-1.182-6.695-2.757-13.391-5.12-20.086h-20.874l-11.422-20.086 + l10.634-18.117c-4.332-5.12-9.058-10.24-14.572-14.572l-18.117,10.24l-20.086-11.815v-20.874c-0.394,0-0.788-0.394-1.575-0.394 + c-5.908-1.969-12.209-3.938-18.511-5.12l-10.634,18.117h-23.237l-10.24-18.117c-6.695,1.182-13.391,2.757-20.086,5.12v20.874 + l-20.086,11.422l-18.117-10.634c-5.12,4.332-10.24,9.058-14.572,14.572l10.24,18.117l-11.815,20.086h-20.874 + c-2.363,6.695-4.332,12.997-5.514,19.692l18.117,10.634v23.237l-18.117,10.24c1.182,6.695,2.757,13.391,5.12,20.086h20.874 + l11.422,20.086l-10.634,18.117c4.332,5.12,9.058,10.24,14.572,14.572l18.117-10.24l20.086,11.815v20.874 + c0.394,0,0.788,0.394,1.575,0.394c5.908,1.969,12.209,3.938,18.511,5.12l10.634-18.117h23.237l10.24,18.117 + c6.695-1.182,13.391-2.757,20.086-5.12v-20.874l20.086-11.422l18.117,10.634c5.12-4.332,10.24-9.058,14.572-14.572l-10.24-18.117 + l11.815-20.086h20.874c2.363-6.695,4.332-12.997,5.514-19.692l-18.117-10.634V355.446z M382.031,435.003 + c-37.809,0-68.923-30.72-68.923-68.529s30.72-68.923,68.923-68.923c37.809,0,68.923,30.72,68.923,68.529 + S419.84,435.003,382.031,435.003z"/> +<path style="fill:#26A6D1;" d="M274.905,240.049c0-7.483-0.394-15.36-1.575-22.843l-22.449-4.726l-8.271-24.418l15.36-17.329 + c-3.545-6.695-7.877-12.997-12.603-18.905l-22.055,7.483l-19.298-16.935l4.726-22.843c-6.695-3.938-13.391-7.483-20.48-10.24 + l-14.966,17.329l-25.206-5.12l-7.483-22.055c-7.483,0-15.36,0.394-22.843,1.575l-4.726,22.449l-24.418,8.271l-17.329-15.36 + c-6.695,3.545-12.997,7.877-18.905,12.603l7.483,22.055l-16.935,19.298l-22.843-4.726c-3.938,6.695-7.483,13.391-10.24,20.48 + l17.329,15.36l-5.12,25.206L0,233.748c0,7.483,0.394,15.36,1.575,22.843l22.843,4.726l8.271,24.418l-15.36,17.329 + c3.545,6.695,7.877,12.997,12.603,18.905l22.055-7.483l19.298,16.935l-5.12,22.843c6.695,3.938,13.391,7.483,20.48,10.24 + l15.36-17.329l25.206,5.12l7.483,22.055c7.483,0,15.36-0.394,22.843-1.575l4.726-22.449l24.418-8.271l17.329,15.36 + c6.695-3.545,12.997-7.877,18.905-12.603l-7.483-22.055l16.935-19.298l22.843,4.726c3.938-6.695,7.483-13.391,10.24-20.48 + l-17.329-15.36l5.12-25.206L274.905,240.049L274.905,240.049z M137.452,312.911c-42.142,0-76.406-34.265-76.406-76.406 + s34.265-76.406,76.406-76.406s76.406,34.265,76.406,76.406S179.594,312.911,137.452,312.911z"/> +<path style="fill:#638090;" d="M456.862,125.046l16.542-6.695c-0.394-5.908-1.182-11.815-2.363-17.723l-17.723-2.363l-7.483-18.511 + l11.028-14.178c-3.151-5.12-6.695-9.846-10.634-14.178l-16.542,6.695l-15.754-12.209l2.363-17.723l-1.182-0.788 + c-5.12-2.363-10.24-4.726-15.36-6.302l-11.028,14.178l-19.692-2.757l-6.695-16.935c-5.908,0.394-11.815,0.788-17.723,1.969 + l-2.363,17.723l-18.905,7.877L309.17,32.098c-5.12,3.151-9.846,6.695-14.178,10.634l6.695,16.542l-12.209,15.754l-17.723-2.363 + c-2.757,5.12-5.12,10.634-7.089,16.542l14.178,11.028l-2.757,19.692l-16.542,6.695c0.394,5.908,1.182,11.815,2.363,17.723 + l17.723,2.363l7.483,18.511l-11.028,14.178c3.151,5.12,6.695,9.846,10.634,14.178l16.542-6.695l15.754,12.209l-2.363,17.723 + l1.182,0.788c5.12,2.363,10.24,4.726,15.36,6.302l11.028-14.178l19.692,2.757l6.695,16.542c5.908-0.394,11.815-0.788,17.723-2.363 + l2.363-17.723l18.511-7.483l14.178,11.028c5.12-3.151,9.846-6.695,14.178-10.634l-6.695-16.542l12.209-15.754l17.723,2.363 + c2.757-5.12,5.12-10.634,7.089-16.542l-14.178-11.028C453.711,144.345,456.862,125.046,456.862,125.046z M366.671,183.335 + c-33.871,0-61.046-27.175-61.046-61.046s27.175-61.046,61.046-61.046s61.046,27.175,61.046,61.046S400.542,183.335,366.671,183.335z + "/> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/Software/PMR/Messages/Common/MessageContainer.proto b/Software/PMR/Messages/Common/MessageContainer.proto index ac76d28dd..ae507822f 100644 --- a/Software/PMR/Messages/Common/MessageContainer.proto +++ b/Software/PMR/Messages/Common/MessageContainer.proto @@ -8,6 +8,7 @@ import "MessageType.proto"; message MessageContainer { MessageType Type = 1; - bytes Data = 2; + string Token = 2; + bytes Data = 3; } |
