Пример #1
0
        public virtual bool Init()
        {
            if (mIsInitCalled)
            {
                return(false);
            }
            mIsInitCalled = true;

            if (string.IsNullOrEmpty(MyBaseThing.ID))
            {
                MyBaseThing.ID = Guid.NewGuid().ToString();
                this.Gen_Config_StatsUpdateInterval = 5000;
            }
            MyBaseThing.Value = "0";
            TheThing.SetSafePropertyBool(MyBaseThing, "IsActive", true);
            MyBaseThing.GetProperty(nameof(Gen_Config_PropertyUpdateInterval), true).RegisterEvent(eThingEvents.PropertyChanged, OnChangeTimer);
            MyBaseThing.GetProperty(nameof(Gen_Config_NumberOfActiveProperties), true).RegisterEvent(eThingEvents.PropertyChanged, OnChangeTimer);
            MyBaseThing.StatusLevel = 0;
            if (TheThing.GetSafePropertyBool(MyBaseThing, "AutoStart"))
            {
                OnChangeTimer(null);
            }
            mIsInitialized = true;
            return(true);
        }
Пример #2
0
        public virtual bool Init()
        {
            if (mIsInitCalled)
            {
                return(false);
            }
            mIsInitCalled = true;
            IsStarted     = false;
            if (string.IsNullOrEmpty(MyBaseThing.ID))
            {
                MyBaseThing.ID = Guid.NewGuid().ToString();
            }

            if (MyBaseThing.GetProperty(nameof(PlaybackSpeedFactor), false) == null)
            {
                PlaybackSpeedFactor = 1;
            }
            if (MyBaseThing.GetProperty(nameof(InputFileName), false) == null)
            {
                InputFileName = "meshsenderdata.log";
            }
            if (MyBaseThing.GetProperty(nameof(ParallelPlaybackCount), false) == null)
            {
                ParallelPlaybackCount = 1;
            }

            MyBaseThing.RegisterOnChange(nameof(ParallelPlaybackCount), (o) => {
                if (IsStarted)
                {
                    StopPlaybackAsync("Changed number of things").ContinueWith(t => StartPlaybackAsync(false));
                }
            });

            MyBaseThing.Value       = "0";
            IsActive                = true;
            MyBaseThing.StatusLevel = 0;
            if (AutoStart)
            {
                TheCommonUtils.cdeRunAsync("DataPLayerAutostart", true, async o =>
                {
                    //if (AutoStartDelay > 0)
                    //{
                    //    await TheCommonUtils.TaskDelayOneEye(AutoStartDelay, 100);
                    //}
                    await StartPlaybackAsync(true);
                });
            }

            MyBaseThing.RegisterEvent(eEngineEvents.FileReceived, sinkFileReceived);

            mIsInitialized = true;
            return(true);
        }
Пример #3
0
        public void DeclareSecurePropertyTest()
        {
            var testPW    = "testpassword123YYY###$$$";
            var testThing = new TheThing();

            TheThing.SetSafePropertyString(testThing, "Password", testPW);

            var testPWReadNotEncrypted = TheThing.GetSafePropertyString(testThing, "Password");

            Assert.AreSame(testPW, testPWReadNotEncrypted, "Failed to read ununecrypted property");

            testThing.DeclareSecureProperty("Password", ePropertyTypes.TString);

            var testPWReadNotEncryptedObject = testThing.GetProperty("Password").Value;

            Assert.IsTrue(testPWReadNotEncryptedObject is string, $"Encrypted password is not of type string. Type: {testPWReadNotEncryptedObject.GetType()}");
            var testPWReadObjectString = testPWReadNotEncryptedObject as string;

            Assert.AreNotSame(testPW, testPWReadObjectString, "Password not encrypted after transition from unsecure to secure property");

            Assert.IsTrue((testPWReadNotEncryptedObject as string).StartsWith("&^CDESP1^&:"), "Encrypted string does not have expected encryption prefix");
            var testPWReadDecryptedString = TheThing.GetSafePropertyString(testThing, "Password");

            Assert.AreEqual(testPW, testPWReadDecryptedString, "Password not preserved after transition from unsecure to secure property");
        }
Пример #4
0
        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);
        }
Пример #5
0
        private void RemoveTrigger(TheRule tRule, bool DoForce)
        {
            if (TheCDEngines.MyThingEngine == null || !TheBaseAssets.MasterSwitch)
            {
                return;
            }
            if (tRule.IsRuleActive || DoForce)
            {
                if (TheThingRegistry.HasThingsWithFunc(MyBaseEngine.GetEngineName(), s => s.cdeMID != tRule.GetBaseThing().cdeMID&&
                                                       TheThing.GetSafePropertyString(s, "TriggerObject") == tRule.TriggerObject && TheThing.GetSafePropertyBool(s, "IsRuleActive")))
                {
                    return;
                }
                switch (tRule.TriggerObjectType)
                {
                default:
                    TheThing tTriggerThing = TheThingRegistry.GetThingByMID("*", TheCommonUtils.CGuid(tRule.TriggerObject));
                    if (tTriggerThing != null)
                    {
                        cdeP tProp = tTriggerThing.GetProperty(tRule.TriggerProperty);
                        if (tProp != null)
                        {
                            tProp.UnregisterEvent(eThingEvents.PropertyChanged, sinkRuleAction);
                        }
                    }
                    break;

                case "CDE_ENGINE":
                    TheThing tBase = TheThingRegistry.GetBaseEngineAsThing(tRule.TriggerObject);
                    if (tBase != null)
                    {
                        tBase.UnregisterEvent(eEngineEvents.IncomingMessage, sinkRuleIncoming);
                    }
                    break;

                case "CDE_EVENTFIRED":
                    TheThing tBaseE = TheThingRegistry.GetThingByID("*", tRule.TriggerObject);
                    if (tBaseE != null)
                    {
                        tBaseE.UnregisterEvent(tRule.TriggerProperty, sinkRuleThingEvent);
                    }
                    break;
                }
                tRule.IsRuleActive  = false;
                tRule.IsRuleRunning = false;
                tRule.IsRuleWaiting = true;
            }
        }
