Merge pull request #4339 from thingsboard/lwm2m_add_resourses

Lwm2m add resourses
This commit is contained in:
nickAS21 2021-03-30 17:21:54 +03:00 committed by GitHub
commit 0aa16d28a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 45 deletions

View File

@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
@ -41,8 +42,10 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.StringJoiner;
@Slf4j
@RestController
@ -108,13 +111,24 @@ public class TbResourceController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/resource", method = RequestMethod.POST)
@ResponseBody
public TbResource saveResource(@RequestBody TbResource resource) throws ThingsboardException {
public List<TbResource> saveResources(@RequestBody List<TbResource> resources) throws ThingsboardException {
try {
resource.setTenantId(getTenantId());
checkEntity(resource.getId(), resource, Resource.TB_RESOURCE);
TbResource savedResource = checkNotNull(resourceService.saveResource(resource));
tbClusterService.onResourceChange(savedResource, null);
return savedResource;
List<TbResource> addResources = new ArrayList<>();
StringJoiner noSaveResources = new StringJoiner("; ");
resources.forEach(resource -> {
try {
resource.setTenantId(getTenantId());
checkEntity(resource.getId(), resource, Resource.TB_RESOURCE);
addResources.add(addResource(resource));
} catch (Exception e) {
noSaveResources.add(resource.getFileName());
log.warn("Fail save resource: [{}]", resource.getFileName(), e);
}
});
if (noSaveResources.length() > 0) {
throw new ThingsboardException(String.format("Fail save resource: %s", noSaveResources.toString()), ThingsboardErrorCode.INVALID_ARGUMENTS);
}
return addResources;
} catch (Exception e) {
throw handleException(e);
}
@ -183,4 +197,11 @@ public class TbResourceController extends BaseController {
throw handleException(e);
}
}
}
private TbResource addResource(TbResource resource) throws Exception {
checkEntity(resource.getId(), resource, Resource.TB_RESOURCE);
TbResource savedResource = checkNotNull(resourceService.saveResource(resource));
tbClusterService.onResourceChange(savedResource, null);
return savedResource;
}
}

View File

@ -596,8 +596,7 @@ transport:
timeout: "${LWM2M_TIMEOUT:120000}"
recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}"
recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
request_pool_size: "${LWM2M_REQUEST_POOL_SIZE:100}"
request_error_pool_size: "${LWM2M_REQUEST_ERROR_POOL_SIZE:10}"
response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}"
registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}"
update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}"
un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}"
@ -606,8 +605,7 @@ transport:
# To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format
# Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh
key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}"
# key_store_type: "${LWM2M_KEYSTORE_TYPE:PKCS12}"
# key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks"
# key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks"
key_store_path_file: "${KEY_STORE_PATH_FILE:}"
key_store_password: "${LWM2M_KEYSTORE_PASSWORD_SERVER:server_ks_password}"
root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}"
@ -626,24 +624,26 @@ transport:
# - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)]
public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}"
public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" # Only Certificate_x509:
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
bootstrap:
enable: "${LWM2M_BOOTSTRAP_ENABLED:true}"
id: "${LWM2M_SERVER_ID:111}"
enable: "${LWM2M_ENABLED_BS:true}"
id: "${LWM2M_SERVER_ID_BS:111}"
bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC_BS:5687}"
secure:
bind_address_security: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
bind_port_security: "${LWM2M_BIND_PORT_SEC_BS:5688}"
bind_port_security: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
# - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)]
# - Public Key (Hex): [3059301306072a8648ce3d020106082a8648ce3d030107034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34]
# - Private Key (Hex): [308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34],
public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}"
# Use redis for Security and Registration stores
redis.enabled: "${LWM2M_REDIS_ENABLED:false}"

View File

