Example #1
0
 public PlanningPokerSignalRClientFixture()
 {
     Mock         = new MockHubConnection();
     SentMessages = new HubMessageQueue(Mock.SentMessages);
     Target       = new PlanningPokerSignalRClient(Mock.HubConnectionBuilder);
     _timeoutCancellationToken = System.Diagnostics.Debugger.IsAttached ? new CancellationTokenSource() : new CancellationTokenSource(_timeout);
 }
Example #2
0
        // ReSharper disable once UnusedMember.Local
        private static void Demo(IpiSensorNetConfiguration moduleConfiguration, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, IReadOnlyMap <string, int> functionNames, IReadOnlyDictionary <FunctionTypeEnum, IFunctionHandler> functionHandlers, IReadOnlyDictionary <FunctionTypeEnum, IQueryableFunctionHandler> queryableFunctionHandlers, IReadOnlyDictionary <TriggerSourceTypeEnum, ITriggerSourceHandler> triggerSourceHandlers, IReadOnlyDictionary <int, TriggerDelegate> triggerDelegates, IReadOnlyDictionary <TriggerDependencyTypeEnum, ITriggerDependencyHandler> triggerDependencyHandlers)
        {
            using (var context = PiSensorNetDbContext.Connect(moduleConfiguration.ConnectionString).WithChangeTracking())
            {
                var functionID   = context.Functions.AsNoTracking().Where(i => i.FunctionType == FunctionTypeEnum.FunctionList).Select(i => i.ID).Single();
                var moduleNumber = context.Modules.AsNoTracking().Count() + 1;
                var address      = $"test{moduleNumber}";

                context.Modules
                .Add(new Module(address)
                {
                    FriendlyName = address,
                    Description  = "Test module",
                }
                     .For(i => { i.ModuleFunctions.Add(context.Functions.Select(f => new ModuleFunction(i, f))); })
                     .For(i =>
                {
                    i.Packets.Add(new[]
                    {
                        new Packet(i, 0, "identify;function_list;voltage;report;ow_list;ow_ds18b20_temperature;ow_ds18b20_temperature_periodical;", DateTime.Now)
                        // "2854280E02000070|25.75;28AC5F2600008030|25.75;"
                        {
                            FunctionID = functionID,
                        }
                    });
                })
                     );

                context.SaveChanges();

                var module = context.Modules.AsNoTracking().Where(i => i.Address == address).Single();
                var packet = context.Packets.Include(i => i.Function).AsNoTracking().Where(i => i.ModuleID == module.ID).OrderByDescending(i => i.Created).First();

                // ReSharper disable once PossibleInvalidOperationException
                var functionHandler = functionHandlers[packet.Function.FunctionType];
                var taskQueue       = new HubMessageQueue();

                functionHandler.Handle(new FunctionHandlerContext(moduleConfiguration, context, queryableFunctionHandlers, functionTypes, functionNames, triggerSourceHandlers, triggerDelegates, triggerDependencyHandlers, DateTime.Now), packet, ref taskQueue);

                context.SaveChanges();
            }
        }
Example #3
0
 public abstract FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue);
        protected override void ItemCallback(FunctionHandlerContext context, Packet packet, HubMessageQueue hubMessageQueue, KeyValuePair <string, string> item, TemperatureSensor sensor, bool wasSensorCreated)
        {
            decimal reading;

            if (!decimal.TryParse(item.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out reading))
            {
                Log(context, packet,
                    MethodBase.GetCurrentMethod().GetFullName(),
                    $"Could not parse text '{item.Value}' to decimal temperature.");

                return;
            }

            var temperatureReading = new TemperatureReadout(sensor.ID, reading, packet.Received);

            context.DatabaseContext.TemperatureReadouts.Add(temperatureReading);

            hubMessageQueue.Enqueue(i => i.NewTemperatureReading(packet.Module.ID, temperatureReading.TemperatureSensorID, temperatureReading.Value, temperatureReading.Created, temperatureReading.Received));
        }