Пример #6
0
        internal override string RegisterInHostThing()
        {
            string error = null;

            string   propertyName = DisplayName;
            TheThing targetThing  = null;

            if (this.IsSubscribedAsThing)
            {
                // Dedicated event thing
                targetThing = MyBaseThing;
            }
            if (this.IsSubscribedAsProperty)
            {
                // This is an external, multi-event thing: use the browsepath to avoid collisions with properties from multiple events
                targetThing = this.GetHostThing().GetBaseThing();
            }
            if (targetThing != null)
            {
                var prop       = targetThing.GetProperty(propertyName, true);
                var sensorMeta = prop.GetSensorMeta();
                prop = targetThing.DeclareSensorProperty(propertyName, ePropertyTypes.NOCHANGE, sensorMeta);
                if (prop != null)
                {
                    var opcSubscriptionInfo = new TheOPCSensorSubscription
                    {
                        SampleRate    = this.SampleRate,
                        SensorId      = this.NodeIdName,
                        ChangeTrigger = this.ChangeTrigger,
                        DeadbandValue = this.DeadbandFilterValue,
                        EventInfo     = this.EventInfo,
                    };

                    var providerInfo = new cdeP.TheProviderInfo(this.MyOPCServer.GetBaseThing(), opcSubscriptionInfo);
                    prop.SetSensorProviderInfo(providerInfo);
                }
                else
                {
                    error = "ERROR: Property not found";
                }
            }
            else
            {
                error = "ERROR: Thing not found";
            }
            return(error);
        }
Пример #7
0
 internal static TheThing RegisterNMISubscription(TheClientInfo pClientInfo, string pDataItem, TheMetaDataBase tFld)
 {
     if (!string.IsNullOrEmpty(pDataItem))
     {
         TheThing tThing = null;
         lock (MyNMIElements.MyLock) //This can cause jams of threads here! Highly optimized to get out of lock as fast as possible
         {
             if (!MyNMIElements.ContainsKey(tFld.cdeMID))
             {
                 MyNMIElements.TryAdd(tFld.cdeMID, new cdeConcurrentDictionary <Guid, TheNMISubscription>());
             }
             if (!MyNMIElements[tFld.cdeMID].ContainsKey(pClientInfo.NodeID))
             {
                 tThing = TheThingRegistry.GetThingByMID(tFld.cdeO); //Most expensive call in here
                 if (tThing != null)
                 {
                     var tNewEle = new TheNMISubscription()
                     {
                         cdeN = pClientInfo.NodeID, cdeO = tThing.cdeMID, HasLiveSub = true, DataItem = pDataItem, cdeMID = tFld.cdeMID
                     };
                     MyNMIElements[tFld.cdeMID].TryAdd(pClientInfo.NodeID, tNewEle);
                 }
             }
         }
         if (tThing != null)
         {
             if (tFld is TheFieldInfo && (tFld as TheFieldInfo).Type == eFieldType.Table)    //fix for Bug#1195
             {
                 return(tThing);
             }
             RegisterNewNMINode(pClientInfo.NodeID, tFld.cdeMID, tThing.cdeMID, pDataItem, true);
             var OnUpdateName = pDataItem;
             if (OnUpdateName.StartsWith("MyPropertyBag."))  //TODO: Test this with Prop of Prop
             {
                 OnUpdateName = OnUpdateName.Split('.')[1];
             }
             tThing.GetProperty(OnUpdateName, true).SetPublication(true, Guid.Empty); //Guid.Empty uses PublishCentral - a specific node would use SYSTEMWIDE
             return(tThing);
         }
     }
     return(null);
 }
