Skip to content

Commit 248d66b

Browse files
committed
feat(new iot): merge generator-iot closes #450
1 parent 8ac8b2f commit 248d66b

File tree

67 files changed

+3745
-7
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3745
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
using Cmf.CLI.Core;
2+
using Cmf.CLI.Core.Attributes;
3+
using Cmf.CLI.Core.Commands;
4+
using Cmf.CLI.Core.Enums;
5+
using Cmf.CLI.Core.Objects;
6+
using Cmf.CLI.Utilities;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Newtonsoft.Json;
9+
using Spectre.Console;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.CommandLine;
13+
using System.CommandLine.NamingConventionBinder;
14+
using System.IO.Abstractions;
15+
16+
namespace Cmf.CLI.Commands.New.IoT
17+
{
18+
/// <summary>
19+
/// Generates IoT Converter structure
20+
/// </summary>
21+
[CmfCommand("converter", ParentId = "new_iot", Id = "iot_converter")]
22+
public class GenerateConverterCommand : TemplateCommand
23+
{
24+
/// <summary>
25+
/// constructor
26+
/// </summary>
27+
public GenerateConverterCommand() : base("converter")
28+
{
29+
}
30+
31+
/// <summary>
32+
/// constructor
33+
/// </summary>
34+
/// <param name="fileSystem">the filesystem implementation</param>
35+
public GenerateConverterCommand(IFileSystem fileSystem) : base("converter", fileSystem)
36+
{
37+
}
38+
39+
public override void Configure(Command cmd)
40+
{
41+
var nearestIoTPackage = FileSystemUtilities.GetPackageRootByType(
42+
this.fileSystem.Directory.GetCurrentDirectory(),
43+
PackageType.IoT,
44+
this.fileSystem
45+
);
46+
47+
cmd.AddArgument(new Argument<IDirectoryInfo>(
48+
name: "workingDir",
49+
parse: (argResult) => Parse<IDirectoryInfo>(argResult, nearestIoTPackage?.FullName),
50+
isDefault: true
51+
)
52+
{
53+
Description = "Working Directory"
54+
});
55+
56+
cmd.Handler = CommandHandler.Create<IDirectoryInfo>(this.Execute);
57+
}
58+
59+
/// <summary>
60+
/// Execute the command
61+
/// </summary>
62+
/// <param name="workingDir">nearest root package</param>
63+
/// <param name="version">package version</param>
64+
/// <param name="htmlPackageLocation">location of html package</param>
65+
public void Execute(IDirectoryInfo workingDir)
66+
{
67+
if (workingDir == null)
68+
{
69+
throw new CliException("This command needs to run inside an iot project. Run `cmf new iot` to create a new project.");
70+
}
71+
72+
if (ExecutionContext.Instance.ProjectConfig.MESVersion.Major < 11)
73+
{
74+
throw new CliException("This command is only valid for versions above 11.0.0");
75+
}
76+
77+
using var activity = ExecutionContext.ServiceProvider?.GetService<ITelemetryService>()?.StartExtendedActivity(this.GetType().Name);
78+
79+
var converter = HandleConverter(new ConverterValues());
80+
81+
var args = this.GenerateArgs(workingDir, this.fileSystem.Directory.GetCurrentDirectory(), converter.Name, converter.ClassName, converter.Title, converter.InputAsJS, converter.OutputAsJS);
82+
this.CommandName = "iot-converter";
83+
base.RunCommand(args);
84+
85+
var indexPath = this.fileSystem.Path.Join(this.fileSystem.Directory.GetCurrentDirectory(), "src/index.ts");
86+
this.fileSystem.File.AppendAllLines(indexPath, ["export { " + converter.ClassName + "Converter } from \"./converters/" + converter.Name + "/" + converter.Name + ".converter\";\r\n"]);
87+
88+
var template = new TemplateTaskLibrary()
89+
{
90+
Converters = [converter]
91+
};
92+
var templatePath = this.fileSystem.Path.Join(this.fileSystem.Directory.GetCurrentDirectory(), $"templates/converter_{converter.Name}.json");
93+
this.fileSystem.File.WriteAllText(templatePath,
94+
JsonConvert.SerializeObject(template,
95+
new JsonSerializerSettings()
96+
{
97+
NullValueHandling = NullValueHandling.Ignore,
98+
Formatting = Formatting.Indented
99+
}));
100+
}
101+
102+
private ConverterValues HandleConverter(ConverterValues converter)
103+
{
104+
converter.Name = AnsiConsole.Ask("What is the converter name?", converter.Name).ToCamelCase();
105+
converter.ClassName = converter.Name.ToPascalCase();
106+
converter.Title = AnsiConsole.Ask("What is the converter Title?", converter.Title);
107+
108+
converter.Input = AnsiConsole.Prompt(
109+
new SelectionPrompt<string>()
110+
.Title("What is the input type?")
111+
.AddChoices(Enum.GetNames(typeof(DataTypeInputOutput))));
112+
converter.Output = AnsiConsole.Prompt(
113+
new SelectionPrompt<string>()
114+
.Title("What is the output type?")
115+
.AddChoices(Enum.GetNames(typeof(DataTypeInputOutput))));
116+
117+
converter.HasParameters = AnsiConsole.Prompt(new ConfirmationPrompt("Do you require parameters?") { DefaultValue = converter.HasParameters });
118+
119+
if (converter.HasParameters)
120+
{
121+
converter = this.HandleParameters(converter);
122+
}
123+
124+
converter.InputAsJS = IoTStructures.ConvertIoTTypesToJSTypes(converter.Input);
125+
converter.OutputAsJS = IoTStructures.ConvertIoTTypesToJSTypes(converter.Output);
126+
127+
return converter;
128+
}
129+
130+
private ConverterValues HandleParameters(ConverterValues converter)
131+
{
132+
var addParameter = true;
133+
134+
while (addParameter)
135+
{
136+
var name = AnsiConsole.Ask("Parameter Name:", "newParameter");
137+
var type = AnsiConsole.Prompt(
138+
new SelectionPrompt<string>()
139+
.Title("Parameter Type:")
140+
.AddChoices(Enum.GetNames(typeof(IoTValueType))));
141+
var typeEnum = (IoTValueType)Enum.Parse(typeof(IoTValueType), type, true);
142+
var value = IoTStructures.ConvertIoTValueTypeToTaskValueType(typeEnum);
143+
144+
if (typeEnum == IoTValueType.Any || typeEnum == IoTValueType.Enum)
145+
{
146+
value = """
147+
[{
148+
friendlyName: "First",
149+
value: "1"
150+
}, {
151+
friendlyName: "Second",
152+
value: "2"
153+
}]
154+
""";
155+
converter.ParametersAsJS += $"\t{name}:{value}\r\n";
156+
}
157+
158+
if (!converter.Parameters.TryAdd(name, typeEnum))
159+
{
160+
converter.Parameters[name] = typeEnum;
161+
}
162+
163+
converter.ParametersAsJS = converter.ParametersAsJS.TrimEnd();
164+
165+
addParameter = AnsiConsole.Prompt(new ConfirmationPrompt("Do you require more parameters?") { DefaultValue = false });
166+
}
167+
168+
return converter;
169+
}
170+
171+
/// <inheritdoc />
172+
private List<string> GenerateArgs(
173+
IDirectoryInfo workingDir,
174+
string packageLocation,
175+
string converterName,
176+
string className,
177+
string title,
178+
string inputAsJS,
179+
string outputAsJS)
180+
{
181+
Log.Debug($"Creating IoT Converter at {packageLocation}");
182+
183+
var args = new List<string>();
184+
args.AddRange(new[]
185+
{
186+
"--converterName", converterName,
187+
"--className", className,
188+
"--title", title,
189+
"--inputAsJS", inputAsJS,
190+
"--outputAsJS", outputAsJS
191+
});
192+
193+
return args;
194+
}
195+
}
196+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using Cmf.CLI.Core;
2+
using Cmf.CLI.Core.Attributes;
3+
using Cmf.CLI.Core.Commands;
4+
using Cmf.CLI.Core.Enums;
5+
using Cmf.CLI.Core.Objects;
6+
using Cmf.CLI.Utilities;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Spectre.Console;
9+
using System.Collections.Generic;
10+
using System.CommandLine;
11+
using System.CommandLine.NamingConventionBinder;
12+
using System.IO.Abstractions;
13+
14+
namespace Cmf.CLI.Commands.New.IoT
15+
{
16+
/// <summary>
17+
/// Generates IoT Driver structure
18+
/// </summary>
19+
[CmfCommand("driver", ParentId = "new_iot", Id = "iot_driver")]
20+
public class GenerateDriverCommand : TemplateCommand
21+
{
22+
/// <summary>
23+
/// constructor
24+
/// </summary>
25+
public GenerateDriverCommand() : base("driver")
26+
{
27+
}
28+
29+
/// <summary>
30+
/// constructor
31+
/// </summary>
32+
/// <param name="fileSystem">the filesystem implementation</param>
33+
public GenerateDriverCommand(IFileSystem fileSystem) : base("driver", fileSystem)
34+
{
35+
}
36+
37+
public override void Configure(Command cmd)
38+
{
39+
var nearestIoTPackage = FileSystemUtilities.GetPackageRootByType(
40+
this.fileSystem.Directory.GetCurrentDirectory(),
41+
PackageType.IoT,
42+
this.fileSystem
43+
);
44+
45+
cmd.AddArgument(new Argument<IDirectoryInfo>(
46+
name: "workingDir",
47+
parse: (argResult) => Parse<IDirectoryInfo>(argResult, nearestIoTPackage?.FullName),
48+
isDefault: true
49+
)
50+
{
51+
Description = "Working Directory"
52+
});
53+
54+
cmd.Handler = CommandHandler.Create<IDirectoryInfo>(this.Execute);
55+
}
56+
57+
/// <summary>
58+
/// Execute the command
59+
/// </summary>
60+
/// <param name="workingDir">nearest root package</param>
61+
/// <param name="version">package version</param>
62+
/// <param name="htmlPackageLocation">location of html package</param>
63+
public void Execute(IDirectoryInfo workingDir)
64+
{
65+
if (workingDir == null)
66+
{
67+
throw new CliException("This command needs to run inside an iot project. Run `cmf new iot` to create a new project.");
68+
}
69+
70+
if (ExecutionContext.Instance.ProjectConfig.MESVersion.Major < 11)
71+
{
72+
throw new CliException("This command is only valid for versions above 11.0.0");
73+
}
74+
75+
using var activity = ExecutionContext.ServiceProvider?.GetService<ITelemetryService>()?.StartExtendedActivity(this.GetType().Name);
76+
77+
var driver = HandleDriver(new DriverValues());
78+
79+
var args = this.GenerateArgs(workingDir, this.fileSystem.Directory.GetCurrentDirectory(), driver.Directory, driver.Identifier, driver.IdentifierCamel, driver.PackageFullName, driver.PackageVersion, driver.HasCommands);
80+
this.CommandName = "iot-driver";
81+
base.RunCommand(args);
82+
}
83+
84+
private DriverValues HandleDriver(DriverValues driver)
85+
{
86+
driver.Directory = AnsiConsole.Ask("What is the identifier (directory name)?", driver.Directory);
87+
driver.PackageScope = AnsiConsole.Ask("What is the driver scope?", driver.PackageScope);
88+
driver.PackageName = AnsiConsole.Ask("What is the package name?", driver.PackageName);
89+
driver.PackageFullName = $"{driver.PackageScope}/{driver.PackageName}";
90+
91+
driver.PackageVersion = AnsiConsole.Ask("What is the package version?", driver.PackageVersion);
92+
driver.Identifier = AnsiConsole.Ask("What is the identifier (Protocol name, no spaces)?", driver.Identifier).ToPascalCase();
93+
driver.IdentifierCamel = driver.Identifier.ToCamelCase();
94+
95+
driver.HasCommands = AnsiConsole.Prompt(new ConfirmationPrompt("Does the protocol support commands?") { DefaultValue = driver.HasCommands });
96+
97+
return driver;
98+
}
99+
100+
/// <inheritdoc />
101+
private List<string> GenerateArgs(
102+
IDirectoryInfo workingDir,
103+
string packageLocation,
104+
string directoryName,
105+
string identifier,
106+
string identifierCamel,
107+
string packageName,
108+
string packageVersion,
109+
bool hasCommands)
110+
{
111+
var mesVersion = ExecutionContext.Instance.ProjectConfig.MESVersion;
112+
Log.Debug($"Creating IoT Driver at {packageLocation}");
113+
114+
var args = new List<string>();
115+
args.AddRange(new[]
116+
{
117+
"--targetSystemVersionProcessed", $"release-{mesVersion.Major}{mesVersion.Minor}{mesVersion.Build}",
118+
"--directoryName", directoryName,
119+
"--identifier", identifier,
120+
"--identifierCamel", identifierCamel,
121+
"--packageName", packageName,
122+
"--packageVersion", packageVersion,
123+
"--npmRegistry", ExecutionContext.Instance.ProjectConfig.NPMRegistry.ToString(),
124+
"--hasCommands", hasCommands.ToString()
125+
});
126+
127+
return args;
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)