Example #5
0
        public sealed override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
        {
            var items  = GetItems(context.ModuleConfiguration, packet);
            var module = packet.Module;
            var moduleTemperatureSensors = context.DatabaseContext.TemperatureSensors
                                           .AsNoTracking()
                                           .Where(i => i.ModuleID == module.ID)
                                           .ToDictionary(i => i.Address, i => i);

            var newSensors = new List <TemperatureSensor>();

            foreach (var item in items)
            {
                var address = GetAddress(item).ToUpper();
                var isAdded = false;
                TemperatureSensor temperatureSensor;

                if (moduleTemperatureSensors.ContainsKey(address))
                {
                    temperatureSensor = moduleTemperatureSensors[address];
                }
                else
                {
                    temperatureSensor = new TemperatureSensor(module, address);

                    context.DatabaseContext.TemperatureSensors.Add(temperatureSensor);
                    moduleTemperatureSensors.Add(temperatureSensor.Address, temperatureSensor);
                    newSensors.Add(temperatureSensor);

                    isAdded = true;
                    context.DatabaseContext.SaveChanges();

                    hubMessageQueue.Enqueue(i => i.NewTemperatureSensor(temperatureSensor.ModuleID, temperatureSensor.ID, temperatureSensor.Address));
                }

                ItemCallback(context, packet, hubMessageQueue, item, temperatureSensor, isAdded);
            }

            if (newSensors.Count > 0)
            {
                var message = new Message(context.FunctionTypes.Forward[FunctionTypeEnum.OwDS18B20TemperaturePeriodical], true)
                {
                    ModuleID = module.ID,
                };

                context.DatabaseContext.Messages.Add(message);
            }

            context.DatabaseContext.SaveChanges();

            OnHandled(context, module, hubMessageQueue, newSensors);

            return(new FunctionHandlerResult(PacketStateEnum.Handled, newSensors.Count > 0));
        }
Example #6
0
 protected virtual void OnHandled(FunctionHandlerContext context, Module module, HubMessageQueue hubMessageQueue, IReadOnlyCollection <TemperatureSensor> newSensors)
 {
 }
Example #7
0
 protected virtual void ItemCallback(FunctionHandlerContext context, Packet packet, HubMessageQueue hubMessageQueue, T item, TemperatureSensor sensor, bool wasSensorCreated)
 {
 }
Example #8
0
        protected override void OnHandled(FunctionHandlerContext context, Module module, HubMessageQueue hubMessageQueue, IReadOnlyCollection <TemperatureSensor> newSensors)
        {
            var dictionary = newSensors.ToDictionary(i => i.ID, i => i.Address);

            hubMessageQueue.Enqueue(i => i.NewOneWireDevices(module.ID, dictionary));
        }
Example #9
0
        public PacketStateEnum Handle(FunctionHandlerContext context, Packet originalPacket, string response, HubMessageQueue hubMessageQueue)
        {
            var module = originalPacket.Module;

            int periodUnits;

            if (!int.TryParse(response, NumberStyles.Integer, CultureInfo.InvariantCulture, out periodUnits))
            {
                return(LogAndReturn(context, originalPacket,
                                    MethodBase.GetCurrentMethod().GetFullName(),
                                    $"Could not parse text '{originalPacket.Text}' to integer period units."));
            }

            if (periodUnits < 0)
            {
                return(LogAndReturn(context, originalPacket,
                                    MethodBase.GetCurrentMethod().GetFullName(),
                                    $"Period units {periodUnits} cannot be negative."));
            }

            var periodLengthinMs = periodUnits * context.ModuleConfiguration.PeriodUnitLengthInMs;
            var period           = TimeSpan.FromMilliseconds(periodLengthinMs);

            context.DatabaseContext.EnqueueUpdate <TemperatureSensor>(
                i => i.Period == period,
                i => i.ModuleID == module.ID);

            context.DatabaseContext.ExecuteRaw();

            hubMessageQueue.Enqueue(i => i.ChangedTemperatureSensorPeriod(module.ID, period));

            return(PacketStateEnum.Handled);
        }
Example #10
0
 public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
 => Handle(context, packet, packet.Text, hubMessageQueue);
Example #11
0
        public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
        {
            var module = packet.Module;

            decimal reading;

            if (!decimal.TryParse(packet.Text, NumberStyles.Number, CultureInfo.InvariantCulture, out reading))
            {
                return(LogAndReturn(context, packet,
                                    MethodBase.GetCurrentMethod().GetFullName(),
                                    $"Could not parse text '{packet.Text}' to decimal voltage."));
            }

            var voltageReading = new VoltageReadout(module.ID, reading, packet.Received);

            context.DatabaseContext.VoltageReadouts.Add(voltageReading);
            context.DatabaseContext.SaveChanges();

            hubMessageQueue.Enqueue(i => i.NewVoltageReading(voltageReading.ModuleID, voltageReading.Value, voltageReading.Created, voltageReading.Received));

            return(PacketStateEnum.Handled);
        }