@ -465,6 +465,10 @@ public abstract class AbstractWebTest {
return readResponse(doPost(urlTemplate, content, params).andExpect(status().isOk()), responseType);
}
protected <T, R> R doPostWithTypedResponse(String urlTemplate, T content, TypeReference<R> responseType, ResultMatcher resultMatcher, String... params) throws Exception {
return readResponse(doPost(urlTemplate, content, params).andExpect(resultMatcher), responseType);
}
protected <T> T doPostAsync(String urlTemplate, T content, Class<T> responseClass, ResultMatcher resultMatcher, String... params) throws Exception {
return readResponse(doPostAsync(urlTemplate, content, DEFAULT_TIMEOUT, params).andExpect(resultMatcher), responseClass);
}

View File

@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.security.Authority;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -79,7 +80,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setFileName(DEFAULT_FILE_NAME);
resource.setData("Test Data");
TbResource savedResource = doPost("/api/resource", resource, TbResource.class);
TbResource savedResource = save(resource);
Assert.assertNotNull(savedResource);
Assert.assertNotNull(savedResource.getId());
@ -92,7 +93,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
savedResource.setTitle("My new resource");
doPost("/api/resource", savedResource, TbResource.class);
save(savedResource);
TbResource foundResource = doGet("/api/resource/" + savedResource.getId().getId().toString(), TbResource.class);
Assert.assertEquals(foundResource.getTitle(), savedResource.getTitle());
@ -106,10 +107,10 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setFileName(DEFAULT_FILE_NAME);
resource.setData("Test Data");
TbResource savedResource = doPost("/api/resource", resource, TbResource.class);
TbResource savedResource = save(resource);
loginDifferentTenant();
doPost("/api/resource", savedResource, TbResource.class, status().isForbidden());
doPostWithTypedResponse("/api/resource", Collections.singletonList(savedResource), new TypeReference<>(){}, status().isBadRequest());
deleteDifferentTenant();
}
@ -121,7 +122,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setFileName(DEFAULT_FILE_NAME);
resource.setData("Test Data");
TbResource savedResource = doPost("/api/resource", resource, TbResource.class);
TbResource savedResource = save(resource);
TbResource foundResource = doGet("/api/resource/" + savedResource.getId().getId().toString(), TbResource.class);
Assert.assertNotNull(foundResource);
@ -136,7 +137,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setFileName(DEFAULT_FILE_NAME);
resource.setData("Test Data");
TbResource savedResource = doPost("/api/resource", resource, TbResource.class);
TbResource savedResource = save(resource);
doDelete("/api/resource/" + savedResource.getId().getId().toString())
.andExpect(status().isOk());
@ -147,15 +148,18 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
@Test
public void testFindTenantTbResources() throws Exception {
List<TbResourceInfo> resources = new ArrayList<>();
List<TbResource> resourcesToSave = new ArrayList<>();
for (int i = 0; i < 173; i++) {
TbResource resource = new TbResource();
resource.setTitle("Resource" + i);
resource.setResourceType(ResourceType.JKS);
resource.setFileName(i + DEFAULT_FILE_NAME);
resource.setData("Test Data");
resources.add(new TbResourceInfo(doPost("/api/resource", resource, TbResource.class)));
resourcesToSave.add(resource);
}
List<TbResourceInfo> resources =save(resourcesToSave).stream().map(TbResourceInfo::new).collect(Collectors.toList());
List<TbResourceInfo> loadedResources = new ArrayList<>();
PageLink pageLink = new PageLink(24);
PageData<TbResourceInfo> pageData;
@ -186,7 +190,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setResourceType(ResourceType.JKS);
resource.setFileName(i + DEFAULT_FILE_NAME);
resource.setData("Test Data");
resources.add(new TbResourceInfo(doPost("/api/resource", resource, TbResource.class)));
resources.add(new TbResourceInfo(save(resource)));
}
List<TbResourceInfo> loadedResources = new ArrayList<>();
PageLink pageLink = new PageLink(24);
@ -236,7 +240,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setResourceType(ResourceType.JKS);
resource.setFileName(i + DEFAULT_FILE_NAME);
resource.setData("Test Data");
expectedResources.add(new TbResourceInfo(doPost("/api/resource", resource, TbResource.class)));
expectedResources.add(new TbResourceInfo(save(resource)));
}
loginSysAdmin();
@ -247,7 +251,7 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
resource.setResourceType(ResourceType.JKS);
resource.setFileName(i + DEFAULT_FILE_NAME);
resource.setData("Test Data");
TbResourceInfo savedResource = new TbResourceInfo(doPost("/api/resource", resource, TbResource.class));
TbResourceInfo savedResource = new TbResourceInfo(save(resource));
systemResources.add(savedResource);
if (i >= 73) {
expectedResources.add(savedResource);
@ -281,4 +285,12 @@ public abstract class BaseTbResourceControllerTest extends AbstractControllerTes
.andExpect(status().isOk());
}
}
private TbResource save(TbResource tbResource) throws Exception {
return save(Collections.singletonList(tbResource)).get(0);
}
private List<TbResource> save(List<TbResource> tbResources) throws Exception {
return doPostWithTypedResponse("/api/resource", tbResources, new TypeReference<>(){});
}
}

