Skip to content

Commit

Permalink
feat(iot-dev): Add means to set version on Twin reported properties f…
Browse files Browse the repository at this point in the history
…or MQTT protocol
  • Loading branch information
mamokarz committed Feb 7, 2018
1 parent 2569896 commit 00ca4d3
Show file tree
Hide file tree
Showing 8 changed files with 1,177 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,6 @@ public void subscribeToTwinDesiredProperties(Map<Property, Pair<TwinPropertyCall
* @throws IOException if called when client is not opened or called before starting twin.
* @throws IllegalArgumentException if reportedProperties is null or empty.
*/

public void sendReportedProperties(Set<Property> reportedProperties) throws IOException
{
if (this.deviceTwin == null)
Expand Down Expand Up @@ -726,6 +725,55 @@ public void sendReportedProperties(Set<Property> reportedProperties) throws IOEx

}

/**
* Sends reported properties
*
* @param reportedProperties the Set for desired properties and their corresponding callback and context. Cannot be {@code null}.
* @param version the Reported property version. Cannot be negative.
*
* @throws IOException if called when client is not opened or called before starting twin.
* @throws IllegalArgumentException if reportedProperties is null or empty.
*/
public void sendReportedProperties(Set<Property> reportedProperties, int version) throws IOException
{
if (this.deviceTwin == null)
{
/*
**Codes_SRS_DEVICECLIENT_25_032: [**If the client has not started twin before calling this method, the function shall throw an IOException.**]**
*/
throw new IOException("Start twin before using it");
}

if (!this.deviceIO.isOpen())
{
/*
**Codes_SRS_DEVICECLIENT_25_033: [**If the client has not been open, the function shall throw an IOException.**]**
*/
throw new IOException("Open the client connection before using it.");
}

if (reportedProperties == null || reportedProperties.isEmpty())
{
/*
**Codes_SRS_DEVICECLIENT_25_034: [**If reportedProperties is null or empty, the function shall throw an IllegalArgumentException.**]**
*/
throw new IllegalArgumentException("Reported properties set cannot be null or empty.");
}

if(version < 0)
{
/*
**Codes_SRS_DEVICECLIENT_21_053: [**If version is negative, the function shall throw an IllegalArgumentException.**]**
*/
throw new IllegalArgumentException("Version cannot be null.");
}

/*
**Codes_SRS_DEVICECLIENT_25_035: [**This method shall send to reported properties by calling updateReportedProperties on the twin object.**]**
*/
this.deviceTwin.updateReportedProperties(reportedProperties, version);
}

/**
* Subscribes to device methods
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ public IotHubMessageResult execute(Message message, Object callbackContext)
**Codes_SRS_DEVICETWIN_25_030: [**If the message is of type DEVICE_TWIN and DEVICE_OPERATION_TWIN_GET_RESPONSE then the payload is deserialized only if the status is ok.**]**
*/
TwinState twinState = TwinState.createFromPropertiesJson(new String(dtMessage.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET));
if(twinState.getDesiredProperty() != null)
if (twinState.getDesiredProperty() != null)
{
OnDesiredPropertyChanged(twinState.getDesiredProperty());
}
if (twinState.getReportedProperty() != null)
{
OnReportedPropertyChanged(twinState.getReportedProperty());
}
}
break;
}
Expand Down Expand Up @@ -138,6 +142,75 @@ public IotHubMessageResult execute(Message message, Object callbackContext)
}
}