Пример #8
0
        public override bool DoCreateUX()
        {
            MyBaseThing.RegisterProperty("ClickState");
            var tFlds = TheNMIEngine.AddStandardForm(MyBaseThing, null, 24, null, "Value");

            MyStatusForm = tFlds["Form"] as TheFormInfo;
            //MyStatusForm.PropertyBag = new ThePropertyBag { "TileWidth=6" };
            MyStatusForm.RegisterEvent2(eUXEvents.OnShow, (pmse, sen) => { UpdateUx(); });
            SummaryForm             = tFlds["DashIcon"] as TheDashPanelInfo;
            SummaryForm.PropertyBag = new nmiDashboardTile()
            {
                Format = $"{MyBaseThing.FriendlyName}<br>{{0}}", Caption = MyBaseThing.FriendlyName
            };

            CountBar             = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleEnded, 5, 2, MyBaseThing.cdeA, "CurrentValue", "Value", null);
            ChangeTimestampField = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.DateTime, 6, 0, MyBaseThing.cdeA, "Last Change", nameof(ValueChangeTimestamp), new nmiCtrlDateTime {
                ParentFld = 1, Visibility = ShowChangeTimestamp
            });
            TimestampField = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.DateTime, 7, 0, MyBaseThing.cdeA, "Timestamp", nameof(ValueTimestamp), new nmiCtrlDateTime {
                ParentFld = 1, Visibility = ShowChangeTimestamp
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 800, 2, 0x80, "Configuration...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup()
            {
                ParentFld = 1, DoClose = true, IsSmall = true
            }));

            var ts = TheNMIEngine.AddStatusBlock(MyBaseThing, MyStatusForm, 810);

            ts["Group"].SetParent(800);
            ts["Group"].PropertyBag = new nmiCtrlCollapsibleGroup {
                DoClose = true
            };



            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 1000, 2, 0x80, "NMI Settings...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup()
            {
                ParentFld = 800, DoClose = true, IsSmall = true, TileWidth = 6
            }));
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 3000, 2, 0x80, "Advanced NMI Settings...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup()
            {
                ParentFld = 1000, DoClose = true, IsSmall = true, TileWidth = 6
            }));
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.ComboOption, 3010, 2, 0x80, "NMI Screen", "FormName", new ThePropertyBag()
            {
                "Options=%GetLiveScreens%", "TileWidth=6", "TileHeight=1", "ParentFld=3000"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CheckField, 3020, 2, 0x80, "Flags", "Flags", new ThePropertyBag()
            {
                "Bits=6", "TileHeight=6", "TileFactorY=2",
                "ImageList=<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf21b;</i><i class='fa fa-stack-2x'>&#x2003;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf044;</i><i class='fa fa-stack-2x'>&#x2003;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf10b;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf0ce;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf0f6;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf15c;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>", "ParentFld=3000"
            }).FldWidth = 1;

            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.ComboBox, 1500, 2, 0x80, "Control Type", "ControlType", new ThePropertyBag()
            {
                "Options=%RegisteredControlTypes%", "ParentFld=1000"
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 2000, 2, 0x80, "All Properties...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup()
            {
                NoTE = true, ParentFld = 1000, DoClose = true, IsSmall = true, TileWidth = 6
            }));

            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Table, 2010, 0xA2, 0x80, "All Properties", "mypropertybag;1", new ThePropertyBag()
            {
                "NoTE=true", "TileHeight=4", "TileLeft=9", "TileTop=3", "TileWidth=6", "FldWidth=6", "ParentFld=2000"
            });
            TheNMIEngine.AddFields(MyStatusForm, new List <TheFieldInfo> {
                { new TheFieldInfo()
                  {
                      FldOrder = 2020, DataItem = "MyPropertyBag.ScratchName.Value", Flags = 0x0A, Type = eFieldType.SingleEnded, Header = "New Property Name", TileWidth = 6, TileHeight = 1, PropertyBag = new ThePropertyBag()
                      {
                          "ParentFld=2000"
                      }
                  } },
            });

            TheFieldInfo tBut = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 2040, 0x0A, 0, "Add Property", false, null, null, new nmiCtrlTileButton()
            {
                ParentFld = 2000, NoTE = true, ClassName = "cdeGoodActionButton"
            });

            tBut.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "AddProp", (pThing, pObj) =>
            {
                TheProcessMessage pMsg = pObj as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                string[] parts = pMsg.Message.PLS.Split(':');
                TheThing tOrg  = TheThingRegistry.GetThingByMID(MyBaseEngine.GetEngineName(), TheCommonUtils.CGuid(parts[2]));
                if (tOrg == null)
                {
                    return;
                }

                string tNewPropName = TheThing.GetSafePropertyString(tOrg, "ScratchName");
                if (string.IsNullOrEmpty(tNewPropName))
                {
                    TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Please specify a new property name"));
                }
                else
                {
                    if (tOrg.GetProperty(tNewPropName) != null)
                    {
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property already exists"));
                        tOrg.SetProperty("ScratchName", "");
                    }
                    else
                    {
                        tOrg.DeclareNMIProperty(tNewPropName, ePropertyTypes.TString);
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property Added"));
                        tOrg.SetProperty("ScratchName", "");
                        MyStatusForm.Reload(pMsg, false);
                    }
                }
            });
            TheFieldInfo mSendbutton = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 1550, 2, 0x80, "Reload", false, "", null, new nmiCtrlTileButton()
            {
                TileWidth = 6, NoTE = true, ClassName = "cdeGoodActionButton", ParentFld = 1000
            });

            mSendbutton.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) =>
            {
                TheProcessMessage pMsg = pPara as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                UpdateUx();
                MyStatusForm.Reload(pMsg, true);
                //TheNMIEngine.GetEngineDashBoardByThing(MyBaseEngine.GetBaseThing()).Reload(pMsg, true);
            });


            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.CollapsibleGroup, 5000, 2, 0x80, "Source...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup()
            {
                DoClose = true, IsSmall = true, ParentFld = 800, TileWidth = 6
            }));
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.ThingPicker, 5010, 2, 0x80, "Source Thing", "Address", new nmiCtrlThingPicker()
            {
                ParentFld = 5000, IncludeEngines = true, IncludeRemotes = true
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.PropertyPicker, 5020, 2, 0x80, "Source Property", "SourceProp", new nmiCtrlPropertyPicker()
            {
                ParentFld = 5000, ThingFld = 5010
            });


            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleCheck, 5030, 2, 0x80, "Show Timestamp", nameof(ShowTimestamp), new nmiCtrlSingleCheck {
                ParentFld = 5000, TileWidth = 3
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleCheck, 5040, 2, 0x80, "Show Change Time", nameof(ShowChangeTimestamp), new nmiCtrlSingleCheck {
                ParentFld = 5000, TileWidth = 3
            });
            TheFieldInfo mSendbutton2 = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 5050, 2, 0x80, "Engage", false, "", null, new nmiCtrlTileButton()
            {
                NoTE = true, TileWidth = 6, ClassName = "cdeGoodActionButton", ParentFld = 5000
            });

            mSendbutton2.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) =>
            {
                TheProcessMessage pMsg = pPara as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                UpdateUx();
            });

            UpdateUx();
            return(true);
        }
