public string OpenModBus() { if (MyModMaster != null && tcpClient != null && tcpClient.Connected) { return(null); } string error = null; try { CloseModBus(); tcpClient = new TcpClient(); int port = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "CustomPort"); if (port == 0) { port = 502; //MOdbus default Port TheThing.SetSafePropertyNumber(MyBaseThing, "CustomPort", port); } tcpClient.Connect(IPAddress.Parse(MyBaseThing.Address), port); MyModMaster = ModbusIpMaster.CreateIp(tcpClient); } catch (SocketException e) { error = e.Message; CloseModBus(); } return(error); }
private void sinkLoopChanged(cdeP pProp) { int tTime = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(this, "MsToTrigger")); //if (tTime > 0) { int tPeriod = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(this, "LoopPeriod")); if (tPeriod == 0) { tPeriod = -1; } if (tPeriod > 0 && tPeriod < 10) { tPeriod = 10; } MyBaseThing.Value = "0"; if (mTimer != null) { mTimer.Change(tTime, tPeriod); } else { mTimer = new Timer(sinkTriggerTimeout, null, tTime, tPeriod); } IsActive = true; MyBaseThing.StatusLevel = 1; MyBaseThing.LastMessage = $"Timer started at {DateTimeOffset.Now}"; SummaryForm?.SetUXProperty(Guid.Empty, string.Format("Background=green")); } }
public void AddSpeedGauge(TheFormInfo tMyForm, int pFldNumber = 25000, int pParentFld = TheDefaultSensor.SensorGaugeGroup, bool IsHighGood = false) { string Plotband = ""; if (IsHighGood) { Plotband = $"PlotBand=[{{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMinValue")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"color\": \"#FF000088\" }}, {{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue")}, \"color\": \"#00FF0044\" }}]"; } else { Plotband = $"PlotBand=[{{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMinValue")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"color\": \"#00FF0088\" }}, {{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue")}, \"color\": \"#FF000044\" }}]"; } GaugeFld = TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.UserControl, pFldNumber, 0, 0, null, "QValue", new ThePropertyBag() { "ControlType=Speed Gauge", "NoTE=true", $"ParentFld={pParentFld}", "TileWidth=6", "TileHeight=3", $"MinValue={TheThing.GetSafePropertyNumber(MyBaseThing,"StateSensorMinValue")}", $"MaxValue={TheThing.GetSafePropertyNumber(MyBaseThing,"StateSensorMaxValue")}", $"SubTitle={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorUnit")}", Plotband, $"SetSeries={{ \"name\": \"{TheThing.GetSafePropertyString(MyBaseThing, "StateSensorValueName")}\",\"data\": [{TheThing.GetSafePropertyNumber(MyBaseThing,"QValue")}],\"tooltip\": {{ \"valueSuffix\": \" {TheThing.GetSafePropertyString(MyBaseThing, "StateSensorUnit")}\"}}}}", $"Value={MyBaseThing.Value}" }); }
private double CalculateX() { var step = TheThing.GetSafePropertyNumber(MyBaseThing, "Step"); if (step == 0) { step = 1; } return(_index += step); }
public override bool DoInit() { base.DoInit(); IsActive = false; TheThing.SetSafePropertyBool(MyBaseThing, "IsStateSensor", true); MyBaseThing.StatusLevel = 4; if (string.IsNullOrEmpty(MyBaseThing.ID)) { MyBaseThing.ID = Guid.NewGuid().ToString(); TheThing.SetSafePropertyString(MyBaseThing, "StateSensorType", "analog"); TheThing.SetSafePropertyString(MyBaseThing, "StateSensorUnit", "units"); TheThing.SetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue", 100); TheThing.SetSafePropertyNumber(MyBaseThing, "StateSensorAverage", 50); TheThing.SetSafePropertyNumber(MyBaseThing, "StateSensorMinValue", 0); TheThing.SetSafePropertyNumber(MyBaseThing, "Interval", 500); } TheThing.SetSafePropertyString(MyBaseThing, "StateSensorIcon", "/P066/Images/iconVThingsRest.png"); GetProperty("FriendlyName", true).RegisterEvent(eThingEvents.PropertyChanged, sinkNameChanged); cdeP tRW = GetProperty("RawValue", true); tRW.RegisterEvent(eThingEvents.PropertyChanged, sinkPrePro); cdeP.SetSafePropertyBool(tRW, "IsStateSensor", true); cdeP.SetSafePropertyString(tRW, "StateSensorType", "analog"); cdeP.SetSafePropertyString(tRW, "StateSensorUnit", "°F"); cdeP.SetSafePropertyNumber(tRW, "StateSensorMaxValue", 100); cdeP.SetSafePropertyNumber(tRW, "StateSensorAverage", 50); cdeP.SetSafePropertyNumber(tRW, "StateSensorMinValue", 0); if (!string.IsNullOrEmpty(TheThing.GetSafePropertyString(MyBaseThing, "RealSensorThing")) && !string.IsNullOrEmpty(TheThing.GetSafePropertyString(MyBaseThing, "RealSensorProperty"))) { EngageMapper(); } GetProperty("IsGlobal", true).RegisterEvent(eThingEvents.PropertyChanged, (p) => { if (TheCommonUtils.CBool(p.ToString())) { TheThingRegistry.RegisterThingGlobally(MyBaseThing); } else { TheThingRegistry.UnregisterThingGlobally(MyBaseThing); } }); GetProperty("Interval", true).RegisterEvent(eThingEvents.PropertyChanged, (p) => { changeInterval(TheCommonUtils.CInt(p.ToString())); }); MyBaseThing.SetPublishThrottle((int)TheThing.GetSafePropertyNumber(MyBaseThing, "Interval")); //TheQueuedSenderRegistry.RegisterHealthTimer(checkMapperHealth); return(true); }
void sinkPChanged(cdeP prop) { if (MyBaseEngine.GetEngineState().IsSimulated || !IsConnected) { return; } var field = MyModFieldStore.MyMirrorCache.GetEntryByFunc(s => s.PropertyName == prop.Name); if (field == null) { return; } var error = OpenModBus(); if (!string.IsNullOrEmpty(error)) { MyBaseThing.LastMessage = $"{DateTime.Now} - Modbus Device could not be opened: {error}"; TheBaseAssets.MySYSLOG.WriteToLog(10000, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, MyBaseThing.LastMessage, eMsgLevel.l1_Error)); return; } try { ushort tMainOffset = (ushort)(TheThing.GetSafePropertyNumber(MyBaseThing, "Offset") + field.SourceOffset); byte tSlaveAddress = (byte)TheThing.GetSafePropertyNumber(MyBaseThing, "SlaveAddress"); int tReadWay = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ConnectionType"); switch (tReadWay) { case 1: MyModMaster.WriteSingleCoil(tSlaveAddress, tMainOffset, TheCommonUtils.CBool(prop.ToString())); break; default: MyModMaster.WriteSingleRegister(tSlaveAddress, tMainOffset, TheCommonUtils.CUShort(prop.ToString())); break; } } catch (Exception e) { MyBaseThing.LastMessage = $"{DateTime.Now} - Failure during write of modbus property: {e.Message}"; TheBaseAssets.MySYSLOG.WriteToLog(10000, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, MyBaseThing.LastMessage, eMsgLevel.l1_Error, e.ToString())); } if (!KeepOpen) // races with reader thread, but reader thread will retry/reopen so at most one data point is lost { CloseModBus(); } }
void sinkUpdateUX(cdeP prop) { if (prop.Name == "StateSensorValueName") { ValueField?.SetUXProperty(Guid.Empty, $"Title={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorValueName")}"); } if (prop.Name == "StateSensorMaxValue" || prop.Name == "StateSensorMinValue" || prop.Name == "StateSensorSteps") { LiveChartFld?.SetUXProperty(Guid.Empty, $"MaxValue={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorMaxValue")}:;:MinValue={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorMinValue")}"); GaugeFld?.SetUXProperty(Guid.Empty, $"MaxValue={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorMaxValue")}:;:MinValue={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorMinValue")}"); if (mBucket != null) { mBucket = new TheBucketChart <T>((int)TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMinValue"), (int)TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue"), (int)TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorSteps"), true); BucketChartFld?.SetUXProperty(Guid.Empty, $"XAxis={{ \"categories\": {mBucket.GetBuckets()} }}"); TheThing.SetSafePropertyString(MyBaseThing, "BucketChart", mBucket.GetBucketArray()); } } }
public static bool CopyStateSensorInfo(TheThing pBaseThing) { if (pBaseThing == null) { return(false); } var t = TheThingRegistry.GetThingByMID("*", TheThing.GetSafePropertyGuid(pBaseThing, "RealSensorThing")); if (t != null && TheThing.GetSafePropertyBool(t, "IsStateSensor")) { if (string.IsNullOrEmpty(TheThing.GetSafePropertyString(pBaseThing, "StateSensorType"))) { TheThing.SetSafePropertyString(pBaseThing, "StateSensorType", TheThing.GetSafePropertyString(t, "StateSensorType")); } if (string.IsNullOrEmpty(TheThing.GetSafePropertyString(pBaseThing, "StateSensorUnit"))) { TheThing.SetSafePropertyString(pBaseThing, "StateSensorUnit", TheThing.GetSafePropertyString(t, "StateSensorUnit")); } if (string.IsNullOrEmpty(TheThing.GetSafePropertyString(pBaseThing, "StateSensorValueName"))) { TheThing.SetSafePropertyString(pBaseThing, "StateSensorValueName", TheThing.GetSafePropertyString(t, "StateSensorValueName")); } if (pBaseThing.GetProperty("StateSensorAverage") == null) { TheThing.SetSafePropertyNumber(pBaseThing, "StateSensorAverage", TheThing.GetSafePropertyNumber(t, "StateSensorAverage")); } if (pBaseThing.GetProperty("StateSensorMinValue") == null) { TheThing.SetSafePropertyNumber(pBaseThing, "StateSensorMinValue", TheThing.GetSafePropertyNumber(t, "StateSensorMinValue")); } if (pBaseThing.GetProperty("StateSensorMaxValue") == null) { TheThing.SetSafePropertyNumber(pBaseThing, "StateSensorMaxValue", TheThing.GetSafePropertyNumber(t, "StateSensorMaxValue")); } if (string.IsNullOrEmpty(TheThing.GetSafePropertyString(pBaseThing, "StateSensorIcon"))) { TheThing.SetSafePropertyString(pBaseThing, "StateSensorIcon", TheThing.GetSafePropertyString(t, "StateSensorIcon")); } return(true); } return(false); }
public override void Connect(TheProcessMessage pMsg) { if (IsConnected) { return; } IsConnected = true; MyBaseThing.StatusLevel = 1; MyBaseThing.LastMessage = $"Connected to Logger at {DateTimeOffset.Now}"; mLogFilePath = Address; mMaxLogFileSize = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "MaxLogFileSize"); mWriteToConsole = TheThing.GetSafePropertyBool(MyBaseThing, "WriteToConsole"); MyCurLog = TheThing.GetSafePropertyString(MyBaseThing, "LogFilePath"); mLogFileDate = TheThing.GetSafePropertyDate(MyBaseThing, "LogFileDate"); if (string.IsNullOrEmpty(MyCurLog) || (mLogFileDate != DateTimeOffset.MinValue && mLogFileDate.Day != DateTimeOffset.Now.Day)) { LogFilePath = MyCurLog = TheCommonUtils.cdeFixupFileName(mLogFilePath + string.Format("\\LOG_{0:yyyMMdd_HHmmss}.txt", DateTime.Now)); LogFileDate = mLogFileDate = DateTimeOffset.Now; } TheCommonUtils.CreateDirectories(MyCurLog); TheCDEngines.MyContentEngine.RegisterEvent(eEngineEvents.NewEventLogEntry, sinkNewEvent); #if !CDE_NET4 && !CDE_NET35 if (TheBaseAssets.MyCmdArgs?.ContainsKey("CreateEventLog") != true) { // CODE REVIEW: What is the purpose of this export? var pipelineConfig = MyBaseThing.GetThingPipelineConfigurationAsync(false).Result; if (pipelineConfig != null) { var tWrite = TheCommonUtils.SerializeObjectToJSONString(pipelineConfig); TheCommonUtils.CreateDirectories(TheCommonUtils.cdeFixupFileName($"\\ConfigTemplates\\{MyBaseThing.FriendlyName}.cdeConfig")); using (System.IO.StreamWriter fs = new System.IO.StreamWriter(TheCommonUtils.cdeFixupFileName($"\\ConfigTemplates\\{MyBaseThing.FriendlyName}.cdeConfig"), false)) { fs.Write(tWrite); } } } #endif }
private void CreateTHHUx(string tGuid, string FileToImport) { var MyServiceHealthDataStore = new TheStorageMirror <TheThingStore>(TheCDEngines.MyIStorageService); MyServiceHealthDataStore.IsRAMStore = true; MyServiceHealthDataStore.IsCachePersistent = true; MyServiceHealthDataStore.CacheStoreInterval = 200; MyServiceHealthDataStore.IsStoreIntervalInSeconds = true; MyServiceHealthDataStore.CacheTableName = tGuid; MyServiceHealthDataStore.InitializeStore(true, false, FileToImport); int tBS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartValues"); if (tBS < 10) { tBS = 10; } if (tBS > 10000) { tBS = 10000; } int tCS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartSize"); if (tCS < 6) { tCS = 6; } TheNMIEngine.AddChartScreen(MyBaseThing, new TheChartDefinition(TheThing.GetSafeThingGuid(MyBaseThing, tGuid), tGuid, tBS, tGuid, true, "", "PB.HostAddress", "PB.QSenders,PB.QSLocalProcessed,PB.QSSent,PB.QKBSent,PB.QKBReceived,PB.QSInserted,PB.EventTimeouts,PB.TotalEventTimeouts,PB.CCTSMsRelayed,PB.CCTSMsReceived,PB.CCTSMsEvaluated,PB.HTCallbacks,PB.KPI1,PB.KPI2,PB.KPI3,PB.KPI4,PB.KPI5,PB.KPI10") { GroupMode = 0, IntervalInMS = 0 }, 5, 3, 0, "Customer KPIs", false, new ThePropertyBag() { ".TileHeight=8", ".NoTE=true", ".TileWidth=" + tCS }); }
protected override void SensorCyclicCalc(long timer) { base.SensorCyclicCalc(timer); if ((timer % PingFreq) != 0) { return; } if (IsInCyclic) { return; } IsInCyclic = true; PingFreq = (int)TheThing.GetSafePropertyNumber(MyBaseEngine.GetBaseThing(), "CalcAggregation"); if (PingFreq == 0) { PingFreq = 30; } var tVals = MyHistorian?.GetValues(); //TODO: This returns null if the SensorHistorian is in the SQL Server. We need to think about what we do here! if (tVals?.Any() == true) { string tValues = TheThing.GetSafePropertyString(MyBaseThing, "HistoryFields"); if (tValues.Contains("QValue_Ave")) { TheThing.SetSafePropertyNumber(MyBaseThing, "QValue_Ave", tVals.Average(w => w.PB.ContainsKey("QValue") ? TheCommonUtils.CDbl(w.PB["QValue"]) : 0)); } if (tValues.Contains("QValue_Min")) { TheThing.SetSafePropertyNumber(MyBaseThing, "QValue_Min", tVals.Min(w => w.PB.ContainsKey("QValue") ? TheCommonUtils.CDbl(w.PB["QValue"]) : 0)); } if (tValues.Contains("QValue_Max")) { TheThing.SetSafePropertyNumber(MyBaseThing, "QValue_Max", tVals.Max(w => w.PB.ContainsKey("QValue") ? TheCommonUtils.CDbl(w.PB["QValue"]) : 0)); } } IsInCyclic = false; }
void sinkPChanged(cdeP tProp) { if (m_Tag != null && tProp != null && tProp.HasChanged && tProp.Name == "DontMonitor") { if (!TheCommonUtils.CBool(tProp.ToString())) { m_Tag.SampleRate = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(MyBaseThing, "SampleRate")); string error; TheBaseAssets.MySYSLOG.WriteToLog(78102, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM(MyBaseThing.EngineName, $"Monitoring tag due to DontMonitor property change {m_Tag}", eMsgLevel.l4_Message, "")); var subscription = m_Tag.MyOPCServer.GetOrCreateSubscription(m_Tag.SampleRate); if (subscription != null) { m_Tag.MonitorTag(subscription, out error); // TODO Handle error } } else { m_Tag.UnmonitorTag(); } } }
static public bool CreatePerformanceHeader(TheThing pBaseThing, TheFormInfo pFormInfo, int pFldOrder, int pParent, string pSensorPicSource = "SENSORS/Images/SensorLogo_156x78.png", string pLogo = null) { var tG = TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.TileGroup, pFldOrder, 0, 0, null, null, new nmiCtrlTileGroup() { ParentFld = pParent, /*MaxTileWidth = 18,*/ Background = "transparent" }); tG.AddOrUpdatePlatformBag(eWebPlatform.Mobile, new nmiPlatBag { MaxTileWidth = 6 }); tG.AddOrUpdatePlatformBag(eWebPlatform.HoloLens, new nmiPlatBag { MaxTileWidth = 12 }); TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.TileGroup, pFldOrder + 1, 0, 0, null, null, new nmiCtrlTileGroup() { ParentFld = pFldOrder, TileWidth = 6 }); //TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.StatusLight, pFldOrder + 2, 0, 0, "Current status", "StatusLevel", new TheNMIBaseControl { ParentFld = pFldOrder + 1, TileHeight = 1, TileWidth = 4 }); //TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.SmartLabel, pFldOrder + 3, 0, 0, null, "LastMessage", new nmiCtrlTextArea() { ParentFld = pFldOrder + 1, TileWidth = 6, TileHeight = 1, Background = "transparent",NoTE=true, FontSize = 20, HorizontalAlignment = "left", VerticalAlignment = "center"/*, Value = pCurrentStatus*/ }); var tMiniStatus = TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.TileGroup, pFldOrder + 5, 0, 0, null, null, new nmiCtrlTileGroup() { ParentFld = pFldOrder, TileWidth = 6, Background = "transparent" }); if (!string.IsNullOrEmpty(pLogo)) { var tBut2 = TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.Picture, pFldOrder + 7, 2, 0, null, null, new nmiCtrlPicture() { ParentFld = pFldOrder + 5, TileWidth = 2, TileHeight = 1, NoTE = true, Background = "transparent", Source = pLogo }); tBut2.RegisterUXEvent(pBaseThing, eUXEvents.OnClick, "ImageClick2", (sender, para) => { uint min = TheCommonUtils.CUInt(TheThing.GetSafePropertyNumber(pBaseThing, "StateSensorMinValue")); uint max = TheCommonUtils.CUInt(TheThing.GetSafePropertyNumber(pBaseThing, "StateSensorMaxValue")); TheThing.SetSafePropertyNumber(pBaseThing, "QValue", TheCommonUtils.GetRandomUInt(min, max)); }); } var tFld = TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.TileGroup, pFldOrder + 8, 0, 0, null, null, new nmiCtrlTileGroup() { ParentFld = pFldOrder, TileWidth = 6, TileHeight = 2, Background = "transparent" }); tFld.AddOrUpdatePlatformBag(eWebPlatform.Any, new nmiPlatBag { Hide = true }); tFld.AddOrUpdatePlatformBag(eWebPlatform.Desktop, new nmiPlatBag { Show = true }); tFld.AddOrUpdatePlatformBag(eWebPlatform.XBox, new nmiPlatBag { Show = true }); TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.SmartLabel, pFldOrder + 9, 0, 0, null, "FriendlyName", new nmiCtrlSmartLabel() { ParentFld = pFldOrder + 8, NoTE = true, TileWidth = 3, TileHeight = 1, LabelClassName = "cdeSelDevice", FontSize = 20, HorizontalAlignment = "left", VerticalAlignment = "center" /*, Value = pSelectedDeviceName*/ }); if (!string.IsNullOrEmpty(pSensorPicSource)) { var tBut3 = TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.Picture, pFldOrder + 10, 0, 0, null, null, new nmiCtrlPicture() { NoTE = true, ParentFld = pFldOrder + 8, TileWidth = 3, TileHeight = 1, Source = pSensorPicSource });; tBut3.RegisterUXEvent(pBaseThing, eUXEvents.OnClick, "LogoClick3", (sender, para) => { uint min = TheCommonUtils.CUInt(TheThing.GetSafePropertyNumber(pBaseThing, "StateSensorMinValue")); uint max = TheCommonUtils.CUInt(TheThing.GetSafePropertyNumber(pBaseThing, "StateSensorMaxValue")); TheThing.SetSafePropertyNumber(pBaseThing, "QValue", TheCommonUtils.GetRandomUInt(min, max)); }); } TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.StatusLight, pFldOrder + 12, 0, 0, null, "StatusLevel", new TheNMIBaseControl { NoTE = true, TileHeight = 1, TileWidth = 1, ParentFld = pFldOrder + 8 }); TheNMIEngine.AddSmartControl(pBaseThing, pFormInfo, eFieldType.TextArea, pFldOrder + 11, 0, 0, null, "LastMessage", new nmiCtrlTextArea { TileHeight = 1, ParentFld = pFldOrder + 8, TileWidth = 5, FontSize = 12, NoTE = true, Foreground = "gray", Background = "Transparent" }); return(true); }
public long GetDataReceivedCount() { return((long)TheThing.GetSafePropertyNumber(GetOpcThing(), "DataReceivedCount")); }
void sinkPrePro(cdeP pProp) { if (TheThing.GetSafePropertyString(MyBaseThing, "StateSensorType") != "analog") { SetProperty("Value", pProp.Value); return; } int prepro = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(MyBaseThing, "PrePro")); int preprotime = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(MyBaseThing, "PreProTime")); double valScale = TheCommonUtils.CDbl(TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorScaleFactor")); var pPropString = TheCommonUtils.CStr(pProp); if (!string.IsNullOrEmpty(ValueFilterPattern)) { try { if (ValueFilterPattern != filterPattern || filterRegex == null) { #if !CDE_NET4 filterRegex = new Regex(ValueFilterPattern, RegexOptions.Compiled | RegexOptions.CultureInvariant, new TimeSpan(0, 0, 5)); #else filterRegex = new Regex(ValueFilterPattern, RegexOptions.Compiled | RegexOptions.CultureInvariant); #endif filterPattern = ValueFilterPattern; } pPropString = filterRegex.Match(pPropString).Value; } catch (Exception e) { LastMessage = $"Error applying filter pattern: {e.Message}"; return; // CODE REVIEW: Or ist it better to treat this as 0, so other time processing doesn not get confused? } } double pValue; if (!string.IsNullOrEmpty(ValueMatchPattern)) { try { if (ValueMatchPattern != matchPattern || matchRegex == null) { #if !CDE_NET4 matchRegex = new Regex(ValueMatchPattern, RegexOptions.Compiled | RegexOptions.CultureInvariant, new TimeSpan(0, 0, 5)); #else matchRegex = new Regex(ValueMatchPattern, RegexOptions.Compiled | RegexOptions.CultureInvariant); #endif matchPattern = ValueMatchPattern; } if (matchRegex.IsMatch(pProp.ToString())) { pValue = 1; } else { pValue = 0; } } catch (Exception e) { LastMessage = $"Error applying match pattern: {e.Message}"; return; // CODE REVIEW: Or ist it better to treat this as 0, so other time processing doesn not get confused? } } else { pValue = TheCommonUtils.CDbl(pPropString); } if (valScale != 0) { pValue /= valScale; } if (pValue < 0 && TheThing.GetSafePropertyBool(MyBaseThing, "StateSensorIsAbs")) { pValue = Math.Abs(pValue); } if (preprotime > 0 && prepro > 0) { if (pValue < min) { min = pValue; } if (pValue > max) { max = pValue; } ave += pValue; aveCnt++; if (DateTimeOffset.Now.Subtract(lastWrite).TotalSeconds < preprotime) { return; } lastWrite = DateTimeOffset.Now; switch (prepro) { case 1: if (min == double.MaxValue) { return; } pValue = min; min = double.MaxValue; break; case 2: if (max == double.MinValue) { return; } pValue = max; min = double.MinValue; break; case 3: if (aveCnt == 0) { return; } pValue = ave / aveCnt; ave = 0; aveCnt = 0; break; } } if (GetProperty("StateSensorDigits", false) != null) { int tDigits = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorDigits"); SetProperty("Value", decimal.Round((decimal)pValue, tDigits, MidpointRounding.AwayFromZero)); } else { SetProperty("Value", pValue); } }
public override bool DoCreateUX() { var tFlds = TheNMIEngine.AddStandardForm(MyBaseThing, null, 12, null, "Value"); MyStatusForm = tFlds["Form"] as TheFormInfo; SummaryForm = tFlds["DashIcon"] as TheDashPanelInfo; SummaryForm.PropertyBag = new ThePropertyBag() { string.Format("Format={0}<br>{{0}}", MyBaseThing.FriendlyName) }; var ts = TheNMIEngine.AddStatusBlock(MyBaseThing, MyStatusForm, 10); ts["Group"].SetParent(1); // loading spinner //var tDash = TheThingRegistry.IsEngineRegistered("CDMyNMIControls.TheNMIctrls") var tDash = new nmiDashboardTile { ClassName = "cdeDashPlate", Format = "Loading... <i class='fa fa-spinner fa-pulse'></i>", TileWidth = 2, TileHeight = 2, HTML = "<div><p><%C20:FriendlyName%></p><div id='COUNTD%cdeMID%'></div></div>", Style = "background-image:url('GlasButton.png');color:white;background-color:gray", RSB = true }; //: new ThePropertyBag { $"Format={MyBaseThing.FriendlyName}<br>{{0}}", "Foreground=white" }; SummaryForm.PropertyBag = tDash; SummaryForm.RegisterPropertyChanged(SinkStatChanged); var tControl = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(MyBaseThing, "ControlType")); var tBag = ThePropertyBag.CreateUXBagFromProperties(MyBaseThing); tBag.Add("ParentFld=1"); CountBar = tControl > 0 ? TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, (eFieldType)tControl, 21, 2, 0, "Current Value", "Value", tBag) : TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.BarChart, 21, 2, 0, "Current Value", "Value", new nmiCtrlBarChart { ParentFld = 1 }); //if (TheThingRegistry.IsEngineRegistered("CDMyNMIControls.TheNMIctrls")) { //MyGauge=TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.UserControl, 4000, 2, 0, "Countdown", "Value", new ThePropertyBag { "TileWidth=2", "NoTE=true", "EngineName=CDMyNMIControls.TheNMIctrls", "RenderTarget=COUNTD%cdeMID%", "ControlType=cdeNMI.ctrlCircularGauge", "LabelForeground=#00b9ff", "Foreground=#FFFFFF" }); MyGauge = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CircularGauge, 4000, 2, 0, "Countdown", "Value", new ThePropertyBag { "TileWidth=2", "NoTE=true", "RenderTarget=COUNTD%cdeMID%", "LabelForeground=#00b9ff", "Foreground=#FFFFFF" }); } var mSendbutton = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 120, 2, 0x80, "Trigger", false, "", null, new nmiCtrlTileButton { NoTE = true, TileWidth = 3, ParentFld = 10, ClassName = "cdeGoodActionButton" }); mSendbutton.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) => { if (_mTimer != null) { _mTimer.Dispose(); _mTimer = null; } SinkTriggered(GetProperty("StartValue", false)); }); var mSP = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 130, 2, 0x80, "Stop", false, "", null, new nmiCtrlTileButton { NoTE = true, TileWidth = 3, ParentFld = 10, ClassName = "cdeBadActionButton" }); mSP.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) => { if (_mTimer != null) { _mTimer.Dispose(); _mTimer = null; } }); // Settings Controls & User Input TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 151, 2, 0x80, "Settings...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup { ParentFld = 1, TileWidth = 6, IsSmall = true, DoClose = true })); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 153, 2, 0x80, "Tick time in ms", nameof(Frequency), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 151 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 156, 2, 0x80, "Step", nameof(Step), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 151 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 157, 2, 0x80, "Amplitude", nameof(Amplitude), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 151 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 158, 2, 0x80, "Shift", nameof(Shift), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 151 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleCheck, 180, 2, 0x80, "Autostart", nameof(AutoStart), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 151 }); return(true); }
internal static TheScreenInfo GenerateLiveScreen(Guid pScreenId, TheClientInfo tClientInfo) // Guid pUserGuid, int lcid, int pFlag) { if (TheCDEngines.MyNMIService == null) { return(null); } TheScreenInfo tInfo = new TheScreenInfo { cdeMID = pScreenId, MyDashboard = null, MyStorageInfo = new List <TheFormInfo>(), MyStorageMeta = new cdeConcurrentDictionary <string, TheFormInfo>(), MyStorageMirror = new List <object>(), MyDashPanels = new List <TheDashPanelInfo>() }; TheThing tLiveForm = TheThingRegistry.GetThingByMID("*", pScreenId); if (tLiveForm == null || !TheUserManager.HasUserAccess(tClientInfo.UserID, tLiveForm.cdeA)) { return(null); //V3.1: BUG 126 - could lead to racing condition. TODO: Revisit later //TheFormInfo tI = new TheFormInfo(tLiveForm) { FormTitle = (tLiveForm == null ? "Form not Found!" : "Access Denied!") }; //tI.TargetElement = pScreenId.ToString(); //tI.AssociatedClassName = pScreenId.ToString(); //tInfo.MyStorageInfo.Add(tI); //tI.FormFields = new List<TheFieldInfo>(); //TheFieldInfo tFldInfo = new TheFieldInfo(null, null, 10, 0, 0); //tFldInfo.Type = eFieldType.SmartLabel; //tFldInfo.Header = (tLiveForm == null ? "This Form was defined but has not Meta-Data associated with it." : "You do not have the required access permissions!"); //tI.FormFields.Add(tFldInfo); //return tInfo; } string tFormName = TheThing.GetSafePropertyString(tLiveForm, "FriendlyName"); List <TheThing> tFields = TheThingRegistry.GetThingsByFunc("*", s => s.cdeO == TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID && TheThing.GetSafePropertyString(s, "FormName") == tFormName && TheThing.GetSafePropertyBool(s, "IsLiveTag") && (s.UID == Guid.Empty || s.UID == tClientInfo.UserID)); if (tFields != null && tFields.Any()) { string tFormTitle = TheThing.GetSafePropertyString(tLiveForm, "FormTitle"); if (string.IsNullOrEmpty(tFormTitle)) { tFormTitle = tFormName; } TheFormInfo tI = new TheFormInfo(tLiveForm) { FormTitle = tFormTitle, TargetElement = pScreenId.ToString(), DefaultView = eDefaultView.Form, TileWidth = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tLiveForm, "TileWidth")), TileHeight = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tLiveForm, "TileHeight")), IsUsingAbsolute = TheThing.GetSafePropertyBool(tLiveForm, "IsAbsolute"), AssociatedClassName = pScreenId.ToString() }; tInfo.MyStorageInfo.Add(tI); tI.FormFields = new List <TheFieldInfo>(); int fldNo = 10; foreach (TheThing tTh in tFields) { int tfldNo = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tTh, "FldOrder")); if (tfldNo == 0) { tfldNo = fldNo; } int tFlags = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tTh, "Flags")); cdeP ValProp = tTh.GetProperty("Value"); bool IsNewFld = true; TheFieldInfo tFldInfo = TheNMIEngine.GetFieldById(TheThing.GetSafePropertyGuid(tTh, "FldID")); if (tFldInfo == null) { tFldInfo = new TheFieldInfo(tTh, "Value", tfldNo, tFlags & 0xFFBF, tTh.GetBaseThing().cdeA); } else { tFldInfo.FldOrder = tfldNo; tFldInfo.Flags = tFlags; IsNewFld = false; } if (tFldInfo.PropertyBag == null) { tFldInfo.PropertyBag = new ThePropertyBag(); } ThePropertyBag.PropBagUpdateValue(tFldInfo.PropertyBag, "IsOnTheFly", "=", "True"); ThePropertyBag.PropBagUpdateValue(tFldInfo.PropertyBag, "UXID", "=", $"{tTh.cdeMID}"); tFldInfo.Header = tTh.FriendlyName; RegisterNMISubscription(tClientInfo, "Value", tFldInfo); string tControlType = TheThing.GetSafePropertyString(tTh, "ControlType"); if (TheCommonUtils.CInt(tControlType) == 0 && !TheCommonUtils.IsNullOrWhiteSpace(tControlType)) { tFldInfo.Type = eFieldType.UserControl; RegisterFieldEvents(tTh, ValProp, IsNewFld, tFldInfo, tControlType); } else { tFldInfo.Type = (eFieldType)TheCommonUtils.CInt(tControlType); } tFldInfo.DefaultValue = ValProp?.ToString(); tFldInfo.TileWidth = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tTh, "TileWidth")); tFldInfo.TileHeight = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(tTh, "TileHeight")); foreach (cdeP prop in tTh.GetNMIProperties()) { ThePropertyBag.PropBagUpdateValue(tFldInfo.PropertyBag, prop.Name, "=", prop.ToString()); } if (tFldInfo.Type == eFieldType.TileButton) { tTh.DeclareNMIProperty("IsDown", ePropertyTypes.TBoolean); ThePropertyBag.PropBagUpdateValue(tFldInfo.PropertyBag, "EnableTap", "=", "True"); tFldInfo.RegisterUXEvent(tTh, eUXEvents.OnPropertyChanged, "IsDown", (pThing, pObj) => { if (!(pObj is TheProcessMessage pMsg) || pMsg.Message == null) { return; } TheThing.SetSafePropertyBool(pThing, "IsDown", TheCommonUtils.CBool(pMsg.Message.PLS)); });
public Dictionary <string, object> ReadAll() { if (MyModFieldStore == null || MyModFieldStore.TheValues.Count == 0) { return(null); } var timestamp = DateTimeOffset.Now; var dict = new Dictionary <string, object>(); dict["Timestamp"] = timestamp; // Read configured data items via Modbus int tMainOffset = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "Offset"); int tSlaveAddress = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "SlaveAddress"); int tReadWay = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ConnectionType"); foreach (var field in MyModFieldStore.TheValues) { try { int address = field.SourceOffset + tMainOffset; ushort[] data = null; float scale = field.ScaleFactor; if (scale == 0) { scale = 1.0f; } switch (tReadWay) { case 1: { bool[] datab = MyModMaster.ReadCoils((ushort)address, (ushort)field.SourceSize); for (int i = 0; i < field.SourceSize && i < datab.Length; i++) { dict[$"{field.PropertyName}_{i}"] = datab[i]; } field.Value = dict[$"{field.PropertyName}_0"]; } continue; case 2: { bool[] datab = MyModMaster.ReadInputs((ushort)address, (ushort)field.SourceSize); for (int i = 0; i < field.SourceSize && i < datab.Length; i++) { dict[$"{field.PropertyName}_{i}"] = datab[i]; } field.Value = dict[$"{field.PropertyName}_0"]; } continue; case 4: data = MyModMaster.ReadInputRegisters((byte)tSlaveAddress, (ushort)address, (ushort)field.SourceSize); break; default: data = MyModMaster.ReadHoldingRegisters((byte)tSlaveAddress, (ushort)address, (ushort)field.SourceSize); break; } if (data == null) { continue; } if (field.SourceType == "float") { var value1 = TypeFloat.Convert(data, TypeFloat.ByteOrder.CDAB); dict[field.PropertyName] = value1 / scale; } else if (field.SourceType == "float-abcd") { var value1 = TypeFloat.Convert(data, TypeFloat.ByteOrder.ABCD); dict[field.PropertyName] = value1 / scale; } else if (field.SourceType == "double") { var value1 = TypeDouble.Convert(data, TypeDouble.ByteOrder.ABCD); dict[field.PropertyName] = value1 / scale; } else if (field.SourceType == "double-cdab") { var value1 = TypeDouble.Convert(data, TypeDouble.ByteOrder.CDAB); dict[field.PropertyName] = value1 / scale; } else if (field.SourceType == "int32") { var value = TypeInt32.Convert(data); var dblValue = Convert.ToDouble(value); dict[field.PropertyName] = dblValue / scale; } else if (field.SourceType == "int64") { var value = TypeInt64.Convert(data); var dblValue = Convert.ToDouble(value); dict[field.PropertyName] = dblValue / scale; } else if (field.SourceType == "float32") { var value = TypeFloat.Convert(data, TypeFloat.ByteOrder.SinglePrecIEEE); dict[field.PropertyName] = value / scale; } else if (field.SourceType == "uint16") { var value = TypeUInt16.Convert(data); dict[field.PropertyName] = value / scale; } else if (field.SourceType == "int16") { var value = TheCommonUtils.CInt(data[0]); dict[field.PropertyName] = value / scale; } else if (field.SourceType == "utf8") { var value = TypeUTF8.Convert(data); dict[field.PropertyName] = value; } else if (field.SourceType == "byte") { byte value = (byte)(data[0] & 255); dict[field.PropertyName] = value; } field.Value = dict[field.PropertyName]; //dict[$"[{field.PropertyName}].[Status]"] = $""; } catch (Exception e) { try { // Future: convey per-tag status similar to OPC statuscode? //dict[$"[{field.PropertyName}].[Status]"] = $"##cdeError: {e.Message}"; TheBaseAssets.MySYSLOG.WriteToLog(10000, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, $"Error reading property {field.PropertyName}", eMsgLevel.l2_Warning, e.ToString())); } catch { } } } return(dict); }
public override bool Init() { if (mIsInitCalled) { return(false); } mIsInitCalled = true; MyBaseThing.StatusLevel = 4; string temp; TheBaseAssets.MyCmdArgs.TryGetValue("IsHealthCollectionOff", out temp); if (!string.IsNullOrEmpty(temp)) { IsHealthCollectionOff = TheCommonUtils.CBool(temp); } if (HealthCollectionCycle == 0) { TheBaseAssets.MyCmdArgs.TryGetValue("HealthCollectionCycle", out temp); if (!string.IsNullOrEmpty(temp)) { HealthCollectionCycle = TheCommonUtils.CInt(temp); } if (HealthCollectionCycle == 0) { HealthCollectionCycle = 15; } } if (SensorDelay == 0) { TheBaseAssets.MyCmdArgs.TryGetValue("SensorDelay", out temp); if (!string.IsNullOrEmpty(temp)) { SensorDelay = TheCommonUtils.CInt(temp); } if (SensorDelay == 0) { SensorDelay = 500; } } if (SensorAccelDeadband < 1) { TheBaseAssets.MyCmdArgs.TryGetValue("SensorAccelDeadband", out temp); if (!string.IsNullOrEmpty(temp)) { SensorAccelDeadband = TheCommonUtils.CDbl(temp); } if (SensorAccelDeadband < 0.1) { SensorAccelDeadband = 3.0; } } int tBS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartValues"); if (tBS < 10) { tBS = 1000; TheThing.SetSafePropertyNumber(MyBaseThing, "ChartValues", tBS); } tBS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartSize"); if (tBS < 6) { tBS = 18; TheThing.SetSafePropertyNumber(MyBaseThing, "ChartSize", tBS); } TheUserManager.RegisterNewRole(new TheUserRole(new Guid("{0A254170-D4D4-4B2D-9E05-D471729BE739}"), "ComputerManager", 1, new Guid("{3FB56264-9AA8-4AC9-9208-A01F1142B153}"), true, "Person allowed to view Computer Details")); MyBaseThing.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage); //Event when C-DEngine has new Telegram for this service as a subscriber (Client Side) MyBaseThing.RegisterEvent("FileReceived", sinkFileReceived); MyBaseThing.RegisterEvent(eEngineEvents.ShutdownEvent, sinkEngineShutdown); StartEngineServices(); if (MyBaseThing.StatusLevel == 4) { MyBaseThing.StatusLevel = 1; } mIsInitialized = true; return(true); }
public override bool CreateUX() { if (mIsUXInitCalled) { return(false); } mIsUXInitCalled = true; MyPCVitalsDashboard = TheNMIEngine.AddDashboard(MyBaseThing, new TheDashboardInfo(MyBaseEngine, "Node Vitals") { PropertyBag = new ThePropertyBag() { "Category=Diagnostics", "Caption=Node Vitals", "Thumbnail=FA5:f108", } }); TheFormInfo tMyConfForm = new TheFormInfo(TheThing.GetSafeThingGuid(MyBaseThing, "Config"), eEngineName.NMIService, "Setting", string.Format("TheThing;:;0;:;True;:;cdeMID={0}", MyBaseThing.cdeMID)) { DefaultView = eDefaultView.Form, PropertyBag = new ThePropertyBag { "TileWidth=6" } }; TheNMIEngine.AddFormToThingUX(MyBaseThing, tMyConfForm, "CMyForm", "Settings", 1, 9, 0xC0, TheNMIEngine.GetNodeForCategory(), null, null); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.SingleCheck, 1, 2, 0xC0, "Disable Collection", "IsHealthCollectionOff"); //TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.SingleCheck, 2, 2, 0xC0, "Enable OHM", "EnableOHM"); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.Number, 10, 2, 0xC0, "Health Collection Cycle", "HealthCollectionCycle"); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.Number, 11, 2, 0xC0, "Sensor Delay", "SensorDelay"); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.Number, 12, 2, 0xC0, "Sensor Deadband", "SensorAccelDeadband"); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.Number, 13, 2, 0xC0, "Chart Values", "ChartValues", new nmiCtrlNumber { MinValue = 10 }); TheNMIEngine.AddSmartControl(MyBaseThing, tMyConfForm, eFieldType.Number, 14, 2, 0xC0, "Default Chart TileWidth", "ChartSize", new nmiCtrlNumber { MinValue = 6, MaxValue = 30 }); if (!TheCommonUtils.IsHostADevice()) { TheFormInfo tMyForm = new TheFormInfo() { cdeMID = new Guid("{A3765D29-8EFF-4F09-B5BC-E5CE4C7DEA6F}"), FormTitle = "CPU Details", defDataSource = "TheThing;:;0;:;True;:;DeviceType=CPUInfo" }; TheNMIEngine.AddFormToThingUX(MyBaseThing, tMyForm, "CMyTable", "CPUs", 2, 3, 0, "Live Tables", null, null); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 5, FldWidth = 4, Flags = 2, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Friendly Name", DataItem = "MyPropertyBag.FriendlyName.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 6, FldWidth = 2, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "HostURL", DataItem = "MyPropertyBag.HostUrl.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 11, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Speed", DataItem = "MyPropertyBag.MaxClockSpeed.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 12, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Cores", DataItem = "MyPropertyBag.NumberOfCores.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 13, FldWidth = 2, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Manufacturer", DataItem = "MyPropertyBag.Manufacturer.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 14, Flags = 0, cdeA = 0xC0, Type = eFieldType.SingleEnded, Header = "Architecture", DataItem = "MyPropertyBag.AddressWidth.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 15, Flags = 0, cdeA = 0xC0, Type = eFieldType.SingleEnded, Header = "Rev", DataItem = "MyPropertyBag.Revision.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 16, Flags = 0, cdeA = 0xC0, Type = eFieldType.SingleEnded, Header = "L2 Cache", DataItem = "MyPropertyBag.L2CacheSize.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 17, Flags = 0, cdeA = 0xC0, Type = eFieldType.SingleEnded, Header = "Version", DataItem = "MyPropertyBag.Version.Value" }); TheNMIEngine.AddField(tMyForm, new TheFieldInfo() { FldOrder = 80, FldWidth = 2, cdeA = 0xFF, Type = eFieldType.DateTime, Header = "Last Update", DataItem = "MyPropertyBag.LastUpdate.Value" }); TheFormInfo tMyHForm = new TheFormInfo() { cdeMID = new Guid("{33170B1F-CA19-4DC6-A18F-15B5F7669E0A}"), FormTitle = "PC Health Details", defDataSource = "TheThing;:;0;:;True;:;DeviceType=PC-Health" }; TheNMIEngine.AddFormToThingUX(MyBaseThing, tMyHForm, "CMyTable", "PC Health", 3, 3, 0, "Live Tables", null, null); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 5, FldWidth = 3, Flags = 2, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Friendly Name", DataItem = "MyPropertyBag.FriendlyName.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 6, FldWidth = 2, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "HostAddress", DataItem = "MyPropertyBag.HostAddress.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 7, FldWidth = 3, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Host Version", DataItem = "MyPropertyBag.HostVersion.Value" }); //TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 8, Flags = 0, cdeA = 0xC0, Type = eFieldType.SingleEnded, Header = "Station Roles", DataItem = "MyPropertyBag.StationRoles.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 11, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "CPU Load", DataItem = "MyPropertyBag.CPULoad.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 13, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "CPU Temp", DataItem = "MyPropertyBag.CPUTemp.Value" }); //TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 14, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Core Temps", DataItem = "MyPropertyBag.CoreTemps.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 21, FldWidth = 2, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "RAM Available", DataItem = "MyPropertyBag.RAMAvailable.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 22, FldWidth = 2, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "PC Uptime", DataItem = "MyPropertyBag.PCUptime.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 23, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "Watts", DataItem = "MyPropertyBag.StationWatts.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 31, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "cdeUptime", DataItem = "MyPropertyBag.cdeUptime.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 32, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "cdeHandles", DataItem = "MyPropertyBag.cdeHandles.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 33, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "cdeWorkingSetSize", DataItem = "MyPropertyBag.cdeWorkingSetSize.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 34, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "cdeThreadCount", DataItem = "MyPropertyBag.cdeThreadCount.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 35, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "EventTimeOuts", DataItem = "MyPropertyBag.TotalEventTimeouts.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 36, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "QSenders", DataItem = "MyPropertyBag.QSenders.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 37, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "TSM Inserts", DataItem = "MyPropertyBag.QSInserted.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 38, Flags = 0, cdeA = 0x0, Type = eFieldType.SingleEnded, Header = "TSM Sents", DataItem = "MyPropertyBag.QSSent.Value" }); TheNMIEngine.AddField(tMyHForm, new TheFieldInfo() { FldOrder = 80, FldWidth = 2, cdeA = 0xFF, Type = eFieldType.DateTime, Header = "Last Update", DataItem = "MyPropertyBag.LastUpdate.Value" }); } if (!TheBaseAssets.MyServiceHostInfo.IsCloudService) { int tBS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartValues"); if (tBS < 10) { tBS = 10; } if (tBS > 10000) { tBS = 10000; } int tCS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartSize"); if (tCS < 6) { tCS = 6; } TheNMIEngine.AddChartScreen(MyBaseThing, new TheChartDefinition(TheThing.GetSafeThingGuid(MyBaseThing, "CPUState"), "Computer CPU State", tBS, "TheHealthHistory", true, "", "PB.HostAddress", "PB.CPULoad;PB.CPUTemp;PB.RAMAvailable") { GroupMode = 0, IntervalInMS = 0 }, 2, 3, 0, TheNMIEngine.GetNodeForCategory(), false, new ThePropertyBag() { ".TileHeight=8", ".NoTE=true", $".TileWidth={tCS}", $"Header={TheNMIEngine.GetNodeForCategory()}" }); TheNMIEngine.AddChartScreen(MyBaseThing, new TheChartDefinition(TheThing.GetSafeThingGuid(MyBaseThing, "CDERes"), "CDE Resources", tBS, "TheHealthHistory", true, "", "PB.HostAddress", "PB.cdeHandles;PB.cdeWorkingSetSize") { GroupMode = 0, IntervalInMS = 0 }, 5, 3, 0, TheNMIEngine.GetNodeForCategory(), false, new ThePropertyBag() { ".TileHeight=8", ".NoTE=true", $".TileWidth={tCS}", $"Header={TheNMIEngine.GetNodeForCategory()}" }); TheNMIEngine.AddChartScreen(MyBaseThing, new TheChartDefinition(TheThing.GetSafeThingGuid(MyBaseThing, "CDEKPIs"), "CDE KPIs", tBS, "TheHealthHistory", true, "", "PB.HostAddress", "PB.QSenders;PB.QSLocalProcessed;PB.QSSent;PB.QKBSent;PB.QKBReceived;PB.QSInserted;PB.EventTimeouts;PB.TotalEventTimeouts;PB.CCTSMsRelayed;PB.CCTSMsReceived;PB.CCTSMsEvaluated;PB.HTCallbacks;PB.KPI1;PB.KPI2;PB.KPI3;PB.KPI4;PB.KPI5;PB.KPI10") { GroupMode = 0, IntervalInMS = 0 }, 5, 3, 0, TheNMIEngine.GetNodeForCategory(), false, new ThePropertyBag() { ".TileHeight=8", ".NoTE=true", $".TileWidth={tCS}", $"Header={TheNMIEngine.GetNodeForCategory()}" }); if (!TheCommonUtils.IsOnLinux()) { var tMyLiveForm = TheNMIEngine.AddStandardForm(MyBaseThing, "Live CPU Chart", 18, "CPULoad", null, 0, TheNMIEngine.GetNodeForCategory()); (tMyLiveForm["Header"] as TheFieldInfo).Header = $"{TheNMIEngine.GetNodeForCategory()} CPU Chart"; var tc = TheNMIEngine.AddSmartControl(MyBaseThing, tMyLiveForm["Form"] as TheFormInfo, eFieldType.UserControl, 22, 0, 0, "CPU Load", "LoadBucket", new ThePropertyBag() { "ParentFld=1", "ControlType=Line Chart", "Title=CPU Load", "SubTitle=" + GetProperty("HostAddress", true), "SeriesNames=[{ \"name\":\"CPU-Load\", \"lineColor\":\"rgba(0,255,0,0.39)\"}, { \"name\":\"CDE-Load\", \"lineColor\":\"rgba(0,0,255,0.39)\"}]", "TileHeight=4", "Speed=800", "Delay=0", "Background=rgba(0,0,0,0.01)", "MaxValue=100", "NoTE=true" }); tc.AddOrUpdatePlatformBag(eWebPlatform.Any, new nmiPlatBag { TileWidth = 18 }); tc.AddOrUpdatePlatformBag(eWebPlatform.Mobile, new nmiPlatBag { TileWidth = 6 }); tc.AddOrUpdatePlatformBag(eWebPlatform.HoloLens, new nmiPlatBag { TileWidth = 12 }); } } if (TheCommonUtils.CBool(TheBaseAssets.MySettings.GetSetting("PCVitalsMaster"))) { TheFormInfo tMyFormUp = TheNMIEngine.AddForm(new TheFormInfo(MyBaseThing) { cdeMID = TheThing.GetSafeThingGuid(MyBaseThing, "THHUPLOAD"), FormTitle = "PC Vitals Uploader", DefaultView = eDefaultView.Form }); TheNMIEngine.AddFormToThingUX(MyBaseThing, tMyFormUp, "CMyForm", "PC Vitals Uploader", 3, 13, 0x80, TheNMIEngine.GetNodeForCategory(), null, new nmiDashboardTile { TileThumbnail = "FA3:f093", }); TheNMIEngine.AddSmartControl(MyBaseThing, tMyFormUp, eFieldType.DropUploader, 3, 2, 128, "Drop a TheHealthHistory-file here", null, new nmiCtrlDropUploader { TileHeight = 6, NoTE = true, TileWidth = 6, EngineName = MyBaseEngine.GetEngineName(), MaxFileSize = 10000000 }); FindTHHFiles(); } TheNMIEngine.AddPageDefinitions(new List <ThePageDefinition> { { new ThePageDefinition(new Guid("{7FED3369-AF7C-451F-9ED1-71131BB993F4}"), "/PCHEALTH", "Health Info", "", Guid.Empty) { WPID = 10, IncludeCDE = true, RequireLogin = false, PortalGuid = MyBaseEngine.GetDashboardGuid(), StartScreen = MyBaseEngine.GetDashboardGuid() } }, }); TheNMIEngine.AddAboutButton(MyBaseThing); TheNMIEngine.RegisterEngine(MyBaseEngine); mIsUXInitialized = true; return(true); }
internal static void ToThingProperties(TheThing pThing, bool bReset) { lock (thingHarvestLock) { if (pThing == null) { return; } if (KPIIndexes == null) { CreateKPIIndexes(); } if (KPIs == null) { KPIs = new long[KPIIndexes.Count]; } if (KPIs != null && KPIIndexes != null) { TimeSpan timeSinceLastReset = DateTimeOffset.Now.Subtract(LastReset); bool resetReady = timeSinceLastReset.TotalMilliseconds >= 1000; foreach (var keyVal in KPIIndexes.GetDynamicEnumerable()) { bool donres = doNotReset.Contains(keyVal.Key); long kpiValue; if (bReset && !donres && resetReady) { kpiValue = Interlocked.Exchange(ref KPIs[keyVal.Value], 0); } else { kpiValue = Interlocked.Read(ref KPIs[keyVal.Value]); } // LastReset not set yet - shouldn't happen since it is set in first call to Reset (TheBaseAssets.InitAssets) if (LastReset == DateTimeOffset.MinValue || timeSinceLastReset.TotalSeconds <= 1 || donres) { pThing.SetProperty(keyVal.Key, kpiValue); } else { pThing.SetProperty(keyVal.Key, kpiValue / timeSinceLastReset.TotalSeconds); // Normalize value to "per second" } if (!doNotComputeTotals.Contains(keyVal.Key)) { pThing.SetProperty(keyVal.Key + "Total", TheThing.GetSafePropertyNumber(pThing, keyVal.Key + "Total") + kpiValue); } } if (bReset && resetReady) { LastReset = DateTimeOffset.Now; } // Grab some KPIs from sources - Workaround, this should be computed in the source instead SetKPI(eKPINames.QSenders, TheQueuedSenderRegistry.GetSenderListNodes().Count); SetKPI(eKPINames.QSenderInRegistry, TheQueuedSenderRegistry.Count()); SetKPI(eKPINames.SessionCount, TheBaseAssets.MySession.GetSessionCount()); SetKPI(eKPINames.UniqueMeshes, TheQueuedSenderRegistry.GetUniqueMeshCount()); SetKPI(eKPINames.UnsignedNodes, TheQueuedSenderRegistry.GetUnsignedNodeCount()); SetKPI(eKPINames.KnownNMINodes, Engines.NMIService.TheFormsGenerator.GetNMINodeCount()); SetKPI(eKPINames.StreamsNotFound, Communication.HttpService.TheHttpService.IsStreaming.Count); SetKPI(eKPINames.BlobsNotFound, Engines.ContentService.TheContentServiceEngine.BlobsNotHere.Count); } } }
public override bool DoCreateUX() { var tFlds = TheNMIEngine.AddStandardForm(MyBaseThing, null, null, 0, new nmiStandardForm { IconUpdateName = "Value", MaxTileWidth = 12, UseMargin = true }); MyStatusForm = tFlds["Form"] as TheFormInfo; MyStatusForm.ModelID = "CountdownForm"; ThePropertyBag tDash = new nmiDashboardTile() { ClassName = "cdeDashPlate", Caption = "Loading... <i class='fa fa-spinner fa-pulse'></i>", TileWidth = 2, TileHeight = 2, HTML = "<div><div id='COUNTD%cdeMID%'></div><p><%C20:FriendlyName%></p></div>", //TODO:SETP Move to Generate Screen for all HTML blocks! Style = "background-image:none;color:white;background-color:gray", RSB = true, RenderTarget = "HomeCenterStage" }; SummaryForm = tFlds["DashIcon"] as TheDashPanelInfo; SummaryForm.PropertyBag = tDash; SummaryForm.RegisterPropertyChanged(sinkStatChanged); tGauge = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CircularGauge, 4000, 2, 0, "Countdown", "Value", new ThePropertyBag() { "TileWidth=2", "NoTE=true", "RenderTarget=COUNTD%cdeMID%", "LabelForeground=#00b9ff", "Foreground=#FFFFFF" }); var ts = TheNMIEngine.AddStatusBlock(MyBaseThing, MyStatusForm, 10); ts["Group"].SetParent(1); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 150, 2, 128, "###CDMyVThings.TheVThings#Settings796959#Settings...###", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup() { DoClose = true, TileWidth = 6, IsSmall = true, ParentFld = 1 })); TheFieldInfo mSendbutton = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 151, 2, 0, "###CDMyVThings.TheVThings#Trigger796959#Trigger###", false, "", null, new nmiCtrlTileButton() { NoTE = true, ParentFld = 150, ClassName = "cdeGoodActionButton" }); mSendbutton.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) => { if (mTimer != null) { mTimer.Dispose(); mTimer = null; } sinkTriggered(this.GetProperty(nameof(StartValue), false)); //UpdateUx(); }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 152, 2, MyBaseThing.cdeA, "###CDMyVThings.TheVThings#StartValue633339#Start Value###", nameof(StartValue), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 150 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 153, 2, MyBaseThing.cdeA, "###CDMyVThings.TheVThings#Ticktimeinms633339#Tick time in ms###", nameof(Frequency), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 150 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleCheck, 154, 2, MyBaseThing.cdeA, "###CDMyVThings.TheVThings#ContinueonRestart992144#Continue on Restart###", nameof(AutoStart), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 150 }); TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleCheck, 155, 2, MyBaseThing.cdeA, "###CDMyVThings.TheVThings#StartOverwhenzero992144#Start Over when zero###", nameof(Restart), new nmiCtrlNumber { TileWidth = 3, TileHeight = 1, ParentFld = 150 }); int tControl = TheCommonUtils.CInt(TheThing.GetSafePropertyNumber(MyBaseThing, "ControlType")); ThePropertyBag tBag = ThePropertyBag.CreateUXBagFromProperties(MyBaseThing); tBag.Add("ParentFld=1"); if (tControl > 0) { CountBar = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, (eFieldType)tControl, 100, 2, MyBaseThing.cdeA, "CurrentValue", "Value", tBag); } else { TheThing.SetSafePropertyString(MyBaseThing, "ControlType", "34"); TheThing.SetSafePropertyString(MyBaseThing, "NoTE", "true"); TheThing.SetSafePropertyString(MyBaseThing, "TileWidth", "6"); TheThing.SetSafePropertyString(MyBaseThing, "TileHeight", "1"); CountBar = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.BarChart, 100, 2, MyBaseThing.cdeA, "CurrentValue", "Value", new nmiCtrlBarChart() { NoTE = true, TileWidth = 6, TileHeight = 1, ParentFld = 10 }); } return(true); }
void sinkUpdateUX2(cdeP prop) { string Plotband; if (TheThing.GetSafePropertyBool(MyBaseThing, "IsLowAlarm")) { Plotband = $"SubTitle={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorUnit")}:;:PlotBand=[{{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMinValue")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"color\": \"#FF000088\" }}, {{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue")}, \"color\": \"#00FF0044\" }}]"; } else { Plotband = $"SubTitle={TheThing.GetSafePropertyString(MyBaseThing, "StateSensorUnit")}:;:PlotBand=[{{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMinValue")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"color\": \"#00FF0088\" }}, {{ \"from\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorAverage")}, \"to\": {TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue")}, \"color\": \"#FF000044\" }}]"; } GaugeFld?.SetUXProperty(Guid.Empty, Plotband); }
public virtual void DoCreateUX(TheFormInfo tMyForm, ThePropertyBag pChartControlBag = null) { var tQVN = TheThing.GetSafePropertyString(MyBaseThing, "StateSensorValueName"); //var tQV = TheThing.GetSafePropertyString(MyBaseThing, "StateSensorValue"); var tQU = TheThing.GetSafePropertyString(MyBaseThing, "StateSensorUnit"); TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.TileGroup, 12460, 0, 0, null, null, new nmiCtrlTileGroup { ParentFld = 12011, TileWidth = 6, TileHeight = 3 }); ValueField = TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.SmartLabel, 12461, 0, 0, $"{tQVN}", "QValue", new nmiCtrlSmartLabel { ParentFld = 12460, TileWidth = 6, TileFactorY = 2, TileHeight = 3, FontSize = 96 }); TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.SmartLabel, 12462, 0, 0, $"{tQU}", "StateSensorUnit", new nmiCtrlSmartLabel { ParentFld = 12460, NoTE = true, TileWidth = 6, TileFactorY = 2, TileHeight = 1, FontSize = 18, HorizontalAlignment = "right", VerticalAlignment = "top" }); var tG = TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.TileGroup, 12000, 0, 0, null, null, new nmiCtrlTileGroup() { TileWidth = 18 }); tG.AddOrUpdatePlatformBag(eWebPlatform.Mobile, new nmiPlatBag { MaxTileWidth = 6 }); tG.AddOrUpdatePlatformBag(eWebPlatform.HoloLens, new nmiPlatBag { MaxTileWidth = 12 }); tG.AddOrUpdatePlatformBag(eWebPlatform.TeslaXS, new nmiPlatBag { MaxTileWidth = 12 }); string pSensorPicSource = TheThing.GetSafePropertyString(MyBaseThing, "StateSensorLogo"); if (string.IsNullOrEmpty(pSensorPicSource)) { pSensorPicSource = "SENSORS/Images/SensorLogo_156x78.png"; } TheSensorNMI.CreatePerformanceHeader(MyBaseThing, tMyForm, 12010, 12000, pSensorPicSource); TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.CollapsibleGroup, 12030, 2, 0, $"Live Chart", null, new nmiCtrlCollapsibleGroup() { ParentFld = 12000, TileWidth = 6, NoTE = true, Background = "transparent", Foreground = "black", FontSize = 10, IsSmall = true, HorizontalAlignment = "left" }); //LabelClassName = "cdeTileGroupHeaderSmall SensorGroupLabel", LabelForeground = "white", LiveChartFld = TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.UserControl, 12031, 2, 0, $"{tQVN} Chart", "QValue", new ThePropertyBag() { "ControlType=Live Chart", "ParentFld=12030", "NoTE=true", $"Title={tQVN}", "SeriesNames=[{ \"name\":\"Current Temp\", \"lineColor\":\"rgba(0,255,0,0.39)\"}, { \"name\":\"Max Temp\", \"lineColor\":\"rgba(0,0,255,0.64)\"}]", "TileWidth=6", "TileHeight=4", "Speed=500", $"MaxValue={TheThing.GetSafePropertyNumber(MyBaseThing, "StateSensorMaxValue")}", "Delay=0", "Background=rgba(0,0,0,0.01)" }); TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.CollapsibleGroup, 12040, 2, 0, "Distribution Curve", null, new nmiCtrlCollapsibleGroup() { ParentFld = 12000, TileWidth = 6, NoTE = true, Background = "transparent", Foreground = "black", FontSize = 10, IsSmall = true, HorizontalAlignment = "left" }); //LabelClassName = "cdeTileGroupHeaderSmall SensorGroupLabel", LabelForeground = "white", BucketChartFld = TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.UserControl, 12041, 0, 0, $"{tQVN} Chart", "BucketChart", new ThePropertyBag() { "NoTE=true", "ParentFld=12040", $"SubTitle={tQVN}", $"SetSeries={{\"name\": \"{tQVN}\"}}", "TileWidth=6", "TileHeight=4", "ControlType=Stack Chart", $"XAxis={{ \"categories\": {mBucket?.GetBuckets()} }}", $"iValue={mBucket?.GetBucketArray()}" }); TheSensorNMI.CreateDeviceDetails(MyBaseThing, tMyForm, 12060, 12000, null); // new List<string> { $"{tQVN},{tQV}" }); if (pChartControlBag == null) { pChartControlBag = new ThePropertyBag { "DoClose=true" } } ; else { ThePropertyBag.PropBagUpdateValue(pChartControlBag, "DoClose", "=", "true"); } var tt = MyHistorian?.CreateHistoryTrendUX(tMyForm, 12300, 12000, $"{tQVN} Trend", $"{tQVN} Trend", TheThing.GetSafePropertyString(MyBaseThing, "HistoryFields"), false, false, pChartControlBag); }