protected override void OnStart(string[] args)
        {
            int port = int.Parse(ConfigurationManager.AppSettings["WebSocketServerPort"]);
            _wsServerWrapper = new WebSocketServerWrapper(port: port);
            _userManager = new UserManager(_wsServerWrapper);
            _wsServerWrapper.Start();
            Trace.TraceInformation("Started server on {0}:{1}", IPAddress.Any, port);

            _nmsWrapper = new NMSWrapper(_userManager, _cancellationTokenSource);
            _cacheController = new CacheController(_nmsWrapper, _wsServerWrapper, _userManager);
            _nmsTask = _nmsWrapper.Start();

            _nmsTimer = new Timer((s) =>
            {
                if (_cancellationTokenSource.IsCancellationRequested)
                {
                    Trace.TraceError("Cancellation Requested");
                    ExitCode = -1;
                    throw new OperationCanceledException(_cancellationTokenSource.Token);
                }
                else if (_nmsTask.IsFaulted)
                {
                    Trace.TraceError("NMS Task Faulted: {0}", _nmsTask.Exception);
                    ExitCode = -1;
                    throw _nmsTask.Exception;
                }
                else if (_nmsTask.IsCompleted)
                {
                    Trace.TraceInformation("NMS Task Finished");

                    Stop();
                }
            }, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
        }
 public NMSWrapper(UserManager userManager, CancellationTokenSource cancellationTokenSource)
 {
     _userManager = userManager;
     _cancellationTokenSource = cancellationTokenSource;
     _nmsDownloader = new NMSConnector(_cancellationTokenSource);
 }
        public CacheController(NMSWrapper nmsWrapper, WebSocketServerWrapper wssWrapper, UserManager userManager)
        {
            _tiplocs = _tiplocRepository.GetTiplocs().ToList();

            _userManager = userManager;
            nmsWrapper.FeedDataRecieved += (s, f) =>
            {
                Task.Run(() =>
                     {
                         switch (f.Source)
                         {
                             case Common.Feed.TrainMovement:
                                 ICollection<ITrainData> data = new List<ITrainData>(32);
                                 foreach (var message in f.Data)
                                 {
                                     switch (byte.Parse((string)message.header.msg_type))
                                     {
                                         // activation
                                         case 1:
                                             data.Add(CacheActivation(message.body));
                                             break;

                                         // cancellation
                                         case 2:
                                             data.Add(CacheTrainCancellation((string)message.body.train_id, message.body));
                                             break;

                                         // train movement
                                         case 3:
                                             data.Add(CacheTrainMovement((string)message.body.train_id, message.body));
                                             break;

                                         // unidentified train
                                         case 4:
                                             break;

                                         // train reinstatement
                                         case 5:
                                             data.Add(CacheTrainReinstatement((string)message.body.train_id, message.body));
                                             break;

                                         // train change of origin
                                         case 6:
                                             data.Add(CacheChangeOfOrigin((string)message.body.train_id, message.body));
                                             break;

                                         // train change of identity
                                         case 7:
                                             break;

                                         // train change of location
                                         case 8:
                                             break;
                                     }
                                 }
                                 data = data.Where(d => d != null)
                                     .ToList();
                                 if (data.Any())
                                 {
                                     lock (_cacheLock)
                                     {
                                         CacheServiceClient cacheService = null;
                                         try
                                         {
                                             cacheService = new CacheServiceClient();
                                             cacheService.Open();
                                             cacheService.CacheTrainData(data);
                                         }
                                         finally
                                         {
                                             try
                                             {
                                                 if (cacheService != null)
                                                     cacheService.Close();
                                             }
                                             catch (CommunicationObjectFaultedException e)
                                             {
                                                 Trace.TraceError("Error Closing Cache Connection: {0}", e);
                                             }
                                         }
                                     }
                                 }
                                 break;
                             case Common.Feed.TrainDescriber:
                                 ICollection<TrainDescriber> tdData = new List<TrainDescriber>(32);
                                 foreach (var message in f.Data)
                                 {
                                     tdData.Add(TrainDescriberMapper.MapFromBody(message));
                                 }
                                 tdData = tdData.Where(d => d != null)
                                     .ToList();

                                 if (tdData.Any())
                                 {
                                     TDCacheServiceClient cacheService = null;
                                     try
                                     {
                                         cacheService = new TDCacheServiceClient();
                                         cacheService.Open();
                                         cacheService.CacheTrainDescriberData(tdData);
                                     }
                                     catch (Exception e)
                                     {
                                         Trace.TraceError("Error In Cache Connection: {0}", e);
                                     }
                                     finally
                                     {
                                         try
                                         {
                                             if (cacheService != null)
                                                 cacheService.Close();
                                         }
                                         catch (CommunicationObjectFaultedException e)
                                         {
                                             Trace.TraceError("Error Closing Cache Connection: {0}", e);
                                         }
                                     }
                                 }
                                 break;

                             case Common.Feed.VSTP:

                                 ScheduleTrain train = null;
                                 try
                                 {
                                     train = VSTPMapper.ParseJsonVSTP(f.Data, _tiplocs);
                                 }
                                 catch (TiplocNotFoundException tnfe)
                                 {
                                     Trace.TraceError("Could not add VSTP: {0}", tnfe);
                                 }
                                 catch (Exception e)
                                 {
                                     Trace.TraceError("Could not add VSTP: {0}", e);
                                 }

                                 if (train != null)
                                 {
                                     CacheServiceClient cacheService = null;
                                     try
                                     {
                                         cacheService = new CacheServiceClient();
                                         cacheService.Open();
                                         cacheService.CacheVSTPSchedule(train);
                                     }
                                     catch (Exception e)
                                     {
                                         Trace.TraceError("Error In Cache Connection: {0}", e);
                                     }
                                     finally
                                     {
                                         try
                                         {
                                             if (cacheService != null)
                                                 cacheService.Close();
                                         }
                                         catch (CommunicationObjectFaultedException e)
                                         {
                                             Trace.TraceError("Error Closing Cache Connection: {0}", e);
                                         }
                                     }
                                 }

                                 break;

                             case Common.Feed.RtPPM:
                                 RtppmData ppmData = null;
                                 try
                                 {
                                     ppmData = PPMJsonMapper.ParsePPMData(f.Data.RTPPMDataMsgV1.RTPPMData);
                                 }
                                 catch (Exception e)
                                 {
                                     Trace.TraceError("Could not add PPM Data: {0}", e);
                                 }
                                 if (ppmData != null)
                                 {
                                     CacheServiceClient cacheService = null;
                                     try
                                     {
                                         cacheService = new CacheServiceClient();
                                         cacheService.Open();
                                         cacheService.CachePPMData(ppmData);
                                     }
                                     catch (Exception e)
                                     {
                                         Trace.TraceError("Error In Cache Connection: {0}", e);
                                     }
                                     finally
                                     {
                                         try
                                         {
                                             if (cacheService != null)
                                                 cacheService.Close();
                                         }
                                         catch (CommunicationObjectFaultedException e)
                                         {
                                             Trace.TraceError("Error Closing Cache Connection: {0}", e);
                                         }
                                     }
                                 }
                                 break;
                         }
                     });
            };

            wssWrapper.OnReceive += (s, context) =>
            {
                string command = context.UserContext.DataFrame.ToString();
                int idx = command.IndexOf(':');
                if (idx != -1)
                {
                    string cmdText = new string(command.Take(idx).ToArray());
                    string args = new string(command.Skip(idx + 1).ToArray());
                    switch (cmdText)
                    {
                        case "substanox":
                            HandleSubStanoxCommand(context, args, true);
                            break;
                        case "unsubstanox":
                            HandleSubStanoxCommand(context, args, false);
                            break;
                    }
                }
            };
        }