Пример #9
0
 public cdeP GetProperty(string pName, bool DoCreate)
 {
     return(MyBaseThing?.GetProperty(pName, DoCreate));
 }
Пример #10
0
        public virtual bool DoCreateUX()
        {
            MyEditorForm = new TheFormInfo(MyBaseThing)
            {
                DefaultView = eDefaultView.Form, PropertyBag = new ThePropertyBag {
                    "MaxTileWidth=6", "HideCaption=true", "AllowDrag=true"
                }
            };
            MyEditorForm.ModelID = "NMIEditor";

            TheDashboardInfo tDash = TheNMIEngine.GetDashboardById(TheNMIHtml5RT.eNMIDashboard);

            MyEditorDashIcon = TheNMIEngine.AddFormToThingUX(tDash, MyBaseThing, MyEditorForm, "CMyForm", "NMI Control Editor", 1, 0x89, 0x80, "NMI", null, new ThePropertyBag()
            {
                "RenderTarget=cdeInSideBarRight", "NeverHide=true"
            });                                                                                                                                                                                                                           //"mAllowDrag=true", "nVisibility=false",

            MySampleControl = TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.SingleEnded, 3, 2, MyBaseThing.cdeA, "CurrentValue", "Value", null);


            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileGroup, 9, 0, 0, null, null, new nmiCtrlTileGroup {
                TileWidth = 7, TileHeight = 1, TileFactorY = 2
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 10, 2, 0, "Basic", null, new nmiCtrlTileButton {
                ParentFld = 9, OnClick = "GRP:NMIP:Basic", TileWidth = 1, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 20, 2, 0, "Screen", null, new nmiCtrlTileButton {
                ParentFld = 9, OnClick = "GRP:NMIP:Screen", TileWidth = 1, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 30, 2, 0, "All", null, new nmiCtrlTileButton {
                ParentFld = 9, OnClick = "GRP:NMIP:All", TileWidth = 1, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 40, 2, 0, "Source", null, new nmiCtrlTileButton {
                ParentFld = 9, OnClick = "GRP:NMIP:Source", TileWidth = 1, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton"
            });
            //TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 50, 2, 0, "Compounds", null, new nmiCtrlTileButton { OnClick = "GRP:Cate:5", TileWidth = 2, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton" });
            //TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 60, 2, 0, "Gauges", null, new nmiCtrlTileButton {  OnClick = "GRP:Cate:6", TileWidth = 2, TileHeight = 1, TileFactorY = 2, NoTE = true, ClassName = "cdeTransitButton" });
            TheFieldInfo mSendbutton = TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 70, 2, 0x80, "Reload", false, "", null, new nmiCtrlTileButton()
            {
                ParentFld = 9, TileWidth = 2, NoTE = true, TileFactorY = 2, ClassName = "cdeGoodActionButton"
            });

            mSendbutton.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) =>
            {
                TheProcessMessage pMsg = pPara as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                UpdateUx(pThing.GetBaseThing());
                MyEditorForm.Reload(pMsg, tDash.cdeMID, true);
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileGroup, 1000, 2, 0x80, null, null, new nmiCtrlTileGroup()
            {
                Group = "NMIP:Basic"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ComboBox, 1010, 2, 0x80, "Control Type", "ControlType", new ThePropertyBag()
            {
                "Options=%RegisteredControlTypes%", "ParentFld=1000"
            });
            GetProperty("ControlType", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                UpdateUx(MyBaseThing);
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.Number, 1020, 2, 0, "Tile Width", "TileWidth", new nmiCtrlNumber()
            {
                ParentFld = 1000, TileHeight = 1, TileFactorY = 1, DefaultValue = "6", TileWidth = 3
            });
            GetProperty("TileWidth", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "TileWidth= " + p.ToString());
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.Number, 1030, 2, 0, "Tile Height", "TileHeight", new nmiCtrlNumber()
            {
                ParentFld = 1000, TileHeight = 1, TileFactorY = 1, DefaultValue = "1", TileWidth = 3
            });
            GetProperty("TileHeight", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "TileHeight= " + p.ToString());
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ComboBox, 1040, 2, 0, "Horizontal Alignment", "HorizontalAlignment", new nmiCtrlComboBox()
            {
                ParentFld = 1000, Options = ";left;center;right"
            });
            GetProperty("HorizontalAlignment", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "HorizontalAlignment= " + p.ToString());
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ComboBox, 1050, 2, 0, "Class Name", "ClassName", new nmiCtrlComboBox()
            {
                ParentFld = 1000, Options = ";BlueWhite;GreenYellow;RedWhite"
            });
            GetProperty("ClassName", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "ClassName= " + p.ToString());
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.SingleEnded, 1060, 2, 0, "HelpText", "HelpText", new nmiCtrlSingleEnded()
            {
                ParentFld = 1000
            });
            GetProperty("HelpText", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "HelpText= " + p.ToString());
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ComboBox, 1070, 2, 0, "Opacity", "Opacity", new nmiCtrlComboBox()
            {
                ParentFld = 1000, Options = ";0.1;0.3;0.5;0.7;0.9;1.0"
            });
            GetProperty("Opacity", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "Opacity= " + p.ToString());
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.SingleCheck, 1080, 2, 0, "No TE", "NoTE", new nmiCtrlSingleCheck()
            {
                ParentFld = 1000
            });
            GetProperty("NoTE", true).RegisterEvent(eThingEvents.PropertyChanged, (p) =>
            {
                MySampleControl.SetUXProperty(Guid.Empty, "NoTE= " + p.ToString());
            });


            //Screen Properties
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileGroup, 3000, 2, 0x80, null, null, new nmiCtrlTileGroup()
            {
                Group = "NMIP:Screen", Visibility = false
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ComboOption, 3010, 2, 0x80, "NMI Screen", "FormName", new ThePropertyBag()
            {
                "Options=%GetLiveScreens%", "TileWidth=6", "TileHeight=1", "ParentFld=3000"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.CheckField, 3020, 2, 0x80, "Flags", "Flags", new ThePropertyBag()
            {
                "Bits=6", "TileHeight=6", "TileFactorY=2",
                "ImageList=<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf21b;</i><i class='fa fa-stack-2x'>&#x2003;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf044;</i><i class='fa fa-stack-2x'>&#x2003;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf10b;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf0ce;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf0f6;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>," +
                "<span class='fa-stack'><i class='fa fa-stack-1x'>&#xf15c;</i><i class='fa fa-stack-2x text-danger' style='opacity:0.5'>&#xf05e;</i></span>", "ParentFld=3000"
            }).FldWidth = 1;

            //ALL Properties
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileGroup, 2000, 2, 0x80, null, null, new nmiCtrlTileGroup()
            {
                TileWidth = 6, Group = "NMIP:All", Visibility = false
            });

            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.Table, 2010, 0xA2, 0x80, "All Properties", "mypropertybag;1", new ThePropertyBag()
            {
                "NoTE=true", "TileHeight=4", "TileLeft=9", "TileTop=3", "TileWidth=6", "FldWidth=6", "ParentFld=2000"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.SingleEnded, 2020, 0x0A, 0, "New Property Name", "ScratchName", new nmiCtrlSingleEnded()
            {
                ParentFld = 2000
            });
            TheFieldInfo tBut = TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 2040, 0x0A, 0, "Add Property", false, null, null, new nmiCtrlTileButton()
            {
                ParentFld = 2000, NoTE = true, ClassName = "cdeGoodActionButton"
            });

            tBut.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "AddProp", (pThing, pObj) =>
            {
                TheProcessMessage pMsg = pObj as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                string[] parts = pMsg.Message.PLS.Split(':');
                TheThing tOrg  = pThing.GetBaseThing(); // TheThingRegistry.GetThingByMID(MyBaseEngine.GetEngineName(), TheCommonUtils.CGuid(parts[2]));
                //if (tOrg == null) return;

                string tNewPropName = TheThing.GetSafePropertyString(tOrg, "ScratchName");
                if (string.IsNullOrEmpty(tNewPropName))
                {
                    TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Please specify a new property name"));
                }
                else
                {
                    if (tOrg.GetProperty(tNewPropName) != null)
                    {
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property already exists"));
                    }
                    else
                    {
                        tOrg.DeclareNMIProperty(tNewPropName, ePropertyTypes.TString);
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property Added"));
                        MyEditorForm.Reload(pMsg, false);
                    }
                    tOrg.SetProperty("ScratchName", "");
                }
            });

            //THING Connector
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileGroup, 5000, 2, 0x80, null, null, new nmiCtrlTileGroup()
            {
                TileWidth = 6, Group = "NMIP:Source", Visibility = false
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.ThingPicker, 5010, 2, 0x80, "Source Thing", "Address", new nmiCtrlThingPicker()
            {
                ParentFld = 5000, IncludeEngines = true
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.PropertyPicker, 5020, 2, 0x80, "Source Property", "SourceProp", new nmiCtrlPropertyPicker()
            {
                ParentFld = 5000, ThingFld = 5010
            });

            TheFieldInfo mSendbutton2 = TheNMIEngine.AddSmartControl(MyBaseThing, MyEditorForm, eFieldType.TileButton, 5050, 2, 0x80, "Engage", false, "", null, new nmiCtrlTileButton()
            {
                NoTE = true, TileWidth = 6, ClassName = "cdeGoodActionButton", ParentFld = 5000
            });

            mSendbutton2.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) =>
            {
                TheProcessMessage pMsg = pPara as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                UpdateUx(pThing.GetBaseThing());
            });
            UpdateUx(MyBaseThing);
            return(true);
        }
