private HashSet <string> GetNonExistingMappingFields(IReadOnlyMap <string, string> fieldsMapping) { var nonExistingFields = new HashSet <string>(); string mappedFieldName; foreach (var fieldName in base.GetFieldNames()) { if (!fieldsMapping.TryGetKey(fieldName, out mappedFieldName)) { // If nothing maps into current field - ignore continue; } // There is a mapping that results into already existing field, preserve source field name nonExistingFields.Add(mappedFieldName); } // All preserved source field names should be ignored (should not belong to data item), otherwise we have a conflict foreach (var fieldName in base.GetFieldNames()) { if (nonExistingFields.Contains(fieldName) && // this is not a check, just get target field name for the exception message fieldsMapping.TryGetValue(fieldName, out mappedFieldName)) { throw Errors.DataItemAlreadyContainsField(mappedFieldName); } } return(nonExistingFields); }
public RemappedFieldsDataItem(IDataItem dataItem, IReadOnlyMap<string, string> fieldsMapping) : base(dataItem) { Guard.NotNull("fieldsMapping", fieldsMapping); this.fieldsMapping = fieldsMapping; inactiveMappings = GetNonExistingMappingFields(fieldsMapping); }
public RemappedFieldsDataItem(IDataItem dataItem, IReadOnlyMap <string, string> fieldsMapping) : base(dataItem) { Guard.NotNull("fieldsMapping", fieldsMapping); this.fieldsMapping = fieldsMapping; inactiveMappings = GetNonExistingMappingFields(fieldsMapping); }
public FunctionHandlerContext(IpiSensorNetConfiguration moduleConfiguration, PiSensorNetDbContext databaseContext, IReadOnlyDictionary <FunctionTypeEnum, IQueryableFunctionHandler> queryableFunctionHandlers, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, IReadOnlyMap <string, int> functionNames, IReadOnlyDictionary <TriggerSourceTypeEnum, ITriggerSourceHandler> triggerSourceHandlers, IReadOnlyDictionary <int, TriggerDelegate> triggerDelegates, IReadOnlyDictionary <TriggerDependencyTypeEnum, ITriggerDependencyHandler> triggerDependencyHandlers, DateTime triggerDateTime) : base(databaseContext, triggerSourceHandlers, triggerDelegates, triggerDependencyHandlers, triggerDateTime) { ModuleConfiguration = moduleConfiguration; QueryableFunctionHandlers = queryableFunctionHandlers; FunctionTypes = functionTypes; FunctionNames = functionNames; }
public static string GetOrEmpty(this IReadOnlyMap <string, string> coll, string key) { if (!coll.Contains(key)) { return(string.Empty); } return(coll[key] ?? string.Empty); }
// public static IEnumerable<TValue> GetOrNull<TKey, TValue>(this IReadOnlyMap<TKey, TValue> coll, TKey key) // { // if (!coll.Contains(key)) // { // return null; // } // // return coll[key]; // } // public static IEnumerable<TValue> GetOrEmpty<TKey, TValue>(this IReadOnlyMap<TKey, TValue> coll, TKey key) // { // if (!coll.Contains(key)) // { // return new TValue[0]; // } // // return coll[key]; // } public static TValue GetOrNull <TKey, TValue>(this IReadOnlyMap <TKey, TValue> coll, TKey key) { if (!coll.Contains(key)) { return(default(TValue)); } return(coll[key]); }
public static string Write(IReadOnlyMap <string, string> flash) { List <string> sb = new List <string>(); foreach (var key in flash.Keys) { sb.Add(string.Concat(Uri.EscapeDataString(key), "=", Uri.EscapeDataString(flash[key] ?? string.Empty))); } return(string.Join("&", sb)); }
// 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(); } }
private static void BuildCache() { using (var context = PiSensorNetDbContext.Connect(Configuration.ConnectionString)) { ModuleAddresses = CacheModuleAddresses(context); var cachedFunctions = CacheFunctions(context); FunctionTypes = cachedFunctions.Item1; FunctionNames = cachedFunctions.Item2; var cachedFunctionHandlers = CacheFunctionHandlers(); FunctionHandlers = cachedFunctionHandlers.Item1; QueryableFunctionHandlers = cachedFunctionHandlers.Item2; TriggerSourceHandlers = CacheTriggerSourceHandlers(); TriggerDependencyHandlers = CacheTriggerDependencyHandlers(); var cachedTriggerSources = CacheTriggerSources(context, TriggerDependencyHandlers); TriggerSources = cachedTriggerSources.Item1; TriggerDelegates = cachedTriggerSources.Item2; } ToConsole("BuildCache: Cache built!"); }
private HashSet<string> GetNonExistingMappingFields(IReadOnlyMap<string, string> fieldsMapping) { var nonExistingFields = new HashSet<string>(); string mappedFieldName; foreach (var fieldName in base.GetFieldNames()) { if (!fieldsMapping.TryGetKey(fieldName, out mappedFieldName)) // If nothing maps into current field - ignore continue; // There is a mapping that results into already existing field, preserve source field name nonExistingFields.Add(mappedFieldName); } // All preserved source field names should be ignored (should not belong to data item), otherwise we have a conflict foreach (var fieldName in base.GetFieldNames()) if (nonExistingFields.Contains(fieldName) && // this is not a check, just get target field name for the exception message fieldsMapping.TryGetValue(fieldName, out mappedFieldName)) throw Errors.DataItemAlreadyContainsField(mappedFieldName); return nonExistingFields; }
public static string Write(IReadOnlyMap <string, string> collection) { return(WriteInternal(collection, key => new[] { collection[key] ?? string.Empty })); }
public static IReadOnlyMap <TForwardKey, TReverseKey> ReadOnly <TForwardKey, TReverseKey>([CanBeNull] this IReadOnlyMap <TForwardKey, TReverseKey> map) => map;
public static TKey TryGetValue <TKey, TValue>(this IReadOnlyMap <TKey, TValue> map, TValue key, TKey defaultValue = default) { return(TryGetValue(map, key, out TKey result) ? result : defaultValue); }
public static Boolean TryGetValue <TKey, TValue>(this IReadOnlyMap <TKey, TValue> map, TValue key, out TKey result) { return(map.TryGetValue(key, out result)); }
public MapManager(IReadOnlyMap map) { Map = map; }
internal static bool MergePackets(PiSensorNetDbContext context, IpiSensorNetConfiguration moduleConfiguration, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, IReadOnlyMap <string, int> functionNames, IReadOnlyMap <string, int> moduleAddresses, CacheModuleAddressesDelegate cacheModuleAddresses, Action <string> logger) { logger("MergePackets: Start..."); var partialPackets = context.PartialPackets .AsNoTracking() .Where(i => i.State == PartialPacketStateEnum.New) .ToList(); //logger("MergePackets: Done selecting..."); // ~14ms var groupedPackets = partialPackets.GroupBy(i => new { i.Address, i.Number, i.Total }) .ToList(); var newModules = new Dictionary <string, Module>(); foreach (var packetGroup in groupedPackets) { var address = packetGroup.Key.Address; if (moduleAddresses.Forward.ContainsKey(address) || newModules.ContainsKey(address)) { continue; } var module = new Module(address); context.Modules.Add(module); newModules.Add(address, module); } if (newModules.Count > 0) { logger("MergePackets: Done finding modules..."); context.SaveChanges(); logger("MergePackets: Done saving modules..."); moduleAddresses = cacheModuleAddresses(context); } logger($"MergePackets: Done creating new modules, found {newModules.Count}!"); // 700us, no modules var packetGroupWithPacket = new List <Tuple <Packet, IEnumerable <PartialPacket> > >(groupedPackets.Count); foreach (var packetGroup in groupedPackets) { if (packetGroup.Count() != packetGroup.Key.Total) { context.EnqueueUpdate <PartialPacket>( i => i.State == PartialPacketStateEnum.Fragmented, i => packetGroup.Select(ii => ii.ID).Contains(i.ID)); continue; } var moduleID = moduleAddresses.Forward[packetGroup.Key.Address]; int?messageID = null; var text = packetGroup.OrderBy(i => i.Current).Select(i => i.Message).Concat(); var received = packetGroup.Max(i => i.Received); var messageIDDelimiterIndex = text.IndexOf(moduleConfiguration.MessageIDDelimiter); if (messageIDDelimiterIndex > 0) { messageID = text.Substring(0, messageIDDelimiterIndex).FromBase36(); text = text.Substring(messageIDDelimiterIndex + 1); } var functionName = text.SubstringBefore(moduleConfiguration.FunctionResultNameDelimiter).ToLowerInvariant(); var functionID = functionNames.Forward.GetValueOrNullable(functionName); if (functionID.HasValue) { text = text.Substring(functionName.Length + 1); } var packet = new Packet(moduleID, packetGroup.Key.Number, text, received) { MessageID = messageID, FunctionID = functionID, }; context.Packets.Add(packet); packetGroupWithPacket.Add(Tuple.Create(packet, (IEnumerable <PartialPacket>)packetGroup)); } if (packetGroupWithPacket.Count > 0) { //logger("MergePackets: Done parsing packet groups!"); // ~3ms context.SaveChanges(); logger("MergePackets: Saved changes!"); // ~23ms packetGroupWithPacket.Each(p => context.EnqueueUpdate <PartialPacket>( i => i.PacketID == p.Item1.ID && i.State == PartialPacketStateEnum.Merged, i => p.Item2.Select(ii => ii.ID).Contains(i.ID))); context.ExecuteRaw(); logger("MergePackets: Updated partial packets!"); // ~15ms, 1 packet } logger($"MergePackets: Done, created {packetGroupWithPacket.Count} packet(s)!"); return(packetGroupWithPacket.Count > 0); }
public RemapFieldsTransformation(IReadOnlyMap <string, string> fieldsMapping) { this.fieldsMapping = fieldsMapping; }
internal static void HandleMessage(string clientID, int?moduleID, FunctionTypeEnum functionType, bool isQuery, string text, IReadOnlyMap <string, int> moduleAddresses, IpiSensorNetConfiguration moduleConfiguration, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, IHubProxy hubProxy, Action <string> logger) { logger($"HandleMessage: Received message from ${clientID} to @{moduleID?.ToString() ?? "ALL"} - {functionType}{(text == null ? (isQuery ? "?" : String.Empty) : ":" + text)}"); if (moduleID.HasValue && !moduleAddresses.Reverse.ContainsKey(moduleID.Value)) { hubProxy.Invoke("error", clientID, $"Module #{moduleID.Value} does not exist."); logger($"HandleMessage: ERROR: Message not handled, module #{moduleID.Value} does not exist!"); return; } int messageID; using (var context = PiSensorNetDbContext.Connect(moduleConfiguration.ConnectionString)) { var message = new Message(functionTypes.Forward[functionType], isQuery) { ModuleID = moduleID, }; if (!isQuery) { message.Text = text; } context.Messages.Add(message); context.SaveChanges(); messageID = message.ID; } logger($"HandleMessage: Message handled to #{messageID}!"); // ~38ms }
private static IHubProxy InitializeHubConnection(IReadOnlyConfiguration configuration, IpiSensorNetConfiguration moduleConfiguration, MessageHandler handler, IReadOnlyMap <string, int> moduleAddresses, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, int?serialProcessID, DisposalQueue toDispose, Action <string> logger) { var hubConnection = new HubConnection(configuration["Settings:WebAddress"], new Dictionary <string, string> { { configuration["Settings:SignalREngineFlagName"], true.ToString().ToLowerInvariant() } }); hubConnection.StateChanged += change => logger($"InitializeHubConnection: StateChanged: '{change.OldState}' -> '{change.NewState}'!"); hubConnection.JsonSerializer.Converters.Add(new NullConverter()); // handle NULLs var hubProxy = hubConnection.CreateHubProxy(configuration["Settings:SignalRHubName"]); toDispose += hubProxy.On <string, int?, FunctionTypeEnum, string>("sendMessage", (clientID, moduleID, functionType, text) => handler(clientID, moduleID, functionType, false, text, moduleAddresses, moduleConfiguration, functionTypes, serialProcessID, hubProxy, logger)); toDispose += hubProxy.On <string, int?, FunctionTypeEnum>("sendQuery", (clientID, moduleID, functionType) => handler(clientID, moduleID, functionType, true, null, moduleAddresses, moduleConfiguration, functionTypes, serialProcessID, hubProxy, logger)); try { hubConnection.Start().Wait(); } catch (Exception e) { logger($"InitializeHubConnection: ERROR: Exception occurred while initializing hub connection: {e.Message}."); return(null); } logger($"InitializeHubConnection: Connection to hub started with ID '{hubConnection.ConnectionId}'!"); toDispose += hubConnection; return(hubProxy); }
private static void InternalHandleMessage(string clientID, int?moduleID, FunctionTypeEnum functionType, bool isQuery, string text, IReadOnlyMap <string, int> modules, IpiSensorNetConfiguration moduleConfiguration, IReadOnlyMap <FunctionTypeEnum, int> functionTypes, int?serialProcessID, IHubProxy hubProxy, Action <string> logger) { HandleMessage(clientID, moduleID, functionType, isQuery, text, modules, moduleConfiguration, functionTypes, hubProxy, logger); if (serialProcessID.HasValue) { Signal.Send(serialProcessID.Value, SignalTypeEnum.User1); } }
public static System.Collections.IDictionary CreateObjectIDictionary <TKey, TValue>(IReadOnlyMap <TKey, TValue> map) { return(new ObjectDictionaryShim <TKey, TValue>(map)); }
public static IDictionary <TKey, TValue> CreateIDictionary <TKey, TValue>(IReadOnlyMap <TKey, TValue> map) { return(new DictionaryShim <TKey, TValue>(map)); }
internal ObjectDictionaryShim(IReadOnlyMap <TKey, TValue> map) { m_map = map; }
public RemapFieldsTransformation(IReadOnlyMap<string, string> fieldsMapping) { this.fieldsMapping = fieldsMapping; }
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); }