|
|
@ -65,6 +65,7 @@ import org.thingsboard.server.service.state.DeviceStateService; |
|
|
import java.util.Collections; |
|
|
import java.util.Collections; |
|
|
import java.util.List; |
|
|
import java.util.List; |
|
|
import java.util.Optional; |
|
|
import java.util.Optional; |
|
|
|
|
|
import java.util.concurrent.ExecutionException; |
|
|
import java.util.concurrent.locks.ReentrantLock; |
|
|
import java.util.concurrent.locks.ReentrantLock; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -109,7 +110,7 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public ListenableFuture<ProvisionResponse> provisionDevice(ProvisionRequest provisionRequest) { |
|
|
public ProvisionResponse provisionDevice(ProvisionRequest provisionRequest) { |
|
|
String provisionRequestKey = provisionRequest.getCredentials().getProvisionDeviceKey(); |
|
|
String provisionRequestKey = provisionRequest.getCredentials().getProvisionDeviceKey(); |
|
|
String provisionRequestSecret = provisionRequest.getCredentials().getProvisionDeviceSecret(); |
|
|
String provisionRequestSecret = provisionRequest.getCredentials().getProvisionDeviceSecret(); |
|
|
|
|
|
|
|
|
@ -152,35 +153,24 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.NOT_FOUND.name()); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.NOT_FOUND.name()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private ListenableFuture<ProvisionResponse> processProvision(Device device, ProvisionRequest provisionRequest) { |
|
|
private ProvisionResponse processProvision(Device device, ProvisionRequest provisionRequest) { |
|
|
ListenableFuture<Optional<AttributeKvEntry>> provisionStateFuture = attributesService.find(device.getTenantId(), device.getId(), |
|
|
try { |
|
|
DataConstants.SERVER_SCOPE, DEVICE_PROVISION_STATE); |
|
|
Optional<AttributeKvEntry> provisionState = attributesService.find(device.getTenantId(), device.getId(), |
|
|
ListenableFuture<Boolean> provisionedFuture = Futures.transformAsync(provisionStateFuture, optionalAtr -> { |
|
|
DataConstants.SERVER_SCOPE, DEVICE_PROVISION_STATE).get(); |
|
|
if (optionalAtr != null && optionalAtr.isPresent()) { |
|
|
if (provisionState != null && provisionState.isPresent() && !provisionState.get().getValueAsString().equals(PROVISIONED_STATE)) { |
|
|
String state = optionalAtr.get().getValueAsString(); |
|
|
|
|
|
if (state.equals(PROVISIONED_STATE)) { |
|
|
|
|
|
return Futures.immediateFuture(true); |
|
|
|
|
|
} else { |
|
|
|
|
|
log.error("[{}][{}] Unknown provision state: {}!", device.getName(), DEVICE_PROVISION_STATE, state); |
|
|
|
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return Futures.transform(saveProvisionStateAttribute(device), input -> false, MoreExecutors.directExecutor()); |
|
|
|
|
|
}, MoreExecutors.directExecutor()); |
|
|
|
|
|
if (provisionedFuture.isCancelled()) { |
|
|
|
|
|
throw new RuntimeException("Unknown provision state!"); |
|
|
|
|
|
} |
|
|
|
|
|
return Futures.transform(provisionedFuture, provisioned -> { |
|
|
|
|
|
if (provisioned) { |
|
|
|
|
|
notify(device, provisionRequest, DataConstants.PROVISION_FAILURE, false); |
|
|
notify(device, provisionRequest, DataConstants.PROVISION_FAILURE, false); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
|
|
|
} else { |
|
|
|
|
|
saveProvisionStateAttribute(device).get(); |
|
|
|
|
|
notify(device, provisionRequest, DataConstants.PROVISION_SUCCESS, true); |
|
|
} |
|
|
} |
|
|
notify(device, provisionRequest, DataConstants.PROVISION_SUCCESS, true); |
|
|
} catch (InterruptedException | ExecutionException e) { |
|
|
return new ProvisionResponse(deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId()), ProvisionResponseStatus.SUCCESS); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
}, MoreExecutors.directExecutor()); |
|
|
} |
|
|
|
|
|
return new ProvisionResponse(deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId()), ProvisionResponseStatus.SUCCESS); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private ListenableFuture<ProvisionResponse> createDevice(ProvisionRequest provisionRequest, DeviceProfile profile) { |
|
|
private ProvisionResponse createDevice(ProvisionRequest provisionRequest, DeviceProfile profile) { |
|
|
deviceCreationLock.lock(); |
|
|
deviceCreationLock.lock(); |
|
|
try { |
|
|
try { |
|
|
return processCreateDevice(provisionRequest, profile); |
|
|
return processCreateDevice(provisionRequest, profile); |
|
|
@ -194,22 +184,24 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { |
|
|
logAction(device.getTenantId(), device.getCustomerId(), device, success, provisionRequest); |
|
|
logAction(device.getTenantId(), device.getCustomerId(), device, success, provisionRequest); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private ListenableFuture<ProvisionResponse> processCreateDevice(ProvisionRequest provisionRequest, DeviceProfile profile) { |
|
|
private ProvisionResponse processCreateDevice(ProvisionRequest provisionRequest, DeviceProfile profile) { |
|
|
Device device = deviceService.findDeviceByTenantIdAndName(profile.getTenantId(), provisionRequest.getDeviceName()); |
|
|
Device device = deviceService.findDeviceByTenantIdAndName(profile.getTenantId(), provisionRequest.getDeviceName()); |
|
|
if (device == null) { |
|
|
try { |
|
|
Device savedDevice = deviceService.saveDevice(provisionRequest, profile); |
|
|
if (device == null) { |
|
|
|
|
|
Device savedDevice = deviceService.saveDevice(provisionRequest, profile); |
|
|
deviceStateService.onDeviceAdded(savedDevice); |
|
|
|
|
|
pushDeviceCreatedEventToRuleEngine(savedDevice); |
|
|
deviceStateService.onDeviceAdded(savedDevice); |
|
|
notify(savedDevice, provisionRequest, DataConstants.PROVISION_SUCCESS, true); |
|
|
saveProvisionStateAttribute(savedDevice).get(); |
|
|
|
|
|
pushDeviceCreatedEventToRuleEngine(savedDevice); |
|
|
return Futures.transform(saveProvisionStateAttribute(savedDevice), input -> |
|
|
notify(savedDevice, provisionRequest, DataConstants.PROVISION_SUCCESS, true); |
|
|
new ProvisionResponse( |
|
|
|
|
|
getDeviceCredentials(savedDevice), |
|
|
return new ProvisionResponse(getDeviceCredentials(savedDevice), ProvisionResponseStatus.SUCCESS); |
|
|
ProvisionResponseStatus.SUCCESS), MoreExecutors.directExecutor()); |
|
|
} else { |
|
|
} else { |
|
|
log.warn("[{}] The device is already provisioned!", device.getName()); |
|
|
log.warn("[{}] The device is already provisioned!", device.getName()); |
|
|
notify(device, provisionRequest, DataConstants.PROVISION_FAILURE, false); |
|
|
notify(device, provisionRequest, DataConstants.PROVISION_FAILURE, false); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (InterruptedException | ExecutionException e) { |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|