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); }
// 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(); } }
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)); }
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)); }
protected virtual void OnHandled(FunctionHandlerContext context, Module module, HubMessageQueue hubMessageQueue, IReadOnlyCollection <TemperatureSensor> newSensors) { }
protected virtual void ItemCallback(FunctionHandlerContext context, Packet packet, HubMessageQueue hubMessageQueue, T item, TemperatureSensor sensor, bool wasSensorCreated) { }
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)); }
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); }
public override FunctionHandlerResult Handle(FunctionHandlerContext context, Packet packet, ref HubMessageQueue hubMessageQueue) => Handle(context, packet, packet.Text, hubMessageQueue);
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); }
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); }
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)); }
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); }
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); }