public override bool CreateUX()
        {
            if (mIsUXInitCalled)
            {
                return(false);
            }
            mIsUXInitCalled = true;

            base.CreateUXBase("Mesh Receiver");
            if (MyForm != null)
            {
                MyForm.DeleteByOrder(11);
                MyForm.DeleteByOrder(24); //Removes the ADDRES Field from the Form
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.CollapsibleGroup, 40, 2, 0xC0, "Advanced Configurations...", null, ThePropertyBag.Create(new nmiCtrlCollapsibleGroup() { DoClose = true }));//() { "TileWidth=6", "Format=Advanced Configurations", "Style=font-size:26px;text-align: left" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.Password, 41, 7, 0xC0, "Connection String", TheAzureConnectionHelper.strConnectionString, new ThePropertyBag() { "ParentFld=40", "TileWidth=6", "TileHeight=1", "HideMTL=true" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 42, 7, 0xC0, "Event Hub Name", TheAzureConnectionHelper.strEventHubName, new ThePropertyBag() { "ParentFld=40", "TileWidth=6", "TileHeight=1" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 43, 0, 0xC0, "Event Hub Address:", "Address", new ThePropertyBag() { "ParentFld=40", "TileHeight=1", "TileWidth=6" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 44, 7, 0xC0, "Consumer Group", strConsumerGroup, new ThePropertyBag() { "ParentFld=40", "TileWidth=6", "TileHeight=1" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.Password, 45, 7, 0xC0, "Storage Connection String (Checkpoints)", strStorageConnectionString, new ThePropertyBag() { "ParentFld=40", "TileWidth=6", "TileHeight=1", "HideMTL=true" });
                //TheNMIEngine.AddSmartControl(MyBaseThing, tMyForm, eFieldType.SingleCheck, 46, 3, 0xC0, "Preserve Order for all Things", "PreserveSendOrderAllThings", new ThePropertyBag() { "TileWidth=6", "TileHeight=1" });

                TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.ComboBox, 24, 2, 0xC0, "Receiver Event Converter", nameof(ReceiverEventConverter), new nmiCtrlComboBox {
                    ParentFld = 20, DefaultValue = TheEventConverters.GetDisplayName(typeof(JSonObjectEventConverter)), Options = TheEventConverters.GetDisplayNamesAsSemicolonSeperatedList()
                });
                TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 30, 2, 0xC0, "Property for Sender Time:", nameof(SenderTimePropertyName), new ThePropertyBag()
                {
                    "ParentFld=20", "TileHeight=1", "TileWidth=6"
                });
                TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 40, 2, 0xC0, "Property for Time Drift:", nameof(TimeDriftPropertyName), new ThePropertyBag()
                {
                    "ParentFld=20", "TileHeight=1", "TileWidth=6"
                });
#if CDEPUBSUB
                TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.SingleEnded, 45, 2, 0xC0, "PubSub Topic", nameof(PubSubTopic), new ThePropertyBag()
                {
                    "ParentFld=20", "TileHeight=1", "TileWidth=6"
                });
#endif
                //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.Number, 310, 0, 0, "Last Received", nameof(LastReceiveTime), new ThePropertyBag() { "ParentFld=300", "TileHeight=1", "TileWidth=6", "FldWidth=4" });

                mIsUXInitialized = true;
                return(true);
            }
            return(false);
        }
