Skip to content

Commit 6762658

Browse files
committed
camera client updated
1 parent 30259bf commit 6762658

15 files changed

+186
-133
lines changed

rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/CameraClient.java

+31-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package one.microproject.rpi.camera.client;
22

33
import one.microproject.rpi.camera.client.dto.CameraConfiguration;
4-
import one.microproject.rpi.camera.client.dto.CameraSelectRequest;
4+
import one.microproject.rpi.camera.client.dto.CameraSelect;
55
import one.microproject.rpi.camera.client.dto.ImageCapture;
66
import one.microproject.rpi.camera.client.dto.CameraInfo;
7+
import one.microproject.rpi.camera.client.dto.Resolutions;
8+
import one.microproject.rpi.camera.client.dto.Rotations;
79
import one.microproject.rpi.device.RPiDevice;
810
import one.microproject.rpi.device.dto.SystemInfo;
911

12+
import java.io.InputStream;
13+
1014

1115
/**
1216
* Read data from RPi remote camera.
@@ -35,16 +39,40 @@ public interface CameraClient extends RPiDevice<CameraInfo> {
3539
CameraConfiguration setConfiguration(CameraConfiguration configuration);
3640

3741
/**
38-
* Capture camera image using current {@link CameraConfiguration}.
42+
* Capture image using current {@link CameraConfiguration}.
3943
* @return image data as {@link ImageCapture}.
4044
*/
4145
ImageCapture captureImage();
4246

47+
/**
48+
* Capture video using current {@link CameraConfiguration}.
49+
* @return video data stream.
50+
*/
51+
InputStream captureVideo();
52+
4353
/**
4454
* Select connected camera. This method is only effective if camera controller uses hardware "camera scheduler" https://www.waveshare.com/wiki/Camera_Scheduler.
4555
* @param cameraSelectRequest select camera request.
4656
* @return index of selected camera.
4757
*/
48-
Integer selectCamera(CameraSelectRequest cameraSelectRequest);
58+
CameraSelect selectCamera(CameraSelect cameraSelectRequest);
59+
60+
/**
61+
* Get selected connected camera.
62+
* @return index of selected camera.
63+
*/
64+
CameraSelect getSelectedCamera();
65+
66+
/**
67+
* Get available camera resolutions.
68+
* @return available camera resolutions.
69+
*/
70+
Resolutions getResolutions();
71+
72+
/**
73+
* Get available camera rotations.
74+
* @return available camera rotations.
75+
*/
76+
Rotations getRotations();
4977

5078
}

rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/client/CameraClientImpl.java

+58-12
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
import one.microproject.rpi.camera.client.CameraClient;
1212
import one.microproject.rpi.camera.client.ClientException;
1313
import one.microproject.rpi.camera.client.dto.CameraConfiguration;
14-
import one.microproject.rpi.camera.client.dto.CameraSelectRequest;
14+
import one.microproject.rpi.camera.client.dto.CameraSelect;
1515
import one.microproject.rpi.camera.client.dto.ImageCapture;
1616
import one.microproject.rpi.camera.client.dto.CameraInfo;
17+
import one.microproject.rpi.camera.client.dto.Resolutions;
18+
import one.microproject.rpi.camera.client.dto.Rotations;
1719
import one.microproject.rpi.device.dto.SystemInfo;
1820
import org.slf4j.Logger;
1921
import org.slf4j.LoggerFactory;
2022

2123
import java.io.IOException;
24+
import java.io.InputStream;
2225
import java.net.URL;
2326
import java.util.Base64;
2427

