Skip to content

Commit 0df513b

Browse files
authored
Merge pull request #5 from neXenio/bugfix/003-offset-ignored
Client specific value providers
2 parents 146e218 + 6066014 commit 0df513b

File tree

11 files changed

+172
-10
lines changed

11 files changed

+172
-10
lines changed

.idea/jarRepositories.xml

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ android {
2626
dependencies {
2727
implementation project(path: ':rxandroidbleserver')
2828

29-
implementation 'io.reactivex.rxjava3:rxjava:3.0.1'
29+
implementation 'io.reactivex.rxjava3:rxjava:3.0.3'
3030
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
3131
implementation 'com.github.niklasvd96:rxpermissions:0.11.2'
3232

3333
implementation 'androidx.appcompat:appcompat:1.1.0'
3434
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
3535
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
36+
implementation 'com.google.android.material:material:1.1.0'
3637

3738
implementation 'com.jakewharton.timber:timber:4.7.1'
3839

@@ -41,5 +42,4 @@ dependencies {
4142
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
4243
androidTestImplementation 'androidx.test:runner:1.2.0'
4344
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
44-
implementation 'com.google.android.material:material:1.0.0'
4545
}

app/src/main/java/com/nexenio/rxandroidbleserverapp/ExampleProfile.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.nexenio.rxandroidbleserver.service.value.RxBleValue;
1717

1818
import java.nio.ByteBuffer;
19+
import java.nio.charset.StandardCharsets;
1920
import java.util.UUID;
2021
import java.util.concurrent.TimeUnit;
2122

@@ -40,7 +41,7 @@ public ExampleProfile(@NonNull Context context) {
4041

4142
public Completable updateCharacteristicValues() {
4243
return Observable.interval(1, TimeUnit.SECONDS)
43-
.map(count -> (int) (count % 1337))
44+
.map(count -> "Updated example value #" + count)
4445
.map(this::createExampleValue)
4546
.flatMapCompletable(value -> exampleCharacteristic.setValue(value)
4647
.andThen(exampleCharacteristic.sendNotifications()));
@@ -79,7 +80,7 @@ private RxBleService createExampleService() {
7980

8081
private RxBleCharacteristic createExampleCharacteristic() {
8182
exampleCharacteristic = new CharacteristicBuilder(EXAMPLE_CHARACTERISTIC_UUID)
82-
.withInitialValue(createExampleValue(0))
83+
.withInitialValue(createExampleValue("Initial example value"))
8384
.withDescriptor(new CharacteristicUserDescription("Example"))
8485
.withDescriptor(new ClientCharacteristicConfiguration())
8586
.withDescriptor(createExampleDescriptor())
@@ -108,4 +109,8 @@ private RxBleValue createExampleValue(int number) {
108109
return new BaseValue(buffer.array());
109110
}
110111

112+
private RxBleValue createExampleValue(String value) {
113+
return new BaseValue(value.getBytes(StandardCharsets.UTF_8));
114+
}
115+
111116
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/BaseServer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.nexenio.rxandroidbleserver.request.characteristic.RxBleCharacteristicWriteRequest;
2828
import com.nexenio.rxandroidbleserver.request.descriptor.RxBleDescriptorReadRequest;
2929
import com.nexenio.rxandroidbleserver.request.descriptor.RxBleDescriptorWriteRequest;
30+
import com.nexenio.rxandroidbleserver.response.BaseServerResponse;
3031
import com.nexenio.rxandroidbleserver.response.RxBleServerResponse;
3132
import com.nexenio.rxandroidbleserver.service.RxBleService;
3233
import com.nexenio.rxandroidbleserver.service.characteristic.RxBleCharacteristic;
@@ -135,8 +136,8 @@ public Completable provideServices() {
135136
@Override
136137
public Completable provideServicesAndAdvertise(@NonNull UUID uuid) {
137138
return Completable.mergeArray(
138-
provideServices().subscribeOn(Schedulers.io()),
139-
advertise(uuid).subscribeOn(Schedulers.io())
139+
provideServices(),
140+
advertise(uuid)
140141
);
141142
}
142143

@@ -436,7 +437,7 @@ private Completable sendResponse(RxBleServerResponse response) {
436437
response.getRequestId(),
437438
response.getStatus(),
438439
response.getOffset(),
439-
response.getValue().getBytes()
440+
BaseServerResponse.trimData(response.getValue().getBytes(), response.getOffset())
440441
);
441442

442443
if (success) {

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/response/BaseServerResponse.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public String toString() {
7979
public static byte[] trimData(byte[] data, int offset) {
8080
if (offset == 0) {
8181
return data;
82+
} else if (offset >= data.length) {
83+
return new byte[]{};
8284
} else {
8385
return Arrays.copyOfRange(data, offset, data.length);
8486
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/characteristic/BaseCharacteristic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
import androidx.annotation.NonNull;
2828
import io.reactivex.rxjava3.core.Completable;
2929
import io.reactivex.rxjava3.core.Maybe;
30-
import io.reactivex.rxjava3.core.Single;
3130
import io.reactivex.rxjava3.core.Observable;
31+
import io.reactivex.rxjava3.core.Single;
3232
import io.reactivex.rxjava3.disposables.Disposable;
3333
import io.reactivex.rxjava3.schedulers.Schedulers;
3434
import timber.log.Timber;

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/value/BaseValueContainer.java

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,21 @@ public Single<RxBleValue> getValue() {
3737

3838
@Override
3939
public Completable setValue(@NonNull RxBleValue value) {
40-
return sharedValueProvider.setValue(value);
40+
return Completable.mergeArray(
41+
sharedValueProvider.setValue(value),
42+
clientValueProvider.setValueForAllClients(value)
43+
);
4144
}
4245

4346
@Override
4447
public Observable<RxBleValue> getValueChanges() {
45-
return sharedValueProvider.getValueChanges();
48+
return Observable.defer(() -> {
49+
if (shareValues) {
50+
return sharedValueProvider.getValueChanges();
51+
} else {
52+
return clientValueProvider.getValueChangesFromAllClients();
53+
}
54+
});
4655
}
4756

4857
@Override
@@ -56,6 +65,17 @@ public Single<RxBleValue> getValue(@NonNull RxBleClient client) {
5665
});
5766
}
5867

68+
@Override
69+
public Observable<RxBleValue> getValuesFromAllClients() {
70+
return Observable.defer(() -> {
71+
if (shareValues) {
72+
return sharedValueProvider.getValue().toObservable();
73+
} else {
74+
return clientValueProvider.getValuesFromAllClients();
75+
}
76+
});
77+
}
78+
5979
@Override
6080
public Completable setValue(@NonNull RxBleClient client, @NonNull RxBleValue value) {
6181
return Completable.defer(() -> {
@@ -67,11 +87,33 @@ public Completable setValue(@NonNull RxBleClient client, @NonNull RxBleValue val
6787
});
6888
}
6989

90+
@Override
91+
public Completable setValueForAllClients(@NonNull RxBleValue value) {
92+
return Completable.defer(() -> {
93+
if (shareValues) {
94+
return sharedValueProvider.setValue(value);
95+
} else {
96+
return clientValueProvider.setValueForAllClients(value);
97+
}
98+
});
99+
}
100+
70101
@Override
71102
public Observable<RxBleValue> getValueChanges(@NonNull RxBleClient client) {
72103
return clientValueProvider.getValueChanges(client);
73104
}
74105

106+
@Override
107+
public Observable<RxBleValue> getValueChangesFromAllClients() {
108+
return Observable.defer(() -> {
109+
if (shareValues) {
110+
return sharedValueProvider.getValueChanges();
111+
} else {
112+
return clientValueProvider.getValueChangesFromAllClients();
113+
}
114+
});
115+
}
116+
75117
public Single<RxBleServerResponse> createReadRequestResponse(@NonNull RxBleReadRequest request) {
76118
return getValue(request.getClient())
77119
.map(value -> new BaseServerResponse(request, value))
@@ -114,4 +156,22 @@ public String toString() {
114156
'}';
115157
}
116158

159+
@Override
160+
public boolean isSharingValuesBetweenClients() {
161+
return shareValues;
162+
}
163+
164+
@Override
165+
public void shareValuesBetweenClients(boolean shareValues) {
166+
this.shareValues = shareValues;
167+
}
168+
169+
public RxBleSharedValueProvider getSharedValueProvider() {
170+
return sharedValueProvider;
171+
}
172+
173+
public RxBleClientValueProvider getClientValueProvider() {
174+
return clientValueProvider;
175+
}
176+
117177
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/value/RxBleValueContainer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ public interface RxBleValueContainer extends RxBleClientValueProvider, RxBleShar
1616

1717
Maybe<RxBleServerResponse> createWriteRequestResponse(@NonNull RxBleWriteRequest request);
1818

19+
boolean isSharingValuesBetweenClients();
20+
21+
void shareValuesBetweenClients(boolean shareValues);
22+
1923
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/value/provider/BaseClientValueProvider.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,29 @@
44
import com.nexenio.rxandroidbleserver.exception.ValueNotAvailableException;
55
import com.nexenio.rxandroidbleserver.service.value.RxBleValue;
66

7+
import java.util.Collection;
78
import java.util.HashMap;
9+
import java.util.HashSet;
810
import java.util.Map;
911

1012
import androidx.annotation.NonNull;
1113
import io.reactivex.rxjava3.core.Completable;
1214
import io.reactivex.rxjava3.core.Observable;
1315
import io.reactivex.rxjava3.core.Single;
1416
import io.reactivex.rxjava3.subjects.PublishSubject;
17+
import io.reactivex.rxjava3.subjects.ReplaySubject;
1518

1619
public class BaseClientValueProvider implements RxBleClientValueProvider {
1720

21+
private final ReplaySubject<RxBleClient> clientPublisher;
22+
1823
private final Map<RxBleClient, RxBleValue> valueMap;
1924
private final Map<RxBleClient, PublishSubject<RxBleValue>> valuePublisherMap;
2025

2126
public BaseClientValueProvider() {
2227
this.valueMap = new HashMap<>();
2328
this.valuePublisherMap = new HashMap<>();
29+
this.clientPublisher = ReplaySubject.create();
2430
}
2531

2632
@Override
@@ -36,21 +42,55 @@ public Single<RxBleValue> getValue(@NonNull RxBleClient client) {
3642
});
3743
}
3844

45+
@Override
46+
public Observable<RxBleValue> getValuesFromAllClients() {
47+
return getCurrentClients().flatMapSingle(this::getValue);
48+
}
49+
3950
@Override
4051
public Completable setValue(@NonNull RxBleClient client, @NonNull RxBleValue value) {
4152
return Completable.fromAction(() -> {
53+
boolean isNewClient;
4254
synchronized (valueMap) {
55+
isNewClient = !valueMap.containsKey(client);
4356
valueMap.put(client, value);
4457
}
58+
if (isNewClient) {
59+
clientPublisher.onNext(client);
60+
}
4561
getOrCreateValuePublisher(client).onNext(value);
4662
});
4763
}
4864

65+
@Override
66+
public Completable setValueForAllClients(@NonNull RxBleValue value) {
67+
return getCurrentClients().flatMapCompletable(client -> setValue(client, value));
68+
}
69+
4970
@Override
5071
public Observable<RxBleValue> getValueChanges(@NonNull RxBleClient client) {
5172
return getOrCreateValuePublisher(client);
5273
}
5374

75+
@Override
76+
public Observable<RxBleValue> getValueChangesFromAllClients() {
77+
return getCurrentAndFutureClients().flatMap(this::getValueChanges);
78+
}
79+
80+
private Observable<RxBleClient> getCurrentClients() {
81+
return Observable.defer(() -> {
82+
Collection<RxBleClient> clients;
83+
synchronized (valueMap) {
84+
clients = new HashSet<>(valueMap.keySet());
85+
}
86+
return Observable.fromIterable(clients);
87+
});
88+
}
89+
90+
private Observable<RxBleClient> getCurrentAndFutureClients() {
91+
return clientPublisher;
92+
}
93+
5494
private PublishSubject<RxBleValue> getOrCreateValuePublisher(@NonNull RxBleClient client) {
5595
synchronized (valuePublisherMap) {
5696
if (valuePublisherMap.containsKey(client)) {
@@ -63,4 +103,11 @@ private PublishSubject<RxBleValue> getOrCreateValuePublisher(@NonNull RxBleClien
63103
}
64104
}
65105

106+
@Override
107+
public String toString() {
108+
return "BaseClientValueProvider{" +
109+
"valueMap=" + valueMap +
110+
'}';
111+
}
112+
66113
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/value/provider/BaseSharedValueProvider.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,11 @@ public Observable<RxBleValue> getValueChanges() {
4545
return valuePublisher;
4646
}
4747

48+
@Override
49+
public String toString() {
50+
return "BaseSharedValueProvider{" +
51+
"value=" + value +
52+
'}';
53+
}
54+
4855
}

rxandroidbleserver/src/main/java/com/nexenio/rxandroidbleserver/service/value/provider/RxBleClientValueProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ public interface RxBleClientValueProvider {
1212

1313
Single<RxBleValue> getValue(@NonNull RxBleClient client);
1414

15+
Observable<RxBleValue> getValuesFromAllClients();
16+
1517
Completable setValue(@NonNull RxBleClient client, @NonNull RxBleValue value);
1618

19+
Completable setValueForAllClients(@NonNull RxBleValue value);
20+
1721
Observable<RxBleValue> getValueChanges(@NonNull RxBleClient client);
1822

23+
Observable<RxBleValue> getValueChangesFromAllClients();
24+
1925
}

0 commit comments

Comments
 (0)