Merge branch 'new/UnderTheHood' of https://bitbucket.org/ncarminati/cms_thermo_active into new/UnderTheHood

This commit is contained in:
Thermo_SIM
2021-02-05 16:30:00 +01:00
36 changed files with 825 additions and 814 deletions
@@ -119,6 +119,8 @@
<sampling>
<thread name="alarms" value="200" />
<thread name="axis" value="200" />
<thread name="channelsIoFast" value="300" />
<thread name="channelsIoSlow" value="5000" />
<thread name="area" value="500" />
<thread name="confReq" value="2000" />
<thread name="expMan" value="30000" />
+50
View File
@@ -30,6 +30,7 @@ using static Thermo.Active.Utils.ExceptionManager;
using System.Windows;
using System.Drawing;
using System.Configuration;
using Thermo.Active.Model.DTOModels.ThIO;
public static class ThreadsFunctions
{
@@ -412,6 +413,55 @@ public static class ThreadsFunctions
ncAdapter.Dispose();
}
}
/// <summary>
/// Lettura valorichannelsIO
/// </summary>
public static void ReadChannelsIoData()
{
NcAdapter ncAdapter = new NcAdapter();
Stopwatch sw = new Stopwatch();
try
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
ManageLibraryError(libraryError);
while (true)
{
sw.Restart();
if (ncAdapter.numericalControl.NC_IsConnected())
{
// Get Data from config and PLC
libraryError = ncAdapter.ReadValIO(out DTOChannelsIOVal currChannelsIoVal);
if (libraryError.errorCode != 0)
ManageLibraryError(libraryError);
else
// Send through signalR
MessageServices.Current.Publish(SEND_CHANNELS_IO_DATA, null, currChannelsIoVal);
}
else
RestoreConnection();
sw.Stop();
//Update thread timer
UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds);
// verifico se periodo rapido o veloce...
int timerAct = RedisController.FastIoSample ? samplMsec("channelsIoFast") : samplMsec("channelsIoSlow");
// Wait
Thread.Sleep(CalcSleepTime(timerAct, (int)sw.ElapsedMilliseconds));
}
}
catch (ThreadAbortException)
{
ncAdapter.Dispose();
}
}
public static void ReadEnabledFunctionality()
{
+1
View File
@@ -36,6 +36,7 @@ namespace Thermo.Active.Core
ThreadsFunctions.ReadScadaData,
ThreadsFunctions.ReadMComandsData,
ThreadsFunctions.ReadAxisInfoData,
ThreadsFunctions.ReadChannelsIoData,
ThreadsFunctions.ReadM154Data // levare?
};
@@ -19,7 +19,7 @@ namespace Thermo.Active.Database.Controllers
private const string machinePowerPath = "Machine:Power";
private const string machineAlarmPath = "Machine:Alarm";
private const string machineEmergencyPath = "Machine:Emergency";
private const string alarmsPath = "Machine:Plc:Condition";
private const string alarmsPath = "Machine:Plc:Condition";
private const string processStatusPath = "Machine:Cnc:CncProcesses:%NN%:Status";
private const string processModePath = "Machine:Cnc:CncProcesses:%NN%:Mode";
private const string processFeedOverridePath = "Machine:Cnc:CncProcesses:%NN%:FeedOverride";
@@ -27,7 +27,7 @@ namespace Thermo.Active.Database.Controllers
private const string processSpeedOverridePath = "Machine:Cnc:CncProcesses:%NN%:SpeedOverride";
private const string datamodelPath = "AdpConf:DataModel";
private const string currentActiveVersionPath = "Machine:Hmi:Version";
private const string currentActiveVersionPath = "Machine:Hmi:Version";
private const string machineAxisPosition = "Machine:Axes:%NN%:CurrentPos";
private const string machineAxisSpeed = "Machine:Axes:%NN%:FeedRate";
private const string machineAxisLoad = "Machine:Axes:%NN%:Load";
@@ -70,7 +70,7 @@ namespace Thermo.Active.Database.Controllers
string redisHash = redUtil.man.redHash(redisAlmEn);
return redUtil.man.redSaveHashDict(redisHash, alarms);
}
public static bool WriteDatamodel(string datamodel)
{
@@ -79,7 +79,7 @@ namespace Thermo.Active.Database.Controllers
}
public static bool WriteDefaultEntry(Dictionary<string, string> entries)
{
foreach (KeyValuePair<string,string> entry in entries)
foreach (KeyValuePair<string, string> entry in entries)
{
if (!redUtil.man.setRSV(redUtil.man.redHash(entry.Key), entry.Value))
return false;
@@ -109,7 +109,7 @@ namespace Thermo.Active.Database.Controllers
string redisHash = redUtil.man.redHash(machineStatusPath);
return redUtil.man.setRSV(redisHash, status.ToString());
}
public static bool WriteCurrentProcessStatus(uint ProductionProcess, string status)
{
string redisHash = redUtil.man.redHash(processStatusPath).Replace("%NN%", ProductionProcess.ToString("00"));
@@ -131,21 +131,21 @@ namespace Thermo.Active.Database.Controllers
if (!redUtil.man.setRSV(redisHash, "100"))
return false;
redisHash = redUtil.man.redHash(processSpeedOverridePath).Replace("%NN%", ProductionProcess.ToString("00"));
if(!redUtil.man.setRSV(redisHash, "100"))
if (!redUtil.man.setRSV(redisHash, "100"))
return false;
return true;
}
public static bool WriteCurrentMachinePowerPath(bool status)
{
string redisHash = redUtil.man.redHash(machinePowerPath);
if(status)
if (status)
return redUtil.man.setRSV(redisHash, "true");
else
return redUtil.man.setRSV(redisHash, "false");
}
public static bool WriteCurrentMachineAlarmPath(bool status)
{
string redisHash = redUtil.man.redHash(machineAlarmPath);
@@ -154,7 +154,7 @@ namespace Thermo.Active.Database.Controllers
else
return redUtil.man.setRSV(redisHash, "false");
}
public static bool WriteCurrentMachineEmergencyPath(bool status)
{
string redisHash = redUtil.man.redHash(machineEmergencyPath);
@@ -183,14 +183,41 @@ namespace Thermo.Active.Database.Controllers
redUtil.man.ListPush(redisHash, msg);
return true;
}
public static string ReadValue(string msgKey)
{
string redisHash = redUtil.man.redHash(msgKey);
return redUtil.man.getRSV(redisHash);
}
public static bool WriteValue(string msgKey, string msg, int ttlSec)
{
string redisHash = redUtil.man.redHash(msgKey);
redUtil.man.setRSV(redisHash, msg, ttlSec);
return true;
}
public static bool FastIoSample
{
get
{
var currVal = ReadValue("FastIoSample");
bool answ = !string.IsNullOrEmpty(currVal);
return answ;
}
set
{
// TTL: se true 5 min, altrimenti 1 sec
int ttlSec = value ? 60 * 5 : 1;
WriteValue("FastIoSample", "Active", ttlSec);
}
}
public static bool WriteCurrentAxisStatus(Dictionary<int, DTOAxisInfoModel> axis)
{
foreach(KeyValuePair<int, DTOAxisInfoModel> asse in axis)
foreach (KeyValuePair<int, DTOAxisInfoModel> asse in axis)
{
string redisHash = redUtil.man.redHash(machineAxisName).Replace("%NN%", asse.Value.ID.ToString("00"));
if(redUtil.man.getRSV(redisHash) != null)
if (redUtil.man.getRSV(redisHash) != null)
{
redisHash = redUtil.man.redHash(machineAxisPosition).Replace("%NN%", asse.Value.ID.ToString("00"));
if (!redUtil.man.setRSV(redisHash, asse.Value.position.ToString()))
@@ -203,7 +230,7 @@ namespace Thermo.Active.Database.Controllers
redisHash = redUtil.man.redHash(machineAxisLoad).Replace("%NN%", asse.Value.ID.ToString("00"));
if (!redUtil.man.setRSV(redisHash, asse.Value.load.ToString()))
return false;
}
}
}
return true;
}
+1
View File
@@ -377,6 +377,7 @@ namespace Thermo.Active.Model
public const string SEND_NC_SOFTKEYS_DATA = "SEND_NC_SOFTKEYS_DATA";
public const string SEND_HEADS_DATA = "SEND_HEADS_DATA";
public const string SEND_AXIS_INFO = "SEND_AXIS_INFO";
public const string SEND_CHANNELS_IO_DATA = "SEND_CHANNELS_IO_DATA";
public const string SEND_ACTIVE_PROGRAM_DATA = "SEND_ACTIVE_PROGRAM_DATA";
public const string SEND_QUEUE_DATA = "SEND_QUEUE_DATA";
public const string SEND_M155_DATA = "SEND_M155_DATA";
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Thermo.Active.Model.DTOModels.ThIO
{
public class DTOCycleLog
{
public List<CycleEvent> events { get; set; } = new List<CycleEvent>();
}
public class CycleEvent
{
public DateTime dtEvent { get; set; }
public int code { get; set; } = 0;
}
}
@@ -10,7 +10,15 @@ namespace Thermo.Active.Model.DTOModels.ThIO
{
public int Id { get; set; } = 0;
}
public class IoItemConf:IoItem
public class IoItemDigi : IoItem
{
public bool value { get; set; } = false;
}
public class IoItemAnal : IoItem
{
public int value { get; set; } = 0;
}
public class IoItemConf : IoItem
{
public string Bank { get; set; } = "0";
public string Position { get; set; } = "0";
@@ -114,9 +114,10 @@
<Compile Include="DTOModels\DTOMessageModel.cs" />
<Compile Include="DTOModels\ThAxes\DTOAxisInfoModel.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsIOVal.cs" />
<Compile Include="DTOModels\ThIO\DTOCycleLog.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsSetup.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsIO.cs" />
<Compile Include="DTOModels\ThIO\IoBaseConf.cs" />
<Compile Include="DTOModels\ThIO\IoItemConf.cs" />
<Compile Include="DTOModels\ThModules\DTOModulesBlock.cs" />
<Compile Include="DTOModels\ThProd\DTOProdInfo.cs" />
<Compile Include="DTOModels\ThProd\DTOThermoPanelProd.cs" />
+122 -5
View File
@@ -2168,7 +2168,7 @@ namespace Thermo.Active.NC
return libraryError;
}
/// <summary>
/// Restitusice intero set dati IO Channels (conf + valori)
/// Restituisce intero set dati IO Channels (conf + valori)
/// </summary>
/// <param name="currChannelsIO"></param>
/// <returns></returns>
@@ -2272,11 +2272,9 @@ namespace Thermo.Active.NC
{
// lettura da PLC
Dictionary<int, ThermoModels.ModuleBlock> currModBlock = new Dictionary<int, ThermoModels.ModuleBlock>();
ThermoModels.ChanIOVis currThermoIOVis = new ThermoModels.ChanIOVis();
ThermoModels.ChanIOVal currThermoIOVal = new ThermoModels.ChanIOVal();
ThermoModels.ChanIOFor currThermoIOFor = new ThermoModels.ChanIOFor();
ThermoModels.ChanIOValFor currThermoIOValFor = new ThermoModels.ChanIOValFor();
libraryError = numericalControl.PLC_RIOChannelsConf(ref currThermoIOVis);
libraryError = numericalControl.PLC_RIOChannelsVal(ref currThermoIOVal, ref currThermoIOFor, ref currThermoIOValFor);
// setup da config
@@ -3340,7 +3338,7 @@ namespace Thermo.Active.NC
/// </summary>
/// <param name="updtRecipe">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scriottura multi parametri singoli</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
public CmsError WriteRecipeParametersToPLC(Dictionary<string, DTORecipeParam> updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3370,7 +3368,7 @@ namespace Thermo.Active.NC
/// </summary>
/// <param name="updtRecipe">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scriottura multi parametri singoli</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
public CmsError WriteRecipeParams(Dictionary<string, DTORecipeParam> updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3379,6 +3377,125 @@ namespace Thermo.Active.NC
return libraryError;
}
/// <summary>
/// ChannelsID: write DO to PLC (values + setForce)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError Write_IO_DO_ToPLC(Dictionary<int, bool> newValues)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
// scrivo!
CmsError libraryError = numericalControl.PLC_W_IO_DO_Val(newValues);
if (libraryError.IsError())
return libraryError;
}
else
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// ChannelsID: write AO to PLC (values + setForce)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError Write_IO_AO_ToPLC(Dictionary<int, int> newValues)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
// scrivo!
CmsError libraryError = numericalControl.PLC_W_IO_AO_Val(newValues);
if (libraryError.IsError())
return libraryError;
}
else
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for DO to PLC (setForce = false)
/// </summary>
/// <param name="channels">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError WriteReset_IO_DO_ToPLC(List<int> channels)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
Dictionary<int, bool> newForced = new Dictionary<int, bool>();
foreach (var item in channels)
{
newForced.Add(item, false);
}
// scrivo!
CmsError libraryError = numericalControl.PLC_W_IO_DO_Reset(newForced);
if (libraryError.IsError())
return libraryError;
}
else
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for AO to PLC (setForce = false)
/// </summary>
/// <param name="channels">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError WriteReset_IO_AO_ToPLC(List<int> channels)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
Dictionary<int, bool> newForced = new Dictionary<int, bool>();
foreach (var item in channels)
{
newForced.Add(item, false);
}
// scrivo!
CmsError libraryError = numericalControl.PLC_W_IO_AO_Reset(newForced);
if (libraryError.IsError())
return libraryError;
}
else
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for DO + AO to PLC (setForce = false)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
public CmsError WriteReset_IO_ALL_ToPLC()
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
// scrivo!
CmsError libraryError = numericalControl.PLC_W_IO_ResetAll();
if (libraryError.IsError())
return libraryError;
}
else
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// Scrive le softkey star
/// </summary>
+116 -110
View File
@@ -1,6 +1,9 @@
using Swashbuckle.Application;
using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web.Http;
using System.Web.Http.Description;
@@ -33,129 +36,132 @@ namespace Thermo.Active
//
c.SingleApiVersion("v1", "ThermoActive");
// If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
//
//c.PrettyPrint();
// If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
//
//c.PrettyPrint();
// If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
// In this case, you must provide a lambda that tells Swashbuckle which actions should be
// included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
// returns an "Info" builder so you can provide additional metadata per API version.
//
//c.MultipleApiVersions(
// (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
// (vc) =>
// {
// vc.Version("v2", "Swashbuckle Dummy API V2");
// vc.Version("v1", "Swashbuckle Dummy API V1");
// });
// If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
// In this case, you must provide a lambda that tells Swashbuckle which actions should be
// included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
// returns an "Info" builder so you can provide additional metadata per API version.
//
//c.MultipleApiVersions(
// (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
// (vc) =>
// {
// vc.Version("v2", "Swashbuckle Dummy API V2");
// vc.Version("v1", "Swashbuckle Dummy API V1");
// });
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
// at the document or operation level to indicate which schemes are required for an operation. To do this,
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
//
//c.BasicAuth("basic")
// .Description("Basic HTTP Authentication");
//
// NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
//c.ApiKey("apiKey")
// .Description("API Key Authentication")
// .Name("apiKey")
// .In("header");
//
//c.OAuth2("oauth2")
// .Description("OAuth2 Implicit Grant")
// .Flow("implicit")
// .AuthorizationUrl("http://localhost:9000/token")
// .TokenUrl("http://localhost:9000/token")
// .Scopes(scopes =>
// {
// scopes.Add("read", "Read access to protected resources");
// scopes.Add("write", "Write access to protected resources");
// });
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
// at the document or operation level to indicate which schemes are required for an operation. To do this,
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
//
//c.BasicAuth("basic")
// .Description("Basic HTTP Authentication");
//
// NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
//c.ApiKey("apiKey")
// .Description("API Key Authentication")
// .Name("apiKey")
// .In("header");
//
//c.OAuth2("oauth2")
// .Description("OAuth2 Implicit Grant")
// .Flow("implicit")
// .AuthorizationUrl("http://localhost:9000/token")
// .TokenUrl("http://localhost:9000/token")
// .Scopes(scopes =>
// {
// scopes.Add("read", "Read access to protected resources");
// scopes.Add("write", "Write access to protected resources");
// });
// Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
//c.IgnoreObsoleteActions();
// Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
//c.IgnoreObsoleteActions();
// Each operation be assigned one or more tags which are then used by consumers for various reasons.
// For example, the swagger-ui groups operations according to the first tag of each operation.
// By default, this will be controller name but you can use the "GroupActionsBy" option to
// override with any value.
//
//c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
// Each operation be assigned one or more tags which are then used by consumers for various reasons.
// For example, the swagger-ui groups operations according to the first tag of each operation.
// By default, this will be controller name but you can use the "GroupActionsBy" option to
// override with any value.
//
//c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
// You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
// the order in which operations are listed. For example, if the default grouping is in place
// (controller name) and you specify a descending alphabetic sort order, then actions from a
// ProductsController will be listed before those from a CustomersController. This is typically
// used to customize the order of groupings in the swagger-ui.
//
//c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
// You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
// the order in which operations are listed. For example, if the default grouping is in place
// (controller name) and you specify a descending alphabetic sort order, then actions from a
// ProductsController will be listed before those from a CustomersController. This is typically
// used to customize the order of groupings in the swagger-ui.
//
//c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
// If you annotate Controllers and API Types with
// Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
// those comments into the generated docs and UI. You can enable this by providing the path to one or
// more Xml comment files.
//
//c.IncludeXmlComments(GetXmlCommentsPath());
// If you annotate Controllers and API Types with
// Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
// those comments into the generated docs and UI. You can enable this by providing the path to one or
// more Xml comment files.
//
//c.IncludeXmlComments(GetXmlCommentsPath());
//var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
//var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
//c.IncludeXmlComments(xmlPath);
// Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
// exposed in your API. However, there may be occasions when more control of the output is needed.
// This is supported through the "MapType" and "SchemaFilter" options:
//
// Use the "MapType" option to override the Schema generation for a specific type.
// It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
// While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
// It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
// use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
// complex Schema, use a Schema filter.
//
//c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
// Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
// exposed in your API. However, there may be occasions when more control of the output is needed.
// This is supported through the "MapType" and "SchemaFilter" options:
//
// Use the "MapType" option to override the Schema generation for a specific type.
// It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
// While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
// It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
// use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
// complex Schema, use a Schema filter.
//
//c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
// If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
// specific type, you can wire up one or more Schema filters.
//
//c.SchemaFilter<ApplySchemaVendorExtensions>();
// If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
// specific type, you can wire up one or more Schema filters.
//
//c.SchemaFilter<ApplySchemaVendorExtensions>();
// In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
// Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
// works well because it prevents the "implementation detail" of type namespaces from leaking into your
// Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
// need to opt out of this behavior to avoid Schema Id conflicts.
//
//c.UseFullTypeNameInSchemaIds();
// In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
// Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
// works well because it prevents the "implementation detail" of type namespaces from leaking into your
// Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
// need to opt out of this behavior to avoid Schema Id conflicts.
//
//c.UseFullTypeNameInSchemaIds();
// Alternatively, you can provide your own custom strategy for inferring SchemaId's for
// describing "complex" types in your API.
//
//c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
// Alternatively, you can provide your own custom strategy for inferring SchemaId's for
// describing "complex" types in your API.
//
//c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
// Set this flag to omit schema property descriptions for any type properties decorated with the
// Obsolete attribute
//c.IgnoreObsoleteProperties();
// Set this flag to omit schema property descriptions for any type properties decorated with the
// Obsolete attribute
//c.IgnoreObsoleteProperties();
// In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
// You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
// enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
// approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
//
//c.DescribeAllEnumsAsStrings();
// In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
// You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
// enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
// approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
//
//c.DescribeAllEnumsAsStrings();
// Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
//
// Post-modify Operation descriptions once they've been generated by wiring up one or more
// Operation filters.
//
//c.OperationFilter<AddDefaultResponse>();
//
// If you've defined an OAuth2 flow as described above, you could use a custom filter
// to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
// to execute the operation
//
c.OperationFilter(() => new AddRequiredHeaderParameter());
// Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
//
// Post-modify Operation descriptions once they've been generated by wiring up one or more
// Operation filters.
//
//c.OperationFilter<AddDefaultResponse>();
//
// If you've defined an OAuth2 flow as described above, you could use a custom filter
// to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
// to execute the operation
//
c.OperationFilter(() => new AddRequiredHeaderParameter());
// Post-modify the entire Swagger document by wiring up one or more Document filters.
// This gives full control to modify the final SwaggerDocument. You should have a good understanding of
@@ -10,6 +10,7 @@ using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using System.Windows.Media.Animation;
using TeamDev.SDK.MVVM;
using Thermo.Active.Config;
@@ -34,26 +35,35 @@ namespace Thermo.Active.Controllers.WebApi
/// </summary>
protected static NcAdapter ncAdapter = new NcAdapter();
[ResponseType(typeof(DTOCycleLog))]
[Route("cyclelog"), HttpGet]
public IHttpActionResult GetCycleLog()
{
// // Try connection
CmsError libraryError = ncAdapter.Connect();
DTOCycleLog currCycleLog = new DTOCycleLog();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"ncAdapter Not connected! | GetCycleLog | {libraryError.exception}");
}
libraryError = ncAdapter.GetCycleLog(out Dictionary<DateTime, int> machineLog);
libraryError = ncAdapter.GetCycleLog(out Dictionary<DateTime, int> cycleLog);
foreach (var item in cycleLog)
{
currCycleLog.events.Add(new CycleEvent() { dtEvent=item.Key, code=item.Value });
}
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"GetCycleLog error | {libraryError.exception}");
return BadRequest(libraryError.localizationKey);
}
return Ok(machineLog);
return Ok(currCycleLog);
}
[ResponseType(typeof(DTOChannelsIO))]
[Route("channels_io"), HttpGet]
public IHttpActionResult GetChannelsIO()
{
@@ -76,6 +86,8 @@ namespace Thermo.Active.Controllers.WebApi
// ritorno!
return Ok(ChannelsIO);
}
[ResponseType(typeof(DTOChannelsIOVal))]
[Route("channels_io_val"), HttpGet]
public IHttpActionResult GetChannelsIoVal()
{
@@ -98,5 +110,169 @@ namespace Thermo.Active.Controllers.WebApi
// ritorno!
return Ok(ChannelsIOVal);
}
[Route("io_force_ch_do"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ForceChDO(List<IoItemDigi> updVal)
{
if (updVal != null)
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"NC Not connected! | ForceChDO | {libraryError.exception}");
return InternalServerError();
}
if (updVal.Count > 0)
{
// converto
Dictionary<int, bool> parametersList = new Dictionary<int, bool>();
foreach (var item in updVal)
{
parametersList.Add(item.Id, item.value);
}
// scrivo sul PLC con i parametri specificati
ncAdapter.Write_IO_DO_ToPLC(parametersList);
}
// ritorno solo fatto!
return Ok();
}
else
{
ThermoActiveLogger.LogError($"ForceChDO updatedVal null | Empty Parameters");
return BadRequest();
}
}
[Route("io_force_ch_ao"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ForceChAO(List<IoItemAnal> updVal)
{
if (updVal != null)
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"NC Not connected! | ForceChAO | {libraryError.exception}");
return InternalServerError();
}
if (updVal.Count > 0)
{
Dictionary<int, int> parametersList = new Dictionary<int, int>();
foreach (var item in updVal)
{
parametersList.Add(item.Id, item.value);
}
// scrivo sul PLC con i parametri specificati
ncAdapter.Write_IO_AO_ToPLC(parametersList);
}
// ritorno solo fatto!
return Ok();
}
else
{
ThermoActiveLogger.LogError($"ForceChAO parametersList null | Empty Parameters");
return BadRequest();
}
}
[Route("io_reset_ch_do"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ResetChDO(List<int> parametersList)
{
if (parametersList != null)
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"NC Not connected! | ResetChDO | {libraryError.exception}");
return InternalServerError();
}
if (parametersList.Count > 0)
{
// scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
ncAdapter.WriteReset_IO_DO_ToPLC(parametersList);
}
// ritorno solo fatto!
return Ok();
}
else
{
ThermoActiveLogger.LogError($"ResetChDO parametersList null | Empty Parameters");
return BadRequest();
}
}
/// <summary>
/// Reset "force bit" on selected channels
/// </summary>
/// <param name="parametersList">List of channels index, zero based</param>
/// <returns></returns>
[Route("io_reset_ch_ao"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ResetChAO(List<int> parametersList)
{
if (parametersList != null)
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"NC Not connected! | ResetChAO | {libraryError.exception}");
return InternalServerError();
}
if (parametersList.Count > 0)
{
// scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
ncAdapter.WriteReset_IO_AO_ToPLC(parametersList);
}
// ritorno solo fatto!
return Ok();
}
else
{
ThermoActiveLogger.LogError($"ResetChAO parametersList null | Empty Parameters");
return BadRequest();
}
}
[Route("io_reset_all_ch"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ResetAllCh()
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.IsError())
{
ThermoActiveLogger.LogError($"NC Not connected! | ResetAllCh | {libraryError.exception}");
return InternalServerError();
}
// scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
ncAdapter.WriteReset_IO_ALL_ToPLC();//parametersList);
// ritorno solo fatto!
return Ok();
}
[Route("io_sample_fast"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult SetFastSample(bool value)
{
// imposta (su redis) campionamento RAPIDO/lento x IO...
RedisController.FastIoSample = value;
// ritorno solo fatto!
return Ok();
}
}
}
@@ -64,6 +64,10 @@ namespace Thermo.Active.Listeners
{
SignalRListener.SendThermoAxisInfoData(a);
}));
infos.Add(MessageServices.Current.Subscribe(SEND_CHANNELS_IO_DATA, (a, b) =>
{
SignalRListener.SendThermoChannelsIoData(a);
}));
infos.Add(MessageServices.Current.Subscribe(SEND_ACTIVE_PROGRAM_DATA, (a, b) =>
{
SignalRListener.SendActiveProgramData(a);
@@ -13,6 +13,7 @@ using Thermo.Active.Model.DTOModels;
using Thermo.Active.Model.DTOModels.AlarmModels;
using Thermo.Active.Model.DTOModels.Scada;
using Thermo.Active.Model.DTOModels.ThAxes;
using Thermo.Active.Model.DTOModels.ThIO;
using Thermo.Active.Model.DTOModels.ThModules;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
@@ -59,7 +60,7 @@ namespace Thermo.Active.Listeners.SignalR
{
RedisController.WriteCurrentMachineEmergencyPath(LastPowerOnData.PrePowerOn.EmergencyButtons.Active);
}
}
}
@@ -456,8 +457,8 @@ namespace Thermo.Active.Listeners.SignalR
LastProdPanelData = currProdPanel;
var context = GlobalHost.ConnectionManager.GetHubContext<NcHub>();
context.Clients.Group("ncData").prodPanelData(currProdPanel);
context.Clients.Group("ncData").prodPanelData(currProdPanel);
if (Config.ServerConfig.ServerStartupConfig.CmsConnectReady)
{
if (newPiece)
@@ -508,8 +509,8 @@ namespace Thermo.Active.Listeners.SignalR
RedisController.WriteCurrentMachineStatus(CMSConnectConstants.ConvertThermoToConnectStatus(currProdCycle.Status));
RedisController.WriteCurrentMachinePowerPath(CMSConnectConstants.ConvertThermoToConnectPower(currProdCycle.Status));
RedisController.WriteCurrentProcessStatus(1,CMSConnectConstants.ConvertThermoToConnectProcessStatus(currProdCycle.Status));
RedisController.WriteCurrentProcessMode(1,CMSConnectConstants.ConvertThermoToConnectProcessMode(currProdCycle.Mode));
RedisController.WriteCurrentProcessStatus(1, CMSConnectConstants.ConvertThermoToConnectProcessStatus(currProdCycle.Status));
RedisController.WriteCurrentProcessMode(1, CMSConnectConstants.ConvertThermoToConnectProcessMode(currProdCycle.Mode));
}
@@ -551,6 +552,65 @@ namespace Thermo.Active.Listeners.SignalR
}
}
public static void SendThermoChannelsIoData(object channelsIoData)
{
DTOChannelsIOVal currChannelsIoData = channelsIoData as DTOChannelsIOVal;
DTOChannelsIOVal diffChannelsData = new DTOChannelsIOVal();
// processing differenze DI
foreach (var item in currChannelsIoData.DI)
{
// recupero
var element = LastChannelsIoData.DI.Find(x => x.Id == item.Id);
if ((element == null) || (!item.Value.Equals(element)))
{
diffChannelsData.DI.Add(item);
}
}
// processing differenze DO
foreach (var item in currChannelsIoData.DO)
{
// recupero
var element = LastChannelsIoData.DO.Find(x => x.Id == item.Id);
if ((element == null) || (!item.Value.Equals(element)))
{
diffChannelsData.DO.Add(item);
}
}
// processing differenze AI
foreach (var item in currChannelsIoData.AI)
{
// recupero
var element = LastChannelsIoData.AI.Find(x => x.Id == item.Id);
if ((element == null) || (!item.Value.Equals(element)))
{
diffChannelsData.AI.Add(item);
}
}
// processing differenze AO
foreach (var item in currChannelsIoData.AO)
{
// recupero
var element = LastChannelsIoData.AO.Find(x => x.Id == item.Id);
if ((element == null) || (!item.Value.Equals(element)))
{
diffChannelsData.AO.Add(item);
}
}
// se ho differenze invio!
if (diffChannelsData.DI.Count + diffChannelsData.DO.Count + diffChannelsData.AI.Count + diffChannelsData.AO.Count > 0)
{
// salvo update CLONANDO
LastChannelsIoData.DI = currChannelsIoData.DI.Clone();
LastChannelsIoData.DO = currChannelsIoData.DO.Clone();
LastChannelsIoData.AI = currChannelsIoData.AI.Clone();
LastChannelsIoData.AO = currChannelsIoData.AO.Clone();
var context = GlobalHost.ConnectionManager.GetHubContext<NcHub>();
context.Clients.Group("ncData").channelsIoVal(diffChannelsData);
}
}
public static void SetGatewayRebootStatus(object status)
{
string msg = status.ToString();
@@ -1,9 +1,11 @@
using CMS_CORE_Library.Models;
using System;
using System.Collections.Generic;
using Thermo.Active.Model.DTOModels;
using Thermo.Active.Model.DTOModels.AlarmModels;
using Thermo.Active.Model.DTOModels.Scada;
using Thermo.Active.Model.DTOModels.ThAxes;
using Thermo.Active.Model.DTOModels.ThIO;
using Thermo.Active.Model.DTOModels.ThModules;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
@@ -46,6 +48,8 @@ namespace Thermo.Active.Listeners
public static DTOThermoPanelProd LastProdPanelData = new DTOThermoPanelProd();
// Oggetti per assi THERMO
public static Dictionary<int, DTOAxisInfoModel> LastAxisInfoData = new Dictionary<int, DTOAxisInfoModel>();
// Oggetti x Valori Channels IO
public static DTOChannelsIOVal LastChannelsIoData = new DTOChannelsIOVal();
public static bool LastIsNcConnected = false;
}
+1 -1
View File
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.1.152")]
[assembly: AssemblyVersion("1.1.156")]
@@ -1,10 +1,11 @@
// math: always
@import url(../../libs/font-awesome/css/font-awesome.css);
@import url(../../libs/glyphicons/styles/glyphicons.css);
@import "base/layout.less";
@import "iziToast.min.css";
body {
font-family: 'Work Sans', sans-serif;
font-family: "Work Sans", sans-serif;
}
.t-loading {
@@ -21,7 +22,6 @@ body {
top: 80px;
}
.iziToast {
background-color: @color-white2;
border-color: @color-white2;
@@ -44,7 +44,7 @@ body {
background-color: @color-scarlet;
}
.iziToast>.iziToast-progressbar {
.iziToast > .iziToast-progressbar {
background-color: rgba(255, 255, 255, 0.6);
}
@@ -59,7 +59,6 @@ body {
margin-top: 60px;
}
.login-form .login-avatar {
height: 88px;
width: 88px;
@@ -75,4 +74,4 @@ body {
font-family: Arial, sans-serif;
font-weight: bold;
text-transform: uppercase;
}
}
@@ -2,7 +2,7 @@
"env": "development",
"api": {
"enabled": true,
"apiServerUrl": "http://95.236.130.105:9000/"
"apiServerUrl": "http://seriate.steamware.net:9000/"
},
"allUIVisible": false
}
+1 -1
View File
@@ -13,7 +13,7 @@
<script src="Scripts/jquery.mousewheel.js"></script>
<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="Scripts/raphael-2.1.4.min.js"></script>
<script src="http://95.236.130.105:9000/signalr/hubs" async></script>
<script src="http://seriate.steamware.net:9000//signalr/hubs" async></script>
<link href="assets/styles/style.css" rel="stylesheet" />
</head>
+7 -10
View File
@@ -23,17 +23,14 @@
<modal-container containerName="modal-login" name="modal-login"></modal-container>
<keyboard></keyboard>
<div class="window-buttons" :class="{prioritize: prioritizeWindowsButtons, 'blur':(applyBlurNc && !prioritizeWindowsButtons)}">
<button
class="gray square close"
@click="sendMessage('hide')"
>-</button>
<button
class="gray square close"
@click="sendMessage('close')"
>&times;</button>
<div
class="window-buttons"
:class="{prioritize: prioritizeWindowsButtons, 'blur':(applyBlurNc && !prioritizeWindowsButtons)}"
>
<button class="gray square close" @click="sendMessage('hide')">-</button>
<button class="gray square close" @click="sendMessage('close')">&times;</button>
</div>
<modal-container name="modal" :class="{'blur':applyBlurNc}"></modal-container>
<modal-container name="modal" :class="{'blur':applyBlurNc}"></modal-container>
<modal-nc-container name="modal-nc"></modal-nc-container>
</div>
</template>
@@ -1,9 +1,5 @@
@import "../../../../variable.less";
span {
display: inline-block;
}
.log-assi-table {
width: 1384px;
height: 886px;
@@ -1,7 +1,5 @@
@import "../../../variable.less";
span {
display: inline-block;
}
.column-page-header {
width: 672px;
@@ -23,4 +23,8 @@ export default class IO extends Vue {
return store.state.underTheHood.ioChannelsConfig;
}
scrollto(key) {
document.getElementById(key).scrollIntoView();
}
}
@@ -6,6 +6,7 @@
<a href>Pinned</a>
<template v-for="(group, idx) in ['di','ai']">
<a
@click="scrollto(`input-${group}`)"
class="upper"
v-for="(inputid, idx2) in config[group]"
:key="`h-${idx}-${idx2}`"
@@ -21,6 +22,7 @@
<a href>Pinned</a>
<template v-for="(group, idx) in ['do','ao']">
<a
@click="scrollto(`output-${group}`)"
class="upper"
v-for="(inputid, idx2) in config[group]"
:key="`h-${idx}-${idx2}`"
@@ -16,7 +16,8 @@ td {
}
}
.value-button-input-container-off {
.value-button-input-container-off,
.value-button-input-container-on {
width: 48px;
height: 25px;
margin: 20px 10px 19px 10px;
@@ -39,20 +40,5 @@ td {
}
.value-button-input-container-on {
width: 48px;
height: 25px;
margin: 20px 10px 19px 10px;
padding: 3px 0;
border-radius: 2px;
float: right;
background-color: @clear-blue;
&-label {
width: 48px;
height: 19px;
padding: 2px 0 0 0px;
text-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
font-size: 16px;
text-align: center;
color: #e8e8e8;
}
}
@@ -1,9 +1,25 @@
@import "../../../variable.less";
span {
display: inline-block;
.button-details {
width: 93px;
padding: 14px 0px 13px 0px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 2px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.4);
background-image: linear-gradient(to bottom, #818a8f 0%, #42494e 98%);
cursor: pointer;
> label {
font-size: 18px;
font-weight: 500;
color: @very-light-pink;
}
}
.log-ciclo-automatico-table {
tbody tr:nth-child(odd) {
background-color: @fill-under-grey-3-2;
@@ -1,6 +1,6 @@
<template>
<div class="main-container">
<div class="column-page">
<div class="column-page-one-column">
<LogCicloAutomaticoTable></LogCicloAutomaticoTable>
</div>
</div>
@@ -1,186 +1,30 @@
@import "../../../../variable.less";
span {
display: inline-block;
.date {
width: 212px;
}
.log-ciclo-automatico-table {
width: 1384px;
height: 886px;
margin: 20px 20px 0 20px;
thead {
height: 34px;
opacity: 0.5;
background-color: @fill-under-grey-1-2;
}
th {
display: inline-block;
}
tbody {
overflow-y: scroll;
height: 752px;
tr {
display: inline-block;
width: 1358px;
height: 64px;
float: left;
&-inner {
width: 1358px;
height: 64px;
margin: 34px 26px 0 0;
padding: 0 2px 0 10px;
}
}
}
}
.date-ciclo {
width: 63px;
height: 12px;
margin: 10px 149px 12px 9px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
color: @white;
text-align: left !important;
float: left;
&-inner {
width: 177px;
height: 16px;
margin: 24px 0px 0px 10px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
float: left;
text-align: left;
color: @very-light-pink;
}
}
.class-ciclo {
width: 63px;
height: 12px;
margin: 10px 36px 12px 0px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: center;
float: left;
color: @white;
&-inner {
width: 35px;
height: 16px;
margin: 24px 0px 0px 47px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
float: left;
color: @very-light-pink;
}
}
.recipe-ciclo {
width: 63px;
height: 12px;
margin: 10px 108px 12px 0px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
float: left;
color: @white;
&-inner {
width: 121px;
height: 16px;
margin: 24px 0px 0px 51px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
float: left;
color: @very-light-pink;
}
}
.message-ciclo {
width: 114px;
height: 12px;
margin: 10px 0px 12px 0px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
float: left;
text-align: left !important;
color: @white;
&-inner {
.message {
width: 751px;
height: 64px;
margin: 18px 0px 0px 50px;
}
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
float: left;
text-align: initial;
color: @very-light-pink;
th,
td {
&.ciclo-date {
width: 212px;
max-width: 212px;
}
&.ciclo-message {
width: 751px;
max-width: 751px;
}
&.ciclo-recipe {
width: 171px;
max-width: 171px;
}
}
.button-details {
width: 99px;
float: right;
display: flex;
justify-content: center;
padding: 14px 0px 13px 0px;
margin: 8px 8px 8px 8px;
object-fit: contain;
border-radius: 2px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.4);
background-image: linear-gradient(to bottom, #818a8f 0%, #42494e 98%);
cursor: pointer;
&-label {
width: 62px;
height: 21px;
object-fit: contain;
font-size: 18px;
font-weight: 500;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
@@ -1,40 +1,29 @@
<template>
<div>
<table class="log-ciclo-automatico-table">
<div class="one-column-table-container scrollable">
<table>
<thead>
<tr>
<th class="date-ciclo">Date</th>
<th class="class-ciclo">Class</th>
<th class="recipe-ciclo">Recipe</th>
<th class="message-ciclo">Message</th>
<th class="ciclo-date">Date</th>
<th>Class</th>
<th class="ciclo-recipe">Recipe</th>
<th class="ciclo-message">Message</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) of rowData" :key="i" class="tr-inner">
<td>
<span class="date-ciclo-inner">
{{ item.date }}
</span>
</td>
<td>
<span class="class-ciclo-inner">
{{ item.class }}
</span>
</td>
<td>
<span class="recipe-ciclo-inner">
{{ item.recipe }}
</span>
</td>
<td>
<span class="message-ciclo-inner">
{{ item.message }}
</span>
<span class="button-details" @click="goToDetails()">
<span class="button-details-label">Details</span>
</span>
</td>
</tr>
<template v-for="(item, idx) in rowData">
<tr :key="`c-${idx}`">
<td>{{ item.date }}</td>
<td>{{ item.class }}</td>
<td>{{ item.recipe }}</td>
<td>{{ item.message }}</td>
<td>
<span class="button-details">
<label>Details</label>
</span>
</td>
</tr>
</template>
</tbody>
</table>
</div>
@@ -1,6 +1,6 @@
<template>
<div class="main-container">
<div class="column-page">
<div class="column-page-one-column">
<LogMisurazioniTable></LogMisurazioniTable>
</div>
</div>
@@ -1,163 +1,23 @@
@import "../../../../variable.less";
span {
display: inline-block;
}
.log-misurazioni-table {
width: 1384px;
height: 886px;
margin: 20px 20px 0 20px;
thead {
height: 34px;
opacity: 0.5;
background-color: @fill-under-grey-1-2;
th,
td {
&.misurazioni-value {
width: 322px;
max-width: 322px;
}
th {
display: inline-block;
&.misurazioni-recipe {
width: 539px;
max-width: 539px;
}
tbody tr:nth-child(odd) {
background-color: @fill-under-grey-3-2;
&.misurazioni-date {
width: 313px;
max-width: 313px;
}
tbody tr:nth-child(even) {
background-color: @fill-under-grey-1-2;
}
tbody {
overflow-y: scroll;
height: 752px;
tr {
display: inline-block;
width: 1358px;
height: 64px;
float: left;
&-inner {
width: 1358px;
height: 64px;
margin: 34px 26px 0 0;
padding: 0 2px 0 10px;
}
}
&.misurazioni-type {
width: 187px;
max-width:187px;
}
}
.date-misurazioni {
width: 63px;
height: 12px;
margin: 10px 0px 12px 9px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
color: @white;
text-align: left !important;
float: left;
&-inner {
width: 164px;
height: 16px;
margin: 24px 0px 24px 10px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: left !important;
float: left;
color: @very-light-pink;
}
}
.recipe-misurazioni {
width: 63px;
height: 12px;
margin: 10px 0px 12px 267px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: left;
float: left;
color: @white;
&-inner {
width: 121px;
height: 16px;
margin: 24px 0px 24px 139px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center !important;
float: left;
color: @very-light-pink;
}
}
.type-misurazioni {
width: 63px;
height: 12px;
margin: 10px 0 12px 448px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: left !important;
float: left;
color: @white;
&-inner {
width: 48px;
height: 16px;
margin: 24px 0px 24px 410px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
float: left;
color: @very-light-pink;
}
}
.value-misurazioni {
width: 63px;
height: 12px;
margin: 10px 268px 12px 124px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: left !important;
color: @white;
&-inner {
width: 253px;
height: 16px;
margin: 24px 69px 24px 142px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
float: left;
text-align: initial;
color: @very-light-pink;
}
}
@@ -1,33 +1,33 @@
<template>
<div>
<table class="log-misurazioni-table">
<div class="one-column-table-container scrollable">
<table>
<thead>
<tr>
<th class="date-misurazioni">Date</th>
<th class="recipe-misurazioni">Recipe</th>
<th class="type-misurazioni">Type</th>
<th class="value-misurazioni">Value</th>
<th class="misurazioni-date">Date</th>
<th class="misurazioni-recipe">Recipe</th>
<th class="misurazioni-type">Type</th>
<th class="misurazioni-value">Value</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) of rowData" :key="i" class="tr-inner">
<td>
<span class="date-misurazioni-inner">
<span>
{{ item.date }}
</span>
</td>
<td>
<span class="recipe-misurazioni-inner">
<span>
{{ item.recipe }}
</span>
</td>
<td>
<span class="type-misurazioni-inner">
<span>
{{ item.type }}
</span>
</td>
<td>
<span class="value-misurazioni-inner">
<span>
{{ item.value }}
</span>
</td>
@@ -1,6 +1,6 @@
<template>
<div class="main-container">
<div class="column-page">
<div class="column-page-one-column">
<RiscaldiTable></RiscaldiTable>
</div>
</div>
@@ -1,268 +1,71 @@
@import "../../../../variable.less";
span {
display: inline-block;
}
.riscaldi-table {
width: 1384px;
height: 886px;
margin: 20px 20px 0 20px;
thead {
height: 34px;
opacity: 0.5;
background-color: @fill-under-grey-1-2;
th,
td {
&.riscaldi-status {
width: 435px;
max-width: 435px;
padding: 0 0 0 38px;
}
th {
display: inline-block;
&.riscaldi-set {
width: 378px;
max-width: 378px;
}
tbody {
overflow-y: scroll;
height: 752px;
tr:nth-child(odd) {
background-color: @fill-under-grey-3-2;
}
tr {
display: inline-block;
width: 1358px;
height: 64px;
&-inner {
width: 1358px;
height: 64px;
margin: 34px 26px 0 0;
padding: 0 2px 0 10px;
}
}
&.riscaldi-cell-id {
width: 254px;
max-width: 254px;
}
&.riscaldi-current {
width: 308px;
max-width: 308px;
}
}
.cell-id {
height: 16px;
margin: 10px 0px 12px 9px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: left;
float: left;
color: @very-light-pink;
&-inner {
width: 6px;
height: 16px;
margin: 24px 0px 24px 10px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
float: left;
color: @very-light-pink;
}
}
.current {
width: 63px;
height: 12px;
margin: 10px 0px 12px 173px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: center;
float: left;
color: @white;
&-inner {
width: 44px;
height: 16px;
margin: 24px 0px 24px 216px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
float: left;
color: @very-light-pink;
}
}
.set {
width: 63px;
height: 12px;
margin: 10px 0px 12px 226px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: center;
float: left;
color: @white;
&-inner {
width: 21px;
height: 16px;
margin: 24px 0px 24px 260px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
.status {
width: 63px;
height: 12px;
margin: 10px 0 12px 325px;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 0.86;
letter-spacing: normal;
text-align: center;
float: left;
color: @white;
}
.button-details {
width: 93px;
float: right;
padding: 14px 0px 13px 0px;
margin: 8px 8px 8px 8px;
object-fit: contain;
.status-buttons {
padding: 3px 16px;
border-radius: 2px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.4);
background-image: linear-gradient(to bottom, #818a8f 0%, #42494e 98%);
cursor: pointer;
&-label {
width: 62px;
height: 21px;
object-fit: contain;
}
font-size: 18px;
font-weight: 500;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
label {
margin: 3px 16px 3px 16px;
}
.ok-button {
width: 55px;
height: 25px;
margin: 20px 263px 19px 336px;
padding: 3px 16px;
border-radius: 2px;
background-color: @booger;
&-label {
width: 23px;
height: 19px;
> label {
text-shadow: 0 0 4px @black-50;
margin: 3px 16px 3px 16px;
font-size: 16px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
.broken-button {
width: 87px;
height: 25px;
margin: 20px 247px 19px 320px;
padding: 3px 16px;
border-radius: 2px;
background-color: @scarlet;
&-label {
width: 55px;
height: 19px;
margin: 3px 16px 3px 16px;
text-shadow: 0 0 4px @black-50;
> label {
text-shadow: 0 0 4px rgb(0 0 0 / 50%);
font-size: 16px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
.error-button {
width: 96px;
height: 25px;
margin: 20px 243px 19px 315px;
padding: 3px 16px;
border-radius: 2px;
background-color: @scarlet;
&-label {
width: 64px;
height: 19px;
margin: 3px 16px 3px 16px;
> label {
text-shadow: 0 0 4px @black-50;
font-size: 16px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
.warning-button {
width: 96px;
height: 25px;
margin: 20px 243px 19px 315px;
padding: 3px 16px;
border-radius: 2px;
display: flex;
justify-content: center;
background-color: @macaroni-and-cheese;
&-label {
width: 79px;
height: 19px;
> label {
margin: 3px 0px 3px 0px;
text-shadow: 0 0 4px @black-50;
font-size: 16px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: @very-light-pink;
}
}
.status-container {
width: 126px;
display: flex;
justify-content: center;
}
@@ -1,50 +1,69 @@
<template>
<div>
<table class="riscaldi-table">
<div class="one-column-table-container scrollable">
<table>
<thead>
<tr>
<th class="cell-id">Cell ID</th>
<th class="current">Current</th>
<th class="set">Set</th>
<th class="status">Status</th>
<th class="riscaldi-cell-id">Cell ID</th>
<th class="riscaldi-current">Current</th>
<th class="riscaldi-set">Set</th>
<th class="riscaldi-status">Status</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) of rowData" :key="i" class="tr-inner">
<tr v-for="(item, i) of rowData" :key="i">
<td>
<span class="cell-id-inner">
<span>
{{ item.cellId }}
</span>
</td>
<td>
<span class="current-inner">
<span>
{{ item.current }}
</span>
</td>
<td>
<span class="set-inner">
<span>
{{ item.set }}
</span>
</td>
<td>
<span class="status-inner">
<span v-if="item.status === 'ok'" class="ok-button status-ok">
<span class="ok-button-label">OK</span>
</span>
<span v-else-if="item.status === 'broken'" class="broken-button">
<span class="broken-button-label">Broken</span>
</span>
<span v-else-if="item.status === 'error 23'" class="error-button">
<span class="error-button-label">Error 23</span>
</span>
<span v-else-if="item.status === 'error 12'" class="error-button">
<span class="error-button-label">Error 12</span>
</span>
<span class="status-container">
<span
v-else-if="item.status === 'warning 3'"
class="warning-button"
v-if="item.status === 'ok'"
class="status-buttons ok-button status-ok"
>
<span class="warning-button-label">Warning 3</span>
<label>OK</label>
</span>
</span>
<span>
<span class="status-container">
<span
v-if="item.status === 'broken'"
class="status-buttons broken-button"
>
<label>Broken</label>
</span>
</span>
</span>
<span
v-if="item.status === 'error 23'"
class="status-buttons error-button"
>
<label>Error 23</label>
</span>
<span
v-if="item.status === 'error 12'"
class="status-buttons error-button"
>
<label>Error 12</label>
</span>
<span class="status-container">
<span
v-if="item.status === 'warning 3'"
class="status-buttons warning-button"
>
<label>Warning 3</label>
</span>
</span>
</td>
@@ -5,7 +5,7 @@
@click="go('io')"
:class="{white: this.value == 'io'}"
>{{'i-o' | localize("I/O")}}</div>
<!-- <div
<div
class="rettangle"
@click="go('log-ciclo-automatico')"
:class="{white: this.value == 'log-ciclo-automatico'}"
@@ -15,16 +15,16 @@
@click="go('log-misurazioni')"
:class="{white: this.value == 'log-misurazioni'}"
>{{'log-misurazioni' | localize("Log misurazioni")}}</div>
<div
<!-- <div
class="rettangle"
@click="go('assi')"
:class="{white: this.value == 'assi'}"
>{{'log-assi' | localize('Log assi')}}</div>
>{{'log-assi' | localize('Log assi')}}</div> -->
<div
class="rettangle"
@click="go('riscaldi')"
:class="{white: this.value == 'riscaldi'}"
>{{'riscaldi' | localize("Riscaldi")}}</div>-->
>{{'riscaldi' | localize("Riscaldi")}}</div>
</div>
</template>
<style lang="less">
@@ -128,6 +128,27 @@
grid-template-columns: repeat(auto-fill, minmax(600px, 1fr));
}
.column-page-one-column {
grid-row: 2;
grid-column: 2;
width: 1384px;
height: 885px;
border-top: @white 2px solid;
background-color: @fill-under-grey-2-2;
display: grid;
> table {
margin: 20px 0 0 20px
}
}
.one-column-table-container {
height: 800px;
margin: 20px 0 0 20px;
> table {
width: -webkit-fill-available;
}
}
.pointer {
cursor: pointer;
}