Changes to create default simulations (#298)

This commit is contained in:
Hugh Xiong 2018-10-30 00:10:37 -07:00 коммит произвёл Harleen Thind
Родитель 4f90c13b42
Коммит bb62b8f017
12 изменённых файлов: 258 добавлений и 31 удалений

3
.vscode/launch.json поставляемый
Просмотреть файл

@ -30,7 +30,8 @@
"PCS_SUBSCRIPTION_DOMAIN": "",
"PCS_SUBSCRIPTION_ID": "",
"PCS_RESOURCE_GROUP": "",
"PCS_IOHUB_NAME": ""
"PCS_IOHUB_NAME": "",
"PCS_SEED_TEMPLATE": ""
},
"stopAtEntry": false,
"justMyCode":false,

Просмотреть файл

@ -36,6 +36,7 @@ namespace Services.Test
private readonly Mock<IStorageAdapterClient> mockStorageAdapterClient;
private readonly Mock<IStorageRecords> mockStorageRecords;
private readonly Mock<IDevices> devices;
private readonly Mock<IFileSystem> file;
private readonly Mock<ILogger> logger;
private readonly Mock<IDiagnosticsLogger> diagnosticsLogger;
private readonly Mock<IIotHubConnectionStringManager> connStringManager;
@ -73,6 +74,7 @@ namespace Services.Test
this.logger = new Mock<ILogger>();
this.diagnosticsLogger = new Mock<IDiagnosticsLogger>();
this.devices = new Mock<IDevices>();
this.file = new Mock<IFileSystem>();
this.connStringManager = new Mock<IIotHubConnectionStringManager>();
this.models = new List<DeviceModel>
{
@ -89,6 +91,7 @@ namespace Services.Test
this.mockStorageAdapterClient.Object,
this.connStringManager.Object,
this.devices.Object,
this.file.Object,
this.logger.Object,
this.diagnosticsLogger.Object,
this.simulationStatistics.Object);
@ -833,6 +836,40 @@ namespace Services.Test
this.devices.Verify(x => x.DeleteListUsingJobsAsync(It.IsAny<IEnumerable<string>>()), Times.Once);
}
[Fact, Trait(Constants.TYPE, Constants.UNIT_TEST)]
public void ItTrysToCreateDefaultSimulationsWhenThereIsNoDefaultSimulationsInStorage()
{
// Arrange
this.ThereIsNoDefaultSimulationsInStorage();
this.ThereIsATemplateForDefaultSimulations();
// Act
this.target.TrySeedAsync().CompleteOrTimeout();
// Assert
this.mockStorageRecords.Verify(x => x.CreateAsync(It.IsAny<StorageRecord>()), Times.Once);
}
private void ThereIsATemplateForDefaultSimulations()
{
var simulationList = new List<SimulationModel>()
{
new SimulationModel()
};
string fileContent = JsonConvert.SerializeObject(simulationList);
const string TEMPLATE_FILE_PATH = "/data/";
this.mockConfig.Setup(x => x.SeedTemplateFolder).Returns(TEMPLATE_FILE_PATH);
this.mockConfig.Setup(x => x.SeedTemplate).Returns("template");
this.file.Setup(x => x.Exists(It.IsAny<string>())).Returns(true);
this.file.Setup(x => x.ReadAllText(It.IsAny<string>())).Returns(fileContent);
}
private void ThereIsNoDefaultSimulationsInStorage()
{
this.mockStorageRecords.Setup(x => x.ExistsAsync(It.IsAny<string>())).ReturnsAsync(false);
this.mockStorageRecords.Setup(x => x.GetAsync(It.IsAny<string>())).ThrowsAsync(new ResourceNotFoundException());
}
private void ThereAreSomeDeviceModels()
{
this.deviceModels.Setup(x => x.GetListAsync())

25
Services/FileWrapper.cs Normal file
Просмотреть файл

@ -0,0 +1,25 @@
// Copyright (c) Microsoft. All rights reserved.
using System.IO;
namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
{
public interface IFileSystem
{
bool Exists(string path);
string ReadAllText(string path);
}
public class FileWrapper : IFileSystem
{
public bool Exists(string path)
{
return File.Exists(path);
}
public string ReadAllText(string path)
{
return File.ReadAllText(path);
}
}
}

Просмотреть файл

@ -7,6 +7,8 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services.Runtime
{
public interface IServicesConfig
{
string SeedTemplate { get; }
string SeedTemplateFolder { get; }
string DeviceModelsFolder { get; }
string DeviceModelsScriptsFolder { get; }
string IoTHubConnString { get; }
@ -34,12 +36,14 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services.Runtime
{
public const string USE_DEFAULT_IOTHUB = "default";
private string stf;
private string dtf;
private string dtbf;
private string ihf;
public ServicesConfig()
{
this.stf = string.Empty;
this.dtf = string.Empty;
this.dtbf = string.Empty;
this.ihf = string.Empty;
@ -57,6 +61,14 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services.Runtime
set { this.dtbf = this.NormalizePath(value); }
}
public string SeedTemplateFolder
{
get { return this.stf; }
set { this.stf = this.NormalizePath(value); }
}
public string SeedTemplate { get; set; }
public string IoTHubConnString { get; set; }
public string IoTHubImportStorageAccount { get; set; }

Просмотреть файл

@ -5,6 +5,11 @@
<AssemblyName>Microsoft.Azure.IoTSolutions.DeviceSimulation.Services</AssemblyName>
<RootNamespace>Microsoft.Azure.IoTSolutions.DeviceSimulation.Services</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Content Include="data\templates\multiple-simulations-template.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.5.1" />
<PackageReference Include="jint" Version="2.10.4" />

Просмотреть файл

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.Services.Diagnostics;
@ -47,6 +48,9 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
// Delete a simulation and its devices.
Task DeleteAsync(string id);
// Seed default simulations
Task TrySeedAsync();
// Try to start a job to create all the devices
Task<bool> TryToStartDevicesCreationAsync(string simulationId, IDevices devices);
@ -71,14 +75,18 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
private const string DEFAULT_SIMULATION_ID = "1";
private const string DEFAULT_TEMPLATE_NAME = "default";
private const string DEVICES_COLLECTION = "SimulatedDevices";
private const string SEED_STATUS_KEY = "SeedCompleted";
private const int DEVICES_PER_MODEL_IN_DEFAULT_TEMPLATE = 1;
private readonly IServicesConfig config;
private readonly IDeviceModels deviceModels;
private readonly IStorageAdapterClient storageAdapterClient;
private readonly IStorageRecords mainStorage;
private readonly IStorageRecords simulationsStorage;
private readonly IIotHubConnectionStringManager connectionStringManager;
private readonly ISimulationStatistics simulationStatistics;
private readonly IDevices devices;
private readonly IFileSystem fileSystem;
private readonly ILogger log;
private readonly IDiagnosticsLogger diagnosticsLogger;
@ -89,15 +97,19 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
IStorageAdapterClient storageAdapterClient,
IIotHubConnectionStringManager connectionStringManager,
IDevices devices,
IFileSystem fileSystem,
ILogger logger,
IDiagnosticsLogger diagnosticsLogger,
ISimulationStatistics simulationStatistics)
{
this.config = config;
this.deviceModels = deviceModels;
this.storageAdapterClient = storageAdapterClient;
this.mainStorage = factory.Resolve<IStorageRecords>().Init(config.MainStorage);
this.simulationsStorage = factory.Resolve<IStorageRecords>().Init(config.SimulationsStorage);
this.connectionStringManager = connectionStringManager;
this.devices = devices;
this.fileSystem = fileSystem;
this.log = logger;
this.diagnosticsLogger = diagnosticsLogger;
this.simulationStatistics = simulationStatistics;
@ -387,6 +399,34 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
await this.simulationsStorage.DeleteAsync(id);
}
public async Task TrySeedAsync()
{
try
{
var templateName = this.config.SeedTemplate;
if (string.IsNullOrEmpty(templateName)) return;
// Skips if the seeding has already been complete
if (!await this.mainStorage.ExistsAsync(SEED_STATUS_KEY))
{
await this.SeedSimulationsAsync(templateName);
var record = new StorageRecord { Id = SEED_STATUS_KEY, Data = "Seed Completed" };
await this.mainStorage.CreateAsync(record);
}
else
{
this.log.Info("Seeding skipped.");
}
}
catch (Exception e)
{
var msg = "Failed to seed default simulations." + e;
this.log.Error(msg);
this.diagnosticsLogger.LogServiceError(msg);
}
}
public async Task<bool> TryToStartDevicesCreationAsync(string simulationId, IDevices devices)
{
// Fetch latest record
@ -594,6 +634,58 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.Services
return simulation;
}
// This creates sample simulations that will be shown on simulation dashboard by default
private async Task SeedSimulationsAsync(string templateName)
{
string content;
var fileName = templateName + ".json";
var filePath = Path.Combine(this.config.SeedTemplateFolder, fileName);
if (this.fileSystem.Exists(filePath))
{
content = this.fileSystem.ReadAllText(filePath);
}
else
{
this.log.Debug("Template not found for setting sample simulations.");
return;
}
Models.Simulation simulation = null;
try
{
var simulationList = JsonConvert.DeserializeObject<List<Models.Simulation>>(content);
if (simulationList == null || simulationList.Count == 0) return;
for (int index = 0; index < simulationList.Count; index++)
{
// We need to start creating simulations starting with id 1 as it is treated as default simulation
// and is referenced in Welcome page on UI
simulation = simulationList[index];
var simulationId = index + 1;
simulation.Id = simulationId.ToString();
try
{
// Check if there is an existing simulation with the given id
// if it exists then skip creating a new simulation
await this.GetAsync(simulation.Id);
}
catch (ResourceNotFoundException)
{
// create a simulation if no sample simulation exists with provided id.
simulation.StartTime = DateTimeOffset.UtcNow;
await this.UpsertAsync(simulation);
}
}
}
catch (Exception ex)
{
var message = "Failed to create sample simulation. " + " template: " + JsonConvert.SerializeObject(simulation);
this.log.Error(message, ex);
}
}
private async Task<Models.Simulation> ResetSimulationStatisticsAsync(Models.Simulation simulation)
{
// Reset ActualStartTime, which is used to calculate statistics

Просмотреть файл

@ -0,0 +1,32 @@
[
{
"Name": "Sample Simple Simulation",
"Enabled": false,
"IotHubConnectionStrings": [
"default"
],
"DeviceModels": [
{
"Id": "truck-01",
"Count": 10
}
]
},
{
"Name": "Sample Multiple Devices",
"Enabled": false,
"IotHubConnectionStrings": [
"default"
],
"DeviceModels": [
{
"Id": "chiller-01",
"Count": 50
},
{
"Id": "elevator-01",
"Count": 10
}
]
}
]

Просмотреть файл

@ -20,7 +20,8 @@
"PCS_SUBSCRIPTION_DOMAIN": "",
"PCS_SUBSCRIPTION_ID": "",
"PCS_RESOURCE_GROUP": "",
"PCS_IOHUB_NAME": ""
"PCS_IOHUB_NAME": "",
"PCS_SEED_TEMPLATE": ""
},
"applicationUrl": "http://localhost:9003/v1/status"
}

Просмотреть файл

@ -45,6 +45,8 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService.Runtime
{
private const string APPLICATION_KEY = "DeviceSimulationService:";
private const string SEED_TEMPLATE_KEY = APPLICATION_KEY + "seed_template_name";
private const string SEED_TEMPLATE_FOLDER_KEY = APPLICATION_KEY + "seed_template_folder";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string DEVICE_MODELS_FOLDER_KEY = APPLICATION_KEY + "device_models_folder";
private const string DEVICE_MODELS_SCRIPTS_FOLDER_KEY = APPLICATION_KEY + "device_models_scripts_folder";
@ -252,6 +254,8 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService.Runtime
return new ServicesConfig
{
SeedTemplate = configData.GetString(SEED_TEMPLATE_KEY),
SeedTemplateFolder = MapRelativePath(configData.GetString(SEED_TEMPLATE_FOLDER_KEY)),
DeviceModelsFolder = MapRelativePath(configData.GetString(DEVICE_MODELS_FOLDER_KEY)),
DeviceModelsScriptsFolder = MapRelativePath(configData.GetString(DEVICE_MODELS_SCRIPTS_FOLDER_KEY)),
IoTHubConnString = connstring,

Просмотреть файл

@ -6,6 +6,7 @@ using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.PartitioningAgent;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.Services;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.SimulationAgent;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService.Auth;
using Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService.Runtime;
@ -25,6 +26,9 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService
// Agent responsible for simulating IoT devices
private ISimulationAgent simulationAgent;
// Service responsible for managing simulation state
private ISimulations simulationService;
// Initialized in `Startup`
public IConfigurationRoot Configuration { get; }
@ -109,6 +113,10 @@ namespace Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService
this.simulationAgent = this.ApplicationContainer.Resolve<ISimulationAgent>();
this.simulationAgent.StartAsync();
// This creates sample simulations that will be shown on simulation dashboard by default
this.simulationService = this.ApplicationContainer.Resolve<ISimulations>();
this.simulationService.TrySeedAsync();
}
private void StopAgents()

Просмотреть файл

@ -9,20 +9,23 @@
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
<StartAction>Project</StartAction>
<EnvironmentVariables>
<Variable name="ASPNETCORE_ENVIRONMENT" value="Development"/>
<Variable name="PCS_IOTHUB_CONNSTRING" value="your Azure IoT Hub connection string"/>
<Variable name="PCS_STORAGEADAPTER_WEBSERVICE_URL" value="http://localhost:9022/v1"/>
<Variable name="PCS_RESOURCE_GROUP_LOCATION" value="your Azure resource group location"/>
<Variable name="PCS_VMSS_NAME" value="your vm scale set name"/>
<Variable name="PCS_LOG_LEVEL" value="Debug"/>
<Variable name="PCS_AUTH_REQUIRED" value="false"/>
<Variable name="PCS_AUTH_ISSUER" value=""/>
<Variable name="PCS_AUTH_AUDIENCE" value=""/>
<Variable name="PCS_CORS_WHITELIST" value=""/>
<Variable name="PCS_SUBSCRIPTION_DOMAIN" value=""/>
<Variable name="PCS_SUBSCRIPTION_ID" value=""/>
<Variable name="PCS_RESOURCE_GROUP" value=""/>
<Variable name="PCS_IOHUB_NAME" value=""/>
<Variable name="ASPNETCORE_ENVIRONMENT" value="Development" />
<Variable name="PCS_IOTHUB_CONNSTRING" value="your Azure IoT Hub connection string" />
<Variable name="PCS_STORAGEADAPTER_WEBSERVICE_URL" value="http://localhost:9022/v1" />
<Variable name="PCS_STORAGEADAPTER_DOCUMENTDB_CONNSTRING" value="your DocumentDb connection string" />
<Variable name="PCS_AZURE_STORAGE_ACCOUNT" value="your Azure Storage Account connection string" />
<Variable name="PCS_RESOURCE_GROUP_LOCATION" value="your Azure resource group location" />
<Variable name="PCS_VMSS_NAME" value="your vm scale set name" />
<Variable name="PCS_LOG_LEVEL" value="Debug" />
<Variable name="PCS_AUTH_REQUIRED" value="false" />
<Variable name="PCS_AUTH_ISSUER" value="" />
<Variable name="PCS_AUTH_AUDIENCE" value="" />
<Variable name="PCS_CORS_WHITELIST" value="" />
<Variable name="PCS_SUBSCRIPTION_DOMAIN" value="" />
<Variable name="PCS_SUBSCRIPTION_ID" value="" />
<Variable name="PCS_RESOURCE_GROUP" value="" />
<Variable name="PCS_IOHUB_NAME" value="" />
<Variable name="PCS_SEED_TEMPLATE" value="" />
</EnvironmentVariables>
<ApplicationURL>http://localhost:9003</ApplicationURL>
<LaunchUrl>http://localhost:9003/v1/status</LaunchUrl>
@ -33,28 +36,28 @@
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="4.8.1"/>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.3.0"/>
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.3"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.2"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.1.1"/>
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="2.1.5"/>
<PackageReference Include="Autofac" Version="4.8.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.1.1" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="2.1.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PartitioningAgent\PartitioningAgent.csproj"/>
<ProjectReference Include="..\Services\Services.csproj"/>
<ProjectReference Include="..\SimulationAgent\SimulationAgent.csproj"/>
<ProjectReference Include="..\PartitioningAgent\PartitioningAgent.csproj" />
<ProjectReference Include="..\Services\Services.csproj" />
<ProjectReference Include="..\SimulationAgent\SimulationAgent.csproj" />
</ItemGroup>
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/x-csharp"/>
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="True" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" NewLineForMembersInObjectInit="True" NewLineForMembersInAnonymousTypes="True" NewLineForClausesInQuery="True" SpacingAfterMethodDeclarationName="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="True" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" scope="text/x-csharp"/>
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/plain"/>
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/x-json"/>
<JSONFormattingPolicy AutomaticFormatting="False" AutoStructureCompletion="True" BracePositions="SemiExpanded" FormatOnPaste="True" scope="text/x-json"/>
<StandardHeader IncludeInNewFiles="True" Text="// Copyright (c) Microsoft. All rights reserved.&#xA;"/>
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="True" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" NewLineForMembersInObjectInit="True" NewLineForMembersInAnonymousTypes="True" NewLineForClausesInQuery="True" SpacingAfterMethodDeclarationName="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="True" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" scope="text/x-csharp" />
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/plain" />
<TextStylePolicy TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" FileWidth="80" TabsToSpaces="True" scope="text/x-json" />
<JSONFormattingPolicy AutomaticFormatting="False" AutoStructureCompletion="True" BracePositions="SemiExpanded" FormatOnPaste="True" scope="text/x-json" />
<StandardHeader IncludeInNewFiles="True" Text="// Copyright (c) Microsoft. All rights reserved.&#xA;" />
</Policies>
</Properties>
</MonoDevelop>

Просмотреть файл

@ -19,6 +19,13 @@
# TCP port where to listen for web service requests. 9003 by default.
webservice_port = 9003
# Template (name) to be used for solution seeding
# e.g. multiple-simulations-template corresponds to multiple-simulations-template.json
seed_template_name = "${?PCS_SEED_TEMPLATE}"
# Folder where templates are located
seed_template_folder = ./data/templates/
# Azure IoT Hub connection string
# Format: HostName=_____.azure-devices.net;SharedAccessKeyName=_____;SharedAccessKey=_____
iothub_connstring = "${PCS_IOTHUB_CONNSTRING}"