Skip to content

Commit

Permalink
feat: add options for automatic startup of instance on startup of the…
Browse files Browse the repository at this point in the history
… manager
  • Loading branch information
Jasper De Keukelaere (imec) authored and Jasper De Keukelaere (imec) committed Aug 2, 2024
1 parent 292f975 commit 741a3a2
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.1] - 2024-08-02

### Features
- Add a settings tab in the instance view. It is now possible to enable "Register On Startup" and "Power On Startup". When this is enabled the instance will be registered or started when the manager exe is started.
- Add a persistence.json file in the manager folder to store the settings.

## [0.1.0] - 2024-07-25

This is a major update with some new features and improvements, mainly for the UI.
Expand Down
2 changes: 1 addition & 1 deletion PLCsimAdvanced_Manager/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
_open = !_open;
}

string version = "0.1.0";
string version = "0.1.1";
bool newVersionAvailable = false;

// protected override async Task OnInitializedAsync()
Expand Down
87 changes: 83 additions & 4 deletions PLCsimAdvanced_Manager/Pages/Instance.razor
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
@inject ISnackbar Snackbar
@page "/instance/{instanceName}"
@using PLCsimAdvanced_Manager.Services
@using PLCsimAdvanced_Manager.Services.Persistence
@using Siemens.Simatic.Simulation.Runtime
@using Color = MudBlazor.Color
@inject ManagerFacade managerFacade
@inject IDialogService DialogService
@inject PersistenceHandler persistenceHandler


<div style="width: 100vw; min-width: 1000px; overflow-x: auto; justify-content: center; height:93vh">
Expand Down Expand Up @@ -247,12 +249,12 @@
case "Invalid":
<MudChip Icon="@Icons.Material.Outlined.ErrorOutline" Variant="Variant.Text" Size="Size.Small" Color="Color.Error"> @word </MudChip>
break;
case "ShuttingDown":
case "ShuttingDown":
<MudChip Icon="@Icons.Material.Outlined.Info" Variant="Variant.Text" Size="Size.Small" Color="Color.Info"> @word </MudChip>
break;
case "Startup":
<MudChip Icon="@Icons.Material.Outlined.Info" Variant="Variant.Text" Size="Size.Small" Color="Color.Info"> @word </MudChip>
break;
case "Startup":
<MudChip Icon="@Icons.Material.Outlined.Info" Variant="Variant.Text" Size="Size.Small" Color="Color.Info"> @word </MudChip>
break;
case "Booting":
<MudChip Icon="@Icons.Material.Outlined.Info" Variant="Variant.Text" Size="Size.Small" Color="Color.Info"> @word </MudChip>
break;
Expand All @@ -271,12 +273,80 @@
</MudTable>
</MudCard>
</MudTabPanel>
<MudTabPanel Text="Settings">
<MudStack>
<MudItem>
<MudText Typo="Typo.h5"> On Startup</MudText>
<MudText Typo="Typo.body1"> Actions to be taken on this instance, when starting up PLCsim Advanced Manager</MudText>
<MudCard Style="padding: 20px; flex: auto">

<MudGrid>
<MudItem xs="4">
<MudStack>
<MudText Typo="Typo.subtitle2">Register On Startup</MudText>
<MudCheckBox @bind-Checked="RegisterOnStartup"></MudCheckBox>
</MudStack>
</MudItem>
<MudItem xs="4">
<MudStack>
<MudText Typo="Typo.subtitle2">Power On Startup</MudText>
<MudCheckBox @bind-Checked="PowerOnStartup"></MudCheckBox>
</MudStack>
</MudItem>
</MudGrid>
</MudCard>


</MudItem>
</MudStack>
</MudTabPanel>
</MudTabs>

</div>
</div>

@code {

private bool _registerOnStartup;
private bool _powerOnStartup;
private bool _runOnStartup;

public bool RegisterOnStartup
{
get => _registerOnStartup;
set
{
if (_registerOnStartup != value)
{
_registerOnStartup = value;
if (!value)
{
PowerOnStartup = false;
}
}
persistenceHandler.UpdateSettings(SelectedInstance.StoragePath, RegisterOnStartup, PowerOnStartup);
}
}

public bool PowerOnStartup
{
get => _powerOnStartup;
set
{
if (_powerOnStartup != value)
{
_powerOnStartup = value;
if (value)
{
RegisterOnStartup = true;
}
}
persistenceHandler.UpdateSettings(SelectedInstance.StoragePath, RegisterOnStartup, PowerOnStartup);
}
}



[Parameter] public string InstanceName { get; set; }

private IInstance SelectedInstance;
Expand Down Expand Up @@ -322,6 +392,15 @@
subnetMask.Add(RegexMask.IPv4());
gatewayMask.Add(RegexMask.IPv4());
}

var settings = persistenceHandler.ReadSettings(SelectedInstance.StoragePath);
if (settings != null)
{
_registerOnStartup = settings.RegisterOnStartup;
_powerOnStartup = settings.PowerOnOnStartup;
}


}

private void OnLogsUpdated()
Expand Down
5 changes: 5 additions & 0 deletions PLCsimAdvanced_Manager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using MudBlazor.Services;
using PLCsimAdvanced_Manager.Services;
using PLCsimAdvanced_Manager.Services.Logger;
using PLCsimAdvanced_Manager.Services.Persistence;
using PLCsimAdvanced_Manager.Shared;

var builder = WebApplication.CreateBuilder(args);

Expand Down Expand Up @@ -37,6 +39,7 @@
builder.Services.AddSingleton<InstanceHandler>();
builder.Services.AddSingleton<EventDispatchService>();
builder.Services.AddSingleton<ManagerFacade>();
builder.Services.AddSingleton<PersistenceHandler>();

