├── .gitignore ├── LibraryTest ├── .gitignore ├── LibraryTest.csproj ├── LibraryTest.csproj.user ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── README.md ├── XRIT ├── .gitignore ├── Console │ ├── ConsoleMessage.cs │ └── UIConsole.cs ├── DCS │ ├── DCSHeader.cs │ └── DCSParser.cs ├── EventMaster │ ├── EventMaster.cs │ ├── EventMasterData.cs │ └── Events │ │ ├── ConfigChangeEventData.cs │ │ ├── EventTypes.cs │ │ ├── FrameEventData.cs │ │ └── NewFileReceivedEventData.cs ├── GOES │ ├── DemuxManager.cs │ ├── Demuxer.cs │ ├── EMWIN.cs │ ├── FileHandler.cs │ ├── ImageManager.cs │ ├── MultiImageManager.cs │ └── PacketManager.cs ├── Geo │ ├── GeoConverter.cs │ ├── GeoTools.cs │ └── MapDrawer.cs ├── LICENSE ├── LUT │ ├── falsecolor-original.png │ └── falsecolor.png ├── Log │ ├── Facility.cs │ ├── Level.cs │ ├── Message.cs │ └── SyslogClient.cs ├── Models │ ├── ConfigDescription.cs │ ├── CrashData.cs │ ├── GroupData.cs │ ├── OrganizerData.cs │ └── StackTraceData.cs ├── PacketData │ ├── AncillaryHeader.cs │ ├── AnnotationHeader.cs │ ├── DCSFilenameHeader.cs │ ├── EMWINHeader.cs │ ├── EmwinFile.cs │ ├── Enums │ │ ├── CompressionType.cs │ │ ├── FileTypeCode.cs │ │ ├── HeaderType.cs │ │ ├── NOAAProductID.cs │ │ ├── SatelliteID.cs │ │ └── SubProductEnums.cs │ ├── Head9Header.cs │ ├── HeaderStructuredHeader.cs │ ├── ImageDataFunctionHeader.cs │ ├── ImageNavigationHeader.cs │ ├── ImageStructureHeader.cs │ ├── MSDU.cs │ ├── MSDUInfo.cs │ ├── NOAAProduct.cs │ ├── NOAASpecificHeader.cs │ ├── NOAASubproduct.cs │ ├── Presets.cs │ ├── PrimaryHeader.cs │ ├── RiceCompressionHeader.cs │ ├── SegmentIdentificationHeader.cs │ ├── SequenceType.cs │ ├── Structs │ │ ├── AncillaryText.cs │ │ ├── AnnotationRecord.cs │ │ ├── DCSFilenameRecord.cs │ │ ├── HeaderStructuredRecord.cs │ │ ├── ImageDataFunctionRecord.cs │ │ ├── ImageNavigationRecord.cs │ │ ├── ImageStructureRecord.cs │ │ ├── NOAASpecificRecord.cs │ │ ├── PrimaryRecord.cs │ │ ├── RiceCompressionRecord.cs │ │ ├── SegmentIdentificationRecord.cs │ │ ├── TimestampRecord.cs │ │ └── UnknownHeaders.cs │ ├── TimestampHeader.cs │ ├── XRITHeader.cs │ └── XRitBaseHeader.cs ├── Properties │ ├── AssemblyInfo.cs │ └── LibInfo.cs ├── SQLite.cs ├── SQLiteAsync.cs ├── ShapeFiles │ ├── README.md │ ├── ShapeFiles.cs │ ├── ne_50m_admin_0_countries.dbf │ ├── ne_50m_admin_0_countries.prj │ ├── ne_50m_admin_0_countries.shp │ └── ne_50m_admin_0_countries.shx ├── Storage │ ├── ConfigurationManager.cs │ ├── DBConfig.cs │ ├── DBStatistics.cs │ ├── Database.cs │ └── StatisticsManager.cs ├── Tools │ ├── AEC.cs │ ├── CrashReport.cs │ ├── Decompress.cs │ ├── FileParser.cs │ ├── ImageHandler.cs │ ├── ImageTools.cs │ ├── LLTools.cs │ ├── MimeTypes.cs │ ├── Organizer.cs │ ├── Presets.cs │ └── TextHandler.cs ├── XRIT.csproj ├── build-pre.sh ├── build.sh ├── build │ ├── XRIT.nuspec.tpl │ └── build │ │ ├── OpenSatelliteProject.XRIT.targets │ │ └── x86 │ │ ├── COPYING-libaec │ │ ├── COPYING-satdecompress │ │ ├── aec.dl_ │ │ ├── satdecompress.dl_ │ │ ├── sqlite3.dl_ │ │ └── szip.dl_ ├── packages.config └── update-tpl-release.py ├── goesdump.sln ├── goesdump.userprefs ├── goesdump ├── .gitignore ├── GOES Dumper.csproj ├── GoesDecoder │ ├── Connector.cs │ └── Statistics.cs ├── HeadlessMain.cs ├── Icon.ico ├── Main.cs ├── Models │ ├── BaseModel.cs │ ├── ConfigEntryModel.cs │ ├── ConsoleModel.cs │ ├── ConstellationModel.cs │ ├── DirList.cs │ ├── ModelType.cs │ ├── ProgConfig.cs │ ├── StatisticsModel.cs │ └── XMLProgConfig.cs ├── PacketData │ └── NOAAProductId.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Tools.cs ├── WebManager │ ├── ConfigEntryInfo.cs │ ├── DHInfo.cs │ ├── DirectoryHandler.cs │ └── WSHandler.cs ├── icon.png └── packages.config ├── overlays └── goes13-fulldisk.jpg ├── screenshot.png ├── web ├── .gitignore ├── README.md ├── package.json ├── public │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── blank.gif │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── file.gif │ ├── folder.gif │ ├── index.html │ ├── manifest.json │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ └── ms-icon-70x70.png ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Components │ │ ├── BarElementRight.js │ │ ├── Constellation.js │ │ ├── Led.css │ │ └── TopBar.js │ ├── Controllers │ │ ├── Charts.js │ │ ├── Configuration.js │ │ ├── Console.js │ │ ├── Dashboard.js │ │ └── Explorer.js │ ├── OSP │ │ └── Connector.js │ ├── atom.svg │ ├── electron-starter.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── registerServiceWorker.js └── yarn.lock └── web_simple ├── .gitignore ├── README.md ├── index.html ├── package.json └── static ├── 2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2 ├── blank.gif ├── file.gif ├── folder.gif ├── leds.css ├── main.css ├── main.js └── material-icons.css /.gitignore: -------------------------------------------------------------------------------- 1 | packages/ 2 | .vs 3 | .idea 4 | -------------------------------------------------------------------------------- /LibraryTest/.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | obj/* 3 | Content/bin 4 | Content/obj 5 | -------------------------------------------------------------------------------- /LibraryTest/LibraryTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {7692605F-AC81-4688-A7D2-F8B5C4E0C397} 7 | Exe 8 | LibraryTest 9 | LibraryTest 10 | 1.3.0 11 | v4.5 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug 18 | 4 19 | 20 | 21 | false 22 | bin\Release 23 | 4 24 | 25 | 26 | 27 | 28 | 29 | ..\packages\DotSpatial.Mono.1.9\lib\net40-Client\DotSpatial.Mono.dll 30 | 31 | 32 | ..\packages\DotSpatial.Serialization.1.9\lib\net40-Client\DotSpatial.Serialization.dll 33 | 34 | 35 | ..\packages\DotSpatial.Topology.1.9\lib\net40-Client\DotSpatial.Topology.dll 36 | 37 | 38 | ..\packages\DotSpatial.Projections.1.9\lib\net40-Client\DotSpatial.Projections.dll 39 | 40 | 41 | ..\packages\DotSpatial.Data.1.9\lib\net40-Client\DotSpatial.Data.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {31BC62BD-1EE9-4B14-A931-19C572126A51} 52 | XRIT 53 | 54 | 55 | {E1B44542-24FF-409C-A2A3-237A00A8520D} 56 | GOES Dumper 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /LibraryTest/LibraryTest.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Project 5 | false 6 | true 7 | Mono 5.2.0 8 | 9 | -------------------------------------------------------------------------------- /LibraryTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("LibraryTest")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("lucas")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /LibraryTest/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GOES xRIT Dumper 2 | ========================= 3 | 4 | This program receives a TCP Stream from decoder and decodes the channel in realtime generating .lrit files. It also depends on **satdecompress** to decompress LritRice (see Decompressor project). 5 | 6 | With all **LRIT** files, you can use [xrit2pic](http://www.alblas.demon.nl/wsat/software/soft_msg.html). 7 | 8 | ![GOES Dump](screenshot.png) 9 | -------------------------------------------------------------------------------- /XRIT/.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | obj/* 3 | Content/bin 4 | Content/obj 5 | build/*.nupkg 6 | build/lib/* 7 | git-hash.txt 8 | git-log.txt 9 | build/XRIT-rc.nuspec 10 | build/XRIT.nuspec 11 | -------------------------------------------------------------------------------- /XRIT/Console/ConsoleMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenSatelliteProject { 5 | public enum ConsoleMessagePriority { 6 | INFO, 7 | WARN, 8 | ERROR, 9 | DEBUG 10 | } 11 | 12 | public class ConsoleMessage: ICloneable { 13 | 14 | public DateTime TimeStamp { get; set; } 15 | public string Message { get; set; } 16 | public ConsoleMessagePriority Priority { get; set; } 17 | public ConsoleMessage(ConsoleMessagePriority priority, string message) { 18 | TimeStamp = DateTime.Now; 19 | Message = message; 20 | Priority = priority; 21 | } 22 | 23 | public override string ToString() { 24 | return String.Format("{0}/{1,-5} {2}", TimeStamp.ToLongTimeString(), Priority.ToString(), Message); 25 | } 26 | 27 | #region ICloneable implementation 28 | 29 | public object Clone() { 30 | ConsoleMessage cm = new ConsoleMessage(this.Priority, this.Message); 31 | cm.TimeStamp = this.TimeStamp; 32 | return cm; 33 | } 34 | 35 | #endregion 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /XRIT/DCS/DCSHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace OpenSatelliteProject.DCS { 6 | public class DCSHeader { 7 | 8 | public string Address { get; set; } 9 | public DateTime DateTime { get; set; } 10 | public string Status { get; set; } 11 | public int Signal { get; set; } 12 | public int FrequencyOffset { get; set; } 13 | public string ModIndexNormal { get; set; } 14 | public string DataQualNominal { get; set; } 15 | public string Channel { get; set; } 16 | public string SourceCode { get; set; } 17 | 18 | public DCSHeader(string header) { 19 | try { 20 | Address = header.Substring(0, 8); 21 | ModIndexNormal = "" + header[25]; 22 | DataQualNominal = "" + header[26]; 23 | Channel = header.Substring(27, 4); 24 | SourceCode = header.Substring(31, 2); 25 | Status = "" + header[20]; 26 | 27 | int year = int.Parse(header.Substring(9, 2)); 28 | int dayOfYear = int.Parse(header.Substring(11, 3)); 29 | int hour = int.Parse(header.Substring(14, 2)); 30 | int min = int.Parse(header.Substring(16, 2)); 31 | int second = int.Parse(header.Substring(18, 2)); 32 | DateTime = new DateTime(2000 + year, 1, 1, hour, min, second); 33 | DateTime = DateTime.AddDays(dayOfYear); 34 | 35 | Signal = int.Parse(header.Substring(21, 2)); 36 | FrequencyOffset = int.Parse(header.Substring(23, 2)); 37 | } catch(Exception e) { 38 | Console.WriteLine("Invalid header: {0}", e); 39 | } 40 | } 41 | 42 | public DCSHeader(byte[] header) : this(Encoding.ASCII.GetString(header.Take(33).ToArray())) { 43 | 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /XRIT/DCS/DCSParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using OpenSatelliteProject.Tools; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace OpenSatelliteProject.DCS { 8 | public static class DCSParser { 9 | 10 | 11 | public static List parseDCS(string filename) { 12 | List headers = new List(); 13 | var header = FileParser.GetHeaderFromFile(filename); 14 | var dataOffset = header.PrimaryHeader.HeaderLength; 15 | int dataSize; 16 | byte[] fileData; 17 | 18 | using (var fs = File.OpenRead(filename)) { 19 | fs.Seek(dataOffset, SeekOrigin.Begin); 20 | dataSize = (int)(fs.Length - dataOffset); 21 | fileData = new byte[dataSize]; 22 | fs.Read(fileData, 0, dataSize); 23 | } 24 | 25 | //byte[] baseHeader = fileData.Take(64).ToArray(); 26 | fileData = fileData.Skip(64).ToArray(); 27 | 28 | List dcs = new List(); 29 | 30 | int lastPos = 0; 31 | int pos = 0; 32 | while (pos < fileData.Length - 3) { 33 | if (fileData[pos] == 0x02 && fileData[pos + 1] == 0x02 && fileData[pos + 2] == 0x18) { 34 | Console.WriteLine("Found segment at {0}", pos); 35 | byte[] segment = fileData.Skip(lastPos).Take(pos - lastPos - 3).ToArray(); 36 | dcs.Add(segment); 37 | pos += 3; 38 | lastPos = pos; 39 | } else { 40 | pos++; 41 | } 42 | } 43 | 44 | dcs.ForEach(a => { 45 | if (a.Length > 33) { 46 | DCSHeader h = new DCSHeader(a); 47 | headers.Add(h); 48 | } 49 | }); 50 | 51 | return headers; 52 | } 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /XRIT/EventMaster/EventMaster.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenSatelliteProject { 5 | /// 6 | /// An Global Event master to mimic Node.JS EventEmitter. 7 | /// 8 | public class EventMaster { 9 | 10 | public static EventMaster Master { get; private set; } 11 | 12 | static EventMaster() { 13 | Master = new EventMaster (); 14 | } 15 | 16 | readonly Dictionary handlers; 17 | 18 | EventMaster () { 19 | handlers = new Dictionary (); 20 | } 21 | 22 | /// 23 | /// Attaches a listener for the event described by parameter type. 24 | /// 25 | /// Event Type to listen 26 | /// Event Handler 27 | public static void On(string type, EMEventHandler handler) { 28 | EventMaster.Master._On (type, handler); 29 | } 30 | 31 | /// 32 | /// Post a event to everyone that is listening to. 33 | /// 34 | /// Event Type to listen 35 | /// Event Data 36 | public static void Post(string type, object data) { 37 | EventMaster.Master._Post (new EventMasterData(type, data)); 38 | } 39 | 40 | public static void Detach(string type, EMEventHandler handler) { 41 | EventMaster.Master._Detach (type, handler); 42 | } 43 | 44 | public void _On(string type, EMEventHandler handler) { 45 | lock (handlers) { 46 | if (!handlers.ContainsKey (type)) { 47 | handlers.Add (type, handler); 48 | } else { 49 | handlers [type] += handler; 50 | } 51 | } 52 | } 53 | 54 | public void _Detach(string type, EMEventHandler handler) { 55 | lock (handlers) { 56 | if (handlers.ContainsKey (type)) { 57 | Delegate.Remove(handlers [type], handler); 58 | } 59 | } 60 | } 61 | 62 | public void _Post(EventMasterData data) { 63 | lock (handlers) { 64 | if (handlers.ContainsKey (data.Type)) { 65 | handlers [data.Type] (data); 66 | } 67 | } 68 | } 69 | 70 | } 71 | public delegate void EMEventHandler(EventMasterData data); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /XRIT/EventMaster/EventMasterData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class EventMasterData { 5 | public string Type { get; private set; } 6 | public object Data { get; private set; } 7 | 8 | public EventMasterData(string type) { 9 | Type = type; 10 | } 11 | 12 | public EventMasterData(string type, object data) { 13 | Type = type; 14 | Data = data; 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /XRIT/EventMaster/Events/ConfigChangeEventData.cs: -------------------------------------------------------------------------------- 1 | namespace OpenSatelliteProject { 2 | public class ConfigChangeEventData { 3 | public string Name { get; set; } 4 | public string Value { get; set; } 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /XRIT/EventMaster/Events/EventTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public static class EventTypes { 5 | public const string ConfigChangeEvent = "configChange"; 6 | public const string FrameEvent = "frameEvent"; 7 | public const string NewFileEvent = "newFile"; 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /XRIT/EventMaster/Events/FrameEventData.cs: -------------------------------------------------------------------------------- 1 | namespace OpenSatelliteProject { 2 | public class FrameEventData { 3 | public int ChannelID { get; set; } 4 | public int PacketNumber { get; set; } 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /XRIT/EventMaster/Events/NewFileReceivedEventData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | 5 | namespace OpenSatelliteProject { 6 | public class NewFileReceivedEventData { 7 | public string Name { get; set; } 8 | public string Path { get; set; } 9 | public Dictionary Metadata { get; set; } 10 | 11 | public NewFileReceivedEventData() { 12 | Name = ""; 13 | Path = ""; 14 | Metadata = new Dictionary (); 15 | } 16 | 17 | public override string ToString() { 18 | string ret = $"Name: {Name} | Path: {Path}: \nMetadata:\n"; 19 | Metadata.Keys.ToList().ForEach (k => ret += $"\t{k}: {Metadata[k]}\n"); 20 | return ret; 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /XRIT/GOES/DemuxManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using OpenSatelliteProject.Tools; 6 | using System.Threading; 7 | 8 | namespace OpenSatelliteProject { 9 | public class DemuxManager { 10 | readonly static int FILL_VCID = 63; 11 | readonly Dictionary demuxers; 12 | bool recordFile = false; 13 | string fileName; 14 | FileStream fStream; 15 | readonly Mutex recordMutex; 16 | readonly Mutex resetMutex; 17 | Dictionary productsReceived; 18 | 19 | public int CRCFails { get; set; } 20 | public int Bugs { get; set; } 21 | public int Packets { get; set; } 22 | public int LengthFails { get; set; } 23 | public long FrameLoss { get; set; } 24 | public uint FrameJumps { get; set; } 25 | 26 | public Dictionary ProductsReceived { 27 | get { 28 | Dictionary o = new Dictionary(); 29 | lock (productsReceived) { 30 | foreach (var k in productsReceived) { 31 | o[k.Key] = k.Value; 32 | } 33 | } 34 | return o; 35 | } 36 | } 37 | 38 | public bool RecordToFile { 39 | get { return recordFile; } 40 | set { 41 | try { 42 | recordMutex.WaitOne(); 43 | recordFile = value; 44 | if (value && fStream == null) { 45 | fileName = string.Format("demuxdump-{0}.bin", LLTools.Timestamp()); 46 | UIConsole.Log($"Starting dump on file {fileName}"); 47 | fStream = File.OpenWrite(fileName); 48 | } else if (!value && fStream != null) { 49 | UIConsole.Log($"Closing dump on file {fileName}"); 50 | try { 51 | fStream.Close(); 52 | fStream = null; 53 | } catch (Exception) { 54 | // Ignore 55 | } 56 | } 57 | recordMutex.ReleaseMutex(); 58 | } catch (Exception e) { 59 | CrashReport.Report (e); 60 | } 61 | } 62 | } 63 | 64 | public DemuxManager() { 65 | try { 66 | demuxers = new Dictionary(); 67 | productsReceived = new Dictionary(); 68 | CRCFails = 0; 69 | Bugs = 0; 70 | Packets = 0; 71 | LengthFails = 0; 72 | FrameLoss = 0; 73 | FrameJumps = 0; 74 | recordMutex = new Mutex(); 75 | resetMutex = new Mutex(); 76 | if (RecordToFile) { 77 | fileName = string.Format("demuxdump-{0}.bin", LLTools.Timestamp()); 78 | UIConsole.Log(string.Format("Demux Dump filename: {0}", Path.GetFileName(fileName))); 79 | fStream = File.OpenWrite(fileName); 80 | } 81 | } catch(Exception e) { 82 | CrashReport.Report (e); 83 | throw e; 84 | } 85 | } 86 | 87 | ~DemuxManager() { 88 | RecordToFile = false; 89 | } 90 | 91 | public void incProductCount(int productId) { 92 | lock (productsReceived) { 93 | if (!productsReceived.ContainsKey(productId)) { 94 | productsReceived.Add(productId, 1); 95 | } else { 96 | productsReceived[productId]++; 97 | } 98 | } 99 | } 100 | 101 | /// 102 | /// Reset this instance. 103 | /// 104 | public void reset() { 105 | try { 106 | resetMutex.WaitOne(); 107 | CRCFails = 0; 108 | Bugs = 0; 109 | Packets = 0; 110 | LengthFails = 0; 111 | FrameLoss = 0; 112 | FrameJumps = 0; 113 | productsReceived = new Dictionary(); 114 | lock (demuxers) { 115 | var ks = demuxers.Keys.ToList(); 116 | foreach (var k in ks) { 117 | demuxers[k] = new Demuxer(this); 118 | } 119 | } 120 | bool lastState = RecordToFile; 121 | RecordToFile = false; 122 | RecordToFile = lastState; 123 | resetMutex.ReleaseMutex(); 124 | } catch (Exception e) { 125 | CrashReport.Report (e); 126 | throw e; 127 | } 128 | } 129 | 130 | public void parseBytes(byte[] data) { 131 | try { 132 | int scid = ((data[0] & 0x3F) << 2) | ((data[1] & 0xC0) >> 6); 133 | int vcid = (data[1] & 0x3F); 134 | int vcnt = (data[2] << 16 | data[3] << 8 | data[4]); 135 | 136 | // UIConsole.Log($"Satellite ID: {scid}"); 137 | 138 | EventMaster.Post(EventTypes.FrameEvent, new FrameEventData { ChannelID = vcid, PacketNumber = vcnt }); 139 | 140 | if (vcid != FILL_VCID) { 141 | resetMutex.WaitOne(); 142 | lock (demuxers) { 143 | if (!demuxers.ContainsKey(vcid)) { 144 | UIConsole.Log($"I don't have a demuxer for VCID {vcid}. Creating..."); 145 | demuxers.Add(vcid, new Demuxer(this)); 146 | } 147 | } 148 | recordMutex.WaitOne(); 149 | if (RecordToFile) { 150 | try { 151 | fStream.Write(data, 0, data.Length); 152 | } catch (Exception e) { 153 | UIConsole.Error($"Error writting demuxdump file: {e}"); 154 | } 155 | } 156 | recordMutex.ReleaseMutex(); 157 | demuxers[vcid].ParseBytes(data); 158 | resetMutex.ReleaseMutex(); 159 | } 160 | } catch (Exception e) { 161 | CrashReport.Report (e); 162 | throw e; 163 | } 164 | } 165 | } 166 | } 167 | 168 | -------------------------------------------------------------------------------- /XRIT/GOES/EMWIN.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using OpenSatelliteProject.PacketData; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.IO.Compression; 7 | using System.Text; 8 | 9 | namespace OpenSatelliteProject { 10 | public class EMWIN { 11 | 12 | public static EMWIN Ingestor; 13 | 14 | static EMWIN() { 15 | Ingestor = new EMWIN(); 16 | } 17 | 18 | private static readonly int MAX_FRAME_SIZE = 1116; 19 | private static readonly string FILLFILENAME = "PFFILLFILE.TXT"; 20 | private byte[] buffer; 21 | private Dictionary files; 22 | 23 | private EMWIN() { 24 | buffer = new byte[0]; 25 | files = new Dictionary(); 26 | } 27 | 28 | public void Process(byte[] inData) { 29 | buffer = buffer.Concat(inData).ToArray(); 30 | var pos = FindSyncMarker(buffer); 31 | if (pos == -1) { 32 | if (buffer.Length > MAX_FRAME_SIZE * 3) { 33 | UIConsole.Warn($"EMWIN Buffer grown beyond {MAX_FRAME_SIZE * 3}! This should happen. Clearing buffer."); 34 | buffer = new byte[0]; 35 | } 36 | return; 37 | } 38 | 39 | var data = buffer.Skip(pos + 6).Take(MAX_FRAME_SIZE - 6).ToArray(); // 12 for the syncMark 40 | 41 | if (data.Length != MAX_FRAME_SIZE - 6) { 42 | // Not Enough Data 43 | return; 44 | } 45 | 46 | buffer = buffer.Skip(pos + MAX_FRAME_SIZE).ToArray(); 47 | if (data.Length > 0) { 48 | var headerData = Encoding.GetEncoding("ISO-8859-1").GetString(data.Take(80).ToArray()); 49 | data = data.Skip(80).ToArray(); 50 | 51 | try { 52 | var header = new EMWINHeader(headerData); 53 | if (header.Filename.Equals(FILLFILENAME)) { 54 | return; 55 | } 56 | //UIConsole.GlobalConsole.Log(string.Format("Received {0}/{1} of {2}", header.PartNumber, header.PartTotal, header.Filename)); 57 | if (header.PartNumber == 1) { 58 | if (files.ContainsKey(header.Filename)) { 59 | UIConsole.Warn($"Files already has a key for file {header.Filename}"); 60 | } else { 61 | string newfilename = DateTime.Now.ToString("yyyyMMddHHmmssffff") + header.Filename; 62 | files.Add(header.Filename, new EmwinFile()); 63 | files[header.Filename].Parts = header.PartTotal; 64 | files[header.Filename].Received = 0; 65 | files[header.Filename].Output = Path.Combine("channels", Path.Combine("tmp", newfilename)); 66 | } 67 | } 68 | 69 | if (!files.ContainsKey(header.Filename)) { 70 | //UIConsole.GlobalConsole.Warn(string.Format("(EMWIN) Received incomplete part for {0}", header.Filename)); 71 | return; 72 | } else if (files[header.Filename].Received + 1 != header.PartNumber) { 73 | //UIConsole.GlobalConsole.Error(string.Format("(EMWIN) Missed {0} frames for file {1}", header.PartNumber - files[header.Filename].Received - 1, header.Filename)); 74 | files.Remove(header.Filename); 75 | return; 76 | } else { 77 | string dir = Path.GetDirectoryName(files[header.Filename].Output); 78 | if (!Directory.Exists(dir)) { 79 | Directory.CreateDirectory(dir); 80 | } 81 | 82 | var f = File.Open(files[header.Filename].Output, header.PartNumber == 1 ? FileMode.Create : FileMode.Append); 83 | f.Write(data, 0, data.Length); 84 | f.Close(); 85 | files[header.Filename].Received += 1; 86 | } 87 | 88 | if (header.PartNumber == header.PartTotal && files.ContainsKey(header.Filename)) { 89 | string output = files[header.Filename].Output; 90 | string basedir = new DirectoryInfo(Path.GetDirectoryName(output)).Parent.FullName; 91 | string newdir = Path.Combine(basedir, "EMWIN"); 92 | 93 | if (!Directory.Exists(newdir)) { 94 | Directory.CreateDirectory(newdir); 95 | } 96 | 97 | string fname = Path.Combine(newdir, header.Filename); 98 | if (File.Exists(fname)) { 99 | fname = DateTime.Now.ToString("yyyyMMddHHmmssffff") + "-" + header.Filename; 100 | fname = Path.Combine(newdir, fname); 101 | } 102 | File.Move(files[header.Filename].Output, fname); 103 | UIConsole.Log(string.Format("New EMWIN ({0})", header.Filename)); 104 | files.Remove(header.Filename); 105 | if (fname.Contains(".ZIS")) { 106 | PacketManager.ExtractZipFile(fname); 107 | } 108 | } 109 | } catch (Exception e) { 110 | UIConsole.Error($"(EMWIN) Error: {e.Message}"); 111 | } 112 | } 113 | } 114 | 115 | private static int FindSyncMarker(byte[] data) { 116 | // The sync marker is 6 null bytes. We check for 6 null and a '/' 117 | // Because sometimes there is null bytes in the middle of a packet. 118 | int searchSize = data.Length - 7; 119 | int pos = -1; 120 | 121 | for (int i = 0; i < searchSize; i++) { 122 | bool t = true; 123 | for (int z = 0; z < 7; z++) { 124 | if (z == 6) { 125 | if (data[i + z] != '/') { 126 | t = false; 127 | break; 128 | } 129 | } else { 130 | if (data[i + z] != '\x00') { 131 | t = false; 132 | break; 133 | } 134 | } 135 | } 136 | 137 | if (t) { 138 | pos = i; 139 | break; 140 | } 141 | } 142 | 143 | return pos; 144 | } 145 | } 146 | } 147 | 148 | -------------------------------------------------------------------------------- /XRIT/GOES/MultiImageManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | 6 | namespace OpenSatelliteProject.GOES { 7 | public class MultiImageManager { 8 | private readonly List imageManagers; 9 | private readonly bool multiThread; 10 | private bool running; 11 | private Thread imageThread; 12 | 13 | public MultiImageManager(IEnumerable folders, bool MultiThreaded = true) { 14 | this.multiThread = MultiThreaded; 15 | imageManagers = folders.Select(folder => new ImageManager(folder)).ToList(); 16 | } 17 | 18 | 19 | public void Start() { 20 | if (running) return; 21 | if (multiThread) { 22 | UIConsole.Log("Starting Multi-Image Manager in Multi Thread mode."); 23 | imageManagers.ForEach(im => im.Start()); 24 | } else { 25 | UIConsole.Log("Starting Multi-Image Manager in Single Thread mode."); 26 | imageThread = new Thread(ThreadLoop) { 27 | IsBackground = true, 28 | Priority = ThreadPriority.BelowNormal 29 | }; 30 | imageThread.Start(); 31 | } 32 | 33 | running = true; 34 | } 35 | 36 | public void InitMapDrawer() { 37 | imageManagers.ForEach(im => im.InitMapDrawer()); 38 | } 39 | 40 | public void InitMapDrawer(string filename) { 41 | imageManagers.ForEach(im => im.InitMapDrawer(filename)); 42 | } 43 | 44 | public void Stop() { 45 | if (!running) return; 46 | UIConsole.Log("Stopping Multi-Image Manager."); 47 | if (multiThread) { 48 | imageManagers.ForEach(im => im.Stop()); 49 | } else { 50 | running = false; 51 | imageThread?.Join(); 52 | imageThread = null; 53 | } 54 | } 55 | 56 | private static void ManageImageManager(ImageManager im) { 57 | try { 58 | UIConsole.Debug($"Processing folder {im.Folder}"); 59 | im.RunningSingleThread = true; 60 | im.SingleThreadRun(); 61 | Thread.Sleep(200); 62 | } catch (Exception e) { 63 | UIConsole.Error($"Error processing image manager single thread: {e}"); 64 | CrashReport.Report(e); 65 | throw; 66 | } 67 | } 68 | 69 | private void ThreadLoop() { 70 | UIConsole.Log("MultiImage Thread running."); 71 | while (running) { 72 | imageManagers.ForEach(ManageImageManager); 73 | Thread.Sleep(2); 74 | } 75 | UIConsole.Log("MultiImage Thread stopped."); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /XRIT/Geo/GeoConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.Geo { 4 | /// 5 | /// Class to convert Pixels to LatLon or the inverse using LRIT Geolocation Parameters 6 | /// 7 | public class GeoConverter { 8 | private readonly int coff; 9 | private readonly int loff; 10 | private readonly float cfac; 11 | private readonly float lfac; 12 | private readonly float satelliteLongitude; 13 | private float aspectRatio; 14 | private bool fixAspect; 15 | private int cropLeft; 16 | 17 | public int ColumnOffset { get { return coff; } } 18 | public int LineOffset { get { return loff; } } 19 | public int CropLeft { get { return cropLeft; } } 20 | 21 | /// 22 | /// Maximum Visible Latitude 23 | /// 24 | /// The max latitude. 25 | public float MaxLatitude { 26 | get { 27 | return 79; 28 | } 29 | } 30 | 31 | /// 32 | /// Minimum Visible Latitude 33 | /// 34 | /// The minimum latitude. 35 | public float MinLatitude { 36 | get { 37 | return -79; 38 | } 39 | } 40 | 41 | /// 42 | /// Maximum visible Longitude 43 | /// 44 | /// The max longitude. 45 | public float MaxLongitude { 46 | get { 47 | return satelliteLongitude + 79; 48 | } 49 | } 50 | 51 | /// 52 | /// Minimum visible latitude 53 | /// 54 | /// The minimum longitude. 55 | public float MinLongitude { 56 | get { 57 | return satelliteLongitude - 79; 58 | } 59 | } 60 | 61 | /// 62 | /// Coverage of the view in Latitude Degrees 63 | /// 64 | /// The latitude coverage. 65 | public float LatitudeCoverage { 66 | get { 67 | return MaxLatitude - MinLatitude; 68 | } 69 | } 70 | 71 | /// 72 | /// Coverage of the view in Longitude Degrees 73 | /// 74 | /// The latitude coverage. 75 | public float LongitudeCoverage { 76 | get { 77 | return MaxLongitude - MinLongitude; 78 | } 79 | } 80 | 81 | /// 82 | /// Longitude Trim parameter for removing artifacts on Reprojection (in degrees) 83 | /// 84 | /// The trim longitude. 85 | public float TrimLongitude { 86 | get { 87 | return 16; 88 | } 89 | } 90 | 91 | 92 | /// 93 | /// Latitude Trim parameter for removing artifacts on Reprojection (in degrees) 94 | /// 95 | /// The trim longitude. 96 | public float TrimLatitude { 97 | get { 98 | return 16; 99 | } 100 | } 101 | 102 | /// 103 | /// Initializes a new instance of the class. 104 | /// 105 | /// Satellite longitude. 106 | /// Column Offset 107 | /// Line Offset 108 | /// Column Scaling Factor 109 | /// Line Scaling Factor 110 | /// Fix Aspect Ratio Cut 111 | /// Image Width 112 | public GeoConverter(float satelliteLongitude, int coff, int loff, float cfac, float lfac, bool fixAspect=false, int imageWidth = 0) { 113 | this.satelliteLongitude = satelliteLongitude; 114 | this.coff = coff; 115 | this.loff = loff; 116 | this.cfac = cfac; 117 | this.lfac = lfac; 118 | this.aspectRatio = cfac / lfac; 119 | this.fixAspect = fixAspect; 120 | this.cropLeft = coff - Math.Min(imageWidth - coff, coff); 121 | } 122 | 123 | /// 124 | /// Converts Latitude/Longitude to Pixel X/Y 125 | /// 126 | /// Latitude in Degrees 127 | /// Longitude in Degrees 128 | public Tuple latlon2xy(float lat, float lon) { 129 | var xy = GeoTools.lonlat2xy(satelliteLongitude, GeoTools.deg2rad(lon), GeoTools.deg2rad(lat), coff, cfac, loff, lfac); 130 | if (fixAspect) { 131 | xy = new Tuple(xy.Item1, (int) (xy.Item2 * aspectRatio)); 132 | } 133 | 134 | return xy; 135 | } 136 | 137 | public Tuple latlon2xyf(float lat, float lon) { 138 | var xy = GeoTools.lonlat2xyf(satelliteLongitude, GeoTools.deg2rad(lon), GeoTools.deg2rad(lat), coff, cfac, loff, lfac); 139 | if (fixAspect) { 140 | xy = new Tuple(xy.Item1, xy.Item2 * aspectRatio); 141 | } 142 | 143 | return xy; 144 | } 145 | 146 | /// 147 | /// Converts Pixel X/Y to Latitude/Longitude 148 | /// 149 | /// The x coordinate. 150 | /// The y coordinate. 151 | public Tuple xy2latlon(int x, int y) { 152 | var radCoord = GeoTools.xy2lonlat(satelliteLongitude, x, y, coff, cfac, loff, lfac); 153 | return new Tuple(GeoTools.rad2deg(radCoord.Item2), GeoTools.rad2deg(radCoord.Item1)); 154 | } 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /XRIT/Geo/GeoTools.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.Geo { 4 | /// 5 | /// Geographic Conversion Tools 6 | /// Based on: http://www.cgms-info.org/documents/pdf_cgms_03.pdf 7 | /// 8 | public static class GeoTools { 9 | 10 | public static readonly float MAXLON = GeoTools.deg2rad(75); 11 | public static readonly float MINLON = GeoTools.deg2rad(-75); 12 | public static readonly float MAXLAT = GeoTools.deg2rad(79); 13 | public static readonly float MINLAT = GeoTools.deg2rad(-79); 14 | 15 | public static readonly float radiusPoles = 6356.7523f; 16 | public static readonly float radiusEquator = 6378.1370f; 17 | public static readonly float vehicleDistance = 42142.5833f; 18 | 19 | public static float deg2rad(float deg) { 20 | return (float) (deg * Math.PI / 180); 21 | } 22 | 23 | public static float rad2deg(float rad) { 24 | return (float) (rad * 180 / Math.PI); 25 | } 26 | 27 | /// 28 | /// Converts Latitude/Longitude to Pixel X/Y on image 29 | /// 30 | /// Satellite Longitude 31 | /// Longitude in Radians 32 | /// Latitude in Radians 33 | /// Column Offset 34 | /// Column Scaling Factor 35 | /// Line Offset 36 | /// Line Scaling Factor 37 | public static Tuple lonlat2xy(float satLongitude, float lon, float lat, int coff, float cfac, int loff, float lfac) { 38 | var sub_lon = deg2rad(satLongitude); 39 | var rep = (radiusPoles * radiusPoles) / (radiusEquator * radiusEquator); 40 | lon -= sub_lon; 41 | 42 | lon = Math.Min(Math.Max(lon, MINLON), MAXLON); 43 | lat = Math.Min(Math.Max(lat, MINLAT), MAXLAT); 44 | 45 | var psi = Math.Atan(rep * Math.Tan(lat)); 46 | var re = radiusPoles / (Math.Sqrt( 1 - ( 1 - rep) * Math.Cos(psi) * Math.Cos(psi))); 47 | var r1 = vehicleDistance - re * Math.Cos(psi) * Math.Cos(lon); 48 | var r2 = -1 * re * Math.Cos(psi) * Math.Sin(lon); 49 | var r3 = re * Math.Sin(psi); 50 | 51 | var rn = Math.Sqrt ( r1 * r1 + r2 * r2 + r3 * r3 ); 52 | var x = Math.Atan(-1 * r2 / r1); 53 | var y = Math.Asin(-1 * r3 / rn); 54 | x = rad2deg((float)x); 55 | y = rad2deg((float)y); 56 | 57 | var c = coff + (int)(x * (float)(cfac) / 0x10000); 58 | var l = loff + (int)(y * (float)(lfac) / 0x10000); 59 | 60 | return new Tuple(c, l); 61 | } 62 | 63 | public static Tuple lonlat2xyf(float satLongitude, float lon, float lat, int coff, float cfac, int loff, float lfac) { 64 | var sub_lon = deg2rad(satLongitude); 65 | var rep = (radiusPoles * radiusPoles) / (radiusEquator * radiusEquator); 66 | lon -= sub_lon; 67 | 68 | lon = Math.Min(Math.Max(lon, MINLON), MAXLON); 69 | lat = Math.Min(Math.Max(lat, MINLAT), MAXLAT); 70 | 71 | var psi = Math.Atan(rep * Math.Tan(lat)); 72 | var re = radiusPoles / (Math.Sqrt( 1 - ( 1 - rep) * Math.Cos(psi) * Math.Cos(psi))); 73 | var r1 = vehicleDistance - re * Math.Cos(psi) * Math.Cos(lon); 74 | var r2 = -1 * re * Math.Cos(psi) * Math.Sin(lon); 75 | var r3 = re * Math.Sin(psi); 76 | 77 | var rn = Math.Sqrt ( r1 * r1 + r2 * r2 + r3 * r3 ); 78 | var x = Math.Atan(-1 * r2 / r1); 79 | var y = Math.Asin(-1 * r3 / rn); 80 | x = rad2deg((float)x); 81 | y = rad2deg((float)y); 82 | 83 | var c = coff + (x * (float)(cfac) / 0x10000); 84 | var l = loff + (y * (float)(lfac) / 0x10000); 85 | 86 | return new Tuple((float)c, (float)l); 87 | } 88 | 89 | /// 90 | /// Converts Pixel X/Y to Latitude / Longitude 91 | /// 92 | /// Satellite Longitude 93 | /// Column (X) 94 | /// Line (Y) 95 | /// Column Offset 96 | /// Column Scaling Factor 97 | /// Line Offset 98 | /// Line Scaling Factor 99 | public static Tuple xy2lonlat(float satelliteLon, int c, int l, int coff, float cfac, int loff, float lfac) { 100 | var q2 = (radiusEquator * radiusEquator) / (radiusPoles * radiusPoles); 101 | var d2 = vehicleDistance * vehicleDistance - radiusEquator * radiusEquator; 102 | var sub_lon = deg2rad(satelliteLon); 103 | 104 | var x = (c - coff) * 0x10000 / cfac; 105 | var y = (l - loff) * 0x10000 / lfac; 106 | 107 | var cosx = Math.Cos(deg2rad(x)); 108 | var cosy = Math.Cos(deg2rad(y)); 109 | var sinx = Math.Sin(deg2rad(x)); 110 | var siny = Math.Sin(deg2rad(y)); 111 | 112 | var a1 = vehicleDistance * vehicleDistance * cosx * cosx * cosy * cosy; 113 | var a2 = (cosy * cosy + q2 * siny * siny) * d2; 114 | if (a1 < a2) { 115 | return new Tuple(0, 0); 116 | } 117 | 118 | var sd = Math.Sqrt(a1 - a2); 119 | 120 | var sn = ( vehicleDistance * cosx * cosy - sd ) / (cosy * cosy + q2 * siny * siny); 121 | var s1 = vehicleDistance - sn * cosx * cosy; 122 | var s2 = sn * sinx * cosy; 123 | var s3 = -1 * sn * siny; 124 | var sxy = Math.Sqrt(s1 * s1 + s2 * s2); 125 | var lat = 0f; 126 | var lon = 0f; 127 | 128 | if (s1 == 0) { 129 | lon = s2 > 0 ? deg2rad(90) + sub_lon : deg2rad(-90) + sub_lon; 130 | } else { 131 | lon = (float) Math.Atan(s2 / s1) + sub_lon; 132 | } 133 | 134 | if (sxy == 0) { 135 | lat = q2 * s3 > 0 ? deg2rad(90) : deg2rad(-90); 136 | } else { 137 | lat = (float) Math.Atan(q2 * s3 / sxy); 138 | } 139 | 140 | return new Tuple(lon, lat); 141 | } 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /XRIT/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Lucas Teske 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | For binaries Releases please check license for libaec and satdecompress at: 10 | https://github.com/opensatelliteproject/decompressor 11 | https://github.com/opensatelliteproject/libaec 12 | -------------------------------------------------------------------------------- /XRIT/LUT/falsecolor-original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/LUT/falsecolor-original.png -------------------------------------------------------------------------------- /XRIT/LUT/falsecolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/LUT/falsecolor.png -------------------------------------------------------------------------------- /XRIT/Log/Facility.cs: -------------------------------------------------------------------------------- 1 | namespace OpenSatelliteProject.Log { 2 | public enum Facility { 3 | Kernel=0, 4 | User=1, 5 | Mail=2, 6 | Daemon=3, 7 | Auth=4, 8 | Syslog=5, 9 | Lpr=6, 10 | News=7, 11 | UUCP=8, 12 | Cron=9, 13 | Local0=16, 14 | Local1=17, 15 | Local2=18, 16 | Local3=19, 17 | Local4=20, 18 | Local5=21, 19 | Local6=22, 20 | Local7=23 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /XRIT/Log/Level.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.Log { 4 | public enum Level { 5 | Emergency= 0, 6 | Alert=1, 7 | Critical=2, 8 | Error=3, 9 | Warning=4, 10 | Notice=5, 11 | Information=6, 12 | Debug=7, 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /XRIT/Log/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.Log { 4 | 5 | public class Message { 6 | public string Facility { get; set; } 7 | 8 | public int Level { get; set; } 9 | 10 | public string Text { get; set; } 11 | 12 | public string Name { get; set; } 13 | 14 | public Message() { 15 | Name = "OpenSatelliteProject"; 16 | } 17 | 18 | public Message(string facility, int level, string text) { 19 | this.Facility = facility; 20 | this.Level = level; 21 | this.Text = text; 22 | this.Name = "OpenSatelliteProject"; 23 | } 24 | 25 | public Message(string facility, Level level, string text) { 26 | this.Facility = facility; 27 | this.Level = (int)level; 28 | this.Text = text; 29 | this.Name = "OpenSatelliteProject"; 30 | } 31 | 32 | public Message(string facility, int level, string name, string text) { 33 | this.Facility = facility; 34 | this.Level = level; 35 | this.Text = text; 36 | this.Name = name; 37 | } 38 | 39 | public Message(string facility, Level level, string name, string text) { 40 | this.Facility = facility; 41 | this.Level = (int)level; 42 | this.Text = text; 43 | this.Name = name; 44 | } 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /XRIT/Log/SyslogClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | using System.Collections.Generic; 5 | 6 | namespace OpenSatelliteProject.Log { 7 | public class SyslogClient { 8 | private static IPHostEntry ipHostInfo; 9 | private static IPAddress ipAddress; 10 | private static IPEndPoint ipLocalEndPoint; 11 | private static UdpClient udpClient; 12 | private static Dictionary FacilityMap; 13 | public static int Port { get; set; } 14 | public static string SysLogServerIp { get; set; } 15 | public static bool IsActive { get; set; } 16 | 17 | static SyslogClient() { 18 | if (!Tools.LLTools.IsLinux) { 19 | Console.WriteLine("Syslog only works on Linux"); 20 | return; 21 | } 22 | 23 | ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); 24 | ipAddress = ipHostInfo.AddressList[0]; 25 | ipLocalEndPoint = new IPEndPoint(ipAddress, 0); 26 | udpClient= new UdpClient(ipLocalEndPoint); 27 | Port = 514; 28 | InitFacilityMap(); 29 | } 30 | 31 | public void Close() { 32 | if (IsActive) { 33 | udpClient.Close(); 34 | IsActive = false; 35 | } 36 | } 37 | 38 | public static void Send(string syslogFacility, Level level, string message) { 39 | SyslogClient.Send(new Message(syslogFacility, level, message)); 40 | } 41 | 42 | public static void Send(Message message) { 43 | if (Tools.LLTools.IsLinux) { 44 | if (!IsActive) { 45 | udpClient.Connect(SysLogServerIp, Port); 46 | IsActive = true; 47 | } 48 | 49 | if (IsActive) { 50 | int priority = (int)FacilityMap[message.Facility] * 8 + message.Level; 51 | string msg = System.String.Format("<{0}>{1} {2} {3}", priority, DateTime.Now.ToString("MMM dd HH:mm:ss"), "XRIT", message.Text); 52 | byte[] bytes = System.Text.Encoding.ASCII.GetBytes(msg); 53 | udpClient.Send(bytes, bytes.Length); 54 | } 55 | } 56 | } 57 | 58 | private static void InitFacilityMap() { 59 | FacilityMap = new Dictionary(); 60 | 61 | FacilityMap["LOG_KERNEL"] = Facility.Kernel; 62 | FacilityMap["LOG_USER"] = Facility.User; 63 | FacilityMap["LOG_MAIL"] = Facility.Mail; 64 | FacilityMap["LOG_DAEMON"] = Facility.Daemon; 65 | FacilityMap["LOG_AUTH"] = Facility.Auth; 66 | FacilityMap["LOG_SYSLOG"] = Facility.Syslog; 67 | FacilityMap["LOG_LPR"] = Facility.Lpr; 68 | FacilityMap["LOG_NEWS"] = Facility.News; 69 | FacilityMap["LOG_UUCP"] = Facility.UUCP; 70 | FacilityMap["LOG_CRON"] = Facility.Cron; 71 | FacilityMap["LOG_LOCAL0"] = Facility.Local0; 72 | FacilityMap["LOG_LOCAL1"] = Facility.Local1; 73 | FacilityMap["LOG_LOCAL2"] = Facility.Local2; 74 | FacilityMap["LOG_LOCAL3"] = Facility.Local3; 75 | FacilityMap["LOG_LOCAL4"] = Facility.Local4; 76 | FacilityMap["LOG_LOCAL5"] = Facility.Local5; 77 | FacilityMap["LOG_LOCAL6"] = Facility.Local6; 78 | FacilityMap["LOG_LOCAL7"] = Facility.Local7; 79 | } 80 | 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /XRIT/Models/ConfigDescription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class ConfigDescription: Attribute { 5 | public string Description; 6 | public object Default; 7 | 8 | public ConfigDescription (string description) : this(description, null) { 9 | 10 | } 11 | 12 | public ConfigDescription (string description, object def) { 13 | this.Description = description; 14 | this.Default = def; 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /XRIT/Models/CrashData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Script.Serialization; 3 | using OpenSatelliteProject.Tools; 4 | using System.Diagnostics; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Newtonsoft.Json; 8 | 9 | namespace OpenSatelliteProject { 10 | public class CrashData { 11 | 12 | public string ID { get; private set; } 13 | public CrashData InnerCrashData { get; private set; } 14 | public string StackTrace { get; private set; } 15 | public string Source { get; private set; } 16 | public int ExceptionCode { get; private set; } 17 | public string ExceptionName { get; private set; } 18 | public string Date { get; private set; } 19 | public string Time { get; private set; } 20 | public long Timestamp { get; private set; } 21 | public string XRITVersion { get; private set; } 22 | public string XRITCommit { get; private set; } 23 | public List StackTraceData { get; private set; } 24 | public string Username { get; private set; } 25 | 26 | public string Filename { 27 | get { 28 | return (StackTraceData.Count > 0) ? StackTraceData [0].Filename : "No File"; 29 | } 30 | } 31 | 32 | public int Line { 33 | get { 34 | return (StackTraceData.Count > 0) ? StackTraceData [0].Line : 0; 35 | } 36 | } 37 | 38 | public CrashData(Exception e) : this(e, "Not Defined") {} 39 | 40 | public CrashData (Exception e, string Username) { 41 | this.Username = Username; 42 | StackTrace trace = new StackTrace(e, true); 43 | StackTraceData = trace.GetFrames ().Select ((sf) => { 44 | return new StackTraceData { 45 | Line = sf.GetFileLineNumber (), 46 | Column = sf.GetFileColumnNumber (), 47 | Filename = sf.GetFileName (), 48 | ClassName = sf.GetMethod ().ReflectedType.FullName, 49 | Method = sf.GetMethod ().Name, 50 | }; 51 | }).ToList (); 52 | 53 | ID = Guid.NewGuid ().ToString (); 54 | ExceptionCode = e.HResult; 55 | Source = e.Source; 56 | StackTrace = e.StackTrace; 57 | ExceptionName = e.GetType ().Name; 58 | Timestamp = LLTools.TimestampMS (); 59 | Date = DateTime.Now.ToLongDateString (); 60 | Time = DateTime.Now.ToLongTimeString (); 61 | XRITVersion = LibInfo.Version; 62 | XRITCommit = LibInfo.CommitID; 63 | if (e.InnerException != null) { 64 | InnerCrashData = new CrashData (e); 65 | } 66 | } 67 | 68 | public string ToJSON() { 69 | try { 70 | return JsonConvert.SerializeObject(this, Formatting.Indented); 71 | } catch (Exception e) { 72 | Console.WriteLine ($"FATAL: Cannot serialize Crash Data: {e}"); 73 | } 74 | return "error"; 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /XRIT/Models/GroupData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using OpenSatelliteProject.Tools; 5 | 6 | namespace OpenSatelliteProject { 7 | public class GroupData { 8 | private const int GROUP_DATA_TIMEOUT = 3600; // 1h 9 | private const int DATA_TIMEOUT = 15 * 60; // 15 minutes 10 | private const int MIN_DATA_MARK = 13 * 60; // 13 minutes 11 | 12 | public string SatelliteName { get; set; } 13 | public string RegionName { get; set; } 14 | public float SatelliteLongitude { get; set; } 15 | public DateTime FrameTime { get; set; } 16 | public OrganizerData Visible { get; set; } 17 | public OrganizerData Infrared { get; set; } 18 | public OrganizerData WaterVapour { get; set; } 19 | public Dictionary OtherData { get; set; } 20 | 21 | public bool IsProcessed { get; set; } 22 | public bool IsFalseColorProcessed { get; set; } 23 | public bool IsVisibleProcessed { get; set; } 24 | public bool IsInfraredProcessed { get; set; } 25 | public bool IsWaterVapourProcessed { get; set; } 26 | public bool CropImage { get; set; } 27 | public bool HasNavigationData { get; set; } 28 | 29 | public int FallBackLineOffset { get; set; } 30 | public int FallBackColumnOffset { get; set; } 31 | public float FallBackColumnScalingFactor { get; set; } 32 | public float FallBackLineScalingFactor { get; set; } 33 | 34 | public int RetryCount { get; set; } 35 | public bool Failed { get; set; } 36 | /// 37 | /// Code used for desambiguation 38 | /// 39 | /// The code. 40 | public string Code { get; set; } 41 | 42 | public bool IsComplete { get { 43 | return Visible.IsComplete && 44 | Infrared.IsComplete && 45 | WaterVapour.IsComplete && 46 | IsOtherDataProcessed; 47 | } 48 | } 49 | 50 | public bool IsOtherDataProcessed { 51 | get { 52 | return OtherData.Count == 0 || (OtherData 53 | .Select(x => x.Value.IsComplete) 54 | .Aggregate((x, y) => x & y) && OtherData 55 | .Select(x => x.Value.OK) 56 | .Aggregate((x, y) => x & y)); 57 | } 58 | } 59 | 60 | public bool Timeout { 61 | get { 62 | return (LLTools.Timestamp() - Created) > DATA_TIMEOUT; 63 | } 64 | } 65 | 66 | public bool ReadyToMark { 67 | get { 68 | return (LLTools.Timestamp () - Created) > MIN_DATA_MARK; 69 | } 70 | } 71 | 72 | public bool GroupTimeout { 73 | get { 74 | return (LLTools.Timestamp () - Created) > GROUP_DATA_TIMEOUT; 75 | } 76 | } 77 | 78 | public void ForceComplete() { 79 | IsProcessed = true; 80 | IsFalseColorProcessed = true; 81 | IsVisibleProcessed= true; 82 | IsInfraredProcessed = true; 83 | IsWaterVapourProcessed = true; 84 | OtherData.Select (x => x.Value).ToList ().ForEach (k => { k.OK = true; }); 85 | } 86 | 87 | private int Created; 88 | 89 | public GroupData() { 90 | SatelliteName = "Unknown"; 91 | RegionName = "Unknown"; 92 | SatelliteLongitude = 0f; 93 | FrameTime = DateTime.Now; 94 | Visible = new OrganizerData(); 95 | Infrared = new OrganizerData(); 96 | WaterVapour = new OrganizerData(); 97 | OtherData = new Dictionary(); 98 | IsFalseColorProcessed = false; 99 | IsVisibleProcessed = false; 100 | IsInfraredProcessed = false; 101 | IsWaterVapourProcessed = false; 102 | IsProcessed = false; 103 | Failed = false; 104 | RetryCount = 0; 105 | CropImage = false; 106 | Created = LLTools.Timestamp(); 107 | Code = DateTime.UtcNow.ToString(); 108 | HasNavigationData = false; 109 | FallBackColumnOffset = -1; 110 | FallBackLineOffset = -1; 111 | FallBackColumnScalingFactor = 0f; 112 | FallBackLineScalingFactor = 0f; 113 | } 114 | 115 | public override string ToString() { 116 | return string.Format( 117 | "Satellite Name: {0}\n" + 118 | "Region Name: {1}\n" + 119 | "Frame Time: {2}\n" + 120 | "Visible Segments: {3} ({4})\n" + 121 | "Infrared Segments: {5} ({6})\n" + 122 | "Water Vapour Segments: {7} ({8})\n" + 123 | "Other Data {9} ({10})\n" + 124 | "\n", 125 | SatelliteName, 126 | RegionName, 127 | FrameTime, 128 | Visible.Segments.Count, 129 | Visible.IsComplete ? "Complete" : "Incomplete", 130 | Infrared.Segments.Count, 131 | Infrared.IsComplete ? "Complete" : "Incomplete", 132 | WaterVapour.Segments.Count, 133 | WaterVapour.IsComplete ? "Complete" : "Incomplete", 134 | OtherData.Count, 135 | IsOtherDataProcessed ? "Complete" : "Incomplete" 136 | ); 137 | } 138 | } 139 | } 140 | 141 | -------------------------------------------------------------------------------- /XRIT/Models/OrganizerData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using OpenSatelliteProject.PacketData; 4 | 5 | namespace OpenSatelliteProject { 6 | public class OrganizerData { 7 | public Dictionary Segments { get; set; } 8 | public int Lines { get; set; } 9 | public int Columns { get; set; } 10 | public float PixelAspect { get; set; } 11 | public int ColumnOffset { get; set; } 12 | public int MaxSegments; 13 | public bool OK { get; set; } 14 | public int Timestamp { get; set; } 15 | public int FirstSegment { get; set; } 16 | public int LineOffset { get; set; } 17 | public float ColumnScalingFactor { get; set; } 18 | public float LineScalingFactor { get; set; } 19 | 20 | /// 21 | /// Code used for desambiguation 22 | /// 23 | /// The code. 24 | public string Code { get; set; } 25 | 26 | public XRITHeader FileHeader { get; set; } 27 | 28 | public OrganizerData() { 29 | Segments = new Dictionary(); 30 | Lines = -1; 31 | Columns = -1; 32 | PixelAspect = -1; 33 | ColumnOffset = 0; 34 | MaxSegments = 1; 35 | OK = false; 36 | Timestamp = 0; 37 | FirstSegment = 999999; 38 | Code = DateTime.UtcNow.ToShortTimeString (); 39 | FileHeader = null; 40 | ColumnOffset = -1; 41 | LineOffset = -1; 42 | ColumnScalingFactor = 0f; 43 | LineScalingFactor = 0f; 44 | } 45 | 46 | public bool IsComplete { get { return Segments.Count == MaxSegments; }} 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /XRIT/Models/StackTraceData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class StackTraceData { 5 | public int Line { get; set; } 6 | public int Column { get; set; } 7 | public string Filename { get; set; } 8 | public string ClassName { get; set; } 9 | public string Method { get; set; } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /XRIT/PacketData/AncillaryHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace OpenSatelliteProject.PacketData { 8 | public class AncillaryHeader: XRITBaseHeader { 9 | public String RawString { get; set; } 10 | public Dictionary Values { get; set; } 11 | 12 | public AncillaryHeader(AncillaryText data) { 13 | Type = HeaderType.AncillaryTextRecord; 14 | RawString = data.Data; 15 | 16 | Values = data.Data.Split(';') 17 | .Where(x => x.Trim().Length > 0) // Filter out empty items 18 | .Select(x => x.Trim()) // Trim strings 19 | .Select(x => x.Split('=')) // Split by '=' (key = value) 20 | .ToDictionary(x => x[0].Trim(), x => x.Length > 1 ? x[1].Trim() : ""); // Map to Dictionary 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /XRIT/PacketData/AnnotationHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class AnnotationHeader: XRITBaseHeader { 7 | public string Filename { get; set;} 8 | 9 | public AnnotationHeader(AnnotationRecord data) { 10 | Type = HeaderType.AnnotationRecord; 11 | Filename = data.Filename; 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /XRIT/PacketData/DCSFilenameHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class DCSFilenameHeader: XRITBaseHeader { 7 | public string Filename { get; set; } 8 | 9 | public DCSFilenameHeader(DCSFilenameRecord data) { 10 | Type = HeaderType.DCSFileNameRecord; 11 | Filename = data.Filename; 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /XRIT/PacketData/EMWINHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace OpenSatelliteProject.PacketData { 5 | public class EMWINHeader { 6 | 7 | public string Filename { get; } 8 | public int PartNumber { get; } 9 | public int PartTotal { get; } 10 | public int CS { get; } 11 | public string DateTime { get; } 12 | 13 | public EMWINHeader(string header) { 14 | if (header[0] != '/') { 15 | throw new InvalidOperationException(string.Format("Invalid header: {0}", header)); 16 | } 17 | //UIConsole.GlobalConsole.Debug("EMWIN Header: " + header); 18 | ///PFMISDCPNI.TXT/PN1 /PT1 /CS11024 /FD02/12/2017 07:27:29 PM 19 | try { 20 | Filename = header.Substring(1, 14); 21 | PartNumber = int.Parse(header.Substring(18, 6).Trim()); 22 | PartTotal = int.Parse(header.Substring(27, 6).Trim()); 23 | CS = int.Parse(header.Substring(36, 7).Trim()); 24 | this.DateTime = header.Substring(46, 22).Trim(); 25 | } catch (Exception e) { 26 | Console.WriteLine("ERROR Parsing header \"{0}\": {1}", header, e); 27 | Filename = "PFFILLFILE.TXT"; // To EMWIN Ingestor skip corrupted header 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /XRIT/PacketData/EmwinFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData { 4 | public class EmwinFile { 5 | 6 | public string Output { get; set; } 7 | 8 | public int Parts { get; set; } 9 | 10 | public int Received { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/CompressionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData { 4 | public enum CompressionType { 5 | NO_COMPRESSION = 0, 6 | LRIT_RICE = 1, 7 | JPEG = 2, 8 | GIF = 5, 9 | ZIP = 10 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/FileTypeCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData { 4 | public enum FileTypeCode { 5 | UNKNOWN = -1, 6 | 7 | // By LRIT/HRIT Standard 8 | // Section 4 of LRIT/HRIT Global Specification, CGMS 03, August 12, 1999 9 | IMAGE = 0, 10 | MESSAGES = 1, 11 | TEXT = 2, 12 | ENCRYPTION_KEY = 3, 13 | RESERVED4 = 4, 14 | 15 | METEOROLOGICAL_DATA = 128, 16 | 17 | // NOAA 18 | DCS = 130, 19 | EMWIN = 214 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/HeaderType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Enums { 4 | public enum HeaderType { 5 | Unknown = -1, 6 | PrimaryHeader = 0, 7 | ImageStructureRecord = 1, 8 | ImageNavigationRecord = 2, 9 | ImageDataFunctionRecord = 3, 10 | AnnotationRecord = 4, 11 | TimestampRecord = 5, 12 | AncillaryTextRecord = 6, 13 | KeyRecord = 7, 14 | Head9 = 9, // Weird 15 | 16 | SegmentIdentificationRecord = 128, 17 | NOAASpecificHeader = 129, 18 | HeaderStructuredRecord = 130, 19 | RiceCompressionRecord = 131, 20 | DCSFileNameRecord = 132 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/NOAAProductID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Enums { 4 | public enum NOAAProductID { 5 | NOAA_TEXT = 1, 6 | OTHER_SATELLITES_1 = 3, 7 | OTHER_SATELLITES_2 = 4, 8 | WEATHER_DATA = 6, 9 | ABI_RELAY = 7, 10 | DCS = 8, 11 | HRIT_EMWIN = 9, 12 | GOES13_ABI = 13, 13 | GOES15_ABI = 15, 14 | GOES16_ABI = 16, 15 | GOES17_ABI = 17, 16 | EMWIN = 42, 17 | HIMAWARI8_ABI = 43 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/SatelliteID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace OpenSatelliteProject { 3 | public enum SatelliteID { 4 | NOAA = 0x0, 5 | METEOSAT = 0x43, 6 | COMS = 0xC3 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /XRIT/PacketData/Enums/SubProductEnums.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public enum ScannerSubProduct { 5 | NONE = 0, 6 | 7 | // Infrared Images 8 | INFRARED_FULLDISK = 1, 9 | INFRARED_NORTHERN = 2, 10 | INFRARED_SOUTHERN = 3, 11 | INFRARED_UNITEDSTATES = 4, 12 | INFRARED_AREA_OF_INTEREST = 5, 13 | 14 | // Visible Images 15 | VISIBLE_FULLDISK = 11, 16 | VISIBLE_NORTHERN = 12, 17 | VISIBLE_SOUTHERN = 13, 18 | VISIBLE_UNITEDSTATES = 14, 19 | VISIBLE_AREA_OF_INTEREST = 15, 20 | 21 | // Water Vapour 22 | WATERVAPOUR_FULLDISK = 21, 23 | WATERVAPOUR_NORTHERN = 22, 24 | WATERVAPOUR_SOUTHERN = 23, 25 | WATERVAPOUR_UNITEDSTATES = 24, 26 | WATERVAPOUR_AREA_OF_INTEREST = 25 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /XRIT/PacketData/Head9Header.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using OpenSatelliteProject.PacketData.Enums; 3 | using OpenSatelliteProject.PacketData; 4 | 5 | namespace OpenSatelliteProject { 6 | public class Head9Header: XRITBaseHeader { 7 | 8 | public byte[] Data { get; set; } 9 | public string FileName { get; set; } 10 | 11 | public Head9Header(Head9 data) { 12 | Type = HeaderType.Head9; 13 | Data = data.Data; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XRIT/PacketData/HeaderStructuredHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class HeaderStructuredHeader: XRITBaseHeader { 7 | 8 | public string Data { get; set;} 9 | 10 | public HeaderStructuredHeader(HeaderStructuredRecord data) { 11 | Type = HeaderType.HeaderStructuredRecord; 12 | Data = data.Data; 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /XRIT/PacketData/ImageDataFunctionHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class ImageDataFunctionHeader: XRITBaseHeader { 7 | public string Data { get; set; } 8 | public ImageDataFunctionHeader(ImageDataFunctionRecord data) { 9 | Type = HeaderType.ImageDataFunctionRecord; 10 | Data = data.Data; 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /XRIT/PacketData/ImageNavigationHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class ImageNavigationHeader: XRITBaseHeader { 7 | 8 | public string ProjectionName { get; set; } 9 | public UInt32 ColumnScalingFactor { get; set; } 10 | public UInt32 LineScalingFactor { get; set; } 11 | public Int32 ColumnOffset { get; set; } 12 | public Int32 LineOffset { get; set; } 13 | 14 | public ImageNavigationHeader(ImageNavigationRecord data) { 15 | Type = HeaderType.ImageNavigationRecord; 16 | ProjectionName = data.ProjectionName; 17 | ColumnScalingFactor = data.ColumnScalingFactor; 18 | LineScalingFactor = data.LineScalingFactor; 19 | ColumnOffset = data.ColumnOffset; 20 | LineOffset = data.LineOffset; 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /XRIT/PacketData/ImageStructureHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class ImageStructureHeader: XRITBaseHeader { 7 | 8 | public byte BitsPerPixel { get; set; } 9 | public UInt16 Columns { get; set; } 10 | public UInt16 Lines { get; set; } 11 | public CompressionType Compression { get; set; } 12 | 13 | public ImageStructureHeader(ImageStructureRecord data) { 14 | Type = HeaderType.ImageStructureRecord; 15 | BitsPerPixel = data.BitsPerPixel; 16 | Columns = data.Columns; 17 | Lines = data.Lines; 18 | Compression = (CompressionType)data.Compression; 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /XRIT/PacketData/MSDU.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using OpenSatelliteProject.Tools; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class MSDU { 7 | #region Properties 8 | 9 | public int Version { get; set; } 10 | 11 | public int SHF { get; set; } 12 | 13 | public int APID { get; set; } 14 | 15 | public int Type { get; set; } 16 | 17 | public bool SecondHeader { get; set; } 18 | 19 | public SequenceType Sequence { get; set; } 20 | 21 | public int PacketNumber { get; set; } 22 | 23 | public int PacketLength { get; set; } 24 | 25 | public byte[] Data { get; set; } 26 | 27 | public byte[] RemainingData { get; set; } 28 | 29 | public bool FrameLost { get; set; } 30 | 31 | public string TemporaryFilename { get; set; } 32 | 33 | public bool Full { 34 | get { 35 | return Data.Length == PacketLength + 2; 36 | } 37 | } 38 | 39 | public int CRC { 40 | get { 41 | byte[] o = Data.Skip(Data.Length - 2).ToArray(); 42 | if (BitConverter.IsLittleEndian) { 43 | Array.Reverse(o); 44 | } 45 | return BitConverter.ToUInt16(o, 0); 46 | } 47 | } 48 | 49 | public bool Valid { 50 | get { 51 | if (Data.Length > 2) { 52 | return Data.Take(Data.Length - 2).ToArray().CRC() == CRC; 53 | } else { 54 | // Not enough data 55 | return false; 56 | } 57 | } 58 | } 59 | 60 | public bool FillPacket { 61 | get { 62 | return APID == 2047; 63 | } 64 | } 65 | 66 | #endregion 67 | 68 | #region Constructor / Destructor 69 | 70 | private MSDU() { 71 | } 72 | 73 | #endregion 74 | 75 | #region Methods 76 | 77 | public void addDataBytes(byte[] data) { 78 | /*if (data.Length + Data.Length > PacketLength + 2) { 79 | Console.WriteLine("Overflow in MSDU!"); 80 | }*/ 81 | byte[] newData = new byte[Data.Length + data.Length]; 82 | Array.Copy(Data, newData, Data.Length); 83 | Array.Copy(data, 0, newData, Data.Length, data.Length); 84 | if (newData.Length > PacketLength + 2) { 85 | Data = newData.Take(PacketLength + 2).ToArray(); 86 | } else { 87 | Data = newData; 88 | } 89 | 90 | } 91 | 92 | #endregion 93 | 94 | 95 | #region Builders / Parsers 96 | 97 | public static MSDU parseMSDU(byte[] data) { 98 | MSDU msdu = new MSDU(); 99 | 100 | byte[] ob = data.Take(2).ToArray(); 101 | if (BitConverter.IsLittleEndian) { 102 | Array.Reverse(ob); 103 | } 104 | 105 | UInt16 o = BitConverter.ToUInt16(ob, 0); 106 | 107 | msdu.Version = (o & 0xE000) >> 13; 108 | msdu.Type = (o & 0x1000) >> 12; 109 | msdu.SecondHeader = ((o & 0x800) >> 11) > 0; 110 | msdu.APID = o & 0x7FF; 111 | 112 | msdu.TemporaryFilename = $"{msdu.APID}.lrittmp"; 113 | 114 | ob = data.Skip(2).Take(2).ToArray(); 115 | if (BitConverter.IsLittleEndian) { 116 | Array.Reverse(ob); 117 | } 118 | 119 | o = BitConverter.ToUInt16(ob, 0); 120 | 121 | msdu.Sequence = (SequenceType)((o & 0xC000) >> 14); 122 | msdu.PacketNumber = (o & 0x3FFF); 123 | 124 | ob = data.Skip(4).Take(2).ToArray(); 125 | if (BitConverter.IsLittleEndian) { 126 | Array.Reverse(ob); 127 | } 128 | 129 | msdu.PacketLength = BitConverter.ToUInt16(ob, 0) - 1; 130 | data = data.Skip(6).ToArray(); 131 | if (data.Length > msdu.PacketLength + 2) { 132 | msdu.RemainingData = data.Skip(msdu.PacketLength + 2).ToArray(); 133 | data = data.Take(msdu.PacketLength + 2).ToArray(); 134 | } else { 135 | msdu.RemainingData = new byte[0]; 136 | } 137 | 138 | msdu.Data = data.ToArray(); 139 | 140 | msdu.FrameLost = false; 141 | 142 | return msdu; 143 | } 144 | 145 | #endregion 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /XRIT/PacketData/MSDUInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData; 3 | using OpenSatelliteProject.Tools; 4 | 5 | namespace OpenSatelliteProject { 6 | class MSDUInfo { 7 | const long TIMEOUT = 15 * 60 * 60; // 15 minutes 8 | 9 | public int APID { get; set; } 10 | public long ReceivedTime { get; private set; } 11 | public string FileName { get; set; } 12 | public XRITHeader Header { get; set; } 13 | public int LastPacketNumber { get; set; } 14 | 15 | public bool Expired { 16 | get { 17 | return LLTools.TimestampMS() - ReceivedTime > TIMEOUT; 18 | } 19 | } 20 | 21 | public MSDUInfo() { 22 | ReceivedTime = LLTools.TimestampMS(); 23 | } 24 | 25 | public void Refresh() { 26 | ReceivedTime = LLTools.TimestampMS(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /XRIT/PacketData/NOAAProduct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class NOAAProduct { 7 | public int ID { get; set; } 8 | 9 | public string Name { get; set; } 10 | 11 | public Dictionary SubProducts; 12 | 13 | public NOAAProduct(int id) { 14 | ID = id; 15 | Name = "Unknown"; 16 | SubProducts = new Dictionary(); 17 | } 18 | 19 | public NOAAProduct(int id, string name) { 20 | ID = id; 21 | Name = name; 22 | SubProducts = new Dictionary(); 23 | } 24 | 25 | public NOAAProduct(NOAAProductID id, string name) : this((int)id, name) { 26 | 27 | } 28 | 29 | public NOAAProduct(NOAAProductID id, string name, Dictionary subProducts) : this((int)id, name, subProducts) { 30 | 31 | } 32 | 33 | public NOAAProduct(int id, string name, Dictionary subProducts) { 34 | ID = id; 35 | Name = name; 36 | SubProducts = new Dictionary(); 37 | foreach (int key in subProducts.Keys) { 38 | SubProducts.Add(key, subProducts[key]); 39 | } 40 | } 41 | 42 | public NOAASubproduct getSubProduct(int id) { 43 | if (SubProducts.ContainsKey(id)) { 44 | return SubProducts[id]; 45 | } else { 46 | return new NOAASubproduct(id, "Unknown"); 47 | } 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /XRIT/PacketData/NOAASpecificHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class NOAASpecificHeader: XRITBaseHeader { 7 | 8 | public string Signature { get; set; } 9 | public NOAAProduct Product { get; set; } 10 | public NOAASubproduct SubProduct { get; set; } 11 | public UInt16 Parameter { get; set; } 12 | public CompressionType Compression; 13 | 14 | public NOAASpecificHeader(NOAASpecificRecord data) { 15 | Type = HeaderType.NOAASpecificHeader; 16 | Signature = data.Signature; 17 | Product = Presets.GetProductById(data.ProductID); 18 | SubProduct = Product.getSubProduct(data.ProductSubID); 19 | Parameter = data.Parameter; 20 | Compression = (CompressionType)data.Compression; 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /XRIT/PacketData/NOAASubproduct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData { 4 | public class NOAASubproduct { 5 | public int ID { get; set; } 6 | 7 | public string Name; 8 | 9 | public NOAASubproduct(int id) { 10 | ID = id; 11 | Name = "Unknown"; 12 | } 13 | 14 | public NOAASubproduct(ScannerSubProduct id, string name) : this((int)id, name) { 15 | 16 | } 17 | 18 | public NOAASubproduct(int id, string name) { 19 | ID = id; 20 | Name = name; 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /XRIT/PacketData/PrimaryHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class PrimaryHeader: XRITBaseHeader { 7 | 8 | public FileTypeCode FileType { get; set; } 9 | public UInt32 HeaderLength; 10 | public UInt64 DataLength; 11 | 12 | public PrimaryHeader(PrimaryRecord data) { 13 | Type = HeaderType.PrimaryHeader; 14 | FileType = (FileTypeCode)data.FileTypeCode; 15 | HeaderLength = data.HeaderLength; 16 | DataLength = data.DataLength; 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /XRIT/PacketData/RiceCompressionHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Structs; 3 | using OpenSatelliteProject.PacketData.Enums; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class RiceCompressionHeader: XRITBaseHeader { 7 | public UInt16 Flags; 8 | public byte Pixel; 9 | public byte Line; 10 | 11 | public RiceCompressionHeader(RiceCompressionRecord data) { 12 | Type = HeaderType.RiceCompressionRecord; 13 | Flags = data.Flags; 14 | Pixel = data.Pixel; 15 | Line = data.Line; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /XRIT/PacketData/SegmentIdentificationHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Enums; 3 | using OpenSatelliteProject.PacketData.Structs; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class SegmentIdentificationHeader: XRITBaseHeader { 7 | 8 | public UInt16 ImageID { get; set; } 9 | public UInt16 Sequence { get; set; } 10 | public UInt16 StartColumn { get; set; } 11 | public UInt16 StartLine { get; set; } 12 | public UInt16 MaxSegments { get; set; } 13 | public UInt16 MaxColumns { get; set; } 14 | public UInt16 MaxRows { get; set; } 15 | 16 | public SegmentIdentificationHeader(SegmentIdentificationRecord data) { 17 | Type = HeaderType.SegmentIdentificationRecord; 18 | ImageID = data.ImageID; 19 | Sequence = data.Sequence; 20 | StartColumn = data.StartColumn; 21 | StartLine = data.StartLine; 22 | MaxSegments = data.MaxSegments; 23 | MaxRows = data.MaxRows; 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /XRIT/PacketData/SequenceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData { 4 | public enum SequenceType { 5 | CONTINUED_SEGMENT = 0, 6 | FIRST_SEGMENT = 1, 7 | LAST_SEGMENT = 2, 8 | SINGLE_DATA = 3 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/AncillaryText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | public struct AncillaryText { 7 | public byte type; 8 | public UInt16 size; 9 | public string Data; 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/AnnotationRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Structs { 4 | public struct AnnotationRecord { 5 | public byte type; 6 | public UInt16 size; 7 | public string Filename; 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/DCSFilenameRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Structs { 4 | public struct DCSFilenameRecord { 5 | public byte type; 6 | public UInt16 size; 7 | public string Filename; 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/HeaderStructuredRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Structs { 4 | 5 | public struct HeaderStructuredRecord { 6 | public byte type; 7 | public UInt16 size; 8 | public string Data; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/ImageDataFunctionRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject.PacketData.Structs { 4 | public struct ImageDataFunctionRecord { 5 | public byte type; 6 | public UInt16 size; 7 | public string Data; 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/ImageNavigationRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct ImageNavigationRecord { 8 | public byte type; 9 | public UInt16 size; 10 | 11 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 12 | public string ProjectionName; 13 | public UInt32 ColumnScalingFactor; 14 | public UInt32 LineScalingFactor; 15 | public Int32 ColumnOffset; 16 | public Int32 LineOffset; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/ImageStructureRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct ImageStructureRecord { 8 | public byte type; 9 | public UInt16 size; 10 | public byte BitsPerPixel; 11 | public UInt16 Columns; 12 | public UInt16 Lines; 13 | public byte Compression; 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/NOAASpecificRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct NOAASpecificRecord { 8 | public byte type; 9 | public UInt16 size; 10 | 11 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] 12 | public string Signature; 13 | 14 | public UInt16 ProductID; 15 | public UInt16 ProductSubID; 16 | public UInt16 Parameter; 17 | public byte Compression; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/PrimaryRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct PrimaryRecord { 8 | public byte type; 9 | public UInt16 size; 10 | public byte FileTypeCode; 11 | public UInt32 HeaderLength; 12 | public UInt64 DataLength; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/RiceCompressionRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct RiceCompressionRecord { 8 | public byte type; 9 | public UInt16 size; 10 | 11 | public UInt16 Flags; 12 | public byte Pixel; 13 | public byte Line; 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/SegmentIdentificationRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct SegmentIdentificationRecord { 8 | public byte type; 9 | public UInt16 size; 10 | 11 | public UInt16 ImageID; 12 | public UInt16 Sequence; 13 | public UInt16 StartColumn; 14 | public UInt16 StartLine; 15 | public UInt16 MaxSegments; 16 | public UInt16 MaxColumns; 17 | public UInt16 MaxRows; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/TimestampRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.PacketData.Structs { 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct TimestampRecord { 8 | public byte type; 9 | public UInt16 size; 10 | public UInt16 Days; 11 | public UInt32 Milisseconds; 12 | 13 | public DateTime getDateTime() { 14 | DateTime t = new DateTime(1958, 1, 1); 15 | t.AddDays(Days); 16 | t.AddMilliseconds(Milisseconds); 17 | return t; 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /XRIT/PacketData/Structs/UnknownHeaders.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace OpenSatelliteProject { 3 | /** 4 | * Head with code 9, found on GOES-15 after GOES-16 transition. 5 | * It's a weird header, but consistent. Under LRIT spec is reserved. 6 | */ 7 | public struct Head9 { 8 | public byte type; 9 | public byte[] Data; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /XRIT/PacketData/TimestampHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Enums; 3 | using OpenSatelliteProject.PacketData.Structs; 4 | 5 | namespace OpenSatelliteProject.PacketData { 6 | public class TimestampHeader: XRITBaseHeader { 7 | 8 | public DateTime DateTime { get; set; } 9 | 10 | public TimestampHeader(TimestampRecord data) { 11 | Type = HeaderType.TimestampRecord; 12 | DateTime = data.getDateTime(); 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /XRIT/PacketData/XRitBaseHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenSatelliteProject.PacketData.Enums; 3 | 4 | namespace OpenSatelliteProject.PacketData { 5 | public class XRITBaseHeader { 6 | public HeaderType Type { get; set; } 7 | public byte[] RawData { get; set; } 8 | 9 | public XRITBaseHeader() { 10 | Type = HeaderType.Unknown; 11 | RawData = new byte[0]; 12 | } 13 | 14 | public XRITBaseHeader(HeaderType type, byte[] rawData) { 15 | Type = type; 16 | RawData = rawData; 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /XRIT/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("XRIT")] 8 | [assembly: AssemblyDescription("XRIT Auxiliary Library")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("OpenSatelliteProject")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("Lucas Teske @ 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.4.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /XRIT/Properties/LibInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.IO; 3 | using System; 4 | 5 | namespace OpenSatelliteProject { 6 | public static class LibInfo { 7 | 8 | private static string _commitId = "development"; 9 | private static string _gitlog = ""; 10 | 11 | static LibInfo() { 12 | var assembly = Assembly.GetExecutingAssembly(); 13 | 14 | try { 15 | using (Stream stream = assembly.GetManifestResourceStream("OpenSatelliteProject.git-hash.txt")) 16 | using (StreamReader reader = new StreamReader(stream)) 17 | { 18 | string result = reader.ReadToEnd(); 19 | _commitId = result; 20 | } 21 | } catch (Exception) { 22 | UIConsole.Warn ("Cannot load git-hash from library."); 23 | } 24 | 25 | try { 26 | using (Stream stream = assembly.GetManifestResourceStream("OpenSatelliteProject.git-log.txt")) 27 | using (StreamReader reader = new StreamReader(stream)) 28 | { 29 | string result = reader.ReadToEnd(); 30 | _gitlog = result; 31 | } 32 | } catch (Exception) { 33 | UIConsole.Warn ("Cannot load git-log from library."); 34 | } 35 | } 36 | 37 | public static string CommitID { get { return _commitId; } } 38 | public static string ShortCommitID { get { return _commitId.Substring(0, 7); } } 39 | public static string[] ArrayLogLines { get { return _gitlog.Split ('\n'); } } 40 | public static string LogLines { get { return _gitlog; } } 41 | 42 | public static int VersionMajor { 43 | get { 44 | return typeof(LibInfo).Assembly.GetName ().Version.Major; 45 | } 46 | } 47 | 48 | public static int VersionMinor { 49 | get { 50 | return typeof(LibInfo).Assembly.GetName ().Version.Minor; 51 | } 52 | } 53 | 54 | public static int VersionBuild { 55 | get { 56 | return typeof(LibInfo).Assembly.GetName ().Version.Build; 57 | } 58 | } 59 | 60 | public static int VersionRevision { 61 | get { 62 | return typeof(LibInfo).Assembly.GetName ().Version.Revision; 63 | } 64 | } 65 | 66 | public static string Version { 67 | get { 68 | return string.Format("{0}.{1}.{2}.{3}", 69 | typeof(LibInfo).Assembly.GetName().Version.Major, 70 | typeof(LibInfo).Assembly.GetName().Version.Minor, 71 | typeof(LibInfo).Assembly.GetName().Version.Build, 72 | typeof(LibInfo).Assembly.GetName().Version.Revision 73 | ); 74 | } 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /XRIT/ShapeFiles/README.md: -------------------------------------------------------------------------------- 1 | Shape Files 2 | ========================== 3 | 4 | These are the shapefiles that XRIT uses to generate overlays. 5 | 6 | You can find more information / download them / update them at http://www.naturalearthdata.com/downloads/ 7 | -------------------------------------------------------------------------------- /XRIT/ShapeFiles/ShapeFiles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | 5 | namespace OpenSatelliteProject { 6 | public static class ShapeFiles { 7 | private static byte[] ReadFileFromAssembly(string filename) { 8 | byte[] data = null; 9 | var assembly = Assembly.GetExecutingAssembly(); 10 | try { 11 | Stream stream = assembly.GetManifestResourceStream($"OpenSatelliteProject.ShapeFiles.{filename}"); 12 | if (stream == null) { 13 | stream = assembly.GetManifestResourceStream($"OpenSatelliteProject.{filename}"); 14 | } 15 | using (stream) { 16 | data = new byte[stream.Length]; 17 | int position = 0; 18 | while (position < stream.Length) { 19 | int chunkSize = stream.Length - position > 4096 ? 4096 : (int) (stream.Length - position); 20 | stream.Read(data, position, chunkSize); 21 | position += chunkSize; 22 | } 23 | } 24 | } catch (Exception e) { 25 | UIConsole.Warn ($"ShapeFiles -- Cannot load {filename} from library."); 26 | UIConsole.Error($"ShapeFiles -- {e.Message}"); 27 | } 28 | 29 | return data; 30 | } 31 | 32 | public static byte[] ReadSHX() { 33 | return ReadFileFromAssembly ("ne_50m_admin_0_countries.shx"); 34 | } 35 | 36 | public static byte[] ReadDBF() { 37 | return ReadFileFromAssembly ("ne_50m_admin_0_countries.dbf"); 38 | } 39 | 40 | public static byte[] ReadPRJ() { 41 | return ReadFileFromAssembly ("ne_50m_admin_0_countries.prj"); 42 | } 43 | 44 | public static byte[] ReadSHP() { 45 | return ReadFileFromAssembly ("ne_50m_admin_0_countries.shp"); 46 | } 47 | 48 | private static string ExtractFile(string filename) { 49 | string output = Path.Combine (Path.GetTempPath (), filename); 50 | UIConsole.Debug ($"ShapeFiles -- Extracting {filename} to {output}"); 51 | byte[] data = ReadFileFromAssembly (filename); 52 | File.WriteAllBytes (output, data); 53 | return output; 54 | } 55 | 56 | // Need to do better, but since DotSpatial doesn't support loading from memory, thats what we have for now. 57 | 58 | public static string ExtractSHX() { 59 | UIConsole.Debug ("ShapeFiles -- Extracting SHX File ne_50m_admin_0_countries.shx"); 60 | return ExtractFile ("ne_50m_admin_0_countries.shx"); 61 | } 62 | public static string ExtractDBF() { 63 | UIConsole.Debug ("ShapeFiles -- Extracting DBF File ne_50m_admin_0_countries.dbf"); 64 | return ExtractFile ("ne_50m_admin_0_countries.dbf"); 65 | } 66 | public static string ExtractPRJ() { 67 | UIConsole.Debug ("ShapeFiles -- Extracting PRJ File ne_50m_admin_0_countries.prj"); 68 | return ExtractFile ("ne_50m_admin_0_countries.prj"); 69 | } 70 | public static string ExtractSHP() { 71 | UIConsole.Debug ("ShapeFiles -- Extracting SHP File ne_50m_admin_0_countries.shp"); 72 | return ExtractFile ("ne_50m_admin_0_countries.shp"); 73 | } 74 | 75 | public static string InitShapeFiles() { 76 | try { 77 | UIConsole.Debug("ShapeFiles -- Initializing ShapeFiles"); 78 | ExtractDBF (); 79 | ExtractPRJ (); 80 | ExtractSHX (); 81 | return ExtractSHP (); 82 | } catch (Exception e) { 83 | UIConsole.Error ($"ShapeFiles -- There was an error extracting ShapeFiles: {e}"); 84 | } 85 | return null; 86 | } 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /XRIT/ShapeFiles/ne_50m_admin_0_countries.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/ShapeFiles/ne_50m_admin_0_countries.dbf -------------------------------------------------------------------------------- /XRIT/ShapeFiles/ne_50m_admin_0_countries.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] -------------------------------------------------------------------------------- /XRIT/ShapeFiles/ne_50m_admin_0_countries.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/ShapeFiles/ne_50m_admin_0_countries.shp -------------------------------------------------------------------------------- /XRIT/ShapeFiles/ne_50m_admin_0_countries.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/ShapeFiles/ne_50m_admin_0_countries.shx -------------------------------------------------------------------------------- /XRIT/Storage/ConfigurationManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public static class ConfigurationManager { 5 | const string ConfigFileName = "config.db"; 6 | static readonly Database db; 7 | 8 | static ConfigurationManager() { 9 | db = new Database (ConfigFileName); 10 | } 11 | 12 | public static void PutStatistics(DBStatistics statistics, bool autoTimestamp = true) { 13 | db.PutStatistic (statistics, autoTimestamp); 14 | } 15 | 16 | public static string Get(string key, string def = null) { 17 | return db[key] ?? def; 18 | } 19 | 20 | public static void Set(string key, string value) { 21 | db[key] = value; 22 | } 23 | 24 | public static void Set(string key, bool value) { 25 | db.Set (key, value); 26 | } 27 | 28 | public static void Set(string key, int value) { 29 | db.Set (key, value); 30 | } 31 | 32 | public static void Set(string key, float value) { 33 | db.Set (key, value); 34 | } 35 | 36 | public static void Set(string key, double value) { 37 | db.Set (key, value); 38 | } 39 | 40 | public static int GetInt(string key) { 41 | return db.GetInt (key); 42 | } 43 | 44 | public static bool GetBool(string key) { 45 | return db.GetBool (key); 46 | } 47 | 48 | public static float GetFloat(string key) { 49 | return db.GetFloat (key); 50 | } 51 | 52 | public static double GetDouble(string key) { 53 | return db.GetDouble (key); 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /XRIT/Storage/DBConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLite; 3 | 4 | namespace OpenSatelliteProject { 5 | public class DBConfig { 6 | [PrimaryKey, MaxLength(50)] 7 | public string Name { get; set; } 8 | [MaxLength(255)] 9 | public string Value { get; set; } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /XRIT/Storage/DBStatistics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLite; 3 | 4 | namespace OpenSatelliteProject { 5 | public class DBStatistics { 6 | [PrimaryKey, AutoIncrement] 7 | public int Id { get; set; } 8 | public long Timestamp { get; set; } 9 | public int SCID { get; set; } 10 | public int VCID { get; set; } 11 | public long PacketNumber { get; set; } 12 | public int VitErrors { get; set; } 13 | public int FrameBits { get; set; } 14 | public int RSErrors0 { get; set; } 15 | public int RSErrors1 { get; set; } 16 | public int RSErrors2 { get; set; } 17 | public int RSErrors3 { get; set; } 18 | public byte SignalQuality { get; set; } 19 | public byte SyncCorrelation { get; set; } 20 | public byte PhaseCorrection { get; set; } 21 | public long LostPackets { get; set; } 22 | public int AverageVitCorrections { get; set; } 23 | public byte AverageRSCorrections { get; set; } 24 | public long DroppedPackets { get; set; } 25 | [MaxLength(16)] 26 | public string SyncWord { get; set; } 27 | public bool FrameLock { get; set; } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /XRIT/Storage/Database.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | using OpenSatelliteProject.Tools; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | namespace OpenSatelliteProject { 7 | public class Database { 8 | readonly SQLiteConnection conn; 9 | readonly SQLiteConnection statConn; 10 | readonly Dictionary configCache; 11 | 12 | public Database (string filename, string statisticsFilename = "statistics.db") { 13 | conn = new SQLiteConnection (filename); 14 | statConn = new SQLiteConnection (statisticsFilename); 15 | configCache = new Dictionary (); 16 | Init (); 17 | } 18 | 19 | void Init() { 20 | var x = conn.GetTableInfo ("DBConfig"); 21 | if (x.Count == 0) { 22 | conn.CreateTable (); 23 | } 24 | x = statConn.GetTableInfo ("DBStatistics"); 25 | if (x.Count == 0) { 26 | statConn.CreateTable (); 27 | } 28 | } 29 | 30 | public void Close() { 31 | lock (conn) { 32 | conn.Close (); 33 | } 34 | lock (statConn) { 35 | statConn.Close (); 36 | } 37 | } 38 | 39 | public void PutStatistic(DBStatistics statistics, bool autoTimestamp = true) { 40 | lock (statConn) { 41 | if (autoTimestamp) { 42 | statistics.Timestamp = LLTools.TimestampMS (); 43 | } 44 | statConn.Insert (statistics); 45 | } 46 | } 47 | 48 | public string this[string key] { 49 | get { 50 | lock (configCache) { 51 | if (!configCache.ContainsKey (key)) { 52 | // Fetch from DB 53 | var res = conn.Table ().Where (a => a.Name == key); 54 | configCache [key] = res.Count () > 0 ? res.First ().Value : null; 55 | } 56 | return configCache [key]; 57 | } 58 | } 59 | set { 60 | lock (configCache) { 61 | conn.Insert (new DBConfig () { Name = key, Value = value }, "OR REPLACE"); 62 | configCache [key] = value; 63 | } 64 | } 65 | } 66 | 67 | #region Typed Setter / Getter 68 | 69 | public void Set(string key, bool value) { 70 | this [key] = value.ToString (); 71 | } 72 | 73 | public void Set(string key, int value) { 74 | this [key] = value.ToString (); 75 | } 76 | 77 | public void Set(string key, float value) { 78 | this [key] = value.ToString (); 79 | } 80 | 81 | public void Set(string key, double value) { 82 | this [key] = value.ToString (); 83 | } 84 | 85 | public int GetInt(string key) { 86 | try { 87 | return int.Parse(this[key]); 88 | } catch (Exception) { 89 | return 0; 90 | } 91 | } 92 | 93 | public bool GetBool(string key) { 94 | return this[key].ToLower() == "true"; 95 | } 96 | 97 | public float GetFloat(string key) { 98 | try { 99 | return float.Parse(this[key]); 100 | } catch (Exception) { 101 | return float.NaN; 102 | } 103 | } 104 | 105 | public double GetDouble(string key) { 106 | try { 107 | return double.Parse(this[key]); 108 | } catch (Exception) { 109 | return double.NaN; 110 | } 111 | } 112 | 113 | #endregion 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /XRIT/Storage/StatisticsManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using OpenSatelliteProject.Tools; 4 | 5 | namespace OpenSatelliteProject { 6 | public static class StatisticsManager { 7 | const int checkInterval = 5; // Seconds 8 | static readonly List statistics; 9 | static int lastCheck; 10 | static long lastTimestamp; 11 | 12 | static StatisticsManager() { 13 | statistics = new List (); 14 | lastCheck = LLTools.Timestamp (); 15 | lastTimestamp = LLTools.TimestampMS (); 16 | } 17 | 18 | public static void Update(DBStatistics stats) { 19 | lock (statistics) { 20 | stats.Timestamp = LLTools.TimestampMS (); 21 | if (stats.Timestamp == lastTimestamp) { 22 | stats.Timestamp++; 23 | } 24 | lastTimestamp = stats.Timestamp; 25 | 26 | statistics.Add (stats); 27 | if (LLTools.Timestamp () - lastCheck > checkInterval) { 28 | long startTime = LLTools.TimestampMS (); 29 | // Time to dump 30 | foreach (var s in statistics) { 31 | ConfigurationManager.PutStatistics (s, false); 32 | } 33 | statistics.Clear (); 34 | lastCheck = LLTools.Timestamp (); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /XRIT/Tools/AEC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace OpenSatelliteProject.Tools { 5 | /// 6 | /// libaec Wrapper Class 7 | /// 8 | /// Used for decompressing LRIT Rice 9 | /// 10 | public static class AEC { 11 | public static readonly int ALLOW_K13_OPTION_MASK = 1; 12 | public static readonly int CHIP_OPTION_MASK = 2; 13 | public static readonly int EC_OPTION_MASK = 4; 14 | public static readonly int LSB_OPTION_MASK = 8; 15 | public static readonly int MSB_OPTION_MASK = 16; 16 | public static readonly int NN_OPTION_MASK = 32; 17 | public static readonly int RAW_OPTION_MASK = 128; 18 | 19 | [DllImport("satdecompress", CallingConvention = CallingConvention.Cdecl)] 20 | public static unsafe extern int Decompress(byte *input, byte *output, uint inputLength, uint outputLength, int bitsPerPixel, int pixelsPerBlock, int pixelsPerScanline, int mask); 21 | 22 | public static int LritRiceDecompress(ref byte[] dest, byte[] source, int bitsPerPixel, int pixelsPerBlock, int pixelsPerScanline, int mask) { 23 | int status = -100; 24 | unsafe { 25 | fixed (byte* destPtr = dest) { 26 | fixed (byte *srcPtr = source) { 27 | status = Decompress(srcPtr, destPtr, (uint) source.Length, (uint) dest.Length, bitsPerPixel, pixelsPerBlock, pixelsPerScanline, mask); 28 | } 29 | } 30 | } 31 | 32 | if (status <= 0) { 33 | throw new AECException((AECStatus)status); 34 | } 35 | 36 | return status; 37 | } 38 | } 39 | 40 | public class AECException: Exception { 41 | public AECStatus status; 42 | 43 | public AECException(AECStatus error) { 44 | this.status = error; 45 | } 46 | } 47 | 48 | public enum AECStatus { 49 | INTERNAL_ERROR = -100, 50 | MEMORY_ERROR = -4, 51 | DATA_ERROR = -3, 52 | STREAM_ERROR = -2, 53 | CONFIG_ERROR = -1, 54 | OK = 0, 55 | OUTPUT_BUFFER_FULL = 2, 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /XRIT/Tools/CrashReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading; 4 | 5 | namespace OpenSatelliteProject { 6 | public static class CrashReport { 7 | public static bool EnableSendCrashDump = true; 8 | public static bool EnableSaveCrashDump = true; 9 | public static string CrashLogFolder = "crash"; 10 | public static string Username = "Not defined"; 11 | 12 | public static void DefaultExceptionHandler(object sender, ThreadExceptionEventArgs e) { 13 | Report (e.Exception); 14 | } 15 | 16 | public static void DefaultExceptionHandler(object sender, UnhandledExceptionEventArgs e) { 17 | Report ((Exception) e.ExceptionObject); 18 | } 19 | 20 | public static void Report(Exception e) { 21 | var cd = new CrashData (e, Username); 22 | try { 23 | UIConsole.Error($"Got {cd.ExceptionName} at {cd.Filename}:{cd.Line}"); 24 | } catch (Exception) { 25 | Console.WriteLine($"Got {cd.ExceptionName} at {cd.Filename}:{cd.Line}"); 26 | } 27 | SaveCrashDump (cd); 28 | SendCrashDump (cd); 29 | } 30 | 31 | static void SaveCrashDump(CrashData cd) { 32 | if (EnableSaveCrashDump) { 33 | try { 34 | Directory.CreateDirectory(CrashLogFolder); 35 | string jsonData = cd.ToJSON(); 36 | string filename = $"crashdata-{cd.ExceptionName}-{cd.ID}.json"; 37 | try { 38 | UIConsole.Error($"Saving Crash Dump to: {filename}"); 39 | } catch (Exception) { 40 | Console.WriteLine($"Saving Crash Dump to: {filename}"); 41 | } 42 | File.WriteAllText(Path.Combine(CrashLogFolder, filename), jsonData); 43 | } catch (Exception e) { 44 | Console.WriteLine ("FATAL: Cannot write crash dump: {0}", e); 45 | } 46 | } 47 | } 48 | 49 | static void SendCrashDump(CrashData cd) { 50 | if (EnableSendCrashDump) { 51 | // TODO 52 | } 53 | } 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /XRIT/Tools/TextHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using OpenSatelliteProject.PacketData.Structs; 5 | using OpenSatelliteProject.PacketData; 6 | 7 | namespace OpenSatelliteProject.Tools { 8 | public class TextHandler { 9 | 10 | public static TextHandler Handler { get; private set; } 11 | 12 | static TextHandler() { 13 | TextHandler.Handler = new TextHandler(); 14 | } 15 | 16 | private TextHandler() {} 17 | 18 | 19 | public void HandleFile(string filename, string outputFolder) { 20 | var f = File.Open(filename, FileMode.Open); 21 | var firstHeader = new byte[3]; 22 | f.Read(firstHeader, 0, 3); 23 | if (firstHeader[0] == 0) { 24 | var tmp = firstHeader.Skip(1).Take(2).ToArray(); 25 | if (BitConverter.IsLittleEndian) { 26 | Array.Reverse(tmp); 27 | } 28 | 29 | int size = BitConverter.ToUInt16(tmp, 0); 30 | firstHeader = new byte[size - 3]; 31 | f.Seek(0, SeekOrigin.Begin); 32 | f.Read(firstHeader, 0, size - 3); 33 | 34 | PrimaryRecord fh = LLTools.ByteArrayToStruct(firstHeader); 35 | fh = LLTools.StructToSystemEndian(fh); 36 | 37 | f.Seek(0, SeekOrigin.Begin); 38 | tmp = new byte[fh.HeaderLength]; 39 | f.Read(tmp, 0, (int)fh.HeaderLength); 40 | var header = FileParser.GetHeader(tmp); 41 | ProcessFile(f, header, outputFolder); 42 | f.Close(); 43 | } else { 44 | Console.WriteLine("Expected header type 0 for first header. Got {0}.", (int)firstHeader[0]); 45 | } 46 | } 47 | 48 | private void ProcessFile(FileStream file, XRITHeader header, string outputFolder) { 49 | int bytesToRead = (int) (file.Length - header.PrimaryHeader.HeaderLength); 50 | 51 | var buffer = new byte[bytesToRead]; 52 | file.Read(buffer, 0, bytesToRead); 53 | 54 | string outName = header.Filename.Replace(".lrit", ".txt"); 55 | outName = Path.Combine(outputFolder, outName); 56 | 57 | var fo = File.OpenWrite(outName); 58 | fo.Write(buffer, 0, bytesToRead); 59 | fo.Close(); 60 | 61 | EventMaster.Post (EventTypes.NewFileEvent, new NewFileReceivedEventData { 62 | Name = Path.GetFileName(outName), 63 | Path = outName, 64 | Metadata = { 65 | { "product", header.Product.Name }, 66 | { "subProduct", header.SubProduct.Name }, 67 | { "productId", header.Product.ID.ToString() }, 68 | { "subProductId", header.SubProduct.ID.ToString() } 69 | } 70 | }); 71 | } 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /XRIT/build-pre.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | msbuild /p:Configuration=Release 4 | cp bin/Release/XRIT.dll build/lib/net45/ 5 | cp bin/Release/XRIT.dll build/lib/net452/ 6 | LIBVER=`monodis --assembly bin/Release/XRIT.dll |grep Version | cut -d: -f2 | sed -e 's/^[[:space:]]*//'` 7 | 8 | echo "Current Version: ${LIBVER%.*}" 9 | # sed "s/|{|VERSION|}|/${LIBVER%.*}/g" XRIT.nuspec.tpl > XRIT.nuspec 10 | python update-tpl-release.py build/XRIT-rc.nuspec "${LIBVER%.*}" 11 | 12 | cd build 13 | 14 | nuget pack XRIT-rc.nuspec 15 | -------------------------------------------------------------------------------- /XRIT/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | msbuild /p:Configuration=Release 4 | cp bin/Release/XRIT.dll build/lib/net45/ 5 | cp bin/Release/XRIT.dll build/lib/net452/ 6 | LIBVER=`monodis --assembly bin/Release/XRIT.dll |grep Version | cut -d: -f2 | sed -e 's/^[[:space:]]*//'` 7 | 8 | 9 | echo "Current Version: ${LIBVER%.*}" 10 | # sed "s/|{|VERSION|}|/${LIBVER%.*}/g" XRIT.nuspec.tpl > XRIT.nuspec 11 | python update-tpl-release.py build/XRIT.nuspec "${LIBVER%.*}" 12 | 13 | cd build 14 | nuget pack XRIT.nuspec -verbosity detailed 15 | -------------------------------------------------------------------------------- /XRIT/build/XRIT.nuspec.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenSatelliteProject.XRIT 5 | |{|VERSION|}| 6 | XRIT Library 7 | Lucas Teske 8 | Lucas Teske 9 | https://github.com/opensatelliteproject/goesdump/blob/master/XRIT/LICENSE 10 | https://github.com/opensatelliteproject/goesdump/ 11 | https://github.com/opensatelliteproject/goesdump/raw/master/goesdump/icon.png 12 | true 13 | xRIT File / Packet Processing Library 14 | 15 | |{|RELEASE|}| 16 | 17 | Copyright 2018 18 | GOES XRIT NOAA Satellite OpenSatelliteProject OSP SDR Ingestor 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /XRIT/build/build/OpenSatelliteProject.XRIT.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | x86 9 | 10 | 11 | 12 | 13 | $(PrepareForRunDependsOn); 14 | CopyNativeBinaries 15 | 16 | 17 | 18 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /XRIT/build/build/x86/COPYING-libaec: -------------------------------------------------------------------------------- 1 | Copyright 2012 - 2016 2 | 3 | Mathis Rosenhauer, Moritz Hanke, Joerg Behrens 4 | Deutsches Klimarechenzentrum GmbH 5 | Bundesstr. 45a 6 | 20146 Hamburg 7 | Germany 8 | 9 | Luis Kornblueh 10 | Max-Planck-Institut fuer Meteorologie 11 | Bundesstr. 53 12 | 20146 Hamburg 13 | Germany 14 | 15 | All rights reserved. 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions 19 | are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright 22 | notice, this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright 24 | notice, this list of conditions and the following disclaimer in the 25 | documentation and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | -------------------------------------------------------------------------------- /XRIT/build/build/x86/COPYING-satdecompress: -------------------------------------------------------------------------------- 1 | Source: https://github.com/opensatelliteproject/decompressor 2 | -------------------------------------------------------------------------------- /XRIT/build/build/x86/aec.dl_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/build/build/x86/aec.dl_ -------------------------------------------------------------------------------- /XRIT/build/build/x86/satdecompress.dl_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/build/build/x86/satdecompress.dl_ -------------------------------------------------------------------------------- /XRIT/build/build/x86/sqlite3.dl_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/build/build/x86/sqlite3.dl_ -------------------------------------------------------------------------------- /XRIT/build/build/x86/szip.dl_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/XRIT/build/build/x86/szip.dl_ -------------------------------------------------------------------------------- /XRIT/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /XRIT/update-tpl-release.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | if len(sys.argv) < 3: 6 | print "Missing output name" 7 | exit(1) 8 | 9 | outputname = sys.argv[1] 10 | version = sys.argv[2] 11 | 12 | f = open("git-log.txt", "r") 13 | gitlog = f.read().replace("\n", "\n ").strip() 14 | f.close() 15 | 16 | f = open("build/XRIT.nuspec.tpl", "r") 17 | tpl = f.read() 18 | f.close() 19 | 20 | tpl = tpl.replace("|{|RELEASE|}|", gitlog) 21 | tpl = tpl.replace("|{|VERSION|}|", version) 22 | 23 | f = open(outputname, "w") 24 | f.write(tpl) 25 | f.close() -------------------------------------------------------------------------------- /goesdump.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /goesdump/.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | obj/* 3 | Content/bin 4 | Content/obj 5 | -------------------------------------------------------------------------------- /goesdump/GOES Dumper.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {E1B44542-24FF-409C-A2A3-237A00A8520D} 7 | Exe 8 | OpenSatelliteProject 9 | GOES Dumper 10 | v4.5 11 | 1.3.0 12 | 13 | 14 | Icon.ico 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug 21 | DEBUG; 22 | 4 23 | 24 | 25 | false 26 | bin\Release 27 | 4 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ..\packages\WebSocketSharp.1.0.3-rc11\lib\websocket-sharp.dll 39 | 40 | 41 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | {31BC62BD-1EE9-4B14-A931-19C572126A51} 80 | XRIT 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /goesdump/GoesDecoder/Statistics.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace OpenSatelliteProject { 4 | 5 | [StructLayout(LayoutKind.Sequential, Size = 4167, Pack = 1)] 6 | public struct Statistics_st { 7 | 8 | public byte scid; 9 | 10 | public byte vcid; 11 | 12 | public ulong packetNumber; 13 | 14 | public ushort vitErrors; 15 | 16 | public ushort frameBits; 17 | 18 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 19 | public int[] rsErrors; 20 | 21 | public byte signalQuality; 22 | 23 | public byte syncCorrelation; 24 | 25 | public byte phaseCorrection; 26 | 27 | public ulong lostPackets; 28 | 29 | public ushort averageVitCorrections; 30 | 31 | public byte averageRSCorrections; 32 | 33 | public ulong droppedPackets; 34 | 35 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] 36 | public long[] receivedPacketsPerChannel; 37 | 38 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] 39 | public long[] lostPacketsPerChannel; 40 | 41 | public ulong totalPackets; 42 | 43 | public uint startTime; 44 | 45 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 46 | public byte[] syncWord; 47 | 48 | public byte frameLock; 49 | 50 | public byte demodulatorFifoUsage; 51 | 52 | public byte decoderFifoUsage; 53 | 54 | public static Statistics_st fromByteArray(byte[] data) { 55 | var handle = GCHandle.Alloc(data, GCHandleType.Pinned); 56 | var stuff = (Statistics_st)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Statistics_st)); 57 | handle.Free(); 58 | return stuff; 59 | } 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /goesdump/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/goesdump/Icon.ico -------------------------------------------------------------------------------- /goesdump/Models/BaseModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace OpenSatelliteProject { 5 | public class BaseModel { 6 | 7 | public string DataType { get; set; } 8 | 9 | public BaseModel(string type) { this.DataType = type; } 10 | public string toJSON() { 11 | return JsonConvert.SerializeObject(this); 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /goesdump/Models/ConfigEntryModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenSatelliteProject { 5 | public class ConfigEntryModel: BaseModel { 6 | public Dictionary Configuration { get; set; } 7 | 8 | public ConfigEntryModel(Dictionary configuration) : base("configList") { 9 | this.Configuration = configuration; 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /goesdump/Models/ConsoleModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class ConsoleModel: BaseModel { 5 | public string message { get; set; } 6 | public string level { get; set; } 7 | 8 | public ConsoleModel(string level, string message) : base("console") { 9 | this.message = message; 10 | this.level = level; 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /goesdump/Models/ConstellationModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class ConstellationModel: BaseModel { 5 | 6 | public float[] data { get; set; } 7 | 8 | public ConstellationModel(float[] data) : base("constellationData") { 9 | this.data = data; 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /goesdump/Models/DirList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenSatelliteProject { 5 | public class DirList: BaseModel { 6 | public List Listing { get; set; } 7 | 8 | public DirList (List listing) : base("dirlist") { 9 | this.Listing = listing; 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /goesdump/Models/ModelType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public enum ModelType { 5 | STATISTICS_DATA = "statisticsData", 6 | CONSTELLATION_DATA = "constellationData" 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /goesdump/Models/StatisticsModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using OpenSatelliteProject.Tools; 4 | 5 | namespace OpenSatelliteProject { 6 | public class StatisticsModel: BaseModel { 7 | 8 | public int satelliteID { get; set; } 9 | public int virtualChannelID { get; set; } 10 | public UInt64 packetNumber { get; set; } 11 | public int totalBits { get; set; } 12 | public int viterbiErrors { get; set; } 13 | public int signalQuality { get; set; } 14 | public int syncCorrelation { get; set; } 15 | public int phaseCorrection { get; set; } 16 | public int[] reedSolomon { get; set; } 17 | public string syncWord { get; set; } 18 | public bool frameLock { get; set; } 19 | public DateTime startTime { get; set; } 20 | public TimeSpan runningTime { get; set; } 21 | 22 | public StatisticsModel(Statistics_st data) : base("statisticsData") { 23 | Refresh(data); 24 | } 25 | 26 | public void Refresh(Statistics_st data) { 27 | this.satelliteID = data.scid; 28 | this.virtualChannelID = data.vcid; 29 | this.packetNumber = data.packetNumber; 30 | this.totalBits = data.frameBits; 31 | this.viterbiErrors = data.vitErrors; 32 | this.signalQuality = data.signalQuality; 33 | this.syncCorrelation = data.syncCorrelation; 34 | if (data.syncWord != null) { 35 | this.syncWord = 36 | $"{data.syncWord[0]:X02}{data.syncWord[1]:X02}{data.syncWord[2]:X02}{data.syncWord[3]:X02}"; 37 | } else { 38 | this.syncWord = "00000000"; 39 | } 40 | this.reedSolomon = data.rsErrors; 41 | this.frameLock = data.frameLock > 0; 42 | this.startTime = LLTools.UnixTimeStampToDateTime(data.startTime); 43 | this.runningTime = DateTime.UtcNow.Subtract(startTime); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /goesdump/PacketData/NOAAProductId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenSatelliteProject.PacketData 5 | { 6 | public class NOAAProductId 7 | { 8 | } 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /goesdump/Program.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | #if MONOMAC 8 | using MonoMac.AppKit; 9 | using MonoMac.Foundation; 10 | #endif 11 | #endregion 12 | 13 | namespace OpenSatelliteProject { 14 | static class Program { 15 | 16 | 17 | private static HeadlessMain main; 18 | internal static void RunProg() { 19 | UIConsole.Log ("Starting GOES Dump"); 20 | main = new HeadlessMain(); 21 | main.Start(); 22 | } 23 | 24 | /// 25 | /// The main entry point for the application. 26 | /// 27 | #if !MONOMAC 28 | [STAThread] 29 | #endif 30 | static void Main(string[] args) { 31 | #if MONOMAC 32 | NSApplication.Init (); 33 | 34 | using (var p = new NSAutoreleasePool ()) { 35 | NSApplication.SharedApplication.Delegate = new AppDelegate(); 36 | NSApplication.Main(args); 37 | } 38 | #else 39 | RunProg(); 40 | #endif 41 | } 42 | 43 | } 44 | 45 | #if MONOMAC 46 | class AppDelegate : NSApplicationDelegate 47 | { 48 | public override void FinishedLaunching (MonoMac.Foundation.NSObject notification) 49 | { 50 | AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs a) => { 51 | if (a.Name.StartsWith("MonoMac")) { 52 | return typeof(MonoMac.AppKit.AppKitFramework).Assembly; 53 | } 54 | return null; 55 | }; 56 | Program.RunProg(); 57 | } 58 | 59 | public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender) 60 | { 61 | return true; 62 | } 63 | } 64 | #endif 65 | } 66 | 67 | -------------------------------------------------------------------------------- /goesdump/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("GOES Dumper")] 8 | [assembly: AssemblyDescription ("OpenSatelliteProject GOES Data Dumper")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("OpenSatelliteProject")] 11 | [assembly: AssemblyProduct ("GOES Dumper")] 12 | [assembly: AssemblyCopyright ("Lucas Teske")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("1.1.0")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /goesdump/Tools.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Reflection; 4 | using System.Linq; 5 | 6 | namespace OpenSatelliteProject { 7 | public static class Tools { 8 | 9 | 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /goesdump/WebManager/ConfigEntryInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class ConfigEntryInfo { 5 | public string Name { get; set; } 6 | public object Value { get; set; } 7 | public string Type { get; set; } 8 | public string Description { get; set; } 9 | public object DefaultValue { get; set; } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /goesdump/WebManager/DHInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenSatelliteProject { 4 | public class DHInfo { 5 | public string Name { get; set; } 6 | public string Path { get; set; } 7 | public int LastModified { get; set; } 8 | public long Size { get; set; } 9 | public bool IsFile { get; set; } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /goesdump/WebManager/WSHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WebSocketSharp.Server; 3 | using WebSocketSharp; 4 | using System.Collections.Generic; 5 | using Newtonsoft.Json.Linq; 6 | using Newtonsoft.Json; 7 | 8 | namespace OpenSatelliteProject { 9 | public class WSHandler: WebSocketBehavior { 10 | 11 | public DirectoryHandler dh { get; set; } 12 | 13 | protected override void OnMessage(MessageEventArgs e) { 14 | var d = e.Data; 15 | try { 16 | var json = (JObject)JsonConvert.DeserializeObject (d); 17 | if (json["type"] != null) { 18 | var type = (string)json["type"]; 19 | switch (type) { 20 | case "config": 21 | var variable = (string)json["variable"]; 22 | var value = (string)json["value"]; 23 | UIConsole.Debug($"Received config change request of {variable} to {value}"); 24 | EventMaster.Post(EventTypes.ConfigChangeEvent, new ConfigChangeEventData { Name = variable, Value = value }); 25 | break; 26 | case "dirlist": 27 | var path = (string)json["path"]; 28 | UIConsole.Debug($"Received request for listing folder {path}"); 29 | if (dh != null) { 30 | var list = dh.ListDir(path); 31 | var dl = new DirList(list); 32 | Send(dl.toJSON()); 33 | } 34 | break; 35 | case "configList": 36 | var configList = ProgConfig.GetConfig(); 37 | UIConsole.Debug("Received request for listing config."); 38 | try { 39 | var cl = new ConfigEntryModel(configList); 40 | Send(cl.toJSON()); 41 | } catch (Exception ex) { 42 | UIConsole.Error($"Error serializing configList: {ex}"); 43 | } 44 | break; 45 | } 46 | } 47 | } catch (Exception) { 48 | UIConsole.Debug ($"Received invalid message from ws client: {d}"); 49 | } 50 | } 51 | 52 | protected override void OnOpen() { 53 | List messages = HeadlessMain.GetCachedMessages; 54 | for (int i = 0; i < messages.Count; i++) { 55 | ConsoleModel cm = new ConsoleModel(messages[i].Priority.ToString(), messages[i].Message); 56 | Send(cm.toJSON()); 57 | } 58 | } 59 | 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /goesdump/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/goesdump/icon.png -------------------------------------------------------------------------------- /goesdump/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /overlays/goes13-fulldisk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/overlays/goes13-fulldisk.jpg -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/screenshot.png -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | .idea 23 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "goesdump-web", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "chart.js": "^2.6.0", 7 | "classlist-polyfill": "^1.2.0", 8 | "fbemitter": "^2.1.1", 9 | "immutability-helper": "^2.2.2", 10 | "material-ui": "^0.18.1", 11 | "moment": "^2.18.1", 12 | "rc-progress": "^2.1.2", 13 | "react": "^15.5.4", 14 | "react-chartjs-2": "^2.1.0", 15 | "react-dom": "^15.5.4", 16 | "react-flexbox-grid": "^1.1.3", 17 | "react-list": "^0.8.6", 18 | "react-material-icons": "git+https://github.com/mikamaunula/react-material-icons.git", 19 | "react-router-dom": "^4.1.1", 20 | "react-scroll-box": "^0.3.3-beta", 21 | "react-scrollbar": "^0.5.1", 22 | "react-tap-event-plugin": "^2.0.1", 23 | "react-tooltip": "^3.3.0" 24 | }, 25 | "devDependencies": { 26 | "electron": "^1.6.10", 27 | "react-scripts": "1.0.6" 28 | }, 29 | "main": "electron-starter.js", 30 | "scripts": { 31 | "start": "react-scripts start", 32 | "build": "react-scripts build && cp src/electron-starter.js build/", 33 | "test": "react-scripts test --env=jsdom", 34 | "eject": "react-scripts eject", 35 | "elec": "./node_modules/.bin/electron ." 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /web/public/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-144x144.png -------------------------------------------------------------------------------- /web/public/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-192x192.png -------------------------------------------------------------------------------- /web/public/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-36x36.png -------------------------------------------------------------------------------- /web/public/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-48x48.png -------------------------------------------------------------------------------- /web/public/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-72x72.png -------------------------------------------------------------------------------- /web/public/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/android-icon-96x96.png -------------------------------------------------------------------------------- /web/public/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-114x114.png -------------------------------------------------------------------------------- /web/public/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-120x120.png -------------------------------------------------------------------------------- /web/public/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-144x144.png -------------------------------------------------------------------------------- /web/public/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-152x152.png -------------------------------------------------------------------------------- /web/public/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-180x180.png -------------------------------------------------------------------------------- /web/public/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-57x57.png -------------------------------------------------------------------------------- /web/public/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-60x60.png -------------------------------------------------------------------------------- /web/public/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-72x72.png -------------------------------------------------------------------------------- /web/public/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-76x76.png -------------------------------------------------------------------------------- /web/public/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon-precomposed.png -------------------------------------------------------------------------------- /web/public/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/apple-icon.png -------------------------------------------------------------------------------- /web/public/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/blank.gif -------------------------------------------------------------------------------- /web/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /web/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/favicon-16x16.png -------------------------------------------------------------------------------- /web/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/favicon-32x32.png -------------------------------------------------------------------------------- /web/public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/favicon-96x96.png -------------------------------------------------------------------------------- /web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/favicon.ico -------------------------------------------------------------------------------- /web/public/file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/file.gif -------------------------------------------------------------------------------- /web/public/folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/folder.gif -------------------------------------------------------------------------------- /web/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 23 | Open Satellite Project 24 | 25 | 26 | 29 |
30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /web/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "OSP", 3 | "name": "Open Satellite Project", 4 | "icons": [ 5 | { 6 | "src": "\/android-icon-36x36.png", 7 | "sizes": "36x36", 8 | "type": "image\/png", 9 | "density": "0.75" 10 | }, 11 | { 12 | "src": "\/android-icon-48x48.png", 13 | "sizes": "48x48", 14 | "type": "image\/png", 15 | "density": "1.0" 16 | }, 17 | { 18 | "src": "\/android-icon-72x72.png", 19 | "sizes": "72x72", 20 | "type": "image\/png", 21 | "density": "1.5" 22 | }, 23 | { 24 | "src": "\/android-icon-96x96.png", 25 | "sizes": "96x96", 26 | "type": "image\/png", 27 | "density": "2.0" 28 | }, 29 | { 30 | "src": "\/android-icon-144x144.png", 31 | "sizes": "144x144", 32 | "type": "image\/png", 33 | "density": "3.0" 34 | }, 35 | { 36 | "src": "\/android-icon-192x192.png", 37 | "sizes": "192x192", 38 | "type": "image\/png", 39 | "density": "4.0" 40 | } 41 | ], 42 | "start_url": "./index.html", 43 | "display": "standalone", 44 | "theme_color": "#000000", 45 | "background_color": "#ffffff" 46 | } 47 | -------------------------------------------------------------------------------- /web/public/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/ms-icon-144x144.png -------------------------------------------------------------------------------- /web/public/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/ms-icon-150x150.png -------------------------------------------------------------------------------- /web/public/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/ms-icon-310x310.png -------------------------------------------------------------------------------- /web/public/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web/public/ms-icon-70x70.png -------------------------------------------------------------------------------- /web/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .rotating-atom { 11 | animation: App-logo-spin infinite 20s linear; 12 | height: 80px; 13 | } 14 | 15 | .rotation-fast { 16 | animation: App-logo-spin-rev infinite 1s linear 17 | } 18 | 19 | .drawer-icon { 20 | animation: App-logo-spin infinite 20s linear; 21 | height: 48px; 22 | cursor: pointer; 23 | } 24 | 25 | .card-header { 26 | background: #46B6AC; 27 | } 28 | 29 | .menu-icon { 30 | padding-top: 10px; 31 | margin-bottom: -5px; 32 | margin-right: 15px; 33 | } 34 | 35 | .statistics-ul { 36 | padding: 0; 37 | margin-top: 0; 38 | list-style-type: none; 39 | line-height: 18px; 40 | color: rgba(0,0,0,.54); 41 | } 42 | 43 | .led-block { 44 | display: -webkit-box; 45 | display: -moz-box; 46 | display: -ms-flexbox; 47 | display: -webkit-flex; 48 | display: flex; 49 | align-items: center; 50 | justify-content: center; 51 | flex-direction: column; 52 | height: 250px; 53 | } 54 | 55 | .led-block-item { 56 | } 57 | 58 | .statistics li { 59 | height:18px; 60 | padding: 0 0 0 0; 61 | font-family: "Verdana", sans-serif; 62 | } 63 | 64 | .statistics-val { 65 | float: right; 66 | } 67 | 68 | .console-card { 69 | position: relative; 70 | width: 100%; 71 | height: 500px; 72 | } 73 | 74 | .console-area { 75 | height: 400px; 76 | } 77 | 78 | .console-text { 79 | font-family: "Lucida Console", monospace; 80 | } 81 | 82 | .clickable { 83 | cursor: pointer; 84 | } 85 | 86 | @keyframes App-logo-spin { 87 | from { transform: rotate(0deg); } 88 | to { transform: rotate(360deg); } 89 | } 90 | 91 | @keyframes App-logo-spin-rev { 92 | from { transform: rotate(360deg); } 93 | to { transform: rotate(0deg); } 94 | } 95 | 96 | .footer { 97 | position: fixed; 98 | text-align: right; 99 | bottom: 15px; 100 | right: 15px; 101 | font-size: 10px; 102 | color: #9E9E9E; 103 | } 104 | 105 | .footer a { 106 | color: #9E9E9E; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /web/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /web/src/Components/BarElementRight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 27/05/17. 3 | * @flow 4 | */ 5 | import React, { Component } from 'react'; 6 | import '../Components/Led.css'; 7 | 8 | import GPSNotFixed from 'react-material-icons/icons/device/gps-not-fixed'; 9 | import GPSFixed from 'react-material-icons/icons/device/gps-fixed'; 10 | import PortableWifiOff from 'react-material-icons/icons/communication/portable-wifi-off'; 11 | import WifiTethering from 'react-material-icons/icons/device/wifi-tethering'; 12 | import Cached from 'react-material-icons/icons/action/cached'; 13 | 14 | import Wifi0Icon from 'react-material-icons/icons/device/signal-wifi-0-bar'; 15 | import Wifi1Icon from 'react-material-icons/icons/device/signal-wifi-1-bar'; 16 | import Wifi2Icon from 'react-material-icons/icons/device/signal-wifi-2-bar'; 17 | import Wifi3Icon from 'react-material-icons/icons/device/signal-wifi-3-bar'; 18 | import Wifi4Icon from 'react-material-icons/icons/device/signal-wifi-4-bar'; 19 | import ReactTooltip from 'react-tooltip' 20 | 21 | import '../App.css'; 22 | 23 | const iconStyle = { 24 | marginRight: 15, 25 | }; 26 | 27 | const divStyle = { 28 | display: 'flex', 29 | alignItems: 'center', 30 | height: 50, 31 | marginRight: 15, 32 | }; 33 | 34 | class BarElementRight extends Component { 35 | 36 | constructor(props) { 37 | super(props); 38 | 39 | this.state = { 40 | signalQuality: 0, 41 | frameLock: false, 42 | websocket: this.props.ospConn.isConnected, 43 | satelliteBusy: false, 44 | loading: false, 45 | }; 46 | 47 | this.props.ospConn.on('wsConnected', () => this.handleConnection(true)); 48 | this.props.ospConn.on('wsDisconnected', () => this.handleConnection(false)); 49 | this.props.ospConn.on('statistics', this.handleStatistics.bind(this)); 50 | this.props.ospConn.on('loadStatus', this.handleLoading.bind(this)); 51 | } 52 | 53 | handleLoading(status) { 54 | this.setState({ 55 | loading: status, 56 | }); 57 | } 58 | 59 | handleStatistics(data) { 60 | if (this.refresh) { 61 | console.log(data.frameLock); 62 | this.setState({ 63 | frameLock: data.frameLock, 64 | satelliteBusy: data.virtualChannelID !== 63, 65 | signalQuality: data.signalQuality, 66 | }); 67 | } 68 | } 69 | 70 | handleConnection(connected) { 71 | if (this.refresh) { 72 | this.setState({ 73 | websocket: connected, 74 | frameLock: connected ? this.state.frameLock : false, 75 | satelliteBusy: connected ? this.state.satelliteBusy : false, 76 | }); 77 | } 78 | } 79 | 80 | componentDidMount() { 81 | this.refresh = true; 82 | } 83 | 84 | componentWillUnmount () { 85 | this.refresh = false; 86 | } 87 | 88 | render() { 89 | let signalLevel = []; 90 | const signal = this.state.signalQuality; 91 | 92 | if (signal > 90) { 93 | signalLevel = []; 94 | } else if (signal > 70) { 95 | signalLevel = []; 96 | } else if (signal > 50) { 97 | signalLevel = []; 98 | } else if (signal > 40) { 99 | signalLevel = []; 100 | } 101 | 102 | return ( 103 |
104 |
105 |

106 | {signalLevel} 107 |

108 |

109 | { 110 | this.state.frameLock ? () : () 111 | } 112 |

113 |

114 | { 115 | this.state.websocket ? () : () 116 | } 117 |

118 |

119 | { 120 | this.state.loading ? () : () 121 | } 122 |

123 | 124 | Signal Quality Icon
125 | This represents the signal quality 126 |
127 | 128 | FrameLock Icon
129 | This represents the frame lock status 130 |
131 | 132 | WebSocket Icon
133 | This represents the connection with the server 134 |
135 | 136 | Syncing Icon
137 | This will rotate when something is loading. 138 |
139 |
140 |
141 | ) 142 | } 143 | } 144 | 145 | export default BarElementRight; -------------------------------------------------------------------------------- /web/src/Components/Constellation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 24/05/17. 3 | * @flow 4 | */ 5 | 6 | import React, { Component } from 'react'; 7 | 8 | class Constellation extends Component { 9 | 10 | constructor(props) { 11 | super(props); 12 | this.points = []; 13 | this.refreshCanvas = this.refreshCanvas.bind(this); 14 | } 15 | 16 | componentDidMount() { 17 | this.canvas = this.refs.canvas; 18 | this.ctx = this.canvas.getContext("2d"); 19 | this.refreshCanvas(); 20 | } 21 | 22 | refreshCanvas(points) { 23 | if (points !== undefined) { 24 | this.points = points; 25 | } 26 | const size = this.props.size; 27 | const numPoints = this.points.length; 28 | this.ctx.clearRect(0, 0, size, size); 29 | // Draw grid 30 | this.ctx.strokeStyle = 'rgba(190, 190, 190, 1)'; 31 | this.ctx.moveTo(0, size / 2); 32 | this.ctx.lineTo(size, size / 2); 33 | this.ctx.stroke(); 34 | this.ctx.moveTo(size / 2, 0); 35 | this.ctx.lineTo(size / 2, size); 36 | this.ctx.stroke(); 37 | 38 | // Draw points 39 | this.ctx.strokeStyle = 'rgba(0, 0, 0, 1)'; 40 | for (let i = 0; i < numPoints; i += 2) { 41 | // Comes flipped 42 | const Q = (this.points[i] * size) / 2; 43 | const I = (this.points[i + 1] * size) / 2; 44 | 45 | const x = I + size / 2; 46 | const y = Q + size / 2; 47 | 48 | this.ctx.beginPath(); 49 | this.ctx.arc(~~x, ~~y, 2, 0, 2 * Math.PI); 50 | this.ctx.stroke(); 51 | } 52 | } 53 | 54 | render() { 55 | return ( 56 | 60 | Your browser does not support canvas. 61 | 62 | ) 63 | } 64 | } 65 | 66 | Constellation.defaultProps = { 67 | size: 240, 68 | }; 69 | 70 | export default Constellation; -------------------------------------------------------------------------------- /web/src/Components/TopBar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 28/05/17. 3 | * @flow 4 | */ 5 | 6 | import React, { Component } from 'react'; 7 | import Badge from 'material-ui/Badge'; 8 | import { 9 | AppBar, 10 | }from 'material-ui'; 11 | 12 | import atom from '../atom.svg'; 13 | import '../App.css'; 14 | import BarElementRight from './BarElementRight'; 15 | 16 | class TopBar extends Component { 17 | 18 | constructor(props) { 19 | super(props); 20 | 21 | this.state = { 22 | consoleNotifications: 0, 23 | chartsNotifications: 0, 24 | dashboardNotifications: 0, 25 | }; 26 | 27 | this.notifyCharts = this.notifyCharts.bind(this); 28 | this.notifyConsole = this.notifyConsole.bind(this); 29 | this.notifyDashboard = this.notifyDashboard.bind(this); 30 | 31 | this.props.ospConn.on('consoleMessage', ([ level, message ]) => { 32 | const currentPath = this.props.router.history.location.pathname; 33 | if ((level === 'ERROR' || level === 'WARN') && currentPath !== '/console') { 34 | this.notifyConsole(); 35 | } 36 | }); 37 | } 38 | 39 | notifyConsole() { 40 | this.setState({ consoleNotifications: this.state.consoleNotifications + 1 }); 41 | } 42 | 43 | notifyDashboard() { 44 | this.setState({ dashboardNotifications: this.state.dashboardNotifications + 1 }); 45 | } 46 | 47 | notifyCharts() { 48 | this.setState({ chartsNotifications: this.state.chartsNotifications + 1 }); 49 | } 50 | 51 | clearConsoleNotification() { 52 | this.setState({ consoleNotifications: 0 }); 53 | } 54 | 55 | clearDashboardNotification() { 56 | this.setState({ dashboardNotifications: 0 }); 57 | } 58 | 59 | clearChartsNotification() { 60 | this.setState({ chartsNotifications: 0 }); 61 | } 62 | 63 | componentDidMount() { 64 | this.refresh = true; 65 | } 66 | 67 | componentWillUnmount () { 68 | this.refresh = false; 69 | } 70 | 71 | render() { 72 | const totalNotifications = this.state.consoleNotifications + this.state.chartsNotifications + this.state.dashboardNotifications; 73 | return ( 74 | Open Satellite Project - {this.props.title}} 76 | onLeftIconButtonTouchTap={this.props.toggleDrawer} 77 | onTitleTouchTap={this.props.toggleDrawer} 78 | iconElementLeft={ 79 | 0 ? 'flex' : 'none'}} 83 | style={{height: 60, padding: '0 0 0 0', marginRight: 20, top: 0 }} 84 | > 85 | Menu Icon 86 | 87 | } 88 | iconElementRight={} 89 | /> 90 | ) 91 | } 92 | } 93 | 94 | export default TopBar; -------------------------------------------------------------------------------- /web/src/Controllers/Console.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 25/05/17. 3 | * @flow 4 | */ 5 | import 'classlist-polyfill'; 6 | import React, { Component } from 'react'; 7 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 8 | import { Card, CardHeader, CardText } from 'material-ui/Card'; 9 | 10 | const MAXLINES = 15; 11 | 12 | class Console extends Component { 13 | 14 | constructor(props) { 15 | super(props); 16 | this.props.ospConn.on('consoleMessage', this.handleConsoleMessage.bind(this)); 17 | this.state = { 18 | messages: [], 19 | } 20 | } 21 | 22 | handleConsoleMessage(data) { 23 | if (this.refresh) { 24 | const msgs = this.state.messages; 25 | const now = new Date(); 26 | let textColor; 27 | 28 | if (msgs.length > MAXLINES) { 29 | msgs.splice(0, 1); 30 | } 31 | 32 | switch (data[0]) { 33 | case "INFO": 34 | textColor = "blue"; 35 | break; 36 | case "WARN": 37 | textColor = "yellow"; 38 | break; 39 | case "ERROR": 40 | textColor = "red"; 41 | break; 42 | case "DEBUG": 43 | textColor = "brown"; 44 | break; 45 | default: 46 | textColor = "blue"; 47 | break; 48 | } 49 | 50 | const message = `${now.toLocaleTimeString()}/${String(" " + data[0]).slice(-5)} ${data[1]}`; 51 | 52 | msgs.push({ 53 | color: textColor, 54 | message, 55 | }); 56 | 57 | this.setState({messages: msgs}); 58 | } 59 | } 60 | 61 | componentDidMount() { 62 | this.refresh = true; 63 | this.props.setTitle('Console'); 64 | this.setState({ 65 | messages: this.props.messageCache(), 66 | }); 67 | } 68 | 69 | componentWillUnmount () { 70 | this.refresh = false; 71 | } 72 | 73 | render() { 74 | let messages = []; 75 | for (let i = 0; i < this.state.messages.length; i++) { 76 | const msg = this.state.messages[i]; 77 | messages.push( 78 | {msg.message}
79 | ); 80 | } 81 | 82 | return ( 83 | 84 |
85 | 86 | 92 | 93 |
94 | {messages} 95 |
96 |
97 |
98 |
99 |
100 | ); 101 | } 102 | } 103 | 104 | export default Console; 105 | -------------------------------------------------------------------------------- /web/src/Controllers/Explorer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 27/05/17. 3 | * @flow 4 | */ 5 | import 'classlist-polyfill'; 6 | import React, { Component } from 'react'; 7 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 8 | import { Link } from 'react-router-dom'; 9 | import moment from 'moment'; 10 | 11 | const hrsSuffix = ["B", "KB", "MB", "GB", "TB", "PB", "EB"]; 12 | 13 | const logN = (v, b) => { 14 | return Math.log(v)/(b ? Math.log(b) : 1); 15 | }; 16 | 17 | const BytesToString = (byteCount) => { 18 | 19 | if (byteCount === 0) { 20 | return "0" + hrsSuffix[0]; 21 | } 22 | 23 | const bytes = Math.abs(byteCount); 24 | const place = Math.floor(logN(bytes, 1024)); 25 | const num = Math.round(bytes / Math.pow(1024, place)); 26 | return (Math.sign(byteCount) * num).toString() + hrsSuffix[place]; 27 | }; 28 | 29 | class Explorer extends Component { 30 | 31 | constructor(props) { 32 | super(props); 33 | this.props.ospConn.on('dirList', this.handleListReception.bind(this)); 34 | this.state = { 35 | data: [], 36 | curPath: '', 37 | nextPath: this.props.location.pathname.replace('/explorer', '') , 38 | }; 39 | } 40 | 41 | handleListReception(data) { 42 | if (this.refresh) { 43 | this.setState({ 44 | data, 45 | curPath: this.state.nextPath, 46 | }); 47 | this.props.setTitle(`Explorer - ${this.state.nextPath}`); 48 | } 49 | } 50 | 51 | componentDidMount() { 52 | this.refresh = true; 53 | this.props.setTitle('Explorer'); 54 | if (this.props.ospConn.isConnected) { 55 | this.switchFolder(this.state.nextPath); 56 | } else { 57 | this.props.ospConn.on('wsConnected', () => { 58 | this.switchFolder(this.state.nextPath); 59 | }); 60 | } 61 | 62 | window.onpopstate = this.onBackButtonEvent.bind(this); 63 | } 64 | onBackButtonEvent(e) { 65 | e.preventDefault(); 66 | this.switchFolder(this.props.location.pathname.replace('/explorer', '')); 67 | } 68 | 69 | componentWillUnmount () { 70 | this.refresh = false; 71 | } 72 | 73 | switchFolder(path) { 74 | console.log(`Switching folder to ${path}`); 75 | this.setState({ 76 | nextPath: path, 77 | }); 78 | this.props.ospConn.listDir(path); 79 | } 80 | 81 | render() { 82 | let files = []; 83 | for (let i = 0; i < this.state.data.length; i++) { 84 | const entry = this.state.data[i]; 85 | files.push( 86 | 87 | {entry.IsFile 88 | 89 | { 90 | !entry.IsFile ? 91 | ( { this.switchFolder(`/${entry.Path}`)}}>{entry.Name}) : 92 | ({entry.Name}) 93 | } 94 | 95 | {entry.LastModified !== -1 ? moment(entry.LastModified*1000).toString() : '-'} 96 | {entry.Size === -1 ? '-' : BytesToString(entry.Size)} 97 | 98 | ); 99 | } 100 | return ( 101 | 102 |
103 | 104 | 105 | 106 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | {files} 119 | 120 |
107 | Blank Icon 108 | NameLast modifiedSize

121 |
122 |
123 | ); 124 | } 125 | } 126 | 127 | export default Explorer; 128 | -------------------------------------------------------------------------------- /web/src/OSP/Connector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Lucas Teske on 24/05/17. 3 | * @flow 4 | */ 5 | 6 | import { EventEmitter } from 'fbemitter'; 7 | 8 | export default class OSPConnector extends EventEmitter { 9 | 10 | constructor(serverUrl) { 11 | super(); 12 | this.serverUrl = serverUrl.replace('http', 'ws').replace('https', 'wss') + '/mainws'; 13 | this._initWS(); 14 | this.isConnected = false; 15 | } 16 | 17 | _initWS() { 18 | this.ws = new WebSocket(this.serverUrl); 19 | this.ws.onopen = this.onOpen.bind(this); 20 | this.ws.onmessage = this.onMessage.bind(this); 21 | this.ws.onerror = this.onError.bind(this); 22 | this.ws.onclose = this.onClose.bind(this); 23 | } 24 | 25 | onOpen(event) { 26 | this.emit('consoleMessage', ["INFO", "Connected to Server"]); 27 | this.emit('wsConnected'); 28 | this.ws.send(JSON.stringify({ "method": "getCacheMessages"})); 29 | this.isConnected = true; 30 | } 31 | 32 | onMessage(event) { 33 | try { 34 | const data = JSON.parse(event.data); 35 | switch (data.DataType) { 36 | case "console": 37 | this.handleConsole(data); 38 | break; 39 | case "statisticsData": 40 | this.handleStatistics(data); 41 | break; 42 | case "constellationData": 43 | this.handleConstellation(data); 44 | break; 45 | case "dirlist": 46 | this.handleDirList(data); 47 | break; 48 | case "configList": 49 | this.handleConfigList(data); 50 | break; 51 | default: 52 | console.log(`OSPConnector -- Unknown DataType: ${data.DataType}`); 53 | break; 54 | } 55 | } catch (e) { 56 | console.log(`OSPConnector -- Error parsing message: ${e}`); 57 | } 58 | } 59 | 60 | onError(event) { 61 | this.emit('consoleMessage', ["ERROR", `There was an WebSocket error: ${JSON.stringify(event)}`]); 62 | console.log(`OSPConnector -- Error: ${event}`); 63 | } 64 | 65 | onClose(event) { 66 | this.emit('consoleMessage', ["INFO", "Connection to the server has been closed. Trying again in 2 seconds."]); 67 | this.emit('wsDisconnected'); 68 | this.isConnected = false; 69 | setTimeout(() => { 70 | this._initWS(); 71 | }, 2000); 72 | } 73 | 74 | handleStatistics(data) { 75 | this.emit('statistics', data); 76 | } 77 | 78 | handleConstellation(data) { 79 | this.emit('constellation', data.data); 80 | } 81 | 82 | handleConsole(data) { 83 | this.emit('consoleMessage', [ data.level, data.message ]); 84 | } 85 | 86 | handleDirList(data) { 87 | this.emit('loadStatus', false); 88 | this.emit('dirList', data.Listing); 89 | } 90 | 91 | handleConfigList(data) { 92 | this.emit('loadStatus', false); 93 | this.emit('configList', data.Configuration); 94 | } 95 | 96 | listDir(path) { 97 | console.log(`List dir path: ${path}`); 98 | this.emit('loadStatus', true); 99 | this.ws.send(JSON.stringify({ 100 | type: 'dirlist', 101 | path, 102 | })); 103 | } 104 | 105 | listConfig() { 106 | console.log('List config'); 107 | this.emit('loadStatus', true); 108 | this.ws.send(JSON.stringify({ type: 'configList' })); 109 | } 110 | 111 | updateConfig(name, value) { 112 | this.ws.send(JSON.stringify({ type: 'config', variable: name, value })); 113 | } 114 | 115 | on(...args) { 116 | this.addListener(...args); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /web/src/atom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /web/src/electron-starter.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | // Module to control application life. 3 | const app = electron.app 4 | const protocol = electron.protocol; 5 | // Module to create native browser window. 6 | const BrowserWindow = electron.BrowserWindow 7 | 8 | const path = require('path') 9 | const url = require('url') 10 | 11 | // Keep a global reference of the window object, if you don't, the window will 12 | // be closed automatically when the JavaScript object is garbage collected. 13 | let mainWindow 14 | 15 | function createWindow () { 16 | // Create the browser window. 17 | mainWindow = new BrowserWindow({width: 1200, height: 800}) 18 | 19 | // and load the index.html of the app. 20 | mainWindow.loadURL(url.format({ 21 | pathname: path.join(__dirname, 'index.html'), 22 | protocol: 'file:', 23 | slashes: true 24 | })); 25 | 26 | protocol.interceptFileProtocol('file', function(req, callback) { 27 | var url = req.url.substr(7); 28 | if (!url.match('index.html')) { 29 | callback({path: path.normalize(path.join(__dirname, url))}) 30 | } else { 31 | callback({path: url}) 32 | } 33 | }) 34 | 35 | //mainWindow.loadURL('http://localhost:3000'); 36 | 37 | // Open the DevTools. 38 | //mainWindow.webContents.openDevTools() 39 | 40 | // Emitted when the window is closed. 41 | mainWindow.on('closed', function () { 42 | // Dereference the window object, usually you would store windows 43 | // in an array if your app supports multi windows, this is the time 44 | // when you should delete the corresponding element. 45 | mainWindow = null 46 | }) 47 | } 48 | 49 | // This method will be called when Electron has finished 50 | // initialization and is ready to create browser windows. 51 | // Some APIs can only be used after this event occurs. 52 | app.on('ready', createWindow) 53 | 54 | // Quit when all windows are closed. 55 | app.on('window-all-closed', function () { 56 | // On OS X it is common for applications and their menu bar 57 | // to stay active until the user quits explicitly with Cmd + Q 58 | if (process.platform !== 'darwin') { 59 | app.quit() 60 | } 61 | }) 62 | 63 | app.on('activate', function () { 64 | // On OS X it's common to re-create a window in the app when the 65 | // dock icon is clicked and there are no other windows open. 66 | if (mainWindow === null) { 67 | createWindow() 68 | } 69 | }) 70 | 71 | // In this file you can include the rest of your app's specific main process 72 | // code. You can also put them in separate files and require them here. 73 | -------------------------------------------------------------------------------- /web/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /web/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import registerServiceWorker from './registerServiceWorker'; 5 | import './index.css'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /web/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /web/src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | export default function register() { 12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 13 | window.addEventListener('load', () => { 14 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 15 | navigator.serviceWorker 16 | .register(swUrl) 17 | .then(registration => { 18 | registration.onupdatefound = () => { 19 | const installingWorker = registration.installing; 20 | installingWorker.onstatechange = () => { 21 | if (installingWorker.state === 'installed') { 22 | if (navigator.serviceWorker.controller) { 23 | // At this point, the old content will have been purged and 24 | // the fresh content will have been added to the cache. 25 | // It's the perfect time to display a "New content is 26 | // available; please refresh." message in your web app. 27 | console.log('New content is available; please refresh.'); 28 | } else { 29 | // At this point, everything has been precached. 30 | // It's the perfect time to display a 31 | // "Content is cached for offline use." message. 32 | console.log('Content is cached for offline use.'); 33 | } 34 | } 35 | }; 36 | }; 37 | }) 38 | .catch(error => { 39 | console.error('Error during service worker registration:', error); 40 | }); 41 | }); 42 | } 43 | } 44 | 45 | export function unregister() { 46 | if ('serviceWorker' in navigator) { 47 | navigator.serviceWorker.ready.then(registration => { 48 | registration.unregister(); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /web_simple/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /web_simple/README.md: -------------------------------------------------------------------------------- 1 | WebUI 2 | ===== 3 | 4 | 5 | For downloading the needed packages run: `npm install` -------------------------------------------------------------------------------- /web_simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | OpenSatelliteProject xRIT Ingestor 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | Open Satellite Project 21 |
22 | 25 |
    26 |
  • About
  • 27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |

Statistics

36 |
37 |
38 |
    39 |
  • 40 | SC ID:
    0
    41 |
  • 42 |
  • 43 | VC ID:
    0
    44 |
  • 45 |
  • 46 | Packet Number:
    0
    47 |
  • 48 |
  • 49 | Viterbi Errors:
    0/0
    50 |
  • 51 |
  • 52 | Signal Quality:
    0
    53 |
  • 54 |
  • 55 | Sync Correlation:
    0
    56 |
  • 57 |
  • 58 | Phase Shift:
    0
    59 |
  • 60 |
  • 61 | Running Time:
    0
    62 |
  • 63 |
  • 64 | Reed Solomon:
    0 0 0 0
    65 |
  • 66 |
  • 67 | Sync Word:
    00000000
    68 |
  • 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |

Constellation

77 |
78 |
79 |
80 | 81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |

Status

89 |
90 |
91 |
92 |
93 |
94 |

Frame Lock

95 |
96 |
97 |
98 |

WebSocket

99 |
100 |
101 |
102 |

Satellite Busy

103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |

Console

114 |
115 |
116 | Console Here 117 |
118 |
119 |
120 |
121 |
122 |
123 | 124 | -------------------------------------------------------------------------------- /web_simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "goesdump-web", 3 | "version": "1.0.0", 4 | "description": "OpenSatelliteProject xRIT Ingestor WebUI", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Lucas Teske", 10 | "license": "MIT", 11 | "dependencies": { 12 | "jquery": "^3.1.1", 13 | "material-design-lite": "^1.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web_simple/static/2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web_simple/static/2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2 -------------------------------------------------------------------------------- /web_simple/static/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web_simple/static/blank.gif -------------------------------------------------------------------------------- /web_simple/static/file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web_simple/static/file.gif -------------------------------------------------------------------------------- /web_simple/static/folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensatelliteproject/goesdump/186a76f20c2622c357142284ec18eaeeb8cc7e9e/web_simple/static/folder.gif -------------------------------------------------------------------------------- /web_simple/static/leds.css: -------------------------------------------------------------------------------- 1 | /* From https://codepen.io/fskirschbaum/pen/MYJNaj */ 2 | .container { 3 | background-size: cover; 4 | background: rgb(226,226,226); /* Old browsers */ 5 | background: -moz-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(219,219,219,1) 50%, rgba(209,209,209,1) 51%, rgba(254,254,254,1) 100%); /* FF3.6+ */ 6 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(226,226,226,1)), color-stop(50%,rgba(219,219,219,1)), color-stop(51%,rgba(209,209,209,1)), color-stop(100%,rgba(254,254,254,1))); /* Chrome,Safari4+ */ 7 | background: -webkit-linear-gradient(top, rgba(226,226,226,1) 0%,rgba(219,219,219,1) 50%,rgba(209,209,209,1) 51%,rgba(254,254,254,1) 100%); /* Chrome10+,Safari5.1+ */ 8 | background: -o-linear-gradient(top, rgba(226,226,226,1) 0%,rgba(219,219,219,1) 50%,rgba(209,209,209,1) 51%,rgba(254,254,254,1) 100%); /* Opera 11.10+ */ 9 | background: -ms-linear-gradient(top, rgba(226,226,226,1) 0%,rgba(219,219,219,1) 50%,rgba(209,209,209,1) 51%,rgba(254,254,254,1) 100%); /* IE10+ */ 10 | background: linear-gradient(to bottom, rgba(226,226,226,1) 0%,rgba(219,219,219,1) 50%,rgba(209,209,209,1) 51%,rgba(254,254,254,1) 100%); /* W3C */ 11 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e2e2e2', endColorstr='#fefefe',GradientType=0 ); /* IE6-9 */ 12 | padding: 20px; 13 | } 14 | 15 | .led-box { 16 | height: 80px; 17 | width: 90px; 18 | margin: 10px 0; 19 | float: left; 20 | } 21 | 22 | .led-box p { 23 | font-size: 12px; 24 | text-align: center; 25 | margin: 1em; 26 | } 27 | 28 | .led-red { 29 | margin: 0 auto; 30 | width: 24px; 31 | height: 24px; 32 | background-color: #F00; 33 | border-radius: 50%; 34 | box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 12px; 35 | -webkit-animation: blinkRed 0.5s infinite; 36 | -moz-animation: blinkRed 0.5s infinite; 37 | -ms-animation: blinkRed 0.5s infinite; 38 | -o-animation: blinkRed 0.5s infinite; 39 | animation: blinkRed 0.5s infinite; 40 | } 41 | 42 | @-webkit-keyframes blinkRed { 43 | from { background-color: #F00; } 44 | 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} 45 | to { background-color: #F00; } 46 | } 47 | @-moz-keyframes blinkRed { 48 | from { background-color: #F00; } 49 | 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} 50 | to { background-color: #F00; } 51 | } 52 | @-ms-keyframes blinkRed { 53 | from { background-color: #F00; } 54 | 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} 55 | to { background-color: #F00; } 56 | } 57 | @-o-keyframes blinkRed { 58 | from { background-color: #F00; } 59 | 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} 60 | to { background-color: #F00; } 61 | } 62 | @keyframes blinkRed { 63 | from { background-color: #F00; } 64 | 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} 65 | to { background-color: #F00; } 66 | } 67 | 68 | .led-yellow { 69 | margin: 0 auto; 70 | width: 24px; 71 | height: 24px; 72 | background-color: #FF0; 73 | border-radius: 50%; 74 | box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 12px; 75 | -webkit-animation: blinkYellow 1s infinite; 76 | -moz-animation: blinkYellow 1s infinite; 77 | -ms-animation: blinkYellow 1s infinite; 78 | -o-animation: blinkYellow 1s infinite; 79 | animation: blinkYellow 1s infinite; 80 | } 81 | 82 | @-webkit-keyframes blinkYellow { 83 | from { background-color: #FF0; } 84 | 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } 85 | to { background-color: #FF0; } 86 | } 87 | @-moz-keyframes blinkYellow { 88 | from { background-color: #FF0; } 89 | 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } 90 | to { background-color: #FF0; } 91 | } 92 | @-ms-keyframes blinkYellow { 93 | from { background-color: #FF0; } 94 | 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } 95 | to { background-color: #FF0; } 96 | } 97 | @-o-keyframes blinkYellow { 98 | from { background-color: #FF0; } 99 | 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } 100 | to { background-color: #FF0; } 101 | } 102 | @keyframes blinkYellow { 103 | from { background-color: #FF0; } 104 | 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } 105 | to { background-color: #FF0; } 106 | } 107 | 108 | .led-green { 109 | margin: 0 auto; 110 | width: 24px; 111 | height: 24px; 112 | background-color: #ABFF00; 113 | border-radius: 50%; 114 | box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; 115 | } 116 | 117 | .led-blue { 118 | margin: 0 auto; 119 | width: 24px; 120 | height: 24px; 121 | background-color: #24E0FF; 122 | border-radius: 50%; 123 | box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #006 0 -1px 9px, #3F8CFF 0 2px 14px; 124 | } -------------------------------------------------------------------------------- /web_simple/static/main.css: -------------------------------------------------------------------------------- 1 | .console-card.mdl-card { 2 | width: 100%; 3 | } 4 | 5 | .console-card > .mdl-card__title { 6 | color: #fff; 7 | background: #46B6AC; 8 | } 9 | 10 | .main-grid { 11 | padding-bottom: 0; 12 | justify-content: center; 13 | } 14 | 15 | .main-grid-cell { 16 | } 17 | 18 | .statistics-ul { 19 | padding: 0; 20 | margin-top: 0; 21 | list-style-type: none; 22 | } 23 | 24 | .statistics li { 25 | height:18px; 26 | padding: 0 0 0 0; 27 | font-family: "Verdana", sans-serif; 28 | } 29 | 30 | .statistics-val { 31 | float: right; 32 | } 33 | 34 | .osp-card { 35 | height: 310px; 36 | } 37 | 38 | .osp-card > .mdl-card__title { 39 | color: #fff; 40 | background: #46B6AC; 41 | padding: 8px 16px; 42 | align-items: flex-start; 43 | } 44 | 45 | .led-holder { 46 | width: 50px; 47 | } 48 | 49 | .led-card-content { 50 | justify-content: center; 51 | text-align: center; 52 | vertical-align: middle; 53 | position: relative; 54 | height: 250px; 55 | } 56 | 57 | .led-block { 58 | position: absolute; 59 | top: 50%; 60 | left: 50%; 61 | width: 280px; 62 | height: 100px; 63 | transform: translate(-50%,-50%); 64 | } 65 | 66 | .constellation-holder { 67 | justify-content: center; 68 | text-align: center; 69 | vertical-align: middle; 70 | margin: auto; 71 | } -------------------------------------------------------------------------------- /web_simple/static/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | window.serverUrl = "ws://" + window.location.host + "/mainws"; 4 | 5 | var consoleMessages = []; 6 | var maxConsoleMessages = 10; 7 | var lastLockState = false; 8 | var lastSatteliteBusy = false; 9 | var constellationCtx; 10 | var constellationCanvas; 11 | var constellationPoints = []; 12 | var ws; 13 | function init() { 14 | consoleWrite("INFO", "Starting websocket"); 15 | 16 | setLedColor("led-frame-lock", "red"); 17 | setLedColor("led-websocket", "red"); 18 | setLedColor("led-satellite-busy", "red"); 19 | 20 | ws = new WebSocket(window.serverUrl); 21 | 22 | ws.onopen = function (e) { onOpen(e); } 23 | ws.onmessage = function (e) { onMessage(e); } 24 | ws.onerror = function (e) { onError(e); } 25 | ws.onclose = function (e) { onClose(e); } 26 | 27 | constellationCanvas = $("#constellation")[0]; 28 | constellationCtx = constellationCanvas.getContext("2d"); 29 | refreshConstellation(); 30 | } 31 | 32 | function refreshConstellation() { 33 | var ctx = constellationCtx; 34 | var width = constellationCanvas.width; 35 | var height = constellationCanvas.height; 36 | ctx.clearRect(0, 0, width, height); 37 | // Draw grid 38 | ctx.strokeStyle = 'rgba(190, 190, 190, 1)'; 39 | ctx.moveTo(0, height / 2); 40 | ctx.lineTo(width, height / 2); 41 | ctx.stroke(); 42 | ctx.moveTo(width / 2, 0); 43 | ctx.lineTo(width / 2, height); 44 | ctx.stroke(); 45 | 46 | // Draw points 47 | ctx.strokeStyle = 'rgba(0, 0, 0, 1)'; 48 | for (var i=0; i<1024; i+=2) { 49 | // Comes flipped 50 | var Q = (constellationPoints[i + 0] * height) / 2; 51 | var I = (constellationPoints[i + 1] * width) / 2; 52 | 53 | var x = I + width / 2; 54 | var y = Q + height / 2; 55 | ctx.beginPath(); 56 | ctx.arc(~~x, ~~y, 2, 0, 2 *Math.PI); 57 | ctx.stroke(); 58 | } 59 | } 60 | 61 | function onOpen(event) { 62 | consoleWrite("INFO", "Connected to Server"); 63 | setLedColor("led-websocket", "green"); 64 | ws.send(JSON.stringify({ 65 | "method": "getCacheMessages" 66 | })); 67 | } 68 | 69 | function setLedColor(led, color) { 70 | var colorClass = "led-blue"; 71 | switch (color) { 72 | case "blue": 73 | colorClass = "led-blue"; 74 | break; 75 | case "yellow": 76 | colorClass = "led-yellow"; 77 | break; 78 | case "green": 79 | colorClass = "led-green"; 80 | break; 81 | case "red": 82 | colorClass = "led-red"; 83 | break; 84 | } 85 | 86 | $("#" + led).attr('class', colorClass); 87 | } 88 | 89 | function onMessage(event) { 90 | var data = JSON.parse(event.data); 91 | switch (data.DataType) { 92 | case "console": 93 | handleConsole(data); 94 | break; 95 | case "statisticsData": 96 | handleStatistics(data); 97 | break; 98 | case "constellationData": 99 | handleConstellation(data); 100 | break; 101 | } 102 | } 103 | 104 | function onError(event) { 105 | consoleWrite("ERROR", "There was an WebSocket error: " + event); 106 | console.log("Error: ", event); 107 | } 108 | 109 | function onClose(event) { 110 | consoleWrite("INFO", "Connection to the server has been closed."); 111 | setLedColor("led-websocket", "red"); 112 | } 113 | 114 | function handleStatistics(data) { 115 | $("#field_scid").html(data.satelliteID); 116 | $("#field_vcid").html(data.virtualChannelID); 117 | $("#field_packetnumber").html(data.packetNumber); 118 | $("#field_framebits").html(data.totalBits); 119 | $("#field_viterrors").html(data.viterbiErrors); 120 | $("#field_signalquality").html(data.signalQuality); 121 | $("#field_synccorrelation").html(data.syncCorrelation); 122 | $("#field_phasecorrection").html(data.phaseCorrection); 123 | $("#field_rserror0").html(data.reedSolomon[0]); 124 | $("#field_rserror1").html(data.reedSolomon[1]); 125 | $("#field_rserror2").html(data.reedSolomon[2]); 126 | $("#field_rserror3").html(data.reedSolomon[3]); 127 | $("#field_runningtime").html(data.runningTime); 128 | $("#field_syncword").html(data.syncWord); 129 | if (data.frameLock != lastLockState) { 130 | lastLockState = data.frameLock; 131 | setLedColor("led-frame-lock", lastLockState ? "green" : "red"); 132 | } 133 | 134 | var satBusy = data.virtualChannelID != 63; 135 | if (satBusy != lastSatteliteBusy) { 136 | lastSatteliteBusy = satBusy; 137 | setLedColor("led-satellite-busy", lastSatteliteBusy ? "green" : "red"); 138 | } 139 | } 140 | 141 | function handleConstellation(data) { 142 | constellationPoints = data.data; 143 | refreshConstellation(); 144 | } 145 | 146 | function handleConsole(data) { 147 | consoleWrite(data.level, data.message); 148 | } 149 | 150 | function consoleClear() { 151 | $("#console-text").html(""); 152 | } 153 | 154 | function consoleWrite(level, message) { 155 | var textColor = "blue"; 156 | var logFunc = console.log; 157 | switch(level) { 158 | case "INFO": 159 | textColor = "blue"; 160 | logFunc = console.log; 161 | break; 162 | case "WARN": 163 | textColor = "yellow"; 164 | if (console.hasOwnProperty("warn")) { 165 | logFunc = console.warn; 166 | } 167 | break; 168 | case "ERROR": 169 | textColor = "red"; 170 | if (console.hasOwnProperty("error")) { 171 | logFunc = console.error; 172 | } 173 | break; 174 | case "DEBUG": 175 | textColor = "brown"; 176 | if (console.hasOwnProperty("debug")) { 177 | logFunc = console.debug; 178 | } 179 | break; 180 | default: 181 | level = "INFO"; 182 | logFunc = console.log; 183 | break; 184 | } 185 | 186 | var now = new Date(); 187 | 188 | message = now.toLocaleTimeString() + "/" + level + " " + message; 189 | 190 | logFunc(message); 191 | if (consoleMessages.length >= maxConsoleMessages) { 192 | consoleMessages.shift(); 193 | } 194 | 195 | consoleMessages.push('' + message + '
'); 196 | refreshConsoleUI(); 197 | } 198 | 199 | function refreshConsoleUI() { 200 | consoleClear(); 201 | for (var i in consoleMessages) { 202 | $("#console-text").append(consoleMessages[i]); 203 | } 204 | } 205 | 206 | if (!String.prototype.format) { 207 | String.prototype.format = function() { 208 | var args = arguments; 209 | return this.replace(/{(\d+)}/g, function(match, number) { 210 | return typeof args[number] != 'undefined' 211 | ? args[number] 212 | : match 213 | ; 214 | }); 215 | }; 216 | } 217 | 218 | window.addEventListener ("load", init, false); 219 | })(); -------------------------------------------------------------------------------- /web_simple/static/material-icons.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Material Icons'), local('MaterialIcons-Regular'), url(/static/2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2) format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } 24 | --------------------------------------------------------------------------------