@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j ;
import lombok.extern.slf4j.Slf4j ;
import org.eclipse.leshan.core.Link ;
import org.eclipse.leshan.core.Link ;
import org.eclipse.leshan.core.LwM2m ;
import org.eclipse.leshan.core.LwM2m ;
import org.eclipse.leshan.core.ResponseCode ;
import org.eclipse.leshan.core.attributes.Attribute ;
import org.eclipse.leshan.core.attributes.Attribute ;
import org.eclipse.leshan.core.attributes.AttributeSet ;
import org.eclipse.leshan.core.attributes.AttributeSet ;
import org.eclipse.leshan.core.model.LwM2mModel ;
import org.eclipse.leshan.core.model.LwM2mModel ;
@ -65,21 +64,20 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes ;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes ;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent ;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent ;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig ;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig ;
import org.thingsboard.server.transport.lwm2m.server.LwM2m TransportContext ;
import org.thingsboard.server.transport.lwm2m.server.LwM2M TransportContext ;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2m Client ;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2M Client ;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2m ClientContext ;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2M ClientContext ;
import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService ;
import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService ;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest ;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest ;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService ;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService ;
import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcWriteCompositeRequest ;
import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcWriteCompositeRequest ;
import org.thingsboard.server.transport.lwm2m.utils.LwM2m ValueConverterImpl ;
import org.thingsboard.server.transport.lwm2m.utils.LwM2M ValueConverterImpl ;
import javax.annotation.PostConstruct ;
import javax.annotation.PostConstruct ;
import javax.annotation.PreDestroy ;
import javax.annotation.PreDestroy ;
import java.util.Arrays ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Collection ;
import java.util.Date ;
import java.util.Date ;
import java.util.LinkedHashMap ;
import java.util.LinkedList ;
import java.util.LinkedList ;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
@ -96,29 +94,29 @@ import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD;
import static org.eclipse.leshan.core.attributes.Attribute.STEP ;
import static org.eclipse.leshan.core.attributes.Attribute.STEP ;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK ;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK ;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE ;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2m TransportUtil.convertMultiResourceValuesFromRpcBody ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2M TransportUtil.convertMultiResourceValuesFromRpcBody ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2m TransportUtil.createModelsDefault ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2M TransportUtil.createModelsDefault ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2m TransportUtil.fromVersionedIdToObjectId ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2M TransportUtil.fromVersionedIdToObjectId ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2m TransportUtil.getVerFromPathIdVerOrId ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2M TransportUtil.getVerFromPathIdVerOrId ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2m TransportUtil.validateVersionedId ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2M TransportUtil.validateVersionedId ;
@Slf4j
@Slf4j
@Service
@Service
@TbLwM2mTransportComponent
@TbLwM2mTransportComponent
@RequiredArgsConstructor
@RequiredArgsConstructor
public class DefaultLwM2m DownlinkMsgHandler extends LwM2MExecutorAwareService implements LwM2m DownlinkMsgHandler {
public class DefaultLwM2M DownlinkMsgHandler extends LwM2MExecutorAwareService implements LwM2M DownlinkMsgHandler {
public LwM2m ValueConverterImpl converter ;
public LwM2M ValueConverterImpl converter ;
private final LwM2m TransportContext context ;
private final LwM2M TransportContext context ;
private final LwM2MTransportServerConfig config ;
private final LwM2MTransportServerConfig config ;
private final LwM2MTelemetryLogService logService ;
private final LwM2MTelemetryLogService logService ;
private final LwM2m ClientContext clientContext ;
private final LwM2M ClientContext clientContext ;
@PostConstruct
@PostConstruct
public void init ( ) {
public void init ( ) {
super . init ( ) ;
super . init ( ) ;
this . converter = LwM2m ValueConverterImpl . getInstance ( ) ;
this . converter = LwM2M ValueConverterImpl . getInstance ( ) ;
}
}
@PreDestroy
@PreDestroy
@ -137,7 +135,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendReadRequest ( LwM2m Client client , TbLwM2MReadRequest request , DownlinkRequestCallback < ReadRequest , ReadResponse > callback ) {
public void sendReadRequest ( LwM2M Client client , TbLwM2MReadRequest request , DownlinkRequestCallback < ReadRequest , ReadResponse > callback ) {
try {
try {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
ReadRequest downlink = new ReadRequest ( getReadRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) , request . getObjectId ( ) ) ;
ReadRequest downlink = new ReadRequest ( getReadRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) , request . getObjectId ( ) ) ;
@ -148,10 +146,10 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendReadCompositeRequest ( LwM2m Client client , TbLwM2MReadCompositeRequest request ,
public void sendReadCompositeRequest ( LwM2M Client client , TbLwM2MReadCompositeRequest request ,
DownlinkRequestCallback < ReadCompositeRequest , ReadCompositeResponse > callback , ContentFormat contentFormatComposite ) {
DownlinkRequestCallback < ReadCompositeRequest , ReadCompositeResponse > callback , ContentFormat compositeCo ntentFormat ) {
try {
try {
ReadCompositeRequest downlink = new ReadCompositeRequest ( contentFormatComposite , contentFormatComposite , request . getObjectIds ( ) ) ;
ReadCompositeRequest downlink = new ReadCompositeRequest ( compositeCo ntentFormat , compositeCo ntentFormat , request . getObjectIds ( ) ) ;
sendCompositeRequest ( client , downlink , this . config . getTimeout ( ) , callback ) ;
sendCompositeRequest ( client , downlink , this . config . getTimeout ( ) , callback ) ;
} catch ( InvalidRequestException e ) {
} catch ( InvalidRequestException e ) {
callback . onValidationError ( request . toString ( ) , e . getMessage ( ) ) ;
callback . onValidationError ( request . toString ( ) , e . getMessage ( ) ) ;
@ -159,7 +157,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendObserveRequest ( LwM2m Client client , TbLwM2MObserveRequest request , DownlinkRequestCallback < ObserveRequest , ObserveResponse > callback ) {
public void sendObserveRequest ( LwM2M Client client , TbLwM2MObserveRequest request , DownlinkRequestCallback < ObserveRequest , ObserveResponse > callback ) {
try {
try {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
@ -185,19 +183,19 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendObserveAllRequest ( LwM2m Client client , TbLwM2MObserveAllRequest request , DownlinkRequestCallback < TbLwM2MObserveAllRequest , Set < String > > callback ) {
public void sendObserveAllRequest ( LwM2M Client client , TbLwM2MObserveAllRequest request , DownlinkRequestCallback < TbLwM2MObserveAllRequest , Set < String > > callback ) {
Set < Observation > observations = context . getServer ( ) . getObservationService ( ) . getObservations ( client . getRegistration ( ) ) ;
Set < Observation > observations = context . getServer ( ) . getObservationService ( ) . getObservations ( client . getRegistration ( ) ) ;
Set < String > paths = observations . stream ( ) . map ( observation - > observation . getPath ( ) . toString ( ) ) . collect ( Collectors . toUnmodifiableSet ( ) ) ;
Set < String > paths = observations . stream ( ) . map ( observation - > observation . getPath ( ) . toString ( ) ) . collect ( Collectors . toUnmodifiableSet ( ) ) ;
callback . onSuccess ( request , paths ) ;
callback . onSuccess ( request , paths ) ;
}
}
@Override
@Override
public void sendDiscoverAllRequest ( LwM2m Client client , TbLwM2MDiscoverAllRequest request , DownlinkRequestCallback < TbLwM2MDiscoverAllRequest , List < Link > > callback ) {
public void sendDiscoverAllRequest ( LwM2M Client client , TbLwM2MDiscoverAllRequest request , DownlinkRequestCallback < TbLwM2MDiscoverAllRequest , List < Link > > callback ) {
callback . onSuccess ( request , Arrays . asList ( client . getRegistration ( ) . getSortedObjectLinks ( ) ) ) ;
callback . onSuccess ( request , Arrays . asList ( client . getRegistration ( ) . getSortedObjectLinks ( ) ) ) ;
}
}
@Override
@Override
public void sendExecuteRequest ( LwM2m Client client , TbLwM2MExecuteRequest request , DownlinkRequestCallback < ExecuteRequest , ExecuteResponse > callback ) {
public void sendExecuteRequest ( LwM2M Client client , TbLwM2MExecuteRequest request , DownlinkRequestCallback < ExecuteRequest , ExecuteResponse > callback ) {
try {
try {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
LwM2mPath pathIds = new LwM2mPath ( fromVersionedIdToObjectId ( request . getVersionedId ( ) ) ) ;
LwM2mPath pathIds = new LwM2mPath ( fromVersionedIdToObjectId ( request . getVersionedId ( ) ) ) ;
@ -209,19 +207,19 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
if ( resourceModelExecute = = null ) {
if ( resourceModelExecute = = null ) {
callback . onValidationError ( request . toString ( ) , "ResourceModel with " + request . getVersionedId ( ) + " is absent in system. Need ddd Lwm2m Model with id=" +
callback . onValidationError ( request . toString ( ) , "ResourceModel with " + request . getVersionedId ( ) +
pathIds . getObjectId ( ) + " ver=" + getVerFromPathIdVerOrId ( request . getVersionedId ( ) ) + " to profile." ) ;
" is absent in system. Need ddd Lwm2m Model with id=" + pathIds . getObjectId ( ) + " ver=" +
}
getVerFromPathIdVerOrId ( request . getVersionedId ( ) ) + " to profile." ) ;
else if ( resourceModelExecute . operations . isExecutable ( ) ) {
} else if ( resourceModelExecute . operations . isExecutable ( ) ) {
ExecuteRequest downlink ;
ExecuteRequest downlink ;
if ( request . getParams ( ) ! = null & & ! resourceModelExecute . multiple ) {
if ( request . getParams ( ) ! = null & & ! resourceModelExecute . multiple ) {
downlink = new ExecuteRequest ( request . getObjectId ( ) , ( String ) this . converter . convertValue ( request . getParams ( ) , resourceModelExecute . type , ResourceModel . Type . STRING , new LwM2mPath ( request . getObjectId ( ) ) ) ) ;
downlink = new ExecuteRequest ( request . getObjectId ( ) , ( String ) this . converter . convertValue ( request . getParams ( ) ,
resourceModelExecute . type , ResourceModel . Type . STRING , new LwM2mPath ( request . getObjectId ( ) ) ) ) ;
} else {
} else {
downlink = new ExecuteRequest ( request . getObjectId ( ) ) ;
downlink = new ExecuteRequest ( request . getObjectId ( ) ) ;
}
}
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
}
} else {
else {
callback . onValidationError ( request . toString ( ) , "Resource with " + request . getVersionedId ( ) + " is not executable." ) ;
callback . onValidationError ( request . toString ( ) , "Resource with " + request . getVersionedId ( ) + " is not executable." ) ;
}
}
} catch ( InvalidRequestException e ) {
} catch ( InvalidRequestException e ) {
@ -230,7 +228,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendDeleteRequest ( LwM2m Client client , TbLwM2MDeleteRequest request , DownlinkRequestCallback < DeleteRequest , DeleteResponse > callback ) {
public void sendDeleteRequest ( LwM2M Client client , TbLwM2MDeleteRequest request , DownlinkRequestCallback < DeleteRequest , DeleteResponse > callback ) {
try {
try {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
sendSimpleRequest ( client , new DeleteRequest ( request . getObjectId ( ) ) , request . getTimeout ( ) , callback ) ;
sendSimpleRequest ( client , new DeleteRequest ( request . getObjectId ( ) ) , request . getTimeout ( ) , callback ) ;
@ -240,20 +238,20 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendCancelObserveRequest ( LwM2m Client client , TbLwM2MCancelObserveRequest request , DownlinkRequestCallback < TbLwM2MCancelObserveRequest , Integer > callback ) {
public void sendCancelObserveRequest ( LwM2M Client client , TbLwM2MCancelObserveRequest request , DownlinkRequestCallback < TbLwM2MCancelObserveRequest , Integer > callback ) {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
int observeCancelCnt = context . getServer ( ) . getObservationService ( ) . cancelObservations ( client . getRegistration ( ) , request . getObjectId ( ) ) ;
int observeCancelCnt = context . getServer ( ) . getObservationService ( ) . cancelObservations ( client . getRegistration ( ) , request . getObjectId ( ) ) ;
callback . onSuccess ( request , observeCancelCnt ) ;
callback . onSuccess ( request , observeCancelCnt ) ;
}
}
@Override
@Override
public void sendCancelAllRequest ( LwM2m Client client , TbLwM2MCancelAllRequest request , DownlinkRequestCallback < TbLwM2MCancelAllRequest , Integer > callback ) {
public void sendCancelAllRequest ( LwM2M Client client , TbLwM2MCancelAllRequest request , DownlinkRequestCallback < TbLwM2MCancelAllRequest , Integer > callback ) {
int observeCancelCnt = context . getServer ( ) . getObservationService ( ) . cancelObservations ( client . getRegistration ( ) ) ;
int observeCancelCnt = context . getServer ( ) . getObservationService ( ) . cancelObservations ( client . getRegistration ( ) ) ;
callback . onSuccess ( request , observeCancelCnt ) ;
callback . onSuccess ( request , observeCancelCnt ) ;
}
}
@Override
@Override
public void sendDiscoverRequest ( LwM2m Client client , TbLwM2MDiscoverRequest request , DownlinkRequestCallback < DiscoverRequest , DiscoverResponse > callback ) {
public void sendDiscoverRequest ( LwM2M Client client , TbLwM2MDiscoverRequest request , DownlinkRequestCallback < DiscoverRequest , DiscoverResponse > callback ) {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
sendSimpleRequest ( client , new DiscoverRequest ( request . getObjectId ( ) ) , request . getTimeout ( ) , callback ) ;
sendSimpleRequest ( client , new DiscoverRequest ( request . getObjectId ( ) ) , request . getTimeout ( ) , callback ) ;
}
}
@ -271,7 +269,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
* addAttribute ( attributes , OBJECT_VERSION , params . getVer ( ) , StringUtils : : isNotEmpty , Function . identity ( ) ) ;
* addAttribute ( attributes , OBJECT_VERSION , params . getVer ( ) , StringUtils : : isNotEmpty , Function . identity ( ) ) ;
* /
* /
@Override
@Override
public void sendWriteAttributesRequest ( LwM2m Client client , TbLwM2MWriteAttributesRequest request , DownlinkRequestCallback < WriteAttributesRequest , WriteAttributesResponse > callback ) {
public void sendWriteAttributesRequest ( LwM2M Client client , TbLwM2MWriteAttributesRequest request , DownlinkRequestCallback < WriteAttributesRequest , WriteAttributesResponse > callback ) {
try {
try {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
if ( request . getAttributes ( ) = = null ) {
if ( request . getAttributes ( ) = = null ) {
@ -292,7 +290,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendWriteReplaceRequest ( LwM2m Client client , TbLwM2MWriteReplaceRequest request , DownlinkRequestCallback < WriteRequest , WriteResponse > callback ) {
public void sendWriteReplaceRequest ( LwM2M Client client , TbLwM2MWriteReplaceRequest request , DownlinkRequestCallback < WriteRequest , WriteResponse > callback ) {
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
if ( resultIds . isResource ( ) | | resultIds . isResourceInstance ( ) ) {
if ( resultIds . isResource ( ) | | resultIds . isResourceInstance ( ) ) {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
@ -301,12 +299,15 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
try {
try {
WriteRequest downlink = null ;
WriteRequest downlink = null ;
String msgError = "" ;
if ( resourceModelWrite . multiple ) {
if ( resourceModelWrite . multiple ) {
if ( request . getValue ( ) instanceof Map & & ( ( Map ) request . getValue ( ) ) . size ( ) > 0 ) {
try {
Map value = convertMultiResourceValuesFromRpcBody ( request . getValue ( ) , resourceModelWrite . type , request . getObjectId ( ) ) ;
downlink = new WriteRequest ( contentFormat , resultIds . getObjectId ( ) , resultIds . getObjectInstanceId ( ) , resultIds . getResourceId ( ) ,
downlink = new WriteRequest ( contentFormat , resultIds . getObjectId ( ) , resultIds . getObjectInstanceId ( ) , resultIds . getResourceId ( ) ,
( Map < Integer , ? > ) request . getValue ( ) , resourceModelWrite . type ) ;
value , resourceModelWrite . type ) ;
} else {
} catch ( Exception e ) {
callback . onValidationError ( toString ( request ) , "Resource value is: " + request . getValue ( ) . getClass ( ) . getSimpleName ( ) + ". Value of Multi-Instance Resource must be in Json format!" ) ;
msgError = "Resource id=" + resultIds . toString ( ) + ", value = " + request . getValue ( ) +
", class = " + request . getValue ( ) . getClass ( ) . getSimpleName ( ) + "is bad. Value of Multi-Instance Resource must be in Json format!" ;
}
}
} else {
} else {
downlink = this . getWriteRequestSingleResource ( resourceModelWrite . type , contentFormat ,
downlink = this . getWriteRequestSingleResource ( resourceModelWrite . type , contentFormat ,
@ -315,7 +316,10 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
if ( downlink ! = null ) {
if ( downlink ! = null ) {
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
} else {
} else {
callback . onValidationError ( toString ( request ) , "WriteRequest is null." ) ;
if ( msgError . isEmpty ( ) ) {
msgError = "WriteRequest is null." ;
}
callback . onValidationError ( toString ( request ) , msgError ) ;
}
}
} catch ( Exception e ) {
} catch ( Exception e ) {
callback . onError ( toString ( request ) , e ) ;
callback . onError ( toString ( request ) , e ) ;
@ -330,7 +334,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendWriteCompositeRequest ( LwM2m Client client , RpcWriteCompositeRequest rpcWriteCompositeRequest ,
public void sendWriteCompositeRequest ( LwM2M Client client , RpcWriteCompositeRequest rpcWriteCompositeRequest ,
DownlinkRequestCallback < WriteCompositeRequest , WriteCompositeResponse > callback , ContentFormat contentFormatComposite ) {
DownlinkRequestCallback < WriteCompositeRequest , WriteCompositeResponse > callback , ContentFormat contentFormatComposite ) {
try {
try {
WriteCompositeRequest downlink = new WriteCompositeRequest ( contentFormatComposite , rpcWriteCompositeRequest . getNodes ( ) ) ;
WriteCompositeRequest downlink = new WriteCompositeRequest ( contentFormatComposite , rpcWriteCompositeRequest . getNodes ( ) ) ;
@ -344,110 +348,121 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
@Override
@Override
public void sendWriteUpdateRequest ( LwM2m Client client , TbLwM2MWriteUpdateRequest request , DownlinkRequestCallback < WriteRequest , WriteResponse > callback ) {
public void sendWriteUpdateRequest ( LwM2M Client client , TbLwM2MWriteUpdateRequest request , DownlinkRequestCallback < WriteRequest , WriteResponse > callback ) {
try {
try {
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
if ( resultIds . isObjectInstance ( ) | | resultIds . isResource ( ) ) {
if ( resultIds . isObjectInstance ( ) | | resultIds . isResource ( ) ) {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
WriteRequest downlink = null ;
WriteRequest downlink = null ;
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
if ( resultIds . isObjectInstance ( ) ) {
String msgError = "" ;
/ *
if ( resultIds . isObjectInstance ( ) ) {
* params = "{\"id\":0,\"value\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
/ *
* int rscId = resultIds . getObjectInstanceId ( ) ;
* params = "{\"id\":0,\"value\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
* contentFormat – Format of the payload ( TLV or JSON ) .
* int rscId = resultIds . getObjectInstanceId ( ) ;
* /
* contentFormat – Format of the payload ( TLV or JSON ) .
Collection < LwM2mResource > resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) , request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
* /
if ( resources . size ( ) > 0 ) {
Collection < LwM2mResource > resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) ,
downlink = new WriteRequest ( WriteRequest . Mode . UPDATE , contentFormat , resultIds . getObjectId ( ) , resultIds . getObjectInstanceId ( ) , resources ) ;
request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
} else {
if ( resources . size ( ) > 0 ) {
callback . onValidationError ( toString ( request ) , "No resources to update!" ) ;
downlink = new WriteRequest ( WriteRequest . Mode . UPDATE , contentFormat , resultIds . getObjectId ( ) ,
}
resultIds . getObjectInstanceId ( ) , resources ) ;
} else {
msgError = " No resources to update!" ;
}
}
else if ( resultIds . isResource ( ) ) {
} else if ( resultIds . isResource ( ) ) {
ResourceModel resourceModelWrite = client . getResourceModel ( request . getVersionedId ( ) , this . config . getModelProvider ( ) ) ;
ResourceModel resourceModelWrite = client . getResourceModel ( request . getVersionedId ( ) , this . config . getModelProvider ( ) ) ;
if ( resourceModelWrite ! = null ) {
if ( resourceModelWrite ! = null ) {
if ( resourceModelWrite . multiple ) {
if ( resourceModelWrite . multiple ) {
if ( request . getValue ( ) instanceof Map & & ( ( Map ) request . getValue ( ) ) . size ( ) > 0 ) {
try {
Map value = convertMultiResourceValuesFromRpcBody ( ( LinkedHashMap ) request . getValue ( ) , resourceModelWrite . type , request . getObjectId ( ) ) ;
Map value = convertMultiResourceValuesFromRpcBody ( request . getValue ( ) , resourceModelWrite . type , request . getObjectId ( ) ) ;
downlink = new WriteRequest ( WriteRequest . Mode . UPDATE , contentFormat , resultIds . getObjectId ( ) , resultIds . getObjectInstanceId ( ) , resultIds . getResourceId ( ) ,
downlink = new WriteRequest ( WriteRequest . Mode . UPDATE , contentFormat , resultIds . getObjectId ( ) ,
value , resourceModelWrite . type ) ;
resultIds . getObjectInstanceId ( ) , resultIds . getResourceId ( ) ,
} else {
value , resourceModelWrite . type ) ;
callback . onValidationError ( toString ( request ) , "Resource value is bad. Format: " + request . getValue ( ) . getClass ( ) . getSimpleName ( ) + ". Value of Multi-Instance Resource must be in Json format!" ) ;
} catch ( Exception e1 ) {
}
msgError = " Resource id=" + resultIds . toString ( ) +
", class = " + request . getValue ( ) . getClass ( ) . getSimpleName ( ) +
", value = " + request . getValue ( ) + " is bad. " +
"Value of Multi-Instance Resource must be in Json format!" ;
}
}
} else {
callback . onValidationError ( toString ( request ) , "Resource " + request . getVersionedId ( ) + " is not configured in the device profile!" ) ;
}
}
}
if ( downlink ! = null ) {
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
} else {
} else {
callback . onValidationError ( toString ( request ) , " Resource " + request . getVersionedId ( ) + ". This operation can only be used for ObjectInstance or Multi-Instance Resource !" ) ;
msgError = " Resource " + request . getVersionedId ( ) + " is not configured in the device profile!" ;
}
}
}
}
else {
if ( downlink ! = null ) {
callback . onValidationError ( toString ( request ) , "Resource " + request . getVersionedId ( ) + ". This operation can only be used for ObjectInstance or Resource (multiple)" ) ;
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
} else {
callback . onValidationError ( toString ( request ) , "Resource " + request . getVersionedId ( ) +
". This operation can only be used for ObjectInstance or Multi-Instance Resource !" + msgError ) ;
}
} else {
callback . onValidationError ( toString ( request ) , "Resource " + request . getVersionedId ( ) +
". This operation can only be used for ObjectInstance or Resource (multiple)" ) ;
}
}
} catch ( Exception e ) {
} catch ( Exception e ) {
callback . onValidationError ( toString ( request ) , e . getMessage ( ) ) ;
callback . onValidationError ( toString ( request ) , e . getMessage ( ) ) ;
}
}
}
}
public void sendCreateRequest ( LwM2mClient client , TbLwM2MCreateRequest request , DownlinkRequestCallback < CreateRequest , CreateResponse > callback ) {
public void sendCreateRequest ( LwM2M Client client , TbLwM2MCreateRequest request , DownlinkRequestCallback < CreateRequest , CreateResponse > callback ) {
validateVersionedId ( client , request ) ;
validateVersionedId ( client , request ) ;
CreateRequest downlink = null ;
CreateRequest downlink = null ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
LwM2mPath resultIds = new LwM2mPath ( request . getObjectId ( ) ) ;
ObjectModel objectModel = client . getObjectModel ( request . getObject Id ( ) , this . config . getModelProvider ( ) ) ;
ObjectModel objectModel = client . getObjectModel ( request . getVersioned Id ( ) , this . config . getModelProvider ( ) ) ;
// POST /{Object ID}/{Object Instance ID} && Resources is Mandatory
// POST /{Object ID}/{Object Instance ID} && Resources is Mandatory
if ( objectModel . multiple ) {
if ( objectModel ! = null ) {
// LwM2M CBOR, SenML CBOR, SenML JSON, or TLV (see [LwM2M-CORE])
if ( objectModel . multiple ) {
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
if ( resultIds . isObject ( ) | | resultIds . isObjectInstance ( ) ) {
// LwM2M CBOR, SenML CBOR, SenML JSON, or TLV (see [LwM2M-CORE])
Collection < LwM2mResource > resources ;
ContentFormat contentFormat = getWriteRequestContentFormat ( client , request , this . config . getModelProvider ( ) ) ;
if ( resultIds . isObject ( ) ) {
if ( resultIds . isObject ( ) | | resultIds . isObjectInstance ( ) ) {
// contentFormat = ContentFormat.TLV;
Collection < LwM2mResource > resources ;
if ( request . getValue ( ) ! = null ) {
if ( resultIds . isObject ( ) ) {
if ( request . getValue ( ) ! = null ) {
resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) , request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , resources ) ;
} else if ( request . getNodes ( ) ! = null & & request . getNodes ( ) . size ( ) > 0 ) {
Set < LwM2mObjectInstance > instances = ConcurrentHashMap . newKeySet ( ) ;
request . getNodes ( ) . forEach ( ( key , value ) - > {
Collection < LwM2mResource > resourcesForInstance = client . getNewResourcesForInstance ( request . getVersionedId ( ) , value , this . config . getModelProvider ( ) , this . converter ) ;
LwM2mObjectInstance instance = new LwM2mObjectInstance ( Integer . parseInt ( key ) , resourcesForInstance ) ;
instances . add ( instance ) ;
} ) ;
LwM2mObjectInstance [ ] instanceArrays = instances . toArray ( new LwM2mObjectInstance [ instances . size ( ) ] ) ;
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , instanceArrays ) ;
}
} else {
resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) , request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) , request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , resources ) ;
LwM2mObjectInstance instance = new LwM2mObjectInstance ( resultIds . getObjectInstanceId ( ) , resources ) ;
} else if ( request . getNodes ( ) ! = null & & request . getNodes ( ) . size ( ) > 0 ) {
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , instance ) ;
Set < LwM2mObjectInstance > instances = ConcurrentHashMap . newKeySet ( ) ;
request . getNodes ( ) . forEach ( ( key , value ) - > {
Collection < LwM2mResource > resourcesForInstance = client . getNewResourcesForInstance ( request . getVersionedId ( ) , value , this . config . getModelProvider ( ) , this . converter ) ;
LwM2mObjectInstance instance = new LwM2mObjectInstance ( Integer . parseInt ( key ) , resourcesForInstance ) ;
instances . add ( instance ) ;
} ) ;
LwM2mObjectInstance [ ] instanceArrays = instances . toArray ( new LwM2mObjectInstance [ instances . size ( ) ] ) ;
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , instanceArrays ) ;
}
}
}
if ( downlink ! = null ) {
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
} else {
} else {
resources = client . getNewResourcesForInstance ( request . getVersionedId ( ) , request . getValue ( ) , this . config . getModelProvider ( ) , this . converter ) ;
callback . onValidationError ( toString ( request ) , "Path " + request . getVersionedId ( ) +
LwM2mObjectInstance instance = new LwM2mObjectInstance ( resultIds . getObjectInstanceId ( ) , resources ) ;
". Object must be Multiple !" ) ;
downlink = new CreateRequest ( contentFormat , resultIds . getObjectId ( ) , instance ) ;
}
}
}
if ( downlink ! = null ) {
sendSimpleRequest ( client , downlink , request . getTimeout ( ) , callback ) ;
} else {
} else {
callback . onValidationError ( toString ( request ) , "Path " + request . getVersionedId ( ) +
throw new IllegalArgumentException ( "Path " + request . getVersionedId ( ) + ". Object must be Multiple !" ) ;
". This operation can only be used for created new ObjectInstance !" ) ;
}
}
} else {
} else {
throw new IllegalArgumentException ( "Path " + request . getVersionedId ( ) +
callback . onValidationError ( toString ( request ) , "Resource " + request . getVersionedId ( ) +
". Object must be Multiple !" ) ;
" is not configured in the device profile !" ) ;
}
}
}
}
private < R extends SimpleDownlinkRequest < T > , T extends LwM2mResponse > void sendSimpleRequest ( LwM2m Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback ) {
private < R extends SimpleDownlinkRequest < T > , T extends LwM2mResponse > void sendSimpleRequest ( LwM2M Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback ) {
sendRequest ( client , request , timeoutInMs , callback , r - > request . getPath ( ) . toString ( ) ) ;
sendRequest ( client , request , timeoutInMs , callback , r - > request . getPath ( ) . toString ( ) ) ;
}
}
private < R extends CompositeDownlinkRequest < T > , T extends LwM2mResponse > void sendCompositeRequest ( LwM2m Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback ) {
private < R extends CompositeDownlinkRequest < T > , T extends LwM2mResponse > void sendCompositeRequest ( LwM2M Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback ) {
sendRequest ( client , request , timeoutInMs , callback , r - > request . getPaths ( ) . toString ( ) ) ;
sendRequest ( client , request , timeoutInMs , callback , r - > request . getPaths ( ) . toString ( ) ) ;
}
}
private < R extends DownlinkRequest < T > , T extends LwM2mResponse > void sendRequest ( LwM2m Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback , Function < R , String > pathToStringFunction ) {
private < R extends DownlinkRequest < T > , T extends LwM2mResponse > void sendRequest ( LwM2M Client client , R request , long timeoutInMs , DownlinkRequestCallback < R , T > callback , Function < R , String > pathToStringFunction ) {
if ( ! clientContext . isDownlinkAllowed ( client ) ) {
if ( ! clientContext . isDownlinkAllowed ( client ) ) {
log . trace ( "[{}] ignore downlink request cause client is sleeping." , client . getEndpoint ( ) ) ;
log . trace ( "[{}] ignore downlink request cause client is sleeping." , client . getEndpoint ( ) ) ;
return ;
return ;
@ -472,7 +487,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private < R extends SimpleDownlinkRequest < T > , T extends LwM2mResponse > void sendWriteCompositeRequest ( LwM2m Client client , WriteCompositeRequest request , long timeoutInMs , DownlinkRequestCallback < WriteCompositeRequest , WriteCompositeResponse > callback ) {
private < R extends SimpleDownlinkRequest < T > , T extends LwM2mResponse > void sendWriteCompositeRequest ( LwM2M Client client , WriteCompositeRequest request , long timeoutInMs , DownlinkRequestCallback < WriteCompositeRequest , WriteCompositeResponse > callback ) {
if ( ! clientContext . isDownlinkAllowed ( client ) ) {
if ( ! clientContext . isDownlinkAllowed ( client ) ) {
log . trace ( "[{}] ignore downlink request cause client is sleeping." , client . getEndpoint ( ) ) ;
log . trace ( "[{}] ignore downlink request cause client is sleeping." , client . getEndpoint ( ) ) ;
return ;
return ;
@ -500,7 +515,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private < R extends DownlinkRequest < T > , T extends LwM2mResponse > void handleDownlinkError ( LwM2m Client client , R request , DownlinkRequestCallback < R , T > callback , Exception e ) {
private < R extends DownlinkRequest < T > , T extends LwM2mResponse > void handleDownlinkError ( LwM2M Client client , R request , DownlinkRequestCallback < R , T > callback , Exception e ) {
log . trace ( "[{}] Received downlink error: {}." , client . getEndpoint ( ) , e ) ;
log . trace ( "[{}] Received downlink error: {}." , client . getEndpoint ( ) , e ) ;
executor . submit ( ( ) - > {
executor . submit ( ( ) - > {
if ( e instanceof TimeoutException | | e instanceof ClientSleepingException ) {
if ( e instanceof TimeoutException | | e instanceof ClientSleepingException ) {
@ -556,7 +571,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private static < T extends HasContentFormat & HasVersionedId > ContentFormat getReadRequestContentFormat ( LwM2m Client client , T request , LwM2mModelProvider modelProvider ) {
private static < T extends HasContentFormat & HasVersionedId > ContentFormat getReadRequestContentFormat ( LwM2M Client client , T request , LwM2mModelProvider modelProvider ) {
if ( request . getRequestContentFormat ( ) . isPresent ( ) ) {
if ( request . getRequestContentFormat ( ) . isPresent ( ) ) {
return request . getRequestContentFormat ( ) . get ( ) ;
return request . getRequestContentFormat ( ) . get ( ) ;
} else {
} else {
@ -564,7 +579,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private static ContentFormat getWriteRequestContentFormat ( LwM2m Client client , TbLwM2MDownlinkRequest request , LwM2mModelProvider modelProvider ) {
private static ContentFormat getWriteRequestContentFormat ( LwM2M Client client , TbLwM2MDownlinkRequest request , LwM2mModelProvider modelProvider ) {
if ( request instanceof TbLwM2MWriteReplaceRequest & & ( ( TbLwM2MWriteReplaceRequest ) request ) . getContentFormat ( ) ! = null ) {
if ( request instanceof TbLwM2MWriteReplaceRequest & & ( ( TbLwM2MWriteReplaceRequest ) request ) . getContentFormat ( ) ! = null ) {
return ( ( TbLwM2MWriteReplaceRequest ) request ) . getContentFormat ( ) ;
return ( ( TbLwM2MWriteReplaceRequest ) request ) . getContentFormat ( ) ;
} else if ( request instanceof TbLwM2MWriteUpdateRequest & & ( ( TbLwM2MWriteUpdateRequest ) request ) . getObjectContentFormat ( ) ! = null ) {
} else if ( request instanceof TbLwM2MWriteUpdateRequest & & ( ( TbLwM2MWriteUpdateRequest ) request ) . getObjectContentFormat ( ) ! = null ) {
@ -582,20 +597,11 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private static ContentFormat getRequestContentFormat ( LwM2m Client client , String versionedId , LwM2mModelProvider modelProvider ) {
private static ContentFormat getRequestContentFormat ( LwM2M Client client , String versionedId , LwM2mModelProvider modelProvider ) {
LwM2mPath pathIds = new LwM2mPath ( fromVersionedIdToObjectId ( versionedId ) ) ;
LwM2mPath pathIds = new LwM2mPath ( fromVersionedIdToObjectId ( versionedId ) ) ;
if ( pathIds . isResourceInstance ( ) ) {
if ( pathIds . isResource ( ) | | pathIds . isResourceInstance ( ) ) {
ResourceModel resourceModel = client . getResourceModel ( versionedId , modelProvider ) ;
if ( OBJLNK . equals ( resourceModel . type ) ) {
return ContentFormat . LINK ;
} else if ( OPAQUE . equals ( resourceModel . type ) ) {
return ContentFormat . OPAQUE ;
} else {
return findFirst ( client . getClientSupportContentFormats ( ) , client . getDefaultContentFormat ( ) , ContentFormat . CBOR , ContentFormat . SENML_CBOR , ContentFormat . SENML_JSON ) ;
}
} else if ( pathIds . isResource ( ) ) {
ResourceModel resourceModel = client . getResourceModel ( versionedId , modelProvider ) ;
ResourceModel resourceModel = client . getResourceModel ( versionedId , modelProvider ) ;
if ( resourceModel ! = null & & ! resourceModel . multiple ) {
if ( resourceModel ! = null & & ( pathIds . isResourceInstance ( ) | | ( pathIds . isResource ( ) & & ! resourceModel . multiple ) ) ) {
if ( OBJLNK . equals ( resourceModel . type ) ) {
if ( OBJLNK . equals ( resourceModel . type ) ) {
return ContentFormat . LINK ;
return ContentFormat . LINK ;
} else if ( OPAQUE . equals ( resourceModel . type ) ) {
} else if ( OPAQUE . equals ( resourceModel . type ) ) {
@ -611,7 +617,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
}
}
private static ContentFormat getContentFormatForComplex ( LwM2m Client client ) {
private static ContentFormat getContentFormatForComplex ( LwM2M Client client ) {
if ( LwM2m . Version . V1_0 . equals ( client . getRegistration ( ) . getLwM2mVersion ( ) ) ) {
if ( LwM2m . Version . V1_0 . equals ( client . getRegistration ( ) . getLwM2mVersion ( ) ) ) {
return ContentFormat . TLV ;
return ContentFormat . TLV ;
} else if ( LwM2m . Version . V1_1 . equals ( client . getRegistration ( ) . getLwM2mVersion ( ) ) ) {
} else if ( LwM2m . Version . V1_1 . equals ( client . getRegistration ( ) . getLwM2mVersion ( ) ) ) {
@ -639,7 +645,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
try {
try {
return request ! = null ? request . toString ( ) : "" ;
return request ! = null ? request . toString ( ) : "" ;
} catch ( Exception e ) {
} catch ( Exception e ) {
log . trace ( "Failed to convert request to string" , e ) ;
log . debug ( "Failed to convert request to string" , e ) ;
return request . getClass ( ) . getSimpleName ( ) ;
return request . getClass ( ) . getSimpleName ( ) ;
}
}
}
}