Example #12
0
        public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
        {
            var module = packet.Module;

            var currentFunctions = context.DatabaseContext
                                   .Functions
                                   .ToDictionary(i => i.Name, i => i)
                                   .ReadOnly();

            var currentModuleFunctions = context.DatabaseContext
                                         .ModuleFunctions
                                         .AsNoTracking()
                                         .Where(i => i.ModuleID == module.ID)
                                         .Select(i => i.FunctionID)
                                         .ToHashSet();

            var functionNames = packet.Text
                                .ToLowerInvariant()
                                .Split(context.ModuleConfiguration.FunctionResultDelimiter)
                                .Where(i => !string.IsNullOrEmpty(i))
                                .ToList();

            var newModuleFunctions = new List <KeyValuePair <FunctionTypeEnum, string> >(functionNames.Count);

            foreach (var functionName in functionNames)
            {
                var function = currentFunctions.GetValueOrDefault(functionName);
                if (function != null && currentModuleFunctions.Contains(function.ID))
                {
                    continue;
                }

                if (function == null)
                {
                    Log(context, packet,
                        MethodBase.GetCurrentMethod().GetFullName(),
                        $"Unknown function '{functionName}' received in th list.");
                }

                function = function ?? new Function(FunctionTypeEnum.Unknown, false);

                context.DatabaseContext.ModuleFunctions.Add(new ModuleFunction(module, function));

                newModuleFunctions.Add(KeyValuePair.Create(function.FunctionType, function.Name));
            }

            if (newModuleFunctions.Count > 0)
            {
                context.DatabaseContext.SaveChanges();

                hubMessageQueue.Enqueue(i => i.NewModuleFunctions(module.ID, newModuleFunctions));
            }

            return(PacketStateEnum.Handled);
        }
Example #13
0
        public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
        {
            var module = packet.Module;

            if (module.State != ModuleStateEnum.New)
            {
                return(PacketStateEnum.Redundant);
            }

            context.DatabaseContext.Messages.Add(new Message(context.FunctionTypes.Forward[FunctionTypeEnum.FunctionList], false)
            {
                Module = module
            });

            context.DatabaseContext.Messages.Add(new Message(context.FunctionTypes.Forward[FunctionTypeEnum.Report], false)
            {
                Module = module
            });

            module.State = ModuleStateEnum.Identified;

            context.DatabaseContext.EnqueueUpdate <Module>(
                i => i.State == ModuleStateEnum.Identified,
                i => i.ID == packet.ModuleID);

            context.DatabaseContext.EnqueueUpdate <Packet>(
                i => i.State == PacketStateEnum.New,
                i => i.ModuleID == packet.ModuleID && i.State == PacketStateEnum.Skipped);

            context.DatabaseContext.SaveChanges();

            hubMessageQueue.Enqueue(i => i.NewModule(module.ID, module.Address));

            return(new FunctionHandlerResult(PacketStateEnum.Handled, true, true));
        }
Example #14
0
        public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue)
        {
            var queryableFunctionPairs = FunctionHandlerHelper.SplitPairs(packet.Text, context.ModuleConfiguration.FunctionResultDelimiter, context.ModuleConfiguration.FunctionResultNameDelimiter);
            var module          = packet.Module;
            var moduleFunctions = context.DatabaseContext.ModuleFunctions
                                  .AsNoTracking()
                                  .Where(i => i.ModuleID == module.ID)
                                  .Select(i => i.FunctionID)
                                  .ToHashSet();

            foreach (var queryableFunctionPair in queryableFunctionPairs)
            {
                var functionName = queryableFunctionPair.Key;
                var functionID   = context.FunctionNames.Forward.GetValueOrNullable(functionName);
                if (!functionID.HasValue)
                {
                    Log(context, packet,
                        MethodBase.GetCurrentMethod().GetFullName(),
                        $"Unrecognized function '{functionName}' received in the report.");

                    continue;
                }

                if (!moduleFunctions.Contains(functionID.Value))
                {
                    Log(context, packet,
                        MethodBase.GetCurrentMethod().GetFullName(),
                        $"Unbound function '{functionName}' received in the report.");

                    continue;
                }

                var functionType = context.FunctionTypes.Reverse[functionID.Value];
                var handler      = context.QueryableFunctionHandlers.GetValueOrDefault(functionType);
                if (handler == null)
                {
                    Log(context, packet,
                        MethodBase.GetCurrentMethod().GetFullName(),
                        $"No handler found for function '{functionName}' received in the report.");

                    continue;
                }

                handler.Handle(context, packet, queryableFunctionPair.Value, hubMessageQueue);
            }

            return(PacketStateEnum.Handled);
        }