Пример #11
0
        private static Image DrawStrip(Guid pThingGuid, DateTimeOffset now, TheFieldInfo pInfo)
        {
            int pixelWidth = 78 * TheCommonUtils.CInt(pInfo?.PropBagGetValue("TileWidth"));

            if (pixelWidth == 0)
            {
                pixelWidth = 78;
            }
            int Hours = TheCommonUtils.CInt(pInfo?.PropBagGetValue("Hours"));

            if (Hours == 0)
            {
                Hours = 1;
            }
            int    pixelHeight = 1;
            Bitmap bmp         = new Bitmap(pixelWidth, pixelHeight, PixelFormat.Format32bppArgb);

            int    st           = 0;
            string tColorString = pInfo?.PropBagGetValue("ChartColors");

            string[] htmlColors = null;
            if (string.IsNullOrEmpty(tColorString))
            {
                htmlColors = TheBaseAssets.MyServiceHostInfo.StatusColors.Split(';');
            }
            else
            {
                htmlColors = tColorString.Split(';');
            }
            Dictionary <int, SolidBrush> stateColorMapping = htmlColors.ToDictionary(x => st++, y => new SolidBrush(ColorTranslator.FromHtml(y)));

            TheThing tThing = TheThingRegistry.GetThingByMID("*", pThingGuid);

            if (tThing == null)
            {
                return(null);
            }
            cdeP pMSH = ((ICDEThing)tThing.GetObject())?.GetProperty("MachineStorageHistory", false);

            if (pMSH == null)
            {
                return(null);
            }
            List <TheMachineStateHistory> tList = TheCommonUtils.DeserializeJSONStringToObject <List <TheMachineStateHistory> >(pMSH.ToString());

            if (tList == null)
            {
                return(null);
            }
            tList = tList.Where(s => now.Subtract(s.StateChangeTime).TotalHours < Hours).OrderBy(s => s.StateChangeTime).ToList();

            cdeP LastDeletedEntry            = tThing.GetProperty("LastDeletedEntry", false);
            TheMachineStateHistory lastState = null;

            if (LastDeletedEntry != null)
            {
                TheMachineStateHistory tHis = TheCommonUtils.DeserializeJSONStringToObject <TheMachineStateHistory>(LastDeletedEntry.ToString());
                lastState = new TheMachineStateHistory()
                {
                    State = tHis.State, StateChangeTime = now.Subtract(new TimeSpan(Hours, 0, 0))
                };
            }

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.ScaleTransform((float)pixelWidth / (Hours * 60 * 60), 1.0f);
                List <KeyValuePair <int, RectangleF> > rectangles = new List <KeyValuePair <int, RectangleF> >();
                foreach (var t in tList)
                {
                    if (lastState != null && t.State != lastState.State)
                    {
                        float start = (float)now.Subtract(t.StateChangeTime).TotalSeconds;
                        float size  = (float)t.StateChangeTime.Subtract(lastState.StateChangeTime).TotalSeconds;
                        rectangles.Add(new KeyValuePair <int, RectangleF>(lastState.State, new RectangleF(new PointF(start, 0), new SizeF(size, pixelHeight))));
                        lastState = t;
                    }
                    if (lastState == null)
                    {
                        lastState = t;
                    }
                }
                if (lastState != null)
                {
                    float size = (float)now.Subtract(lastState.StateChangeTime).TotalSeconds;
                    rectangles.Add(new KeyValuePair <int, RectangleF>(lastState.State, new RectangleF(new PointF(0, 0), new SizeF(size, pixelHeight))));
                }
                if (rectangles.Count > 0)
                {
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    // g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    for (int state = 0; state <= rectangles.Max(x => x.Key); state++)
                    {
                        if (stateColorMapping.ContainsKey(state))
                        {
                            IEnumerable <RectangleF> rects = rectangles.Where(x => x.Key == state).Select(x => x.Value);
                            var rectangleFs = rects as RectangleF[] ?? rects.ToArray();
                            if (rectangleFs.Any())
                            {
                                if (state > stateColorMapping.Count)
                                {
                                    g.FillRectangles(new SolidBrush(Color.Pink), rectangleFs.ToArray());
                                }
                                else
                                {
                                    g.FillRectangles(stateColorMapping[state], rectangleFs.ToArray());
                                }
                            }
                        }
                    }
                }
            }
            if (TheCommonUtils.CBool(pInfo?.PropBagGetValue("DrawRightToLeft")))
            {
                bmp.RotateFlip(RotateFlipType.RotateNoneFlipX); //draw right to left
            }
            return(bmp);
        }
