├── LonScan ├── dev.ico ├── dev.png ├── plus.ico ├── plus.png ├── scope.ico ├── scope.png ├── App.config ├── ILMergeOrder.txt ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── packages.config ├── Extensions.cs ├── HexForm.cs ├── LonDeviceConfig.cs ├── Program.cs ├── DynamicXml.cs ├── ILMerge.props ├── HexForm.Designer.cs ├── PacketForgeDlg.cs ├── HexForm.resx ├── PacketForge.cs ├── LonScan.csproj ├── ScanForm.Designer.cs ├── XifFile.cs ├── DeviceForm.cs ├── PacketForgeDlg.Designer.cs ├── ScanForm.cs ├── LonScannerMain.cs ├── LonNetwork.cs ├── LonDevice.cs ├── DeviceForm.Designer.cs ├── LonScannerMain.Designer.cs ├── Config.cs └── DeviceForm.resx ├── .gitignore └── LonScan.sln /LonScan/dev.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/dev.ico -------------------------------------------------------------------------------- /LonScan/dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/dev.png -------------------------------------------------------------------------------- /LonScan/plus.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/plus.ico -------------------------------------------------------------------------------- /LonScan/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/plus.png -------------------------------------------------------------------------------- /LonScan/scope.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/scope.ico -------------------------------------------------------------------------------- /LonScan/scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/LonScan/master/LonScan/scope.png -------------------------------------------------------------------------------- /LonScan/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LonScan/ILMergeOrder.txt: -------------------------------------------------------------------------------- 1 | # this file contains the partial list of the merged assemblies in the merge order 2 | # you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build 3 | # and finetune merge order to your satisfaction 4 | 5 | -------------------------------------------------------------------------------- /LonScan/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Diese .gitignore-Datei wurde von Microsoft(R) Visual Studio automatisch erstellt. 3 | ################################################################################ 4 | 5 | /.vs/LonScan 6 | /LonScan/bin 7 | /LonScan/obj 8 | /packages 9 | -------------------------------------------------------------------------------- /LonScan/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LonScan.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29009.5 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LonScan", "LonScan\LonScan.csproj", "{DD1B0597-84AA-43F6-91C3-4166EED15AF4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DD1B0597-84AA-43F6-91C3-4166EED15AF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DD1B0597-84AA-43F6-91C3-4166EED15AF4}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DD1B0597-84AA-43F6-91C3-4166EED15AF4}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DD1B0597-84AA-43F6-91C3-4166EED15AF4}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {9F224627-7E7C-436F-9973-E9FC7CFB0464} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /LonScan/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace LonScan.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LonScan/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace LonScan 8 | { 9 | public static class Extensions 10 | { 11 | /* https://stackoverflow.com/questions/47815660/does-c-sharp-7-have-array-enumerable-destructuring */ 12 | public static void Deconstruct(this IEnumerable seq, out T first, out IEnumerable rest) 13 | { 14 | first = seq.FirstOrDefault(); 15 | rest = seq.Skip(1); 16 | } 17 | 18 | public static void Deconstruct(this IEnumerable seq, out T first, out T second, out IEnumerable rest) 19 | => (first, (second, rest)) = seq; 20 | public static void Deconstruct(this IEnumerable seq, out T first, out T second, out T third, out IEnumerable rest) 21 | => (first, second, (third, rest)) = seq; 22 | public static void Deconstruct(this IEnumerable seq, out T first, out T second, out T third, out T fourth, out IEnumerable rest) 23 | => (first, second, third, (fourth, rest)) = seq; 24 | public static void Deconstruct(this IEnumerable seq, out T first, out T second, out T third, out T fourth, out T fifth, out IEnumerable rest) 25 | => (first, second, third, fourth, (fifth, rest)) = seq; 26 | public static void Deconstruct(this IEnumerable seq, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth, out IEnumerable rest) 27 | => (first, second, third, fourth, fifth, (sixth, rest)) = seq; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LonScan/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die einer Assembly zugeordnet sind. 8 | [assembly: AssemblyTitle("LonScan")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("LonScan")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly 18 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("dd1b0597-84aa-43f6-91c3-4166eed15af4")] 24 | 25 | 26 | [assembly: AssemblyVersion(ThisAssembly.Git.BaseVersion.Major + "." + ThisAssembly.Git.BaseVersion.Minor + "." + ThisAssembly.Git.BaseVersion.Patch)] 27 | 28 | [assembly: AssemblyFileVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor + "." + ThisAssembly.Git.SemVer.Patch)] 29 | 30 | [assembly: AssemblyInformationalVersion( 31 | ThisAssembly.Git.SemVer.Major + "." + 32 | ThisAssembly.Git.SemVer.Minor + "." + 33 | ThisAssembly.Git.SemVer.Patch + "-" + 34 | ThisAssembly.Git.Branch + "+" + 35 | ThisAssembly.Git.Commit)] -------------------------------------------------------------------------------- /LonScan/HexForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace LonScan 12 | { 13 | public partial class HexForm : Form 14 | { 15 | public byte[] Data = null; 16 | 17 | public HexForm(byte[] data = null) 18 | { 19 | InitializeComponent(); 20 | if (data != null) 21 | { 22 | Data = data; 23 | string hex = BitConverter.ToString(data).Replace("-", " "); 24 | txtHex.Text = hex; 25 | } 26 | } 27 | 28 | public HexForm(string data) 29 | { 30 | InitializeComponent(); 31 | if (data != null) 32 | { 33 | Data = StringToByteArray(data.Replace(" ", "")); 34 | string hex = BitConverter.ToString(Data).Replace("-", " "); 35 | txtHex.Text = hex; 36 | } 37 | } 38 | 39 | public static byte[] StringToByteArray(string hex) 40 | { 41 | return Enumerable.Range(0, hex.Length) 42 | .Where(x => x % 2 == 0) 43 | .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) 44 | .ToArray(); 45 | } 46 | 47 | private void btnWrite_Click(object sender, EventArgs e) 48 | { 49 | string hex = txtHex.Text.Replace(" ", ""); 50 | 51 | if((hex.Length % 2) != 0) 52 | { 53 | return; 54 | } 55 | 56 | Data = StringToByteArray(hex); 57 | 58 | DialogResult = DialogResult.OK; 59 | Close(); 60 | } 61 | 62 | private void btnCancel_Click(object sender, EventArgs e) 63 | { 64 | DialogResult = DialogResult.Cancel; 65 | Close(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /LonScan/LonDeviceConfig.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LonScan 5 | { 6 | public class NvInfo 7 | { 8 | public string Name = ""; 9 | public string Description = ""; 10 | public string LonType 11 | { 12 | get => Type.Name; 13 | set 14 | { 15 | Type = LonStandardTypes.Get(value); 16 | } 17 | } 18 | public string SelfDoc = ""; 19 | 20 | 21 | internal LonStandardTypes.LonType Type; 22 | 23 | public NvInfo() 24 | { 25 | } 26 | 27 | public NvInfo(string name, string description, string format) : this(name, description, LonStandardTypes.Get(format)) 28 | { 29 | } 30 | 31 | public NvInfo(string name, string description, LonStandardTypes.LonType type) 32 | { 33 | Name = name.Trim(); 34 | Description = description.Trim(); 35 | if (type != null) 36 | { 37 | Type = type; 38 | } 39 | else 40 | { 41 | Type = LonStandardTypes.Get("UNVT"); 42 | } 43 | } 44 | } 45 | 46 | public class LonDeviceConfig 47 | { 48 | [JsonProperty(Order = 1)] 49 | public string Name = ""; 50 | 51 | [JsonProperty(Order = 2)] 52 | public int[] Addresses = new int[0]; 53 | [JsonProperty(Order = 3)] 54 | public string ProgramId; 55 | [JsonProperty(Order = 4)] 56 | public string SelfDoc = ""; 57 | [JsonProperty(Order = 5)] 58 | public Dictionary NvMap = new Dictionary(); 59 | 60 | internal NvInfo[] NvInfos 61 | { 62 | set 63 | { 64 | NvMap = new Dictionary(); 65 | for (int pos = 0; pos < value.Length; pos++) 66 | { 67 | NvMap.Add(pos, value[pos]); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /LonScan/Program.cs: -------------------------------------------------------------------------------- 1 | using CrashReporterDotNET; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace LonScan 10 | { 11 | static class Program 12 | { 13 | private static ReportCrash _reportCrash; 14 | 15 | [STAThread] 16 | static void Main() 17 | { 18 | Application.ThreadException += (sender, args) => SendReport(args.Exception); 19 | AppDomain.CurrentDomain.UnhandledException += (sender, args) => 20 | { 21 | SendReport((Exception)args.ExceptionObject); 22 | }; 23 | 24 | Application.EnableVisualStyles(); 25 | Application.SetCompatibleTextRenderingDefault(false); 26 | 27 | _reportCrash = new ReportCrash("LonScan@g3gg0.de") 28 | { 29 | Silent = true, 30 | ShowScreenshotTab = true, 31 | IncludeScreenshot = false, 32 | AnalyzeWithDoctorDump = true, 33 | DoctorDumpSettings = new DoctorDumpSettings 34 | { 35 | ApplicationID = new Guid("1205bba2-0d38-4351-bba1-8ca63993f8b6"), 36 | OpenReportInBrowser = true 37 | } 38 | }; 39 | _reportCrash.RetryFailedReports(); 40 | 41 | Application.Run(new LonScannerMain()); 42 | } 43 | public static void SendReport(Exception exception, string developerMessage = "") 44 | { 45 | _reportCrash.DeveloperMessage = developerMessage; 46 | _reportCrash.Silent = false; 47 | _reportCrash.Send(exception); 48 | } 49 | 50 | public static void SendReportSilently(Exception exception, string developerMessage = "") 51 | { 52 | _reportCrash.DeveloperMessage = developerMessage; 53 | _reportCrash.Silent = true; 54 | _reportCrash.Send(exception); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /LonScan/DynamicXml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml.Linq; 8 | 9 | namespace LonScan 10 | { 11 | public class DynamicXml : DynamicObject 12 | { 13 | XElement _root; 14 | private DynamicXml(XElement root) 15 | { 16 | _root = root; 17 | } 18 | 19 | public static DynamicXml Parse(string xmlString) 20 | { 21 | return new DynamicXml(RemoveNamespaces(XDocument.Parse(xmlString).Root)); 22 | } 23 | 24 | public static DynamicXml Load(string filename) 25 | { 26 | return new DynamicXml(RemoveNamespaces(XDocument.Load(filename).Root)); 27 | } 28 | 29 | private static XElement RemoveNamespaces(XElement xElem) 30 | { 31 | var attrs = xElem.Attributes() 32 | .Where(a => !a.IsNamespaceDeclaration) 33 | .Select(a => new XAttribute(a.Name.LocalName, a.Value)) 34 | .ToList(); 35 | 36 | if (!xElem.HasElements) 37 | { 38 | XElement xElement = new XElement(xElem.Name.LocalName, attrs); 39 | xElement.Value = xElem.Value; 40 | return xElement; 41 | } 42 | 43 | var newXElem = new XElement(xElem.Name.LocalName, xElem.Elements().Select(e => RemoveNamespaces(e))); 44 | newXElem.Add(attrs); 45 | return newXElem; 46 | } 47 | 48 | public override bool TryGetMember(GetMemberBinder binder, out object result) 49 | { 50 | result = null; 51 | 52 | var att = _root.Attribute(binder.Name); 53 | if (att != null) 54 | { 55 | result = att.Value; 56 | return true; 57 | } 58 | 59 | var nodes = _root.Elements(binder.Name); 60 | if (nodes.Count() > 1) 61 | { 62 | result = nodes.Select(n => n.HasElements ? (object)new DynamicXml(n) : n.Value).ToList(); 63 | return true; 64 | } 65 | 66 | var node = _root.Element(binder.Name); 67 | if (node != null) 68 | { 69 | result = node.HasElements || node.HasAttributes ? (object)new DynamicXml(node) : node.Value; 70 | return true; 71 | } 72 | 73 | return true; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /LonScan/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace LonScan.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. 17 | /// 18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert 19 | // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. 20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen 21 | // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LonScan.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle 51 | /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /LonScan/ILMerge.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 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 | -------------------------------------------------------------------------------- /LonScan/HexForm.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace LonScan 3 | { 4 | partial class HexForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.btnCancel = new System.Windows.Forms.Button(); 33 | this.btnWrite = new System.Windows.Forms.Button(); 34 | this.txtHex = new System.Windows.Forms.TextBox(); 35 | this.label1 = new System.Windows.Forms.Label(); 36 | this.SuspendLayout(); 37 | // 38 | // btnCancel 39 | // 40 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 41 | this.btnCancel.Location = new System.Drawing.Point(215, 59); 42 | this.btnCancel.Name = "btnCancel"; 43 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 44 | this.btnCancel.TabIndex = 0; 45 | this.btnCancel.Text = "Cancel"; 46 | this.btnCancel.UseVisualStyleBackColor = true; 47 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 48 | // 49 | // btnWrite 50 | // 51 | this.btnWrite.Location = new System.Drawing.Point(134, 59); 52 | this.btnWrite.Name = "btnWrite"; 53 | this.btnWrite.Size = new System.Drawing.Size(75, 23); 54 | this.btnWrite.TabIndex = 1; 55 | this.btnWrite.Text = "Write"; 56 | this.btnWrite.UseVisualStyleBackColor = true; 57 | this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click); 58 | // 59 | // txtHex 60 | // 61 | this.txtHex.Location = new System.Drawing.Point(13, 33); 62 | this.txtHex.Name = "txtHex"; 63 | this.txtHex.Size = new System.Drawing.Size(277, 20); 64 | this.txtHex.TabIndex = 2; 65 | // 66 | // label1 67 | // 68 | this.label1.AutoSize = true; 69 | this.label1.Location = new System.Drawing.Point(13, 14); 70 | this.label1.Name = "label1"; 71 | this.label1.Size = new System.Drawing.Size(61, 13); 72 | this.label1.TabIndex = 3; 73 | this.label1.Text = "Write value"; 74 | // 75 | // HexForm 76 | // 77 | this.AcceptButton = this.btnWrite; 78 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 79 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 80 | this.CancelButton = this.btnCancel; 81 | this.ClientSize = new System.Drawing.Size(302, 92); 82 | this.Controls.Add(this.label1); 83 | this.Controls.Add(this.txtHex); 84 | this.Controls.Add(this.btnWrite); 85 | this.Controls.Add(this.btnCancel); 86 | this.Name = "HexForm"; 87 | this.Text = "HexForm"; 88 | this.ResumeLayout(false); 89 | this.PerformLayout(); 90 | 91 | } 92 | 93 | #endregion 94 | 95 | private System.Windows.Forms.Button btnCancel; 96 | private System.Windows.Forms.Button btnWrite; 97 | private System.Windows.Forms.TextBox txtHex; 98 | private System.Windows.Forms.Label label1; 99 | } 100 | } -------------------------------------------------------------------------------- /LonScan/PacketForgeDlg.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Net.Sockets; 8 | using System.Runtime.Remoting.Messaging; 9 | using System.Text; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | using System.Windows.Forms; 13 | 14 | namespace LonScan 15 | { 16 | public partial class PacketForgeDlg : Form 17 | { 18 | private readonly LonNetwork Network; 19 | private readonly Config Config; 20 | 21 | public PacketForgeDlg(LonNetwork network, Config config) 22 | { 23 | Network = network; 24 | Config = config; 25 | InitializeComponent(); 26 | 27 | foreach (string str in Config.PacketForgeTemplates) 28 | { 29 | cmbFrameBytes.Items.Add(str); 30 | } 31 | } 32 | 33 | private void cmbFrameBytes_KeyPress(object sender, KeyPressEventArgs e) 34 | { 35 | UpdatePacket(); 36 | } 37 | 38 | private void UpdatePacket() 39 | { 40 | byte[] data = GetBytes(); 41 | 42 | if (data.Length < 6) 43 | { 44 | return; 45 | } 46 | 47 | try 48 | { 49 | var pdu = LonPPdu.FromData(data, 0, data.Length); 50 | 51 | txtTxDump.Text = BitConverter.ToString(pdu.FrameBytes).Replace("-", " ") + Environment.NewLine + Environment.NewLine + PacketForge.ToString(pdu); 52 | 53 | if (pdu.NPDU.Address.SourceNode != Network.SourceNode) 54 | { 55 | txtRxDump.Text = "Please set source node to 0x" + Network.SourceNode.ToString("X2") + " (" + Network.SourceNode + ") else we will receive no reply."; 56 | } 57 | else 58 | { 59 | txtRxDump.Text = ""; 60 | } 61 | } 62 | catch (Exception ex) 63 | { 64 | txtTxDump.Text = "Failed to parse packet"; 65 | } 66 | } 67 | 68 | private void btnTx_Click(object sender, EventArgs e) 69 | { 70 | SendPacket(); 71 | } 72 | 73 | private void cmbFrameBytes_KeyDown(object sender, KeyEventArgs e) 74 | { 75 | if(e.KeyCode == Keys.Enter) 76 | { 77 | SendPacket(); 78 | e.SuppressKeyPress = true; 79 | } 80 | } 81 | 82 | private void cmbFrameBytes_TextChanged(object sender, EventArgs e) 83 | { 84 | UpdatePacket(); 85 | } 86 | 87 | private void SendPacket() 88 | { 89 | byte[] data = GetBytes(); 90 | 91 | if (cmbFrameBytes.Text.Contains("#")) 92 | { 93 | SaveSequence(cmbFrameBytes.Text); 94 | } 95 | cmbFrameBytes.Text = BitConverter.ToString(data).Replace("-", " "); 96 | 97 | 98 | Thread t = new Thread(() => 99 | { 100 | var pdu = LonPPdu.FromData(data, 0, data.Length); 101 | bool wait = pdu.NPDU.Address.SourceNode == Network.SourceNode; 102 | 103 | if (wait) 104 | { 105 | BeginInvoke(new Action(() => 106 | { 107 | txtRxDump.Text = "(Waiting " + Config.PacketTimeout + "ms for response...)"; 108 | })); 109 | } 110 | 111 | bool success = Network.SendMessage(pdu, (r) => 112 | { 113 | BeginInvoke(new Action(() => 114 | { 115 | txtRxDump.Text = BitConverter.ToString(r.FrameBytes).Replace("-", " ") + Environment.NewLine + Environment.NewLine + PacketForge.ToString(r); 116 | })); 117 | }, wait ? Config.PacketTimeout : -1); 118 | 119 | if (!success) 120 | { 121 | BeginInvoke(new Action(() => 122 | { 123 | txtRxDump.Text = "(Response timed out)"; 124 | })); 125 | } 126 | }); 127 | 128 | t.Start(); 129 | } 130 | 131 | private void SaveSequence(string text) 132 | { 133 | if (!Config.PacketForgeTemplates.Contains(text)) 134 | { 135 | cmbFrameBytes.Items.Add(text); 136 | Config.PacketForgeTemplates.Add(text); 137 | Config.Save(); 138 | } 139 | } 140 | 141 | public byte[] GetBytes() 142 | { 143 | try 144 | { 145 | string msg = cmbFrameBytes.Text.Split('#')[0].Replace(" ", ""); 146 | return Enumerable.Range(0, msg.Length) .Where(x => x % 2 == 0) 147 | .Select(x => Convert.ToByte(msg.Substring(x, 2), 16)) .ToArray(); 148 | } 149 | catch (Exception ex) 150 | { 151 | } 152 | 153 | return new byte[0]; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /LonScan/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /LonScan/HexForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /LonScan/PacketForge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | 5 | namespace LonScan 6 | { 7 | internal class PacketForge 8 | { 9 | internal static string ToString(object pdu, string indent = "") 10 | { 11 | StringBuilder sb = new StringBuilder(); 12 | 13 | try 14 | { 15 | 16 | var fields = pdu.GetType().GetFields(); 17 | 18 | foreach (var field in fields) 19 | { 20 | Type ft = field.FieldType; 21 | 22 | foreach (var att in field.GetCustomAttributes(typeof(PacketForgeAttribute), true)) 23 | { 24 | if (!(att is PacketForgeAttribute pfAtt)) 25 | { 26 | continue; 27 | } 28 | 29 | string typeString = ""; 30 | string nameString = ""; 31 | string valueString = ""; 32 | string infoString = ""; 33 | 34 | nameString = field.Name.PadRight(16); 35 | 36 | 37 | if (pfAtt is PacketFieldBoolAttribute) 38 | { 39 | bool value = false; 40 | if (ft == typeof(bool)) 41 | { 42 | value = (bool)field.GetValue(pdu); 43 | } 44 | else if (ft == typeof(int)) 45 | { 46 | value = (int)field.GetValue(pdu) > 0; 47 | } 48 | else if (ft == typeof(uint)) 49 | { 50 | value = (uint)field.GetValue(pdu) > 0; 51 | } 52 | 53 | typeString = "bool"; 54 | valueString = value ? "yes" : "no"; 55 | } 56 | else if (pfAtt is PacketFieldUnsignedAttribute) 57 | { 58 | PacketFieldUnsignedAttribute attrib = (PacketFieldUnsignedAttribute)pfAtt; 59 | 60 | int value = 0; 61 | if (ft == typeof(int)) 62 | { 63 | value = (int)field.GetValue(pdu); 64 | } 65 | else if (ft == typeof(uint)) 66 | { 67 | value = (int)(uint)field.GetValue(pdu); 68 | } 69 | 70 | typeString = "int"; 71 | valueString = "0x" + value.ToString("X2") + " / " + value.ToString(); 72 | infoString = "";// "(" + attrib.Width + " bit)"; 73 | } 74 | else if (pfAtt is PacketFieldEnumAttribute) 75 | { 76 | typeString = ft.Name; 77 | if (Enum.IsDefined(ft, field.GetValue(pdu))) 78 | { 79 | valueString = Enum.GetName(ft, field.GetValue(pdu)) + " (" + (int)field.GetValue(pdu) + ")"; 80 | } 81 | else 82 | { 83 | valueString = "(invalid) " + (int)field.GetValue(pdu); 84 | } 85 | } 86 | else if (pfAtt is PacketFieldSduAttribute) 87 | { 88 | string data = ""; 89 | 90 | BitConverter.ToString((byte[])field.GetValue(pdu)).Replace("-", " "); 91 | 92 | typeString = "byte[]"; 93 | valueString = data; 94 | } 95 | else if (pfAtt is PacketFieldDataAttribute) 96 | { 97 | byte[] bytes = (byte[])field.GetValue(pdu); 98 | string data = BitConverter.ToString(bytes).Replace("-", " "); 99 | 100 | string readable = ReadableString(Encoding.ASCII.GetString(bytes)); 101 | typeString = "byte[]"; 102 | valueString = "[ " + data + " ] \""+readable+"\""; 103 | } 104 | else if (pfAtt is PacketFieldSubtypeAttribute) 105 | { 106 | PacketFieldSubtypeAttribute attrib = (PacketFieldSubtypeAttribute)att; 107 | 108 | object sub = field.GetValue(pdu); 109 | 110 | if (sub != null) 111 | { 112 | valueString = sub.GetType().Name + Environment.NewLine + ToString(sub, indent + " ").TrimEnd(new[] { '\r', '\n' }); 113 | } 114 | else 115 | { 116 | valueString = field.FieldType.Name + " (null)"; 117 | } 118 | } 119 | 120 | sb.AppendLine(indent + /*" "+ typeString.PadRight(16) + */"" + nameString.PadRight(24) + " = " + valueString + " " + infoString); 121 | } 122 | } 123 | } 124 | catch (Exception ex) 125 | { 126 | sb.Append("Failed to process: " + ex.ToString()); 127 | } 128 | 129 | return sb.ToString(); 130 | } 131 | 132 | private static string ReadableString(string v) 133 | { 134 | StringBuilder sb = new StringBuilder(); 135 | 136 | foreach(char c in v) 137 | { 138 | if(c > 0x20 && c < 0x80) 139 | { 140 | sb.Append(c); 141 | } 142 | else 143 | { 144 | sb.Append('.'); 145 | } 146 | } 147 | 148 | return sb.ToString(); 149 | } 150 | } 151 | 152 | internal class PacketForgeAttribute : Attribute 153 | { 154 | } 155 | 156 | internal class PacketFieldBoolAttribute : PacketForgeAttribute 157 | { 158 | } 159 | 160 | internal class PacketFieldEnumAttribute : PacketForgeAttribute 161 | { 162 | } 163 | 164 | internal class PacketFieldUnsignedAttribute : PacketForgeAttribute 165 | { 166 | internal int Width; 167 | 168 | public PacketFieldUnsignedAttribute() 169 | { 170 | } 171 | 172 | public PacketFieldUnsignedAttribute(int width) 173 | { 174 | this.Width = width; 175 | } 176 | } 177 | 178 | internal class PacketFieldSduAttribute : PacketForgeAttribute 179 | { 180 | } 181 | internal class PacketFieldDataAttribute : PacketForgeAttribute 182 | { 183 | } 184 | 185 | internal class PacketFieldSubtypeAttribute : PacketForgeAttribute 186 | { 187 | public Type[] ValidTypes; 188 | 189 | public PacketFieldSubtypeAttribute(params Type[] types) 190 | { 191 | ValidTypes = types; 192 | } 193 | } 194 | } -------------------------------------------------------------------------------- /LonScan/LonScan.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {DD1B0597-84AA-43F6-91C3-4166EED15AF4} 9 | WinExe 10 | LonScan 11 | LonScan 12 | v4.8 13 | 512 14 | true 15 | true 16 | 17 | 18 | 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | 39 | 40 | scope.ico 41 | 42 | 43 | 44 | ..\packages\CrashReporter.NET.Official.1.6.0\lib\net462\CrashReporter.NET.dll 45 | 46 | 47 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Form 65 | 66 | 67 | DeviceForm.cs 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Form 76 | 77 | 78 | PacketForgeDlg.cs 79 | 80 | 81 | Form 82 | 83 | 84 | ScanForm.cs 85 | 86 | 87 | Form 88 | 89 | 90 | HexForm.cs 91 | 92 | 93 | 94 | 95 | 96 | Form 97 | 98 | 99 | LonScannerMain.cs 100 | 101 | 102 | 103 | 104 | 105 | DeviceForm.cs 106 | 107 | 108 | PacketForgeDlg.cs 109 | 110 | 111 | ScanForm.cs 112 | 113 | 114 | HexForm.cs 115 | 116 | 117 | LonScannerMain.cs 118 | 119 | 120 | ResXFileCodeGenerator 121 | Resources.Designer.cs 122 | Designer 123 | 124 | 125 | True 126 | Resources.resx 127 | True 128 | 129 | 130 | 131 | 132 | SettingsSingleFileGenerator 133 | Settings.Designer.cs 134 | 135 | 136 | True 137 | Settings.settings 138 | True 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /LonScan/ScanForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LonScan 2 | { 3 | partial class ScanForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ScanForm)); 32 | this.lstDevices = new System.Windows.Forms.ListView(); 33 | this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 34 | this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 35 | this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 36 | this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 37 | this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 38 | this.toolStrip1 = new System.Windows.Forms.ToolStrip(); 39 | this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer(); 40 | this.btnDetect = new System.Windows.Forms.ToolStripButton(); 41 | this.btnResetCounters = new System.Windows.Forms.ToolStripButton(); 42 | this.toolStrip1.SuspendLayout(); 43 | this.toolStripContainer1.ContentPanel.SuspendLayout(); 44 | this.toolStripContainer1.TopToolStripPanel.SuspendLayout(); 45 | this.toolStripContainer1.SuspendLayout(); 46 | this.SuspendLayout(); 47 | // 48 | // lstDevices 49 | // 50 | this.lstDevices.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 51 | this.columnHeader1, 52 | this.columnHeader2, 53 | this.columnHeader3, 54 | this.columnHeader4, 55 | this.columnHeader5}); 56 | this.lstDevices.Dock = System.Windows.Forms.DockStyle.Fill; 57 | this.lstDevices.FullRowSelect = true; 58 | this.lstDevices.HideSelection = false; 59 | this.lstDevices.Location = new System.Drawing.Point(0, 0); 60 | this.lstDevices.Name = "lstDevices"; 61 | this.lstDevices.Size = new System.Drawing.Size(740, 210); 62 | this.lstDevices.TabIndex = 0; 63 | this.lstDevices.UseCompatibleStateImageBehavior = false; 64 | this.lstDevices.View = System.Windows.Forms.View.Details; 65 | // 66 | // columnHeader1 67 | // 68 | this.columnHeader1.Text = "Source"; 69 | this.columnHeader1.Width = 100; 70 | // 71 | // columnHeader2 72 | // 73 | this.columnHeader2.Text = "Packets"; 74 | this.columnHeader2.Width = 91; 75 | // 76 | // columnHeader3 77 | // 78 | this.columnHeader3.Text = "Device"; 79 | this.columnHeader3.Width = 164; 80 | // 81 | // columnHeader4 82 | // 83 | this.columnHeader4.Text = "Neuron ID"; 84 | this.columnHeader4.Width = 130; 85 | // 86 | // columnHeader5 87 | // 88 | this.columnHeader5.Text = "Program ID"; 89 | this.columnHeader5.Width = 164; 90 | // 91 | // toolStrip1 92 | // 93 | this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None; 94 | this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 95 | this.btnDetect, 96 | this.btnResetCounters}); 97 | this.toolStrip1.Location = new System.Drawing.Point(3, 0); 98 | this.toolStrip1.Name = "toolStrip1"; 99 | this.toolStrip1.Size = new System.Drawing.Size(212, 25); 100 | this.toolStrip1.TabIndex = 1; 101 | this.toolStrip1.Text = "toolStrip1"; 102 | // 103 | // toolStripContainer1 104 | // 105 | // 106 | // toolStripContainer1.ContentPanel 107 | // 108 | this.toolStripContainer1.ContentPanel.Controls.Add(this.lstDevices); 109 | this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(740, 210); 110 | this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 111 | this.toolStripContainer1.Location = new System.Drawing.Point(0, 0); 112 | this.toolStripContainer1.Name = "toolStripContainer1"; 113 | this.toolStripContainer1.Size = new System.Drawing.Size(740, 235); 114 | this.toolStripContainer1.TabIndex = 3; 115 | this.toolStripContainer1.Text = "toolStripContainer1"; 116 | // 117 | // toolStripContainer1.TopToolStripPanel 118 | // 119 | this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStrip1); 120 | // 121 | // btnDetect 122 | // 123 | this.btnDetect.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; 124 | this.btnDetect.Image = ((System.Drawing.Image)(resources.GetObject("btnDetect.Image"))); 125 | this.btnDetect.ImageTransparentColor = System.Drawing.Color.Magenta; 126 | this.btnDetect.Name = "btnDetect"; 127 | this.btnDetect.Size = new System.Drawing.Size(79, 22); 128 | this.btnDetect.Text = "Scan Devices"; 129 | this.btnDetect.Click += new System.EventHandler(this.btnDetect_Click); 130 | // 131 | // btnResetCounters 132 | // 133 | this.btnResetCounters.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; 134 | this.btnResetCounters.Image = ((System.Drawing.Image)(resources.GetObject("btnResetCounters.Image"))); 135 | this.btnResetCounters.ImageTransparentColor = System.Drawing.Color.Magenta; 136 | this.btnResetCounters.Name = "btnResetCounters"; 137 | this.btnResetCounters.Size = new System.Drawing.Size(90, 22); 138 | this.btnResetCounters.Text = "Reset Counters"; 139 | this.btnResetCounters.Click += new System.EventHandler(this.btnResetCounters_Click); 140 | // 141 | // ScanForm 142 | // 143 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 144 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 145 | this.ClientSize = new System.Drawing.Size(740, 235); 146 | this.Controls.Add(this.toolStripContainer1); 147 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 148 | this.Name = "ScanForm"; 149 | this.Text = "Device Scanner"; 150 | this.toolStrip1.ResumeLayout(false); 151 | this.toolStrip1.PerformLayout(); 152 | this.toolStripContainer1.ContentPanel.ResumeLayout(false); 153 | this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false); 154 | this.toolStripContainer1.TopToolStripPanel.PerformLayout(); 155 | this.toolStripContainer1.ResumeLayout(false); 156 | this.toolStripContainer1.PerformLayout(); 157 | this.ResumeLayout(false); 158 | 159 | } 160 | 161 | #endregion 162 | 163 | private System.Windows.Forms.ListView lstDevices; 164 | private System.Windows.Forms.ColumnHeader columnHeader1; 165 | private System.Windows.Forms.ColumnHeader columnHeader2; 166 | private System.Windows.Forms.ColumnHeader columnHeader3; 167 | private System.Windows.Forms.ColumnHeader columnHeader4; 168 | private System.Windows.Forms.ColumnHeader columnHeader5; 169 | private System.Windows.Forms.ToolStrip toolStrip1; 170 | private System.Windows.Forms.ToolStripButton btnDetect; 171 | private System.Windows.Forms.ToolStripContainer toolStripContainer1; 172 | private System.Windows.Forms.ToolStripButton btnResetCounters; 173 | } 174 | } -------------------------------------------------------------------------------- /LonScan/XifFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml.Serialization; 8 | 9 | namespace LonScan 10 | { 11 | public class XifFile 12 | { 13 | public string DeviceName = "(undefined)"; 14 | public string ProgramId = "(undefined)"; 15 | public string SelfDoc = "(undefined)"; 16 | public List Tags = new List(); 17 | public List Vars = new List(); 18 | 19 | private XifLineReader Reader; 20 | 21 | public XifFile(string file) 22 | { 23 | Reader = new XifLineReader(file); 24 | DeviceName = new FileInfo(file).Name; 25 | 26 | 27 | /* ignore first 11 lines */ 28 | for (int line = 1; line < 5; line++) 29 | { 30 | Reader.ReadLine(); 31 | } 32 | ProgramId = Reader.ReadLine().Replace(":", ""); 33 | for (int line = 6; line < 11; line++) 34 | { 35 | Reader.ReadLine(); 36 | } 37 | 38 | if (Reader.CurrentLine != "*") 39 | { 40 | Console.WriteLine("Failed to read"); 41 | return; 42 | } 43 | Reader.ReadLine(); 44 | 45 | SelfDoc = ReadSelfDoc(); 46 | 47 | if(!string.IsNullOrEmpty(SelfDoc)) 48 | { 49 | string[] fields = SelfDoc.Split(';'); 50 | if(fields.Length > 1) 51 | { 52 | DeviceName = fields.Last(); 53 | } 54 | } 55 | Reader.ReadLine(); 56 | 57 | bool done = false; 58 | while(!done && Reader.CurrentLine != null) 59 | { 60 | string[] fields = Reader.CurrentLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 61 | 62 | if(fields.Length == 0) 63 | { 64 | break; 65 | } 66 | 67 | switch(fields[0]) 68 | { 69 | case "TAG": 70 | Tags.Add(ReadTag()); 71 | break; 72 | case "VAR": 73 | Vars.Add(ReadVar()); 74 | break; 75 | } 76 | } 77 | 78 | try 79 | { 80 | FileInfo[] opData = new FileInfo(file).Directory.GetFiles("OperationalData.xml"); 81 | if (opData.Length > 0) 82 | { 83 | dynamic data = DynamicXml.Parse(File.ReadAllText(opData[0].FullName)); 84 | 85 | string dev = data.Device.SoftwareName; 86 | string ver = data.Device.SoftwareVersion; 87 | 88 | DeviceName = dev + " " + ver; 89 | } 90 | } 91 | catch (Exception ex) 92 | { 93 | 94 | } 95 | } 96 | 97 | public class XifTag 98 | { 99 | public string Name = ""; 100 | public string Index = ""; 101 | public string AvgRate = ""; 102 | public string MaxRate = ""; 103 | 104 | public string BindFlag = ""; 105 | } 106 | 107 | public class XifVar 108 | { 109 | public string Name = ""; 110 | public int Index; 111 | public int AvgRate; 112 | public int MaxRate; 113 | public int ArraySize; 114 | public bool TakeOffline; 115 | public bool Input; 116 | public bool Output => !Input; 117 | public string SelfDoc = ""; 118 | public int SnvtIndex; 119 | public string BindFlag = ""; 120 | 121 | public List Structure = new List(); 122 | 123 | public enum XifVarStructType 124 | { 125 | Character = 0, 126 | Int8, 127 | Int16, 128 | Bitfield, 129 | Union, 130 | Typeless 131 | } 132 | 133 | public class XifVarStructure 134 | { 135 | public XifVarStructType Type; 136 | public int BitOffset; 137 | public int Size; 138 | public bool Signed; 139 | public int ArraySize; 140 | } 141 | } 142 | 143 | private XifVar ReadVar() 144 | { 145 | StringBuilder sb = new StringBuilder(); 146 | 147 | XifVar var = new XifVar(); 148 | string header; 149 | string avgRate; 150 | string maxRate; 151 | string arraySize; 152 | string index; 153 | (header, var.Name, index, avgRate, maxRate, arraySize, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 154 | 155 | if (header != "VAR") 156 | { 157 | return null; 158 | } 159 | var.Index = int.Parse(index); 160 | var.AvgRate = int.Parse(avgRate); 161 | var.MaxRate = int.Parse(maxRate); 162 | var.ArraySize = int.Parse(arraySize); 163 | 164 | var (takeOffline, _, _, dir, serviceType, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 165 | 166 | var.TakeOffline = takeOffline == "1"; 167 | var.Input = dir == "0"; 168 | var.SelfDoc = ReadSelfDoc(); 169 | 170 | var (svnt, _, elements, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 171 | 172 | var.SnvtIndex = int.Parse(svnt); 173 | 174 | int elems = int.Parse(elements); 175 | 176 | for(int pos = 0; pos < elems; pos++) 177 | { 178 | XifVar.XifVarStructure t = new XifVar.XifVarStructure(); 179 | var (type, offset, size, signed, elemArraySize, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 180 | 181 | t.Type = (XifVar.XifVarStructType)int.Parse(type); 182 | t.BitOffset = int.Parse(offset); 183 | t.Size = int.Parse(size); 184 | t.Signed = signed == "1"; 185 | t.ArraySize = int.Parse(elemArraySize); 186 | 187 | var.Structure.Add(t); 188 | } 189 | 190 | return var; 191 | } 192 | private XifTag ReadTag() 193 | { 194 | StringBuilder sb = new StringBuilder(); 195 | 196 | XifTag tag = new XifTag(); 197 | 198 | string header; 199 | (header, tag.Name, tag.Index, tag.AvgRate, tag.MaxRate, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 200 | 201 | if(header != "TAG") 202 | { 203 | return null; 204 | } 205 | (_, tag.BindFlag, _) = Reader.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 206 | 207 | return tag; 208 | } 209 | 210 | private string ReadSelfDoc() 211 | { 212 | StringBuilder sb = new StringBuilder(); 213 | if(Reader.CurrentLine.StartsWith("*")) 214 | { 215 | Reader.ReadLine(); 216 | } 217 | 218 | while(Reader.CurrentLine.StartsWith("\"")) 219 | { 220 | sb.Append(Reader.ReadLine().Substring(1)); 221 | } 222 | 223 | return sb.ToString(); 224 | } 225 | 226 | public class XifLineReader 227 | { 228 | private TextReader Reader; 229 | public string CurrentLine; 230 | public string NextLine; 231 | 232 | public XifLineReader(string file) 233 | { 234 | Reader = File.OpenText(file); 235 | 236 | CurrentLine = Reader.ReadLine(); 237 | NextLine = Reader.ReadLine(); 238 | } 239 | 240 | public string ReadLine() 241 | { 242 | string ret = CurrentLine; 243 | 244 | CurrentLine = NextLine; 245 | NextLine = Reader.ReadLine(); 246 | 247 | //Console.WriteLine("> " + CurrentLine); 248 | 249 | return ret; 250 | } 251 | } 252 | 253 | internal LonDeviceConfig ToDeviceConfig() 254 | { 255 | LonDeviceConfig cfg = new LonDeviceConfig(); 256 | 257 | cfg.Name = DeviceName; 258 | cfg.Addresses = new int[0]; 259 | cfg.ProgramId = ProgramId; 260 | cfg.SelfDoc = SelfDoc; 261 | 262 | foreach (var v in Vars) 263 | { 264 | cfg.NvMap.Add(v.Index, new NvInfo { Name = v.Name, Type = LonStandardTypes.Get(v.SnvtIndex), SelfDoc = v.SelfDoc }); 265 | } 266 | 267 | return cfg; 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /LonScan/DeviceForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Net.Sockets; 10 | using System.Threading; 11 | using System.Windows.Forms; 12 | 13 | namespace LonScan 14 | { 15 | public partial class DeviceForm : Form 16 | { 17 | private int Address = 10; 18 | private Thread ScanThread = null; 19 | private LonDevice Device = null; 20 | private int MemoryAddress = 0; 21 | 22 | 23 | public DeviceForm(LonDevice device) 24 | { 25 | InitializeComponent(); 26 | 27 | Text = "Device view: " + device.Name + " (Address " + device.Address + ")"; 28 | Device = device; 29 | 30 | for(int nv = 0; nv <= Device.Config.NvMap.Keys.Max(); nv++) 31 | { 32 | ListViewItem item; 33 | 34 | if (Device.Config.NvMap.ContainsKey(nv)) 35 | { 36 | item = new ListViewItem(new string[13] { nv.ToString("X2"), Device.Config.NvMap[nv].Name, Device.Config.NvMap[nv].Description, "", "", "", "", "", "", "", "", "", "" }); 37 | } 38 | else 39 | { 40 | item = new ListViewItem(new string[13] { nv.ToString("X2"), "(unused)", "", "", "", "", "", "", "", "", "", "", "" }); 41 | } 42 | listView1.Items.Add(item); 43 | } 44 | 45 | Device.OnNvUpdate += OnNvUpdate; 46 | Device.OnUpdate += OnUpdate; 47 | Device.StartNvScan(); 48 | } 49 | 50 | private void OnUpdate(LonDevice device) 51 | { 52 | try 53 | { 54 | this.BeginInvoke(new Action(() => 55 | { 56 | txtFirmwareDate.Text = Device.ConfigDate; 57 | txtFirmwareVer.Text = Device.ConfigVersion; 58 | txtFirmwareProd.Text = Device.ConfigProduct; 59 | })); 60 | } 61 | catch (Exception) 62 | { 63 | 64 | } 65 | } 66 | 67 | private void OnNvUpdate(LonDevice device, int nv_recv, string hex, string value) 68 | { 69 | try 70 | { 71 | this.BeginInvoke(new Action(() => 72 | { 73 | while (listView1.Items.Count <= nv_recv) 74 | { 75 | var item = new ListViewItem(new string[13] { listView1.Items.Count.ToString("X2"), "", "", "", "", "", "", "", "", "", "", "", "" }); 76 | listView1.Items.Add(item); 77 | } 78 | var curItem = listView1.Items[nv_recv]; 79 | int col = 3; 80 | curItem.SubItems[col++].Text = hex; 81 | curItem.SubItems[col++].Text = value; 82 | 83 | if (Device.NvConfigTable.ContainsKey(nv_recv)) 84 | { 85 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Bound ? "yes" : "no"; 86 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Priority ? "yes" : "no"; 87 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Direction.ToString(); 88 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].NetVarSelector.ToString(); 89 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Turnaround ? "yes" : "no"; 90 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Service.ToString(); 91 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Secure ? "yes" : "no"; 92 | curItem.SubItems[col++].Text = Device.NvConfigTable[nv_recv].Address.ToString(); 93 | 94 | if(Device.NvConfigTable[nv_recv].Bound) 95 | { 96 | if (Device.NvConfigTable[nv_recv].Direction == LonAPdu.LonAPduDirection.In) 97 | { 98 | curItem.BackColor = Color.LightGreen; 99 | } 100 | else 101 | { 102 | curItem.BackColor = Color.LightPink; 103 | } 104 | } 105 | } 106 | listView1.Items[nv_recv].Tag = nv_recv; 107 | 108 | listView1.SelectedIndices.Clear(); 109 | listView1.SelectedIndices.Add(nv_recv); 110 | })); 111 | } 112 | catch (Exception) 113 | { 114 | 115 | } 116 | } 117 | 118 | private void ScanMemory() 119 | { 120 | Thread t = new Thread(()=> 121 | { 122 | MemoryAddress = 0x2306; 123 | 124 | while (MemoryAddress < 0x2400) 125 | { 126 | LonPPdu pdu = new LonPPdu 127 | { 128 | NPDU = new LonNPdu 129 | { 130 | Address = new LonAddressNode 131 | { 132 | SourceSubnet = 1, 133 | SourceNode = 126, 134 | DestinationSubnet = 1, 135 | DestinationNode = Address 136 | }, 137 | 138 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 139 | Domain = 0x54, 140 | PDU = new LonSPdu 141 | { 142 | SPDUType = LonSPdu.LonSPduType.Request, 143 | APDU = LonAPduNetworkManagement.GenerateNMMemoryRead(0, (uint)MemoryAddress, 16) 144 | } 145 | } 146 | }; 147 | 148 | bool success = Device.Network.SendMessage(pdu, (p) => 149 | { 150 | //Console.WriteLine("M: " + Address.ToString("X4") + " " + BitConverter.ToString(p.FrameBytes).Replace("-", " ")); 151 | }); 152 | 153 | if (success) 154 | { 155 | MemoryAddress += 0x10; 156 | } 157 | } 158 | }); 159 | ScanThread.Abort(); 160 | t.Start(); 161 | } 162 | 163 | 164 | protected override void OnClosing(CancelEventArgs e) 165 | { 166 | if(ScanThread != null) 167 | { 168 | ScanThread.Abort(); 169 | ScanThread = null; 170 | } 171 | Device.StopNvScan(); 172 | base.OnClosing(e); 173 | } 174 | 175 | protected override void OnLoad(EventArgs e) 176 | { 177 | base.OnLoad(e); 178 | } 179 | 180 | private void btnDumpFlash_Click(object sender, EventArgs e) 181 | { 182 | ContextMenu menu = new ContextMenu(); 183 | 184 | menu.MenuItems.Add(new MenuItem("Firmware", (s, a) => 185 | { 186 | DumpMemory(0x0000, 0x4000, "Firmware"); 187 | })); 188 | menu.MenuItems.Add(new MenuItem("Application", (s, a) => 189 | { 190 | DumpMemory(0x4000, 0xE800, "Application"); 191 | })); 192 | menu.MenuItems.Add(new MenuItem("RAM", (s, a) => 193 | { 194 | DumpMemory(0xE800, 0xF000, "RAM"); 195 | })); 196 | menu.MenuItems.Add(new MenuItem("EEPROM", (s, a) => 197 | { 198 | DumpMemory(0xF000, 0xF200, "EEPROM"); 199 | })); 200 | 201 | menu.Show(this, PointToClient(MousePosition)); 202 | } 203 | 204 | private void DumpMemory(uint start, uint end, string desc) 205 | { 206 | Thread readThread = new Thread(() => 207 | { 208 | Device.StopNvScan(); 209 | byte[] mem = Device.ReadMemory(start, (int)(end-start), (p) => 210 | { 211 | BeginInvoke(new Action(() => 212 | { 213 | progressBar1.Value = (int)(p * 100); 214 | })); 215 | }); 216 | 217 | Device.StartNvScan(); 218 | 219 | BeginInvoke(new Action(() => 220 | { 221 | if (mem != null && mem.Length > 0) 222 | { 223 | progressBar1.Value = 0; 224 | SaveFileDialog saveFileDialog = new SaveFileDialog(); 225 | saveFileDialog.Filter = "Binary files (*.bin)|*.bin|All files (*.*)|*.*"; 226 | saveFileDialog.Title = "Save neuron's " + desc + " as..."; 227 | saveFileDialog.FileName = desc + ".bin"; 228 | 229 | if (saveFileDialog.ShowDialog() == DialogResult.OK) 230 | { 231 | try 232 | { 233 | File.WriteAllBytes(saveFileDialog.FileName, mem); 234 | } 235 | catch (Exception ex) 236 | { 237 | MessageBox.Show("Failed to save"); 238 | } 239 | } 240 | } 241 | else 242 | { 243 | MessageBox.Show("Failed to read memory"); 244 | } 245 | })); 246 | }); 247 | readThread.Start(); 248 | } 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /LonScan/PacketForgeDlg.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LonScan 2 | { 3 | partial class PacketForgeDlg 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PacketForgeDlg)); 32 | this.cmbFrameBytes = new System.Windows.Forms.ComboBox(); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.txtTxDump = new System.Windows.Forms.TextBox(); 35 | this.btnTx = new System.Windows.Forms.Button(); 36 | this.txtRxDump = new System.Windows.Forms.TextBox(); 37 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 38 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 39 | this.groupBox3 = new System.Windows.Forms.GroupBox(); 40 | this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 41 | this.splitContainer2 = new System.Windows.Forms.SplitContainer(); 42 | this.groupBox1.SuspendLayout(); 43 | this.groupBox2.SuspendLayout(); 44 | this.groupBox3.SuspendLayout(); 45 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 46 | this.splitContainer1.Panel1.SuspendLayout(); 47 | this.splitContainer1.Panel2.SuspendLayout(); 48 | this.splitContainer1.SuspendLayout(); 49 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); 50 | this.splitContainer2.Panel1.SuspendLayout(); 51 | this.splitContainer2.Panel2.SuspendLayout(); 52 | this.splitContainer2.SuspendLayout(); 53 | this.SuspendLayout(); 54 | // 55 | // cmbFrameBytes 56 | // 57 | this.cmbFrameBytes.FormattingEnabled = true; 58 | this.cmbFrameBytes.Location = new System.Drawing.Point(76, 18); 59 | this.cmbFrameBytes.Name = "cmbFrameBytes"; 60 | this.cmbFrameBytes.Size = new System.Drawing.Size(551, 21); 61 | this.cmbFrameBytes.TabIndex = 0; 62 | this.cmbFrameBytes.TextChanged += new System.EventHandler(this.cmbFrameBytes_TextChanged); 63 | this.cmbFrameBytes.KeyDown += new System.Windows.Forms.KeyEventHandler(this.cmbFrameBytes_KeyDown); 64 | this.cmbFrameBytes.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.cmbFrameBytes_KeyPress); 65 | // 66 | // label1 67 | // 68 | this.label1.AutoSize = true; 69 | this.label1.Location = new System.Drawing.Point(6, 21); 70 | this.label1.Name = "label1"; 71 | this.label1.Size = new System.Drawing.Size(64, 13); 72 | this.label1.TabIndex = 1; 73 | this.label1.Text = "Frame bytes"; 74 | // 75 | // txtTxDump 76 | // 77 | this.txtTxDump.Dock = System.Windows.Forms.DockStyle.Fill; 78 | this.txtTxDump.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 79 | this.txtTxDump.Location = new System.Drawing.Point(3, 16); 80 | this.txtTxDump.Multiline = true; 81 | this.txtTxDump.Name = "txtTxDump"; 82 | this.txtTxDump.ReadOnly = true; 83 | this.txtTxDump.ScrollBars = System.Windows.Forms.ScrollBars.Both; 84 | this.txtTxDump.Size = new System.Drawing.Size(397, 437); 85 | this.txtTxDump.TabIndex = 2; 86 | // 87 | // btnTx 88 | // 89 | this.btnTx.Location = new System.Drawing.Point(633, 17); 90 | this.btnTx.Name = "btnTx"; 91 | this.btnTx.Size = new System.Drawing.Size(75, 23); 92 | this.btnTx.TabIndex = 3; 93 | this.btnTx.Text = "Send"; 94 | this.btnTx.UseVisualStyleBackColor = true; 95 | this.btnTx.Click += new System.EventHandler(this.btnTx_Click); 96 | // 97 | // txtRxDump 98 | // 99 | this.txtRxDump.Dock = System.Windows.Forms.DockStyle.Fill; 100 | this.txtRxDump.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 101 | this.txtRxDump.Location = new System.Drawing.Point(3, 16); 102 | this.txtRxDump.Multiline = true; 103 | this.txtRxDump.Name = "txtRxDump"; 104 | this.txtRxDump.ReadOnly = true; 105 | this.txtRxDump.ScrollBars = System.Windows.Forms.ScrollBars.Both; 106 | this.txtRxDump.Size = new System.Drawing.Size(393, 437); 107 | this.txtRxDump.TabIndex = 2; 108 | // 109 | // groupBox1 110 | // 111 | this.groupBox1.Controls.Add(this.txtTxDump); 112 | this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; 113 | this.groupBox1.Location = new System.Drawing.Point(0, 0); 114 | this.groupBox1.Name = "groupBox1"; 115 | this.groupBox1.Size = new System.Drawing.Size(403, 456); 116 | this.groupBox1.TabIndex = 4; 117 | this.groupBox1.TabStop = false; 118 | this.groupBox1.Text = "TX Packet structure"; 119 | // 120 | // groupBox2 121 | // 122 | this.groupBox2.Controls.Add(this.txtRxDump); 123 | this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill; 124 | this.groupBox2.Location = new System.Drawing.Point(0, 0); 125 | this.groupBox2.Name = "groupBox2"; 126 | this.groupBox2.Size = new System.Drawing.Size(399, 456); 127 | this.groupBox2.TabIndex = 5; 128 | this.groupBox2.TabStop = false; 129 | this.groupBox2.Text = "RX Packet structure"; 130 | // 131 | // groupBox3 132 | // 133 | this.groupBox3.Controls.Add(this.label1); 134 | this.groupBox3.Controls.Add(this.cmbFrameBytes); 135 | this.groupBox3.Controls.Add(this.btnTx); 136 | this.groupBox3.Dock = System.Windows.Forms.DockStyle.Fill; 137 | this.groupBox3.Location = new System.Drawing.Point(4, 4); 138 | this.groupBox3.Name = "groupBox3"; 139 | this.groupBox3.Size = new System.Drawing.Size(806, 44); 140 | this.groupBox3.TabIndex = 6; 141 | this.groupBox3.TabStop = false; 142 | this.groupBox3.Text = "Forge a packet"; 143 | // 144 | // splitContainer1 145 | // 146 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 147 | this.splitContainer1.Location = new System.Drawing.Point(4, 4); 148 | this.splitContainer1.Name = "splitContainer1"; 149 | // 150 | // splitContainer1.Panel1 151 | // 152 | this.splitContainer1.Panel1.Controls.Add(this.groupBox1); 153 | // 154 | // splitContainer1.Panel2 155 | // 156 | this.splitContainer1.Panel2.Controls.Add(this.groupBox2); 157 | this.splitContainer1.Size = new System.Drawing.Size(806, 456); 158 | this.splitContainer1.SplitterDistance = 403; 159 | this.splitContainer1.TabIndex = 7; 160 | // 161 | // splitContainer2 162 | // 163 | this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; 164 | this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 165 | this.splitContainer2.IsSplitterFixed = true; 166 | this.splitContainer2.Location = new System.Drawing.Point(0, 0); 167 | this.splitContainer2.Name = "splitContainer2"; 168 | this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; 169 | // 170 | // splitContainer2.Panel1 171 | // 172 | this.splitContainer2.Panel1.Controls.Add(this.groupBox3); 173 | this.splitContainer2.Panel1.Padding = new System.Windows.Forms.Padding(4); 174 | // 175 | // splitContainer2.Panel2 176 | // 177 | this.splitContainer2.Panel2.Controls.Add(this.splitContainer1); 178 | this.splitContainer2.Panel2.Padding = new System.Windows.Forms.Padding(4); 179 | this.splitContainer2.Size = new System.Drawing.Size(814, 520); 180 | this.splitContainer2.SplitterDistance = 52; 181 | this.splitContainer2.TabIndex = 8; 182 | // 183 | // PacketForgeDlg 184 | // 185 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 186 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 187 | this.ClientSize = new System.Drawing.Size(814, 520); 188 | this.Controls.Add(this.splitContainer2); 189 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 190 | this.MinimumSize = new System.Drawing.Size(740, 300); 191 | this.Name = "PacketForgeDlg"; 192 | this.Text = "Packet Forge"; 193 | this.groupBox1.ResumeLayout(false); 194 | this.groupBox1.PerformLayout(); 195 | this.groupBox2.ResumeLayout(false); 196 | this.groupBox2.PerformLayout(); 197 | this.groupBox3.ResumeLayout(false); 198 | this.groupBox3.PerformLayout(); 199 | this.splitContainer1.Panel1.ResumeLayout(false); 200 | this.splitContainer1.Panel2.ResumeLayout(false); 201 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 202 | this.splitContainer1.ResumeLayout(false); 203 | this.splitContainer2.Panel1.ResumeLayout(false); 204 | this.splitContainer2.Panel2.ResumeLayout(false); 205 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); 206 | this.splitContainer2.ResumeLayout(false); 207 | this.ResumeLayout(false); 208 | 209 | } 210 | 211 | #endregion 212 | 213 | private System.Windows.Forms.ComboBox cmbFrameBytes; 214 | private System.Windows.Forms.Label label1; 215 | private System.Windows.Forms.TextBox txtTxDump; 216 | private System.Windows.Forms.Button btnTx; 217 | private System.Windows.Forms.TextBox txtRxDump; 218 | private System.Windows.Forms.GroupBox groupBox1; 219 | private System.Windows.Forms.GroupBox groupBox2; 220 | private System.Windows.Forms.GroupBox groupBox3; 221 | private System.Windows.Forms.SplitContainer splitContainer1; 222 | private System.Windows.Forms.SplitContainer splitContainer2; 223 | } 224 | } -------------------------------------------------------------------------------- /LonScan/ScanForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading; 7 | using System.Windows.Forms; 8 | 9 | namespace LonScan 10 | { 11 | public partial class ScanForm : Form 12 | { 13 | private readonly Config Config; 14 | private readonly LonNetwork Network; 15 | private Dictionary Packets = new Dictionary(); 16 | private readonly Dictionary AddressGuesses = new Dictionary(); 17 | private readonly Dictionary Items = new Dictionary(); 18 | 19 | public ScanForm(LonNetwork network, Config config) 20 | { 21 | InitializeComponent(); 22 | 23 | lstDevices.MouseClick += LstDevices_MouseClick; 24 | lstDevices.MouseDoubleClick += LstDevices_MouseDoubleClick; 25 | 26 | foreach (var dev in config.DeviceConfigs) 27 | { 28 | foreach (int addr in dev.Addresses) 29 | { 30 | if (AddressGuesses.ContainsKey(addr)) 31 | { 32 | AddressGuesses[addr] += ", " + dev.Name; 33 | } 34 | else 35 | { 36 | AddressGuesses.Add(addr, dev.Name); 37 | } 38 | } 39 | } 40 | AddressGuesses.Add(127, "MES-WiFi"); 41 | 42 | Config = config; 43 | Network = network; 44 | Network.OnReceive += DataReceived; 45 | } 46 | 47 | private void btnDetect_Click(object sender, EventArgs e) 48 | { 49 | QueryDevices(); 50 | } 51 | 52 | private void btnResetCounters_Click(object sender, EventArgs e) 53 | { 54 | lock (Items) 55 | { 56 | lstDevices.Items.Clear(); 57 | Items.Clear(); 58 | Packets.Clear(); 59 | } 60 | } 61 | 62 | private void QueryDevices() 63 | { 64 | LonPPdu pduEnable = new LonPPdu 65 | { 66 | NPDU = new LonNPdu 67 | { 68 | Address = new LonAddressSubnet 69 | { 70 | SourceSubnet = 1, 71 | SourceNode = Config.SourceNode, 72 | DestinationSubnet = 1 73 | }, 74 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 75 | Domain = 0x54, 76 | PDU = new LonSPdu 77 | { 78 | SPDUType = LonSPdu.LonSPduType.Request, 79 | APDU = new LonAPduNetworkManagement 80 | { 81 | Code = LonAPdu.LonAPduNMType.RespondToQuery, 82 | Data = new byte[] { 1 } 83 | } 84 | } 85 | } 86 | }; 87 | LonPPdu pduDisable = new LonPPdu 88 | { 89 | NPDU = new LonNPdu 90 | { 91 | Address = new LonAddressSubnet 92 | { 93 | SourceSubnet = 1, 94 | SourceNode = Config.SourceNode, 95 | DestinationSubnet = 1 96 | }, 97 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 98 | Domain = 0x54, 99 | PDU = new LonSPdu 100 | { 101 | SPDUType = LonSPdu.LonSPduType.Request, 102 | APDU = new LonAPduNetworkManagement 103 | { 104 | Code = LonAPdu.LonAPduNMType.RespondToQuery, 105 | Data = new byte[] { 0 } 106 | } 107 | } 108 | } 109 | }; 110 | 111 | LonPPdu pduQuery = new LonPPdu 112 | { 113 | NPDU = new LonNPdu 114 | { 115 | Address = new LonAddressSubnet 116 | { 117 | SourceSubnet = 1, 118 | SourceNode = Config.SourceNode, 119 | DestinationSubnet = 1 120 | }, 121 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 122 | Domain = 0x54, 123 | PDU = new LonSPdu 124 | { 125 | SPDUType = LonSPdu.LonSPduType.Request, 126 | APDU = new LonAPduNetworkManagement 127 | { 128 | Code = LonAPdu.LonAPduNMType.QueryId, 129 | Data = new byte[] { 1 } 130 | } 131 | } 132 | } 133 | }; 134 | 135 | Thread SendThread = new Thread(() => 136 | { 137 | Network.SendMessage(pduEnable, (p) => { }, -1); 138 | Thread.Sleep(500); 139 | Network.SendMessage(pduQuery, (p) => { }, -1); 140 | Thread.Sleep(500); 141 | Network.SendMessage(pduDisable, (p) => { }, -1); 142 | }); 143 | SendThread.Start(); 144 | } 145 | 146 | protected override void OnClosing(CancelEventArgs e) 147 | { 148 | Network.OnReceive -= DataReceived; 149 | base.OnClosing(e); 150 | } 151 | 152 | 153 | private void LstDevices_MouseDoubleClick(object sender, MouseEventArgs e) 154 | { 155 | ListViewItem item = lstDevices.GetItemAt(e.X, e.Y); 156 | 157 | if (item == null) 158 | { 159 | return; 160 | } 161 | int address = Items.Where(p => p.Value == item).First().Key; 162 | 163 | ContextMenu contextMenu = new ContextMenu(); 164 | 165 | var candid = Config.DeviceConfigs.Where(d => d.ProgramId == Items[address].SubItems[4].Text); 166 | if (candid.Count() == 1) 167 | { 168 | LonDeviceConfig cfg = candid.First(); 169 | LonDevice dev = new LonDevice(cfg.Name, address, Network, cfg); 170 | AddDevice(dev); 171 | } 172 | } 173 | 174 | private void LstDevices_MouseClick(object sender, MouseEventArgs e) 175 | { 176 | if (e.Button == MouseButtons.Right) 177 | { 178 | ListViewItem item = lstDevices.GetItemAt(e.X, e.Y); 179 | 180 | if (item == null) 181 | { 182 | return; 183 | } 184 | int address = Items.Where(p => p.Value == item).First().Key; 185 | 186 | ContextMenu contextMenu = new ContextMenu(); 187 | 188 | var candid = Config.DeviceConfigs.Where(d => d.ProgramId == Items[address].SubItems[4].Text); 189 | if (candid.Count() > 0) 190 | { 191 | foreach (LonDeviceConfig cfg in candid) 192 | { 193 | contextMenu.MenuItems.Add(new MenuItem("Add #" + address + " as " + cfg.Name, (s, ev) => 194 | { 195 | LonDevice dev = new LonDevice(cfg.Name, address, Network, cfg); 196 | AddDevice(dev); 197 | })); 198 | } 199 | } 200 | else 201 | { 202 | foreach (LonDeviceConfig cfg in Config.DeviceConfigs) 203 | { 204 | contextMenu.MenuItems.Add(new MenuItem("Add #" + address + " as " + cfg.Name, (s, ev) => 205 | { 206 | LonDevice dev = new LonDevice(cfg.Name, address, Network, cfg); 207 | AddDevice(dev); 208 | })); 209 | } 210 | } 211 | 212 | contextMenu.Show(this, PointToClient(MousePosition)); 213 | } 214 | } 215 | 216 | private void AddDevice(LonDevice dev) 217 | { 218 | (MdiParent as LonScannerMain).AddDevice(dev); 219 | } 220 | 221 | public void DataReceived(LonPPdu pdu) 222 | { 223 | BeginInvoke(new Action(() => 224 | { 225 | if (pdu.NPDU != null) 226 | { 227 | lock (Items) 228 | { 229 | int address = (int)pdu.NPDU.Address.SourceNode; 230 | string possible = ""; 231 | 232 | if (address == Config.SourceNode) 233 | { 234 | possible = "(this tool)"; 235 | } 236 | else if (AddressGuesses.ContainsKey(address)) 237 | { 238 | possible = "Guess: " + AddressGuesses[address]; 239 | } 240 | 241 | if (!Packets.ContainsKey(address)) 242 | { 243 | var item = new ListViewItem(new string[] { "" + address, "" + 0, possible, "", "" }); 244 | Items.Add(address, item); 245 | Packets.Add(address, 0); 246 | lstDevices.Items.Add(item); 247 | } 248 | 249 | if (pdu.NPDU.PDU is LonSPdu spdu) 250 | { 251 | if (spdu.APDU is LonAPduGenericApplication apdu) 252 | { 253 | if (apdu.Code == 0x21) 254 | { 255 | byte[] neuron = new byte[6]; 256 | byte[] prog_str = new byte[8]; 257 | 258 | Array.Copy(apdu.Data, 0, neuron, 0, neuron.Length); 259 | Array.Copy(apdu.Data, 6, prog_str, 0, prog_str.Length); 260 | Items[address].SubItems[3].Text = BitConverter.ToString(neuron).Replace("-", ""); 261 | Items[address].SubItems[4].Text = BitConverter.ToString(prog_str).Replace("-", ""); 262 | 263 | var candid = Config.DeviceConfigs.Where(d => d.ProgramId == Items[address].SubItems[4].Text); 264 | if (candid.Count() > 0) 265 | { 266 | possible = ""; 267 | foreach (var cand in candid) 268 | { 269 | possible += cand.Name + ", "; 270 | } 271 | Items[address].SubItems[2].Text = "Match: " + possible.Trim(new[] { ' ', ',' }); 272 | } 273 | } 274 | } 275 | } 276 | 277 | Packets[address]++; 278 | Items[address].SubItems[1].Text = "" + Packets[address]; 279 | Items.Values.ToList().ForEach(x => x.Selected = false); 280 | Items[address].Selected = true; 281 | } 282 | } 283 | })); 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /LonScan/LonScannerMain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Threading; 9 | using System.Windows.Forms; 10 | 11 | /* 12 | Icons: 13 | https://www.flaticon.com/free-icon/target_3094446 14 | https://pixabay.com/vectors/add-cross-green-maths-plus-symbol-159647/ 15 | https://pixabay.com/vectors/icons-technology-devices-1312802/ 16 | 17 | convert dev.png -bordercolor white -border 0 \( -clone 0 -resize 16x16 \) \( -clone 0 -resize 32x32 \) \( -clone 0 -resize 48x48 \) \( -clone 0 -resize 64x64 \) -delete 0 -alpha off -colors 256 dev.ico 18 | */ 19 | 20 | 21 | namespace LonScan 22 | { 23 | public partial class LonScannerMain : Form 24 | { 25 | public LonNetwork Network; 26 | public Config Config; 27 | private Thread LatencyThread; 28 | private bool Exiting = false; 29 | 30 | public LonScannerMain() 31 | { 32 | InitializeComponent(); 33 | 34 | Text = Text + " " + typeof(LonScannerMain).Assembly.GetCustomAttribute().InformationalVersion; 35 | 36 | LoadConfig(); 37 | 38 | try 39 | { 40 | Network = new LonNetwork(Config); 41 | Network.Start(); 42 | } 43 | catch(Exception ex) 44 | { 45 | MessageBox.Show("Failed to bring up network: " + ex.Message); 46 | throw ex; 47 | } 48 | 49 | LatencyThread = new Thread(LatencyThreadMain); 50 | LatencyThread.Start(); 51 | } 52 | 53 | private void LatencyThreadMain() 54 | { 55 | while (!Exiting) 56 | { 57 | long unixTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); 58 | 59 | LonPPdu pdu = new LonPPdu 60 | { 61 | NPDU = new LonNPdu 62 | { 63 | Address = new LonAddressNode 64 | { 65 | SourceSubnet = Config.SourceSubnet, 66 | SourceNode = Config.SourceNode, 67 | DestinationSubnet = Config.SourceSubnet, 68 | DestinationNode = Config.SourceNode 69 | }, 70 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 71 | Domain = 0x54, 72 | PDU = new LonSPdu 73 | { 74 | SPDUType = LonSPdu.LonSPduType.Response, 75 | APDU = new LonAPduGenericApplication 76 | { 77 | Code = 1, 78 | Data = BitConverter.GetBytes(unixTime) 79 | } 80 | } 81 | } 82 | }; 83 | 84 | double latency = -1; 85 | 86 | bool success = Network.SendMessage(pdu, (p) => 87 | { 88 | if (!(p.NPDU.PDU is LonSPdu spdu)) 89 | { 90 | return; 91 | } 92 | 93 | if (!(spdu.APDU is LonAPduGenericApplication apdu) || apdu.Code != 1 || apdu.Data.Length != 8) 94 | { 95 | return; 96 | } 97 | 98 | long ts = BitConverter.ToInt64(apdu.Data, 0); 99 | DateTimeOffset ofs = DateTimeOffset.FromUnixTimeMilliseconds(ts); 100 | 101 | TimeSpan delta = DateTimeOffset.Now - ofs; 102 | latency = delta.TotalMilliseconds; 103 | 104 | }, Config.LatencyCheckTime, 1); 105 | 106 | Thread.Sleep(Config.LatencyCheckTime); 107 | 108 | int loss = (Network.PacketsTimedOut * 100) / Network.PacketsSent; 109 | string latStr = "-timeout-"; 110 | if (latency > 0) 111 | { 112 | latStr = latency.ToString("0") + " ms"; 113 | } 114 | string stats = "Latency: " + latStr + ", " + loss + "% loss, Sent: " + Network.PacketsSent + " Received: " + Network.PacketsReceived + " Timeouts: " + Network.PacketsTimedOut; 115 | 116 | Color col = Color.Black; 117 | 118 | if (loss > 20 || latency > Config.PacketTimeout / Config.PacketRetries) 119 | { 120 | col = Color.Red; 121 | } 122 | 123 | BeginInvoke(new Action(() => 124 | { 125 | toolStripLatency.Text = stats; 126 | toolStripLatency.ForeColor = col; 127 | })); 128 | } 129 | } 130 | 131 | private void LoadConfig() 132 | { 133 | if (!File.Exists(Config.ConfigFile)) 134 | { 135 | Config = new Config(); 136 | Config.Save(); 137 | } 138 | 139 | Config = Config.Load(); 140 | 141 | if (Config == null) 142 | { 143 | MessageBox.Show("Config invalid, using default config", "Config file error"); 144 | Config = new Config(); 145 | Config.Save(); 146 | } 147 | } 148 | 149 | protected override void OnClosing(CancelEventArgs e) 150 | { 151 | Exiting = true; 152 | Network.Stop(); 153 | LatencyThread.Join(); 154 | base.OnClosing(e); 155 | } 156 | 157 | private void ExitToolsStripMenuItem_Click(object sender, EventArgs e) 158 | { 159 | this.Close(); 160 | } 161 | 162 | private void CascadeToolStripMenuItem_Click(object sender, EventArgs e) 163 | { 164 | LayoutMdi(MdiLayout.Cascade); 165 | } 166 | 167 | private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e) 168 | { 169 | LayoutMdi(MdiLayout.TileVertical); 170 | } 171 | 172 | private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) 173 | { 174 | LayoutMdi(MdiLayout.TileHorizontal); 175 | } 176 | 177 | private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) 178 | { 179 | LayoutMdi(MdiLayout.ArrangeIcons); 180 | } 181 | 182 | private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e) 183 | { 184 | foreach (Form childForm in MdiChildren) 185 | { 186 | childForm.Close(); 187 | } 188 | } 189 | 190 | private void btnAdd_Click(object sender, EventArgs e) 191 | { 192 | ContextMenu contextMenu = new ContextMenu(); 193 | 194 | foreach (LonDeviceConfig cfg in Config.DeviceConfigs) 195 | { 196 | foreach (int addr in cfg.Addresses) 197 | { 198 | contextMenu.MenuItems.Add(new MenuItem(cfg.Name + " (Address #" + addr + ")", (s, ev) => 199 | { 200 | LonDevice dev = new LonDevice((s as MenuItem).Text, addr, Network, cfg); 201 | AddDevice(dev); 202 | })); 203 | } 204 | } 205 | 206 | contextMenu.Show(this, PointToClient(MousePosition)); 207 | } 208 | 209 | internal void AddDevice(LonDevice dev) 210 | { 211 | DeviceForm form = new DeviceForm(dev) { MdiParent = this }; 212 | form.Show(); 213 | } 214 | 215 | private void btnScan_Click(object sender, EventArgs e) 216 | { 217 | ScanForm form = new ScanForm(Network, Config) { MdiParent = this }; 218 | form.Show(); 219 | } 220 | 221 | private void updateSystemTimeToolStripMenuItem_Click(object sender, EventArgs e) 222 | { 223 | DateTime now = DateTime.Now; 224 | byte[] time = new byte[7]; 225 | 226 | time[0] = (byte)(now.Year >> 8); 227 | time[1] = (byte)(now.Year >> 0); 228 | time[2] = (byte)(now.Month); 229 | time[3] = (byte)(now.Day); 230 | time[4] = (byte)(now.Hour); 231 | time[5] = (byte)(now.Minute); 232 | time[6] = (byte)(now.Second); 233 | 234 | for (int group = 0; group < 3; group++) 235 | { 236 | LonPPdu pdu = new LonPPdu 237 | { 238 | NPDU = new LonNPdu 239 | { 240 | Address = new LonAddressGroup 241 | { 242 | SourceSubnet = 1, 243 | SourceNode = 126, 244 | DestinationGroup = (uint)group 245 | }, 246 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 247 | Domain = 0x54, 248 | PDU = new LonAPduNetworkVariable 249 | { 250 | Selector = 0x100, 251 | Data = time 252 | } 253 | } 254 | }; 255 | /* 00 00 00 03 08 31 00 256 | * 257 | int year = GetSigned(data, offset + 0, 1); 258 | uint month = GetUnsigned(data, offset + 2, 1); 259 | uint day = GetUnsigned(data, offset + 3, 1); 260 | uint hour = GetUnsigned(data, offset + 4, 1); 261 | uint minute = GetUnsigned(data, offset + 5, 1); 262 | uint second = GetUnsigned(data, offset + 6, 1); 263 | */ 264 | 265 | bool success = Network.SendMessage(pdu, (p) => 266 | { 267 | }); 268 | } 269 | } 270 | 271 | private void TestFunc_Click(object sender, EventArgs e) 272 | { 273 | //string msg = "01 09 01 DA 01 8F 54 01 0E 25 06 23 06 02 C8 00 40 95 03 CD 63"; 274 | //string msg = "01 19 01 DA 01 8F 54 0F 0E 24 06 21 04 02 C8 00 40"; 275 | string msg = "01 19 01 DA 01 8F 54 0F 0B 02 01"; 276 | byte[] data = msg.Split(' ').Select(b => Convert.ToByte(b, 16)).ToArray(); 277 | 278 | var pdu = LonPPdu.FromData(data, 0, data.Length); 279 | //pdu.NPDU.DestinationNode = 10; 280 | //pdu.NPDU.SourceSubnet = 1; 281 | //pdu.NPDU.DestinationSubnet= 1; 282 | 283 | string text = PacketForge.ToString(pdu); 284 | Console.WriteLine(text); 285 | 286 | //pdu.NPDU.PDU = (pdu.NPDU.PDU as LonSPdu).APDU; 287 | 288 | bool success = Network.SendMessage(pdu, (p) => 289 | { 290 | }); 291 | return; 292 | 293 | /* 294 | for (int group = 0; group < 3 295 | ; group++) 296 | { 297 | LonPPdu pdu = new LonPPdu 298 | { 299 | NPDU = new LonNPdu 300 | { 301 | AddressFormat = LonNPdu.LonNPduAddressFormat.Group, 302 | SourceSubnet = 1, 303 | SourceNode = 126, 304 | DestinationGroup = (uint)group, 305 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 306 | Domain = 0x54, 307 | PDU = new LonAPduNetworkManagement 308 | { 309 | Code = (int)LonAPdu.LonAPduNMType. 310 | Data = time 311 | } 312 | } 313 | }; 314 | 315 | bool success = Network.SendMessage(pdu, (p) => 316 | { 317 | }); 318 | */ 319 | } 320 | 321 | private void ladeXIFToolStripMenuItem_Click(object sender, EventArgs e) 322 | { 323 | OpenFileDialog dlg = new OpenFileDialog(); 324 | dlg.Filter = "XIF files (*.xif)|*.xif|All files (*.*)|*.*"; 325 | dlg.RestoreDirectory = true; 326 | dlg.Multiselect = true; 327 | 328 | if (dlg.ShowDialog() == DialogResult.OK) 329 | { 330 | foreach (string s in dlg.FileNames) 331 | { 332 | try 333 | { 334 | XifFile xif = new XifFile(s); 335 | 336 | if (Config.DeviceConfigs.Any(c => c.Name == xif.DeviceName)) 337 | { 338 | continue; 339 | } 340 | Config.AddDeviceConfig(xif.ToDeviceConfig()); 341 | } 342 | catch 343 | { 344 | 345 | } 346 | } 347 | Config.Save(); 348 | } 349 | } 350 | 351 | private void packetForgeToolStripMenuItem_Click(object sender, EventArgs e) 352 | { 353 | PacketForgeDlg form = new PacketForgeDlg(Network, Config) { MdiParent = this }; 354 | form.Show(); 355 | } 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /LonScan/LonNetwork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Net.NetworkInformation; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using System.Linq; 8 | using System.Windows.Forms; 9 | 10 | namespace LonScan 11 | { 12 | public class LonNetwork 13 | { 14 | public bool ThreadStop = false; 15 | private Thread ReceiveThread; 16 | 17 | public delegate void ResponseCallback(LonPPdu ppdu); 18 | private readonly Dictionary PendingRequests = new Dictionary(); 19 | private readonly Config Config; 20 | private readonly IPAddress Remote; 21 | private readonly IPEndPoint RemoteEndpoint; 22 | private readonly Socket SendSocket; 23 | private readonly UdpClient ReceiveClient; 24 | private int NextTransaction = 0; 25 | private bool Stopped; 26 | internal Action OnReceive; 27 | internal int SourceNode => Config.SourceNode; 28 | internal DateTime LastPacket = DateTime.Now; 29 | 30 | public int PacketsSent; 31 | public int PacketsReceived; 32 | public int PacketsTimedOut; 33 | 34 | 35 | public LonNetwork(Config config) 36 | { 37 | Config = config; 38 | 39 | Remote = null; 40 | 41 | if (IPAddress.TryParse(Config.RemoteAddress, out var ipAddress)) 42 | { 43 | Remote = ipAddress; 44 | } 45 | else if(Config.RemoteAddress != null && Config.RemoteAddress.Length > 0) 46 | { 47 | try 48 | { 49 | var hostAddresses = Dns.GetHostAddresses(Config.RemoteAddress); 50 | if (hostAddresses.Length == 0) 51 | { 52 | MessageBox.Show($"Warning: Unable to resolve hostname: {Config.RemoteAddress}. Using broadcast address.", "Resolve error"); 53 | } 54 | else 55 | { 56 | Remote = hostAddresses[0]; 57 | } 58 | } 59 | catch(Exception ex) 60 | { 61 | MessageBox.Show($"Warning: Unable to resolve hostname: {Config.RemoteAddress}", "Resolve error", MessageBoxButtons.OK, MessageBoxIcon.Warning); 62 | } 63 | } 64 | 65 | if (Remote == null) 66 | { 67 | var allIf = NetworkInterface.GetAllNetworkInterfaces() 68 | .Where(n => n.OperationalStatus == OperationalStatus.Up); 69 | 70 | // Get default gateway 71 | var defaultGateway = 72 | allIf.SelectMany(n => n.GetIPProperties()?.GatewayAddresses) 73 | .FirstOrDefault(g => g?.Address != null && g.Address.AddressFamily.ToString() == "InterNetwork"); 74 | 75 | if (defaultGateway == null) 76 | { 77 | throw new ArgumentException("No default gateway found."); 78 | } 79 | 80 | // Find network interface with default gateway 81 | var networkInterface = allIf.Where(n => n.GetIPProperties().GatewayAddresses.Contains(defaultGateway)) 82 | .FirstOrDefault(); 83 | 84 | if (networkInterface == null) 85 | { 86 | throw new ArgumentException("No network interface with default gateway found."); 87 | } 88 | 89 | // Get IP and subnet mask 90 | var ipInfo = networkInterface.GetIPProperties().UnicastAddresses 91 | .Where(a => a.Address.AddressFamily == AddressFamily.InterNetwork) 92 | .FirstOrDefault(); 93 | 94 | if (ipInfo == null) 95 | { 96 | throw new ArgumentException("No IPv4 address found for network interface."); 97 | } 98 | 99 | // Calculate broadcast address 100 | byte[] ipAdressBytes = ipInfo.Address.GetAddressBytes(); 101 | byte[] subnetMaskBytes = ipInfo.IPv4Mask.GetAddressBytes(); 102 | 103 | Remote = GetBroadcastAddress(ipInfo.Address, ipInfo.IPv4Mask); 104 | } 105 | 106 | if (IsBroadcastAddress(Remote)) 107 | { 108 | MessageBox.Show("Warning: Using broadcast address can lead to high latency or drop rate!" + Environment.NewLine + "Please specify the IP address in LonScan.cfg, field 'RemoteAddress'", "Broadcast Address Warning", 109 | MessageBoxButtons.OK, MessageBoxIcon.Warning); 110 | } 111 | 112 | RemoteEndpoint = new IPEndPoint(Remote, Config.RemoteSendPort); 113 | SendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 114 | ReceiveClient = new UdpClient(Config.RemoteReceivePort); 115 | 116 | OnReceive += (p) => { }; 117 | } 118 | 119 | private bool IsBroadcastAddress(IPAddress ipAddress) 120 | { 121 | foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces()) 122 | { 123 | foreach (var unicastIPAddressInformation in networkInterface.GetIPProperties().UnicastAddresses) 124 | { 125 | if (unicastIPAddressInformation.Address.AddressFamily == AddressFamily.InterNetwork) 126 | { 127 | var broadcastAddress = GetBroadcastAddress(unicastIPAddressInformation.Address, unicastIPAddressInformation.IPv4Mask); 128 | if (ipAddress.Equals(broadcastAddress)) 129 | { 130 | return true; 131 | } 132 | } 133 | } 134 | } 135 | 136 | return false; 137 | } 138 | 139 | private IPAddress GetBroadcastAddress(IPAddress ipAddress, IPAddress subnetMask) 140 | { 141 | byte[] ipAddressBytes = ipAddress.GetAddressBytes(); 142 | byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 143 | 144 | if (ipAddressBytes.Length != subnetMaskBytes.Length) 145 | { 146 | throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 147 | } 148 | 149 | byte[] broadcastAddressBytes = new byte[ipAddressBytes.Length]; 150 | for (int i = 0; i < broadcastAddressBytes.Length; i++) 151 | { 152 | broadcastAddressBytes[i] = (byte)(ipAddressBytes[i] | (subnetMaskBytes[i] ^ 255)); 153 | } 154 | 155 | return new IPAddress(broadcastAddressBytes); 156 | } 157 | 158 | public void Start() 159 | { 160 | ThreadStop = false; 161 | ReceiveThread = new Thread(ThreadReceive); 162 | ReceiveThread.Start(); 163 | } 164 | 165 | /// 166 | /// Send a message to the network, waiting for the response 167 | /// 168 | /// payload to send to the network 169 | /// callback to be called upon a response 170 | /// time to wait for the response in ms, 0 = wait forever, -1 = do not wait at all 171 | /// Returns true when a response arrived in time, false when waiting timed out. 172 | public bool SendMessage(LonPPdu pdu, ResponseCallback response, int waitTime = -2, int maxTries = 0) 173 | { 174 | int trans; 175 | 176 | if (maxTries <= 0) 177 | { 178 | maxTries = Config.PacketRetries; 179 | } 180 | if (waitTime == -2) 181 | { 182 | waitTime = Config.PacketTimeout; 183 | } 184 | 185 | /* update source subnet/address if needed */ 186 | if (pdu.NPDU.Address.SourceSubnet == -1) 187 | { 188 | pdu.NPDU.Address.SourceSubnet = Config.SourceSubnet; 189 | } 190 | if (pdu.NPDU.Address.SourceNode == -1) 191 | { 192 | pdu.NPDU.Address.SourceNode = Config.SourceNode; 193 | } 194 | 195 | for (int retry = 0; retry < maxTries; retry++) 196 | { 197 | lock (PendingRequests) 198 | { 199 | /* delay transmission to prevent flooding */ 200 | while ((DateTime.Now - LastPacket).TotalMilliseconds < Config.PacketDelay) 201 | { 202 | Thread.Sleep(5); 203 | } 204 | 205 | do 206 | { 207 | if (PendingRequests.Count > 5) 208 | { 209 | Monitor.Wait(PendingRequests, 10); 210 | } 211 | 212 | trans = NextTransaction; 213 | NextTransaction++; 214 | NextTransaction %= 8; 215 | 216 | } while (PendingRequests.ContainsKey(trans)); 217 | 218 | if (waitTime >= 0) 219 | { 220 | PendingRequests.Add(trans, response); 221 | } 222 | 223 | /* replace transaction ID */ 224 | if (pdu.NPDU.PDU is LonTransPdu lonpdu) 225 | { 226 | lonpdu.TransNo = (uint)trans; 227 | } 228 | 229 | LastPacket = DateTime.Now; 230 | PacketsSent++; 231 | SendSocket.SendTo(pdu.FrameBytes, RemoteEndpoint); 232 | 233 | var sendTime = LastPacket; 234 | if (waitTime >= 0) 235 | { 236 | while ((DateTime.Now - sendTime).TotalMilliseconds < (waitTime / maxTries) || waitTime == 0) 237 | { 238 | Monitor.Wait(PendingRequests, 10); 239 | 240 | if (!PendingRequests.ContainsKey(trans)) 241 | { 242 | PacketsReceived++; 243 | return true; 244 | } 245 | if (Stopped) 246 | { 247 | return false; 248 | } 249 | } 250 | PacketsTimedOut++; 251 | PendingRequests.Remove(trans); 252 | } 253 | } 254 | } 255 | 256 | return false; 257 | } 258 | 259 | void ThreadReceive() 260 | { 261 | IPEndPoint receiveEndpoint = new IPEndPoint(IPAddress.Any, 0); 262 | 263 | ReceiveClient.Client.ReceiveBufferSize = 1024 * 1024; 264 | 265 | while (!ThreadStop) 266 | { 267 | byte[] bytes = ReceiveClient.Receive(ref receiveEndpoint); 268 | 269 | /* only parse packets, no status responses */ 270 | if (bytes[0] != 2) 271 | { 272 | continue; 273 | } 274 | /* ignore packets with CRC errors */ 275 | if (bytes[1] != 0) 276 | { 277 | continue; 278 | } 279 | /* ignore packets which are too short */ 280 | if (bytes.Length < 8) 281 | { 282 | continue; 283 | } 284 | 285 | try 286 | { 287 | LonPPdu parsed = LonPPdu.FromData(bytes, 6, bytes.Length - 8); 288 | PacketReceived(parsed); 289 | } 290 | catch (Exception ex) 291 | { 292 | Console.WriteLine("Failed to parse packet: " + BitConverter.ToString(bytes).Replace("-", " ")); 293 | Console.WriteLine(ex); 294 | } 295 | } 296 | 297 | ReceiveClient.Close(); 298 | } 299 | 300 | private void PacketReceived(LonPPdu pdu) 301 | { 302 | Console.WriteLine(BitConverter.ToString(pdu.FrameBytes).Replace("-", " ")); 303 | Console.WriteLine(); 304 | Console.WriteLine(PacketForge.ToString(pdu)); 305 | 306 | OnReceive(pdu); 307 | 308 | if (!pdu.NPDU.Address.ForNode(Config.SourceNode)) 309 | { 310 | return; 311 | } 312 | if (!pdu.NPDU.Address.ForSubnet(Config.SourceSubnet)) 313 | { 314 | return; 315 | } 316 | 317 | if (!(pdu.NPDU.PDU is LonSPdu spdu)) 318 | { 319 | return; 320 | } 321 | 322 | lock (PendingRequests) 323 | { 324 | if (spdu.SPDUType == LonSPdu.LonSPduType.Response && PendingRequests.ContainsKey((int)spdu.TransNo)) 325 | { 326 | PendingRequests[(int)spdu.TransNo]?.Invoke(pdu); 327 | PendingRequests.Remove((int)spdu.TransNo); 328 | Monitor.Pulse(PendingRequests); 329 | } 330 | } 331 | } 332 | 333 | public void Stop() 334 | { 335 | Stopped = true; 336 | if (ReceiveThread != null) 337 | { 338 | ThreadStop = true; 339 | ReceiveThread.Join(500); 340 | } 341 | PendingRequests.Clear(); 342 | } 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /LonScan/LonDevice.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.ExceptionServices; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | namespace LonScan 9 | { 10 | public class LonDevice 11 | { 12 | public readonly string Name; 13 | public readonly int Address; 14 | public LonDeviceConfig Config; 15 | public Dictionary NvConfigTable = new Dictionary(); 16 | 17 | public readonly LonNetwork Network; 18 | private bool ThreadStop; 19 | private Thread ScanThread = null; 20 | 21 | public delegate void NvUpdateCallback(LonDevice device, int nv, string hex, string value); 22 | public event NvUpdateCallback OnNvUpdate; 23 | public delegate void UpdateCallback(LonDevice device); 24 | public event UpdateCallback OnUpdate; 25 | 26 | public byte[] ConfigMem = new byte[0x30]; 27 | 28 | public string ConfigVersion; 29 | public string ConfigDate; 30 | public string ConfigProduct; 31 | 32 | public LonDevice(string name, int address, LonNetwork network, LonDeviceConfig config) 33 | { 34 | Name = name; 35 | Address = address; 36 | Network = network; 37 | Config = config; 38 | 39 | OnNvUpdate += (d, n, h, v) => { }; 40 | OnUpdate += (d) => { }; 41 | } 42 | 43 | public byte[] ReadMemory(uint address, int length, Action progress = null) 44 | { 45 | byte[] result = new byte[0]; 46 | 47 | for (uint off = 0; off < length; off += 0x10) 48 | { 49 | LonPPdu pdu = new LonPPdu 50 | { 51 | NPDU = new LonNPdu 52 | { 53 | Address = new LonAddressNode 54 | { 55 | SourceSubnet = -1, 56 | SourceNode = -1, /* automatically set */ 57 | DestinationSubnet = 1, 58 | DestinationNode = Address 59 | }, 60 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 61 | Domain = 0x54, 62 | PDU = new LonSPdu 63 | { 64 | SPDUType = LonSPdu.LonSPduType.Request, 65 | APDU = LonAPduNetworkManagement.GenerateNMMemoryRead(0, address + off, 0x10) 66 | } 67 | } 68 | }; 69 | bool success = Network.SendMessage(pdu, (p) => 70 | { 71 | LonSPdu spdu = (p.NPDU.PDU as LonSPdu); 72 | if (spdu != null && spdu.APDU is LonAPduGenericApplication) 73 | { 74 | LonAPduGenericApplication apdu = (spdu.APDU as LonAPduGenericApplication); 75 | 76 | /* mem read successful */ 77 | if ((apdu.Code & 0x20) != 0 && (apdu.Code & 0x1F) == (int)LonAPduNetworkManagement.LonAPduNMType.ReadMemory && apdu.Payload.Length > 0) 78 | { 79 | Array.Resize(ref result, (int)(off + apdu.Payload.Length)); 80 | Array.Copy(apdu.Payload, 0, result, off, apdu.Payload.Length); 81 | } 82 | } 83 | }, 5000, 5); 84 | 85 | if(progress != null) 86 | { 87 | progress((decimal)result.Length / length); 88 | } 89 | 90 | if(!success) 91 | { 92 | break; 93 | } 94 | } 95 | 96 | return result; 97 | } 98 | 99 | 100 | public void StartNvScan() 101 | { 102 | ThreadStop = false; 103 | ScanThread = new Thread(() => 104 | { 105 | bool versionFetched = false; 106 | 107 | while (true) 108 | { 109 | if(!versionFetched) 110 | { 111 | for (uint addr = 0; addr < ConfigMem.Length; addr += 0x10) 112 | { 113 | LonPPdu pdu = new LonPPdu 114 | { 115 | NPDU = new LonNPdu 116 | { 117 | Address = new LonAddressNode 118 | { 119 | SourceSubnet = -1, 120 | SourceNode = -1, /* automatically set */ 121 | DestinationSubnet = 1, 122 | DestinationNode = Address 123 | }, 124 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 125 | Domain = 0x54, 126 | PDU = new LonSPdu 127 | { 128 | SPDUType = LonSPdu.LonSPduType.Request, 129 | APDU = LonAPduNetworkManagement.GenerateNMMemoryRead(0, 0x4000 + addr, 0x10) 130 | } 131 | } 132 | }; 133 | bool success = Network.SendMessage(pdu, (p) => 134 | { 135 | LonSPdu spdu = (p.NPDU.PDU as LonSPdu); 136 | if (spdu != null && spdu.APDU is LonAPduGenericApplication) 137 | { 138 | LonAPduGenericApplication apdu = (spdu.APDU as LonAPduGenericApplication); 139 | 140 | /* mem read successful */ 141 | if((apdu.Code & 0x20) != 0 && (apdu.Code & 0x1F) == (int)LonAPduNetworkManagement.LonAPduNMType.ReadMemory && apdu.Payload.Length == 0x10) 142 | { 143 | Array.Copy(apdu.Payload, 0, ConfigMem, addr, 0x10); 144 | } 145 | } 146 | }, 5000, 5); 147 | } 148 | 149 | versionFetched = true; 150 | UpdateConfigStrings(); 151 | } 152 | 153 | foreach (var info in Config.NvMap) 154 | { 155 | int nvIndex = info.Key; 156 | 157 | if (ThreadStop) 158 | { 159 | return; 160 | } 161 | 162 | if(!NvConfigTable.ContainsKey(nvIndex)) 163 | { 164 | LonPPdu nvpdu = new LonPPdu 165 | { 166 | NPDU = new LonNPdu 167 | { 168 | Address = new LonAddressNode 169 | { 170 | SourceSubnet = -1, 171 | SourceNode = -1, /* automatically set */ 172 | DestinationSubnet = 1, 173 | DestinationNode = Address 174 | }, 175 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 176 | Domain = 0x54, 177 | PDU = new LonSPdu 178 | { 179 | SPDUType = LonSPdu.LonSPduType.Request, 180 | APDU = new LonAPduNetworkManagement 181 | { 182 | Code = LonAPdu.LonAPduNMType.QueryNetworkVariableConfig, 183 | Data = new byte[] { (byte)nvIndex } 184 | } 185 | } 186 | } 187 | }; 188 | 189 | Network.SendMessage(nvpdu, (p) => 190 | { 191 | LonSPdu spdu = (p.NPDU.PDU as LonSPdu); 192 | if (spdu != null && spdu.APDU is LonAPduGenericApplication) 193 | { 194 | LonAPduGenericApplication apdu = (spdu.APDU as LonAPduGenericApplication); 195 | 196 | /* query nv config successful */ 197 | if ((apdu.Code & 0x20) != 0 && (apdu.Code & 0x1F) == (int)LonAPduNetworkManagement.LonAPduNMType.QueryNetworkVariableConfig) 198 | { 199 | LonAPdu.NvConfig cfg = LonAPdu.NvConfig.FromData(apdu.Data); 200 | NvConfigTable.Add(nvIndex, cfg); 201 | } 202 | } 203 | }); 204 | } 205 | 206 | LonPPdu pdu = new LonPPdu 207 | { 208 | NPDU = new LonNPdu 209 | { 210 | Address = new LonAddressNode 211 | { 212 | SourceSubnet = -1, 213 | SourceNode = -1, /* automatically set */ 214 | DestinationSubnet = 1, 215 | DestinationNode = Address 216 | }, 217 | DomainLength = LonNPdu.LonNPduDomainLength.Bits_8, 218 | Domain = 0x54, 219 | PDU = new LonSPdu 220 | { 221 | SPDUType = LonSPdu.LonSPduType.Request, 222 | APDU = new LonAPduNetworkManagement 223 | { 224 | Code = LonAPdu.LonAPduNMType.NetworkVariableValueFetch, 225 | Data = new byte[] { (byte)info.Key } 226 | } 227 | } 228 | } 229 | }; 230 | 231 | bool success = Network.SendMessage(pdu, (p) => 232 | { 233 | MessageReceived(p); 234 | }); 235 | } 236 | } 237 | }); 238 | ScanThread.Start(); 239 | } 240 | 241 | private void UpdateConfigStrings() 242 | { 243 | int pos = 3; 244 | 245 | ConfigVersion = GetString(ConfigMem, ref pos); 246 | ConfigDate = GetString(ConfigMem, ref pos); 247 | ConfigProduct = GetString(ConfigMem, ref pos); 248 | 249 | OnUpdate(this); 250 | } 251 | 252 | private string GetString(byte[] buf, ref int pos) 253 | { 254 | int length = 0; 255 | 256 | while(pos < buf.Length && buf[pos] == 0) 257 | { 258 | pos++; 259 | } 260 | if(pos == buf.Length && buf[pos] == 0) 261 | { 262 | return ""; 263 | } 264 | 265 | for(int lenChk = pos; lenChk < buf.Length; lenChk++) 266 | { 267 | if(buf[lenChk] == 0) 268 | { 269 | break; 270 | } 271 | length++; 272 | } 273 | 274 | byte[] strBuf = new byte[length]; 275 | Array.Copy(buf, pos, strBuf, 0, length); 276 | 277 | pos += length + 1; 278 | 279 | string str = Encoding.ASCII.GetString(strBuf); 280 | 281 | return str; 282 | } 283 | 284 | public void StopNvScan() 285 | { 286 | if (ScanThread != null) 287 | { 288 | ThreadStop = true; 289 | ScanThread.Join(500); 290 | } 291 | } 292 | 293 | void MessageReceived(LonPPdu pdu) 294 | { 295 | if (pdu.NPDU.Address.ForNode(Address)) 296 | { 297 | return; 298 | } 299 | 300 | if (!(pdu.NPDU.PDU is LonSPdu spdu)) 301 | { 302 | return; 303 | } 304 | 305 | if (!(spdu.APDU is LonAPduGenericApplication apdu)) 306 | { 307 | return; 308 | } 309 | 310 | if ((apdu.Code & 0x1F) != (uint)LonAPdu.LonAPduNMType.NetworkVariableValueFetch) 311 | { 312 | return; 313 | } 314 | 315 | int nv_recv = apdu.Data[0]; 316 | NvInfo info = Config.NvMap[nv_recv]; 317 | 318 | string hex = ""; 319 | 320 | for (int pos = 1; pos < apdu.Data.Length; pos++) 321 | { 322 | hex += apdu.Data[pos].ToString("X2"); 323 | if ((pos % 2) == 1) 324 | { 325 | hex += " "; 326 | } 327 | } 328 | 329 | string value = LonStandardTypes.ToString(apdu.Data, 1, apdu.Data.Length - 1, info.Type); 330 | 331 | OnNvUpdate(this, nv_recv, hex, value); 332 | } 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /LonScan/DeviceForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LonScan 2 | { 3 | partial class DeviceForm 4 | { 5 | /// 6 | /// Erforderliche Designervariable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Verwendete Ressourcen bereinigen. 12 | /// 13 | /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Vom Windows Form-Designer generierter Code 24 | 25 | /// 26 | /// Erforderliche Methode für die Designerunterstützung. 27 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceForm)); 32 | this.listView1 = new System.Windows.Forms.ListView(); 33 | this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 34 | this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 35 | this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 36 | this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 37 | this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 38 | this.columnHeader6a = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 39 | this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 40 | this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 41 | this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 42 | this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 43 | this.columnHeader10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 44 | this.columnHeader12 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 45 | this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 46 | this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 47 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 48 | this.label3 = new System.Windows.Forms.Label(); 49 | this.txtFirmwareDate = new System.Windows.Forms.TextBox(); 50 | this.label2 = new System.Windows.Forms.Label(); 51 | this.txtFirmwareVer = new System.Windows.Forms.TextBox(); 52 | this.label1 = new System.Windows.Forms.Label(); 53 | this.txtFirmwareProd = new System.Windows.Forms.TextBox(); 54 | this.btnDumpFlash = new System.Windows.Forms.Button(); 55 | this.progressBar1 = new System.Windows.Forms.ProgressBar(); 56 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 57 | this.splitContainer1.Panel1.SuspendLayout(); 58 | this.splitContainer1.Panel2.SuspendLayout(); 59 | this.splitContainer1.SuspendLayout(); 60 | this.groupBox1.SuspendLayout(); 61 | this.SuspendLayout(); 62 | // 63 | // listView1 64 | // 65 | this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 66 | this.columnHeader1, 67 | this.columnHeader2, 68 | this.columnHeader3, 69 | this.columnHeader4, 70 | this.columnHeader5, 71 | this.columnHeader6a, 72 | this.columnHeader6, 73 | this.columnHeader7, 74 | this.columnHeader8, 75 | this.columnHeader9, 76 | this.columnHeader10, 77 | this.columnHeader12, 78 | this.columnHeader13}); 79 | this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; 80 | this.listView1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 81 | this.listView1.FullRowSelect = true; 82 | this.listView1.HideSelection = false; 83 | this.listView1.Location = new System.Drawing.Point(0, 0); 84 | this.listView1.Name = "listView1"; 85 | this.listView1.Size = new System.Drawing.Size(1165, 376); 86 | this.listView1.TabIndex = 2; 87 | this.listView1.UseCompatibleStateImageBehavior = false; 88 | this.listView1.View = System.Windows.Forms.View.Details; 89 | // 90 | // columnHeader1 91 | // 92 | this.columnHeader1.Text = "NV#"; 93 | this.columnHeader1.Width = 42; 94 | // 95 | // columnHeader2 96 | // 97 | this.columnHeader2.Text = "Name"; 98 | this.columnHeader2.Width = 130; 99 | // 100 | // columnHeader3 101 | // 102 | this.columnHeader3.Text = "Description"; 103 | this.columnHeader3.Width = 141; 104 | // 105 | // columnHeader4 106 | // 107 | this.columnHeader4.Text = "Hex"; 108 | this.columnHeader4.Width = 138; 109 | // 110 | // columnHeader5 111 | // 112 | this.columnHeader5.Text = "Value"; 113 | this.columnHeader5.Width = 155; 114 | // 115 | // columnHeader6a 116 | // 117 | this.columnHeader6a.Text = "Bound"; 118 | // 119 | // columnHeader6 120 | // 121 | this.columnHeader6.Text = "Prio"; 122 | // 123 | // columnHeader7 124 | // 125 | this.columnHeader7.Text = "Dir"; 126 | // 127 | // columnHeader8 128 | // 129 | this.columnHeader8.Text = "NetVar"; 130 | // 131 | // columnHeader9 132 | // 133 | this.columnHeader9.Text = "Turn."; 134 | // 135 | // columnHeader10 136 | // 137 | this.columnHeader10.Text = "Service"; 138 | this.columnHeader10.Width = 67; 139 | // 140 | // columnHeader12 141 | // 142 | this.columnHeader12.Text = "Secure"; 143 | // 144 | // columnHeader13 145 | // 146 | this.columnHeader13.Text = "Addr."; 147 | // 148 | // splitContainer1 149 | // 150 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 151 | this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 152 | this.splitContainer1.IsSplitterFixed = true; 153 | this.splitContainer1.Location = new System.Drawing.Point(0, 0); 154 | this.splitContainer1.Name = "splitContainer1"; 155 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; 156 | // 157 | // splitContainer1.Panel1 158 | // 159 | this.splitContainer1.Panel1.Controls.Add(this.progressBar1); 160 | this.splitContainer1.Panel1.Controls.Add(this.btnDumpFlash); 161 | this.splitContainer1.Panel1.Controls.Add(this.groupBox1); 162 | // 163 | // splitContainer1.Panel2 164 | // 165 | this.splitContainer1.Panel2.Controls.Add(this.listView1); 166 | this.splitContainer1.Size = new System.Drawing.Size(1165, 512); 167 | this.splitContainer1.SplitterDistance = 132; 168 | this.splitContainer1.TabIndex = 3; 169 | // 170 | // groupBox1 171 | // 172 | this.groupBox1.Controls.Add(this.label3); 173 | this.groupBox1.Controls.Add(this.txtFirmwareDate); 174 | this.groupBox1.Controls.Add(this.label2); 175 | this.groupBox1.Controls.Add(this.txtFirmwareVer); 176 | this.groupBox1.Controls.Add(this.label1); 177 | this.groupBox1.Controls.Add(this.txtFirmwareProd); 178 | this.groupBox1.Location = new System.Drawing.Point(12, 12); 179 | this.groupBox1.Name = "groupBox1"; 180 | this.groupBox1.Size = new System.Drawing.Size(173, 113); 181 | this.groupBox1.TabIndex = 0; 182 | this.groupBox1.TabStop = false; 183 | this.groupBox1.Text = "Firmware Details"; 184 | // 185 | // label3 186 | // 187 | this.label3.AutoSize = true; 188 | this.label3.Location = new System.Drawing.Point(6, 78); 189 | this.label3.Name = "label3"; 190 | this.label3.Size = new System.Drawing.Size(30, 13); 191 | this.label3.TabIndex = 5; 192 | this.label3.Text = "Date"; 193 | // 194 | // txtFirmwareDate 195 | // 196 | this.txtFirmwareDate.Location = new System.Drawing.Point(62, 75); 197 | this.txtFirmwareDate.Name = "txtFirmwareDate"; 198 | this.txtFirmwareDate.ReadOnly = true; 199 | this.txtFirmwareDate.Size = new System.Drawing.Size(100, 20); 200 | this.txtFirmwareDate.TabIndex = 4; 201 | this.txtFirmwareDate.Text = "Fetching..."; 202 | // 203 | // label2 204 | // 205 | this.label2.AutoSize = true; 206 | this.label2.Location = new System.Drawing.Point(6, 52); 207 | this.label2.Name = "label2"; 208 | this.label2.Size = new System.Drawing.Size(42, 13); 209 | this.label2.TabIndex = 3; 210 | this.label2.Text = "Version"; 211 | // 212 | // txtFirmwareVer 213 | // 214 | this.txtFirmwareVer.Location = new System.Drawing.Point(62, 49); 215 | this.txtFirmwareVer.Name = "txtFirmwareVer"; 216 | this.txtFirmwareVer.ReadOnly = true; 217 | this.txtFirmwareVer.Size = new System.Drawing.Size(100, 20); 218 | this.txtFirmwareVer.TabIndex = 2; 219 | this.txtFirmwareVer.Text = "Fetching..."; 220 | // 221 | // label1 222 | // 223 | this.label1.AutoSize = true; 224 | this.label1.Location = new System.Drawing.Point(6, 26); 225 | this.label1.Name = "label1"; 226 | this.label1.Size = new System.Drawing.Size(44, 13); 227 | this.label1.TabIndex = 1; 228 | this.label1.Text = "Product"; 229 | // 230 | // txtFirmwareProd 231 | // 232 | this.txtFirmwareProd.Location = new System.Drawing.Point(62, 23); 233 | this.txtFirmwareProd.Name = "txtFirmwareProd"; 234 | this.txtFirmwareProd.ReadOnly = true; 235 | this.txtFirmwareProd.Size = new System.Drawing.Size(100, 20); 236 | this.txtFirmwareProd.TabIndex = 0; 237 | this.txtFirmwareProd.Text = "Fetching..."; 238 | // 239 | // btnDumpFlash 240 | // 241 | this.btnDumpFlash.Location = new System.Drawing.Point(191, 35); 242 | this.btnDumpFlash.Name = "btnDumpFlash"; 243 | this.btnDumpFlash.Size = new System.Drawing.Size(125, 23); 244 | this.btnDumpFlash.TabIndex = 1; 245 | this.btnDumpFlash.Text = "Dump Memory"; 246 | this.btnDumpFlash.UseVisualStyleBackColor = true; 247 | this.btnDumpFlash.Click += new System.EventHandler(this.btnDumpFlash_Click); 248 | // 249 | // progressBar1 250 | // 251 | this.progressBar1.Location = new System.Drawing.Point(191, 61); 252 | this.progressBar1.Name = "progressBar1"; 253 | this.progressBar1.Size = new System.Drawing.Size(124, 16); 254 | this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous; 255 | this.progressBar1.TabIndex = 2; 256 | // 257 | // DeviceForm 258 | // 259 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 260 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 261 | this.ClientSize = new System.Drawing.Size(1165, 512); 262 | this.Controls.Add(this.splitContainer1); 263 | this.DoubleBuffered = true; 264 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 265 | this.Name = "DeviceForm"; 266 | this.Text = "Device Form"; 267 | this.splitContainer1.Panel1.ResumeLayout(false); 268 | this.splitContainer1.Panel2.ResumeLayout(false); 269 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 270 | this.splitContainer1.ResumeLayout(false); 271 | this.groupBox1.ResumeLayout(false); 272 | this.groupBox1.PerformLayout(); 273 | this.ResumeLayout(false); 274 | 275 | } 276 | 277 | #endregion 278 | private System.Windows.Forms.ListView listView1; 279 | private System.Windows.Forms.ColumnHeader columnHeader1; 280 | private System.Windows.Forms.ColumnHeader columnHeader2; 281 | private System.Windows.Forms.ColumnHeader columnHeader3; 282 | private System.Windows.Forms.ColumnHeader columnHeader4; 283 | private System.Windows.Forms.ColumnHeader columnHeader5; 284 | private System.Windows.Forms.SplitContainer splitContainer1; 285 | private System.Windows.Forms.GroupBox groupBox1; 286 | private System.Windows.Forms.Label label3; 287 | private System.Windows.Forms.TextBox txtFirmwareDate; 288 | private System.Windows.Forms.Label label2; 289 | private System.Windows.Forms.TextBox txtFirmwareVer; 290 | private System.Windows.Forms.Label label1; 291 | private System.Windows.Forms.TextBox txtFirmwareProd; 292 | private System.Windows.Forms.ColumnHeader columnHeader6; 293 | private System.Windows.Forms.ColumnHeader columnHeader7; 294 | private System.Windows.Forms.ColumnHeader columnHeader8; 295 | private System.Windows.Forms.ColumnHeader columnHeader9; 296 | private System.Windows.Forms.ColumnHeader columnHeader10; 297 | private System.Windows.Forms.ColumnHeader columnHeader12; 298 | private System.Windows.Forms.ColumnHeader columnHeader13; 299 | private System.Windows.Forms.ColumnHeader columnHeader6a; 300 | private System.Windows.Forms.Button btnDumpFlash; 301 | private System.Windows.Forms.ProgressBar progressBar1; 302 | } 303 | } 304 | 305 | -------------------------------------------------------------------------------- /LonScan/LonScannerMain.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LonScan 2 | { 3 | partial class LonScannerMain 4 | { 5 | /// 6 | /// Erforderliche Designervariable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Verwendete Ressourcen bereinigen. 12 | /// 13 | /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Vom Windows Form-Designer generierter Code 24 | 25 | /// 26 | /// Erforderliche Methode für die Designerunterstützung. 27 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LonScannerMain)); 33 | this.menuStrip = new System.Windows.Forms.MenuStrip(); 34 | this.fileMenu = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.importXIFToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.updateSystemTimeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.packetForgeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); 39 | this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); 41 | this.testFuncToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.windowsMenu = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.cascadeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 44 | this.tileVerticalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 45 | this.tileHorizontalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 46 | this.closeAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 47 | this.toolStrip = new System.Windows.Forms.ToolStrip(); 48 | this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); 49 | this.btnAdd = new System.Windows.Forms.ToolStripButton(); 50 | this.btnScan = new System.Windows.Forms.ToolStripButton(); 51 | this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); 52 | this.toolStripLatency = new System.Windows.Forms.ToolStripLabel(); 53 | this.statusStrip = new System.Windows.Forms.StatusStrip(); 54 | this.toolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); 55 | this.toolTip = new System.Windows.Forms.ToolTip(this.components); 56 | this.menuStrip.SuspendLayout(); 57 | this.toolStrip.SuspendLayout(); 58 | this.statusStrip.SuspendLayout(); 59 | this.SuspendLayout(); 60 | // 61 | // menuStrip 62 | // 63 | this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 64 | this.fileMenu, 65 | this.windowsMenu}); 66 | this.menuStrip.Location = new System.Drawing.Point(0, 0); 67 | this.menuStrip.MdiWindowListItem = this.windowsMenu; 68 | this.menuStrip.Name = "menuStrip"; 69 | this.menuStrip.Size = new System.Drawing.Size(1384, 24); 70 | this.menuStrip.TabIndex = 0; 71 | this.menuStrip.Text = "MenuStrip"; 72 | // 73 | // fileMenu 74 | // 75 | this.fileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 76 | this.importXIFToolStripMenuItem, 77 | this.updateSystemTimeToolStripMenuItem, 78 | this.packetForgeToolStripMenuItem, 79 | this.toolStripMenuItem2, 80 | this.exitToolStripMenuItem, 81 | this.toolStripMenuItem1, 82 | this.testFuncToolStripMenuItem}); 83 | this.fileMenu.ImageTransparentColor = System.Drawing.SystemColors.ActiveBorder; 84 | this.fileMenu.Name = "fileMenu"; 85 | this.fileMenu.Size = new System.Drawing.Size(37, 20); 86 | this.fileMenu.Text = "&File"; 87 | // 88 | // importXIFToolStripMenuItem 89 | // 90 | this.importXIFToolStripMenuItem.Name = "importXIFToolStripMenuItem"; 91 | this.importXIFToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 92 | this.importXIFToolStripMenuItem.Text = "Import .XIF..."; 93 | this.importXIFToolStripMenuItem.Click += new System.EventHandler(this.ladeXIFToolStripMenuItem_Click); 94 | // 95 | // updateSystemTimeToolStripMenuItem 96 | // 97 | this.updateSystemTimeToolStripMenuItem.Name = "updateSystemTimeToolStripMenuItem"; 98 | this.updateSystemTimeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 99 | this.updateSystemTimeToolStripMenuItem.Text = "&Set system time"; 100 | this.updateSystemTimeToolStripMenuItem.Click += new System.EventHandler(this.updateSystemTimeToolStripMenuItem_Click); 101 | // 102 | // packetForgeToolStripMenuItem 103 | // 104 | this.packetForgeToolStripMenuItem.Name = "packetForgeToolStripMenuItem"; 105 | this.packetForgeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 106 | this.packetForgeToolStripMenuItem.Text = "PacketForge"; 107 | this.packetForgeToolStripMenuItem.Click += new System.EventHandler(this.packetForgeToolStripMenuItem_Click); 108 | // 109 | // toolStripMenuItem2 110 | // 111 | this.toolStripMenuItem2.Name = "toolStripMenuItem2"; 112 | this.toolStripMenuItem2.Size = new System.Drawing.Size(177, 6); 113 | // 114 | // exitToolStripMenuItem 115 | // 116 | this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; 117 | this.exitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 118 | this.exitToolStripMenuItem.Text = "&Quit"; 119 | this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolsStripMenuItem_Click); 120 | // 121 | // toolStripMenuItem1 122 | // 123 | this.toolStripMenuItem1.Name = "toolStripMenuItem1"; 124 | this.toolStripMenuItem1.Size = new System.Drawing.Size(177, 6); 125 | this.toolStripMenuItem1.Visible = false; 126 | // 127 | // testFuncToolStripMenuItem 128 | // 129 | this.testFuncToolStripMenuItem.Name = "testFuncToolStripMenuItem"; 130 | this.testFuncToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 131 | this.testFuncToolStripMenuItem.Text = "Test"; 132 | this.testFuncToolStripMenuItem.Visible = false; 133 | this.testFuncToolStripMenuItem.Click += new System.EventHandler(this.TestFunc_Click); 134 | // 135 | // windowsMenu 136 | // 137 | this.windowsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 138 | this.cascadeToolStripMenuItem, 139 | this.tileVerticalToolStripMenuItem, 140 | this.tileHorizontalToolStripMenuItem, 141 | this.closeAllToolStripMenuItem}); 142 | this.windowsMenu.Name = "windowsMenu"; 143 | this.windowsMenu.Size = new System.Drawing.Size(63, 20); 144 | this.windowsMenu.Text = "&Window"; 145 | // 146 | // cascadeToolStripMenuItem 147 | // 148 | this.cascadeToolStripMenuItem.Name = "cascadeToolStripMenuItem"; 149 | this.cascadeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 150 | this.cascadeToolStripMenuItem.Text = "&Overlap"; 151 | this.cascadeToolStripMenuItem.Click += new System.EventHandler(this.CascadeToolStripMenuItem_Click); 152 | // 153 | // tileVerticalToolStripMenuItem 154 | // 155 | this.tileVerticalToolStripMenuItem.Name = "tileVerticalToolStripMenuItem"; 156 | this.tileVerticalToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 157 | this.tileVerticalToolStripMenuItem.Text = "&Side by side"; 158 | this.tileVerticalToolStripMenuItem.Click += new System.EventHandler(this.TileVerticalToolStripMenuItem_Click); 159 | // 160 | // tileHorizontalToolStripMenuItem 161 | // 162 | this.tileHorizontalToolStripMenuItem.Name = "tileHorizontalToolStripMenuItem"; 163 | this.tileHorizontalToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 164 | this.tileHorizontalToolStripMenuItem.Text = "S&tacked"; 165 | this.tileHorizontalToolStripMenuItem.Click += new System.EventHandler(this.TileHorizontalToolStripMenuItem_Click); 166 | // 167 | // closeAllToolStripMenuItem 168 | // 169 | this.closeAllToolStripMenuItem.Name = "closeAllToolStripMenuItem"; 170 | this.closeAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 171 | this.closeAllToolStripMenuItem.Text = "&Close all"; 172 | this.closeAllToolStripMenuItem.Click += new System.EventHandler(this.CloseAllToolStripMenuItem_Click); 173 | // 174 | // toolStrip 175 | // 176 | this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 177 | this.toolStripSeparator1, 178 | this.btnAdd, 179 | this.btnScan, 180 | this.toolStripSeparator2, 181 | this.toolStripLatency}); 182 | this.toolStrip.Location = new System.Drawing.Point(0, 24); 183 | this.toolStrip.Name = "toolStrip"; 184 | this.toolStrip.Size = new System.Drawing.Size(1384, 25); 185 | this.toolStrip.TabIndex = 1; 186 | this.toolStrip.Text = "ToolStrip"; 187 | // 188 | // toolStripSeparator1 189 | // 190 | this.toolStripSeparator1.Name = "toolStripSeparator1"; 191 | this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); 192 | // 193 | // btnAdd 194 | // 195 | this.btnAdd.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 196 | this.btnAdd.Image = ((System.Drawing.Image)(resources.GetObject("btnAdd.Image"))); 197 | this.btnAdd.ImageTransparentColor = System.Drawing.Color.Magenta; 198 | this.btnAdd.Name = "btnAdd"; 199 | this.btnAdd.Size = new System.Drawing.Size(23, 22); 200 | this.btnAdd.Text = "Add Device"; 201 | this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); 202 | // 203 | // btnScan 204 | // 205 | this.btnScan.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 206 | this.btnScan.Image = ((System.Drawing.Image)(resources.GetObject("btnScan.Image"))); 207 | this.btnScan.ImageTransparentColor = System.Drawing.Color.Black; 208 | this.btnScan.Name = "btnScan"; 209 | this.btnScan.Size = new System.Drawing.Size(23, 22); 210 | this.btnScan.Text = "Scan network"; 211 | this.btnScan.Click += new System.EventHandler(this.btnScan_Click); 212 | // 213 | // toolStripSeparator2 214 | // 215 | this.toolStripSeparator2.Name = "toolStripSeparator2"; 216 | this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); 217 | // 218 | // toolStripLatency 219 | // 220 | this.toolStripLatency.Name = "toolStripLatency"; 221 | this.toolStripLatency.Size = new System.Drawing.Size(54, 22); 222 | this.toolStripLatency.Text = "Latency: "; 223 | // 224 | // statusStrip 225 | // 226 | this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 227 | this.toolStripStatusLabel}); 228 | this.statusStrip.Location = new System.Drawing.Point(0, 695); 229 | this.statusStrip.Name = "statusStrip"; 230 | this.statusStrip.Size = new System.Drawing.Size(1384, 22); 231 | this.statusStrip.TabIndex = 2; 232 | this.statusStrip.Text = "StatusStrip"; 233 | // 234 | // toolStripStatusLabel 235 | // 236 | this.toolStripStatusLabel.Name = "toolStripStatusLabel"; 237 | this.toolStripStatusLabel.Size = new System.Drawing.Size(39, 17); 238 | this.toolStripStatusLabel.Text = "Status"; 239 | // 240 | // LonScannerMain 241 | // 242 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 243 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 244 | this.ClientSize = new System.Drawing.Size(1384, 717); 245 | this.Controls.Add(this.statusStrip); 246 | this.Controls.Add(this.toolStrip); 247 | this.Controls.Add(this.menuStrip); 248 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 249 | this.IsMdiContainer = true; 250 | this.MainMenuStrip = this.menuStrip; 251 | this.Name = "LonScannerMain"; 252 | this.Text = "LON Scanner"; 253 | this.menuStrip.ResumeLayout(false); 254 | this.menuStrip.PerformLayout(); 255 | this.toolStrip.ResumeLayout(false); 256 | this.toolStrip.PerformLayout(); 257 | this.statusStrip.ResumeLayout(false); 258 | this.statusStrip.PerformLayout(); 259 | this.ResumeLayout(false); 260 | this.PerformLayout(); 261 | 262 | } 263 | #endregion 264 | 265 | 266 | private System.Windows.Forms.MenuStrip menuStrip; 267 | private System.Windows.Forms.ToolStrip toolStrip; 268 | private System.Windows.Forms.StatusStrip statusStrip; 269 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; 270 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; 271 | private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel; 272 | private System.Windows.Forms.ToolStripMenuItem tileHorizontalToolStripMenuItem; 273 | private System.Windows.Forms.ToolStripMenuItem fileMenu; 274 | private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; 275 | private System.Windows.Forms.ToolStripMenuItem windowsMenu; 276 | private System.Windows.Forms.ToolStripMenuItem cascadeToolStripMenuItem; 277 | private System.Windows.Forms.ToolStripMenuItem tileVerticalToolStripMenuItem; 278 | private System.Windows.Forms.ToolStripMenuItem closeAllToolStripMenuItem; 279 | private System.Windows.Forms.ToolStripButton btnScan; 280 | private System.Windows.Forms.ToolTip toolTip; 281 | private System.Windows.Forms.ToolStripButton btnAdd; 282 | private System.Windows.Forms.ToolStripMenuItem updateSystemTimeToolStripMenuItem; 283 | private System.Windows.Forms.ToolStripMenuItem importXIFToolStripMenuItem; 284 | private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; 285 | private System.Windows.Forms.ToolStripMenuItem testFuncToolStripMenuItem; 286 | private System.Windows.Forms.ToolStripMenuItem packetForgeToolStripMenuItem; 287 | private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; 288 | private System.Windows.Forms.ToolStripLabel toolStripLatency; 289 | } 290 | } 291 | 292 | 293 | 294 | -------------------------------------------------------------------------------- /LonScan/Config.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace LonScan 10 | { 11 | public class Config 12 | { 13 | public static string ConfigFile = "LonScan.cfg"; 14 | 15 | public string RemoteAddress = "192.168.1.255"; 16 | public int RemoteReceivePort = 3333; 17 | public int RemoteSendPort = 3334; 18 | public int SourceSubnet = 1; 19 | public int SourceNode = 126; 20 | public int PacketRetries = 3; 21 | public int PacketTimeout = 1000; 22 | public int PacketDelay = 100; 23 | public int LatencyCheckTime = 500; 24 | 25 | public List PacketForgeTemplates = new List(); 26 | 27 | public LonDeviceConfig[] DeviceConfigs = new LonDeviceConfig[] 28 | { 29 | /* 30 | new LonDeviceConfig() 31 | { 32 | Name = "WVF", 33 | Addresses = new []{ 2 }, 34 | NvInfos = new NvInfo[] 35 | { 36 | new NvInfo("nviRequest ", " ", "SNVT_obj_request"), 37 | new NvInfo("nvoStatus ", " ", "SNVT_obj_status"), 38 | new NvInfo("nviTimeSet ", "nvi_Systemzeit ", "SNVT_time_stamp"), 39 | new NvInfo("nvoFileDirectory ", " ", "SNVT_address"), 40 | new NvInfo("nvoTimeSet ", "Lokale Zeit ", "SNVT_time_stamp"), 41 | new NvInfo("nciLocation ", "Bezeichnung ", "SNVT_str_asc"), 42 | new NvInfo("N35_m ", " ", ""), 43 | new NvInfo("N35_nviDigOut ", " ", "SNVT_state"), 44 | new NvInfo("N35_nvoAdRaw ", " ", ""), 45 | new NvInfo("WET_nviTsoll[0] ", " ", "SNVT_temp_p"), 46 | new NvInfo("WET_nviTsoll[1] ", " ", "SNVT_temp_p"), 47 | new NvInfo("WET_m ", " ", ""), 48 | new NvInfo("WVF_nviTK ", " ", "SNVT_temp_p"), 49 | new NvInfo("WVF_nviMode ", " ", "SNVT_hvac_mode"), 50 | new NvInfo("WVF_nviTEsoll ", " ", "SNVT_temp_p"), 51 | new NvInfo("WVF_nviStaFmf ", " ", ""), 52 | new NvInfo("WVF_nviTRG ", " ", "SNVT_temp_p"), 53 | new NvInfo("WVF_nviFBflag ", " ", "SNVT_switch"), 54 | new NvInfo("WVF_nviTPO ", " ", "SNVT_temp_p"), 55 | new NvInfo("WVF_nviTPU ", " ", "SNVT_temp_p"), 56 | new NvInfo("WVF_nviTKext ", " ", "SNVT_temp_p"), 57 | new NvInfo("nvoWE_ModeGp1 ", " ", "SNVT_hvac_mode"), 58 | new NvInfo("nvoWE_ModeGp2 ", " ", "SNVT_hvac_mode"), 59 | new NvInfo("WVF_nvoTsollFa ", " ", "SNVT_temp_p"), 60 | new NvInfo("WVF_nvoPKsoll ", " ", "SNVT_lev_cont"), 61 | new NvInfo("WVF_nvoEngyHldHk ", " ", "SNVT_lev_percent"), 62 | new NvInfo("WVF_nvoEngyHldBw ", " ", "SNVT_lev_percent"), 63 | new NvInfo("WVF_nvoTPO ", " ", "SNVT_temp_p"), 64 | new NvInfo("WVF_nvoTPU ", " ", "SNVT_temp_p"), 65 | new NvInfo("WVF_nviTiStaWe ", " ", "SNVT_time_sec"), 66 | new NvInfo("WVF_nviFBKStart ", " ", "SNVT_lev_disc"), 67 | new NvInfo("WVF_nviTPOmin ", " ", "SNVT_temp_p"), 68 | new NvInfo("WVF_nviTiStaWp ", " ", "SNVT_time_sec"), 69 | new NvInfo("WVF_nviTiAufhEnd ", " ", "SNVT_time_sec"), 70 | new NvInfo("WVF_nviTiStaUsa ", " ", "SNVT_time_sec"), 71 | new NvInfo("WVF_nviTiUlvPos ", " ", "SNVT_time_sec"), 72 | new NvInfo("WVF_nviTiBlockWp ", " ", "SNVT_time_sec"), 73 | new NvInfo("WVF_nviTiSperr ", " ", "SNVT_time_sec"), 74 | new NvInfo("WVF_nvoStaWe ", " ", ""), 75 | new NvInfo("WVF_nvoModOgWe ", " ", "SNVT_hvac_mode"), 76 | new NvInfo("WVF_nvoStaWp ", " ", ""), 77 | new NvInfo("WVF_nvoStaUsa ", " ", ""), 78 | new NvInfo("WVF_nvoValve ", " ", "SNVT_lev_percent"), 79 | new NvInfo("WVF_nvoStaKtr ", " ", ""), 80 | new NvInfo("WVF_nvoPump ", " ", "SNVT_lev_cont"), 81 | new NvInfo("WVF_nvoMode ", " ", "SNVT_hvac_mode"), 82 | new NvInfo("SYS_pack ", " ", "") 83 | } 84 | },*/ 85 | new LonDeviceConfig() 86 | { 87 | Name = "UML C1", 88 | Addresses = new []{ 10, 11 }, 89 | ProgramId = "90010010010A0588", 90 | NvInfos = new NvInfo[] 91 | { 92 | new NvInfo("nviRequest ", " ", "SNVT_obj_request"), 93 | new NvInfo("nvoStatus ", " ", "SNVT_obj_status"), 94 | new NvInfo("nviTimeSet ", "nvi_Systemzeit ", "SNVT_time_stamp"), 95 | new NvInfo("nvoFileDirectory ", " ", "SNVT_address"), 96 | new NvInfo("nvoTimeSet ", "Lokale Zeit ", "SNVT_time_stamp"), 97 | new NvInfo("nviError ", "nvi_Störcode ", "SNVT_count"), 98 | new NvInfo("nvoError ", "nvo_Störcode ", "SNVT_count"), 99 | new NvInfo("nciLocation ", "Bezeichnung ", "SNVT_str_asc"), 100 | new NvInfo("N35_m ", " ", ""), 101 | new NvInfo("N35_nviDigOut ", " ", "SNVT_state"), 102 | new NvInfo("N35_nvoDiRaw ", " ", ""), 103 | new NvInfo("N35_nvoAdRaw ", " ", ""), 104 | new NvInfo("N35_nvoBws ", " ", ""), 105 | new NvInfo("nviWvEnergyHold ", "nvi_EnergyHold_HK", "SNVT_lev_percent"), 106 | new NvInfo("nviBwEnergyHold ", "nvi_EnergyHold_BK", "SNVT_lev_percent"), 107 | new NvInfo("nviWE_ModeGp1 ", "nvi_WE_Mode_Gr1 ", "SNVT_hvac_mode"), 108 | new NvInfo("EH_m ", " ", ""), 109 | new NvInfo("WET_nviTsoll[0] ", "WET_T_Soll_HK ", "SNVT_temp_p"), 110 | new NvInfo("WET_nviTsoll[1] ", "WET_T_Soll_WW ", "SNVT_temp_p"), 111 | new NvInfo("WET_nvoTsoll[0] ", "WET_T_Soll_HK ", "SNVT_temp_p"), 112 | new NvInfo("WET_nvoTsoll[1] ", "WET_T_Soll_WW ", "SNVT_temp_p"), 113 | new NvInfo("WET_nviTist ", "nvi_WE_T_Kessel ", "SNVT_temp_p"), 114 | new NvInfo("WET_nvoTist ", "nvo_WET_T_Kessel ", "SNVT_temp_p"), 115 | new NvInfo("WET_m ", " ", ""), 116 | new NvInfo("nviTaFb ", "nvi_T_Aussen ", "SNVT_temp_p"), 117 | new NvInfo("nvoTa ", "T_Aussen ", "SNVT_temp_p"), 118 | new NvInfo("TA_m ", " ", ""), 119 | new NvInfo("LX_nviTist[0] ", "L_T_Boiler ", "SNVT_temp_p"), 120 | new NvInfo("LX_nviTsoll[0] ", "L_T_Boiler1_Soll ", "SNVT_temp_p"), 121 | new NvInfo("LX_nvoPump[0] ", "L_Pumpe_BK1 ", "SNVT_lev_cont"), 122 | new NvInfo("LX_nvoValve[0] ", "L_Ladeventil_BK1 ", "SNVT_lev_cont"), 123 | new NvInfo("LX_m[0] ", " ", ""), 124 | new NvInfo("LX_nvoSetPt ", " ", "SNVT_temp_p"), 125 | new NvInfo("WVF_nviTPO ", "T_PufferOben TPO ", "SNVT_temp_p"), 126 | new NvInfo("M_nviTVsoll ", "T_Vorlauf_Soll ", "SNVT_temp_p"), 127 | new NvInfo("M_nviTVist ", "T_Vorlauf ", "SNVT_temp_p"), 128 | new NvInfo("M_nvoPump ", "Pumpe ", "SNVT_lev_cont"), 129 | new NvInfo("M_nvoValve ", "M_Mischventil ", "SNVT_lev_percent"), 130 | new NvInfo("M_m ", " ", ""), 131 | new NvInfo("RC_nviMode[0] ", " ", ""), 132 | new NvInfo("RC_nvoMode[0] ", "BDM1_Betriebsart ", ""), 133 | new NvInfo("RC_nviFlags[0] ", " ", ""), 134 | new NvInfo("RC_nvoFlags[0] ", " ", ""), 135 | new NvInfo("RC_nviError[0] ", "BDM_Störcode ", "SNVT_count"), 136 | new NvInfo("RC_nvoSpaceTemp[0] ", "BDM_T_Raum ", "SNVT_temp_p"), 137 | new NvInfo("RC_nvoHeatSetPt[0] ", " ", "SNVT_temp_p"), 138 | new NvInfo("RC_nvoBoilSetPt[0] ", "BDM_T_Boiler_Soll", "SNVT_temp_p"), 139 | new NvInfo("RC_nviSolarTemp ", "BDM_TSA_Koll.Aust", "SNVT_temp_p"), 140 | new NvInfo("RC_nviSolarEnrgy ", "BDM_Solargewinn ", "SNVT_elec_kwh"), 141 | new NvInfo("RC_nviSoDayEnrgy ", " ", "SNVT_elec_kwh"), 142 | new NvInfo("FA_m ", " ", ""), 143 | new NvInfo("FA_nviTVsoll ", "FA_T_Kessel_Soll ", "SNVT_temp_p"), 144 | new NvInfo("FA_nvoTk ", "FA_T_Kessel_VL ", "SNVT_temp_p"), 145 | new NvInfo("FA_nvoTr ", "FA_T_Kessel_RL ", "SNVT_temp_p"), 146 | new NvInfo("FA_nviExtTsoll ", " ", "SNVT_temp_p"), 147 | new NvInfo("SYS_pack ", " ", ""), 148 | } 149 | }/*, 150 | new LonDeviceConfig() 151 | { 152 | // cat PMX_A3_V270.XIF | grep VAR -A3 | tr '\r' ';' | tr '\n' ' ' | sed "s/--/\n/g;" | sed "s/^ * //g" | cut -d ' ' -f 3,2,21 153 | Name = "PMX150", 154 | Addresses = new []{ 60 }, 155 | NvInfos = new NvInfo[] 156 | { 157 | new NvInfo("nviRequest ", " ", "SNVT_obj_request"), 158 | new NvInfo("nvoStatus ", " ", "SNVT_obj_status"), 159 | new NvInfo("nviTimeSet ", "nvi_Systemzeit ", "SNVT_time_stamp"), 160 | new NvInfo("nvoFileDirectory ", " ", "SNVT_address"), 161 | new NvInfo("nvoTime ", "Lokale Zeit ", "SNVT_time_stamp"), 162 | new NvInfo("nviObjEvent ", " ", ""), 163 | new NvInfo("nvoObjStatus ", " ", ""), 164 | new NvInfo("nvoError ", " ", "SNVT_count"), 165 | new NvInfo("nvoWvEnergyHold ", "nvo_EnergyHold_HK", "SNVT_lev_percent"), 166 | new NvInfo("nvoBwEnergyHold ", "nvo_EnergyHold_BK", "SNVT_lev_percent"), 167 | new NvInfo("nviWE_ModeGp1 ", "nvi_WE_Mode_Gr1 ", "SNVT_hvac_mode"), 168 | new NvInfo("nviWE_ModeGp3 ", "nvi_WE_Mode_Gr3 ", "SNVT_hvac_mode"), 169 | new NvInfo("EH_m ", " ", ""), 170 | new NvInfo("WET_nviTsoll[0] ", "WET_T_Soll_HK ", "SNVT_temp_p"), 171 | new NvInfo("WET_nviTsoll[1] ", "WET_T_Soll_BK ", "SNVT_temp_p"), 172 | new NvInfo("WET_nvoTist ", "nvo_WET_T_Kessel ", "SNVT_temp_p"), 173 | new NvInfo("BD_nviDsp ", " ", "display"), 174 | new NvInfo("GB_nviNsoll ", " ", "SNVT_rpm"), 175 | new NvInfo("GB_nvoNist ", "A_GB_Drehzahl ", "SNVT_rpm"), 176 | new NvInfo("GB_nvoNsoll ", "A_GB_Drehz. Soll ", "SNVT_rpm"), 177 | new NvInfo("GB_m ", " ", ""), 178 | new NvInfo("FS_nviMsoll ", "A_FS_Menge_Soll ", "SNVT_mass_kilo"), 179 | new NvInfo("FS_nvoMotor ", " ", "SNVT_lev_disc"), 180 | new NvInfo("FS_nvoTein ", " ", "SNVT_time_sec"), 181 | new NvInfo("FS_nvoTaus ", " ", "SNVT_time_sec"), 182 | new NvInfo("FS_nvoMpts ", " ", "SNVT_mass_kilo"), 183 | new NvInfo("FS_m ", " ", ""), 184 | new NvInfo("FS_nviMfoerder ", "A_FS_Menge_berech", "SNVT_mass_kilo"), 185 | new NvInfo("FS_nvoAvgTb_Tk ", " ", "SNVT_temp"), 186 | new NvInfo("ZG_nviOn ", " ", "SNVT_lev_disc"), 187 | new NvInfo("ZG_nvoHeat ", " ", "SNVT_lev_disc"), 188 | new NvInfo("ZG_nvoVent ", " ", "SNVT_lev_disc"), 189 | new NvInfo("RO_nviCount ", " ", "SNVT_count"), 190 | new NvInfo("RO_nvoCount ", " ", "SNVT_count"), 191 | new NvInfo("RO_m ", " ", ""), 192 | new NvInfo("PMX_nviLstg ", "P_Leistung_Soll ", "SNVT_lev_cont"), 193 | new NvInfo("FMF_nvoStatus ", " ", ""), 194 | new NvInfo("PMX_nvoLstg ", "P_Leistung ", "SNVT_lev_cont"), 195 | new NvInfo("PMX_m ", " ", ""), 196 | new NvInfo("PMX_nvoToPzs ", " ", "SNVT_switch"), 197 | new NvInfo("PMX_nviFromPzs ", " ", "SNVT_switch"), 198 | new NvInfo("PMX_nviPzsStatus ", " ", "SNVT_obj_status"), 199 | new NvInfo("PMX_eeBetrStd ", "B_Betriebsstunden", "SNVT_time_hour"), 200 | new NvInfo("PMX_eeNbrAnhz ", "B_Anheizvorgänge ", "SNVT_count"), 201 | new NvInfo("EXT_m ", "B_AAT_HFR ", ""), 202 | new NvInfo("EXT_nvoTacho ", " ", "SNVT_time_min"), 203 | new NvInfo("EXT_nvoTacho1 ", " ", "SNVT_time_min"), 204 | new NvInfo("NIC_nvoValue ", "T_Brennraum ", "SNVT_temp"), 205 | new NvInfo("NIC_nvoTboard ", "T_Schaltfeld ", "SNVT_temp_p"), 206 | new NvInfo("NIC_nvoAvgVal ", "T_Brennr._Mittel ", "SNVT_temp"), 207 | new NvInfo("TK_nviSetP ", "T_Kessel_Soll ", "SNVT_temp_p"), 208 | new NvInfo("TK_nvoPID ", " ", "SNVT_lev_percent"), 209 | new NvInfo("TK_nvoTemp ", "T_Kessel ", "SNVT_temp_p"), 210 | new NvInfo("TK_nvoRist ", "T_Kessel_Rücklauf", "SNVT_temp_p"), 211 | new NvInfo("RG_nviSetP ", "T_Abgas_Soll ", "SNVT_temp"), 212 | new NvInfo("RG_nvoPID ", " ", "SNVT_lev_percent"), 213 | new NvInfo("RG_nvoTemp ", "T_Abgas ", "SNVT_temp"), 214 | new NvInfo("TVB_nvoValue ", " ", "SNVT_temp"), 215 | new NvInfo("HW_nviDigInput ", " ", ""), 216 | new NvInfo("HW_nviDigOutput ", " ", "") 217 | } 218 | }*/ 219 | }; 220 | 221 | internal void AddDeviceConfig(LonDeviceConfig xif) 222 | { 223 | List cfg = DeviceConfigs.ToList(); 224 | cfg.Add(xif); 225 | DeviceConfigs = cfg.ToArray(); 226 | } 227 | 228 | public static Config Load() 229 | { 230 | try 231 | { 232 | string json = File.ReadAllText(ConfigFile); 233 | Config cfg = JsonConvert.DeserializeObject(json); 234 | 235 | return cfg; 236 | } 237 | catch (Exception) 238 | { 239 | return null; 240 | } 241 | } 242 | 243 | public void Save() 244 | { 245 | try 246 | { 247 | string json = JsonConvert.SerializeObject(this, Formatting.Indented); 248 | File.WriteAllText(ConfigFile, json); 249 | } 250 | catch (Exception) 251 | { 252 | } 253 | } 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /LonScan/DeviceForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAQAEBAAAAEAIABoBAAARgAAACAgAAABAAgAqAgAAK4EAAAwMAAAAQAIAKgOAABWDQAAQEAAAAEA 124 | CAAoFgAA/hsAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 125 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 126 | AAAAAAAAAAAAAISEhAGxsbECAAAAAFRUVACxsbECKioqAAAAAAC3t7cIAAAAAAAAAAAAAAAAAAAAAAAA 127 | AAAAAAAAAAAAABsbGwCxsbH/qKio/7y8vBy3t7f/qamp/7u7u//Dw8P/qqqq/wAAAAAAAAAAAAAAAAAA 128 | AAAAAAAAAAAAAAwMDACFhYX/a2tr/2dnZ/9zc3P/bW1t/2dnZ/9vb2//cnJy/2dnZ/+hoaH/AAAAAAAA 129 | AAAAAAAAAAAAALq6uv+VlZX/Ojo6/zY2Nv9GRkb/SUlJ/0lJSf9JSUn/SUlJ/0RERP8zMzP/S0tL/6am 130 | pv+5ubn/AAAAAAAAAAC4uLj/kpKS/zo6Ov9XV1f/m5ub/3h4eP95eXn/eHh4/3t7e/+goKD/TExM/0xM 131 | TP+np6f/urq6/wAAAAAAAAAADAwMAK6urv88PDz/X19f/3h4eP8yMjL/NDQ0/zQ0NP80NDT/i4uL/1NT 132 | U/9SUlL/wMDAUBsbGwAAAAAAAAAAAL29vf+Xl5f/Ojo6/19fX/92dnb/MjIy/zU1Nf81NTX/NTU1/4mJ 133 | if9TU1P/TExM/6mpqf+8vLz/AAAAAAAAAAC5ubn/k5OT/zo6Ov9fX1//dnZ2/zIyMv81NTX/NTU1/zQ0 134 | NP+JiYn/U1NT/0xMTP+oqKj/u7u7/wAAAAAAAAAAoaGhAaKiov87Ozv/YGBg/3t7e/82Njb/ODg4/zg4 135 | OP84ODj/jo6O/1NTU/9QUFD/vLy8/4SEhAEAAAAAAAAAAMDAwFSenp7/Ozs7/1RUVP+goKD/iIiI/4iI 136 | iP+Hh4f/ioqK/6Ojo/9KSkr/Tk5O/7Gxsf/ExMT/AAAAAAAAAAC5ubn/lJSU/zo6Ov80NDT/QUFB/0RE 137 | RP9ERET/RERE/0RERP8/Pz//MzMz/0xMTP+np6f/urq6/wAAAAAAAAAAAAAAAAAAAACDg4P/aWlp/2Vl 138 | Zf9xcXH/a2tr/2VlZf9tbW3/cHBw/2VlZf+fn5//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGxsbALGx 139 | sf+oqKj/vLy8HLe3t/+pqan/u7u7/8PDw/+qqqr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 140 | AACPj48Bt7e3CAAAAABtbW0At7e3CEdHRwABAQEAt7e3CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 141 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAPNv 142 | AADwDwAA4AcAAIABAACAAQAAwAMAAIABAACAAQAAgAEAAIABAACAAQAA4AcAAPAPAADzbwAA//8AACgA 143 | AAAgAAAAQAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0NDQAPDw8AERERABMTEwAU1NTAFxc 144 | XABkZGQAbGxsAHR0dAB8fHwAhISEAIyMjACUlJQAm5ubAKurqwC0tLQAvLy8AMTExADMzMwA1NTUANzc 145 | 3ADk5OQA7OzsAPT09AD8/PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 146 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 147 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 148 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 149 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 150 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 151 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 152 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 153 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 154 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 155 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 156 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 157 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 158 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 159 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 160 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRkZGRkZGRkZGRkZGRkZGRkZ 161 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkVERkTExkV 162 | EhkTExkTFBkUEhkZGRkZGRkZGRkZGRkZGRAIGQwLGQ8JGQwMGQsNGQ4KGRkZGRkZGRkZGRkZGRkZEAgZ 163 | DAsZDgkZDAwZCw0ZDgoZGRkZGRkZGRkZGRkZGRkQCBkMCxkOCRkMDBkLDRkOChkZGRkZGRkZGRkZGRkZ 164 | FQ0GEwoJEwwHEwkJEwkKFAwIExcZGRkZGRkZGRUUFRAEAQECAQECAQECAQECAQECAQECCxUVFRYZGRkW 165 | CAYGBAAAAAAAAAAAAAAAAAAAAAAAAAACBgYGCBYZGRkWFhYPAQAAAAIDAwMDAwMDAwMDAgAAAAcVFRUW 166 | GRkZGRIREg0BAAAGEREPDxAQDxAPEBEQAwAABhISEhMZGRkWCQcHBQAAAAkTBwQEBAQEBAQECxQFAAAC 167 | BwcHCRYZGRkZGRkQAQAACRABAAAAAAAAAAAFEgUAAAcXFxcZGRkZGRUUFQ4BAAAJDwEAAAAAAAAAAAUS 168 | BQAABxQVFRUZGRkWCQYGBAAAAAkPAQAAAAAAAAAABRIFAAACBgYGCBYZGRkWFhYPAQAACRABAAAAAAAA 169 | AAAFEgUAAAcVFhUWGRkZGRIREg0BAAAJEAEAAAAAAAAAAAUSBQAABhITExMZGRkWCQcHBQAAAAkPAQAA 170 | AAAAAAAABRIFAAACBwcHCRYZGRkZGRkQAQAACQ8BAAAAAAAAAAAFEgUAAAcXFxcZGRkZFxEPEAsBAAAJ 171 | EAEAAAAAAAAAAAUTBQAABhESEhMZGRkWCggIBQAAAAkUCwgICAgICAgIDhQFAAACBwcHChYZGRkZGRkQ 172 | AQAABQ8QEBAQEBAQEBAQDgMAAAcXGBcZGRkZGRMSEw0BAAAAAQEBAQEBAQEBAQEBAAAABhMTExQZGRkW 173 | CQYHBAAAAAAAAAAAAAAAAAAAAAAAAAACBgYGCRYZGRkXFxcSAwEBAQEBAQEBAQEBAQEBAQEBAQsWFhYX 174 | GRkZGRkZGRkUDQYSCQkTDAcTCQkTCQoTCwgTFhkZGRkZGRkZGRkZGRkQCBkMCxkOCRkMDBkLDRkOChkZ 175 | GRkZGRkZGRkZGRkZGRAIGQwLGQ4JGQwMGQsNGQ4KGRkZGRkZGRkZGRkZGRkZEAgZDAwZDgkZDAwZCw0Z 176 | DgoZGRkZGRkZGRkZGRkZGRkVERkTExkUERkTExkSExkUEhkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 177 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGf///////////kkk//5J 178 | JP/+SST//kkk//wAAD/AAAADgAAAAcAAAAPAAAADgAAAAfgAAAfAAAADgAAAAcAAAAPAAAADgAAAAfgA 179 | AAeAAAADgAAAAfgAAAfAAAADgAAAAcAAAAP8AAA//kkk//5JJP/+SST//kkk////////////KAAAADAA 180 | AABgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ0NAA8PDwAREREAExMTABUVFQAXFxcAGRk 181 | ZABsbGwAdHR0AHx8fACEhIQAjIyMAJSUlACdnZ0ApKSkAK2trQC0tLQAvLy8AMTExADMzMwA1NTUANzc 182 | 3ADk5OQA7OzsAPT09AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 183 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 184 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 185 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 186 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 187 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 188 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 189 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 190 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 191 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 192 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 193 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 194 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 195 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 196 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 197 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 198 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 199 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 200 | GRkZGRkZGRkZGRkZGRgVGRkZFRgZGRcVGRkZFRgZGRYXGRkZFBgZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 201 | GRAEFRkTBBIZGQ4FFxkTAxIZGQgKGRkWBBAZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwD 202 | FhkRAREZGAUHGRkVAg4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwDFhkRAREZGAYHGRkV 203 | Ag4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwDFhkRAREZGAYHGRkVAg4ZGRkZGRkZGRkZ 204 | GRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwDFhkRAREZGAYHGRkVAg4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 205 | GQ4CExkRARAZGQsDFhkRARAZFwUHGBkVAg0ZGRkZGRkZGRkZGRkZGRkZGRkZGRcMCAUBBggGAQUICAQB 206 | BwgGAQUICAIDCAgHAQUICxYZGRkZGRkZGRkZGRkWFRUVFQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 207 | AAAAAAsWFhYWFhcZGRkZGRYFAgICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDAwMDAwYW 208 | GRkZGRgPDQ0NDQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUMDAwMCw4YGRkZGRkZGRkZGQ8A 209 | AAAAAAACAgICAgICAgICAgICAgICAgEAAAAAAAoZGRkZGRkZGRkZGRkYGBgYGA4AAAAAAAYRExMTExMT 210 | ExMTExMTExMTEw8DAAAAAAoZGBgYGBkZGRkZGRYIBQUFBQMAAAAAAAwWFA4MDAwMDA0MDA0MDA0RFhUG 211 | AAAAAAMHBwcHBwkXGRkZGRcKCAgICAQAAAAAAAwWCgAAAAAAAAAAAAAAAAADEhUGAAAAAAMHBwcHBwoX 212 | GRkZGRkZGRkZGQ4AAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZGRkZGRkZGRkZGQ8A 213 | AAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZGRkZGRkWFRUVFQwAAAAAAAwVBgAAAAAA 214 | AAAAAAAAAAABDxUGAAAAAAkWFhYWFRYZGRkZGRYFAgICAgEAAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUG 215 | AAAAAAEDAwMDAgUWGRkZGRgQDg4ODggAAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAUNDQ0NDA8Y 216 | GRkZGRkZGRkZGQ8AAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZGRkZGRkYGBgYGA4A 217 | AAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZGRkZGRYIBQUFBQMAAAAAAAwVBgAAAAAA 218 | AAAAAAAAAAABDxUGAAAAAAMHBwcHBwoXGRkZGRcKBwcHBwQAAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUG 219 | AAAAAAMHBwcHBgkXGRkZGRkZGRkZGQ4AAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZ 220 | GRkZGRkZGRkZGQ8AAAAAAAwVBgAAAAAAAAAAAAAAAAABDxUGAAAAAAoZGRkZGRkZGRkZGRgQDQ0NDggA 221 | AAAAAAwVBwAAAAAAAAAAAAAAAAABEBUGAAAAAAcRERERERIYGRkZGRYFAgICAgEAAAAAAAwWDgQDAwMD 222 | AwMDAwMDAwMIFBUGAAAAAAECAgICAQQWGRkZGRkWFBQUFAwAAAAAAAsWFhQTExMTExMTExMTExMVFxUG 223 | AAAAAAgSEhISEhQZGRkZGRkZGRkZGQ8AAAAAAAQOEBAQEBAQEBAQEBAQEBAQEAwCAAAAAAoZGRkZGRkZ 224 | GRkZGRkZGRkZGQ4AAAAAAAABAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAoZGRkZGRkZGRkZGRcKBwcHBwQA 225 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQJCQgJCAsXGRkZGRYIBgYGBgMAAAAAAAAAAAAAAAAA 226 | AAAAAAAAAAAAAAAAAAAAAAIFBQUFBQcWGRkZGRkZGBgYGQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 227 | AAAAAAsYGBgYGBgZGRkZGRkZGRkZGRcLBwQBBgcFAAUHBwMBBgcFAAUHBwICBwcGAQQHCRUZGRkZGRkZ 228 | GRkZGRkZGRkZGRkZGQ4CExkRARAZGQsDFhkRARAZFwUHGBkUAg0ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 229 | GQ8CFBkSARAZGQwDFhkRAREZGAYHGRkVAg4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkRARAZGQwD 230 | FhkRAREZGAYHGRkVAg4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwDFhkRAREZGAYHGRkV 231 | Ag4ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ8CFBkSARAZGQwDFhkRAREZGAUHGRkVAg4ZGRkZGRkZGRkZ 232 | GRkZGRkZGRkZGRkZGQ8DFRkTAxIZGQ0EFxkTAxIZGAcJGRkWBA8ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 233 | GRcUGRkYFBgZGRcUGRkYFBgZGRUVGRkZFBgZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 234 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 235 | GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ 236 | GRn///////8AAP///////wAA////////AAD/5zOZz/8AAP/iMRmP/wAA/+IxEY//AAD/4jERj/8AAP/i 237 | MRGP/wAA/+IxEY//AAD/4jEQj/8AAP8AAAAB/wAA4AAAAAAHAADAAAAAAAMAAMAAAAAAAwAA/wAAAAH/ 238 | AADgAAAAAQ8AAMAAAAAAAwAAwAAAAAADAAD/AAAAAf8AAP8AAAAB/wAA4AAAAAAHAADAAAAAAAMAAMAA 239 | AAAAAwAA/wAAAAH/AADgAAAAAf8AAMAAAAAAAwAAwAAAAAADAAD/AAAAAf8AAP8AAAAB/wAAwAAAAAAD 240 | AADAAAAAAAMAAOAAAAAABwAA/wAAAAH/AAD/AAAAAf8AAMAAAAAAAwAAwAAAAAADAADxAAAAAAcAAP8A 241 | AAAB/wAA/+IxEI//AAD/4jERj/8AAP/iMRGP/wAA/+IxEY//AAD/4jERj/8AAP/iMRGP/wAA/+YzGc// 242 | AAD///////8AAP///////wAA////////AAAoAAAAQAAAAIAAAAABAAgAAAAAAAAAAAAAAAAAAAAAAAAA 243 | AAAAAAAALy8vADQ0NAA8PDwAREREAExMTABTU1MAXFxcAGRkZABra2sAdHR0AHx8fACEhIQAjIyMAJSU 244 | lACcnJwApKSkAKysrAC0tLQAvLy8AMTExADMzMwA1NTUANzc3ADk5OQA7OzsAPT09AAAAAAAAAAAAAAA 245 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 246 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 247 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 248 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 249 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 250 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 251 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 252 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 253 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 254 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 255 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 256 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 257 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 258 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 259 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 260 | AAAAAAAAAAAAABoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 261 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 262 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 263 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 264 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGBoaGhoZGRoaGhoaGRoaGhoZ 265 | GRoaGhoZGRoaGhoZGBoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaEQcTGhoZCwoZGhoaEAcV 266 | GhoZCwoZGhoZCgwZGhoaDQgXGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGgwADRoaFwQDFRoa 267 | GgkBERoaFgQDFhoaFQMEFxoaGggCExoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoNAQ0aGhcE 268 | AxUaGhoJAREaGhYEBBYaGhUDBBcaGhoIAhMaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaDQEN 269 | GhoXBAMVGhoaCQERGhoWBAMWGhoVAwQXGhoaCAITGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 270 | Gg0BDRoaFwQDFRoaGgkBERoaFgQEFhoaFQMEFxoaGggCExoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 271 | GhoaGhoNAQ0aGhcEAxUaGhoJAREaGhYEBBYaGhUDBBcaGhoIAhMaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 272 | GhoaGhoaGhoaDQENGhoXBAMVGhoaCQERGhoWBAMWGhoVAwQXGhoaCAITGhoaGhoaGhoaGhoaGhoaGhoa 273 | GhoaGhoaGhoaGhoaGg0BDRoaFwQDFRoaGgkBERoaFgQDFhoaFQMEFxoaGggCExoaGhoaGhoaGhoaGhoa 274 | GhoaGhoaGhoaGhoaGhoXEhIJAQkSEhADAw8SEhEHAQwSEg8DAw8SEg8CAxASEhEFAg0SEhcaGhoaGhoa 275 | GhoaGhoaGhoaGhoaGhoaGhoVBgICAQECAgICAQECAgICAQECAgICAQECAgICAQECAgICAQECAgIHFxoa 276 | GhoaGhoaGhoaGhoaGhoXFhYWFhYWCwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 277 | AQ0XFhYWFhYWGBoaGhoaGhoWBgMDAwMDAwIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 278 | AQEBAQEDBAQEBAQEBAgXGhoaGhoaFwcEBAQEBAQDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 279 | AQEBAQEBAQEBAgMDAwMDAwMGFxoaGhoaGhoYFxcXFxcXCwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 280 | AQEBAQEBAQEBAQEBAQwXFxcXFxcWGBoaGhoaGhoaGhoaGhoaGg0BAQEBAQEBAQMDAwMDAwMDAwMDAwMD 281 | AwMDAwMDAwMDAgEBAQEBAQEOGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoNAQEBAQEBAQYRExMTExMTExMT 282 | ExMTExMTExMTExMTEw4DAQEBAQEBDhoaGhoaGhoaGhoaGhoaGhkRDg4ODg4OBwEBAQEBAQIPFxcXFhUV 283 | FRUVFRUVFRUVFRUVFRUXFxcWCAEBAQEBAQkREBAQEBAQExoaGhoaGhoVAwEBAQEBAQEBAQEBAQECEBcW 284 | DQYFBQUFBQUFBQUFBQUFBQUFChQXFgkBAQEBAQEBAQEBAQEBAQQWGhoaGhoaGA4LCwsLCwsGAQEBAQEB 285 | AhAXEQMBAQEBAQEBAQEBAQEBAQEBAQEMFxYJAQEBAQEBBgoKCgoKCgoNGBoaGhoaGhoaGhoaGhoaDQEB 286 | AQEBAQIQFw4CAQEBAQEBAQEBAQEBAQEBAQEBCRcWCAEBAQEBAQ4aGhoaGhoaGhoaGhoaGhoaGhoaGhoa 287 | Gg0BAQEBAQECEBcOAgEBAQEBAQEBAQEBAQEBAQEBAQkWFgkBAQEBAQEOGhoaGhoaGhoaGhoaGhoaGhoa 288 | GhoaGhoNAQEBAQEBAhAXDgIBAQEBAQEBAQEBAQEBAQEBAQEJFxYJAQEBAQEBDhoaGhoaGhoaGhoaGhoa 289 | GhoXFRUVFRUVCgEBAQEBAQIQFw4CAQEBAQEBAQEBAQEBAQEBAQEBCRcWCQEBAQEBAQwWFhYWFhYWFxoa 290 | GhoaGhoWBQMDAwMDAwIBAQEBAQECEBcOAgEBAQEBAQEBAQEBAQEBAQEBAQkWFgkBAQEBAQECAwMDAwMD 291 | AwYWGhoaGhoaGAkFBQUFBQUDAQEBAQEBAhAXDgIBAQEBAQEBAQEBAQEBAQEBAQEJFxcJAQEBAQEBAwUF 292 | BQUFBAQIFxoaGhoaGhoZGBgYGBgYDAEBAQEBAQIQFw4CAQEBAQEBAQEBAQEBAQEBAQEBCRYWCQEBAQEB 293 | AQwXFxcXFxcXGBoaGhoaGhoaGhoaGhoaGg0BAQEBAQECEBcOAgEBAQEBAQEBAQEBAQEBAQEBAQkWFgkB 294 | AQEBAQEOGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoNAQEBAQEBAhAXDgIBAQEBAQEBAQEBAQEBAQEBAQEJ 295 | FxYJAQEBAQEBDhoaGhoaGhoaGhoaGhoaGhkRDw8PDw8PBwEBAQEBAQIQFw4CAQEBAQEBAQEBAQEBAQEB 296 | AQEBCRcWCQEBAQEBAQkRERERERERFBoaGhoaGhoVAwEBAQEBAQEBAQEBAQECEBcOAgEBAQEBAQEBAQEB 297 | AQEBAQEBAQkXFgkBAQEBAQEBAgICAQEBAQQWGhoaGhoaGA0KCgoKCgoFAQEBAQEBAhAXDgIBAQEBAQEB 298 | AQEBAQEBAQEBAQEJFhYJAQEBAQEBBQkJCQkJCQkMGBoaGhoaGhoaGhoaGhoaDQEBAQEBAQIQFw4CAQEB 299 | AQEBAQEBAQEBAQEBAQEBCRcWCQEBAQEBAQ4aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGg0BAQEBAQECEBcO 300 | AgEBAQEBAQEBAQEBAQEBAQEBAQkWFgkBAQEBAQEOGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoNAQEBAQEB 301 | AhAXDgIBAQEBAQEBAQEBAQEBAQEBAQEJFhYJAQEBAQEBDhoaGhoaGhoaGhoaGhoaGhkPCwsLCwsLBgEB 302 | AQEBAQIQFw8CAQEBAQEBAQEBAQEBAQEBAQEBChcWCAEBAQEBAQgQEBAQEBAQEhkaGhoaGhoVAwEBAQEB 303 | AQEBAQEBAQECEBcUBwICAgICAgICAgICAgICAgICBBEXFgkBAQEBAQEBAQEBAQEBAQMWGhoaGhoaGREN 304 | DQ4ODQ0HAQEBAQEBAhAXFxQQDw8PDw8PDw8PDg8PDg8PDxMXFxYJAQEBAQEBBgsLCwsLCwsPGRoaGhoa 305 | GhoaGhoaGhoaDQEBAQEBAQINFxcXGBgYGBcYGBgXGBgYFxgYGBcXFxcVBwEBAQEBAQ4aGhoaGhoaGhoa 306 | GhoaGhoaGhoaGhoaGg0BAQEBAQEBBA0PDxAPDw8PDxAPDw8PDxAPDw8PDw8PCQIBAQEBAQEOGhoaGhoa 307 | GhoaGhoaGhoaGhoaGhoaGhoNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBDhoa 308 | GhoaGhoaGhoaGhoaGhoUERERERERCAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 309 | AQoTExMTExMTFRoaGhoaGhoVBAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 310 | AQEBAQECAgICAgICAgQVGhoaGhoaGAsJCQkJCQkEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 311 | AQEBAQEBAQEBBAcHBwcHBwcKFxoaGhoaGhoaGhoaGhoaDQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB 312 | AQEBAQEBAQEBAQEBAQ8aGRkZGRkZGhoaGhoaGhoaGhoaGhoaGhUFAgEBAQECAgEBAQECAgEBAQECAgEB 313 | AQECAgEBAQECAgEBAQEBAgYWGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaFRERCAEJEREOAwMOEREQBgEL 314 | EREOAwINERENAgMPEREQBQIMEREWGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGgwBDRoaFwQDFRoa 315 | GgkBERoaFgQDFhoaFQMEFxoaGQgCExoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoNAQ0aGhcE 316 | AxUaGhoJAREaGhYEAxYaGhUDBBcaGhoIAhMaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaDQEN 317 | GhoWBAMVGhoaCQERGhoWBAQWGhoVAwQXGhoaCAITGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 318 | Gg0BDRoaFgQDFRoaGgkBERoaFgQEFhoaFQMEFxoaGggCExoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 319 | GhoaGhoNAQ0aGhcEAxUaGhoJAREaGhYEBBYaGhUDBBcaGhoIAhMaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 320 | GhoaGhoaGhoaDQENGhoXBAMVGhoaCQERGhoWBAQWGhoVAwQXGhoaCAITGhoaGhoaGhoaGhoaGhoaGhoa 321 | GhoaGhoaGhoaGhoaGgwADRoaFwQDFhoaGgkBERoaFgQDFhoaFQMEFxoaGggCExoaGhoaGhoaGhoaGhoa 322 | GhoaGhoaGhoaGhoaGhoaGhoQBRMaGhkKCRgaGhoOBRQaGhkKCRgaGhgICRkaGhoMBxcaGhoaGhoaGhoa 323 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhgaGhoaGRgaGhoaGRgaGhoaGRgaGhoaGBgaGhoaGRgaGhoaGhoa 324 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 325 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 326 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 327 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa 328 | GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr///////////////////////////////////////////// 329 | efeeef////4w4ww4/////jDjDDj////+MOMMOP////4w4ww4/////jDjDDj////+MOMMOP////4w4ww4 330 | /////jDjDDj////wAAAAAB///+AAAAAAD//wAAAAAAAAD+AAAAAAAAAH4AAAAAAAAAfwAAAAAAAAD//g 331 | AAAAAA///+AAAAAAD//gAAAAAAAAD+AAAAAAAAAH4AAAAAAAAAf/4AAAAAAP///gAAAAAA///+AAAAAA 332 | D//wAAAAAAAAD+AAAAAAAAAH4AAAAAAAAAfwAAAAAAAAD//gAAAAAA///+AAAAAAD//gAAAAAAAAD+AA 333 | AAAAAAAH4AAAAAAAAAf/4AAAAAAP///gAAAAAA///+AAAAAAD//gAAAAAAAAB+AAAAAAAAAH4AAAAAAA 334 | AAf/4AAAAAAP///gAAAAAA///+AAAAAAD//wAAAAAAAAD+AAAAAAAAAH4AAAAAAAAAf/4AAAAAAIH//g 335 | AAAAAA////AAAAAAH////jDjDDD////+MOMMOP////4w4ww4/////jDjDDj////+MOMMOP////4w4ww4 336 | /////jDjDDj////+MOMMOP////955555/////////////////////////////////////////////w== 337 | 338 | 339 | --------------------------------------------------------------------------------