private void OnDesiredPropertyChanged(TwinCollection desiredPropertyMap)
{
synchronized (DEVICE_TWIN_LOCK)
{
if (desiredPropertyMap != null)
{
for (Iterator desiredPropertyIt = desiredPropertyMap.entrySet().iterator(); desiredPropertyIt.hasNext();)
{
Map.Entry<String, String> desiredProperty = (Map.Entry<String, String>) desiredPropertyIt.next();
Property property = this.getProperty(desiredPropertyMap, desiredProperty.getKey(), false);

/*
**Codes_SRS_DEVICETWIN_25_022: [**OnDesiredPropertyChange callback shall look for the user registered call back on the property that changed provided in desiredPropertyMap and call the user providing the desired property change key and value pair**]**
*/
if (!reportPropertyCallback(property))
{
/*
**Codes_SRS_DEVICETWIN_25_023: [**OnDesiredPropertyChange callback shall look for the user registered call back on the property that changed and if no callback is registered or is null then OnDesiredPropertyChange shall call the user on generic callback providing with the desired property change key and value pair**]**
*/
reportDeviceTwinGenericPropertyCallback(property);
}
desiredPropertyIt.remove();
}
}
}
}

private void OnReportedPropertyChanged(TwinCollection reportedPropertyMap)
{
synchronized (DEVICE_TWIN_LOCK)
{
if (reportedPropertyMap != null)
{
for (Iterator reportedPropertyIt = reportedPropertyMap.entrySet().iterator(); reportedPropertyIt.hasNext();)
{
Map.Entry<String, String> reportedProperty = (Map.Entry<String, String>) reportedPropertyIt.next();
Property property = this.getProperty(reportedPropertyMap, reportedProperty.getKey(), true);

/*
**Codes_SRS_DEVICETWIN_25_023: [**OnReportedPropertyChanged callback shall look for the user registered call back on the property that changed and if no callback is registered or is null then OnDesiredPropertyChange shall call the user on generic callback providing with the desired property change key and value pair**]**
*/
if(deviceTwinGenericTwinPropertyChangeCallback != null)
{
deviceTwinGenericTwinPropertyChangeCallback.TwinPropertyCallBack(property, deviceTwinGenericPropertyChangeCallbackContext);
}
reportedPropertyIt.remove();
}
}
}
}

private Property getProperty(TwinCollection twinCollection, String key, boolean isReported)
{
Object value = twinCollection.get(key);
Integer propertyVersion = twinCollection.getVersion();
TwinMetadata metadata = twinCollection.getTwinMetadata(key);
Date lastUpdated = null;
Integer lastUpdatedVersion = null;
if(metadata != null)
{
lastUpdated = metadata.getLastUpdated();
lastUpdatedVersion = metadata.getLastUpdatedVersion();
}
return new Property(
key, value,
propertyVersion,
isReported);
}

/*
Callback invoked when device twin operation request has successfully completed
*/
Expand All @@ -148,11 +221,14 @@ public void execute(IotHubStatusCode responseStatus, Object callbackContext)
{
synchronized (DEVICE_TWIN_LOCK)
{
/*
Don't worry about this....this is just delivery complete. Actual response is
another message received in deviceTwinResponseMessageCallback.
*/
deviceTwinStatusCallback.execute(responseStatus, deviceTwinStatusCallbackContext);
/*
Don't worry about this....this is just delivery complete. Actual response is
another message received in deviceTwinResponseMessageCallback.
*/
if((responseStatus != IotHubStatusCode.OK) && (responseStatus != IotHubStatusCode.OK_EMPTY))
{
deviceTwinStatusCallback.execute(responseStatus, deviceTwinStatusCallbackContext);
}
}
}
}
Expand Down Expand Up @@ -233,10 +309,15 @@ public void getDeviceTwin()
/*
**Codes_SRS_DEVICETWIN_25_008: [**This method shall send the message to the lower transport layers by calling sendEventAsync.**]**
*/
this.deviceIO.sendEventAsync(getTwinRequestMessage,new deviceTwinRequestMessageCallback(), null, this.config.getIotHubConnectionString());
this.deviceIO.sendEventAsync(getTwinRequestMessage, new deviceTwinRequestMessageCallback(), null, this.config.getIotHubConnectionString());
}

public synchronized void updateReportedProperties(Set<Property> reportedProperties) throws IOException
{
this.updateReportedProperties(reportedProperties, null);
}

