Skip to content

Commit fb18028

Browse files
committed
Finished Basic LoRa Communication + Test
1 parent 9035b6c commit fb18028

File tree

7 files changed

+275
-18
lines changed

7 files changed

+275
-18
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package net.sharksystem.asap.android.LoRaEngine;
2+
3+
import android.bluetooth.BluetoothAdapter;
4+
import android.bluetooth.BluetoothDevice;
5+
import android.bluetooth.BluetoothSocket;
6+
import android.content.Context;
7+
import android.support.test.InstrumentationRegistry;
8+
import android.support.test.runner.AndroidJUnit4;
9+
10+
import net.sharksystem.asap.android.lora.ASAPLoRaException;
11+
import net.sharksystem.asap.android.lora.LoRaBTInputOutputStream;
12+
import net.sharksystem.asap.android.lora.messages.DiscoverASAPLoRaMessage;
13+
14+
import org.junit.BeforeClass;
15+
import org.junit.FixMethodOrder;
16+
import org.junit.Test;
17+
import org.junit.runner.RunWith;
18+
import org.junit.runners.MethodSorters;
19+
20+
import java.io.BufferedReader;
21+
import java.io.IOException;
22+
import java.io.InputStreamReader;
23+
import java.util.UUID;
24+
25+
import static org.junit.Assert.assertEquals;
26+
27+
/**
28+
* Instrumented test, which will execute on an Android device.
29+
*
30+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
31+
*/
32+
@RunWith(AndroidJUnit4.class)
33+
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
34+
public class BasicCommunicationTest {
35+
36+
public static BluetoothDevice Alice;
37+
public static BluetoothDevice Bob;
38+
public static BluetoothSocket AliceSocket;
39+
public static BluetoothSocket BobSocket;
40+
41+
@BeforeClass
42+
public static void setup() throws IOException, InterruptedException {
43+
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
44+
btAdapter.cancelDiscovery();
45+
46+
for (BluetoothDevice btDevice : btAdapter.getBondedDevices()) {
47+
if (btDevice.getName().indexOf("ASAP-LoRa-1") == 0) {
48+
BasicCommunicationTest.Alice = btDevice;
49+
}
50+
if (btDevice.getName().indexOf("ASAP-LoRa-2") == 0) {
51+
BasicCommunicationTest.Bob = btDevice;
52+
}
53+
}
54+
if (BasicCommunicationTest.Alice == null || BasicCommunicationTest.Bob == null)
55+
throw new IOException("Please Pair BT Modules ASAP-LoRa-1 and ASAP-LoRa-2 to this device!");
56+
57+
BasicCommunicationTest.AliceSocket = BasicCommunicationTest.Alice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
58+
BasicCommunicationTest.BobSocket = BasicCommunicationTest.Bob.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
59+
60+
BasicCommunicationTest.AliceSocket.connect();
61+
BasicCommunicationTest.BobSocket.connect();
62+
63+
Thread.sleep(5000); //Give the BT Modules some time to stabilize
64+
}
65+
66+
@Test
67+
public void usesAppContext() {
68+
// Test if we are running in App Context
69+
Context appContext = InstrumentationRegistry.getTargetContext();
70+
assertEquals("net.sharksystem.asap.example", appContext.getPackageName());
71+
}
72+
73+
@Test(timeout=20000)
74+
public void deviceDiscoveryTest() throws IOException {
75+
this.AliceSocket.getOutputStream().write("{\"COMMAND\":\".DiscoverASAPLoRaMessage\"}".getBytes());
76+
77+
while(true){
78+
if(this.BobSocket.getInputStream().available() > 0) {
79+
BufferedReader br = new BufferedReader(new InputStreamReader(this.BobSocket.getInputStream()));
80+
StringBuilder sb = new StringBuilder(this.BobSocket.getInputStream().available());
81+
do {
82+
sb.append(br.readLine()).append("\n");
83+
} while(br.ready());
84+
String deviceResponse = sb.toString().trim();
85+
System.out.print("ASAP LoRaEngine Test Device Response: ");
86+
System.out.println(deviceResponse);
87+
assertEquals("{\"COMMAND\":\".DeviceDiscoveredASAPLoRaMessage\",\"address\":\"0000\"}", deviceResponse);
88+
break;
89+
}
90+
}
91+
92+
while(true){
93+
if(this.AliceSocket.getInputStream().available() > 0) {
94+
BufferedReader br = new BufferedReader(new InputStreamReader(this.AliceSocket.getInputStream()));
95+
StringBuilder sb = new StringBuilder(this.AliceSocket.getInputStream().available());
96+
do {
97+
sb.append(br.readLine()).append("\n");
98+
} while(br.ready());
99+
String deviceResponse = sb.toString().trim();
100+
System.out.print("ASAP LoRaEngine Test Device Response: ");
101+
System.out.println(deviceResponse);
102+
assertEquals("{\"COMMAND\":\".DeviceDiscoveredASAPLoRaMessage\",\"address\":\"0001\"}", deviceResponse);
103+
break;
104+
}
105+
}
106+
}
107+
108+
@Test(timeout=10000)
109+
public void simpleAliceToBobMessageTest() throws IOException {
110+
this.AliceSocket.getOutputStream().write("{\"COMMAND\":\".ASAPLoRaMessage\",\"address\":\"0001\",\"message\":\"Hello World!\"}".getBytes());
111+
112+
while(true){
113+
if(this.BobSocket.getInputStream().available() > 0) {
114+
BufferedReader br = new BufferedReader(new InputStreamReader(this.BobSocket.getInputStream()));
115+
StringBuilder sb = new StringBuilder(this.BobSocket.getInputStream().available());
116+
do {
117+
sb.append(br.readLine()).append("\n");
118+
} while(br.ready());
119+
String deviceResponse = sb.toString().trim();
120+
System.out.print("ASAP LoRaEngine Test Device Response: ");
121+
System.out.println(deviceResponse);
122+
assertEquals("{\"COMMAND\":\".ASAPLoRaMessage\",\"address\":\"0000\",\"message\":\"Hello World!\"}", deviceResponse);
123+
break;
124+
}
125+
}
126+
}
127+
128+
@Test(timeout=10000)
129+
public void simpleBobToAliceMessageTest() throws IOException {
130+
this.BobSocket.getOutputStream().write("{\"COMMAND\":\".ASAPLoRaMessage\",\"address\":\"0000\",\"message\":\"Hello World!\"}".getBytes());
131+
132+
while(true){
133+
if(this.AliceSocket.getInputStream().available() > 0) {
134+
BufferedReader br = new BufferedReader(new InputStreamReader(this.AliceSocket.getInputStream()));
135+
StringBuilder sb = new StringBuilder(this.AliceSocket.getInputStream().available());
136+
do {
137+
sb.append(br.readLine()).append("\n");
138+
} while(br.ready());
139+
String deviceResponse = sb.toString().trim();
140+
System.out.print("ASAP LoRaEngine Test Device Response: ");
141+
System.out.println(deviceResponse);
142+
assertEquals("{\"COMMAND\":\".ASAPLoRaMessage\",\"address\":\"0001\",\"message\":\"Hello World!\"}", deviceResponse);
143+
break;
144+
}
145+
}
146+
}
147+
}

