MVP with Tensorboard

This commit is contained in:
IDONTSUDO 2024-12-01 16:12:08 +00:00 committed by Igor Brylev
parent 5b9b51ad59
commit a0d089d5bb
549 changed files with 39977 additions and 31449 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
p.py p.py
__pycache__

File diff suppressed because it is too large Load diff

72
.vscode/launch.json vendored
View file

@ -1,40 +1,36 @@
{ {
// Use IntelliSense to learn about possible attributes. "version": "0.2.0",
// Hover to view descriptions of existing attributes. "configurations": [
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 {
"version": "0.2.0", "type": "node",
"request": "launch",
"configurations": [ "name": "server-dev",
"runtimeExecutable": "npm",
{ "runtimeArgs": ["run-script", "dev"],
"type": "node", "cwd": "${workspaceRoot}/server/"
"request": "launch", },
"name": "server-dev", {
"runtimeExecutable": "npm", "type": "node",
"runtimeArgs": [ "request": "launch",
"run-script", "dev" "name": "server-test-watch",
], "runtimeExecutable": "npm",
"cwd": "${workspaceRoot}/server/", "runtimeArgs": ["run-script", "test:watch"],
}, "cwd": "${workspaceRoot}/server/"
{ },
"type": "node", {
"request": "launch", "type": "node",
"name": "server-test-watch", "request": "launch",
"runtimeExecutable": "npm", "name": "ui-dev",
"runtimeArgs": [ "runtimeExecutable": "npm",
"run-script", "test:watch" "runtimeArgs": ["run-script", "dev"],
], "cwd": "${workspaceRoot}/ui/"
"cwd": "${workspaceRoot}/server/", },
}, {
{ "type": "chrome",
"type": "node", "request": "launch",
"request": "launch", "name": "Launch debug chrome",
"name": "ui-dev", "url": "http://localhost:3000",
"runtimeExecutable": "npm", "webRoot": "${workspaceFolder}"
"runtimeArgs": [ }
"run-script", "dev" ]
],
"cwd": "${workspaceRoot}/ui/",
}
]
} }

33
.vscode/settings.json vendored
View file

@ -1,6 +1,35 @@
{ {
"cSpell.words": [ "cSpell.words": [
"введите",
"Ведите", "Ведите",
"typedataset" "дерево",
] "Количество",
"модели",
"может",
"навык",
"Новое",
"отрицательное",
"принимать",
"скила",
"создано",
"число",
"эпох",
"эпоха",
"Collada",
"Contolls",
"GLTF",
"grau",
"idontsudo",
"raycaster",
"skils",
"typedataset",
"URDF",
"usecases"
],
"files.exclude": {
"**/.git": false,
"**/.svn": false,
"**/.hg": false,
"**/CVS": false
}
} }

View file

@ -38,10 +38,12 @@ git clone https://gitlab.com/robossembler/webservice
Для работы Генератора Датасетов нужно задать следующие переменные в окружении `bash` Для работы Генератора Датасетов нужно задать следующие переменные в окружении `bash`
```bash ```bash
export PYTHON_BLENDER="путь_к_директории_сайлами_из_rcg_pipeline" export PYTHON_BLENDER="/путь_к_директории_сайлами_из/rcg_pipeline"
export PYTHON_BLENDER_PROC="путь_к_генераторуатасетов_renderBOPdataset.py" export PYTHON_BLENDER_PROC="/путь_к_генераторуатасетов_/renderBOPdataset.py"
export PYTHON_EDUCATION="absolute_path/webp/education.py"
export PYTHON_ROBOT_BUILDER="/путь_к_генераторуатасетов_/robot_builder.py"
export GET_INTERFACES="/путь_к_директории_WEB_P/get_interfaces.py"
``` ```
## Запуск сервера ## Запуск сервера
Из директории `server` в корне репозитория Из директории `server` в корне репозитория

View file

@ -19,7 +19,7 @@ module.exports = {
"@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": [ "@typescript-eslint/no-unused-vars": [
"warn", // or "error" "warn",
{ {
"argsIgnorePattern": "^_", "argsIgnorePattern": "^_",
"varsIgnorePattern": "^_", "varsIgnorePattern": "^_",

1
server/.gitignore vendored
View file

@ -9,3 +9,4 @@ build/
model_create.ts model_create.ts
public public
p.ts p.ts
package-lock.json

26
server/command.json Normal file
View file

@ -0,0 +1,26 @@
{
"tensorBoard": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": "Fail,Ok",
"delay": 200,
"checkCommand": null,
"filter": null
},
"simulationProcess": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": null,
"delay": 0,
"checkCommand": null,
"filter": null
},
"btBuilderProcess": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": null,
"delay": 0,
"checkCommand": null,
"filter": null
}
}

8576
server/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,7 @@
"test:dev": "NODE_ENV=test_dev tsc-watch --onSuccess 'ts-node ./build/test/test.js'", "test:dev": "NODE_ENV=test_dev tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
"test:unit": "NODE_ENV=unit tsc-watch --onSuccess 'ts-node ./build/test/test.js'", "test:unit": "NODE_ENV=unit tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
"test:e2e": "NODE_ENV=e2e tsc-watch --onSuccess 'ts-node ./build/test/test.js'", "test:e2e": "NODE_ENV=e2e tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
"dev": "NODE_ENV=dev tsc-watch --onSuccess 'ts-node ./build/src/main.js'", "dev": "NODE_ENV=dev tsc-watch --onSuccess 'ts-node ./build/src/main.js'"
"build:stand": " "
}, },
"author": "IDONTSUDO", "author": "IDONTSUDO",
"devDependencies": { "devDependencies": {
@ -24,34 +23,28 @@
"chai": "latest", "chai": "latest",
"eslint": "^8.47.0", "eslint": "^8.47.0",
"mocha": "latest", "mocha": "latest",
"nyc": "latest", "node-watch": "^0.7.4",
"source-map-support": "latest", "source-map-support": "latest",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslint": "latest", "tslint": "latest",
"typescript": "^5.1.6", "typescript": "^5.1.6"
"node-watch": "^0.7.4",
"nodemon": "^3.0.1"
}, },
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.9.0",
"axios": "^1.6.2", "axios": "^1.6.2",
"babel-register": "^6.26.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.0", "class-validator": "^0.14.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"express-fileupload": "^1.4.2", "express-fileupload": "^1.4.2",
"first-di": "^1.0.11",
"md5": "^2.3.0",
"mongoose": "^7.6.2", "mongoose": "^7.6.2",
"mongoose-autopopulate": "^1.1.0", "mongoose-autopopulate": "^1.1.0",
"pattern-matching-ts": "^2.0.0",
"pm2": "^5.3.1", "pm2": "^5.3.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rimraf": "^5.0.5", "rimraf": "^5.0.5",
"socket.io": "^4.7.2", "socket.io": "^4.7.2",
"socket.io-client": "^4.7.2", "socket.io-client": "^4.7.2",
"spark-md5": "^3.0.2", "ts-pattern": "^5.1.1",
"ts-md5": "^1.3.1",
"tsc-watch": "^6.0.4", "tsc-watch": "^6.0.4",
"uuid": "^9.0.1" "uuid": "^9.0.1"
} }

View file