var app = builder.Build();
app.Services.GetService<EventDispatchService>();
Expand All @@ -54,6 +57,8 @@
app.UseHsts();
}

StartupTasks.GetPersistantSettings();


app.UseHttpsRedirection();

Expand Down
81 changes: 81 additions & 0 deletions PLCsimAdvanced_Manager/Services/Persistence/PersistenceHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Siemens.Simatic.Simulation.Runtime;

namespace PLCsimAdvanced_Manager.Services.Persistence;

public class PersistenceHandler
{
private Persistence _persistence = new Persistence();
private PersistenceSettings _settings = new PersistenceSettings();
private string _filePath;

public PersistenceHandler()
{
}

private void setStuffRight(string directory)
{
var managerDirectory = Path.Combine(directory, "manager");
if (!Directory.Exists(managerDirectory))
{
Directory.CreateDirectory(managerDirectory);
}

_filePath = Path.Combine(managerDirectory, "persistence.json");
if (!File.Exists(_filePath))
{
_settings = new PersistenceSettings();
// create persistence.json file
_persistence = new Persistence
{
PersistenceSettings = _settings
};
var jsonString = JsonSerializer.Serialize(_persistence, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(_filePath, jsonString);
}
}

public void UpdateSettings(string directory, bool registerOnStartup , bool powerOnOnStartup)
{
setStuffRight(directory);
_settings.RegisterOnStartup = registerOnStartup;
_settings.PowerOnOnStartup = powerOnOnStartup;
SaveSettings();
}

public PersistenceSettings? ReadSettings(string directory)
{
setStuffRight(directory);

PersistenceSettings? settings = new PersistenceSettings();
if (File.Exists(_filePath))
{
var settingContent = File.ReadAllText(_filePath);
var persistence = JsonSerializer.Deserialize<Persistence>(settingContent);
settings = persistence?.PersistenceSettings;
}

return settings;
}

private void SaveSettings()
{
_persistence.PersistenceSettings = _settings;
var jsonString = JsonSerializer.Serialize(_persistence, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(_filePath, jsonString);
}
}

public class PersistenceSettings
{
[JsonPropertyName("RegisterOnStartup")]
public bool RegisterOnStartup { get; set; } = false;

[JsonPropertyName("PowerOnOnStartup")] public bool PowerOnOnStartup { get; set; } = false;
}

public class Persistence
{
[JsonPropertyName("Settings")] public PersistenceSettings PersistenceSettings { get; set; } = null;
}
63 changes: 63 additions & 0 deletions PLCsimAdvanced_Manager/Shared/StartupTasks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Siemens.Simatic.Simulation.Runtime;

namespace PLCsimAdvanced_Manager.Shared;

public static class StartupTasks
{
public static void GetPersistantSettings()
{
var directories = Directory.GetDirectories(@SimulationRuntimeManager.DefaultStoragePath);
foreach (var directory in directories)
{
var managerDirectory = Path.Combine(directory, "manager");
if (Directory.Exists(managerDirectory))
{
var persistentSettingsFile = Path.Combine(managerDirectory, "persistence.json");
if (File.Exists(persistentSettingsFile))
{
var settingContent = File.ReadAllText(persistentSettingsFile);
var persistence = JsonSerializer.Deserialize<Persistence>(settingContent);
var settings = persistence?.PersistenceSettings;

// Use the autoStartup boolean value in your logic
if (settings?.RegisterOnStartup == true)
{
var instanceName = Path.GetFileName(directory);
try
{
var instance = SimulationRuntimeManager.RegisterInstance(instanceName);

if (settings.PowerOnOnStartup)
{
instance.PowerOn();

}
}
catch (Exception e)
{
Console.WriteLine($"There was an issue with registering the instance [{instanceName}]: {e.Message}");

}
}
}
}

}
}

}


public class PersistenceSettings
{
[JsonPropertyName("RegisterOnStartup")] public bool RegisterOnStartup { get; set; } = false;
[JsonPropertyName("PowerOnOnStartup")] public bool PowerOnOnStartup { get; set; } = false;
}

public class Persistence
{
[JsonPropertyName("Settings")] public PersistenceSettings PersistenceSettings { get; set; } = null;

Check warning on line 61 in PLCsimAdvanced_Manager/Shared/StartupTasks.cs

View workflow job for this annotation

GitHub Actions / release

Cannot convert null literal to non-nullable reference type.

Check warning on line 61 in PLCsimAdvanced_Manager/Shared/StartupTasks.cs

View workflow job for this annotation

GitHub Actions / release

Cannot convert null literal to non-nullable reference type.

}
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ Check the [**documentation**](https://jasperdekeuk.github.io/PLCsim-Advanced-Man

Download from [**releases**](https://github.com/jasperdekeuk/PLCsim-Advanced-Manager/releases)

> [!WARNING]
> The documentation is always behind. Download the latest version to see and play with all the features.
Goals:
Features:

- [x] Manage your PLCSIM Advanced instances remote in a **webserver**. This way you don't have to log in to the target PC, but can start
instances over the network
- [x] Exploit the functionalities of the PLCSIM Advanced API to create a more **advanced UI**
- [x] **Read and write variables** from the PLC (DB/Inputs/Outputs)
- [x] **Advanced network setting**. Being able to set every interface of the instance to an interface of the host machine
- [x] Create **snapshots** and restore them
- [x] Option for **auto start** instances on startup of PLCsim Advanced Manager. Either just register or completely start the instance when starting the manager application. (see instance settings)
- [ ] Easy **virtual commissioning** by e.g. setting buttons and lights in the UI to the PLC variables
- [ ] **Traces** on the variables for analysis

Expand Down

0 comments on commit 741a3a2

Please sign in to comment.