Пример #12
0
        public bool ActivateRules()
        {
            if (TheCDEngines.MyThingEngine == null || TheBaseAssets.MyServiceHostInfo.IsCloudService || TheCommonUtils.cdeIsLocked(LockRules) || !mIsInitialized)
            {
                return(false);
            }

            lock (LockRules)
            {
                if (mIsInitialized)
                {
                    InitRules();
                }
                //List<TheRule> tList = MyRulesStore.MyMirrorCache.GetEntriesByFunc(s => s.IsRuleActive && !s.IsRuleRunning && s.IsRuleWaiting);
                List <TheThing> tList = TheThingRegistry.GetThingsByFunc("*", s =>
                                                                         TheThing.GetSafePropertyString(s, "Parent").Equals(MyBaseThing.ID) && //TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID) &&
                                                                         TheThing.GetSafePropertyBool(s, "IsRuleActive") &&
                                                                         !TheThing.GetSafePropertyBool(s, "IsRuleRunning") &&
                                                                         TheThing.GetSafePropertyBool(s, "IsRuleWaiting"));
                if (tList != null && tList.Count > 0)
                {
                    foreach (TheThing tThing in tList)
                    {
                        TheRule tRule = tThing.GetObject() as TheRule;
                        if (tRule == null)
                        {
                            continue;
                        }
                        if (string.IsNullOrEmpty(tRule.TriggerProperty))
                        {
                            tRule.IsIllegal     = true;
                            tRule.IsRuleWaiting = false;
                            continue;
                        }
                        if (tRule.TriggerStartTime > DateTimeOffset.Now)
                        {
                            continue;
                        }
                        if (tRule.TriggerEndTime < DateTimeOffset.Now)
                        {
                            RemoveTrigger(tRule, false);
                            continue;
                        }
                        switch (tRule.TriggerObjectType)
                        {
                        case "CDE_ENGINE":
                            TheThing tBase = TheThingRegistry.GetBaseEngineAsThing(tRule.TriggerObject);
                            if (tBase != null)
                            {
                                tBase.RegisterEvent(eEngineEvents.IncomingMessage, sinkRuleIncoming);
                                tRule.IsRuleWaiting        = false;
                                tRule.IsRuleRunning        = true;
                                tRule.IsTriggerObjectAlive = true;
                                TheSystemMessageLog.WriteLog(4445, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(eKnownDeviceTypes.TheThingRule, $"Rule {tRule.FriendlyName} started with TriggerType: {tRule.TriggerObjectType}"), false);
                            }
                            break;

                        case "CDE_EVENTFIRED":
                            TheThing tBaseE = TheThingRegistry.GetBaseEngineAsThing(tRule.TriggerObject);
                            if (tBaseE != null)
                            {
                                tBaseE.RegisterEvent(tRule.TriggerProperty, sinkRuleThingEvent);
                                tRule.IsRuleWaiting        = false;
                                tRule.IsRuleRunning        = true;
                                tRule.IsTriggerObjectAlive = true;
                                TheSystemMessageLog.WriteLog(4445, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(eKnownDeviceTypes.TheThingRule, $"Rule {tRule.FriendlyName} started with TriggerType: {tRule.TriggerObjectType}"), false);
                            }
                            break;

                        default:
                            TheThing tTriggerThing = TheThingRegistry.GetThingByMID("*", TheCommonUtils.CGuid(tRule.TriggerObject));
                            if (tTriggerThing != null)
                            {
                                //if (tTriggerThing.GetObject() == null) continue;  //TODO: Verify if this can stay removed
                                //if (tTriggerThing.GetProperty("FriendlyName").Value.ToString().Contains("Motion")) continue;
                                cdeP tProp = tTriggerThing.GetProperty(tRule.TriggerProperty, true);
                                if (tProp != null)
                                {
                                    tProp.UnregisterEvent(eThingEvents.PropertyChanged, sinkRuleAction);
                                    tProp.RegisterEvent(eThingEvents.PropertyChanged, sinkRuleAction);
                                }
                                tRule.IsRuleWaiting        = false;
                                tRule.IsRuleRunning        = true;
                                tRule.IsTriggerObjectAlive = true;
                                tRule.RuleTrigger(tProp.ToString(), true);
                                TheSystemMessageLog.WriteLog(4445, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(eKnownDeviceTypes.TheThingRule, $"Rule {tRule.FriendlyName} started with TriggerType: {tRule.TriggerObjectType}"), false);
                            }
                            break;
                        }
                    }
                }
            }
            return(true);
        }
