From 6efec7f07b130f6766aaeca3bd4514065b402236 Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Sun, 9 Nov 2025 22:47:22 +0100 Subject: [PATCH] Can now parse SPT and TMST2 from GSE. --- .../InteractionChannel.cs | 10 ++++++++ skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs | 23 +++++++++++++++++++ .../InteractionChannelHandler.cs | 1 + .../InteractionChannel/Model2/Tmst2.cs | 4 ++-- .../NullInteractionChannelHandler.cs | 5 ++++ .../Skyscraper/Scraper/SkyscraperContext.cs | 12 ++++++++++ .../Scraper/SkyscraperContextEvent.cs | 3 ++- .../Skyscraper/Scraper/Storage/DataStorage.cs | 2 ++ .../Storage/Filesystem/FilesystemStorage.cs | 10 ++++++++ .../InMemory/InMemoryScraperStorage.cs | 19 +++++++++++++++ .../InteractionChannelContestant.cs | 10 +++++++- 11 files changed, 95 insertions(+), 4 deletions(-) diff --git a/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs b/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs index c9eccb3..b5f7b8d 100644 --- a/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs +++ b/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs @@ -965,6 +965,16 @@ namespace skyscraper5.Data.PostgreSql throw new NotImplementedException(); } + public bool TestForTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + throw new NotImplementedException(); + } + + public void InsertTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + throw new NotImplementedException(); + } + private bool AreArraysEqual(byte[] l, byte[] r) { if (l.Length != r.Length) diff --git a/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs b/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs index 623c465..95670cb 100644 --- a/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs +++ b/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs @@ -73,6 +73,16 @@ namespace skyscraper8.GS.GSE_BFBS Context.Rcs2Output.OnSuperframeComposition(gseTableStructure.InteractiveNetworkId, sct); return; + case 0xa3: + Spt spt = new Spt(ms); + if (!spt.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.SptInvalid); + return; + } + + Context.Rcs2Output.OnSatellitePosition(gseTableStructure.InteractiveNetworkId, spt); + return; case 0xa4: Cmt cmt = new Cmt(ms); if (!cmt.Valid) @@ -109,6 +119,19 @@ namespace skyscraper8.GS.GSE_BFBS } Context.Rcs2Output.OnTerminalBurstTimePlan2(gseTableStructure.InteractiveNetworkId, tbtp2); return; + case 0xae: + int rmtTransmissionStandard = Context.Rcs2Output.GetRmtTransmissionStandard(gseTableStructure.InteractiveNetworkId); + Tmst2 tmst2 = new Tmst2(ms, rmtTransmissionStandard); + if (!tmst2.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.Tmst2Invalid); + return; + } + Context.Rcs2Output.OnTransmissionModeSupport2(gseTableStructure.InteractiveNetworkId, tmst2); + return; + case 0xc0: + //User defined, we have no way of knowing what this is. + return; default: //See en_30154502v010401p.pdf //page 49 diff --git a/skyscraper8/InteractionChannel/InteractionChannelHandler.cs b/skyscraper8/InteractionChannel/InteractionChannelHandler.cs index 3330de2..3a49f52 100644 --- a/skyscraper8/InteractionChannel/InteractionChannelHandler.cs +++ b/skyscraper8/InteractionChannel/InteractionChannelHandler.cs @@ -36,5 +36,6 @@ namespace skyscraper5.src.InteractionChannel void OnBroadcastConfiguration(ushort networkId, Bct bct); void OnRcs2Nit(ushort interactiveNetworkId, RcsNit nit); void OnRcs2Tdt(ushort interactiveNetworkId, Rcs2Tdt tdt); + void OnTransmissionModeSupport2(ushort interactiveNetworkId, Tmst2 tmst2); } } diff --git a/skyscraper8/InteractionChannel/Model2/Tmst2.cs b/skyscraper8/InteractionChannel/Model2/Tmst2.cs index 781155d..467c636 100644 --- a/skyscraper8/InteractionChannel/Model2/Tmst2.cs +++ b/skyscraper8/InteractionChannel/Model2/Tmst2.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace skyscraper5.src.InteractionChannel.Model2 { - internal class Tmst2 : Validatable + public class Tmst2 : Validatable { public Tmst2(MemoryStream ms, int transmissionStandard) { @@ -28,7 +28,7 @@ namespace skyscraper5.src.InteractionChannel.Model2 } if (transmissionStandard == 3) { - throw new NotImplementedException("Transmisison standard 3"); + throw new NotImplementedException("Transmisison standard 3 in DVB-RCS2 is not yet supported. If possible, please share a sample of this stream."); } Valid = true; } diff --git a/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs b/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs index 785d564..745b2a8 100644 --- a/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs +++ b/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs @@ -48,6 +48,11 @@ namespace skyscraper5.src.InteractionChannel } + public void OnTransmissionModeSupport2(ushort interactiveNetworkId, Tmst2 tmst2) + { + + } + public void OnFrameComposition2(ushort? networkId, Fct2 fct2) { diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs index e7feccf..8ccbdca 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs @@ -2504,6 +2504,18 @@ namespace skyscraper5.Skyscraper.Scraper DataStorage.UpdateRcs2Tdt(interactiveNetworkId, tdt.Timestamp); } + public void OnTransmissionModeSupport2(ushort interactiveNetworkId, Tmst2 tmst2) + { + foreach (Tmst2.TransmissionMode mode in tmst2.TransmissionModes) + { + if (!DataStorage.TestForTmst2(interactiveNetworkId, mode)) + { + LogEvent(SkyscraperContextEvent.TransmissionModeSupport2, String.Format("Network ID #{0}, MODCOD {1}", interactiveNetworkId, mode.Modcod)); + DataStorage.InsertTmst2(interactiveNetworkId, mode); + } + } + } + void InteractionChannelHandler.OnTimeslotComposition(ushort interactiveNetworkId, Tct tct) { throw new NotImplementedException(); diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs index f38530c..0d3c5bf 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs @@ -91,6 +91,7 @@ BroadcastConfiguration, EthernetLinkLayerDiscovery, Rcs2Network, - Rcs2TdtTime + Rcs2TdtTime, + TransmissionModeSupport2 } } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs index d85639f..757acff 100644 --- a/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs +++ b/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs @@ -205,5 +205,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage bool TestForRcs2Nit(RcsNit nit); void InsertRcs2Nit(RcsNit nit); bool UpdateRcs2Tdt(ushort interactiveNetworkId, DateTime tdtTimestamp); + bool TestForTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode); + void InsertTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode); } } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs index 2621892..5cd85c3 100644 --- a/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs +++ b/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs @@ -1203,6 +1203,16 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem throw new NotImplementedException(); } + public bool TestForTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + throw new NotImplementedException(); + } + + public void InsertTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + throw new NotImplementedException(); + } + public IEnumerable> SelectAllPmt() { throw new NotImplementedException(); diff --git a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs index 2376946..42c19f0 100644 --- a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs +++ b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs @@ -1058,6 +1058,25 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory return false; } + private Dictionary, Tmst2.TransmissionMode> _tmst2; + public bool TestForTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + if (_tmst2 == null) + return false; + + Tuple key = new Tuple(interactiveNetworkId, mode.Modcod); + return _tmst2.ContainsKey(key); + } + + public void InsertTmst2(ushort interactiveNetworkId, Tmst2.TransmissionMode mode) + { + if (_tmst2 == null) + _tmst2 = new Dictionary, Tmst2.TransmissionMode>(); + + Tuple key = new Tuple(interactiveNetworkId, mode.Modcod); + _tmst2.Add(key, mode); + } + public IEnumerable> SelectAllPmt() { for (int x = 0; x < pmtEntries.Length; x++) diff --git a/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs b/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs index 9747e31..a07415b 100644 --- a/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs +++ b/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs @@ -221,7 +221,15 @@ namespace skyscraper5.src.Skyscraper.Scraper.StreamAutodetection.Contestants //TODO: put validation logic in here, important! } - public void OnFrameComposition2(ushort? networkId, Fct2 fct2) + public void OnTransmissionModeSupport2(ushort interactiveNetworkId, Tmst2 tmst2) + { + if (tmst2.TransmissionModes.Length > 0) + { + Score++; + } + } + + public void OnFrameComposition2(ushort? networkId, Fct2 fct2) { if (fct2.FrameTypes.Length > 0) {