in source/packages/services/assetlibrary/src/devices/devices.full.service.ts [265:352]
public async create(model: DeviceItem, applyProfile?:string) : Promise<string> {
logger.debug(`device.full.service create: in: model: ${JSON.stringify(model)}, applyProfile:${applyProfile}`);
ow(model, ow.object.nonEmpty);
ow(model.templateId, ow.string.nonEmpty);
ow(model.deviceId, ow.string.nonEmpty);
// if a profile to apply has been provided, apply it first
if (applyProfile!==undefined) {
model = await this.applyProfile(model, applyProfile);
}
// remove any non printable characters from the id
model.deviceId = model.deviceId.replace(/[^\x20-\x7E]+/g, '');
// any ids need to be lowercase
this.setIdsToLowercase(model);
// default initial association if none provided
if ( (model.groups===undefined || (model.groups.in===undefined && model.groups.out===undefined)) &&
(model.devices===undefined || (model.devices.in===undefined && model.devices.out===undefined)) &&
this.defaultDeviceParentRelation!=='' && this.defaultDeviceParentGroup!=='') {
model.groups= {
out: {}
};
model.groups.out[this.defaultDeviceParentRelation] = [this.defaultDeviceParentGroup];
}
// we cant check authz til here, as we need to understand any related devices and groups first
await this.authServiceFull.authorizationCheck(model.listRelatedDeviceIds(), model.listRelatedGroupPaths(), ClaimAccess.C);
// default initial state if none provided
if (model.state===undefined && this.defaultDeviceState!==undefined) {
model.state = <DeviceState> this.defaultDeviceState;
}
// perform validation of the device...
const validateSubTypeFuture = this.typesService.validateSubType(model.templateId, TypeCategory.Device, model, Operation.CREATE);
const validateGroupRelationshipsFuture = this.typesService.validateRelationshipsByPath(model.templateId, model.groups);
const validateDeviceRelationshipsFuture = this.typesService.validateRelationshipsByType(model.templateId, model.devices);
const results = await Promise.all([validateSubTypeFuture, validateGroupRelationshipsFuture, validateDeviceRelationshipsFuture]);
// schema validation results
const subTypeValidation = results[0];
if (!subTypeValidation.isValid) {
throw new Error('FAILED_VALIDATION');
}
// validate the path associations
const groupRelationshipsValidation=results[1];
if (!groupRelationshipsValidation) {
throw new Error('INVALID_RELATION');
}
// validate the device associations
const deviceRelationshipsValidation=results[2];
if (!deviceRelationshipsValidation) {
throw new Error('INVALID_RELATION');
}
// Assemble devicemodel into node
model.category = TypeCategory.Device;
const node = this.devicesAssembler.toNode(model);
// Assemble the devices components
const components: Node[]=[];
if (model.components!==undefined) {
model.components.forEach(c=> {
c.category = TypeCategory.Component;
components.push(this.devicesAssembler.toNode(c));
});
}
// Save to datastore
const id = await this.devicesDao.create(node, model.groups, model.devices, components);
// fire event
await this.eventEmitter.fire({
objectId: model.deviceId,
type: Type.device,
event: Event.create,
payload: JSON.stringify(model)
});
logger.debug(`device.full.service create: exit: id: ${id}`);
return id;
}