public synchronized void updateReportedProperties(Set<Property> reportedProperties, Integer version) throws IOException
{
if (reportedProperties == null)
{
Expand Down Expand Up @@ -271,6 +352,14 @@ public synchronized void updateReportedProperties(Set<Property> reportedProperti
*/
updateReportedPropertiesRequest.setRequestId(String.valueOf(requestId++));

if(version != null)
{
/*
**Codes_SRS_DEVICETWIN_21_024: [**If the version is provided, this method shall set the version for the message by calling setVersion .**]**
*/
updateReportedPropertiesRequest.setVersion(Integer.toString(version));
}

/*
**Codes_SRS_DEVICETWIN_25_013: [**This method shall set the message type as DEVICE_OPERATION_TWIN_UPDATE_REPORTED_PROPERTIES_REQUEST by calling setDeviceOperationType.**]**
*/
Expand Down Expand Up @@ -343,47 +432,6 @@ private void checkSubscription()
}
}

private void OnDesiredPropertyChanged(TwinCollection desiredPropertyMap)
{
synchronized (DEVICE_TWIN_LOCK)
{
if (desiredPropertyMap != null)
{
for (Iterator desiredPropertyIt = desiredPropertyMap.entrySet().iterator(); desiredPropertyIt.hasNext();)
{
Map.Entry<String, String> desiredProperty = (Map.Entry<String, String>) desiredPropertyIt.next();
String key = desiredProperty.getKey();
Object value = desiredProperty.getValue();
Integer propertyVersion = desiredPropertyMap.getVersion();
TwinMetadata metadata = desiredPropertyMap.getTwinMetadata();
Date lastUpdated = null;
Integer lastUpdatedVersion = null;
if(metadata != null)
{
lastUpdated = metadata.getLastUpdated();
lastUpdatedVersion = metadata.getLastUpdatedVersion();
}
Property property = new Property(
key, value,
propertyVersion,
lastUpdated, lastUpdatedVersion);

/*
**Codes_SRS_DEVICETWIN_25_022: [**OnDesiredPropertyChange callback shall look for the user registered call back on the property that changed provided in desiredPropertyMap and call the user providing the desired property change key and value pair**]**
*/
if (!reportPropertyCallback(property))
{
/*
**Codes_SRS_DEVICETWIN_25_023: [**OnDesiredPropertyChange callback shall look for the user registered call back on the property that changed and if no callback is registered or is null then OnDesiredPropertyChange shall call the user on generic callback providing with the desired property change key and value pair**]**
*/
reportDeviceTwinGenericPropertyCallback(property);
}
desiredPropertyIt.remove();
}
}
}
}

private boolean reportPropertyCallback(Property property)
{
boolean reported = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ public class Property
{
private Pair<String, Object> property = null;
private Integer version = null;
private Date lastUpdated = null;
private Integer lastUpdatedVersion = null;
private boolean isReported = false;

public Property(String key, Object value)
{
Expand All @@ -35,16 +34,15 @@ public Property(String key, Object value)
this.property = new Pair<>(key, value);
}

protected Property(String key, Object value, Integer version, Date lastUpdated, Integer lastUpdatedVersion)
protected Property(String key, Object value, Integer version, boolean isReported)
{
this(key, value);

/*
**Codes_SRS_Property_21_007: [**The constructor shall store the provided version and metadata.**]**
*/
this.version = version;
this.lastUpdated = lastUpdated;
this.lastUpdatedVersion = lastUpdatedVersion;
this.isReported = isReported;
}

public String getKey()
Expand Down Expand Up @@ -79,20 +77,12 @@ public Integer getVersion()
return this.version;
}

public Date getLastUpdated()
public boolean getIsReported()
{
/*
**Codes_SRS_Property_21_009: [**The function shall return the value for this property.**]**
**Codes_SRS_Property_21_012: [**The function shall return the stored isReported.**]**
*/
return this.lastUpdated;
}

public Integer getLastUpdatedVersion()
{
/*
**Codes_SRS_Property_21_010: [**The function shall return the value for this property.**]**
*/
return this.lastUpdatedVersion;
return this.isReported;
}

/**
Expand Down
Loading

0 comments on commit 00ca4d3

Please sign in to comment.