Beispiel #2
0
        public override void CreateUXBase(string formTitle)
        {
            base.CreateUXBase(formTitle);

            // KPI Form
            //tKPIForm = new TheFormInfo(TheThing.GetSafeThingGuid(MyBaseThing, "AzureKPI_ID"), eEngineName.NMIService, "Azure Receiver: KPIs", tDataSource) { IsNotAutoLoading = true };

            //var tFlds = TheNMIEngine.AddStandardForm(MyBaseThing, MyBaseThing.FriendlyName, 18, "AzureKPI_ID");
            //var tKPIForm = tFlds["Form"] as TheFormInfo;
            //(tFlds["DashIcon"] as TheDashPanelInfo).PropertyBag=new ThePropertyBag() { "Visibility=false" };

            TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.CollapsibleGroup, 300, 2, 0, String.Format("Receiver KPIs: {0}", MyBaseThing.FriendlyName), null, new nmiCtrlCollapsibleGroup()
            {
                DoClose = true, ParentFld = 3, TileWidth = 6, IsSmall = true
            });

            TheNMIEngine.AddFields(MyConnectionThingsForm, new List <TheFieldInfo>
            {
                new TheFieldInfo()
                {
                    FldOrder = 13, DataItem = "EventFormat", Flags = 2, Type = eFieldType.ComboBox, Header = "Data Serializer", FldWidth = 3, PropertyBag = new ThePropertyBag()
                    {
                        "Options=" + TheEventConverters.GetDisplayNamesAsSemicolonSeperatedList()
                    }
                },
            });


            TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.Number, 308, 0, 0, "Events Received", nameof(ReceiveCount), new ThePropertyBag()
            {
                "ParentFld=300", "TileHeight=1", "TileWidth=6", "FldWidth=4"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.DateTime, 309, 0, 0, "Last Receive", nameof(LastReceiveTime), new ThePropertyBag()
            {
                "ParentFld=300", "TileHeight=1", "TileWidth=6", "FldWidth=4"
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, MyForm, eFieldType.Number, 310, 0, 0, "Receive Errors", nameof(ReceiveErrorCount), new ThePropertyBag()
            {
                "ParentFld=300", "TileHeight=1", "TileWidth=6", "FldWidth=4"
            });

            // Add link to KPIs to AzureConnection form
            //TheNMIEngine.AddSmartControl(MyBaseThing, MyForm , eFieldType.TileButton, 12, 2, 0xF0, "Show KPIs", null, new nmiCtrlTileButton() { ParentFld=3, NoTE=true, OnClick=$"TTS:{tKPIForm.cdeMID}", ClassName="cdeTransitButton"  });
        }
        private bool ProcessMessage(string correlationToken, string eventConverterName, DateTimeOffset messageTime, string messagePayload, string originator, bool bIsTargetedMessage, out string error, out bool bSendAck)
        {
            bool bSuccess = false;

            bSendAck = true;

            if (bIsTargetedMessage)
            {
                if (_nodeOwnerManager.RegisterOwnerCandidate(correlationToken, originator, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(), true))
                {
                    var notification = new TSM(MyBaseEngine.GetEngineName(), $"MESHRECEIVER_ACK_NOTIFY:;:{correlationToken}:;:{originator}:;:{bIsTargetedMessage}");
                    TheCommCore.PublishCentral(notification, false);
                }
            }
            else
            {
                if (_nodeOwnerManager.CheckOwner(originator, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString()) != true)
                {
                    _nodeOwnerManager.RequestOwnership(correlationToken, originator, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString());
                }
            }

            IEventConverter eventConverter = null;

            if (!string.IsNullOrEmpty(eventConverterName))
            {
                eventConverter = TheEventConverters.GetEventConverter(eventConverterName);
                if (eventConverter == null)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(180001, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("Mesh Receiver", $"Unknown event converter in incoming MESHSENDER_DATA {this.MyBaseThing.FriendlyName}: {eventConverterName}", eMsgLevel.l1_Error, TSM.L(eDEBUG_LEVELS.OFF) ? null : messagePayload));
                }
            }
            else
            {
                eventConverter = TheEventConverters.GetEventConverter(ReceiverEventConverter);
                if (eventConverter == null)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(180002, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("Mesh Receiver", $"Unknown default event converter {this.MyBaseThing.FriendlyName}: {ReceiverEventConverter}", eMsgLevel.l1_Error));
                }
            }

            //if (EnableDataLogging)
            //{
            //    try
            //    {
            //        lock (dataLoggerLock)
            //        {
            //            System.IO.File.AppendAllText("meshreceiverdata.log", $"{{\"TimeReceived\":\"{DateTimeOffset.Now:O}\", \"PLS\": {pMsg.Message.PLS},\"TXT\":{pMsg.Message.TXT}}},\r\n");
            //        }
            //    }
            //    catch (Exception e)
            //    {
            //        TheBaseAssets.MySYSLOG.WriteToLog(180003, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("Mongo Writer", $"Unable to log data to file: {this.MyBaseThing.FriendlyName}", eMsgLevel.l3_ImportantMessage, e.ToString()));
            //    }
            //}

            if (eventConverter == null)
            {
                error = "Unknown event converter";
            }
            else
            {
                if (IsConnected)
                {
                    try
                    {
                        var now = DateTimeOffset.Now;
                        if (!string.IsNullOrEmpty(TimeDriftPropertyName))
                        {
                            // Calculate time difference (in minutes) between the sender and this node
                            var timeDrift = now - messageTime;
                            timeDrift = TimeSpan.FromMinutes(timeDrift.TotalMinutes > 0 ? Math.Floor(timeDrift.TotalMinutes) : Math.Ceiling(timeDrift.TotalMinutes));
                            if (eventConverter.StaticPropsToAdd == null)
                            {
                                eventConverter.StaticPropsToAdd = new Dictionary <string, object>();
                            }
                            eventConverter.StaticPropsToAdd[TimeDriftPropertyName] = System.Xml.XmlConvert.ToString(timeDrift);
                        }
                        if (!string.IsNullOrEmpty(SenderTimePropertyName))
                        {
                            if (eventConverter.StaticPropsToAdd == null)
                            {
                                eventConverter.StaticPropsToAdd = new Dictionary <string, object>();
                            }
                            eventConverter.StaticPropsToAdd[SenderTimePropertyName] = messageTime;
                        }
                        bool bDetectedOtherOwner = false;
                        // TODO Support picking a thing for formats that don't carry a thing id
                        eventConverter.NewThingCallback = async(t) =>
                        {
                            if (await _nodeOwnerManager.CheckOwnerAsync(correlationToken, originator, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString()).ConfigureAwait(false) == false)
                            {
                                bDetectedOtherOwner = true;
                                return(false);
                            }
                            return(true);
                        };
                        error = eventConverter.ProcessEventData(null, messagePayload, now);
                        if (bDetectedOtherOwner)
                        {
                            error    = "Detected other receiver";
                            bSendAck = false;
                            bSuccess = false;
                        }
                        else
                        {
                            if (String.IsNullOrEmpty(error))
                            {
                                ReceiveCount++;
                                bSuccess = true;
                            }
                            else
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(180004, new TSM("Mesh Receiver", "Error processing data", eMsgLevel.l1_Error, error));
                                ReceiveErrorCount++;
                            }
                            LastReceiveTime = now;
                        }
                    }
                    catch (Exception e)
                    {
                        error = "Error parsing data: " + e.Message;
                        TheBaseAssets.MySYSLOG.WriteToLog(180005, new TSM("Mesh Receiver", "Error processing data", eMsgLevel.l1_Error, e.ToString()));
                        bSuccess = false;
                        ReceiveErrorCount++;
                    }

                    if (bSuccess)
                    {
                        MyBaseThing.StatusLevel = 1;
                    }
                }
                else
                {
                    error = "Not connected";
                }
            }

            return(bSuccess);
        }