Пример #13
0
        public void SetPropertyCloningTest()
        {
            var testThing = new TheThing();
            {
                // This test illustrates some of the corner cases with property values:
                // 1) object values are not cloned on set property; with strings this is mostly irrelevant
                string x = "123";
                testThing.SetProperty("Prop1", x);
                var prop1Value = testThing.GetProperty("Prop1").Value;
                Assert.AreEqual(prop1Value, x);
                Assert.AreSame(prop1Value, x); // Strings can't be (and don't need to be) cloned because they are immutable
                Assert.AreSame(testThing.GetProperty("Prop1").Value, x);

                x = "456";
                Assert.AreEqual(prop1Value, "123");
                Assert.AreNotSame(prop1Value, x);

                testThing.SetProperty("Prop1", "789");
                Assert.IsTrue(String.Equals(x, "456"));
                Assert.AreEqual(prop1Value, "123");

                var prop1Value_2 = testThing.GetProperty("Prop1").Value;
                Assert.AreEqual(prop1Value_2, "789");
                Assert.AreEqual(prop1Value, "123");
                Assert.AreNotSame(prop1Value_2, prop1Value);
            }

            // 2) value types
            {
                // This test illustrates some of the corner cases with property values:
                // 1) object values are not cloned on set property; with strings this is mostly irrelevant
                double x = 1.23;
                testThing.SetProperty("Prop1", x);
                var prop1Value = testThing.GetProperty("Prop1").Value;
                Assert.AreEqual(prop1Value, x);
                Assert.AreNotSame(prop1Value, x);                           // Value types are automatically cloned
                Assert.AreNotSame(testThing.GetProperty("Prop1").Value, x); // Value types are automatically cloned

                x = 4.56;
                Assert.AreEqual(prop1Value, 1.23);
                Assert.AreNotSame(prop1Value, x);

                testThing.SetProperty("Prop1", 7.89);
                Assert.IsTrue(double.Equals(x, 4.56));
                Assert.AreEqual(prop1Value, 1.23);

                var prop1Value_2 = testThing.GetProperty("Prop1").Value;
                Assert.AreEqual(prop1Value_2, 7.89);
                Assert.AreEqual(prop1Value, 1.23);
                Assert.AreNotSame(prop1Value_2, prop1Value);
            }

            // 3) with mutable objects, the differences are more substantial
            {
                // 3a) non-cloneable
                MyTestClass xObj = new MyTestClass {
                    x = "123"
                };
                testThing.SetProperty("Prop3", xObj);
                var prop2Value = testThing.GetProperty("Prop3").Value;
                Assert.AreEqual(prop2Value, xObj);
                Assert.AreSame(prop2Value, xObj); // This would be different if we cloned

                xObj.x = "456";
                Assert.AreEqual(prop2Value, new MyTestClass {
                    x = "456"
                });                                                         // modifying the original object modifies the value of the property
                Assert.AreSame(prop2Value, xObj);

                testThing.SetProperty("Prop3", new MyTestClass {
                    x = "789"
                });
                Assert.IsTrue(String.Equals(xObj, new MyTestClass {
                    x = "456"
                }));
                Assert.AreEqual(prop2Value, new MyTestClass {
                    x = "456"
                });

                var prop2Value_2 = testThing.GetProperty("Prop3").Value;
                Assert.AreEqual(prop2Value_2, new MyTestClass {
                    x = "789"
                });
                Assert.AreEqual(prop2Value, new MyTestClass {
                    x = "456"
                });
                Assert.AreNotSame(prop2Value_2, prop2Value);
            }

            {
                // 3b) cloneable
                MyTestClassCloneable xObj = new MyTestClassCloneable {
                    x = "123"
                };
                testThing.SetProperty("Prop4", xObj);
                var prop2Value = testThing.GetProperty("Prop4").Value;
                Assert.AreEqual(prop2Value, xObj);
                Assert.AreSame(prop2Value, xObj); // This would be different if we cloned

                xObj.x = "456";
                Assert.AreEqual(prop2Value, new MyTestClassCloneable {
                    x = "456"
                });                               // modifying the original object modifies the value of the property: this would be different if we cloned
                Assert.AreSame(prop2Value, xObj); // this would be different if we cloned

                testThing.SetProperty("Prop4", new MyTestClassCloneable {
                    x = "789"
                });
                Assert.IsTrue(String.Equals(xObj, new MyTestClassCloneable {
                    x = "456"
                }));
                Assert.AreEqual(prop2Value, new MyTestClassCloneable {
                    x = "456"
                });

                var prop2Value_2 = testThing.GetProperty("Prop4").Value;
                Assert.AreEqual(prop2Value_2, new MyTestClassCloneable {
                    x = "789"
                });
                Assert.AreEqual(prop2Value, new MyTestClassCloneable {
                    x = "456"
                });
                Assert.AreNotSame(prop2Value_2, prop2Value);
            }
        }
