public async Task StartAsync( CancellationToken cancellationToken) { _appLifetime.ApplicationStarted.Register(OnStarted); _appLifetime.ApplicationStopping.Register(OnStopping); _appLifetime.ApplicationStopped.Register(OnStopped); using var scope = _serviceProvider.CreateScope(); var serverBuilder = scope.ServiceProvider.GetRequiredService <IServerBuilder>(); var options = serverBuilder.GetOptionsBuilder(_interceptor, _messageInterceptor); Server = serverBuilder.GetServer(); await Server.StartAsync(options.Build()); Server.StartedHandler = new MqttServerStartedHandlerDelegate(e => { Console.WriteLine("Mqtt Broker start " + e); }); Server.StoppedHandler = new MqttServerStoppedHandlerDelegate(e => { Console.WriteLine("Mqtt Broker stop " + e); }); Server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(e => { var vehicleId = e.TopicFilter.Topic .Replace("platooning/", "").Replace("/#", ""); _logger.LogInformation("Client subscribed " + e.ClientId + " topic " + e.TopicFilter.Topic + "Vehicle Id " + vehicleId); try { var audit = new Audit { ClientId = e.ClientId, Type = "Sub", Topic = e.TopicFilter.Topic, Payload = JsonConvert.SerializeObject(e.TopicFilter, Formatting.Indented) }; _repo.AddAudit(audit); var sub = _repo.GetSubscribeByTopic(e.ClientId, e.TopicFilter.Topic, e.TopicFilter.QualityOfServiceLevel.ToString()); if (sub != null) { _logger.LogInformation($"There is a subcribe like ClientID {e.ClientId}."); return; } var subClient = new Subscribe { Topic = e.TopicFilter.Topic, Enable = true, ClientId = e.ClientId, QoS = e.TopicFilter.QualityOfServiceLevel.ToString() }; _repo.AddSubscribe(subClient); } catch (Exception exception) { var log = new Log { Exception = exception.StackTrace }; _repo.AddLogAsync(log); _logger.LogError("Error = MqttServerClientSubscribedHandlerDelegate ", exception.StackTrace); } finally { _repo.SaveChangesAsync(cancellationToken); } }); Server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e => { try { var clientId = e.ClientId; var topicFilter = e.TopicFilter; _logger.LogInformation($"[{DateTime.Now}] Client '{clientId}' un-subscribed to {topicFilter}."); try { var sub = _repo.GetSubscribeById(e.ClientId).Where(s => s.Topic == topicFilter); var subscribes = sub as List <Subscribe> ?? sub.ToList(); if (subscribes.All(a => a.Topic != topicFilter)) { return; } subscribes .ForEach(a => a.Enable = false); } catch (Exception exception) { var log = new Log { Exception = exception.StackTrace }; _repo.AddLogAsync(log); _logger.LogError("Error = MqttServerClientSubscribedHandlerDelegate ", exception.StackTrace); Console.WriteLine(exception); } } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now}] Client get error " + ex.Message); } finally { _repo.SaveChangesAsync(cancellationToken); } }); Server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => { try { var payload = Functions.GetPayload(e.ApplicationMessage.Payload); var payloadser = JsonConvert.SerializeObject(payload, Formatting.Indented); var tree = e.ApplicationMessage.Topic.Split('/'); var audit = new Audit { ClientId = e.ClientId, Type = "Pub", Topic = e.ApplicationMessage.Topic, Payload = payloadser }; _repo.AddAudit(audit); if (e.ClientId == null) { var log = new Log { Exception = new string("Broker publish message itself " + payloadser + " " + e.ClientId) }; _repo.AddLogAsync(log); //_repo.SaveChangesAsync(cancellationToken); return; } if (!tree.First().Contains("platooning")) { var log = new Log { Exception = new string("Mqtt broker just only response with starting \"platoon\" " + payloadser + " " + e.ClientId) }; _repo.AddLogAsync(log); //_repo.SaveChangesAsync(cancellationToken); return; } if (payload.PlatoonDissolveStatus) { if (_repo.GetPlatoon().Any(a => a.ClientId == e.ClientId && a.IsLead)) { Console.WriteLine( $"[{DateTime.Now}] This is lead Vehicle PlatoonDissolveStatus is true all platoon infor must be deleted" + " Client Id " + e.ClientId + " payload " + payload); var platoonlist = _repo.GetPlatoon().Where(a => a.IsFollower); var platoonlistArray = platoonlist as Platoon[] ?? platoonlist.ToArray(); foreach (var platoon in platoonlistArray) { Server.UnsubscribeAsync(platoon.ClientId, "platooning/broadcast/" + platoon.PlatoonRealId); Server.UnsubscribeAsync(platoon.ClientId, "platooning/" + platoon.ClientId); } _repo.DeletePlatoonRange(platoonlistArray); } else { Console.WriteLine( $"[{DateTime.Now}] This is following Vehicle PlatoonDissolveStatus is true all platoon infor must be deleted" + " Client Id " + e.ClientId + " payload " + payload); var followingVehicle = _repo.GetPlatoon().FirstOrDefault(a => a.IsFollower && a.ClientId == e.ClientId); Server.UnsubscribeAsync(followingVehicle.ClientId, "platooning/" + followingVehicle.ClientId); _repo.DeletePlatoon(followingVehicle); } } if (payload.Maneuver == Maneuver.CreatePlatoon) { if (tree.Length != 4) { var log = new Log { Exception = new string("For creating platoon, topic must 4 length 1. \"platooning\" " + " 2. \"message\" " + " 3. \"leadvehicleID\" " + " 4. \"platoonID\" " + " payload " + payloadser + " " + " client ID " + e.ClientId + " topic " + e.ApplicationMessage.Topic) }; _repo.AddLogAsync(log); //_repo.SaveChangesAsync(cancellationToken); return; } var platoonId = tree[3]; var platoonList = _repo.GetPlatoon().ToList(); var leadVehicleId = tree[2]; var leadVehicle = _repo.GetSubscribeById(leadVehicleId); var pla = platoonList .FirstOrDefault(f => f.Enable && f.PlatoonRealId == platoonId); if (leadVehicle != null && pla == null) { var platoon = new Platoon() { Enable = true, ClientId = e.ClientId, IsLead = true, VechicleId = tree[2], PlatoonRealId = tree[3] }; _repo.AddPlatoon(platoon); Console.WriteLine($"[{DateTime.Now}] Creating new Platoon Client Id " + e.ClientId + " platooning Id" + platoon.PlatoonRealId + " payload " + payloadser); } else { Console.WriteLine($"[{DateTime.Now}] Platoon is already created Client Id " + e.ClientId + " platooning Id" + platoonId + " payload " + payloadser); } } else if (payload.Maneuver == Maneuver.JoinRequest) { if (tree.Length != 3) { var log = new Log { Exception = new string("For joining platoon, topic must 3 length 1. \"platooning\" " + " 2. \"message\" " + " 3. \"followingVehicleId\" " + " 4. \"#\" " + " payload " + payloadser + " " + " client ID " + e.ClientId + " topic " + e.ApplicationMessage.Topic) }; _repo.AddLogAsync(log); //_repo.SaveChangesAsync(); return; } var isFollowing = _repo.GetPlatoon() .FirstOrDefault(f => f.IsFollower && f.VechicleId == tree[2] && f.Enable); if (isFollowing != null) { return; } var platoonLead = _repo.GetPlatoon().FirstOrDefault(f => f.IsLead && f.Enable); if (platoonLead != null) { var platoon = new Platoon() { Enable = false, ClientId = e.ClientId, IsLead = false, IsFollower = true, VechicleId = tree[2], PlatoonRealId = platoonLead.PlatoonRealId }; _repo.AddPlatoon(platoon); Console.WriteLine($"[{DateTime.Now}] Join Platoon Client Id " + e.ClientId + " platooning Id" + platoon.PlatoonRealId + " payload " + payloadser); var message = new BitArray(_dataLenght); message.Set(0, false); message.Set(1, false); message.Set(2, true); Server.PublishAsync("platooning/" + platoonLead.ClientId + "/" + tree[2], Encoding.ASCII.GetString(Functions.BitArrayToByteArray(message))); } } else if (payload.Maneuver == Maneuver.JoinAccepted) { Console.WriteLine($"[{DateTime.Now}] Join accepted Client Id " + e.ClientId + " payload " + payloadser); var followvehicleId = tree[1]; var leadVehicle = tree[2]; var plattonId = tree[3]; var allplatoon = _repo.GetPlatoon(); if (allplatoon != null) { var enumerable = allplatoon as Platoon[] ?? allplatoon.ToArray(); var platoonfollow = enumerable.FirstOrDefault(f => f.IsFollower && f.ClientId == followvehicleId); if (platoonfollow != null) { platoonfollow.Enable = true; platoonfollow.PlatoonRealId = plattonId; _repo.UpdatePlatoon(platoonfollow); } else { var platoonlead = enumerable .FirstOrDefault(f => f.IsLead && f.Enable && f.ClientId == leadVehicle); if (platoonlead != null) { var platoon = new Platoon() { Enable = true, ClientId = e.ClientId, IsLead = false, IsFollower = true, VechicleId = followvehicleId, PlatoonRealId = platoonlead.PlatoonRealId }; _repo.AddPlatoon(platoon); } } } } else if (payload.Maneuver == Maneuver.JoinRejected) { Console.WriteLine($"[{DateTime.Now}] Join rejected Client Id " + e.ClientId + " payload " + payloadser); var platoonfollow = _repo.GetPlatoon() .FirstOrDefault(f => f.IsFollower && f.ClientId == tree[1]); if (platoonfollow != null) { _repo.DeletePlatoon(platoonfollow); } } else { var log = new Log { Exception = new string("Unknown Maneuver " + payloadser + " " + e.ClientId) }; _repo.AddLogAsync(log); } } catch (Exception exception) { Console.WriteLine(exception); var log = new Log { Exception = exception.StackTrace }; _repo.AddLogAsync(log); } finally { _repo.SaveChangesAsync(cancellationToken); } OnDataReceived(e.ApplicationMessage.Payload); }); }