Example #15
0
        internal static bool HandlePackets(PiSensorNetDbContext context, IpiSensorNetConfiguration moduleConfiguration, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, IReadOnlyMap <string, int> functionNames, IReadOnlyDictionary <FunctionTypeEnum, IFunctionHandler> functionHandlers, IReadOnlyDictionary <FunctionTypeEnum, IQueryableFunctionHandler> queryableFunctionHandlers, IReadOnlyDictionary <TriggerSourceTypeEnum, ITriggerSourceHandler> triggerSourceHandlers, IReadOnlyDictionary <int, TriggerDelegate> triggerDelegates, IReadOnlyDictionary <TriggerDependencyTypeEnum, ITriggerDependencyHandler> triggerDependencyHandlers, int?serialProcessID, IHubProxy hubProxy, Action <string> logger)
        {
            logger("HandlePackets: Start...");

            var packets = context.Packets
                          .Include(i => i.Module)
                          .Include(i => i.Function)
                          .Where(i => i.State == PacketStateEnum.New)
                          .Where(i => i.FunctionID.HasValue)
                          .OrderBy(i => i.Received)
                          .ToList();

            logger("HandlePackets: Done selecting..."); // ~21ms

            if (packets.Count == 0)
            {
                return(false);
            }

            var handlerContext = new FunctionHandlerContext(moduleConfiguration, context, queryableFunctionHandlers, functionTypes, functionNames, triggerSourceHandlers, triggerDelegates, triggerDependencyHandlers, DateTime.Now);

            var handleAgain     = false;
            var newMesagesAdded = false;
            var hubTasksQueue   = new HubMessageQueue();

            foreach (var packet in packets)
            {
                // ReSharper disable once PossibleInvalidOperationException
                var handler = functionHandlers.GetValueOrDefault(packet.Function.FunctionType);
                if (handler == null)
                {
                    context.EnqueueUpdate <Packet>(
                        i => i.State == PacketStateEnum.Unhandled,
                        i => i.ID == packet.ID);

                    logger($"HandlePackets: Packet #{packet.ID} (function '{packet.Function.FunctionType}') could not be handled, no handler found!");

                    continue;
                }

                var functionHandlerResult = handler.IsModuleIdentityRequired && packet.Module.State != ModuleStateEnum.Identified
                    ? PacketStateEnum.Skipped
                    : handler.Handle(handlerContext, packet, ref hubTasksQueue);

                handleAgain     = handleAgain || functionHandlerResult.ShouldHandlePacketsAgain;
                newMesagesAdded = newMesagesAdded || functionHandlerResult.NewMessagesAdded;

                context.EnqueueUpdate <Packet>(
                    i => i.State == functionHandlerResult.PacketState && i.Processed == DateTime.Now,
                    i => i.ID == packet.ID);

                if (handler.TriggerSourceType.HasValue && functionHandlerResult.PacketState == PacketStateEnum.Handled)
                {
                    TriggerSources[handler.TriggerSourceType.Value].Each(i =>
                                                                         TriggerSourceHandlerHelper.Handle(handlerContext, i, packet.Module.ID));
                }

                logger($"HandlePackets: Packet #{packet.ID} processed to '{functionHandlerResult.PacketState}'" +
                       $"{(functionHandlerResult.NewMessagesAdded ? ", new messaged were added" : String.Empty)}" +
                       $"{(functionHandlerResult.ShouldHandlePacketsAgain ? ", requested another handling" : String.Empty)}" +
                       "!");
            }

            logger($"HandlePackets: Done handling packets, processed {packets.Count}!"); // ~51ms

            context.ExecuteRaw();

            logger("HandlePackets: Queries executed!"); // ~13ms

            if (newMesagesAdded && serialProcessID.HasValue)
            {
                Signal.Send(serialProcessID.Value, SignalTypeEnum.User1);
            }

            while (hubTasksQueue.Count > 0)
            {
                hubProxy.SafeInvoke(hubTasksQueue.Dequeue());
            }

            logger($"HandlePackets: Hub message(s) sent{(newMesagesAdded ? ", Serial signaled about new message(s)" : String.Empty)}{(handleAgain ? ", packet(s) will be handled again" : String.Empty)}!"); // ~10ms

            return(handleAgain);
        }