@ -6,7 +6,6 @@ import { Server } from "socket.io";
import { createServer } from "http"; import { createServer } from "http";
import { SocketSubscriber } from "./socket_controller"; import { SocketSubscriber } from "./socket_controller";
import { dirname } from "path"; import { dirname } from "path";
import { SetLastActivePipelineToRealTimeServiceScenario } from "../scenarios/set_active_pipeline_to_realtime_service_scenario";
import { CheckAndCreateStaticFilesFolderUseCase } from "../usecases/check_and_create_static_files_folder_usecase"; import { CheckAndCreateStaticFilesFolderUseCase } from "../usecases/check_and_create_static_files_folder_usecase";
import { DataBaseConnectUseCase } from "../usecases/database_connect_usecase"; import { DataBaseConnectUseCase } from "../usecases/database_connect_usecase";
import { TypedEvent } from "../helpers/typed_event"; import { TypedEvent } from "../helpers/typed_event";
@ -58,8 +57,6 @@ export class App extends TypedEvent<ServerStatus> {
io.on("connection", (socket) => { io.on("connection", (socket) => {
this.socketSubscribers.map((el) => { this.socketSubscribers.map((el) => {
el.emitter.on((e) => { el.emitter.on((e) => {
console.log(el.event)
console.log(e)
socket.emit(el.event, e); socket.emit(el.event, e);
}); });
}); });
@ -109,6 +106,7 @@ export class App extends TypedEvent<ServerStatus> {
await result.fold( await result.fold(
async (_s) => { async (_s) => {
await new CheckAndCreateStaticFilesFolderUseCase().call(); await new CheckAndCreateStaticFilesFolderUseCase().call();
// await new SetLastActivePipelineToRealTimeServiceScenario().call(); // await new SetLastActivePipelineToRealTimeServiceScenario().call();
}, },
async (_e) => { async (_e) => {
@ -124,3 +122,5 @@ export class App extends TypedEvent<ServerStatus> {
return rootDir + "public/"; return rootDir + "public/";
}; };
} }

View file

@ -3,6 +3,7 @@ import { Result } from "../helpers/result";
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { IRouteModel, Routes } from "../interfaces/router"; import { IRouteModel, Routes } from "../interfaces/router";
import { CoreValidation } from "../validations/core_validation"; import { CoreValidation } from "../validations/core_validation";
import { plainToInstance } from "class-transformer";
export type HttpMethodType = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "PATCH" | "HEAD"; export type HttpMethodType = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "PATCH" | "HEAD";
@ -28,16 +29,48 @@ export abstract class CallbackStrategyWithFileUpload {
abstract idValidationExpression: CoreValidation; abstract idValidationExpression: CoreValidation;
abstract call(file: File, id: string): ResponseBase; abstract call(file: File, id: string): ResponseBase;
} }
export abstract class CallbackStrategyWithFilesUploads {
abstract chuckingFileExpressions: RegExp[];
abstract call(files: File[]): ResponseBase;
}
interface ISubSetFeatureRouter<T> { export class SubRouter<A> implements ISubSetFeatureRouter<A> {
method: HttpMethodType; method: HttpMethodType;
subUrl: string; subUrl: string;
fn: fn:
| CallbackStrategyWithValidationModel<T> | CallbackStrategyWithValidationModel<A>
| CallbackStrategyWithEmpty | CallbackStrategyWithEmpty
| CallbackStrategyWithIdQuery | CallbackStrategyWithIdQuery
| CallBackStrategyWithQueryPage | CallBackStrategyWithQueryPage
| CallbackStrategyWithFileUpload; | CallbackStrategyWithFileUpload
| CallbackStrategyWithFilesUploads;
constructor(
method: HttpMethodType,
subUrl: string,
fn:
| CallbackStrategyWithValidationModel<A>
| CallbackStrategyWithEmpty
| CallbackStrategyWithIdQuery
| CallBackStrategyWithQueryPage
| CallbackStrategyWithFileUpload
| CallbackStrategyWithFilesUploads
) {
this.fn = fn;
this.subUrl = subUrl;
this.method = method;
}
}
interface ISubSetFeatureRouter<A> {
method: HttpMethodType;
subUrl: string;
fn:
| CallbackStrategyWithValidationModel<A>
| CallbackStrategyWithEmpty
| CallbackStrategyWithIdQuery
| CallBackStrategyWithQueryPage
| CallbackStrategyWithFileUpload
| CallbackStrategyWithFilesUploads;
} }
abstract class ICoreHttpController { abstract class ICoreHttpController {
@ -78,11 +111,11 @@ export class CoreHttpController<V> implements ICoreHttpController {
} }
call(): Routes { call(): Routes {
if (this.subRoutes.isNotEmpty()) { if (this.subRoutes.isNotEmpty()) {
this.subRoutes.map((el) => { this.subRoutes.map(async (el) => {
this.router[el.method.toLowerCase()](this.mainURL + "/" + el.subUrl, async (req, res) => { this.router[el.method.toLowerCase()](this.mainURL + "/" + el.subUrl, async (req, res) => {
if (el.fn instanceof CallbackStrategyWithValidationModel) { if (el.fn instanceof CallbackStrategyWithValidationModel) {
// TODO(IDONTSUDO): this.responseHelper(res, el.fn.call(req.body));
throw Error("needs to be implimed"); return;
} }
if (el.fn instanceof CallbackStrategyWithIdQuery) { if (el.fn instanceof CallbackStrategyWithIdQuery) {
if (req.query.id === undefined) { if (req.query.id === undefined) {
@ -104,6 +137,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
await this.responseHelper(res, el.fn.call(req["files"]["file"])); await this.responseHelper(res, el.fn.call(req["files"]["file"]));
} }
} }
if (el.fn instanceof CallBackStrategyWithQueryPage) { if (el.fn instanceof CallBackStrategyWithQueryPage) {
throw Error("needs to be implimed"); throw Error("needs to be implimed");
} }
@ -142,6 +176,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
return; return;
} }
} }
await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id)); await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id));
} }
}); });
@ -171,10 +206,10 @@ export class CoreHttpController<V> implements ICoreHttpController {
router: this.router, router: this.router,
}; };
} }
public put(usecase: CallbackStrategyWithValidationModel<V>) { public put(usecase: any) {
this.routes["PUT"] = usecase; this.routes["PUT"] = usecase;
} }
public delete(usecase: CallbackStrategyWithValidationModel<V>) { public delete(usecase: any) {
this.routes["DELETE"] = usecase; this.routes["DELETE"] = usecase;
} }
public async requestResponseController<T>( public async requestResponseController<T>(
@ -191,7 +226,6 @@ export class CoreHttpController<V> implements ICoreHttpController {
if (req.query.page !== undefined) { if (req.query.page !== undefined) {
payload = String(req.query.page); payload = String(req.query.page);
} }
if (req.query.id !== undefined) { if (req.query.id !== undefined) {
payload = String(req.query.id); payload = String(req.query.id);
} }

View file

@ -1,9 +1,29 @@
import { BehaviorTreesPresentation } from "../../features/behavior_trees/behavior_trees_presentation";
import { DatasetsPresentation } from "../../features/datasets/datasets_presentation"; import { DatasetsPresentation } from "../../features/datasets/datasets_presentation";
import { CalculationsTemplatePresentation } from "../../features/calculations_templates/calculations_template_presentation";
import { ProjectsPresentation } from "../../features/projects/projects_presentation"; import { ProjectsPresentation } from "../../features/projects/projects_presentation";
// import { ProjectsPresentation } from "../../features/_projects/projects_presentation";
import { extensions } from "../extensions/extensions"; import { extensions } from "../extensions/extensions";
import { Routes } from "../interfaces/router"; import { Routes } from "../interfaces/router";
import { ScenesPresentation } from "../../features/scenes/scenes_presentation";
import { CalculationsInstancesPresentation } from "../../features/calculations_instance/calculations_instance_presentation";
import { DigitalTwinsInstancePresentation } from "../../features/digital_twins_instance/digital_twins_instance_presentation";
import { DigitalTwinsTemplatePresentation } from "../../features/digital_twins_template/digital_twins_template_presentation";
import { TopicsPresentation } from "../../features/topics/topics_presentation";
import { SkillsPresentation } from "../../features/skills/skill_presentation";
import { RunTimePresentation } from "../../features/runtime/runtime_presentation";
extensions(); extensions();
export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation()].map((el) => el.call()); export const httpRoutes: Routes[] = [
new ProjectsPresentation(),
new DatasetsPresentation(),
new ScenesPresentation(),
new BehaviorTreesPresentation(),
new CalculationsTemplatePresentation(),
new CalculationsInstancesPresentation(),
new DigitalTwinsTemplatePresentation(),
new DigitalTwinsInstancePresentation(),
new TopicsPresentation(),
new SkillsPresentation(),
new RunTimePresentation(),
].map((el) => el.call());

View file

@ -1,44 +0,0 @@
// import { Service } from "typedi";
// @Service()
// export class IEnv{
// rootFolder!: string;
// constructor(){
// }
// toStringEnv(){
// return ''
// }
// static env(){
// return ''
// }
// }
// @Service()
// export class DevEnv implements IEnv {
// rootFolder:string;
// constructor(rootFolder:string){
// this.rootFolder = rootFolder
// }
// toStringEnv(): string {
// return DevEnv.env()
// }
// static env(){
// return 'DevEnv'
// }
// }
// @Service()
// export class UnitTestEnv implements IEnv{
// rootFolder:string;
// constructor(rootFolder:string){
// this.rootFolder = rootFolder
// }
// toStringEnv(): string {
// return UnitTestEnv.env()
// }
// static env(){
// return 'UnitTestEnv'
// }
// }

View file

@ -1,53 +0,0 @@
// import { DevEnv, IEnv, UnitTestEnv } from "./env";
// import { extensions } from "../extensions/extensions";
// // import { Container, Service } from 'typedi';
// export default function locator(env: IEnv) {
// extensions();
// envRegister(env);
// registerRepository(env);
// registerController(env);
// registerService(env);
// // override(MetaDataFileManagerModel, MetaDataFileManagerModel);
// }
// const envRegister = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// // override(IEnv, UnitTestEnv);
// return;
// case "DevEnv":
// // override(IEnv, DevEnv);
// return;
// }
// };
// const registerRepository = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// // override(IEnv, UnitTestEnv);
// return;
// case DevEnv.env():
// // override(IEnv, DevEnv);
// return;
// }
// };
// const registerController = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// return;
// case DevEnv.env():
// return;
// }
// };
// const registerService = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// return;
// case DevEnv.env():
// return;
// }
// };

View file

@ -6,7 +6,6 @@ export const ArrayExtensions = () => {
}; };
} }
if ([].equals === undefined) { if ([].equals === undefined) {
// eslint-disable-next-line no-extend-native
Array.prototype.equals = function (array, strict = true) { Array.prototype.equals = function (array, strict = true) {
if (!array) return false; if (!array) return false;
@ -27,7 +26,6 @@ export const ArrayExtensions = () => {
}; };
} }
if ([].lastElement === undefined) { if ([].lastElement === undefined) {
// eslint-disable-next-line no-extend-native
Array.prototype.lastElement = function () { Array.prototype.lastElement = function () {
const instanceCheck = this; const instanceCheck = this;
if (instanceCheck === undefined) { if (instanceCheck === undefined) {
@ -39,7 +37,6 @@ export const ArrayExtensions = () => {
}; };
} }
if ([].isEmpty === undefined) { if ([].isEmpty === undefined) {
// eslint-disable-next-line no-extend-native
Array.prototype.isEmpty = function () { Array.prototype.isEmpty = function () {
return this.length === 0; return this.length === 0;
}; };

View file

@ -21,6 +21,8 @@ declare global {
hasPattern(pattern: string): boolean; hasPattern(pattern: string): boolean;
hasNoPattern(pattern: string): boolean; hasNoPattern(pattern: string): boolean;
pathNormalize(): string; pathNormalize(): string;
isEqual(str: string): boolean;
isEqualMany(str: string[]): boolean;
} }
} }
export const extensions = () => { export const extensions = () => {

View file

@ -1,6 +1,5 @@
export const StringExtensions = () => { export const StringExtensions = () => {
if ("".isEmpty === undefined) { if ("".isEmpty === undefined) {
// eslint-disable-next-line no-extend-native
String.prototype.isEmpty = function () { String.prototype.isEmpty = function () {
return this.length === 0; return this.length === 0;
}; };
@ -11,7 +10,6 @@ export const StringExtensions = () => {
}; };
} }
if ("".isNotEmpty === undefined) { if ("".isNotEmpty === undefined) {
// eslint-disable-next-line no-extend-native
String.prototype.isNotEmpty = function () { String.prototype.isNotEmpty = function () {
return this.length !== 0; return this.length !== 0;
}; };
@ -31,4 +29,19 @@ export const StringExtensions = () => {
return !this.hasPattern(pattern); return !this.hasPattern(pattern);
}; };
} }
if ("".isEqual === undefined) {
String.prototype.isEqual = function (str: string) {
return this === str;
};
}
if ("".isEqualMany === undefined) {
String.prototype.isEqualMany = function (str: string[]) {
for (const el of str) {
if (el === this) {
return true;
}
}
return false;
};
}
}; };

View file

@ -10,11 +10,13 @@ export const validationModelMiddleware = (
forbidNonWhitelisted = true forbidNonWhitelisted = true
): RequestHandler => { ): RequestHandler => {
return (req, res, next) => { return (req, res, next) => {
if (type === null && type == undefined) { if (type === null && type == undefined) {
next(); next();
return; return;
} }
const model = plainToInstance(type, req[value]); const model = plainToInstance(type, req[value]);
validate(model, { skipMissingProperties, whitelist, forbidNonWhitelisted }).then((errors: ValidationError[]) => { validate(model, { skipMissingProperties, whitelist, forbidNonWhitelisted }).then((errors: ValidationError[]) => {
if (errors.length > 0) { if (errors.length > 0) {
const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(", "); const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(", ");

View file

@ -0,0 +1,5 @@
export interface Instance {
instanceName: string;
path: string;
instancePath: string;
}

View file

@ -1,6 +1,6 @@
import { Trigger } from "../../features/_triggers/models/trigger_database_model";
import { EXEC_TYPE } from "./exec_error_model"; import { EXEC_TYPE } from "./exec_error_model";
export interface Trigger {}
export interface IPipeline { export interface IPipeline {
process: IProcess; process: IProcess;
trigger?: Trigger; trigger?: Trigger;

View file

@ -21,3 +21,4 @@ export class RobossemblerAssets {
return this; return this;
} }
} }

View file

@ -0,0 +1,189 @@
import { IsArray, IsEnum, IsNotEmpty, IsString, ValidateNested } from "class-validator";
import { Type } from "class-transformer";
export class TopicViewModel {
@IsNotEmpty()
@IsString()
name: string;
@IsNotEmpty()
@IsString()
type: string;
constructor(name: string, type: string) {
this.name = name;
this.type = type;
}
static empty() {
return new TopicViewModel("", "");
}
}
export interface IParam {
type: string;
dependency: Object;
}
export interface Skill {
SkillPackage: ISkillPackage;
Module: IModule;
Launch: ILaunch;
ROS2: IRos2;
BTAction: IBTAction[];
Interface: IInterface;
Settings: ISetting[];
xxx: IXxx;
}
export interface IBTAction {
name: string;
format: string;
type: string;
param: IParam[];
result: string[];
}
export interface IInterface {
Input: IPut[];
Output: IPut[];
}
export interface IPut {
name: string;
type: string;
}
export interface ILaunch {
executable: string;
}
export interface IModule {
name: string;
description: string;
}
export interface IRos2 {
node_name: string;
}
export interface ISetting {
name: string;
value: number | string;
}
export interface ISkillPackage {
name: string;
version: string;
format: string;
}
export interface IXxx {
cameraLink: string;
topicImage: string;
topicCameraInfo: string;
}
export class SkillPackage implements ISkillPackage {
@IsString()
name: string;
@IsString()
version: string;
@IsString()
format: string;
}
export class Module implements IModule {
@IsString()
name: string;
@IsString()
description: string;
}
export class BTAction implements IBTAction {
@IsString()
name: string;
@IsString()
format: string;
@IsString()
type: string;
@IsArray()
param: IParam[];
@IsArray()
result: string[];
}
export class Launch implements ILaunch {
@IsString()
executable: string;
}
export class Ros2 implements IRos2 {
@IsString()
node_name: string;
}
export class Put implements IPut {
@IsString()
name: string;
@IsString()
type: string;
}
export class Interface implements IInterface {
@ValidateNested()
@Type(() => Put)
Input: IPut[];
@ValidateNested()
@Type(() => Put)
Output: IPut[];
}
export class Setting implements ISetting {
name: string;
value: string | number;
}
export class Xxx implements IXxx {
cameraLink: string;
topicImage: string;
topicCameraInfo: string;
}
export class SkillModel implements Skill {
@ValidateNested()
@Type(() => SkillPackage)
SkillPackage: ISkillPackage;
@ValidateNested()
@Type(() => Module)
Module: IModule;
@ValidateNested()
@Type(() => Launch)
Launch: ILaunch;
@ValidateNested()
@Type(() => Ros2)
ROS2: IRos2;
@ValidateNested()
@IsArray()
@Type(() => BTAction)
BTAction: IBTAction[];
@ValidateNested()
@Type(() => Interface)
Interface: IInterface;
@ValidateNested()
@IsArray()
@Type(() => Setting)
Settings: ISetting[];
@ValidateNested()
@Type(() => Xxx)
xxx: IXxx;
}
export enum BtAction {
ACTION = "ACTION",
CONDITION = "CONDITION",
}
export class BtActionViewModel implements IBTAction {
@IsNotEmpty()
@IsString()
name: string;
@IsNotEmpty()
@IsString()
format: string;
@IsNotEmpty()
@IsString()
type: string;
param: IParam[];
@IsNotEmpty()
@IsString()
result: string[];
@IsNotEmpty()
@IsEnum(BtAction)
typeAction: BtAction;
}

View file

@ -1,4 +1,13 @@
export enum StaticFiles { export enum StaticFilesProject {
robossembler_assets = "robossembler_assets.json", robossembler_assets = "robossembler_assets.json",
assets = "/assets/assets.json", assets = "/assets/assets.json",
parts = "/assets/parts.json",
scenes = "/scenes/",
behaviorTrees = "behavior_trees",
robots = 'robots'
}
export enum StaticFilesServer {
process = "/process/",
digitalTwins = "/digital_twins/",
} }

View file

@ -1,6 +1,6 @@
import * as fs from "fs"; import * as fs from "fs";
import { promisify } from "node:util"; import { promisify } from "node:util";
import { rimraf } from 'rimraf' import { rimraf } from "rimraf";
export class FileSystemRepository { export class FileSystemRepository {
public createDir = promisify(fs.mkdir); public createDir = promisify(fs.mkdir);
@ -8,6 +8,7 @@ export class FileSystemRepository {
public writeFileAsync = promisify(fs.writeFile); public writeFileAsync = promisify(fs.writeFile);
public dirIsExists = promisify(fs.exists); public dirIsExists = promisify(fs.exists);
public stat = promisify(fs.stat); public stat = promisify(fs.stat);
public deleteDir = promisify(fs.unlink);
public readFileAsync = promisify(fs.readFile); public readFileAsync = promisify(fs.readFile);
public readdir = promisify(fs.readdir); public readdir = promisify(fs.readdir);
public deleteDirRecursive = rimraf; public deleteDirRecursive = rimraf;
@ -21,7 +22,9 @@ export class FileSystemRepository {
} }
return await this.readFileAsync(path); return await this.readFileAsync(path);
} }
delete = async (path: string) => {
return await this.deleteDir(path);
};
readDirRecursive(path: string, filesToDir: string[] = []): string[] { readDirRecursive(path: string, filesToDir: string[] = []): string[] {
const files = fs.readdirSync(path); const files = fs.readdirSync(path);
files.forEach((file) => { files.forEach((file) => {
@ -41,5 +44,4 @@ export class FileSystemRepository {
}); });
return filesToDir; return filesToDir;
} }
} }

View file

@ -0,0 +1,17 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../controllers/http_controller";
import { Instance } from "../models/instance";
import { CreateDataBaseModelUseCase } from "../usecases/create_database_model_usecase";
import { CreateFolderUseCase } from "../usecases/create_folder_usecase";
export abstract class CreateInstanceScenario<V extends Instance> extends CallbackStrategyWithValidationModel<V> {
abstract validationModel: V;
abstract databaseModel: any;
call = async (model: V): ResponseBase => {
model.instancePath = `${model.path}/${model.instanceName}`;
console.log("INSTANCE PATh");
console.log(model.instancePath)
return (await new CreateFolderUseCase().call(model.instancePath)).map(
async () => await new CreateDataBaseModelUseCase(this.databaseModel).call(model)
);
};
}

View file

@ -0,0 +1,16 @@
import { Result } from "../helpers/result";
import { CreateFolderUseCase } from "../usecases/create_folder_usecase";
export class CreateManyFolderScenario {
call = async (path: string, foldersNames: string[]): Promise<Result<Error, string>> => {
try {
foldersNames.forEach(async (folder) => {
await new CreateFolderUseCase().call(`${path}${folder}`.normalize());
});
return Result.ok("many folder created");
} catch (error) {
return Result.error(new Error(error));
}
};
}

View file

@ -0,0 +1,22 @@
import { App } from "../controllers/app";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../controllers/http_controller";
import { StaticFilesServer } from "../models/static_files";
import { CreateDataBaseModelUseCase } from "../usecases/create_database_model_usecase";
import { CreateFolderUseCase } from "../usecases/create_folder_usecase";
interface IModel {
path: string;
name: string;
}
export abstract class CreateTemplateScenario<V extends IModel> extends CallbackStrategyWithValidationModel<V> {
validationModel: V;
abstract databaseModel: any;
abstract path: string;
call = async (model: V): ResponseBase => {
model.path = App.staticFilesStoreDir() + StaticFilesServer.process + model.name;
return (await new CreateFolderUseCase().call(model.path)).map(() => {
return new CreateDataBaseModelUseCase(this.databaseModel).call(model);
});
};
}

View file

@ -0,0 +1,20 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../controllers/http_controller";
import { Instance } from "../models/instance";
import { DeleteDataBaseModelUseCase } from "../usecases/delete_database_model_usecase";
import { DeleteRecursiveFolderUseCase } from "../usecases/delete_recursive_folder_usecase";
import { ReadByIdDataBaseModelUseCase } from "../usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../validations/core_validation";
import { MongoIdValidation } from "../validations/mongo_id_validation";
export abstract class DeleteInstanceScenario<D extends Instance> extends CallbackStrategyWithIdQuery {
abstract databaseModel: any;
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<D>(this.databaseModel).call(id)).map(async (model) => {
return (await new DeleteRecursiveFolderUseCase().call(model.instancePath)).map(
async () => await new DeleteDataBaseModelUseCase(this.databaseModel).call(id)
);
});
}

View file

@ -0,0 +1,20 @@
import { CalculationsTemplateValidationModel } from "../../features/calculations_templates/models/calculations_template_validation_model";
import { CallbackStrategyWithIdQuery, ResponseBase } from "../controllers/http_controller";
import { DeleteDataBaseModelUseCase } from "../usecases/delete_database_model_usecase";
import { DeleteRecursiveFolderUseCase } from "../usecases/delete_recursive_folder_usecase";
import { ReadByIdDataBaseModelUseCase } from "../usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../validations/core_validation";
import { MongoIdValidation } from "../validations/mongo_id_validation";
export abstract class DeleteTemplateScenario extends CallbackStrategyWithIdQuery {
abstract databaseModel: any;
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<CalculationsTemplateValidationModel>(this.databaseModel).call(id)).map(
async (model) => {
return (await new DeleteRecursiveFolderUseCase().call(model.path)).map(
async () => await new DeleteDataBaseModelUseCase(this.databaseModel).call(id)
);
}
);
}

View file

@ -0,0 +1,22 @@
import { CallbackStrategyWithIdQuery } from "../controllers/http_controller";
import { Result } from "../helpers/result";
import { ReadByIdDataBaseModelUseCase } from "../usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../validations/core_validation";
import { MongoIdValidation } from "../validations/mongo_id_validation";
export class ReadByIdDataBaseModelScenario<D> extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
databaseModel: D;
constructor(model) {
super();
this.databaseModel = model;
}
call = async (id: string): Promise<Result<Error, D>> => {
try {
return new ReadByIdDataBaseModelUseCase<D>(this.databaseModel).call(id);
} catch (error) {
return Result.error(error);
}
};
}

View file

@ -1,28 +1,26 @@
import {
IProjectInstanceModel,
ProjectInstanceDbModel, import { IProjectModel, ProjectDBModel } from "../../features/projects/models/project_model_database_model";
} from "../../features/projects/models/project_instance_database_model";
import { pipelineRealTimeService } from "../../features/_realtime/realtime_presentation";
import { App } from "../controllers/app"; import { App } from "../controllers/app";
import { PipelineRealTimeService } from "../services/pipeline_real_time_service";
import { CreateFolderUseCase } from "../usecases/create_folder_usecase"; import { CreateFolderUseCase } from "../usecases/create_folder_usecase";
import { SearchDataBaseModelUseCase } from "../usecases/search_database_model_usecase"; import { SearchOneDataBaseModelUseCase } from "../usecases/search_database_model_usecase";
export const pipelineRealTimeService = new PipelineRealTimeService();
export class SetLastActivePipelineToRealTimeServiceScenario { export class SetLastActivePipelineToRealTimeServiceScenario {
call = async (): Promise<void> => { call = async (): Promise<void> => {
return ( return (
await new SearchDataBaseModelUseCase<IProjectInstanceModel>(ProjectInstanceDbModel).call({ await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({
isActive: true, isActive: true,
}) })
).fold( ).fold(
async (projectModel) => { async (projectModel) => {
if (projectModel.project === null) {
return;
}
const projectPath = App.staticFilesStoreDir() + projectModel.rootDir + "/"; const projectPath = App.staticFilesStoreDir() + projectModel.rootDir + "/";
await new CreateFolderUseCase().call(projectPath); await new CreateFolderUseCase().call(projectPath);
pipelineRealTimeService.setPipelineDependency( pipelineRealTimeService.setPipelineDependency(
projectModel.project.pipelines,
projectPath, projectPath,
projectModel._id, projectModel._id,
projectModel.rootDir projectModel.rootDir

View file

@ -50,6 +50,7 @@ export class ExecutorProgramService
}; };
worker.send(workerDataExec); worker.send(workerDataExec);
worker.on("message", (e) => { worker.on("message", (e) => {
console.log(JSON.stringify(e));
const spawnError = SpawnError.isError(e); const spawnError = SpawnError.isError(e);
if (spawnError instanceof SpawnError) { if (spawnError instanceof SpawnError) {
@ -60,7 +61,7 @@ export class ExecutorProgramService
const execError = ExecError.isExecError(e); const execError = ExecError.isExecError(e);
if (execError instanceof ExecError) { if (execError instanceof ExecError) {
execError.id = id execError.id = id;
this.emit(Result.error(execError)); this.emit(Result.error(execError));
this.worker = undefined; this.worker = undefined;
return; return;
@ -68,7 +69,7 @@ export class ExecutorProgramService
const executorResult = ExecutorResult.isExecutorResult(e); const executorResult = ExecutorResult.isExecutorResult(e);
if (executorResult instanceof ExecutorResult) { if (executorResult instanceof ExecutorResult) {
executorResult.id = id executorResult.id = id;
this.emit(Result.ok(executorResult)); this.emit(Result.ok(executorResult));
this.worker = undefined; this.worker = undefined;
return; return;
@ -103,7 +104,8 @@ export class ExecutorProgramService
return; return;
} }
this.workerExecuted(command, WorkerType.SPAWN, args, id); const commands = command.split(" ");
this.workerExecuted(commands.at(0), WorkerType.SPAWN, commands.slice(1, commands.length), id);
return; return;
} }

View file

@ -58,9 +58,8 @@ export class PipelineRealTimeService extends TypedEvent<ActivePipeline> {
this.status.pipelineIsRunning = false; this.status.pipelineIsRunning = false;
} }
} }
setPipelineDependency(pipelineModels: IPipeline[], path: string, projectId: string, rootDir: string) { setPipelineDependency(path: string, projectId: string, rootDir: string) {
this.pipelineModels = pipelineModels; this.status["projectId"] = projectId;
this.status["projectId"] = projectId;
this.status["path"] = path; this.status["path"] = path;
this.status["rootDir"] = rootDir; this.status["rootDir"] = rootDir;
} }

View file

@ -1,5 +1,5 @@
import { FilesChangeNotifierService, IHashesCache } from "./files_change_notifier_service"; import { FilesChangeNotifierService, IHashesCache } from "./files_change_notifier_service";
import { IPipeline } from "../models/process_model"; import { IPipeline, Trigger } from "../models/process_model";
import { ExecutorProgramService } from "./executor_program_service"; import { ExecutorProgramService } from "./executor_program_service";
import { EXEC_EVENT, ExecError, SpawnError } from "../models/exec_error_model"; import { EXEC_EVENT, ExecError, SpawnError } from "../models/exec_error_model";
import { TypedEvent } from "../helpers/typed_event"; import { TypedEvent } from "../helpers/typed_event";
@ -7,7 +7,6 @@ import { Result } from "../helpers/result";
import { ExecutorResult } from "../models/executor_result"; import { ExecutorResult } from "../models/executor_result";
import { delay } from "../helpers/delay"; import { delay } from "../helpers/delay";
import { TriggerService } from "./trigger_service"; import { TriggerService } from "./trigger_service";
import { Trigger } from "../../features/_triggers/models/trigger_database_model";
export interface Iteration { export interface Iteration {
hashes: IHashesCache | null; hashes: IHashesCache | null;

View file

@ -1,9 +1,10 @@
// @ts-nocheck
import * as vm from "node:vm"; import * as vm from "node:vm";
import { IHashesCache } from "./files_change_notifier_service"; import { IHashesCache } from "./files_change_notifier_service";
import { EventsFileChanger } from "../models/meta_data_file_manager_model"; import { EventsFileChanger } from "../models/meta_data_file_manager_model";
import { Result } from "../helpers/result"; import { Result } from "../helpers/result";
import { TypedEvent } from "../helpers/typed_event"; import { TypedEvent } from "../helpers/typed_event";
import { Trigger, TriggerType } from "../../features/_triggers/models/trigger_database_model"; import { Trigger } from "../models/process_model";
export class TriggerCallResult { export class TriggerCallResult {
results: Array<TriggerSuccessResult | TriggerErrorReport>; results: Array<TriggerSuccessResult | TriggerErrorReport>;

View file

@ -1,24 +1,19 @@
import { App } from "../controllers/app"; import { App } from "../controllers/app";
import { StaticFilesServer } from "../models/static_files";
import { FileSystemRepository } from "../repository/file_system_repository"; import { FileSystemRepository } from "../repository/file_system_repository";
import { CreateFolderUseCase } from "./create_folder_usecase"; import { CreateFolderUseCase } from "./create_folder_usecase";
export class CheckAndCreateStaticFilesFolderUseCase { export class CheckAndCreateStaticFilesFolderUseCase {
fileSystemRepository: FileSystemRepository; fileSystemRepository: FileSystemRepository = new FileSystemRepository();
constructor() {
this.fileSystemRepository = new FileSystemRepository();
}
call = async (): Promise<void> => { call = async (): Promise<void> => {
Object.keys(StaticFilesServer).forEach(async (key) => {
if (!(await this.fileSystemRepository.dirIsExists(App.staticFilesStoreDir() + key))) {
await new CreateFolderUseCase().call(App.staticFilesStoreDir() + key);
}
});
if (await this.fileSystemRepository.dirIsExists(App.staticFilesStoreDir())) { if (await this.fileSystemRepository.dirIsExists(App.staticFilesStoreDir())) {
return; return;
} }
const createFolderUseCase = await new CreateFolderUseCase().call(App.staticFilesStoreDir()); await new CreateFolderUseCase().call(App.staticFilesStoreDir());
createFolderUseCase.fold(
(_s) => {},
(e) => {
console.log(e);
}
);
}; };
} }

View file

@ -0,0 +1,14 @@
import { Result } from "../helpers/result";
import { FileSystemRepository } from "../repository/file_system_repository";
export class DeleteFileUseCase {
fileSystemRepository = new FileSystemRepository();
call = (path: string) => {
try {
this.fileSystemRepository.delete(path);
return Result.ok("file delete");
} catch {
return Result.error("Unknown error");
}
};
}

View file

@ -4,7 +4,6 @@ import { FileSystemRepository } from "../repository/file_system_repository";
export class DeleteRecursiveFolderUseCase{ export class DeleteRecursiveFolderUseCase{
repository:FileSystemRepository = new FileSystemRepository() repository:FileSystemRepository = new FileSystemRepository()
call = async (path:string):Promise<Result<void,void>> =>{ call = async (path:string):Promise<Result<void,void>> =>{
console.log(path)
await this.repository.deleteDirRecursive(path) await this.repository.deleteDirRecursive(path)
return Result.ok() return Result.ok()
} }

View file

@ -1,7 +1,8 @@
import * as cp from "child_process";
import { CallbackStrategyWithEmpty } from "../controllers/http_controller"; import { CallbackStrategyWithEmpty } from "../controllers/http_controller";
import { Result } from "../helpers/result"; import { Result } from "../helpers/result";
import { TypedEvent } from "../helpers/typed_event"; import { TypedEvent } from "../helpers/typed_event";
import { EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model"; import { EXEC_EVENT, EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
import { ExecutorResult } from "../models/executor_result"; import { ExecutorResult } from "../models/executor_result";
import { ExecutorProgramService } from "../services/executor_program_service"; import { ExecutorProgramService } from "../services/executor_program_service";
@ -26,7 +27,7 @@ export class ExecProcessUseCase {
call = async ( call = async (
path: string, path: string,
command: string, command: string,
id:string, id: string,
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
): Promise<Result<Error, string>> => { ): Promise<Result<Error, string>> => {
try { try {
@ -34,7 +35,7 @@ export class ExecProcessUseCase {
executorProgramService.on((event) => { executorProgramService.on((event) => {
if (watcher) watcher.emit(event); if (watcher) watcher.emit(event);
}); });
executorProgramService.call(EXEC_TYPE.EXEC, command, undefined ,id); executorProgramService.call(EXEC_TYPE.EXEC, command, undefined, id);
return Result.ok("ok"); return Result.ok("ok");
} catch (error) { } catch (error) {
@ -42,3 +43,39 @@ export class ExecProcessUseCase {
} }
}; };
} }
export class SpawnProcessUseCase {
call = async (
path: string,
command: string,
id: string,
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
): Promise<Result<Error, string>> => {
try {
const commands = command.split(" ");
const subprocess = cp.spawn(commands.at(0), commands.slice(1, commands.length), {
cwd: path,
});
const sendWatcher = (event: Buffer) => {
if (watcher) {
watcher.emit(Result.ok(new ExecutorResult(EXEC_TYPE.SPAWN, EXEC_EVENT.PROGRESS, event.toString())));
}
};
subprocess.stdout.on("data", (data) => sendWatcher(data));
subprocess.stderr.on("data", (data) => sendWatcher(data));
subprocess.on("error", (error) => {
console.error(`Ошибка: ${error.message}`);
});
subprocess.on("close", (code) => {
console.log(`Процесс завершился с кодом: ${code}`);
});
return Result.ok('ok');
} catch (error) {
return Result.error(error);
}
};
}

View file

@ -2,11 +2,9 @@ import { Result } from "../helpers/result";
import { FileSystemRepository } from "../repository/file_system_repository"; import { FileSystemRepository } from "../repository/file_system_repository";
export class ReadFileAndParseJsonUseCase { export class ReadFileAndParseJsonUseCase {
fileSystemRepository: FileSystemRepository; fileSystemRepository: FileSystemRepository = new FileSystemRepository();
constructor() {
this.fileSystemRepository = new FileSystemRepository();
}
async call<T>(path: string): Promise<Result<string, T>> { async call<T>(path: string): Promise<Result<string, T>> {
try { try {
if (RegExp(path).test("^(.+)/([^/]+)$")) { if (RegExp(path).test("^(.+)/([^/]+)$")) {

View file

@ -1,6 +1,6 @@
import { Result } from "../helpers/result"; import { Result } from "../helpers/result";
export class SearchDataBaseModelUseCase<T> { export class SearchOneDataBaseModelUseCase<T> {
model: any; model: any;
constructor(model: any) { constructor(model: any) {

View file

@ -0,0 +1,18 @@
import { Result } from "../helpers/result";
export class SearchManyDataBaseModelUseCase<T> {
model: any;
constructor(model: any) {
this.model = model;
}
call = async (findFilter: Partial<T>, error: string = "not found database"): Promise<Result<string, T>> => {
const result = await this.model.find(findFilter);
if (result === null) {
return Result.error(error);
} else {
return Result.ok(result);
}
};
}

View file

@ -1,58 +0,0 @@
import { CallbackStrategyWithEmpty, CoreHttpController } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { EXEC_TYPE } from "../../core/models/exec_error_model";
import { ExecutorResult } from "../../core/models/executor_result";
import { IPipeline, IssueType, StackGenerateType } from "../../core/models/process_model";
import { StackService } from "../../core/services/stack_service";
import { TriggerType } from "../_triggers/models/trigger_database_model";
class NixStoreModel {}
const getNixStoreFolderCommand: IPipeline[] = [
{
process: {
type: EXEC_TYPE.EXEC,
command: `ls /nix/store`,
isGenerating: true,
isLocaleCode: false,
issueType: IssueType.WARNING,
},
trigger: {
type: TriggerType.FILE,
value: ["context"],
},
env: null,
stackGenerateType: StackGenerateType.SINGLETON,
},
];
class GetNixStorePackagesUseCase extends CallbackStrategyWithEmpty {
call = async () => {
const stackService = new StackService(
getNixStoreFolderCommand,
"/Users/idontsudo/Desktop/testdeck-mocha-seed/server/build/test/"
);
stackService.call();
const promise = new Promise((resolve, _reject) => {
stackService.on((e) => {
const iteration = e.firstElement();
if (iteration.result instanceof ExecutorResult) {
const nixPackage = iteration.result.data;
resolve(nixPackage.split("\n").filter((e) => e.hasNoPattern(".drv")));
} else {
return "GetNixStorePackagesUseCase unknown Error";
}
});
});
return Result.ok(await promise);
};
}
export class NixStoreManagerPresentation extends CoreHttpController<NixStoreModel> {
constructor() {
super({
url: "nix_store_api",
});
super.get(new GetNixStorePackagesUseCase().call);
}
}

View file

@ -1,27 +0,0 @@
import { Schema, model } from "mongoose";
import { IPipeline } from "../../../core/models/process_model";
import { schemaProcess } from "../../_process/models/process_database_model";
import { triggerSchema } from "../../_triggers/models/trigger_database_model";
export const PipelineSchema = new Schema({
process: {
type: Schema.Types.ObjectId,
ref: schemaProcess,
autopopulate: true,
default: null,
},
trigger: {
type: Schema.Types.ObjectId,
ref: triggerSchema,
autopopulate: true,
default: null,
},
stackGenerateType: {
type: String,
default: null,
},
}).plugin(require("mongoose-autopopulate"));
export const schemaPipeline = "Pipeline";
export const PipelineDBModel = model<IPipeline>(schemaPipeline, PipelineSchema);

View file

@ -1,21 +0,0 @@
import { IsOptional, ValidateNested } from "class-validator";
import { IPipeline, IProcess, StackGenerateType } from "../../../core/models/process_model";
import { Type } from "class-transformer";
import { ProcessModel } from "../../_process/models/process_validation_model";
import { TriggerModelValidationModel } from "../../_triggers/models/trigger_validation_model";
export class PipelineModel implements IPipeline {
@ValidateNested()
@Type(() => ProcessModel)
public process: IProcess;
@ValidateNested()
@Type(() => TriggerModelValidationModel)
public trigger: TriggerModelValidationModel;
@IsOptional()
public env = null;
@IsOptional()
public stackGenerateType: StackGenerateType;
}

View file

@ -1,17 +0,0 @@
import { IsMongoId, IsOptional } from "class-validator";
import { IProcess, StackGenerateType } from "../../../core/models/process_model";
import { TriggerModelValidationModel } from "../../_triggers/models/trigger_validation_model";
export class PipelineValidationModel {
@IsMongoId()
public process: IProcess;
@IsMongoId()
public trigger: TriggerModelValidationModel;
@IsOptional()
public env = null;
@IsOptional()
public stackGenerateType: StackGenerateType;
}

View file

@ -1,13 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { PipelineDBModel } from "./models/pipeline_database_model";
import { PipelineValidationModel } from "./models/pipeline_validation_model";
export class PipelinePresentation extends CrudController<PipelineValidationModel, typeof PipelineDBModel> {
constructor() {
super({
url: "pipeline",
validationModel: PipelineValidationModel,
databaseModel: PipelineDBModel,
});
}
}

View file

@ -1,35 +0,0 @@
import { Schema, model } from "mongoose";
import { IProcess } from "../../../core/models/process_model";
export const ProcessSchema = new Schema({
type: {
type: String,
},
description: {
type: String,
},
command: {
type: String,
},
isGenerating: {
type: String,
},
isLocaleCode: {
type: String,
},
issueType: {
type: String,
},
timeout: {
type: Number,
default: null,
},
commit: {
type: String,
default: null,
},
});
export const schemaProcess = "Process";
export const ProcessDBModel = model<IProcess>(schemaProcess, ProcessSchema);

View file

@ -1,31 +0,0 @@
import { IsBoolean, IsEnum, IsNumber, IsOptional, IsString } from "class-validator";
import { EXEC_TYPE } from "../../../core/models/exec_error_model";
import { IProcess, IssueType } from "../../../core/models/process_model";
export class ProcessModel implements IProcess {
@IsEnum(EXEC_TYPE)
public type: EXEC_TYPE;
@IsString()
public description: string;
@IsString()
public command: string;
@IsBoolean()
public isGenerating: boolean;
@IsBoolean()
public isLocaleCode: boolean;
@IsEnum(IssueType)
public issueType: IssueType;
@IsOptional()
@IsNumber()
public timeout?: number;
@IsOptional()
@IsString()
public commit?: string;
}

View file

@ -1,13 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ProcessDBModel } from "./models/process_database_model";
import { ProcessModel } from "./models/process_validation_model";
export class ProcessPresentation extends CrudController<ProcessModel, typeof ProcessDBModel> {
constructor() {
super({
url: "process",
validationModel: ProcessModel,
databaseModel: ProcessDBModel,
});
}
}

View file

@ -1,9 +0,0 @@
import { IsArray, IsString } from "class-validator";
export class ProjectValidationModel {
@IsArray()
public pipelines: [string];
@IsString()
public description: string;
}

View file

@ -1,13 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ProjectDBModel } from "./models/project_database_model";
import { ProjectValidationModel } from "./models/project_validation_model";
export class ProjectsPresentation extends CrudController<ProjectValidationModel, typeof ProjectDBModel> {
constructor() {
super({
url: "project",
validationModel: ProjectValidationModel,
databaseModel: ProjectDBModel,
});
}
}

View file

@ -1,57 +0,0 @@
import { App } from "../../../core/controllers/app";
import { CallbackStrategyWithEmpty } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { IPipeline } from "../../../core/models/process_model";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { PipelineValidationModel } from "../../_pipelines/models/pipeline_validation_model";
import { IProjectInstanceModel, ProjectInstanceDbModel } from "../../projects/models/project_instance_database_model";
import { pipelineRealTimeService } from "../realtime_presentation";
import { PipelineStatusUseCase } from "./pipeline_status_usecase";
const mongoPipelineModelMapper = (el: PipelineValidationModel): IPipeline => {
const mapObj: IPipeline = {
process: {
type: el.process.type,
command: el.process.command,
isGenerating: Boolean(el.process.isGenerating),
isLocaleCode: Boolean(el.process.isLocaleCode),
issueType: el.process.issueType,
},
trigger: {
type: el.trigger.type,
value: el.trigger.value.map((el) => String(el)),
},
env: null,
stackGenerateType: el.stackGenerateType,
};
return mapObj;
};
export class RunInstancePipelineUseCase extends CallbackStrategyWithEmpty {
async call(): Promise<Result<any, string>> {
return (await new PipelineStatusUseCase().call()).map(async (activePipelineModel) => {
if (activePipelineModel.pipelineIsRunning) {
return Result.error("pipeline is running");
}
const readByIdDataBaseModelUseCase = await new ReadByIdDataBaseModelUseCase<IProjectInstanceModel>(
ProjectInstanceDbModel
).call(activePipelineModel.projectId);
if (readByIdDataBaseModelUseCase.isFailure()) {
return readByIdDataBaseModelUseCase.forward();
}
const projectModel = readByIdDataBaseModelUseCase.value;
const resultMapper = projectModel.project.pipelines.map((el) => mongoPipelineModelMapper(el));
pipelineRealTimeService.setPipelineDependency(
resultMapper,
App.staticFilesStoreDir() + projectModel.rootDir + "/",
projectModel._id,
projectModel.rootDir
);
pipelineRealTimeService.runPipeline();
return Result.ok("ok");
});
}
}

View file

@ -1,28 +0,0 @@
import { IsString } from "class-validator";
import { CoreHttpController } from "../../core/controllers/http_controller";
import { PipelineRealTimeService } from "../../core/services/pipeline_real_time_service";
import { RunInstancePipelineUseCase } from "./domain/run_instance_pipeline_usecase";
import { PipelineStatusUseCase } from "./domain/pipeline_status_usecase";
export const pipelineRealTimeService = new PipelineRealTimeService();
export class RealTimeValidationModel {
@IsString()
public id: string;
}
export class RealTimePresentation extends CoreHttpController<RealTimeValidationModel> {
constructor() {
super({
validationModel: RealTimeValidationModel,
url: "realtime",
databaseModel: null,
});
super.get(new PipelineStatusUseCase().call);
this.subRoutes.push({
method: "POST",
subUrl: "run",
fn: new RunInstancePipelineUseCase(),
});
}
}

View file

@ -1,36 +0,0 @@
import { Schema, model } from "mongoose";
export interface ITriggerModel {
_id?: string;
type: string;
description: string;
value: string[];
}
export const TriggerSchema = new Schema({
type: {
type: String,
require: true,
},
description: {
type: String,
},
value: {
type: Array,
require: true,
},
});
export const triggerSchema = "Trigger";
export const TriggerDBModel = model<ITriggerModel>(triggerSchema, TriggerSchema);
export enum TriggerType {
PROCESS = "PROCESS",
FILE = "FILE",
}
export interface Trigger {
type: TriggerType;
value: string[];
}

View file

@ -1,16 +0,0 @@
import { IsArray, IsOptional, IsEnum, IsString } from "class-validator";
import { ITriggerModel, TriggerType } from "./trigger_database_model";
export class TriggerModelValidationModel implements ITriggerModel {
@IsOptional()
public _id: string;
@IsString()
public description;
@IsEnum(TriggerType)
public type: TriggerType;
@IsArray()
public value: string[];
}

View file

@ -1,13 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { TriggerDBModel } from "./models/trigger_database_model";
import { TriggerModelValidationModel } from "./models/trigger_validation_model";
export class TriggerPresentation extends CrudController<TriggerModelValidationModel, typeof TriggerDBModel> {
constructor() {
super({
url: "trigger",
validationModel: TriggerModelValidationModel,
databaseModel: TriggerDBModel,
});
}
}

View file

@ -0,0 +1,48 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { GetBehaviorTreeSkillsTemplatesUseCase } from "./domain/get_bt_skills_templates_usecase";
import { BehaviorTreeValidationModel } from "./models/behavior_tree_validation_model";
import { BehaviorTreeDBModel } from "./models/behavior_tree_database_model";
import { ReadByIdDataBaseModelScenario } from "../../core/scenarios/read_by_id_database_model_scenario";
import { GetBehaviorTreeActiveProjectScenario } from "./domain/get_behavior_tree_active_project_scenario";
import { SaveBtScenario as FillBtScenario } from "./domain/save_bt_scenario";
import { GetCameraUseCase } from "./domain/get_cameras_usecase";
import { GetRobotsUseCase } from "./domain/get_robots_usecase";
import { GetTopicsUseCase } from "./domain/get_topics_usecase";
export class BehaviorTreesPresentation extends CrudController<BehaviorTreeValidationModel, typeof BehaviorTreeDBModel> {
constructor() {
super({
url: "behavior/trees",
validationModel: BehaviorTreeValidationModel,
databaseModel: BehaviorTreeDBModel,
});
super.get(new GetBehaviorTreeActiveProjectScenario().call);
this.subRoutes.push({
method: "POST",
subUrl: "fill/tree",
fn: new FillBtScenario(),
});
this.subRoutes.push({ method: "GET", subUrl: "templates", fn: new GetBehaviorTreeSkillsTemplatesUseCase() });
this.subRoutes.push({
method: "GET",
subUrl: "by_id",
fn: new ReadByIdDataBaseModelScenario<BehaviorTreeValidationModel>(BehaviorTreeDBModel),
});
this.subRoutes.push({
method: "GET",
subUrl: "cameras",
fn: new GetCameraUseCase()
})
this.subRoutes.push({
method: "GET",
subUrl: "robots",
fn: new GetRobotsUseCase()
})
this.subRoutes.push({
method: "GET",
subUrl: "topics",
fn: new GetTopicsUseCase()
})
}
}

View file

@ -0,0 +1,15 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { BehaviorTreeDBModel } from "../models/behavior_tree_database_model";
export class GetBehaviorTreeActiveProjectScenario extends CallbackStrategyWithEmpty {
call = async (): ResponseBase =>
(
await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
{ isActive: true },
"no active projects"
)
).map(async (project) => Result.ok(await BehaviorTreeDBModel.find({ project: project._id })));
}

View file

@ -0,0 +1,102 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => {
return Result.ok({
skills: [
{
SkillPackage: { name: "Robossembler", version: "1.0", format: "1" },
Module: { name: "MoveToPose", description: "Move to Pose skill with cartesian controllers" },
Launch: { package: "rbss_movetopose", executable: "mtp_cartesian.py", name: "mtp_cartesian" },
BTAction: [
{
name: "move",
type: "action",
param: [
{
type: "move_to_pose",
dependency: {},
},
],
},
],
Interface: {
Input: [
{ name: "robotName", type: "ROBOT" },
{ name: "pose", type: "POSE" },
],
Output: [],
},
Settings: [
{ name: "topicServer", value: "cartesian_move_to_pose" },
{ name: "end_effector_velocity", value: 1.0 },
{ name: "end_effector_acceleration", value: 1.0 },
],
},
{
Module: { name: "MMM", description: "Move to Pose skill with cartesian controllers" },
topicOut: [
{
topicName: "",
topicType: "",
},
],
BTAction: [
{
name: "move",
type: "action",
param: [
{
type: "move_to_pose",
dependency: {},
},
],
},
],
},
{
SkillPackage: { name: "Robossembler", version: "1.0", format: "1", type: "Action" },
Module: { name: "PoseEstimation", description: "Pose Estimation skill with DOPE" },
Launch: { package: "rbs_perception", executable: "pe_dope_lc.py", name: "lc_dope" },
BTAction: [
{
name: "peConfigure",
type: "run",
param: [
{
type: "weights",
dependency: {},
},
{
type: "camera",
dependency: {},
},
{
type: "topic",
dependency: {},
},
],
result: ["POSE"],
},
{ name: "peStop", type: "stop", param: [], result: [] },
],
Interface: {
Input: [
{ name: "cameraLink", type: "CAMERA" },
{ name: "object_name", type: "MODEL" },
],
Output: [{ name: "pose_estimation_topic", type: "POSE" }],
},
Settings: [
{ name: "cameraLink", value: "inner_rgbd_camera" },
{ name: "pose", value: "" },
{ name: "publishDelay", value: 0.5 },
{ name: "tf2_send_pose", value: 1 },
{ name: "mesh_scale", value: 0.001 },
],
},
],
});
};
}

View file

@ -0,0 +1,120 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"
import { Result } from "../../../core/helpers/result"
export class GetCameraUseCase extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => {
return Result.ok({
"camera": [
{
"sid": "1",
"DevicePackage": {
"name": "Robossembler",
"version": "1.0",
"format": "1"
},
"Module": {
"name": "RealSense Dxx",
"description": "ROS Wrapper for Intel(R) RealSense(TM) Cameras"
},
"Launch": {
"package": "realsense2_camera",
"executable": "rs_launch.py"
},
"DTwin": [
{
"interface": {
"input": [
{
"camera_namespace": "robot1"
},
{
"camera_name": "455_1"
},
{
"serial_port": "USB_1"
},
{
"pose": "[0.0,0.0,0.0,0.0,0.0,0.0]"
}
]
}
}
],
"Interface": {
"param": [
{
"type": "camera",
"dependency": {}
}
]
},
"Settings": [
{
"name": "camera_config",
"description": "Camera Config",
"type": "file",
"defaultValue": "{ rgb_camera.profile: 1280x720x15 }"
}
]
},
{
"sid": "2",
"DevicePackage": {
"name": "Robossembler",
"version": "1.0",
"format": "1"
},
"Module": {
"name": "RealSense Dxx",
"description": "ROS Wrapper for Intel(R) RealSense(TM) Cameras"
},
"Launch": {
"package": "realsense2_camera",
"executable": "rs_launch.py"
},
"DTwin": [
{
"interface": {
"input": [
{
"camera_namespace": "robot1"
},
{
"camera_name": "455_1"
},
{
"serial_port": "USB_1"
},
{
"pose": "[0.0,0.0,0.0,0.0,0.0,0.0]"
}
]
}
}
],
"Interface": {
"param": [
{
"type": "camera",
"dependency": {}
}
]
},
"Settings": [
{
"name": "camera_config",
"description": "Camera Config",
"type": "file",
"defaultValue": "{ rgb_camera.profile: 1280x720x15 }"
}
]
}
]
})
}
}

View file

@ -0,0 +1,50 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
export class GetRobotsUseCase extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => {
return Result.ok({
"robots": [
{
"sid": "1",
"DevicePackage": {
"name": "Robossembler",
"version": "1.0",
"format": "1"
},
"Module": {
"name": "RBS",
"description": "Main Robot"
},
"Launch": {
"package": "rbs_bringup",
"executable": "single_robot.launch.py"
},
"DTwin": [
{
"interface": {
"input": [
{
"robot_namespace": "robot1"
},
{
"dof": 6
}
]
}
}
],
"Settings": [
{
"name": "robot_type",
"description": "Type of robot by name",
"defaultValue": "rbs_arm"
}
]
}
]
})
}
}

View file

@ -0,0 +1,23 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
export class GetTopicsUseCase extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => {
return Result.ok({
"topics": [
{
"sid": "1",
"name": "topic camera 1",
"type": "sensor_msgs/Image"
},
{
"sid": "2",
"name": "topic camera 2",
"type": "sensor_msgs/Image"
}
]
}
)
}
}

View file

@ -0,0 +1,32 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { FolderStructure } from "../../projects/domain/upload_file_to_to_project_scenario";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { BehaviorTreeValidationModel } from "../models/behavior_tree_validation_model";
export class SaveBtScenario extends CallbackStrategyWithValidationModel<BehaviorTreeValidationModel> {
validationModel: BehaviorTreeValidationModel = new BehaviorTreeValidationModel();
call = async (model: BehaviorTreeValidationModel): ResponseBase =>
(
await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
{ isActive: true },
"no active projects"
)
).map(async (project) => {
const folder = `${project.rootDir}/${FolderStructure.behaviorTrees}/`;
(await new CreateFolderUseCase().call(folder)).map(async () =>
(await new CreateFolderUseCase().call(`${folder}${model.name}/`)).map(async () =>
(await new CreateFileUseCase().call(`${folder}${model.name}/bt.xml`, Buffer.from(model.xml))).map(
async () =>
await new CreateFileUseCase().call(
`${folder}${model.name}/skills.json`,
Buffer.from(JSON.stringify(model.skills))
)
)
)
);
});
}

View file

@ -0,0 +1,49 @@
import { Schema, model } from "mongoose";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface IBehaviorTreeModel {
name: string;
project?: IProjectModel | string;
unixTime?: number;
local_path?: string;
}
export const BehaviorTreeSchema = new Schema({
name: {
type: String,
},
description: { type: String },
scene: {
type: Schema.Types.Mixed,
default: [],
},
local_path: {
type: String,
},
unixTime: {
type: Number,
},
isFinished: {
type: Boolean,
default: false,
},
dependency: {
type: Schema.Types.Mixed,
},
skills: {
type: Schema.Types.Mixed,
},
sceneId: {
type: String,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
}).plugin(require("mongoose-autopopulate"));
export const behaviorTreeSchema = "Behavior";
export const BehaviorTreeDBModel = model<IBehaviorTreeModel>(behaviorTreeSchema, BehaviorTreeSchema);

View file

@ -0,0 +1,13 @@
import { IsMongoId, IsNumber, IsString } from "class-validator";
import { IBehaviorTreeModel } from "./behavior_tree_database_model";
export class BehaviorTreeValidationModel implements IBehaviorTreeModel {
@IsString()
public name: string;
@IsMongoId()
public project:string;
public skills:any;
public xml:string;
@IsNumber()
public unixTime: number
}

View file

@ -0,0 +1,28 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ExecCalculationInstanceProcessScenario } from "./domain/exec_calculations_instance_process_scenario";
import { CalculationInstanceValidationModel } from "./models/calculations_instance_validation_model";
import { CalculationInstanceDBModel } from "./models/calculations_instance_database_model";
import { CreateCalculationInstanceScenario } from "./domain/create_calculation_instance_scenario";
import { DeleteCalculationsInstanceScenario } from "./domain/delete_calculations_instance_scenario";
export class CalculationsInstancesPresentation extends CrudController<
CalculationInstanceValidationModel,
typeof CalculationInstanceDBModel
> {
constructor() {
super({
url: "calculations/instances",
validationModel: CalculationInstanceValidationModel,
databaseModel: CalculationInstanceDBModel,
});
super.delete(new DeleteCalculationsInstanceScenario().call);
super.post(new CreateCalculationInstanceScenario().call);
this.subRoutes.push({
method: "GET",
subUrl: "exec",
fn: new ExecCalculationInstanceProcessScenario(),
});
}
}

View file

@ -0,0 +1,8 @@
import { CreateInstanceScenario } from "../../../core/scenarios/create_intance_scenario";
import { CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
import { CalculationInstanceValidationModel } from "../models/calculations_instance_validation_model";
export class CreateCalculationInstanceScenario extends CreateInstanceScenario<CalculationInstanceValidationModel> {
databaseModel = CalculationInstanceDBModel;
validationModel: CalculationInstanceValidationModel = new CalculationInstanceValidationModel();
}

View file

@ -0,0 +1,7 @@
import { DeleteInstanceScenario } from "../../../core/scenarios/delete_instance_scenario";
import { CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
import { CalculationInstanceValidationModel } from "../models/calculations_instance_validation_model";
export class DeleteCalculationsInstanceScenario extends DeleteInstanceScenario<CalculationInstanceValidationModel> {
databaseModel = CalculationInstanceDBModel;
}

View file

@ -0,0 +1,37 @@
import { ObjectId } from "mongoose";
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { ExecProcessUseCase, IsHaveActiveProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { ProcessWatcherAndDatabaseUpdateService } from "../../datasets/domain/create_dataset_scenario";
import { CalculationInstanceDBModel, ICalculationInstance } from "../models/calculations_instance_database_model";
import { Result } from "../../../core/helpers/result";
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
export class ExecCalculationInstanceProcessScenario extends CallbackStrategyWithIdQuery {
idValidationExpression = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<ICalculationInstance>(CalculationInstanceDBModel).call(id)).map(
async (model) => {
const fileOutPath = model.instancePath.pathNormalize() + "/form.json";
return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
const execCommand = `${model.script
} --path ${model.instancePath.pathNormalize()} --form ${fileOutPath}`.replace("\n", "");
await new CreateFileUseCase().call(fileOutPath, Buffer.from(JSON.stringify(model.formBuilder)));
await CalculationInstanceDBModel.findById(id).updateOne({
processStatus: "RUN",
lastProcessExecCommand: execCommand,
});
new ExecProcessUseCase().call(
// @ts-expect-error
`${model.project.rootDir}/`,
execCommand,
id,
new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId, CalculationInstanceDBModel)
);
return Result.ok("OK");
});
}
);
}

View file

@ -0,0 +1,11 @@
import { ResponseBase } from "../../../core/controllers/http_controller";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { GetActiveProjectIdScenario } from "../../projects/domain/get_active_project_id_scenario";
import { ICalculationInstance, CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
export class GetAllWeightsActiveProjectScenarios {
call = async (): ResponseBase =>
(await new GetActiveProjectIdScenario().call()).map(
async (model) => await new SearchManyDataBaseModelUseCase<ICalculationInstance>(CalculationInstanceDBModel).call({ project: model.id })
);
}

View file

@ -0,0 +1,77 @@
import { Schema, model } from "mongoose";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface ICalculationInstance {
script: string;
instancePath: string;
formBuilder: FormBuilderValidationModel;
type: string;
name: string;
isEnd: boolean;
createDate: Date;
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
processStatus: string;
project?: IProjectModel | string;
}
export const CalculationInstanceSchema = new Schema({
script: {
type: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
type: {
type: String,
},
instanceName: {
type: String,
},
name: {
type: String,
},
isEnd: {
type: Boolean,
},
createDate: {
type: String,
},
card: {
type: String,
},
lastProcessLogs: {
type: String,
},
lastProcessExecCommand: {
type: String,
},
lastExecDate: {
type: String,
},
processStatus: {
type: String,
},
path: {
type: String,
},
instancePath: {
type: String,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
}).plugin(require("mongoose-autopopulate"));
export const calculationInstanceSchema = "calculations_instances";
export const CalculationInstanceDBModel = model<ICalculationInstance>(
calculationInstanceSchema,
CalculationInstanceSchema
);

View file

@ -0,0 +1,31 @@
import { IsNotEmpty, IsString, IsMongoId } from "class-validator";
import { ICalculationInstance } from "./calculations_instance_database_model";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel } from "../../projects/models/project_model_database_model";
export class CalculationInstanceValidationModel implements ICalculationInstance {
@IsNotEmpty()
@IsString()
instanceName: string;
instancePath: string;
processStatus: string;
@IsString()
path: string;
project?: string | IProjectModel;
@IsString()
@IsNotEmpty()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
name: string;
isEnd: boolean = false;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
}

View file

@ -0,0 +1,20 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { DeleteCalculationsTemplateScenario } from "./domain/delete_calculations_template_scenario";
import { CalculationsTemplateValidationModel as CalculationsTemplateValidationModel } from "./models/calculations_template_validation_model";
import { CalculationsTemplateDBModel } from "./models/calculations_template_database_model";
import { CreateCalculationsTemplateScenario } from "./domain/create_calculations_template_scenario";
export class CalculationsTemplatePresentation extends CrudController<
CalculationsTemplateValidationModel,
typeof CalculationsTemplateDBModel
> {
constructor() {
super({
url: "calculations/template",
validationModel: CalculationsTemplateValidationModel,
databaseModel: CalculationsTemplateDBModel,
});
super.post(new CreateCalculationsTemplateScenario().call);
super.delete(new DeleteCalculationsTemplateScenario().call);
}
}

View file

@ -0,0 +1,10 @@
import { StaticFilesServer } from "../../../core/models/static_files";
import { CreateTemplateScenario } from "../../../core/scenarios/create_template_scenario";
import { CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
import { CalculationsTemplateValidationModel } from "../models/calculations_template_validation_model";
export class CreateCalculationsTemplateScenario extends CreateTemplateScenario<CalculationsTemplateValidationModel> {
validationModel: CalculationsTemplateValidationModel = new CalculationsTemplateValidationModel();
databaseModel = CalculationsTemplateDBModel;
path: string = StaticFilesServer.process;
}

View file

@ -0,0 +1,6 @@
import { DeleteTemplateScenario } from "../../../core/scenarios/delete_template_scenario";
import { CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
export class DeleteCalculationsTemplateScenario extends DeleteTemplateScenario {
databaseModel = CalculationsTemplateDBModel;
}

View file

@ -0,0 +1,11 @@
import { ResponseBase } from "../../../core/controllers/http_controller";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { GetActiveProjectIdScenario } from "../../projects/domain/get_active_project_id_scenario";
import { ICalculationsTemplateModel, CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
export class GetAllCalculationsTemplateScenarios {
call = async (): ResponseBase =>
(await new GetActiveProjectIdScenario().call()).map(
async (model) => await new SearchManyDataBaseModelUseCase<ICalculationsTemplateModel>(CalculationsTemplateDBModel).call({ project: model.id })
);
}

View file

@ -0,0 +1,54 @@
import { Schema, model } from "mongoose";
import { FormBuilderValidationModel, IDatasetModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface ICalculationsTemplateModel {
path?: string;
script: string;
formBuilder: FormBuilderValidationModel;
type: string;
name: string;
isEnd: boolean;
createDate: Date;
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
processStatus: string;
project?: IProjectModel | string;
}
export const CalculationsTemplateSchema = new Schema({
script: {
type: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
type: {
type: String,
},
name: {
type: String,
},
createDate: {
type: Number,
},
card: {
type: String,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
path: {
type: String,
},
}).plugin(require("mongoose-autopopulate"));
export const calculationsTemplateSchema = "calculations_templates";
export const CalculationsTemplateDBModel = model<ICalculationsTemplateModel>(calculationsTemplateSchema, CalculationsTemplateSchema);

View file

@ -0,0 +1,27 @@
import { IsNotEmpty, IsString, IsMongoId } from "class-validator";
import { ICalculationsTemplateModel } from "./calculations_template_database_model";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel } from "../../projects/models/project_model_database_model";
export class CalculationsTemplateValidationModel implements ICalculationsTemplateModel {
processStatus: string;
@IsMongoId()
project?: string | IProjectModel;
@IsString()
@IsNotEmpty()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
name: string;
isEnd: boolean = true;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
path: string;
}

View file

@ -4,16 +4,20 @@ import { Result } from "../../../core/helpers/result";
import { TypedEvent } from "../../../core/helpers/typed_event"; import { TypedEvent } from "../../../core/helpers/typed_event";
import { EXEC_EVENT, ExecError, SpawnError } from "../../../core/models/exec_error_model"; import { EXEC_EVENT, ExecError, SpawnError } from "../../../core/models/exec_error_model";
import { ExecutorResult } from "../../../core/models/executor_result"; import { ExecutorResult } from "../../../core/models/executor_result";
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase"; import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model";
import { DatasetDBModel } from "../models/dataset_database_model"; import { DatasetDBModel } from "../models/dataset_database_model";
import { DatasetValidationModel, ProcessStatus } from "../models/dataset_validation_model"; import { DatasetValidationModel, ProcessStatus } from "../models/dataset_validation_model";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> { export class ProcessWatcherAndDatabaseUpdateService<A> extends TypedEvent<
Result<ExecError | SpawnError, ExecutorResult>
> {
databaseId: ObjectId; databaseId: ObjectId;
constructor(databaseId: ObjectId) { model: A;
constructor(databaseId: ObjectId, model: A) {
super(); super();
this.databaseId = databaseId; this.databaseId = databaseId;
this.model = model;
this.on((event) => this.lister(event)); this.on((event) => this.lister(event));
} }
@ -21,20 +25,22 @@ export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<Ex
event.fold( event.fold(
async (success) => { async (success) => {
if (success.event == EXEC_EVENT.END) { if (success.event == EXEC_EVENT.END) {
const dbModel = await DatasetDBModel.findById(this.databaseId); // @ts-expect-error
const dbModel = await this.model.findById(this.databaseId);
if (dbModel !== null) { if (dbModel !== null) {
dbModel.local_path; dbModel.local_path;
dbModel.processStatus = ProcessStatus.END; dbModel.processStatus = ProcessStatus.END;
dbModel.processLogs = success.data; dbModel.lastProcessLogs = success.data;
await dbModel.save(); await dbModel.save();
} }
} }
}, },
async (error) => { async (error) => {
const dbModel = await DatasetDBModel.findById(this.databaseId); // @ts-expect-error
const dbModel = await this.model.findById(this.databaseId);
if (dbModel !== null) { if (dbModel !== null) {
dbModel.processStatus = ProcessStatus.ERROR; dbModel.processStatus = ProcessStatus.ERROR;
dbModel.processLogs = error.message; dbModel.lastProcessLogs = error.message;
await dbModel.save(); await dbModel.save();
} }
} }
@ -45,7 +51,7 @@ export class CreateDataSetScenario extends CallbackStrategyWithValidationModel<D
validationModel: DatasetValidationModel; validationModel: DatasetValidationModel;
call = async (model: DatasetValidationModel): ResponseBase => { call = async (model: DatasetValidationModel): ResponseBase => {
return ( return (
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects") await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
).map(async (project) => { ).map(async (project) => {
model.processStatus = ProcessStatus.NEW; model.processStatus = ProcessStatus.NEW;
model.local_path = project.rootDir; model.local_path = project.rootDir;

View file

@ -6,6 +6,7 @@ import { MongoIdValidation } from "../../../core/validations/mongo_id_validation
import { DatasetDBModel } from "../models/dataset_database_model"; import { DatasetDBModel } from "../models/dataset_database_model";
import { IDatasetModel } from "../models/dataset_validation_model"; import { IDatasetModel } from "../models/dataset_validation_model";
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scenario"; import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scenario";
import { FolderStructure } from "../../projects/domain/upload_file_to_to_project_scenario";
export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery { export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
idValidationExpression = new MongoIdValidation(); idValidationExpression = new MongoIdValidation();
@ -14,12 +15,13 @@ export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
return (await new ReadByIdDataBaseModelUseCase<IDatasetModel>(DatasetDBModel).call(id)).map(async (model) => { return (await new ReadByIdDataBaseModelUseCase<IDatasetModel>(DatasetDBModel).call(id)).map(async (model) => {
return (await new IsHaveActiveProcessUseCase().call()).map(async () => { return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
await DatasetDBModel.findById(id).updateOne({ processStatus: "RUN" }); await DatasetDBModel.findById(id).updateOne({ processStatus: "RUN" });
console.log(`blenderproc run $PYTHON_BLENDER_PROC --cfg '${JSON.stringify(model)}'`); model.local_path = `${model.local_path}/${FolderStructure.datasets}/`;
return new ExecProcessUseCase().call( return new ExecProcessUseCase().call(
`${model.project.rootDir}/`, `${model.project.rootDir}/`,
`blenderproc run $PYTHON_BLENDER_PROC --cfg '${JSON.stringify(model)}'`, `blenderproc run $PYTHON_BLENDER_PROC --cfg '${JSON.stringify(model)}'`,
id, id,
new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId) new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId, DatasetDBModel)
); );
}); });
}); });

View file

@ -1,13 +1,13 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"; import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result"; import { Result } from "../../../core/helpers/result";
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase"; import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model"; import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { DatasetDBModel } from "../models/dataset_database_model"; import { DatasetDBModel } from "../models/dataset_database_model";
export class GetDatasetActiveProjectScenario extends CallbackStrategyWithEmpty { export class GetDatasetActiveProjectScenario extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => { call = async (): ResponseBase => {
return ( return (
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects") await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
).map(async (project) => { ).map(async (project) => {
return Result.ok(await DatasetDBModel.find({ project: project._id })); return Result.ok(await DatasetDBModel.find({ project: project._id }));
}); });

View file

@ -1,6 +1,6 @@
import { Mongoose, Schema, model } from "mongoose"; import { Schema, model } from "mongoose";
import { IDatasetModel } from "./dataset_validation_model"; import { IDatasetModel } from "./dataset_validation_model";
import { projectSchema } from "../../_projects/models/project_database_model"; import { projectSchema } from "../../projects/models/project_model_database_model";
export const DatasetSchema = new Schema({ export const DatasetSchema = new Schema({
name: { name: {

View file

@ -1,6 +1,6 @@
import { Type } from "class-transformer"; import { Type } from "class-transformer";
import { IsArray, IsOptional, IsString, ValidateNested } from "class-validator"; import { IsArray, IsOptional, IsString, ValidateNested } from "class-validator";
import { IProjectModel } from "../../_projects/models/project_database_model"; import { IProjectModel } from "../../projects/models/project_model_database_model";
export class FormBuilderValidationModel { export class FormBuilderValidationModel {
@IsString() @IsString()
@ -9,6 +9,7 @@ export class FormBuilderValidationModel {
public context: string; public context: string;
@IsArray() @IsArray()
public form: []; public form: [];
output: any;
} }
export enum ProcessStatus { export enum ProcessStatus {
END = "END", END = "END",
@ -16,7 +17,7 @@ export enum ProcessStatus {
NEW = "NEW", NEW = "NEW",
} }
export interface IDatasetModel { export interface IDatasetModel {
_id?:string; _id?: string;
name: string; name: string;
local_path: string; local_path: string;
dataSetObjects: string[]; dataSetObjects: string[];

View file

@ -0,0 +1,26 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { CreateDigitalTwinsInstanceScenario } from "./domain/create_digital_twins_instance";
import { DeleteDigitalTwinsInstanceScenario } from "./domain/delete_digital_twins_instance";
import { ExecInstanceScenario } from "./domain/exec_instance_scenario";
import { DigitalTwinsInstanceDatabaseModel } from "./model/digital_twins_instance_database_model";
import { DigitalTwinsInstanceValidationModel } from "./model/digital_twins_instance_validation_model";
export class DigitalTwinsInstancePresentation extends CrudController<
DigitalTwinsInstanceValidationModel,
typeof DigitalTwinsInstanceDatabaseModel
> {
constructor() {
super({
url: "digital/twins/instance",
validationModel: DigitalTwinsInstanceValidationModel,
databaseModel: DigitalTwinsInstanceDatabaseModel,
});
super.post(new CreateDigitalTwinsInstanceScenario().call);
super.delete(new DeleteDigitalTwinsInstanceScenario().call);
this.subRoutes.push({
method: "POST",
fn: new ExecInstanceScenario(),
subUrl: "exec/instance",
});
}
}

View file

@ -0,0 +1,10 @@
import { CreateInstanceScenario } from "../../../core/scenarios/create_intance_scenario";
import { DigitalTwinsInstanceDatabaseModel } from "../model/digital_twins_instance_database_model";
import { DigitalTwinsInstanceValidationModel } from "../model/digital_twins_instance_validation_model";
export class CreateDigitalTwinsInstanceScenario extends CreateInstanceScenario<DigitalTwinsInstanceValidationModel> {
databaseModel = DigitalTwinsInstanceDatabaseModel;
validationModel: DigitalTwinsInstanceValidationModel = new DigitalTwinsInstanceValidationModel();
}

View file

@ -0,0 +1,7 @@
import { DeleteInstanceScenario } from "../../../core/scenarios/delete_instance_scenario";
import { DigitalTwinsInstanceDatabaseModel } from "../model/digital_twins_instance_database_model";
import { DigitalTwinsInstanceValidationModel } from "../model/digital_twins_instance_validation_model";
export class DeleteDigitalTwinsInstanceScenario extends DeleteInstanceScenario<DigitalTwinsInstanceValidationModel> {
databaseModel = DigitalTwinsInstanceDatabaseModel;
}

View file

@ -0,0 +1,36 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../../../core/validations/core_validation";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import {
DigitalTwinsInstanceDatabaseModel,
IDigitalTwinsInstanceModel,
} from "../model/digital_twins_instance_database_model";
import { ITopicModel } from "../../topics/topic_database_model";
import { ExecInstanceTwinsProcessService } from "../services/exec_instance_twins_process_service";
export interface Topics {
topics: ITopicModel[];
}
export class ExecInstanceScenario extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(
await new ReadByIdDataBaseModelUseCase<IDigitalTwinsInstanceModel>(DigitalTwinsInstanceDatabaseModel).call(id)
).map(
(document) => (
console.log('DOCUMeNT PATH'),
console.log(document.instancePath.pathNormalize()),
new ExecProcessUseCase().call(
document.instancePath,
`python3 $GET_INTERFACES --path ${document.instancePath.pathNormalize()} --package '${JSON.stringify(
document
)}'`,
"",
new ExecInstanceTwinsProcessService(document.instancePath, document)
)
)
);
}

View file

@ -0,0 +1,39 @@
import { Schema, model } from "mongoose";
export interface IDigitalTwinsInstanceModel {
instancePath: string;
status?: string;
}
export const DigitalTwinsInstanceSchema = new Schema({
path: String,
name: String,
entity: String,
description: String,
command: String,
status: {
type: String,
},
interfaces: {
cmd: String,
},
instancePath: {
type: String,
},
package: {
type: String,
},
executable: {
type: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
}).plugin(require("mongoose-autopopulate"));
export const digitalTwinsInstanceSchema = "digital_twins_instance";
export const DigitalTwinsInstanceDatabaseModel = model<IDigitalTwinsInstanceModel>(
digitalTwinsInstanceSchema,
DigitalTwinsInstanceSchema
);

View file

@ -0,0 +1,26 @@
import { Type } from "class-transformer";
import { IsEnum, IsString } from "class-validator";
import { Instance } from "../../../core/models/instance";
enum DigitalTwinsTypes {
CAMERA = "CAMERA",
ROBOT = "ROBOT",
}
export class Interfaces {
@IsString()
cmd: string;
}
export class DigitalTwinsInstanceValidationModel implements Instance {
instanceName: string;
instancePath: string;
path: string;
name: string;
@IsEnum(DigitalTwinsTypes)
entity: DigitalTwinsTypes;
@IsString()
description: string;
@IsString()
command: string;
@Type(() => Interfaces)
interfaces: Interfaces;
}

View file

@ -0,0 +1,49 @@
import { Result } from "../../../core/helpers/result";
import { TypedEvent } from "../../../core/helpers/typed_event";
import { ExecError, SpawnError, EXEC_EVENT } from "../../../core/models/exec_error_model";
import { ExecutorResult } from "../../../core/models/executor_result";
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
import { ReadFileAndParseJsonUseCase } from "../../../core/usecases/read_file_and_parse_json";
import { ITopicModel, TopicDatabaseModel } from "../../topics/topic_database_model";
import { Topics } from "../domain/exec_instance_scenario";
export class ExecInstanceTwinsProcessService extends TypedEvent<
Result<ExecError | SpawnError, ExecutorResult>
> {
path: string;
databaseModel: any;
constructor(path: string, databaseModel: any) {
super();
this.path = path;
this.databaseModel = databaseModel;
this.on((event) => this.lister(event));
}
lister = (event: Result<ExecError | SpawnError, ExecutorResult>) =>
event.fold(
async (success) => {
if (success.event == EXEC_EVENT.END) {
(await new ReadFileAndParseJsonUseCase().call<Topics>(this.path + "/topics.json")).fold(
async (model) => {
await model.topics.forEach(async (el) => {
el.digitalTwinId = this.databaseModel._id;
await new CreateDataBaseModelUseCase<ITopicModel>(TopicDatabaseModel).call(el);
});
this.databaseModel.status = "END";
await this.databaseModel.save();
},
async (_) => {
this.databaseModel.status = "ERROR";
await this.databaseModel.save();
}
);
}
},
async (_) => {
this.databaseModel.status = "ERROR";
await this.databaseModel.save();
}
);
}

View file

@ -0,0 +1,20 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { CreateDigitalTwinsTemplateScenario } from "./domain/create_digital_twins_template";
import { DeleteDigitalTwinsTemplateScenario } from "./domain/delete_digital_twins_template";
import { DigitalTwinsTemplateDBModel } from "./models/digital_twins_template_database_model";
import { DigitalTwinsTemplateValidationModel } from "./models/digital_twins_template_validation_model";
export class DigitalTwinsTemplatePresentation extends CrudController<
DigitalTwinsTemplateValidationModel,
typeof DigitalTwinsTemplateDBModel
> {
constructor() {
super({
url: "digital/twins/template",
validationModel: DigitalTwinsTemplateValidationModel,
databaseModel: DigitalTwinsTemplateDBModel,
});
super.post(new CreateDigitalTwinsTemplateScenario().call);
super.delete(new DeleteDigitalTwinsTemplateScenario().call);
}
}

View file

@ -0,0 +1,10 @@
import { StaticFilesServer } from "../../../core/models/static_files";
import { CreateTemplateScenario } from "../../../core/scenarios/create_template_scenario";
import { DigitalTwinsTemplateDBModel } from "../models/digital_twins_template_database_model";
import { DigitalTwinsTemplateValidationModel } from "../models/digital_twins_template_validation_model";
export class CreateDigitalTwinsTemplateScenario extends CreateTemplateScenario<DigitalTwinsTemplateValidationModel> {
validationModel: DigitalTwinsTemplateValidationModel = new DigitalTwinsTemplateValidationModel();
databaseModel = DigitalTwinsTemplateDBModel;
path: string = StaticFilesServer.digitalTwins;
}

View file

@ -0,0 +1,6 @@
import { DeleteTemplateScenario } from "../../../core/scenarios/delete_template_scenario";
import { DigitalTwinsTemplateDBModel } from "../models/digital_twins_template_database_model";
export class DeleteDigitalTwinsTemplateScenario extends DeleteTemplateScenario {
databaseModel = DigitalTwinsTemplateDBModel;
}

View file

@ -0,0 +1,30 @@
import { Schema, model } from "mongoose";
export interface IDigitalTwinsTemplateTemplateModel {}
export const DigitalTwinsTemplateSchema = new Schema({
path: String,
name: String,
entity: String,
description: String,
command: String,
package: {
type: String,
},
executable: {
type: String,
},
interfaces: {
cmd: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
}).plugin(require("mongoose-autopopulate"));
export const digitalTwinsTemplateSchema = "digital_twins_templates";
export const DigitalTwinsTemplateDBModel = model<IDigitalTwinsTemplateTemplateModel>(
digitalTwinsTemplateSchema,
DigitalTwinsTemplateSchema
);

View file

@ -0,0 +1,23 @@
import { Type } from "class-transformer";
import { IsEnum, IsString } from "class-validator";
enum DigitalTwinsTypes {
CAMERA = "CAMERA",
ROBOT = "ROBOT",
}
export class Interfaces {
@IsString()
cmd: string;
}
export class DigitalTwinsTemplateValidationModel {
path: string;
name: string;
@IsEnum(DigitalTwinsTypes)
entity: DigitalTwinsTypes;
@IsString()
description: string;
@IsString()
command: string;
@Type(() => Interfaces)
interfaces: Interfaces;
}

View file

@ -2,9 +2,8 @@ import { App } from "../../../core/controllers/app";
import { Result } from "../../../core/helpers/result"; import { Result } from "../../../core/helpers/result";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { IsString } from "class-validator"; import { IsString } from "class-validator";
import { ProjectDBModel } from "../../_projects/models/project_database_model";
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase"; import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
import { ProjectDBModel } from "../models/project_model_database_model";
export class ProjectValidationModel { export class ProjectValidationModel {
@IsString() @IsString()

View file

@ -0,0 +1,12 @@
import { CallbackStrategyWithEmpty } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../models/project_model_database_model";
export class GetActiveProjectIdScenario extends CallbackStrategyWithEmpty {
async call(): Promise<Result<any, { id: string }>> {
return (
await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
).map((model) => Result.ok({ id: model._id }));
}
}

View file

@ -1,12 +0,0 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model";
export class GetActiveProjectScenario extends CallbackStrategyWithEmpty {
async call(): ResponseBase {
return (
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
).map((model) => Result.ok({ id: model._id }));
}
}

Some files were not shown because too many files have changed in this diff Show more