/// <summary> /// Activates a given rule /// </summary> /// <param name="pRuleID">ID To activate</param> /// <param name="pTurnActive">if true, the rule will be activated otherwise deactivated</param> /// <returns></returns> public static bool ActivateRule(Guid pRuleID, bool pTurnActive) { InitRR(); if (MyRulesRegistry != null) { ICDEThing pRule = TheThingRegistry.GetThingByID(eEngineName.ThingService, pRuleID.ToString()); if (pRule != null) { try { if (pRule.GetBaseThing().GetObject() is TheThingRule tRule) { tRule.IsRuleActive = pTurnActive; MyRulesRegistry.ActivateRules(); return(true); } } catch { //ignored } } } return(false); }
void sinkUpdated(ICDEThing sender, object inObj) { if (TheBaseAssets.MyServiceHostInfo.IsCloudService) { return; } TheThing pThing = sender.GetBaseThing(); if (pThing != null) { TheRule tRule = pThing.GetObject() as TheRule; if (tRule != null) { if (tRule.IsRuleActive) { ActivateRules(); } else { RemoveTrigger(tRule, true); } } } }
private void WriteAggregatedConditionsToProperty(ICDEThing tEventHost, DateTimeOffset time) { var currentConditionsAsJson = TheCommonUtils.SerializeObjectToJSONString(_currentConditionsByConditionId.Values.OrderByDescending(evnt => { if (evnt.TryGetValue("Time", out var evntTime)) { return(evntTime); } return(null); }).ToList()); if (TheThing.GetSafePropertyString(tEventHost.GetBaseThing(), DisplayName) != currentConditionsAsJson) { TheBaseAssets.MySYSLOG.WriteToLog(78102, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(MyOPCServer.GetBaseThing().EngineName, $"Updated current events {_currentConditionsByConditionId.Count} - {currentConditionsAsJson}", eMsgLevel.l6_Debug, $"{DisplayName} {GetNodeIdForLogs()} {EventInfo.AggregateRetainedConditions}")); // Using publish time because the event timestamps could be way in the past (i.e. when a recent event just was removed) tEventHost.GetBaseThing().SetProperty(DisplayName, currentConditionsAsJson, time); } else { TheBaseAssets.MySYSLOG.WriteToLog(78102, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(MyOPCServer.GetBaseThing().EngineName, $"No change to current events {_currentConditionsByConditionId.Count} - {currentConditionsAsJson}", eMsgLevel.l6_Debug, $"{DisplayName} {GetNodeIdForLogs()} {EventInfo.AggregateRetainedConditions}")); } }
/// <summary> /// Probes if a rule with the given ID exists /// </summary> /// <param name="pRuleID">ID to probe for</param> /// <returns></returns> public static bool HasRuleID(Guid pRuleID) { InitRR(); if (MyRulesRegistry != null) { ICDEThing pRule = TheThingRegistry.GetThingByID(eEngineName.ThingService, pRuleID.ToString()); if (pRule != null) { try { if (pRule.GetBaseThing().GetObject() is TheThingRule tRule) { return(true); } } catch { //ignored } } } return(false); }
/// <summary> /// Clones all TheThing properties and returns a TheThingStore class /// </summary> /// <param name="iThing">The Thing to clone.</param> /// <param name="ResetBase">Use current time instead of Thing timestamp</param> /// <param name="bUsePropertyTimestamp">Use latest timestamp of any of the properties</param> /// <param name="cloneProperties">Indiciates if current properties and their of the iThing should be added to TheThingStore.PB of only an empty PB should be returned.</param> /// <param name="cloneFilter">When cloning, indicates which properties to include. If null, all properties of the thing are included.</param> /// <returns></returns> internal static TheThingStore CloneFromTheThingInternal(ICDEThing iThing, bool ResetBase, bool bUsePropertyTimestamp, bool cloneProperties, ThePropertyFilter cloneFilter) { TheThingStore tThing = new TheThingStore(); if (iThing == null) { return(tThing); } TheThing pThing = iThing.GetBaseThing(); if (pThing != null) { if (ResetBase) { tThing.cdeCTIM = !bUsePropertyTimestamp ? DateTimeOffset.Now : DateTimeOffset.MinValue; tThing.cdeMID = Guid.NewGuid(); } else { tThing.cdeCTIM = pThing.cdeCTIM; tThing.cdeMID = pThing.cdeMID; } tThing.cdeAVA = pThing.cdeAVA; tThing.cdeA = pThing.cdeA; tThing.cdeEXP = pThing.cdeEXP; tThing.cdePRI = pThing.cdePRI; tThing.cdeF = pThing.cdeF; tThing.cdeM = pThing.cdeM; tThing.cdeN = pThing.cdeN; //tThing.cdeO = pThing.cdeO; tThing.cdeO = pThing.cdeMID; //CODE-REVIEW: Since tThing is a "TheThingStore" and is "owned" by the pThing, the cdeO (Owner) property should be updated. Does this break anything for TDS01 etc??? //tThing.OwnerThingMID = pThing.cdeMID; //Alternative we need to add a OwnerThingMID to TheThingStore to be able to segregate retrieval of TheThingStore records from the SQL Server tThing.cdeSEQ = pThing.cdeSEQ; if (cloneProperties) { var propertiesToInclude = pThing.GetMatchingProperties(cloneFilter); int propsIncludeCount = 0; foreach (string key in propertiesToInclude) { try { cdeP prop; if ((prop = pThing.GetProperty(key)) != null) // .MyPropertyBag.TryGetValue(key, out prop)) { //if (prop.CheckAndResetTouchedSinceLastHistorySnapshot() || cloneProperties) // Have to always check and reset, so do this first { tThing.PB[key] = prop.Value; if (bUsePropertyTimestamp) { if (prop.cdeCTIM > tThing.cdeCTIM) { if (tThing.cdeCTIM.Ticks != 0 && tThing.PB.Count > 1) { TheBaseAssets.MySYSLOG.WriteToLog(1, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(eEngineName.ThingService, "Historian timestamp changed by property when cloning for snapshot", eMsgLevel.l6_Debug, $"{prop.Name}: {tThing.cdeCTIM:O} changed to {prop.cdeCTIM:O}. Possible victims: {tThing.PB.Aggregate("", (s, kv) => kv.Key != prop.Name ? $"{s}{kv.Key}," : s)}")); } tThing.cdeCTIM = prop.cdeCTIM; } else if (prop.cdeCTIM != tThing.cdeCTIM) { TheBaseAssets.MySYSLOG.WriteToLog(1, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(eEngineName.ThingService, "Historian timestamp on property not applied when cloning for snapshot", eMsgLevel.l6_Debug, $"{prop.Name}: {prop.cdeCTIM:O} changed to {tThing.cdeCTIM:O}. Possible offenders: {tThing.PB.Aggregate("", (s, kv) => kv.Key != prop.Name ? $"{s}{kv.Key}," : s)}")); } } } } } catch (Exception) { //ignored } propsIncludeCount++; } if (tThing.cdeCTIM == DateTimeOffset.MinValue) { tThing.cdeCTIM = pThing.cdeCTIM; } // We have all properties that are available in the thing as of this time and that are requested: this snapshot can and will now be used as the basis to report unchanged properties tThing.IsFullSnapshot = true; } } return(tThing); }