Beispiel #4
0
        private async Task PlaybackLoop(TheThing tThingOverride, CancellationToken cancelToken, IEnumerable <object> updatesToPlay, TimeSpan startupDelayRange, bool bFromAutoStart)
        {
            var lastItemTime       = DateTimeOffset.MaxValue;
            var previousUpdateTime = DateTimeOffset.Now;

            if (bFromAutoStart && AutoStartDelay > 0 && tThingOverride.FriendlyName != "ignored") // hack to delay only for real things
            {
                TheBaseAssets.MySYSLOG.WriteToLog(700, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, $"Playback loop for {tThingOverride?.FriendlyName} holding for {AutoStartDelay} ms.", eMsgLevel.l6_Debug));
                await TheCommonUtils.TaskDelayOneEye(AutoStartDelay, 100);
            }
            TheBaseAssets.MySYSLOG.WriteToLog(700, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, $"Playback loop started for {tThingOverride?.FriendlyName}", eMsgLevel.l6_Debug));

            if (startupDelayRange > TimeSpan.Zero)
            {
                var startupDelayInMs = (uint)startupDelayRange.TotalMilliseconds;
                var randomDelay      = TheCommonUtils.GetRandomUInt(0, startupDelayInMs);
                await TheCommonUtils.TaskDelayOneEye((int)randomDelay, 100, cancelToken).ConfigureAwait(false);
            }

            var eventconverter = TheEventConverters.GetEventConverter("JSON Things", true) as JSonThingEventConverter;

            // These get set in the callback from ProcessEventData so we can process them afterwards
            List <Tuple <TheThing, TheThingStore> > updatesProcessed = new List <Tuple <TheThing, TheThingStore> >();

            eventconverter.ApplyUpdateCallback = (thing, update) =>
            {
                updatesProcessed.Add(Tuple.Create(thing, update));
                return(false);
            };
            eventconverter.eventDecoder = (o => o.ToString());

            do
            {
                foreach (var updateObj in updatesToPlay)
                {
                    updatesProcessed.Clear();
                    eventconverter.ProcessEventData(tThingOverride, updateObj, DateTimeOffset.Now);
                    if (IsDisabled)
                    {
                        //How can a cacnel token be set?
                        break;
                    }
                    if (cancelToken.IsCancellationRequested)
                    {
                        break;
                    }
                    foreach (var updateAndThing in updatesProcessed)
                    {
                        TimeSpan timeToWait = TimeSpan.Zero;

                        var tThingProcessed       = updateAndThing.Item1;
                        var tThingUpdateProcessed = updateAndThing.Item2;
                        if (PlaybackSpeedFactor > 0)
                        {
                            var now = DateTimeOffset.Now;
                            var timeSinceLastUpdate = now - previousUpdateTime;
                            var timeToNextItem      = tThingUpdateProcessed.cdeCTIM - lastItemTime;
                            if (timeToNextItem > TimeSpan.Zero && timeSinceLastUpdate < timeToNextItem)
                            {
                                timeToWait = timeToNextItem - timeSinceLastUpdate;
                                if (timeToWait > TimeSpan.Zero)
                                {
                                    if (PlaybackSpeedFactor != 1)
                                    {
                                        timeToWait = new TimeSpan(0, 0, 0, 0, (int)(timeToWait.TotalMilliseconds / PlaybackSpeedFactor));
                                    }
                                    if (MaxItemDelay > 0 && timeToWait.TotalMilliseconds > MaxItemDelay)
                                    {
                                        timeToWait = new TimeSpan(0, 0, 0, 0, MaxItemDelay);
                                    }
                                }
                                else
                                {
                                    // falling behind!
                                }
                            }
                        }
                        else if (PlaybackItemDelay > 0)
                        {
                            timeToWait = new TimeSpan(0, 0, 0, 0, PlaybackItemDelay);
                        }

                        if (timeToWait > TimeSpan.Zero)
                        {
                            await TheCommonUtils.TaskDelayOneEye((int)timeToWait.TotalMilliseconds, 100, cancelToken).ConfigureAwait(false);
                        }

                        if (cancelToken.IsCancellationRequested)
                        {
                            break;
                        }

                        lastItemTime = tThingUpdateProcessed.cdeCTIM;
                        {
                            var now = DateTimeOffset.Now;

                            previousUpdateTime = now;

                            var timeToSend = AdjustTimestamps ? now : tThingUpdateProcessed.cdeCTIM;
                            if (tThingOverride != null)
                            {
                                if (tThingUpdateProcessed.PB.ContainsKey("FriendlyName"))
                                {
                                    tThingUpdateProcessed.PB["FriendlyName"] = tThingOverride.FriendlyName;
                                }
                                if (tThingUpdateProcessed.PB.ContainsKey("ID"))
                                {
                                    tThingUpdateProcessed.PB["ID"] = tThingOverride.FriendlyName;
                                }
                                if (tThingUpdateProcessed.PB.ContainsKey("EngineName"))
                                {
                                    tThingUpdateProcessed.PB["EngineName"] = tThingOverride.EngineName;
                                }
                                if (tThingUpdateProcessed.PB.ContainsKey("DeviceType"))
                                {
                                    tThingUpdateProcessed.PB["DeviceType"] = tThingOverride.DeviceType;
                                }
                                if (tThingUpdateProcessed.PB.ContainsKey("DeviceType"))
                                {
                                    tThingUpdateProcessed.PB["DeviceType"] = tThingOverride.DeviceType;
                                }
                            }
                            tThingProcessed.SetProperties(tThingUpdateProcessed.PB, timeToSend);
                            Interlocked.Add(ref _propertyCounter, tThingUpdateProcessed.PB.Count);
                            _lastSendTime = timeToSend;
                        }
                    }
                }
            } while (RestartPlayback && !cancelToken.IsCancellationRequested && !IsDisabled);
            TheBaseAssets.MySYSLOG.WriteToLog(700, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, $"Playback loop stopped for {tThingOverride?.FriendlyName}", eMsgLevel.l6_Debug));
        }