├── 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 |
--------------------------------------------------------------------------------