Пример #14
0
        public virtual bool CreateUX()
        {
            if (mIsUXInitCalled)
            {
                return(false);
            }
            mIsUXInitCalled = true;

            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}} Properties", MyBaseThing.FriendlyName)
            };
            SummaryForm.RegisterPropertyChanged(sinkStatChanged);

            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Number, 21, 0, 0x0, "###CDMyVThings.TheVThings#CountOfProperties598472#Count of Properties###", "Value", new nmiCtrlNumber()
            {
                ParentFld = 1
            });
            TheFieldInfo mSendbutton = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 22, 2, 0, "###CDMyVThings.TheVThings#Reload598472#Reload###", false, "", null, new nmiCtrlTileButton()
            {
                ParentFld = 1, NoTE = true, ClassName = "cdeGoodActionButton"
            });

            mSendbutton.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "", (pThing, pPara) =>
            {
                TheProcessMessage pMsg = pPara as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                sinkStatChanged(null, null);
                MyStatusForm.Reload(pMsg, true);
            });
            PropTable = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.Table, 40, 0xA0, 0x80, "All Properties", "mypropertybag;0", new TheNMIBaseControl()
            {
                NoTE = true, ParentFld = 1, TileWidth = 12, TileHeight = 16
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.SingleEnded, 30, 0x0A, 0, "New Property Name", "ScratchName", new nmiCtrlSingleEnded()
            {
                ParentFld = 1
            });
            TheFieldInfo tBut = TheNMIEngine.AddSmartControl(MyBaseThing, MyStatusForm, eFieldType.TileButton, 35, 0x0A, 0, "Add Property", false, null, null, new nmiCtrlTileButton()
            {
                ParentFld = 1, NoTE = true
            });

            tBut.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, "AddProp", (pThing, pObj) =>
            {
                TheProcessMessage pMsg = pObj as TheProcessMessage;
                if (pMsg?.Message == null)
                {
                    return;
                }
                string[] parts = pMsg.Message.PLS.Split(':');
                TheThing tOrg  = TheThingRegistry.GetThingByMID(MyBaseEngine.GetEngineName(), TheCommonUtils.CGuid(parts[2]));
                if (tOrg == null)
                {
                    return;
                }

                string tNewPropName = TheThing.GetSafePropertyString(tOrg, "ScratchName");
                if (string.IsNullOrEmpty(tNewPropName))
                {
                    TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Please specify a new property name"));
                }
                else
                {
                    if (tOrg.GetProperty(tNewPropName) != null)
                    {
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property already exists"));
                    }
                    else
                    {
                        tOrg.DeclareNMIProperty(tNewPropName, ePropertyTypes.TString);
                        TheCommCore.PublishToOriginator(pMsg.Message, new TSM(eEngineName.NMIService, "NMI_TOAST", "Property Added"));
                        MyStatusForm.Reload(pMsg, false);
                    }
                }
                tOrg.RemoveProperty("ScratchName");
            });
            mIsUXInitialized = true;
            return(true);
        }
Пример #15
0
        /// <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);
        }