Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.

Commit

Permalink
Merge pull request #14 from Azure-Samples/dt-register-change
Browse files Browse the repository at this point in the history
refactor: separated digital twin client register API and renamed interface instance to component
davilu authored Jan 30, 2020
2 parents 3785a69 + 9ec5972 commit 6f7f0b6
Showing 14 changed files with 138 additions and 196 deletions.
2 changes: 1 addition & 1 deletion digital-twin/Samples/device/AndroidSample/app/build.gradle
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ dependencies {
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.github.tony19:logback-android:2.0.0'
implementation 'commons-io:commons-io:2.6'
implementation 'com.microsoft.azure.sdk.iot:digital-twin-device-client-preview:1.0.+'
implementation 'com.microsoft.azure.sdk.iot:digital-twin-device-client-preview:1.+'
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
}
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import com.fasterxml.jackson.databind.node.DoubleNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinReportProperty;

@@ -24,9 +24,9 @@
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.isNotEmpty;

@Slf4j
public class DeviceInformation extends AbstractDigitalTwinInterfaceClient {
public class DeviceInformation extends AbstractDigitalTwinComponent {
private static final String DEVICE_INFORMATION_INTERFACE_ID = "urn:azureiot:DeviceManagement:DeviceInformation:1";
private static final String DEVICE_INFORMATION_INTERFACE_INSTANCE = "deviceInformation";
private static final String DEVICE_INFORMATION_COMPONENT_NAME = "deviceInformation";
private static final String PROPERTY_MANUFACTURER = "manufacturer";
private static final String PROPERTY_MODEL = "model";
private static final String PROPERTY_SOFTWARE_VERSION = "swVersion";
@@ -46,7 +46,7 @@ private DeviceInformation(String manufacturer,
String processorManufacturer,
Double totalStorage,
Double totalMemory) {
super(DEVICE_INFORMATION_INTERFACE_INSTANCE, DEVICE_INFORMATION_INTERFACE_ID);
super(DEVICE_INFORMATION_COMPONENT_NAME, DEVICE_INFORMATION_INTERFACE_ID);
this.properties = new HashMap<>();
if (isNotEmpty(manufacturer)) {
properties.put(PROPERTY_MANUFACTURER, TextNode.valueOf(manufacturer));
@@ -75,8 +75,8 @@ private DeviceInformation(String manufacturer,
}

@Override
protected void onRegistered() {
super.onRegistered();
protected void ready() {
super.ready();
if (!properties.isEmpty()) {
log.debug("Reporting device information...");
List<DigitalTwinReportProperty> reportProperties = new ArrayList<>();
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

package com.microsoft.azure.sdk.iot.digitaltwin.sample;

import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinAsyncCommandUpdate;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandRequest;
@@ -32,12 +32,13 @@
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.deserialize;
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.serialize;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.SECONDS;

@Slf4j
public class EnvironmentalSensor extends AbstractDigitalTwinInterfaceClient {
static final String ENVIRONMENTAL_SENSOR_INTERFACE_ID = "urn:java_sdk_sample:EnvironmentalSensor:1";
private static final String COMMAND_NOT_HANDLED_MESSAGE_PATTERN = "\"Command[%s] is not handled for interface[%s].\"";
public class EnvironmentalSensor extends AbstractDigitalTwinComponent {
public static final String ENVIRONMENTAL_SENSOR_INTERFACE_ID = "urn:java_sdk_sample:EnvironmentalSensor:1";
private static final String COMMAND_NOT_HANDLED_MESSAGE_PATTERN = "\"Command[%s] is not handled for component[%s].\"";
private static final String TELEMETRY_NAME_TEMPERATURE = "temp";
private static final String TELEMETRY_NAME_HUMIDITY = "humid";
private static final String COMMAND_TURN_ON = "turnon";
@@ -49,21 +50,18 @@ public class EnvironmentalSensor extends AbstractDigitalTwinInterfaceClient {
private static final String PROPERTY_BRIGHTNESS = "brightness";
private final UiHandler uiHandler;

protected EnvironmentalSensor(@NonNull String digitalTwinInterfaceInstanceName, @NonNull UiHandler uiHandler) {
super(digitalTwinInterfaceInstanceName, ENVIRONMENTAL_SENSOR_INTERFACE_ID);
protected EnvironmentalSensor(@NonNull String digitalTwinComponentName, @NonNull UiHandler uiHandler) {
super(digitalTwinComponentName, ENVIRONMENTAL_SENSOR_INTERFACE_ID);
this.uiHandler = uiHandler;
}

public Single<DigitalTwinClientResult> updateTemperatureAsync(double temperature) throws IOException {
log.debug("Temperature changed to {}.", temperature);
uiHandler.updateTemperature(temperature);
return sendTelemetryAsync(TELEMETRY_NAME_TEMPERATURE, serialize(temperature));
}

public Single<DigitalTwinClientResult> updateHumidityAsync(double humidity) throws IOException {
log.debug("Humidity changed to {}.", humidity);
uiHandler.updateHumidity(humidity);
return sendTelemetryAsync(TELEMETRY_NAME_HUMIDITY, serialize(humidity));
public Single<DigitalTwinClientResult> updateTemperatureAndHumidityAsync(double temperature, double humidity) throws IOException {
log.info("Temperature changed to {}, Humidity changed to {}.", temperature, humidity);
uiHandler.updateTemperatureAndHumidity(temperature, humidity);
Map<String, Double> properties = new HashMap<>();
properties.put(TELEMETRY_NAME_TEMPERATURE, temperature);
properties.put(TELEMETRY_NAME_HUMIDITY, humidity);
return sendTelemetryAsync(serialize(properties));
}

public Single<DigitalTwinClientResult> updateStatusAsync(final boolean state) {
@@ -77,58 +75,31 @@ public Single<DigitalTwinClientResult> updateStatusAsync(final boolean state) {
}

@Override
public void onRegistered() {
super.onRegistered();
public void ready() {
super.ready();
final Random random = new Random();
Disposable temperatureReportProcess= Single.just(random)
Disposable reportProcess = Single.just(random)
.delay(10, SECONDS)
.map(new Function<Random, Double>() {
.flatMap(new Function<Random, Single<DigitalTwinClientResult>>() {
@Override
public Double apply(Random random) {
return random.nextDouble() * 100;
public Single<DigitalTwinClientResult> apply(Random random) throws IOException {
double temperature = random.nextDouble() * 100, humidity = random.nextDouble() * 100;
return updateTemperatureAndHumidityAsync(temperature, humidity);
}
}).flatMap(new Function<Double, Single<DigitalTwinClientResult>>() {
@Override
public Single<DigitalTwinClientResult> apply(Double temperature) throws IOException {
return updateTemperatureAsync(temperature);
}
}).repeat()
})
.repeat()
.subscribe(new Consumer<DigitalTwinClientResult>() {
@Override
public void accept(DigitalTwinClientResult result) {
log.debug("Update temperature was {}", result);
log.info("Update temperature was {}", result);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
log.debug("Update temperature failed.", throwable);
}
});
Disposable humidityReportProcess = Single.just(random)
.delay(10, SECONDS)
.map(new Function<Random, Double>() {
@Override
public Double apply(Random random) {
return random.nextDouble() * 100;
}
}).flatMap(new Function<Double, Single<DigitalTwinClientResult>>() {
@Override
public Single<DigitalTwinClientResult> apply(Double humidity) throws IOException {
return updateHumidityAsync(humidity);
}
}).repeat()
.subscribe(new Consumer<DigitalTwinClientResult>() {
@Override
public void accept(DigitalTwinClientResult result) {
log.debug("Update humidity was {}", result);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
log.debug("Update humidity failed.", throwable);
}
});
log.debug("Once application quit, should dispose {} and {}.", temperatureReportProcess, humidityReportProcess);
log.debug("Once application quit, should dispose {}.", reportProcess);
}

@Override
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import com.microsoft.azure.sdk.iot.device.transport.IotHubConnectionStatus;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinDeviceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.SdkInformationComponent;

import org.apache.commons.io.IOUtils;

@@ -40,7 +41,6 @@ public class MainActivity extends AppCompatActivity implements UiHandler {
private TextView brightnessView;
private TextView temperatureView;
private TextView humidityView;
private TextView connectivityView;
private TextView registrationView;
private TextView onoffView;
private ObjectAnimator anim;
@@ -54,21 +54,14 @@ protected void onCreate(Bundle savedInstanceState) {
brightnessView = (TextView) findViewById(R.id.brightness);
temperatureView = (TextView) findViewById(R.id.temperature);
humidityView = (TextView) findViewById(R.id.humidity);
connectivityView = (TextView) findViewById(R.id.connectivity);
registrationView = (TextView) findViewById(R.id.registration);
onoffView = (TextView) findViewById(R.id.onoff);
anim = ObjectAnimator.ofInt(findViewById(R.id.blink), "backgroundColor", Color.WHITE, Color.RED, Color.WHITE);

try {
DeviceClient deviceClient = new DeviceClient(DIGITAL_TWIN_CONNECTION_STRING, MQTT);
deviceClient.registerConnectionStatusChangeCallback(new IotHubConnectionStatusChangeCallback() {
@Override
public void execute(IotHubConnectionStatus status, IotHubConnectionStatusChangeReason statusChangeReason, Throwable throwable, Object callbackContext) {
log.debug("Device client status changed to: {}, reason: {}, cause: {}", status, statusChangeReason, throwable);
updateConnectivity(status);
}
}, deviceClient);
DigitalTwinDeviceClient digitalTwinDeviceClient = new DigitalTwinDeviceClient(deviceClient);

DigitalTwinDeviceClient digitalTwinDeviceClient = new DigitalTwinDeviceClient(deviceClient, DCM_ID);
final EnvironmentalSensor environmentalSensor = new EnvironmentalSensor(ENVIRONMENTAL_SENSOR_INTERFACE_INSTANCE_NAME, this);
final DeviceInformation deviceInformation = DeviceInformation.builder()
.manufacturer("Microsoft")
@@ -82,11 +75,18 @@ public void execute(IotHubConnectionStatus status, IotHubConnectionStatusChangeR
.build();
InputStream environmentalSensorModelDefinition = getAssets().open("EnvironmentalSensor.interface.json");
final ModelDefinition modelDefinition = ModelDefinition.builder()
.digitalTwinInterfaceInstanceName(MODEL_DEFINITION_INTERFACE_NAME)
.digitalTwinComponentName(MODEL_DEFINITION_INTERFACE_NAME)
.environmentalSensorModelDefinition(IOUtils.toString(environmentalSensorModelDefinition, UTF_8))
.build();

// step 1: bindComponents
DigitalTwinClientResult bindComponentsResult = digitalTwinDeviceClient.bindComponents(asList(deviceInformation, environmentalSensor, modelDefinition, SdkInformationComponent.getInstance()));
log.info("Bind components result: {}.", bindComponentsResult);

// step 2: send registration message, optional
// TODO It's now required for IoTExplorer
registrationView.setText("Registering...");
digitalTwinDeviceClient.registerInterfacesAsync(DCM_ID, asList(deviceInformation, environmentalSensor, modelDefinition)).subscribe(new Consumer<DigitalTwinClientResult>() {
digitalTwinDeviceClient.registerComponentsAsync().subscribe(new Consumer<DigitalTwinClientResult>() {
@Override
public void accept(DigitalTwinClientResult digitalTwinClientResult) {
log.debug("Register interfaces {}.", digitalTwinClientResult);
@@ -103,11 +103,29 @@ public void accept(Throwable throwable) {
updateRegistrationStatus("Register Failed");
}
});

// step 3: subscribe for commands and properties, optional, to enable command and properties
DigitalTwinClientResult subscribeForCommandsResult = digitalTwinDeviceClient.subscribeForCommands();
log.info("Subscribe for commands result: {}.", subscribeForCommandsResult);
DigitalTwinClientResult subscribeForPropertiesResult = digitalTwinDeviceClient.subscribeForProperties();
log.info("Subscribe for properties result: {}.", subscribeForPropertiesResult);

// step 4: ready to use
DigitalTwinClientResult readyResult = digitalTwinDeviceClient.ready();
log.info("Notify ready result: {}.", readyResult);

// step 5: sync up properties, optional
DigitalTwinClientResult syncupPropertiesResult = digitalTwinDeviceClient.syncupProperties();
log.info("Sync up properties result: {}.", syncupPropertiesResult);

DigitalTwinClientResult updateStatusResult = environmentalSensor.updateStatusAsync(true).blockingGet();
log.info("Update state of environmental sensor to true, result: {}", updateStatusResult);
} catch (Exception e) {
log.error("Create device client failed", e);
}
}

@Override
public void updateName(final String name) {
runOnUiThread(new Runnable() {
@Override
@@ -117,6 +135,7 @@ public void run() {
});
}

@Override
public void updateBrightness(final double brightness) {
runOnUiThread(new Runnable() {
@Override
@@ -126,33 +145,17 @@ public void run() {
});
}

public void updateTemperature(final double temperature) {
@Override
public void updateTemperatureAndHumidity(final double temperature, final double humidity) {
runOnUiThread(new Runnable() {
@Override
public void run() {
temperatureView.setText(String.valueOf(temperature));
}
});
}

public void updateHumidity(final double humidity) {
runOnUiThread(new Runnable() {
@Override
public void run() {
humidityView.setText(String.valueOf(humidity));
}
});
}

private void updateConnectivity(final IotHubConnectionStatus connectionStatus) {
runOnUiThread(new Runnable() {
@Override
public void run() {
connectivityView.setText(connectionStatus.toString());
}
});
}

private void updateRegistrationStatus(final String registrationStatus) {
runOnUiThread(new Runnable() {
@Override
@@ -162,6 +165,7 @@ public void run() {
});
}

@Override
public void updateOnoff(final boolean on) {
runOnUiThread(new Runnable() {
@Override
@@ -171,6 +175,7 @@ public void run() {
});
}

@Override
public void startBlink(final long interval) {
runOnUiThread(new Runnable() {
@Override
Original file line number Diff line number Diff line change
@@ -5,24 +5,24 @@

package com.microsoft.azure.sdk.iot.digitaltwin.sample;

import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandRequest;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandResponse;
import lombok.Builder;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ModelDefinition extends AbstractDigitalTwinInterfaceClient {
public class ModelDefinition extends AbstractDigitalTwinComponent {
private static final String modelDefinitionInterfaceId = "urn:azureiot:ModelDiscovery:ModelDefinition:1";

private final String environmentalSensorModelDefinition;

private static final String getModelDefinitionCommandName = "getModelDefinition";

@Builder
private ModelDefinition(@NonNull String digitalTwinInterfaceInstanceName, @NonNull String environmentalSensorModelDefinition) {
super(digitalTwinInterfaceInstanceName, modelDefinitionInterfaceId);
private ModelDefinition(@NonNull String digitalTwinComponentName, @NonNull String environmentalSensorModelDefinition) {
super(digitalTwinComponentName, modelDefinitionInterfaceId);
this.environmentalSensorModelDefinition = environmentalSensorModelDefinition;
}

Original file line number Diff line number Diff line change
@@ -3,8 +3,7 @@
interface UiHandler {
void updateName(String name);
void updateBrightness(double brightness);
void updateTemperature(double temperature);
void updateHumidity(double humidity);
void updateTemperatureAndHumidity(double temperature, double humidity);
void updateOnoff(boolean on);
void startBlink(long interval);
}
Original file line number Diff line number Diff line change
@@ -87,26 +87,6 @@
android:layout_height="wrap_content" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:layout_width="100sp"
android:layout_height="wrap_content"
android:gravity="start"
android:paddingStart="2sp"
android:paddingEnd="2sp"
android:text="@string/status_connectivity"
android:textStyle="bold" />

<TextView
android:id="@+id/connectivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/status_disconnected" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@
<string name="status_connectivity">Connectivity</string>
<string name="status_registration">Registration</string>
<string name="status_onoff">On/Off</string>
<string name="status_disconnected">Disconnected</string>
<string name="status_unregistered">Unregistered</string>
<string name="status_on">ON</string>
<string name="action_blinking">Blink</string>
Original file line number Diff line number Diff line change
@@ -4,11 +4,9 @@
package com.microsoft.azure.sdk.iot.digitaltwin.sample;

import com.microsoft.azure.sdk.iot.device.DeviceClient;
import com.microsoft.azure.sdk.iot.device.IotHubConnectionStatusChangeCallback;
import com.microsoft.azure.sdk.iot.device.IotHubConnectionStatusChangeReason;
import com.microsoft.azure.sdk.iot.device.transport.IotHubConnectionStatus;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinDeviceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.SdkInformationComponent;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
@@ -23,7 +21,7 @@ public class Application {
private static final String DIGITAL_TWIN_DEVICE_CONNECTION_STRING = System.getenv("DIGITAL_TWIN_DEVICE_CONNECTION_STRING");
private static final String DCM_ID = "urn:java_sdk_sample:sample_device:1";
private static final String ENVIRONMENTAL_SENSOR_INTERFACE_INSTANCE_NAME = "environmentalSensor";
private static final String MODEL_DEFINITION_INTERFACE_NAME = "urn_azureiot_ModelDiscovery_ModelDefinition";
private static final String MODEL_DEFINITION_COMPONENT_NAME = "urn_azureiot_ModelDiscovery_ModelDefinition";

public static void main(String[] args) throws URISyntaxException, IOException {
if (DIGITAL_TWIN_DEVICE_CONNECTION_STRING == null || DIGITAL_TWIN_DEVICE_CONNECTION_STRING.isEmpty()) {
@@ -32,13 +30,8 @@ public static void main(String[] args) throws URISyntaxException, IOException {
}

DeviceClient deviceClient = new DeviceClient(DIGITAL_TWIN_DEVICE_CONNECTION_STRING, MQTT);
deviceClient.registerConnectionStatusChangeCallback(new IotHubConnectionStatusChangeCallback() {
@Override
public void execute(IotHubConnectionStatus status, IotHubConnectionStatusChangeReason statusChangeReason, Throwable throwable, Object callbackContext) {
log.info("Device client status changed to: {}, reason: {}, cause: {}", status, statusChangeReason, throwable);
}
}, deviceClient);
DigitalTwinDeviceClient digitalTwinDeviceClient = new DigitalTwinDeviceClient(deviceClient);

DigitalTwinDeviceClient digitalTwinDeviceClient = new DigitalTwinDeviceClient(deviceClient, DCM_ID);
final EnvironmentalSensor environmentalSensor = new EnvironmentalSensor(ENVIRONMENTAL_SENSOR_INTERFACE_INSTANCE_NAME);
final DeviceInformation deviceInformation = DeviceInformation.builder()
.manufacturer("Microsoft")
@@ -51,14 +44,34 @@ public void execute(IotHubConnectionStatus status, IotHubConnectionStatusChangeR
.totalStorage(1e12)
.build();
final ModelDefinition modelDefinition = ModelDefinition.builder()
.digitalTwinInterfaceInstanceName(MODEL_DEFINITION_INTERFACE_NAME)
.digitalTwinComponentName(MODEL_DEFINITION_COMPONENT_NAME)
.build();
DigitalTwinClientResult result = digitalTwinDeviceClient.registerInterfacesAsync(DCM_ID, asList(deviceInformation, environmentalSensor, modelDefinition)).blockingGet();
log.info("Register interfaces result: {}.", result);

log.info("Updating state of environmental sensor to true...");
environmentalSensor.updateStatusAsync(true).blockingGet();
log.info("State of environmental sensor was set to true");
// step 1: bindComponents
DigitalTwinClientResult bindComponentsResult = digitalTwinDeviceClient.bindComponents(asList(deviceInformation, environmentalSensor, modelDefinition, SdkInformationComponent.getInstance()));
log.info("Bind components result: {}.", bindComponentsResult);

// step 2: send registration message, optional
// TODO It's now required for IoTExplorer
DigitalTwinClientResult registerComponentsResult = digitalTwinDeviceClient.registerComponents();
log.info("Register components result: {}.", registerComponentsResult);

// step 3: subscribe for commands and properties, optional, to enable command and properties
DigitalTwinClientResult subscribeForCommandsResult = digitalTwinDeviceClient.subscribeForCommands();
log.info("Subscribe for commands result: {}.", subscribeForCommandsResult);
DigitalTwinClientResult subscribeForPropertiesResult = digitalTwinDeviceClient.subscribeForProperties();
log.info("Subscribe for properties result: {}.", subscribeForPropertiesResult);

// step 4: ready to use
DigitalTwinClientResult readyResult = digitalTwinDeviceClient.ready();
log.info("Notify ready result: {}.", readyResult);

// step 5: sync up properties, optional
DigitalTwinClientResult syncupPropertiesResult = digitalTwinDeviceClient.syncupProperties();
log.info("Sync up properties result: {}.", syncupPropertiesResult);

DigitalTwinClientResult updateStatusResult = environmentalSensor.updateStatusAsync(true).blockingGet();
log.info("Update state of environmental sensor to true, result: {}", updateStatusResult);

log.info("Waiting for service updates...");
log.info("Enter any key to finish");
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import com.fasterxml.jackson.databind.node.DoubleNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinReportProperty;
import io.reactivex.rxjava3.disposables.Disposable;
@@ -23,9 +23,9 @@
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.isNotEmpty;

@Slf4j
public class DeviceInformation extends AbstractDigitalTwinInterfaceClient {
public class DeviceInformation extends AbstractDigitalTwinComponent {
private static final String DEVICE_INFORMATION_INTERFACE_ID = "urn:azureiot:DeviceManagement:DeviceInformation:1";
private static final String DEVICE_INFORMATION_INTERFACE_INSTANCE = "deviceInformation";
private static final String DEVICE_INFORMATION_COMPONENT_NAME = "deviceInformation";
private static final String PROPERTY_MANUFACTURER = "manufacturer";
private static final String PROPERTY_MODEL = "model";
private static final String PROPERTY_SOFTWARE_VERSION = "swVersion";
@@ -45,7 +45,7 @@ private DeviceInformation(String manufacturer,
String processorManufacturer,
Double totalStorage,
Double totalMemory) {
super(DEVICE_INFORMATION_INTERFACE_INSTANCE, DEVICE_INFORMATION_INTERFACE_ID);
super(DEVICE_INFORMATION_COMPONENT_NAME, DEVICE_INFORMATION_INTERFACE_ID);
this.properties = new HashMap<>();
if (isNotEmpty(manufacturer)) {
properties.put(PROPERTY_MANUFACTURER, TextNode.valueOf(manufacturer));
@@ -74,8 +74,8 @@ private DeviceInformation(String manufacturer,
}

@Override
protected void onRegistered() {
super.onRegistered();
protected void ready() {
super.ready();
if (!properties.isEmpty()) {
log.debug("Reporting device information...");
List<DigitalTwinReportProperty> reportProperties = new ArrayList<>();
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

package com.microsoft.azure.sdk.iot.digitaltwin.sample;

import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.DigitalTwinClientResult;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinAsyncCommandUpdate;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandRequest;
@@ -30,12 +30,13 @@
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.deserialize;
import static com.microsoft.azure.sdk.iot.digitaltwin.device.serializer.JsonSerializer.serialize;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.SECONDS;

@Slf4j
public class EnvironmentalSensor extends AbstractDigitalTwinInterfaceClient {
public class EnvironmentalSensor extends AbstractDigitalTwinComponent {
public static final String ENVIRONMENTAL_SENSOR_INTERFACE_ID = "urn:java_sdk_sample:EnvironmentalSensor:1";
private static final String COMMAND_NOT_HANDLED_MESSAGE_PATTERN = "\"Command[%s] is not handled for interface[%s].\"";
private static final String COMMAND_NOT_HANDLED_MESSAGE_PATTERN = "\"Command[%s] is not handled for component[%s].\"";
private static final String TELEMETRY_NAME_TEMPERATURE = "temp";
private static final String TELEMETRY_NAME_HUMIDITY = "humid";
private static final String COMMAND_TURN_ON = "turnon";
@@ -46,18 +47,16 @@ public class EnvironmentalSensor extends AbstractDigitalTwinInterfaceClient {
private static final String PROPERTY_NAME = "name";
private static final String PROPERTY_BRIGHTNESS = "brightness";

public EnvironmentalSensor(@NonNull String digitalTwinInterfaceInstanceName) {
super(digitalTwinInterfaceInstanceName, ENVIRONMENTAL_SENSOR_INTERFACE_ID);
public EnvironmentalSensor(@NonNull String digitalTwinComponentName) {
super(digitalTwinComponentName, ENVIRONMENTAL_SENSOR_INTERFACE_ID);
}

public Single<DigitalTwinClientResult> updateTemperatureAsync(double temperature) throws IOException {
log.info("Temperature changed to {}.", temperature);
return sendTelemetryAsync(TELEMETRY_NAME_TEMPERATURE, serialize(temperature));
}

public Single<DigitalTwinClientResult> updateHumidityAsync(double humidity) throws IOException {
log.info("Humidity changed to {}.", humidity);
return sendTelemetryAsync(TELEMETRY_NAME_HUMIDITY, serialize(humidity));
public Single<DigitalTwinClientResult> updateTemperatureAndHumidityAsync(double temperature, double humidity) throws IOException {
log.info("Temperature changed to {}, Humidity changed to {}.", temperature, humidity);
Map<String, Double> properties = new HashMap<>();
properties.put(TELEMETRY_NAME_TEMPERATURE, temperature);
properties.put(TELEMETRY_NAME_HUMIDITY, humidity);
return sendTelemetryAsync(serialize(properties));
}

public Single<DigitalTwinClientResult> updateStatusAsync(final boolean state) {
@@ -70,22 +69,19 @@ public Single<DigitalTwinClientResult> updateStatusAsync(final boolean state) {
}

@Override
public void onRegistered() {
super.onRegistered();
public void ready() {
super.ready();
final Random random = new Random();
Disposable temperatureReportProcess = Single.just(random)
Disposable reportProcess = Single.just(random)
.delay(10, SECONDS)
.map(new Function<Random, Double>() {
.flatMap(new Function<Random, Single<DigitalTwinClientResult>>() {
@Override
public Double apply(Random random) {
return random.nextDouble() * 100;
public Single<DigitalTwinClientResult> apply(Random random) throws IOException {
double temperature = random.nextDouble() * 100, humidity = random.nextDouble() * 100;
return updateTemperatureAndHumidityAsync(temperature, humidity);
}
}).flatMap(new Function<Double, Single<DigitalTwinClientResult>>() {
@Override
public Single<DigitalTwinClientResult> apply(Double temperature) throws IOException {
return updateTemperatureAsync(temperature);
}
}).repeat()
})
.repeat()
.subscribe(new Consumer<DigitalTwinClientResult>() {
@Override
public void accept(DigitalTwinClientResult result) {
@@ -97,31 +93,7 @@ public void accept(Throwable throwable) {
log.debug("Update temperature failed.", throwable);
}
});
Disposable humidityReportProcess = Single.just(random)
.delay(10, SECONDS)
.map(new Function<Random, Double>() {
@Override
public Double apply(Random random) {
return random.nextDouble() * 100;
}
}).flatMap(new Function<Double, Single<DigitalTwinClientResult>>() {
@Override
public Single<DigitalTwinClientResult> apply(Double humidity) throws IOException {
return updateHumidityAsync(humidity);
}
}).repeat()
.subscribe(new Consumer<DigitalTwinClientResult>() {
@Override
public void accept(DigitalTwinClientResult result) {
log.info("Update humidity was {}", result);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
log.debug("Update humidity failed.", throwable);
}
});
log.debug("Once application quit, should dispose {} and {}.", temperatureReportProcess, humidityReportProcess);
log.debug("Once application quit, should dispose {}.", reportProcess);
}

@Override
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@

package com.microsoft.azure.sdk.iot.digitaltwin.sample;

import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinInterfaceClient;
import com.microsoft.azure.sdk.iot.digitaltwin.device.AbstractDigitalTwinComponent;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandRequest;
import com.microsoft.azure.sdk.iot.digitaltwin.device.model.DigitalTwinCommandResponse;
import lombok.Builder;
@@ -15,20 +15,19 @@

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;

@Slf4j
public class ModelDefinition extends AbstractDigitalTwinInterfaceClient {
public class ModelDefinition extends AbstractDigitalTwinComponent {
private static final String modelDefinitionInterfaceId = "urn:azureiot:ModelDiscovery:ModelDefinition:1";

private final String environmentalSensorModelDefinition;

private static final String getModelDefinitionCommandName = "getModelDefinition";

@Builder
private ModelDefinition(@NonNull String digitalTwinInterfaceInstanceName) throws IOException, URISyntaxException {
super(digitalTwinInterfaceInstanceName, modelDefinitionInterfaceId);
private ModelDefinition(@NonNull String digitalTwinComponentName) throws IOException {
super(digitalTwinComponentName, modelDefinitionInterfaceId);

//Model definition is located in a json file within the resources folder of this sample
ClassLoader classLoader = ModelDefinition.class.getClassLoader();
Original file line number Diff line number Diff line change
@@ -5,4 +5,6 @@ log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{1}:%L - %m%n

log4j.logger.com.microsoft.azure.sdk.iot.digitaltwin = DEBUG
Original file line number Diff line number Diff line change
@@ -5,4 +5,6 @@ log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{1}:%L - %m%n

log4j.logger.com.microsoft.azure.sdk.iot.digitaltwin = DEBUG

0 comments on commit 6f7f0b6

Please sign in to comment.