View File

@ -101,7 +101,7 @@ public class LwM2mTransportRequest {
@PostConstruct
public void init() {
this.converter = LwM2mValueConverterImpl.getInstance();
executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getRequestPoolSize(),
executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResponsePoolSize(),
new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
}

View File

@ -92,12 +92,8 @@ public class LwM2MTransportConfigServer {
private boolean recommendedSupportedGroups;
@Getter
@Value("${transport.lwm2m.request_pool_size:}")
private int requestPoolSize;
@Getter
@Value("${transport.lwm2m.request_error_pool_size:}")
private int requestErrorPoolSize;
@Value("${transport.lwm2m.response_pool_size:}")
private int responsePoolSize;
@Getter
@Value("${transport.lwm2m.registered_pool_size:}")

View File

@ -129,8 +129,7 @@ transport:
timeout: "${LWM2M_TIMEOUT:120000}"
recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}"
recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
request_pool_size: "${LWM2M_REQUEST_POOL_SIZE:100}"
request_error_pool_size: "${LWM2M_REQUEST_ERROR_POOL_SIZE:10}"
response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}"
registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}"
update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}"
un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}"
@ -139,8 +138,7 @@ transport:
# To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format
# Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh
key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}"
# key_store_type: "${LWM2M_KEYSTORE_TYPE:PKCS12}"
# key_store_path_file: "${KEY_STORE_PATH_FILE:/transport/lwm2m/src/main/data/credentials/serverKeyStore.jks}"
# key_store_path_file: "${KEY_STORE_PATH_FILE:/transport/lwm2m/src/main/data/credentials/serverKeyStore.jks}"
key_store_path_file: "${KEY_STORE_PATH_FILE:}"
key_store_password: "${LWM2M_KEYSTORE_PASSWORD_SERVER:server_ks_password}"
root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}"
@ -159,24 +157,26 @@ transport:
# - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)]
public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}"
public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" # Only Certificate_x509:
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
bootstrap:
enable: "${LWM2M_BOOTSTRAP_ENABLED:true}"
id: "${LWM2M_SERVER_ID:111}"
enable: "${LWM2M_ENABLED_BS:true}"
id: "${LWM2M_SERVER_ID_BS:111}"
bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC_BS:5687}"
secure:
bind_address_security: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
bind_port_security: "${LWM2M_BIND_PORT_SEC_BS:5688}"
bind_port_security: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
# - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)]
# - Public Key (Hex): [3059301306072a8648ce3d020106082a8648ce3d030107034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34]
# - Private Key (Hex): [308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34],
public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}"
# Use redis for Security and Registration stores
redis.enabled: "${LWM2M_REDIS_ENABLED:false}"