@@ -63,11 +66,17 @@ public SystemInfo<CameraInfo> getSystemInfo() {
6366

6467
@Override
6568
public CameraConfiguration getConfiguration() {
69+
return getData("/system/config", CameraConfiguration.class);
70+
}
71+
72+
@Override
73+
public CameraConfiguration setConfiguration(CameraConfiguration configuration) {
6674
try {
75+
RequestBody body = RequestBody.create(mapper.writeValueAsString(configuration), MediaType.get("application/json"));
6776
Request request = new Request.Builder()
6877
.url(baseURL + "/system/config")
6978
.addHeader(AUTHORIZATION, createBasicAuthorizationFromCredentials(clientId, clientSecret))
70-
.get()
79+
.post(body)
7180
.build();
7281
Response response = client.newCall(request).execute();
7382
if (response.code() == 200) {
@@ -81,17 +90,21 @@ public CameraConfiguration getConfiguration() {
8190
}
8291

8392
@Override
84-
public CameraConfiguration setConfiguration(CameraConfiguration configuration) {
93+
public ImageCapture captureImage() {
8594
try {
86-
RequestBody body = RequestBody.create(mapper.writeValueAsString(configuration), MediaType.get("application/json"));
95+
HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(baseURL + "/system/capture").newBuilder();
8796
Request request = new Request.Builder()
88-
.url(baseURL + "/system/config")
97+
.url(httpUrlBuilder.build())
8998
.addHeader(AUTHORIZATION, createBasicAuthorizationFromCredentials(clientId, clientSecret))
90-
.post(body)
99+
.get()
91100
.build();
101+
92102
Response response = client.newCall(request).execute();
93103
if (response.code() == 200) {
94-
return mapper.readValue(response.body().string(), CameraConfiguration.class);
104+
String mimeType = response.header("Content-Type");
105+
String fileName = getFileNameFromHeader(response.header("Content-Disposition"), mimeType);
106+
LOG.debug("Http OK: {} {}", mimeType, fileName);
107+
return new ImageCapture(response.body().byteStream(), fileName, mimeType);
95108
}
96109
LOG.warn("Http error: {}", response.code());
97110
throw new ClientException(ERROR_MESSAGE + response.code());
@@ -101,9 +114,9 @@ public CameraConfiguration setConfiguration(CameraConfiguration configuration) {
101114
}
102115

103116
@Override
104-
public ImageCapture captureImage() {
117+
public InputStream captureVideo() {
105118
try {
106-
HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(baseURL + "/system/capture").newBuilder();
119+
HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(baseURL + "/system/stream.mjpg").newBuilder();
107120
Request request = new Request.Builder()
108121
.url(httpUrlBuilder.build())
109122
.addHeader(AUTHORIZATION, createBasicAuthorizationFromCredentials(clientId, clientSecret))
@@ -115,7 +128,7 @@ public ImageCapture captureImage() {
115128
String mimeType = response.header("Content-Type");
116129
String fileName = getFileNameFromHeader(response.header("Content-Disposition"), mimeType);
117130
LOG.debug("Http OK: {} {}", mimeType, fileName);
118-
return new ImageCapture(response.body().byteStream(), fileName, mimeType);
131+
return response.body().byteStream();
119132
}
120133
LOG.warn("Http error: {}", response.code());
121134
throw new ClientException(ERROR_MESSAGE + response.code());
@@ -125,7 +138,7 @@ public ImageCapture captureImage() {
125138
}
126139

127140
@Override
128-
public Integer selectCamera(CameraSelectRequest cameraSelectRequest) {
141+
public CameraSelect selectCamera(CameraSelect cameraSelectRequest) {
129142
try {
130143
RequestBody body = RequestBody.create(mapper.writeValueAsString(cameraSelectRequest), MediaType.get("application/json"));
131144
Request request = new Request.Builder()
@@ -135,7 +148,7 @@ public Integer selectCamera(CameraSelectRequest cameraSelectRequest) {
135148
.build();
136149
Response response = client.newCall(request).execute();
137150
if (response.code() == 200) {
138-
return mapper.readValue(response.body().string(), CameraSelectRequest.class).getCamera();
151+
return mapper.readValue(response.body().string(), CameraSelect.class);
139152
}
140153
LOG.warn("Http error: {}", response.code());
141154
throw new ClientException(ERROR_MESSAGE + response.code());
@@ -144,6 +157,21 @@ public Integer selectCamera(CameraSelectRequest cameraSelectRequest) {
144157
}
145158
}
146159

160+
@Override
161+
public CameraSelect getSelectedCamera() {
162+
return getData("/system/camera", CameraSelect.class);
163+
}
164+
165+
@Override
166+
public Resolutions getResolutions() {
167+
return getData("/system/resolutions", Resolutions.class);
168+
}
169+
170+
@Override
171+
public Rotations getRotations() {
172+
return getData("/system/rotations", Rotations.class);
173+
}
174+
147175
public static String createBasicAuthorizationFromCredentials(String clientId, String clientSecret) {
148176
String authorization = clientId + ":" + clientSecret;
149177
byte[] encodedBytes = Base64.getEncoder().encode(authorization.getBytes());
@@ -164,4 +192,22 @@ public static String getFileNameFromHeader(String contentDisposition, String mim
164192
}
165193
}
166194

195+
private <T> T getData(String path, Class<T> type) {
196+
try {
197+
Request request = new Request.Builder()
198+
.url(baseURL + path)
199+
.addHeader(AUTHORIZATION, createBasicAuthorizationFromCredentials(clientId, clientSecret))
200+
.get()
201+
.build();
202+
Response response = client.newCall(request).execute();
203+
if (response.code() == 200) {
204+
return mapper.readValue(response.body().string(), type);
205+
}
206+
LOG.warn("Http error: {}", response.code());
207+
throw new ClientException(ERROR_MESSAGE + response.code());
208+
} catch (IOException e) {
209+
throw new ClientException(e);
210+
}
211+
}
212+
167213
}

rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/dto/CameraConfiguration.java

+22-58
Original file line numberDiff line numberDiff line change
@@ -5,99 +5,63 @@
55

66
public class CameraConfiguration {
77

8-
private final Float shutterSpeed;
9-
private final ImageFormat imageFormat;
10-
private final Resolution resolution;
11-
private final Rotation rotation;
12-
private final Integer quality;
8+
private final String resolution;
9+
private final String rotation;
10+
private final Integer framerate;
1311

1412
@JsonCreator
15-
public CameraConfiguration(@JsonProperty("shutterSpeed") Float shutterSpeed,
16-
@JsonProperty("imageFormat") ImageFormat imageFormat,
17-
@JsonProperty("resolution") Resolution resolution,
18-
@JsonProperty("rotation") Rotation rotation,
19-
@JsonProperty("quality") Integer quality) {
20-
this.shutterSpeed = shutterSpeed;
21-
this.imageFormat = imageFormat;
13+
public CameraConfiguration(@JsonProperty("resolution") String resolution,
14+
@JsonProperty("rotation") String rotation,
15+
@JsonProperty("framerate") Integer framerate) {
2216
this.resolution = resolution;
2317
this.rotation = rotation;
24-
this.quality = quality;
18+
this.framerate = framerate;
2519
}
2620

27-
public Float getShutterSpeed() {
28-
return shutterSpeed;
29-
}
30-
31-
public ImageFormat getImageFormat() {
32-
return imageFormat;
33-
}
34-
35-
public Resolution getResolution() {
21+
public String getResolution() {
3622
return resolution;
3723
}
3824

39-
public Rotation getRotation() {
25+
public String getRotation() {
4026
return rotation;
4127
}
4228

43-
public Integer getQuality() {
44-
return quality;
29+
public Integer getFramerate() {
30+
return framerate;
4531
}
4632

4733
public static CameraConfiguration getDefault() {
48-
return new CameraConfiguration(0F, ImageFormat.JPEG, Resolution.M1, Rotation.D0, 85);
49-
}
50-
51-
public static CameraConfiguration getMinimal() {
52-
return new CameraConfiguration(0F, ImageFormat.JPEG, Resolution.M03, Rotation.D0, 45);
34+
return new CameraConfiguration("R1", "D0", 24);
5335
}
5436

5537
private static class Builder {
56-
private Float shutterSpeed = 0F;
57-
private ImageFormat imageFormat = ImageFormat.JPEG;
58-
private Resolution resolution = Resolution.M1;
59-
private Rotation rotation = Rotation.D0;
60-
private Integer quality = 85;
61-
62-
public Builder setShutterSpeed(Float shutterSpeed) {
63-
if (shutterSpeed < 0) {
64-
throw new UnsupportedOperationException("shutterSpeed must be greater than 0 !");
65-
}
66-
if (shutterSpeed > 10000) {
67-
throw new UnsupportedOperationException("shutterSpeed must be less than 10s !");
68-
}
69-
this.shutterSpeed = shutterSpeed;
70-
return this;
71-
}
72-
73-
public Builder setImageFormat(ImageFormat imageFormat) {
74-
this.imageFormat = imageFormat;
75-
return this;
76-
}
38+
private String resolution = "R1";
39+
private String rotation = "D0";
40+
private Integer framerate = 24;
7741

78-
public Builder setResolution(Resolution resolution) {
42+
public Builder setResolution(String resolution) {
7943
this.resolution = resolution;
8044
return this;
8145
}
8246

83-
public Builder setRotation(Rotation rotation) {
47+
public Builder setRotation(String rotation) {
8448
this.rotation = rotation;
8549
return this;
8650
}
8751

88-
public Builder setQuality(Integer quality) {
89-
if (quality < 0) {
52+
public Builder setFrameRate(Integer framerate) {
53+
if (framerate < 0) {
9054
throw new UnsupportedOperationException("quality must be greater than 0 !");
9155
}
92-
if (quality > 100) {
56+
if (framerate > 100) {
9357
throw new UnsupportedOperationException("quality must be less than 100 !");
9458
}
95-
this.quality = quality;
59+
this.framerate = framerate;
9660
return this;
9761
}
9862

9963
public CameraConfiguration build() {
100-
return new CameraConfiguration(shutterSpeed, imageFormat, resolution, rotation, quality);
64+
return new CameraConfiguration(resolution, rotation, framerate);
10165
}
10266

10367
}

rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/dto/CameraSelectRequest.java rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/dto/CameraSelect.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import com.fasterxml.jackson.annotation.JsonCreator;
44
import com.fasterxml.jackson.annotation.JsonProperty;
55

6-
public class CameraSelectRequest {
6+
public class CameraSelect {
77

88
private final Integer camera;
99

1010
@JsonCreator
11-
public CameraSelectRequest(@JsonProperty("camera") Integer camera) {
11+
public CameraSelect(@JsonProperty("camera") Integer camera) {
1212
this.camera = camera;
1313
}
1414

rpi-camera-client/src/main/java/one/microproject/rpi/camera/client/dto/ImageFormat.java

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
package one.microproject.rpi.camera.client.dto;
22

3-
public enum Resolution {
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
45

5-
M03,
6-
M1,
7-
M2,
8-
M5,
9-
M8
6+
public class Resolution {
7+
8+
private final Integer height;
9+
private final Integer width;
10+
11+
@JsonCreator
12+
public Resolution(@JsonProperty("height") Integer height,
13+
@JsonProperty("width") Integer width) {
14+
this.height = height;
15+
this.width = width;
16+
}
17+
18+
public Integer getHeight() {
19+
return height;
20+
}
21+
22+
public Integer getWidth() {
23+
return width;
24+
}
1025

1126
}

0 commit comments

Comments
 (0)