diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e76fde3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS8600: Literál s hodnotou null nebo s možnou hodnotou null se převádí na typ, který nemůže mít hodnotu null. +dotnet_diagnostic.CS8600.severity = silent diff --git a/API_SequentMicrosystems.csproj b/API_SequentMicrosystems.csproj new file mode 100644 index 0000000..47b1d5a --- /dev/null +++ b/API_SequentMicrosystems.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + diff --git a/API_SequentMicrosystems.http b/API_SequentMicrosystems.http new file mode 100644 index 0000000..e67ea87 --- /dev/null +++ b/API_SequentMicrosystems.http @@ -0,0 +1,6 @@ +@API_SequentMicrosystems_HostAddress = http://localhost:5242 + +GET {{API_SequentMicrosystems_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/API_SequentMicrosystems.sln b/API_SequentMicrosystems.sln new file mode 100644 index 0000000..da60ede --- /dev/null +++ b/API_SequentMicrosystems.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34309.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API_SequentMicrosystems", "API_SequentMicrosystems.csproj", "{357DFFA8-F19B-4D1D-91A3-590E8C526763}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libs_SequentMicrosystems", "..\Libs_SequentMicrosystems\Libs_SequentMicrosystems.csproj", "{65BF0CBE-211E-44BD-85CB-ACA4303A5744}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D1EBA159-E66F-40B9-9CA4-771280C2D647}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {357DFFA8-F19B-4D1D-91A3-590E8C526763}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {357DFFA8-F19B-4D1D-91A3-590E8C526763}.Debug|Any CPU.Build.0 = Debug|Any CPU + {357DFFA8-F19B-4D1D-91A3-590E8C526763}.Release|Any CPU.ActiveCfg = Release|Any CPU + {357DFFA8-F19B-4D1D-91A3-590E8C526763}.Release|Any CPU.Build.0 = Release|Any CPU + {65BF0CBE-211E-44BD-85CB-ACA4303A5744}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65BF0CBE-211E-44BD-85CB-ACA4303A5744}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65BF0CBE-211E-44BD-85CB-ACA4303A5744}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65BF0CBE-211E-44BD-85CB-ACA4303A5744}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0195FF77-403C-4F80-BEC9-1D24388A7E04} + EndGlobalSection +EndGlobal diff --git a/Controllers/PointsController.cs b/Controllers/PointsController.cs new file mode 100644 index 0000000..e01a421 --- /dev/null +++ b/Controllers/PointsController.cs @@ -0,0 +1,101 @@ +using API_SequentMicrosystems.Models; +using API_SequentMicrosystems.Services; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace API_SequentMicrosystems.Controllers +{ + [Route("points")] + [ApiController] + public class PointsController : ControllerBase + { + private PointsService _PointsService; + + public PointsController(PointsService _PS) + { + _PointsService = _PS; + } + + // GET: api/ + /// + /// Get all saved points + /// + /// + [HttpGet] + public List Get() + { + return _PointsService.GetPoints(); + } + + // GET api//5 + /// + /// Read points from first to specified number + /// + /// max readed points + /// + [HttpGet("{max}")] + public List Get(int max) + { + return _PointsService.GetPoints().Take(max).ToList(); + } + + // GET api//5/5 + /// + /// Read points from and to specified points positions + /// + /// + /// + /// + [HttpGet("{max}/{start}")] + public List Get(int max, int start) + { + return _PointsService.GetPoints().Skip(start).Take(max).ToList(); + } + + //DELETE api/points + /// + /// Delete saved points + /// + [HttpDelete] + public void Delete() + { + _PointsService.DeletePoints(); + } + + //GET api/points/save + /// + /// Save new point + /// + [HttpGet("save")] + public void GetSave() + { + _PointsService.SavePoint(); + } + + //GET api/points/save/300 + /// + /// Start timer to automatic saving points in specified interval + /// + /// + [HttpGet("save/{sec}")] + public void GetSaveSec(int sec) + { + //start autosave timer + } + + //GET api/points/save + /// + /// Stop timer for automatic save points + /// + [HttpDelete("save")] + public void DeleteSaveSec() + { + //stop autosave timer + } + + + + + } +} diff --git a/Controllers/RTDDataAcquisitionController.cs b/Controllers/RTDDataAcquisitionController.cs new file mode 100644 index 0000000..dd2721b --- /dev/null +++ b/Controllers/RTDDataAcquisitionController.cs @@ -0,0 +1,98 @@ +using API_SequentMicrosystems.Services; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace API_SequentMicrosystems.Controllers +{ + [Route("RTDDA")] + [ApiController] + public class RTDDataAcquisitionController : ControllerBase + { + private RTDDAService _RTDDAservice; + public RTDDataAcquisitionController(RTDDAService serv) + { + _RTDDAservice = serv; + } + + // GET: api/ + /// + /// Read data from all configured cards + /// + /// + [HttpGet] + public SortedList Get() + { + return _RTDDAservice.ReadAllConfiguredCard(); + } + + // GET api//All + /// + /// Read data from All RTD cards + /// + /// + [HttpGet("All")] + public SortedList GetAll() + { + return _RTDDAservice.ReadAllCard(); + } + + // GET api//5 + /// + /// Read data from specified card from stack + /// + /// + /// data from specified card + [HttpGet("{stack}")] + public float[] GetAll(byte stack) + { + return _RTDDAservice.ReadCard(stack); + } + + //GET api/RTDDA/Names + /// + /// Get Configured Names of Chanels + /// + /// + [HttpGet("Names")] + public SortedList GetNames() + { + return _RTDDAservice.GetChanelsNames(); + } + + // POST api/ + /// + /// Post configured names of chanels + /// + /// + [HttpPost("Names")] + public void PostNames([FromBody] SortedList data) + { + _RTDDAservice.SetChanelsNames(data); + } + + //GET api/RTDDA/Names/Preconfigured + /// + /// Get preconfigured Names for chanels + /// + /// + [HttpGet("Names/Preconfigured")] + public List GetNamesPreconfigured() + { + return _RTDDAservice.GetPreconfiguratedChanelsNames(); + } + + //POST api/RTDDA/Names/Preconfigured + /// + /// Post preconfigured names for chanels + /// + /// + [HttpPost("Names/Preconfigured")] + public void PostNamesPreconfigured([FromBody] List data) + { + _RTDDAservice.SetPreconfiguratedChanelsNames(data); + } + + + } +} diff --git a/Models/CardsConfig.cs b/Models/CardsConfig.cs new file mode 100644 index 0000000..0ddd48c --- /dev/null +++ b/Models/CardsConfig.cs @@ -0,0 +1,12 @@ +namespace API_SequentMicrosystems.Models +{ + public class CardsConfig + { +#pragma warning disable CS8618 // Pole, které nemůže být null, musí při ukončování konstruktoru obsahovat hodnotu, která není null. Zvažte možnost deklarovat ho jako pole s možnou hodnotou null. + public string ID { get; set; } + public string Name { get; set; } + public string ShortName { get; set; } + public string Levels { get; set; } + public string UpdateRateMsec { get; set; } + } +} diff --git a/Models/PointsModel.cs b/Models/PointsModel.cs new file mode 100644 index 0000000..9e99336 --- /dev/null +++ b/Models/PointsModel.cs @@ -0,0 +1,18 @@ +namespace API_SequentMicrosystems.Models +{ + public class PointsModel + { + public DateTime Time { get; set; } + public SortedList RTDDA { get; set; } + + + + + + + + + + + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..0ff13ef --- /dev/null +++ b/Program.cs @@ -0,0 +1,39 @@ +using API_SequentMicrosystems.Services; + +namespace API_SequentMicrosystems +{ + public class Program + { + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + // Add services to the container. + + builder.Services.AddControllers(); + + builder.Services.AddSingleton(); + + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(); + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (true)//app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(); + } + + app.UseAuthorization(); + + app.Services.GetService(); + + app.MapControllers(); + + app.Run(); + } + } +} diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..170db4c --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:58419", + "sslPort": 0 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5242", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Services/PointsService.cs b/Services/PointsService.cs new file mode 100644 index 0000000..ac7715c --- /dev/null +++ b/Services/PointsService.cs @@ -0,0 +1,95 @@ +using API_SequentMicrosystems.Models; +using Newtonsoft.Json; + +namespace API_SequentMicrosystems.Services +{ + public class PointsService + { + + + private RTDDAService _RTDDAService; + + public PointsService(RTDDAService _RTDDAS) + { + if (!Directory.Exists("Points")) + Directory.CreateDirectory("Points"); + + _RTDDAService = _RTDDAS; + + _points = LoadPoints(); + } + + private List _points; + + /// + /// Load points from File + /// + /// + private List LoadPoints() + { + try + { + #pragma warning disable CS8603 // Může jít o vrácený odkaz null. + return JsonConvert.DeserializeObject>(File.ReadAllText("Points/SavedData.json")); + #pragma warning restore CS8603 // Může jít o vrácený odkaz null. + } + catch + { + return new(); + } + } + + /// + /// Save points to File + /// + private void SavePoints() + { + File.WriteAllText("Points/SavedData.json", JsonConvert.SerializeObject(_points)); + } + + /// + /// Get saved Points + /// + /// + public List GetPoints() + { + return _points; + } + + /// + /// Delete Points + /// + public void DeletePoints() + { + _points = new(); + SavePoints(); + } + + /// + /// Save data/status point + /// + public void SavePoint() + { + PointsModel pm = new PointsModel(); //initialize point object + pm.Time = DateTime.Now; //set time of point created + pm.RTDDA = _RTDDAService.ReadAllCard(); //save RTD data to point + + _points.Add(pm); //add point to list + SavePoints(); //Save updated points + } + + + + + + + + + + + + + + + } +} diff --git a/Services/RTDDataAcquisitionService.cs b/Services/RTDDataAcquisitionService.cs new file mode 100644 index 0000000..ed68205 --- /dev/null +++ b/Services/RTDDataAcquisitionService.cs @@ -0,0 +1,206 @@ +using API_SequentMicrosystems.Models; +using Libs_SequentMicrosystems; +using Newtonsoft.Json; + +namespace API_SequentMicrosystems.Services +{ + public class RTDDAService + { + private RTDStackLevelReader _stackLevelReader = new RTDStackLevelReader(); + public readonly List _stackLevels = new List(); + + public RTDDAService(IConfiguration configuration) + { + if (!Directory.Exists("RTDDA")) + Directory.CreateDirectory("RTDDA"); + + List cardsConfig = configuration.GetSection("Cards").Get>(); + #pragma warning disable CS8604 // Může jít o argument s odkazem null. + CardsConfig config = cardsConfig.Where(x => x.ID == "0").First(); + #pragma warning restore CS8604 // Může jít o argument s odkazem null. + foreach (char c in config.Levels.ToCharArray()) + { + try + { + _stackLevels.Add(byte.Parse(c.ToString())); + } + catch + { + Console.WriteLine($"Char {c} is not convertable to byte"); + } + } + + ChanelsNames = LoadChanelsNames(); //ChanelsNames + PreconfiguredChanelsNames = LoadPreconfiguredChanelsNames(); //ChanelsPreconfiguredNames + } + + /// + /// Read data from all RTD cards + /// + /// data from all RTD cards + public SortedList ReadAllCard() + { + SortedList data = new SortedList(); + + for (byte i = 0; i < 8; i++) //loop for read all stack levels + { + try + { + data.Add(i, ReadCard(i)); //read stack level + } + catch + { + Console.WriteLine($"RTD stack {i} is not available"); + } + + } + + return data; //return data + } + + /// + /// Read data from all configured cards + /// + /// Data from all configuredd Cards + public SortedList ReadAllConfiguredCard() + { + SortedList data = new SortedList(); + + for (byte i = 0; i < 8; i++) //loop for read all stack levels + { + if (_stackLevels.Contains(i)) + { + try + { + data.Add(i, ReadCard(i)); //read stack level + } + catch + { + Console.WriteLine($"RTD stack {i} is not available"); + } + } + } + + return data; //return data + } + + /// + /// Read data from specified card + /// + /// stack level ID + /// Data of selected stack card + public float[] ReadCard(byte stack) + { + try + { + return _stackLevelReader.GetStack(stack); //return data from specified card + } + catch + { + return new float[0]; //if card read get error, return empty array + } + } + + + #region ChanelsName + private SortedList ChanelsNames; + + /// + /// Load Chanels Names from file + /// + /// + private SortedList LoadChanelsNames() + { + try + { + #pragma warning disable CS8603 // Může jít o vrácený odkaz null. + return JsonConvert.DeserializeObject>(File.ReadAllText("RTDDA/Names.json")); + #pragma warning restore CS8603 // Může jít o vrácený odkaz null. + } + catch + { + return new(); + } + } + + /// + /// Save ChanelsNames to FIle + /// + private void SaveChanelsNames() + { + File.WriteAllText("RTDDA/Names.json", JsonConvert.SerializeObject(ChanelsNames)); + } + + /// + /// Get CHanelsNames + /// + /// + public SortedList GetChanelsNames() + { + return ChanelsNames; + } + + /// + /// Save Chanels Names + /// + /// + public void SetChanelsNames(SortedList ChN) + { + ChanelsNames = ChN; + SaveChanelsNames(); + } + + #endregion + + #region PreconfiguredChanelsNames + private List PreconfiguredChanelsNames; + + /// + /// Load Preconfigurated Chanels Names from file + /// + /// + private List LoadPreconfiguredChanelsNames() + { + try + { + #pragma warning disable CS8603 // Může jít o vrácený odkaz null. + return JsonConvert.DeserializeObject>(File.ReadAllText("RTDDA/PNames.json")); + #pragma warning restore CS8603 // Může jít o vrácený odkaz null. + } + catch + { + return new(); + } + } + + /// + /// Save Preconfigurated chanels names to File + /// + private void SavePreconfiguratedChanelsNames() + { + File.WriteAllText("RTDDA/PNames.json", JsonConvert.SerializeObject(PreconfiguredChanelsNames)); + } + + /// + /// Get preconfigured chanels names + /// + /// + public List GetPreconfiguratedChanelsNames() + { + return PreconfiguredChanelsNames.ToList(); + } + + /// + /// Save Preconfigured ChanelsNames + /// + /// + public void SetPreconfiguratedChanelsNames(List ChN) + { + PreconfiguredChanelsNames = ChN; + SavePreconfiguratedChanelsNames(); + } + + #endregion + + } +} diff --git a/appsettings.Development.json b/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..f18bdf9 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,18 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Cards": [ + { + "ID": "0", + "Name": "RTD Data Acquisition 8-Layer Stackable HAT for Raspberry Pi", + "ShortName": "RTDDA", + "Levels": "1", + "UpdateRateMsec": "1000" + } + ] +}