app/src/main/java/net/sharksystem/asap/android/bluetooth/BluetoothEngine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ private void shutdown() throws ASAPException {
280280

281281
// stop BT adapter
282282
this.getBTAdapter().cancelDiscovery();
283-
this.getBTAdapter().disable();
283+
//this.getBTAdapter().disable();
284284

285285
this.btEnvironmentOn = false;
286286

app/src/main/java/net/sharksystem/asap/android/lora/LoRaBTInputOutputStream.java

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@
66
import com.fasterxml.jackson.databind.ObjectMapper;
77
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
88

9+
import net.sharksystem.asap.android.lora.messages.ASAPLoRaMessage;
910
import net.sharksystem.asap.android.lora.messages.AbstractASAPLoRaMessage;
1011
import net.sharksystem.asap.android.lora.messages.RawASAPLoRaMessage;
1112

1213
import java.io.BufferedReader;
14+
import java.io.ByteArrayInputStream;
15+
import java.io.ByteArrayOutputStream;
1316
import java.io.FilterInputStream;
1417
import java.io.FilterOutputStream;
1518
import java.io.IOException;
1619
import java.io.InputStream;
1720
import java.io.InputStreamReader;
1821
import java.io.OutputStream;
22+
import java.io.SequenceInputStream;
23+
import java.nio.ByteBuffer;
24+
import java.util.HashMap;
1925

2026

2127
public class LoRaBTInputOutputStream {
@@ -30,9 +36,10 @@ public class LoRaBTInputOutputStream {
3036
private BluetoothSocket btSocket;
3137
private LoRaBTInputStream is;
3238
private LoRaBTOutputStream os;
39+
private HashMap<String, LoRaASAPInputStream> loRaASAPInputStreams = new HashMap<>();
40+
private HashMap<String, LoRaASAPOutputStream> loRaASAPOutputStreams = new HashMap<>();
3341

34-
LoRaBTInputOutputStream(/*String mac, */BluetoothSocket btSocket) throws IOException {
35-
//this.LoRaAddress = mac;
42+
LoRaBTInputOutputStream(BluetoothSocket btSocket) throws IOException {
3643
this.btSocket = btSocket;
3744
this.is = new LoRaBTInputStream(btSocket.getInputStream());
3845
this.os = new LoRaBTOutputStream(btSocket.getOutputStream());
@@ -45,11 +52,27 @@ public void close() {
4552
try {
4653
if (this.btSocket != null)
4754
btSocket.close();
48-
}catch (IOException e){
55+
} catch (IOException e) {
4956
Log.e(this.CLASS_LOG_TAG, e.getMessage());
5057
}
5158
}
5259

60+
public LoRaASAPOutputStream getASAPOutputStream(String mac) {
61+
if (this.loRaASAPOutputStreams.containsKey(mac))
62+
return this.loRaASAPOutputStreams.get(mac);
63+
64+
this.loRaASAPOutputStreams.put(mac, new LoRaASAPOutputStream(mac));
65+
return this.getASAPOutputStream(mac); //TODO rewrite to make sure to never have endless loop?
66+
}
67+
68+
public LoRaASAPInputStream getASAPInputStream(String mac) {
69+
if (this.loRaASAPInputStreams.containsKey(mac))
70+
return this.loRaASAPInputStreams.get(mac);
71+
72+
this.loRaASAPInputStreams.put(mac, new LoRaASAPInputStream(mac));
73+
return this.getASAPInputStream(mac); //TODO rewrite to make sure to never have endless loop?
74+
}
75+
5376
public LoRaBTInputStream getInputStream() {
5477
return is;
5578
}
@@ -82,4 +105,51 @@ public void write(AbstractASAPLoRaMessage msg) throws IOException {
82105
this.write(objectMapper.writeValueAsString(msg).getBytes());
83106
}
84107
}
108+
109+
class LoRaASAPInputStream extends InputStream {
110+
private final String LoRaAddress;
111+
112+
private SequenceInputStream sis;
113+
114+
public LoRaASAPInputStream(String mac) {
115+
super();
116+
this.sis = new SequenceInputStream(new ByteArrayInputStream(new byte[0]), new ByteArrayInputStream(new byte[0]));
117+
this.LoRaAddress = mac;
118+
}
119+
120+
public synchronized void appendData(byte[] data) {
121+
this.sis = new SequenceInputStream(this.sis, new ByteArrayInputStream(data)); //TODO this can't be right.
122+
}
123+
124+
@Override
125+
public synchronized int read() throws IOException {
126+
return sis.read();
127+
}
128+
}
129+
130+
class LoRaASAPOutputStream extends ByteArrayOutputStream {
131+
private final String LoRaAddress;
132+
133+
public LoRaASAPOutputStream(String mac) {
134+
super(250); //TODO Prüfen ob wir wirklich immer 250 bytes schicken können
135+
this.LoRaAddress = mac;
136+
}
137+
138+
@Override
139+
public synchronized void write(byte[] b, int off, int len) {
140+
//TODO...? Ist das sinnig?
141+
try {
142+
LoRaBTInputOutputStream.this.getOutputStream().write(new ASAPLoRaMessage(this.LoRaAddress, b));
143+
} catch (IOException e) {
144+
e.printStackTrace(); //TODO...
145+
}
146+
}
147+
148+
@Override
149+
public synchronized void write(int b) {
150+
//TODO...? Ist das sinnig?
151+
byte[] byteArray = ByteBuffer.allocate(1).putInt(b).array();
152+
this.write(byteArray, 0, 1);
153+
}
154+
}
85155
}

app/src/main/java/net/sharksystem/asap/android/lora/LoRaCommunicationManager.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@
1010
import net.sharksystem.asap.android.lora.messages.DeviceDiscoveredASAPLoRaMessage;
1111
import net.sharksystem.asap.android.lora.messages.DiscoverASAPLoRaMessage;
1212
import net.sharksystem.asap.android.lora.messages.ErrorASAPLoRaMessage;
13-
import net.sharksystem.asap.android.lora.messages.RawASAPLoRaMessage;
1413

15-
import java.io.BufferedReader;
1614
import java.io.IOException;
17-
import java.io.InputStreamReader;
15+
import java.io.InputStream;
16+
import java.io.OutputStream;
1817
import java.util.UUID;
1918

2019
public class LoRaCommunicationManager extends Thread {
@@ -57,29 +56,39 @@ public LoRaCommunicationManager() throws ASAPLoRaException {
5756
}
5857
}
5958

59+
public OutputStream getASAPOutputStream(String mac) {
60+
return this.ioStream.getASAPOutputStream(mac);
61+
}
62+
63+
public InputStream getASAPInputStream(String mac) {
64+
return this.ioStream.getASAPInputStream(mac);
65+
}
66+
6067
@Override
6168
public void run() {
6269
super.run();
6370

6471
try {
6572
//this.ioStream.getOutputStream().write(new RawASAPLoRaMessage("AT"));
66-
//this.ioStream.getOutputStream().write(new DiscoverASAPLoRaMessage());
67-
this.ioStream.getOutputStream().write(new ASAPLoRaMessage("A2FF", "Hi there!"));
73+
this.ioStream.getOutputStream().write(new DiscoverASAPLoRaMessage()); //TODO, do this periodically?
74+
//this.ioStream.getOutputStream().write(new ASAPLoRaMessage("A2FF", "Hi there!"));
6875

6976
while (!this.isInterrupted()) {
7077
if (this.ioStream.getInputStream().available() > 0) {
7178
AbstractASAPLoRaMessage asapLoRaMessage = this.ioStream.getInputStream().readASAPLoRaMessage();
7279

7380
//TODO, this is smelly... visitorpattern? handleMessage() in abstract?
74-
if(asapLoRaMessage instanceof ASAPLoRaMessage){
75-
//New Message inbound, write to corresponding inputstream of ASAPPeer
81+
if (asapLoRaMessage instanceof ASAPLoRaMessage) {
82+
//New Message inbound, write to corresponding stream of ASAPPeer
7683
Log.i(this.CLASS_LOG_TAG, asapLoRaMessage.toString());
77-
} else if(asapLoRaMessage instanceof DeviceDiscoveredASAPLoRaMessage){
84+
this.ioStream.getASAPInputStream(((ASAPLoRaMessage) asapLoRaMessage).address).appendData(((ASAPLoRaMessage) asapLoRaMessage).message);
85+
} else if (asapLoRaMessage instanceof DeviceDiscoveredASAPLoRaMessage) {
7886
//New Device in Range found
7987
Log.i(this.CLASS_LOG_TAG, asapLoRaMessage.toString());
80-
} else if(asapLoRaMessage instanceof ErrorASAPLoRaMessage){
88+
LoRaEngine.getASAPLoRaEngine().tryConnect(((DeviceDiscoveredASAPLoRaMessage) asapLoRaMessage).address);
89+
} else if (asapLoRaMessage instanceof ErrorASAPLoRaMessage) {
8190
//LoRa Error occured
82-
Log.i(this.CLASS_LOG_TAG, asapLoRaMessage.toString());
91+
Log.i(this.CLASS_LOG_TAG, asapLoRaMessage.toString()); //TODO
8392
}
8493
}
8594
}

app/src/main/java/net/sharksystem/asap/android/lora/LoRaEngine.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.sharksystem.asap.android.service.ASAPService;
77
import net.sharksystem.asap.android.service.MacLayerEngine;
88

9+
910
public class LoRaEngine extends MacLayerEngine {
1011

1112
private static final String CLASS_LOG_TAG = "ASAPLoRaEngine";
@@ -51,7 +52,7 @@ public void start() {
5152
@Override
5253
public void stop() {
5354
Log.i(this.CLASS_LOG_TAG, "MacLayerEngine.stop() called");
54-
if(loRaCommunicationManager != null){
55+
if (loRaCommunicationManager != null) {
5556
loRaCommunicationManager.interrupt();
5657
}
5758
}
@@ -67,4 +68,13 @@ public void checkConnectionStatus() {
6768
Log.i(this.CLASS_LOG_TAG, "MacLayerEngine.checkConnectionStatus() called");
6869

6970
}
71+
72+
void tryConnect(String macAddress) {
73+
if (this.shouldConnectToMACPeer(macAddress)) {
74+
this.launchASAPConnection(macAddress, this.loRaCommunicationManager.getASAPInputStream(macAddress), this.loRaCommunicationManager.getASAPOutputStream(macAddress));
75+
} else {
76+
Log.d(this.CLASS_LOG_TAG, "Connection to "
77+
+ macAddress + " not needed.");
78+
}
79+
}
7080
}

app/src/main/java/net/sharksystem/asap/android/lora/messages/ASAPLoRaMessage.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
public class ASAPLoRaMessage extends AbstractASAPLoRaMessage {
44
//these need to be public to be picked up by the json automapper
5-
public String message = "";
6-
public String address = "";
5+
public String address;
6+
public byte[] message;
77

8-
public ASAPLoRaMessage(String address, String message){
8+
//Constructor for Jackson
9+
public ASAPLoRaMessage(){
10+
this.address = "";
11+
this.message = new byte[0];
12+
}
13+
public ASAPLoRaMessage(String address, byte[] message){
914
this.address = address;
1015
this.message = message;
1116
}

0 commit comments

Comments
 (0)