├── _config.yml
├── libs
├── Opc.Ua.Core.dll
├── OpcComRcw.dll
├── OpcNetApi.dll
├── Opc.Ua.Client.dll
├── OpcNetApi.Com.dll
└── Opc.Ua.Configuration.dll
├── odenwald-architecture.jpg
├── Odenwald.Common
├── packages.config
├── Opc
│ ├── MeasurementDto.cs
│ ├── OpcMetric.cs
│ ├── OpcPluginConfig.cs
│ └── OpcHelper.cs
├── Properties
│ └── AssemblyInfo.cs
├── Util.cs
└── Odenwald.Common.csproj
├── Odenwald.ConsolePlugin
├── packages.config
├── ConsolePlugin.cs
├── Properties
│ └── AssemblyInfo.cs
└── Odenwald.ConsolePlugin.csproj
├── Odenwald.OpcDaPlugin
├── packages.config
├── OpcDa.config
├── Properties
│ └── AssemblyInfo.cs
├── Odenwald.OpcDaPlugin.csproj
└── OpcDaPlugin.cs
├── Odenwald.InfluxDbPlugin
├── InfluxDb.config
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── InfluxDbPluginConfig.cs
├── InfluxDbPlugin.cs
└── Odenwald.InfluxDbPlugin.csproj
├── Odenwald.KafkaConsumerPlugin
├── KafkaConsumer.config
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── KafkaConsumerPluginConfig.cs
├── KafkaConsumerPlugin.cs
└── Odenwald.KafkaConsumerPlugin.csproj
├── Odenwald.KafkaProducerPlugin
├── KafkaProducer.config
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── KafkaProducerPluginConfig.cs
├── KafkaProducerPlugin.cs
└── Odenwald.KafkaProducerPlugin.csproj
├── Odenwald
├── packages.config
├── Util.cs
├── Interface
│ ├── IMetricsWritePlugin.cs
│ ├── IMetricsReadPlugin.cs
│ └── IMetricsPlugin.cs
├── Config
│ ├── log4net.config
│ ├── Odenwald.config
│ └── OdenwaldConfig.cs
├── Odenwald.licenseheader
├── app.config
├── Properties
│ └── AssemblyInfo.cs
├── PluginRegistry.cs
├── Odenwald.csproj
├── MetricValue.cs
├── Type
│ ├── Types.cs
│ └── types.db
└── Aggregator.cs
├── Odenwald.OpcUaPlugin
├── packages.config
├── opcua.config
├── Properties
│ └── AssemblyInfo.cs
└── Odenwald.OpcUaPlugin.csproj
├── Odenwald.App
├── packages.config
├── OdenwaldService.Designer.cs
├── OdenwaldService.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── app.config
└── Odenwald.App.csproj
├── Odenwald.Service
├── packages.config
├── OdenwaldService.Designer.cs
├── OdenwaldService.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── app.config
└── Odenwald.Service.csproj
├── LICENSE
├── Tests
└── Odenwald.OpcUaPluginTest
│ ├── packages.config
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── Odenwald.OpcUaPluginTest.csproj
│ └── OpcUaClientTest.cs
├── README.md
├── .gitattributes
├── .gitignore
├── Odenwald.WindowsPerformanceCounterPlugin
└── Config
│ └── WindowsPerformanceCounterPluginConfig.cs
└── Odenwald.sln
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/libs/Opc.Ua.Core.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/Opc.Ua.Core.dll
--------------------------------------------------------------------------------
/libs/OpcComRcw.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/OpcComRcw.dll
--------------------------------------------------------------------------------
/libs/OpcNetApi.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/OpcNetApi.dll
--------------------------------------------------------------------------------
/libs/Opc.Ua.Client.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/Opc.Ua.Client.dll
--------------------------------------------------------------------------------
/libs/OpcNetApi.Com.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/OpcNetApi.Com.dll
--------------------------------------------------------------------------------
/odenwald-architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/odenwald-architecture.jpg
--------------------------------------------------------------------------------
/libs/Opc.Ua.Configuration.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinson/Odenwald/HEAD/libs/Opc.Ua.Configuration.dll
--------------------------------------------------------------------------------
/Odenwald.Common/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Odenwald.ConsolePlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Odenwald.OpcDaPlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/InfluxDb.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/KafkaConsumer.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/KafkaProducer.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald.OpcUaPlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Odenwald.App/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Odenwald.Service/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 [Robinson (https://github.com/robinson)]
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Tests/Odenwald.OpcUaPluginTest/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Odenwald/Util.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using log4net;
15 | using System;
16 | using System.Net;
17 | using System.Net.Sockets;
18 |
19 | namespace Odenwald
20 | {
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Odenwald.OpcUaPlugin/opcua.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Odenwald.Common/Opc/MeasurementDto.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 Odenwald.Common.Opc
8 | {
9 | public class MeasurementDto
10 | {
11 | public string Name { get; set; }
12 |
13 | public string DataType { get; set; }
14 | public string AttributeId { get; set; }
15 | public string Path { get; set; }
16 | public int DeadbandAbsolute { get; set; }
17 | public decimal DeadbandRelative { get; set; }
18 | public object LastValue { get; set; }
19 | public string LastOpcstatus { get; set; }
20 | public Dictionary Tags { get; set; }
21 | }
22 | public class MonitoredMeasurement : MeasurementDto
23 | {
24 | public int MonitorResolution { get; set; }
25 | }
26 | public class PolledMeasurement : MeasurementDto
27 | {
28 | public int PollInterval { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Odenwald.OpcDaPlugin/OpcDa.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Odenwald/Interface/IMetricsWritePlugin.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using System.Collections.Generic;
15 | using System.Threading.Tasks;
16 |
17 | namespace Odenwald
18 | {
19 | public interface IMetricsWritePlugin : IMetricsPlugin
20 | {
21 | void Write(MetricValue metric);
22 | void Flush();
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Odenwald/Interface/IMetricsReadPlugin.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using System;
15 | using System.Collections.Generic;
16 | using System.Linq;
17 | using System.Text;
18 | using System.Threading.Tasks;
19 |
20 | namespace Odenwald
21 | {
22 | public interface IMetricsReadPlugin : IMetricsPlugin
23 | {
24 | IList Read();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Odenwald/Interface/IMetricsPlugin.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using System;
15 | using System.Collections.Generic;
16 | using System.Linq;
17 | using System.Text;
18 | using System.Threading.Tasks;
19 |
20 | namespace Odenwald
21 | {
22 | public interface IMetricsPlugin
23 | {
24 | void Configure();
25 | void Start();
26 | void Stop();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Odenwald.ConsolePlugin/ConsolePlugin.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.ConsolePlugin
9 | {
10 | public class ConsolePlugin : IMetricsWritePlugin
11 | {
12 | static ILog l_logger = LogManager.GetLogger(typeof(ConsolePlugin));
13 |
14 |
15 | public void Configure()
16 | {
17 | l_logger.Info("console runner output configured");
18 | }
19 |
20 | public void Flush()
21 | {
22 | Console.WriteLine("console runner output flushing");
23 | }
24 |
25 | public void Start()
26 | {
27 | l_logger.Info("console runner output started");
28 | }
29 |
30 | public void Stop()
31 | {
32 | l_logger.Info("console runner output stopped");
33 | }
34 |
35 | public void Write(MetricValue metric)
36 | {
37 | l_logger.InfoFormat("console runner output {0}", metric.GetJsonString());
38 | Console.WriteLine("console runner output {0}", metric.GetJsonString());
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Odenwald.App/OdenwaldService.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Odenwald.App
2 | {
3 | partial class OdenwaldService
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 Component 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 | components = new System.ComponentModel.Container();
32 | this.ServiceName = "OdenwaldService";
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Odenwald.Service/OdenwaldService.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Odenwald.Runner
2 | {
3 | partial class OdenwaldService
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 Component 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 | components = new System.ComponentModel.Container();
32 | this.ServiceName = "OdenwaldService";
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Odenwald/Config/log4net.config:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Odenwald.App/OdenwaldService.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.ServiceProcess;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace Odenwald.App
13 | {
14 | partial class OdenwaldService : ServiceBase
15 | {
16 | static ILog l_logger = LogManager.GetLogger(typeof(OdenwaldService));
17 | private MetricsCollector l_metricCollector;
18 | public OdenwaldService()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 | protected override void OnStart(string[] args)
24 | {
25 | StartService(args);
26 | }
27 |
28 | protected override void OnStop()
29 | {
30 | StopService();
31 | }
32 | public virtual void StartService(params string[] args)
33 | {
34 | l_logger.Debug("StartService() begin");
35 | l_metricCollector = new MetricsCollector();
36 | l_metricCollector.ConfigureAll();
37 | l_metricCollector.StartAll();
38 | l_logger.Debug("StartService() return");
39 | }
40 |
41 | // public accessibility for running as a console application
42 | public virtual void StopService()
43 | {
44 | l_logger.Debug("StopService() begin");
45 | l_metricCollector.StopAll();
46 | l_logger.Debug("StopService() return");
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Odenwald.Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.Common")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.Common")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("fef57f91-04c1-4d42-ba2e-737697ab26c1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.Service/OdenwaldService.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.ServiceProcess;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace Odenwald.Runner
13 | {
14 | partial class OdenwaldService : ServiceBase
15 | {
16 | static ILog l_logger = LogManager.GetLogger(typeof(OdenwaldService));
17 | private MetricsCollector l_metricCollector;
18 | public OdenwaldService()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 | protected override void OnStart(string[] args)
24 | {
25 | StartService(args);
26 | }
27 |
28 | protected override void OnStop()
29 | {
30 | StopService();
31 | }
32 | public virtual void StartService(params string[] args)
33 | {
34 | l_logger.Debug("StartService() begin");
35 | l_metricCollector = new MetricsCollector();
36 | l_metricCollector.ConfigureAll();
37 | l_metricCollector.StartAll();
38 | l_logger.Debug("StartService() return");
39 | }
40 |
41 | // public accessibility for running as a console application
42 | public virtual void StopService()
43 | {
44 | l_logger.Debug("StopService() begin");
45 | l_metricCollector.StopAll();
46 | l_logger.Debug("StopService() return");
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Odenwald.OpcDaPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.OpcDaPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.OpcDaPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("3c3fd86f-220d-418f-b964-3c4590824fce")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.OpcUaPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.OpcUaPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.OpcUaPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("63e03daa-660e-4c89-ba28-e1f6b72f854a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.ConsolePlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.ConsolePlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.ConsolePlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e7092227-fb5b-40e9-882c-9f636335afb7")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.InfluxDbPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.InfluxDbPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("084be120-923f-4517-850c-17d1d5590ac9")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Tests/Odenwald.OpcUaPluginTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.OpcUaPluginTest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.OpcUaPluginTest")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c46f6932-ab4c-4a49-a3ba-1f9690015a48")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.Common/Opc/OpcMetric.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using Newtonsoft.Json;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Odenwald.Common.Opc
10 | {
11 | public class OpcMetric
12 | {
13 | #region Attribute
14 | static ILog l_logger = LogManager.GetLogger(typeof(OpcMetric));
15 | private readonly IDictionary l_meta = new SortedDictionary();
16 | #endregion
17 |
18 |
19 | public object OpcValue { get; set; }
20 | public MeasurementDto Measurement { get; set; }
21 |
22 | public DateTime Timestamp { get; set; }
23 | public string Opcstatus { get; set; }
24 |
25 | public string JsonString()
26 | {
27 | object opcObject = new
28 | {
29 | OpcValue = OpcValue,
30 | Timestamp = Timestamp,
31 | Opcstatus = Opcstatus,
32 | Name = Measurement.Name,
33 | DataType = Measurement.DataType,
34 | AttributeId = Measurement.AttributeId,
35 | Path = Measurement.Path,
36 | DeadbandAbsolute = Measurement.DeadbandAbsolute,
37 | DeadbandRelative = Measurement.DeadbandRelative,
38 | LastValue = Measurement.LastValue,
39 | LastOpcstatus = Measurement.LastOpcstatus,
40 | Tags = Measurement.Tags
41 | };
42 | return (JsonConvert.SerializeObject(opcObject));
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.KafkaConsumerPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.KafkaConsumerPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("b9a8e446-db9f-46e9-bfcd-916a3d8424aa")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.KafkaProducerPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.KafkaProducerPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("eec9106e-6812-444b-9a5e-59cdf4022d4a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Odenwald.App/Program.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.Linq;
6 | using System.ServiceProcess;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace Odenwald.App
11 | {
12 | public static class Program
13 | {
14 | static ILog l_logger = LogManager.GetLogger(typeof(Program));
15 | public static void Main(string[] args)
16 | {
17 |
18 | var config = ConfigurationManager.GetSection("Odenwald") as OdenwaldConfig;
19 | if (config == null)
20 | {
21 | l_logger.Error("Main(): cannot get configuration section");
22 | return;
23 | }
24 | var odenWaldService = new OdenwaldService();
25 |
26 | if (Array.Find(args, s => s.Equals(@"app")) != null)
27 | {
28 | Console.WriteLine("*** Starting OdenwaldApp in console mode***");
29 | // run as a console application for testing and debugging purpose
30 | odenWaldService.StartService();
31 | Console.WriteLine("*** Enter Ctrl-C to exit: ***");
32 | Console.ReadLine();
33 | odenWaldService.StopService();
34 | }
35 | else
36 | {
37 | // run as a windows service
38 | ServiceBase[] servicesToRun = { odenWaldService };
39 | ServiceBase.Run(servicesToRun);
40 | }
41 | l_logger.Error("OdenwaldService: exiting ...");
42 | }
43 |
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Odenwald.App/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.App")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.App")]
13 | [assembly: AssemblyCopyright("Copyright Odenwald © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 | [assembly: Guid("ad130047-5631-4f12-b357-82b45e671c83")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.0.0")]
37 | [assembly: AssemblyFileVersion("1.0.0.0")]
38 |
39 | [assembly: log4net.Config.XmlConfigurator(Watch = true)]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Updating...
2 | TO BE UPDATING...
3 | # Summary
4 | Odenwald is a tool which switch the data from points to destination, and supports following plugins:
5 | - OPC UA
6 | - OPC DA (opc classic)
7 | - InfluxDB
8 | - Kafka
9 | - Console
10 |
11 | # Disclaimer
12 | The following binaries belong to the OPC Foundation (https://opcfoundation.org/):
13 |
14 | - OPC.Ua.Client.dll
15 | - OPC.Ua.Core.dll
16 | - OPC.Ua.Configuration.dll
17 | - OpcComRcw.dll
18 | - OpcNetApi.Com.dll
19 | - OpcNetApi.dll
20 |
21 | You should become a registered user in order to use.
22 |
23 | Beside some popular packages as thousands opensouces (such as: log4net, newtonsoft.json, etc.), Odenwald use:
24 | - InfluxDB.Net-Main
25 | - kafka-net
26 |
27 | # Reference
28 | In order to test with OPC UA you should register and get the sample OPC UA server as (https://github.com/OPCFoundation/UA-.NET/tree/master/SampleApplications/Samples/Server)
29 | In case of OPC DA testing, you are able to use OPC Classic Demo server from Softing (of course before using it, you should register as a user, althought that is a free of charge software),
30 | http://industrial.softing.com/en/products/software/opc-development-toolkits/opc-classic-development-toolkits/opc-classic-da-ae-xml-da-client-and-server-toolkit-for-windows.html
31 |
32 | Besides, Odenwald refers from these systems:
33 | - collectd (https://github.com/collectd/collectd)
34 | - CollectdWin (https://github.com/bloomberg/collectdwin)
35 |
36 | # TODO
37 | - Installation package use wix toolset.
38 | - A small web app to monitor the service.
39 | - MongoDB plugin.
40 | - Update document.
41 | - Recode MetricData
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Odenwald.Service/Program.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.Linq;
6 | using System.ServiceProcess;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace Odenwald.Runner
11 | {
12 | public static class Program
13 | {
14 | static ILog l_logger = LogManager.GetLogger(typeof(Program));
15 | public static void Main(string[] args)
16 | {
17 |
18 | var config = ConfigurationManager.GetSection("Odenwald") as OdenwaldConfig;
19 | if (config == null)
20 | {
21 | l_logger.Error("Main(): cannot get configuration section");
22 | return;
23 | }
24 | var odenWaldService = new OdenwaldService();
25 |
26 | if (Array.Find(args, s => s.Equals(@"console")) != null)
27 | {
28 | Console.WriteLine("*** Starting OdenwaldService in console mode***");
29 | // run as a console application for testing and debugging purpose
30 | odenWaldService.StartService();
31 | Console.WriteLine("*** Enter Ctrl-C to exit: ***");
32 | Console.ReadLine();
33 | odenWaldService.StopService();
34 | }
35 | else
36 | {
37 | // run as a windows service
38 | ServiceBase[] servicesToRun = { odenWaldService };
39 | ServiceBase.Run(servicesToRun);
40 | }
41 | l_logger.Error("OdenwaldService: exiting ...");
42 | }
43 |
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Odenwald.Service/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Odenwald.Service")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Odenwald.Service")]
13 | [assembly: AssemblyCopyright("Copyright Odenwald © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 | [assembly: Guid("ad130047-5631-4f12-b357-82b45e671c83")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.0.0")]
37 | [assembly: AssemblyFileVersion("1.0.0.0")]
38 |
39 | [assembly: log4net.Config.XmlConfigurator(Watch = true)]
--------------------------------------------------------------------------------
/Odenwald/Odenwald.licenseheader:
--------------------------------------------------------------------------------
1 | extensions: designer.cs generated.cs
2 | extensions: .cs .cpp .h
3 |
4 | // ----------------------------------------------------------------------------
5 | // Copyright (C) 2017 Robinson.
6 | // https://github.com/robinson
7 | // Licensed under the Apache License, Version 2.0 (the "License");
8 | // you may not use this file except in compliance with the License.
9 | // You may obtain a copy of the License at
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | extensions: .aspx .ascx
17 | <%--
18 | Copyright (c) 2011 rubicon IT GmbH
19 | --%>
20 | extensions: .vb
21 | 'Sample license text.
22 | extensions: .xml .config .xsd
23 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/KafkaConsumerPluginConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.KafkaConsumerPlugin
9 | {
10 | public class KafkaConsumerPluginConfig : ConfigurationSection
11 | {
12 | public static KafkaConsumerPluginConfig GetConfig()
13 | {
14 | return (KafkaConsumerPluginConfig)ConfigurationManager.GetSection("KafkaConsumer") ?? new KafkaConsumerPluginConfig();
15 | }
16 | [ConfigurationProperty("Settings", IsRequired = true)]
17 | public SettingsConfig Settings
18 | {
19 | get { return (SettingsConfig)base["Settings"]; }
20 | set { base["Settings"] = value; }
21 | }
22 | }
23 | public sealed class SettingsConfig : ConfigurationElement
24 | {
25 | [ConfigurationProperty("Url", IsRequired = true)]
26 | public string Url
27 | {
28 | get { return (string)base["Url"]; }
29 | set { base["Url"] = value; }
30 | }
31 | [ConfigurationProperty("Topic", IsRequired = true)]
32 | public string Topic
33 | {
34 | get { return (string)base["Topic"]; }
35 | set { base["Topic"] = value; }
36 | }
37 | [ConfigurationProperty("BatchDelayTime")]
38 | public int BatchDelayTime
39 | {
40 | get { return (int)base["BatchDelayTime"]; }
41 | set { base["BatchDelayTime"] = value; }
42 | }
43 | [ConfigurationProperty("BatchSize")]
44 | public int BatchSize
45 | {
46 | get { return (int)base["BatchSize"]; }
47 | set { base["BatchSize"] = value; }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Odenwald/app.config:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Odenwald.Common/Util.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace Odenwald.Common
11 | {
12 | public static class Util
13 | {
14 | static ILog l_logger = LogManager.GetLogger(typeof(Util));
15 |
16 | public static double GetNow()
17 | {
18 | TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
19 | double epoch = t.TotalMilliseconds / 1000;
20 | double now = Math.Round(epoch, 3);
21 | return (now);
22 | }
23 |
24 | public static string GetHostName()
25 | {
26 | string hostname = Environment.MachineName.ToLower();
27 | try
28 | {
29 | hostname = Dns.GetHostEntry("localhost").HostName.ToLower();
30 | }
31 | catch (SocketException)
32 | {
33 | l_logger.WarnFormat("Unable to resolve hostname, using MachineName: {0}", hostname);
34 | }
35 | return hostname;
36 | }
37 | public static bool IsNumber(this object value)
38 | {
39 | return value is sbyte
40 | || value is byte
41 | || value is short
42 | || value is ushort
43 | || value is int
44 | || value is uint
45 | || value is long
46 | || value is ulong
47 | || value is float
48 | || value is double
49 | || value is decimal;
50 | }
51 | public static bool IsBoolean(this object value)
52 | {
53 | return value is bool;
54 | }
55 | public static bool IsString(this object value)
56 | {
57 | return value is string;
58 | }
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/InfluxDbPluginConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.InfluxDbPlugin
9 | {
10 | public sealed class InfluxDbPluginConfig : ConfigurationSection
11 | {
12 | public static InfluxDbPluginConfig GetConfig()
13 | {
14 | return (InfluxDbPluginConfig)ConfigurationManager.GetSection("InfluxDb") ?? new InfluxDbPluginConfig();
15 | }
16 | [ConfigurationProperty("Settings", IsRequired = true)]
17 | public SettingsConfig Settings
18 | {
19 | get { return (SettingsConfig)base["Settings"]; }
20 | set { base["Settings"] = value; }
21 | }
22 | }
23 | public sealed class SettingsConfig : ConfigurationElement
24 | {
25 | [ConfigurationProperty("Interval", IsRequired = true)]
26 | public int Interval
27 | {
28 | get { return (int)base["Interval"]; }
29 | set { base["Interval"] = value; }
30 | }
31 | [ConfigurationProperty("Url", IsRequired = true)]
32 | public string Url
33 | {
34 | get { return (string)base["Url"]; }
35 | set { base["Url"] = value; }
36 | }
37 | [ConfigurationProperty("Database", IsRequired = true)]
38 | public string Database
39 | {
40 | get { return (string)base["Database"]; }
41 | set { base["Database"] = value; }
42 | }
43 | [ConfigurationProperty("Username")]
44 | public string Username
45 | {
46 | get { return (string)base["Username"]; }
47 | set { base["Username"] = value; }
48 | }
49 | [ConfigurationProperty("Password")]
50 | public string Password
51 | {
52 | get { return (string)base["Password"]; }
53 | set { base["Password"] = value; }
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/KafkaProducerPluginConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.KafkaProducerPlugin
9 | {
10 | public class KafkaProducerPluginConfig : ConfigurationSection
11 | {
12 | public static KafkaProducerPluginConfig GetConfig()
13 | {
14 | return (KafkaProducerPluginConfig)ConfigurationManager.GetSection("KafkaProducer") ?? new KafkaProducerPluginConfig();
15 | }
16 | [ConfigurationProperty("Settings", IsRequired = true)]
17 | public SettingsConfig Settings
18 | {
19 | get { return (SettingsConfig)base["Settings"]; }
20 | set { base["Settings"] = value; }
21 | }
22 | }
23 | public sealed class SettingsConfig : ConfigurationElement
24 | {
25 | //[ConfigurationProperty("Interval", IsRequired = true)]
26 | //public int Interval
27 | //{
28 | // get { return (int)base["Interval"]; }
29 | // set { base["Interval"] = value; }
30 | //}
31 | [ConfigurationProperty("Url", IsRequired = true)]
32 | public string Url
33 | {
34 | get { return (string)base["Url"]; }
35 | set { base["Url"] = value; }
36 | }
37 | [ConfigurationProperty("Topic", IsRequired = true)]
38 | public string Topic
39 | {
40 | get { return (string)base["Topic"]; }
41 | set { base["Topic"] = value; }
42 | }
43 | [ConfigurationProperty("BatchDelayTime")]
44 | public int BatchDelayTime
45 | {
46 | get { return (int)base["BatchDelayTime"]; }
47 | set { base["BatchDelayTime"] = value; }
48 | }
49 | [ConfigurationProperty("BatchSize")]
50 | public int BatchSize
51 | {
52 | get { return (int)base["BatchSize"]; }
53 | set { base["BatchSize"] = value; }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Odenwald/Config/Odenwald.config:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
23 |
25 |
27 |
29 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Odenwald/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using System.Reflection;
15 | using System.Runtime.CompilerServices;
16 | using System.Runtime.InteropServices;
17 |
18 | // General Information about an assembly is controlled through the following
19 | // set of attributes. Change these attribute values to modify the information
20 | // associated with an assembly.
21 | [assembly: AssemblyTitle("Odenwald")]
22 | [assembly: AssemblyDescription("")]
23 | [assembly: AssemblyConfiguration("")]
24 | [assembly: AssemblyCompany("")]
25 | [assembly: AssemblyProduct("Odenwald")]
26 | [assembly: AssemblyCopyright("Copyright © 2016")]
27 | [assembly: AssemblyTrademark("")]
28 | [assembly: AssemblyCulture("")]
29 |
30 | // Setting ComVisible to false makes the types in this assembly not visible
31 | // to COM components. If you need to access a type in this assembly from
32 | // COM, set the ComVisible attribute to true on that type.
33 | [assembly: ComVisible(false)]
34 |
35 | // The following GUID is for the ID of the typelib if this project is exposed to COM
36 | [assembly: Guid("bb7a7712-cc11-4d95-83dc-a0ab28714860")]
37 |
38 | // Version information for an assembly consists of the following four values:
39 | //
40 | // Major Version
41 | // Minor Version
42 | // Build Number
43 | // Revision
44 | //
45 | // You can specify all the values or you can default the Build and Revision Numbers
46 | // by using the '*' as shown below:
47 | // [assembly: AssemblyVersion("1.0.*")]
48 | [assembly: AssemblyVersion("1.0.0.0")]
49 | [assembly: AssemblyFileVersion("1.0.0.0")]
50 |
51 | [assembly: log4net.Config.XmlConfigurator(Watch = true)]
52 |
--------------------------------------------------------------------------------
/Odenwald/PluginRegistry.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using log4net;
15 | using System;
16 | using System.Collections.Generic;
17 | using System.Configuration;
18 | using System.Linq;
19 | using System.Text;
20 | using System.Threading.Tasks;
21 |
22 |
23 | namespace Odenwald
24 | {
25 | internal class PluginRegistry
26 | {
27 | static ILog l_logger = LogManager.GetLogger(typeof(PluginRegistry));
28 |
29 | private readonly Dictionary _registry = new Dictionary();
30 |
31 | public PluginRegistry()
32 | {
33 | var config = ConfigurationManager.GetSection("Odenwald") as OdenwaldConfig;
34 | if (config == null)
35 | {
36 | l_logger.ErrorFormat("Cannot get configuration section : Odenwald");
37 | return;
38 | }
39 | foreach (
40 | OdenwaldConfig.PluginConfig pluginConfig in
41 | config.Plugins.Cast()
42 | .Where(pluginConfig => pluginConfig.Enable))
43 | {
44 | _registry[pluginConfig.Name] = pluginConfig.Class;
45 | }
46 | }
47 |
48 | public IList CreatePlugins()
49 | {
50 | IList plugins = new List();
51 | foreach (var entry in _registry)
52 | {
53 | Type classType = Type.GetType(entry.Value);
54 | if (classType == null)
55 | {
56 | l_logger.ErrorFormat("Cannot create plugin:{0}, class:{1}", entry.Key, entry.Value);
57 | continue;
58 | }
59 | var plugin = (IMetricsPlugin)Activator.CreateInstance(classType);
60 | plugins.Add(plugin);
61 | }
62 | return (plugins);
63 | }
64 | }
65 | }
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/KafkaProducerPlugin.cs:
--------------------------------------------------------------------------------
1 | using KafkaNet;
2 | using KafkaNet.Model;
3 | using KafkaNet.Protocol;
4 | using log4net;
5 | using System;
6 | using System.Configuration;
7 | using System.Linq;
8 |
9 | namespace Odenwald.KafkaProducerPlugin
10 | {
11 | public class KafkaProducerPlugin : IMetricsWritePlugin, IDisposable
12 | {
13 | #region attributes
14 | static ILog l_logger = LogManager.GetLogger(typeof(KafkaProducerPlugin));
15 | KafkaProducerPluginConfig l_kafkaProducerConfig;
16 | Producer l_kafkaProducer;
17 | #endregion
18 | public void Configure()
19 | {
20 | l_kafkaProducerConfig = KafkaProducerPluginConfig.GetConfig();
21 | if (l_kafkaProducerConfig == null)
22 | {
23 | throw new Exception("Cannot get configuration section : KafkaProducer");
24 | }
25 |
26 | }
27 |
28 | public void Flush()
29 | {
30 | l_logger.Info("kafka producer flushed!");
31 | }
32 |
33 | public void Start()
34 | {
35 | var urls = l_kafkaProducerConfig.Settings.Url.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
36 | .Select(x => new Uri(x));
37 |
38 | var options = new KafkaOptions(urls.ToArray())
39 | {
40 | Log = new DefaultTraceLog()
41 | };
42 | var batchDelayTime = l_kafkaProducerConfig.Settings.BatchDelayTime == 0 ? 2000 : l_kafkaProducerConfig.Settings.BatchDelayTime;
43 | var batchSize = l_kafkaProducerConfig.Settings.BatchSize == 0 ? 100 : l_kafkaProducerConfig.Settings.BatchSize;
44 | l_kafkaProducer = new Producer(new BrokerRouter(options))
45 | {
46 | BatchDelayTime = TimeSpan.FromMilliseconds(batchDelayTime),
47 | BatchSize = batchSize
48 | };
49 | }
50 |
51 | public void Stop()
52 | {
53 | l_kafkaProducer.Stop();
54 | }
55 |
56 | public void Write(MetricValue metric)
57 | {
58 | var produceResponse = l_kafkaProducer.SendMessageAsync(l_kafkaProducerConfig.Settings.Topic, new[] { new Message(metric.GetJsonString()) });
59 | if (produceResponse.IsFaulted || produceResponse.IsCanceled)
60 | {
61 | l_logger.ErrorFormat("kafka producer write false: {0}", produceResponse.Exception);
62 | }
63 | }
64 |
65 | public void Dispose()
66 | {
67 | if (l_kafkaProducer != null)
68 | l_kafkaProducer.Dispose();
69 | GC.SuppressFinalize(this);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/Odenwald.App/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Odenwald.Service/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/InfluxDbPlugin.cs:
--------------------------------------------------------------------------------
1 | using InfluxDB.Net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.Linq;
6 | using InfluxDB.Net.Models;
7 | using log4net;
8 | using Newtonsoft.Json.Linq;
9 | using Newtonsoft.Json;
10 |
11 | namespace Odenwald.InfluxDbPlugin
12 | {
13 | public class InfluxDbPlugin : IMetricsWritePlugin
14 | {
15 | #region attributes
16 | static ILog l_logger = LogManager.GetLogger(typeof(InfluxDbPlugin));
17 | InfluxDbPluginConfig l_influxDbConfig;
18 | InfluxDb l_influxDbClient;
19 | #endregion
20 |
21 | #region IOutputAdapter properties
22 |
23 | public void Configure()
24 | {
25 | l_influxDbConfig = ConfigurationManager.GetSection("InfluxDb") as InfluxDbPluginConfig;
26 | if (l_influxDbConfig == null)
27 | {
28 | throw new Exception("Cannot get configuration section : InfluxDb");
29 | }
30 | }
31 |
32 | public void Flush()
33 | {
34 | l_logger.Info("InfluxDbAdapter flushed!");
35 | }
36 |
37 | public void Start()
38 | {
39 | l_influxDbClient = new InfluxDb(l_influxDbConfig.Settings.Url, l_influxDbConfig.Settings.Username, l_influxDbConfig.Settings.Password);
40 |
41 | }
42 |
43 | public void Stop()
44 | {
45 | l_logger.Info("InfluxDbAdapter stopped!");
46 | }
47 |
48 |
49 | public void Write(MetricValue metric)
50 | {
51 | if (metric.Extension.Equals("")) // no extension, nothing to write
52 | return;
53 | var extension = JObject.Parse(metric.Extension);
54 | if (extension["OpcValue"] == null) // no OpcValue, nothing to write
55 | return;
56 | var opcValue = extension["OpcValue"];
57 | var opcName = extension["Name"].ToString();
58 | var timeStamp = extension["Timestamp"] != null ? (DateTime)extension["Timestamp"] : DateTime.Now;
59 | Dictionary tags = extension["Tags"] != null ?
60 | JsonConvert.DeserializeObject>(extension["Tags"].ToString()) : null;
61 |
62 | var p = new Point()
63 | {
64 | Measurement = opcName,
65 | Precision = InfluxDB.Net.Enums.TimeUnit.Seconds,
66 | Fields = new Dictionary()
67 | {
68 | {"Value",opcValue},
69 | {"Timestamp", timeStamp}
70 | },
71 | Tags = tags// tags.ToDictionary(k => k.Key, k => k.Value == "" || k.Value == null ? null : (object)k.Value)// metric.MetaData.ToDictionary(k => k.Key, k => k.Value == "" || k.Value == null ? null : (object)k.Value)
72 | };
73 | var writeResponse = l_influxDbClient.WriteAsync(l_influxDbConfig.Settings.Database, p);
74 |
75 | if (writeResponse.IsFaulted || writeResponse.IsCanceled)
76 | l_logger.ErrorFormat("InfluxDb write false: {0}", writeResponse.Exception);
77 | }
78 | #endregion
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/KafkaConsumerPlugin.cs:
--------------------------------------------------------------------------------
1 | using KafkaNet;
2 | using KafkaNet.Common;
3 | using KafkaNet.Model;
4 | using log4net;
5 | using Newtonsoft.Json;
6 | using System;
7 | using System.Collections.Concurrent;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 | using System.Threading.Tasks;
11 |
12 | namespace Odenwald.KafkaConsumerPlugin
13 | {
14 | public class KafkaConsumerPlugin : IMetricsReadPlugin, IDisposable
15 | {
16 | #region attributes
17 | static ILog l_logger = LogManager.GetLogger(typeof(KafkaConsumerPlugin));
18 | KafkaConsumerPluginConfig l_kafkaConsumerConfig;
19 | Consumer l_kafkaConsumer;
20 | BlockingCollection l_metricCollection;
21 | #endregion
22 | public void Configure()
23 | {
24 | l_kafkaConsumerConfig = KafkaConsumerPluginConfig.GetConfig();
25 | if (l_kafkaConsumerConfig == null)
26 | {
27 | throw new Exception("Cannot get configuration section : KafkaConsumer");
28 | }
29 | }
30 |
31 | public IList Read()
32 | {
33 | if (l_metricCollection.Count <= 0)
34 | return null;
35 | List metricList = new List();
36 | while (l_metricCollection.Count > 0)
37 | {
38 |
39 | string data = null;
40 | try
41 | {
42 | data = l_metricCollection.Take();
43 | }
44 | catch (InvalidOperationException) { }
45 |
46 | if (data != null)
47 | {
48 | var metricValue = JsonConvert.DeserializeObject(data);//this is not a good practice, review later
49 |
50 | metricList.Add(metricValue);
51 | }
52 | }
53 | l_logger.DebugFormat("Read {0} items.", metricList.Count);
54 | return metricList;
55 | }
56 |
57 | public void Start()
58 | {
59 | var urls = l_kafkaConsumerConfig.Settings.Url.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
60 | .Select(x => new Uri(x));
61 |
62 | var options = new KafkaOptions(urls.ToArray())
63 | {
64 | Log = new DefaultTraceLog()
65 | };
66 | l_metricCollection = new BlockingCollection();
67 | Task.Run(() =>
68 | {
69 | l_kafkaConsumer = new Consumer(new ConsumerOptions(l_kafkaConsumerConfig.Settings.Topic, new BrokerRouter(options)) { Log = new DefaultTraceLog() });
70 | foreach (var message in l_kafkaConsumer.Consume())
71 | {
72 | var value = message.Value.ToUtf8String();
73 |
74 | l_metricCollection.Add(value);
75 | }
76 | });
77 | }
78 |
79 | public void Stop()
80 | {
81 | l_logger.Info("KafkaConsumer plugin stopped.");
82 | }
83 | public void Dispose()
84 | {
85 | if (l_kafkaConsumer != null)
86 | l_kafkaConsumer.Dispose();
87 | GC.SuppressFinalize(this);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Odenwald.ConsolePlugin/Odenwald.ConsolePlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BA07862A-586A-47AC-9069-7D1904973A83}
8 | Library
9 | Properties
10 | Odenwald.ConsolePlugin
11 | Odenwald.ConsolePlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
35 | True
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
53 | Odenwald
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
71 |
--------------------------------------------------------------------------------
/Odenwald.Common/Odenwald.Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}
8 | Library
9 | Properties
10 | Odenwald.Common
11 | Odenwald.Common
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
35 | True
36 |
37 |
38 | False
39 | ..\Odenwald.OpcUaPlugin\bin\Debug\Newtonsoft.Json.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
70 |
--------------------------------------------------------------------------------
/Odenwald.KafkaProducerPlugin/Odenwald.KafkaProducerPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A}
8 | Library
9 | Properties
10 | Odenwald.KafkaProducerPlugin
11 | Odenwald.KafkaProducerPlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\kafka-net.0.9.0.65\lib\net45\kafka-net.dll
35 | True
36 |
37 |
38 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
39 | True
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | PreserveNewest
59 |
60 |
61 |
62 |
63 |
64 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}
65 | Odenwald
66 |
67 |
68 |
69 |
76 |
--------------------------------------------------------------------------------
/Odenwald.OpcDaPlugin/Odenwald.OpcDaPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3C3FD86F-220D-418F-B964-3C4590824FCE}
8 | Library
9 | Properties
10 | Odenwald.OpcDaPlugin
11 | Odenwald.OpcDaPlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
35 | True
36 |
37 |
38 | False
39 | ..\libs\OpcComRcw.dll
40 |
41 |
42 | ..\libs\OpcNetApi.dll
43 |
44 |
45 | ..\libs\OpcNetApi.Com.dll
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}
64 | Odenwald.Common
65 |
66 |
67 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
68 | Odenwald
69 |
70 |
71 |
72 |
73 | PreserveNewest
74 |
75 |
76 |
77 |
78 |
85 |
--------------------------------------------------------------------------------
/Odenwald.KafkaConsumerPlugin/Odenwald.KafkaConsumerPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}
8 | Library
9 | Properties
10 | Odenwald.KafkaConsumerPlugin
11 | Odenwald.KafkaConsumerPlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\kafka-net.0.9.0.65\lib\net45\kafka-net.dll
35 | True
36 |
37 |
38 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
39 | True
40 |
41 |
42 | False
43 | ..\Odenwald.OpcUaPlugin\bin\Debug\Newtonsoft.Json.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | PreserveNewest
63 |
64 |
65 |
66 |
67 |
68 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}
69 | Odenwald.Common
70 |
71 |
72 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}
73 | Odenwald
74 |
75 |
76 |
77 |
84 |
--------------------------------------------------------------------------------
/Odenwald/Odenwald.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}
8 | Library
9 | Properties
10 | Odenwald
11 | Odenwald
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
35 | True
36 |
37 |
38 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
39 | True
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 |
69 |
70 |
71 | PreserveNewest
72 |
73 |
74 |
75 |
76 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}
77 | Odenwald.Common
78 |
79 |
80 |
81 |
88 |
--------------------------------------------------------------------------------
/Odenwald/MetricValue.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using log4net;
15 | using Newtonsoft.Json;
16 | using System;
17 | using System.Collections.Generic;
18 | using System.Linq;
19 | using System.Text;
20 | using System.Threading.Tasks;
21 |
22 | namespace Odenwald
23 | {
24 | public class MetricValue
25 | {
26 | #region Attribute
27 | static ILog l_logger = LogManager.GetLogger(typeof(MetricValue));
28 | private readonly IDictionary l_meta = new SortedDictionary();
29 | #endregion
30 |
31 | #region Properties
32 | public string PluginName { get; set; }
33 | public string PluginInstanceName { get; set; }
34 |
35 | public string HostName { get; set; }
36 |
37 | public IDictionary MetaData { get { return l_meta; } }
38 |
39 | public string TypeName { get; set; }
40 | public string TypeInstanceName { get; set; }
41 |
42 | public double[] Values { get; set; }
43 |
44 | public double Epoch { get { return DateTimeOffset.Now.ToUnixTimeSeconds(); } }
45 |
46 | public int Interval { get; set; }
47 |
48 | public IList DsTypes { get; set; }
49 |
50 | public IList DsNames { get; set; }
51 |
52 | public string Key
53 | {
54 | get
55 | {
56 | return (HostName + "." + PluginName + "." + PluginName + "." + TypeName + "." + TypeInstanceName);
57 | }
58 | }
59 |
60 | public void AddMetaData(IDictionary meta)
61 | {
62 | if (meta == null)
63 | {
64 | return;
65 | }
66 |
67 | foreach (var tag in meta)
68 | {
69 | l_meta[tag.Key] = tag.Value;
70 | }
71 | }
72 |
73 | public void AddMetaData(string tagName, string tagValue)
74 | {
75 | l_meta[tagName] = tagValue;
76 | }
77 | public string Extension { get; set; } //extension will be a json string
78 |
79 | public MetricValue DeepCopy()
80 | {
81 | var other = (MetricValue)MemberwiseClone();
82 | other.HostName = String.Copy(HostName);
83 | other.PluginName = String.Copy(PluginName);
84 | other.PluginInstanceName = String.Copy(PluginInstanceName);
85 | other.TypeName = String.Copy(TypeName);
86 | other.TypeInstanceName = String.Copy(TypeInstanceName);
87 | other.Values = (double[])Values.Clone();
88 | return (other);
89 | }
90 |
91 | public string GetJsonString()
92 | {
93 | IList dsList = DataSetCollection.Instance.GetDataSource(TypeName);
94 | DsNames = new List();
95 | DsTypes = new List();
96 | if (dsList == null)
97 | {
98 | l_logger.DebugFormat("Invalid type : {0}, not found in types.db", TypeName);
99 | }
100 | else
101 | {
102 | foreach (DataSource ds in dsList)
103 | {
104 | DsNames.Add(ds.Name);
105 | DsTypes.Add(ds.Type.ToString().ToLower());
106 | }
107 | }
108 | var jsonString = "";
109 | try
110 | {
111 | jsonString = JsonConvert.SerializeObject(this);
112 | }
113 | catch (Exception ex)
114 | {
115 | l_logger.ErrorFormat("Got exception in json conversion : {0}", ex);
116 | }
117 | return (jsonString);
118 | }
119 | #endregion
120 |
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Odenwald.OpcUaPlugin/Odenwald.OpcUaPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {712B2914-BF62-4278-BFE2-EB6925760839}
8 | Library
9 | Properties
10 | Odenwald.OpcUaPlugin
11 | Odenwald.OpcUaPlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
35 | True
36 |
37 |
38 | ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
39 | True
40 |
41 |
42 | False
43 | ..\libs\Opc.Ua.Client.dll
44 |
45 |
46 | False
47 | ..\libs\Opc.Ua.Configuration.dll
48 |
49 |
50 | False
51 | ..\libs\Opc.Ua.Core.dll
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Designer
71 | PreserveNewest
72 |
73 |
74 |
75 |
76 |
77 | {fef57f91-04c1-4d42-ba2e-737697ab26c1}
78 | Odenwald.Common
79 |
80 |
81 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
82 | Odenwald
83 |
84 |
85 |
86 |
93 |
--------------------------------------------------------------------------------
/Odenwald.Common/Opc/OpcPluginConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.Common.Opc
9 | {
10 | public sealed class OpcPluginConfig : ConfigurationSection
11 | {
12 | public static OpcPluginConfig GetConfig(string rootElement)
13 | {
14 | return (OpcPluginConfig)ConfigurationManager.GetSection(rootElement) ?? new OpcPluginConfig();
15 | }
16 | [ConfigurationProperty("Settings", IsRequired = true)]
17 | public SettingsConfig Settings
18 | {
19 | get { return (SettingsConfig)base["Settings"]; }
20 | set { base["Settings"] = value; }
21 | }
22 | [ConfigurationProperty("Measurements", IsRequired = true)]
23 | [ConfigurationCollection(typeof(MeasurementCollection), AddItemName = "Measurement")]
24 | public MeasurementCollection Measurements
25 | {
26 | get { return (MeasurementCollection)base["Measurements"]; }
27 | set { base["Measurements"] = value; }
28 | }
29 | }
30 | public sealed class SettingsConfig : ConfigurationElement
31 | {
32 | [ConfigurationProperty("FailoverTimeout", IsRequired = true)]
33 | public int FailoverTimeout
34 | {
35 | get { return (int)base["FailoverTimeout"]; }
36 | set { base["FailoverTimeout"] = value; }
37 | }
38 | [ConfigurationProperty("Url", IsRequired = true)]
39 | public string Url
40 | {
41 | get { return (string)base["Url"]; }
42 | set { base["Url"] = value; }
43 | }
44 | }
45 | public sealed class MeasurementCollection : ConfigurationElementCollection
46 | {
47 | protected override ConfigurationElement CreateNewElement()
48 | {
49 | return new MeasurementConfig();
50 | }
51 |
52 | protected override object GetElementKey(ConfigurationElement element)
53 | {
54 | return (((MeasurementConfig)element).UniqueId);
55 | }
56 | }
57 | public sealed class MeasurementConfig : ConfigurationElement
58 | {
59 | internal Guid UniqueId { get; set; }
60 | public MeasurementConfig()
61 | {
62 | UniqueId = Guid.NewGuid();
63 | }
64 | [ConfigurationProperty("Name", IsRequired = true)]
65 | public string Name
66 | {
67 | get { return (string)base["Name"]; }
68 | set { base["Name"] = value; }
69 | }
70 | [ConfigurationProperty("DataType", IsRequired = true)]
71 | public string DataType
72 | {
73 | get { return (string)base["DataType"]; }
74 | set { base["DataType"] = value; }
75 | }
76 |
77 | [ConfigurationProperty("Path", IsRequired = true)]
78 | public string Path
79 | {
80 | get { return (string)base["Path"]; }
81 | set { base["Path"] = value; }
82 | }
83 | //[ConfigurationProperty("NodeId", IsRequired = true)]
84 | //public string NodeId
85 | //{
86 | // get { return (string)base["NodeId"]; }
87 | // set { base["NodeId"] = value; }
88 | //}
89 | [ConfigurationProperty("CollectionType", IsRequired = true)]
90 | public string CollectionType
91 | {
92 | get { return (string)base["CollectionType"]; }
93 | set { base["CollectionType"] = value; }
94 | }
95 | [ConfigurationProperty("PollInterval")]
96 | public int PollInterval
97 | {
98 | get { return (int)base["PollInterval"]; }
99 | set { base["PollInterval"] = value; }
100 | }
101 | [ConfigurationProperty("MonitorResolution")]
102 | public int MonitorResolution
103 | {
104 | get { return (int)base["MonitorResolution"]; }
105 | set { base["MonitorResolution"] = value; }
106 | }
107 | [ConfigurationProperty("DeadbandAbsolute", IsRequired = true)]
108 | public int DeadbandAbsolute
109 | {
110 | get { return (int)base["DeadbandAbsolute"]; }
111 | set { base["DeadbandAbsolute"] = value; }
112 | }
113 | [ConfigurationProperty("DeadbandRelative", IsRequired = true)]
114 | public decimal DeadbandRelative
115 | {
116 | get { return (decimal)base["DeadbandRelative"]; }
117 | set { base["DeadbandRelative"] = value; }
118 | }
119 | [ConfigurationProperty("Tags")]
120 | public string Tags
121 | {
122 | get { return (string)base["Tags"]; }
123 | set { base["Tags"] = value; }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Odenwald.InfluxDbPlugin/Odenwald.InfluxDbPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {084BE120-923F-4517-850C-17D1D5590AC9}
8 | Library
9 | Properties
10 | Odenwald.InfluxDbPlugin
11 | Odenwald.InfluxDbPlugin
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\InfluxDB.Net-Main.1.0.20\lib\net45\InfluxDB.Net.dll
35 |
36 |
37 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
38 | True
39 |
40 |
41 | False
42 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
64 | Odenwald
65 |
66 |
67 |
68 |
69 | PreserveNewest
70 |
71 |
72 | Designer
73 |
74 |
75 |
76 |
81 |
88 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Microsoft Azure ApplicationInsights config file
170 | ApplicationInsights.config
171 |
172 | # Windows Store app package directory
173 | AppPackages/
174 | BundleArtifacts/
175 |
176 | # Visual Studio cache files
177 | # files ending in .cache can be ignored
178 | *.[Cc]ache
179 | # but keep track of directories ending in .cache
180 | !*.[Cc]ache/
181 |
182 | # Others
183 | ClientBin/
184 | [Ss]tyle[Cc]op.*
185 | ~$*
186 | *~
187 | *.dbmdl
188 | *.dbproj.schemaview
189 | *.pfx
190 | *.publishsettings
191 | node_modules/
192 | orleans.codegen.cs
193 |
194 | # RIA/Silverlight projects
195 | Generated_Code/
196 |
197 | # Backup & report files from converting an old project file
198 | # to a newer Visual Studio version. Backup files are not needed,
199 | # because we have git ;-)
200 | _UpgradeReport_Files/
201 | Backup*/
202 | UpgradeLog*.XML
203 | UpgradeLog*.htm
204 |
205 | # SQL Server files
206 | *.mdf
207 | *.ldf
208 |
209 | # Business Intelligence projects
210 | *.rdl.data
211 | *.bim.layout
212 | *.bim_*.settings
213 |
214 | # Microsoft Fakes
215 | FakesAssemblies/
216 |
217 | # GhostDoc plugin setting file
218 | *.GhostDoc.xml
219 |
220 | # Node.js Tools for Visual Studio
221 | .ntvs_analysis.dat
222 |
223 | # Visual Studio 6 build log
224 | *.plg
225 |
226 | # Visual Studio 6 workspace options file
227 | *.opt
228 |
229 | # Visual Studio LightSwitch build output
230 | **/*.HTMLClient/GeneratedArtifacts
231 | **/*.DesktopClient/GeneratedArtifacts
232 | **/*.DesktopClient/ModelManifest.xml
233 | **/*.Server/GeneratedArtifacts
234 | **/*.Server/ModelManifest.xml
235 | _Pvt_Extensions
236 |
237 | # LightSwitch generated files
238 | GeneratedArtifacts/
239 | ModelManifest.xml
240 |
241 | # Paket dependency manager
242 | .paket/paket.exe
243 |
244 | # FAKE - F# Make
245 | .fake/
--------------------------------------------------------------------------------
/Tests/Odenwald.OpcUaPluginTest/Odenwald.OpcUaPluginTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48}
9 | Library
10 | Properties
11 | Odenwald.OpcUaPluginTest
12 | Odenwald.OpcUaPluginTest
13 | v4.6
14 | 512
15 |
16 |
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\..\libs\Opc.Ua.Client.dll
38 |
39 |
40 | ..\..\libs\Opc.Ua.Core.dll
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
52 | True
53 |
54 |
55 | ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
56 | True
57 |
58 |
59 | ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
60 | True
61 |
62 |
63 | ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
64 | True
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | {712b2914-bf62-4278-bfe2-eb6925760839}
77 | Odenwald.OpcUaPlugin
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
87 |
88 |
89 |
90 |
97 |
--------------------------------------------------------------------------------
/Odenwald.WindowsPerformanceCounterPlugin/Config/WindowsPerformanceCounterPluginConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.WindowsPerformanceCounterPlugin
9 | {
10 | public class WindowsPerformanceCounterPluginConfig : ConfigurationSection
11 | {
12 | [ConfigurationProperty("RefreshInstancesConfiguration", IsRequired = true)]
13 | public RefreshInstancesConfigurationConfig RefreshInstancesConfiguration
14 | {
15 | get { return (RefreshInstancesConfigurationConfig)base["RefreshInstancesConfiguration"]; }
16 | set { base["RefreshInstancesConfiguration"] = value; }
17 | }
18 |
19 | public sealed class RefreshInstancesConfigurationConfig : ConfigurationElement
20 | {
21 | [ConfigurationProperty("Enable", IsRequired = true)]
22 | public bool Enable
23 | {
24 | get { return (bool)base["Enable"]; }
25 | set { base["Enable"] = value; }
26 | }
27 |
28 | [ConfigurationProperty("Interval", IsRequired = true)]
29 | public int Interval
30 | {
31 | get { return (int)base["Interval"]; }
32 | set { base["Interval"] = value; }
33 | }
34 | }
35 |
36 | [ConfigurationProperty("Counters", IsRequired = false)]
37 | [ConfigurationCollection(typeof(CounterConfigCollection), AddItemName = "Counter")]
38 | public CounterConfigCollection Counters
39 | {
40 | get { return (CounterConfigCollection)base["Counters"]; }
41 | set { base["Counters"] = value; }
42 | }
43 |
44 | public static WindowsPerformanceCounterPluginConfig GetConfig()
45 | {
46 | return
47 | (WindowsPerformanceCounterPluginConfig)
48 | ConfigurationManager.GetSection("WindowsPerformanceCounterPlugin") ??
49 | new WindowsPerformanceCounterPluginConfig();
50 | }
51 |
52 | public sealed class CounterConfig : ConfigurationElement
53 | {
54 | [ConfigurationProperty("Transformer", IsRequired = false, DefaultValue = "")]
55 | public string Transformer
56 | {
57 | get { return (string)base["Transformer"]; }
58 | set { base["Transformer"] = value; }
59 | }
60 |
61 | [ConfigurationProperty("TransformerParameters", IsRequired = false)]
62 | public string TransformerParameters
63 | {
64 | get { return (string)base["TransformerParameters"]; }
65 | set { base["TransformerParameters"] = value; }
66 | }
67 |
68 | [ConfigurationProperty("Category", IsRequired = true)]
69 | public string Category
70 | {
71 | get { return (string)base["Category"]; }
72 | set { base["Category"] = value; }
73 | }
74 |
75 | [ConfigurationProperty("Name", IsRequired = true)]
76 | public string Name
77 | {
78 | get { return (string)base["Name"]; }
79 | set { base["Name"] = value; }
80 | }
81 |
82 |
83 | [ConfigurationProperty("Instance", IsRequired = false)]
84 | public string Instance
85 | {
86 | get { return (string)base["Instance"]; }
87 | set { base["Instance"] = value; }
88 | }
89 |
90 | [ConfigurationProperty("CollectdPlugin", IsRequired = true)]
91 | public string CollectdPlugin
92 | {
93 | get { return (string)base["CollectdPlugin"]; }
94 | set { base["CollectdPlugin"] = value; }
95 | }
96 |
97 | [ConfigurationProperty("CollectdPluginInstance", IsRequired = false)]
98 | public string CollectdPluginInstance
99 | {
100 | get { return (string)base["CollectdPluginInstance"]; }
101 | set { base["CollectdPluginInstance"] = value; }
102 | }
103 |
104 | [ConfigurationProperty("CollectdType", IsRequired = true)]
105 | public string CollectdType
106 | {
107 | get { return (string)base["CollectdType"]; }
108 | set { base["CollectdType"] = value; }
109 | }
110 |
111 | [ConfigurationProperty("CollectdTypeInstance", IsRequired = true)]
112 | public string CollectdTypeInstance
113 | {
114 | get { return (string)base["CollectdTypeInstance"]; }
115 | set { base["CollectdTypeInstance"] = value; }
116 | }
117 | }
118 |
119 | public sealed class CounterConfigCollection : ConfigurationElementCollection
120 | {
121 | protected override ConfigurationElement CreateNewElement()
122 | {
123 | return new CounterConfig();
124 | }
125 |
126 | protected override object GetElementKey(ConfigurationElement element)
127 | {
128 | var counterConfig = (CounterConfig)element;
129 | return (counterConfig.CollectdPlugin + "_" + counterConfig.CollectdPluginInstance + "_" + counterConfig.CollectdType + "_" + counterConfig.CollectdTypeInstance);
130 | }
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/Tests/Odenwald.OpcUaPluginTest/OpcUaClientTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xunit;
7 |
8 |
9 | using Opc.Ua.Client;
10 | using Opc.Ua;
11 | using Odenwald.OpcUaPlugin;
12 |
13 | namespace Odenwald.OpcUaPluginTest
14 | {
15 | public class OpcUaClientTest
16 | {
17 | [Fact]
18 | public void TestFindNode()
19 | {
20 | ApplicationConfiguration l_applicationConfig = new ApplicationConfiguration()
21 | {
22 |
23 | ApplicationName = "OdenwaldUnitTest",
24 | ApplicationType = ApplicationType.Client,
25 | SecurityConfiguration = new SecurityConfiguration
26 | {
27 | ApplicationCertificate = new CertificateIdentifier
28 | {
29 | StoreType = @"Windows",
30 | StorePath = @"CurrentUser\My",
31 | SubjectName = Utils.Format(@"CN={0}, DC={1}",
32 | "Odenwald",
33 | System.Net.Dns.GetHostName())
34 | },
35 | TrustedPeerCertificates = new CertificateTrustList
36 | {
37 | StoreType = @"Windows",
38 | StorePath = @"CurrentUser\TrustedPeople",
39 | },
40 | NonceLength = 32,
41 | AutoAcceptUntrustedCertificates = true
42 | },
43 | TransportConfigurations = new TransportConfigurationCollection(),
44 | TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
45 | ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
46 | };
47 | l_applicationConfig.Validate(ApplicationType.Client);
48 | if (l_applicationConfig.SecurityConfiguration.AutoAcceptUntrustedCertificates)
49 | {
50 | l_applicationConfig.CertificateValidator.CertificateValidation += (s, e) =>
51 | { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
52 | }
53 |
54 | Session l_session = Session.Create(l_applicationConfig, new ConfiguredEndpoint(null, new EndpointDescription("opc.tcp://ac-l32-m7-lth1:51210/UA/SampleServer")), true, "OdenwaldUnitTest", 60000, null, null);//EndpointDescription need to be changed according to your OPC server
55 | var nodeId = OpcUaHelper.GetReadValueIdCollection("Data.Dynamic.Scalar.Int32Value", Attributes.Value, l_session);
56 | Assert.Equal(nodeId[0].NodeId.ToString(), "ns=2;i=10849");
57 | }
58 | [Fact]
59 | public void OpcUaHelperTest()
60 | {
61 | //config
62 | ApplicationConfiguration l_applicationConfig = new ApplicationConfiguration()
63 | {
64 |
65 | ApplicationName = "OdenwaldUnitTest",
66 | ApplicationType = ApplicationType.Client,
67 | SecurityConfiguration = new SecurityConfiguration
68 | {
69 | ApplicationCertificate = new CertificateIdentifier
70 | {
71 | StoreType = @"Windows",
72 | StorePath = @"CurrentUser\My",
73 | SubjectName = Utils.Format(@"CN={0}, DC={1}",
74 | "Odenwald",
75 | System.Net.Dns.GetHostName())
76 | },
77 | TrustedPeerCertificates = new CertificateTrustList
78 | {
79 | StoreType = @"Windows",
80 | StorePath = @"CurrentUser\TrustedPeople",
81 | },
82 | NonceLength = 32,
83 | AutoAcceptUntrustedCertificates = true
84 | },
85 | TransportConfigurations = new TransportConfigurationCollection(),
86 | TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
87 | ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
88 | };
89 | l_applicationConfig.Validate(ApplicationType.Client);
90 | if (l_applicationConfig.SecurityConfiguration.AutoAcceptUntrustedCertificates)
91 | {
92 | l_applicationConfig.CertificateValidator.CertificateValidation += (s, e) =>
93 | { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
94 | }
95 |
96 | Session l_session = Session.Create(l_applicationConfig, new ConfiguredEndpoint(null, new EndpointDescription("opc.tcp://ac-l32-m7-lth1:51210/UA/SampleServer")), true, "OdenwaldUnitTest", 60000, null, null);//EndpointDescription need to be changed according to your OPC server
97 |
98 | string[] browsePaths = new string[]
99 | {
100 | "2:Data/2:Dynamic/2:Scalar/2:Int32Value"
101 | };
102 |
103 | string nodeRelativePath = "Data.Dynamic.Scalar.Int32Value";
104 |
105 | var nsCount = l_session.NamespaceUris.Count;
106 | string[] relativePaths = { "Objects/Data/Dynamic/Scalar/Int32Value/" };
107 | relativePaths = nodeRelativePath.Split('.');
108 |
109 | var nodeList = OpcUaHelper.TranslateBrowsePaths(l_session, ObjectIds.ObjectsFolder, l_session.NamespaceUris, browsePaths);
110 |
111 | Assert.NotNull(nodeList);
112 | Assert.Equal(1, nodeList.Count);
113 |
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Odenwald.Common/Opc/OpcHelper.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Odenwald.Common.Opc
9 | {
10 | public static class OpcHelper
11 | {
12 | static ILog l_logger = LogManager.GetLogger(typeof(OpcHelper));
13 | public static bool QualifyMetric(ref OpcMetric metric, Dictionary cache )
14 | {
15 | if (PointHasGoodOrDifferentBadStatus(metric))
16 | {
17 | if (!cache.ContainsKey(metric.Measurement.Name))
18 | {
19 | cache.Add(metric.Measurement.Name, metric.OpcValue);
20 | metric.Measurement.LastOpcstatus = metric.Opcstatus;
21 | metric.Measurement.LastValue = metric.OpcValue;
22 | }
23 | else
24 | {
25 | object lastvalue;
26 | cache.TryGetValue(metric.Measurement.Name, out lastvalue);
27 | metric.Measurement.LastValue = lastvalue;
28 | }
29 |
30 |
31 | if (!PointIsValid(metric) || !PointMatchesType(metric))
32 | {
33 | // Set de default value for the type specified
34 | l_logger.ErrorFormat("Invalid point: measurement.name<{0}>, measurement.path<{1}>, metric.value<{2}>", metric.Measurement.Name, metric.Measurement.Path, metric.OpcValue.ToString());
35 | switch (metric.Measurement.DataType)
36 | {
37 | case "number":
38 | metric.OpcValue = 0;
39 | break;
40 | case "boolean":
41 | metric.OpcValue = false;
42 | break;
43 | case "string":
44 | metric.OpcValue = "";
45 | break;
46 | default:
47 | l_logger.Error("No valid datatype, ignoring point");
48 | break;
49 | }
50 | return false;
51 | }
52 | }
53 | // Check for deadband
54 | if (PointIsWithinDeadband(metric)) return false;
55 | if (!PointMatchesType(metric))
56 | {
57 | l_logger.ErrorFormat("Invalid type returned from OPC. Ignoring point {0}", metric.Measurement.Name);
58 | return false;
59 | }
60 | return true;
61 | }
62 |
63 | static bool PointMatchesType(OpcMetric metric)
64 | {
65 | var match = (metric.OpcValue.IsNumber() && metric.Measurement.DataType == "number")
66 | || metric.OpcValue.IsBoolean() && metric.Measurement.DataType == "boolean"
67 | || metric.OpcValue.IsString() && metric.Measurement.DataType == "string";
68 |
69 | if (!match)
70 | {
71 | //log here
72 |
73 | }
74 | return match;
75 | }
76 | static bool PointIsValid(OpcMetric p)
77 | {
78 | // check if the value is a type that we can handle (number or a bool).
79 | return (p.OpcValue != null && (p.OpcValue.IsBoolean() || p.OpcValue.IsNumber())) || p.OpcValue.IsString();
80 |
81 | }
82 | static bool PointHasGoodOrDifferentBadStatus(OpcMetric p)
83 | {
84 | var curr = p.Opcstatus;
85 | var prev = p.Measurement.LastOpcstatus;
86 |
87 | if (curr == "Good" || curr != prev || curr == "S_OK") return true;
88 | return false;
89 | }
90 |
91 |
92 | static bool PointIsWithinDeadband(OpcMetric metric)
93 | {
94 | // some vars for shorter statements later on.
95 | var curr = metric.OpcValue;
96 | var prev = metric.Measurement.LastValue;
97 | var dba = metric.Measurement.DeadbandAbsolute;
98 | var dbr = metric.Measurement.DeadbandRelative;
99 |
100 | // return early if the type of the previous value is not the same as the current.
101 | // this will also return when this is the first value and prev is still undefined.
102 | if (curr.GetType() != prev.GetType()) return false;
103 |
104 | // calculate deadbands based on value type. For numbers, make the
105 | // calculations for both absolute and relative if they are set. For bool,
106 | // just check if a deadband has been set and if the value has changed.
107 |
108 | if (curr.IsNumber())
109 | {
110 |
111 | if (dba > 0 && Math.Abs(System.Convert.ToDecimal(curr) - System.Convert.ToDecimal(prev)) < dba)
112 | {
113 | return true;
114 | }
115 | if (dbr > 0 && Math.Abs(System.Convert.ToDecimal(curr) - System.Convert.ToDecimal(prev)) < Math.Abs(System.Convert.ToDecimal(prev)) * dbr)
116 | {
117 | // console.log("New value is within relative deadband.", p);
118 | return true;
119 |
120 | }
121 | }
122 | else if (curr.IsBoolean())
123 | {
124 | if (dba > 0 && prev == curr)
125 | // console.log("New value is within bool deadband.", p);
126 | return true;
127 |
128 | }
129 | else if (curr.IsString())
130 | return true;
131 | return false;
132 |
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Odenwald/Config/OdenwaldConfig.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using System;
15 | using System.Collections.Generic;
16 | using System.Configuration;
17 |
18 | namespace Odenwald
19 | {
20 |
21 | public class OdenwaldConfigHelper
22 | {
23 | public static IDictionary GetMetaData()
24 | {
25 | IDictionary metaData = new Dictionary();
26 |
27 | var coreConfig = ConfigurationManager.GetSection("Odenwald") as OdenwaldConfig;
28 | if (coreConfig == null)
29 | {
30 | throw new Exception("Cannot get configuration section : Odenwald");
31 | }
32 | foreach (OdenwaldConfig.TagConfig tagConfig in coreConfig.MetaData)
33 | {
34 | metaData[tagConfig.Name] = tagConfig.Value;
35 | }
36 | return (metaData);
37 | }
38 | }
39 |
40 | public class OdenwaldConfig : ConfigurationSection
41 | {
42 | [ConfigurationProperty("GeneralSettings", IsRequired = true)]
43 | public GeneralSettingsConfig GeneralSettings
44 | {
45 | get { return (GeneralSettingsConfig)base["GeneralSettings"]; }
46 | set { base["GeneralSettings"] = value; }
47 | }
48 |
49 | [ConfigurationProperty("Plugins", IsRequired = true)]
50 | [ConfigurationCollection(typeof(PluginCollection), AddItemName = "Plugin")]
51 | public PluginCollection Plugins
52 | {
53 | get { return (PluginCollection)base["Plugins"]; }
54 | set { base["Plugins"] = value; }
55 | }
56 |
57 | [ConfigurationProperty("MetaData", IsRequired = false)]
58 | [ConfigurationCollection(typeof(TagCollection), AddItemName = "Tag")]
59 | public TagCollection MetaData
60 | {
61 | get { return (TagCollection)base["MetaData"]; }
62 | set { base["MetaData"] = value; }
63 | }
64 |
65 | public static OdenwaldConfigHelper GetConfig()
66 | {
67 | return (OdenwaldConfigHelper)ConfigurationManager.GetSection("OdenwaldConfig") ?? new OdenwaldConfigHelper();
68 | }
69 |
70 | public sealed class GeneralSettingsConfig : ConfigurationElement
71 | {
72 | [ConfigurationProperty("Interval", IsRequired = true)]
73 | public int Interval
74 | {
75 | get { return (int)base["Interval"]; }
76 | set { base["Interval"] = value; }
77 | }
78 |
79 | [ConfigurationProperty("Timeout", IsRequired = true)]
80 | public int Timeout
81 | {
82 | get { return (int)base["Timeout"]; }
83 | set { base["Timeout"] = value; }
84 | }
85 |
86 | [ConfigurationProperty("StoreRates", IsRequired = true)]
87 | public bool StoreRates
88 | {
89 | get { return (bool)base["StoreRates"]; }
90 | set { base["StoreRates"] = value; }
91 | }
92 | }
93 |
94 | public sealed class PluginCollection : ConfigurationElementCollection
95 | {
96 | protected override ConfigurationElement CreateNewElement()
97 | {
98 | return new PluginConfig();
99 | }
100 |
101 | protected override object GetElementKey(ConfigurationElement element)
102 | {
103 | return (((PluginConfig)element).UniqueId);
104 | }
105 | }
106 |
107 | public sealed class PluginConfig : ConfigurationElement
108 | {
109 | public PluginConfig()
110 | {
111 | UniqueId = Guid.NewGuid();
112 | }
113 |
114 | internal Guid UniqueId { get; set; }
115 |
116 | [ConfigurationProperty("Name", IsRequired = true)]
117 | public string Name
118 | {
119 | get { return (string)base["Name"]; }
120 | set { base["Name"] = value; }
121 | }
122 |
123 | [ConfigurationProperty("Class", IsRequired = true)]
124 | public string Class
125 | {
126 | get { return (string)base["Class"]; }
127 | set { base["Class"] = value; }
128 | }
129 |
130 | [ConfigurationProperty("Enable", IsRequired = true)]
131 | public bool Enable
132 | {
133 | get { return (bool)base["Enable"]; }
134 | set { base["Enable"] = value; }
135 | }
136 | }
137 |
138 | public sealed class TagCollection : ConfigurationElementCollection
139 | {
140 | protected override ConfigurationElement CreateNewElement()
141 | {
142 | return new TagConfig();
143 | }
144 |
145 | protected override object GetElementKey(ConfigurationElement element)
146 | {
147 | return (((TagConfig)element).UniqueId);
148 | }
149 | }
150 | public sealed class TagConfig : ConfigurationElement
151 | {
152 | public TagConfig()
153 | {
154 | UniqueId = Guid.NewGuid();
155 | }
156 |
157 | internal Guid UniqueId { get; set; }
158 |
159 | [ConfigurationProperty("Name", IsRequired = true)]
160 | public string Name
161 | {
162 | get { return (string)base["Name"]; }
163 | set { base["Name"] = value; }
164 | }
165 |
166 | [ConfigurationProperty("Value", IsRequired = true)]
167 | public string Value
168 | {
169 | get { return (string)base["Value"]; }
170 | set { base["Value"] = value; }
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Odenwald.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald", "Odenwald\Odenwald.csproj", "{BB7A7712-CC11-4D95-83DC-A0AB28714860}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC6D364C-E228-46F3-B0DC-36E10395334B}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{5256FABB-EEFB-4508-A51C-EAC828656DE7}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.ConsolePlugin", "Odenwald.ConsolePlugin\Odenwald.ConsolePlugin.csproj", "{BA07862A-586A-47AC-9069-7D1904973A83}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.OpcUaPlugin", "Odenwald.OpcUaPlugin\Odenwald.OpcUaPlugin.csproj", "{712B2914-BF62-4278-BFE2-EB6925760839}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.OpcUaPluginTest", "Tests\Odenwald.OpcUaPluginTest\Odenwald.OpcUaPluginTest.csproj", "{C46F6932-AB4C-4A49-A3BA-1F9690015A48}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.InfluxDbPlugin", "Odenwald.InfluxDbPlugin\Odenwald.InfluxDbPlugin.csproj", "{084BE120-923F-4517-850C-17D1D5590AC9}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.OpcDaPlugin", "Odenwald.OpcDaPlugin\Odenwald.OpcDaPlugin.csproj", "{3C3FD86F-220D-418F-B964-3C4590824FCE}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.Common", "Odenwald.Common\Odenwald.Common.csproj", "{FEF57F91-04C1-4D42-BA2E-737697AB26C1}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.KafkaProducerPlugin", "Odenwald.KafkaProducerPlugin\Odenwald.KafkaProducerPlugin.csproj", "{EEC9106E-6812-444B-9A5E-59CDF4022D4A}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.KafkaConsumerPlugin", "Odenwald.KafkaConsumerPlugin\Odenwald.KafkaConsumerPlugin.csproj", "{B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}"
27 | EndProject
28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Odenwald.App", "Odenwald.App\Odenwald.App.csproj", "{AD130047-5631-4F12-B357-82B45E671C83}"
29 | EndProject
30 | Global
31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
32 | Debug|Any CPU = Debug|Any CPU
33 | Release|Any CPU = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {BB7A7712-CC11-4D95-83DC-A0AB28714860}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {BA07862A-586A-47AC-9069-7D1904973A83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {BA07862A-586A-47AC-9069-7D1904973A83}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {BA07862A-586A-47AC-9069-7D1904973A83}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {BA07862A-586A-47AC-9069-7D1904973A83}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {712B2914-BF62-4278-BFE2-EB6925760839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {712B2914-BF62-4278-BFE2-EB6925760839}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {712B2914-BF62-4278-BFE2-EB6925760839}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {712B2914-BF62-4278-BFE2-EB6925760839}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {084BE120-923F-4517-850C-17D1D5590AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {084BE120-923F-4517-850C-17D1D5590AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {084BE120-923F-4517-850C-17D1D5590AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {084BE120-923F-4517-850C-17D1D5590AC9}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {3C3FD86F-220D-418F-B964-3C4590824FCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {3C3FD86F-220D-418F-B964-3C4590824FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {3C3FD86F-220D-418F-B964-3C4590824FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {3C3FD86F-220D-418F-B964-3C4590824FCE}.Release|Any CPU.Build.0 = Release|Any CPU
60 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {FEF57F91-04C1-4D42-BA2E-737697AB26C1}.Release|Any CPU.Build.0 = Release|Any CPU
64 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
66 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
71 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA}.Release|Any CPU.Build.0 = Release|Any CPU
72 | {AD130047-5631-4F12-B357-82B45E671C83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73 | {AD130047-5631-4F12-B357-82B45E671C83}.Debug|Any CPU.Build.0 = Debug|Any CPU
74 | {AD130047-5631-4F12-B357-82B45E671C83}.Release|Any CPU.ActiveCfg = Release|Any CPU
75 | {AD130047-5631-4F12-B357-82B45E671C83}.Release|Any CPU.Build.0 = Release|Any CPU
76 | EndGlobalSection
77 | GlobalSection(SolutionProperties) = preSolution
78 | HideSolutionNode = FALSE
79 | EndGlobalSection
80 | GlobalSection(NestedProjects) = preSolution
81 | {BA07862A-586A-47AC-9069-7D1904973A83} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
82 | {712B2914-BF62-4278-BFE2-EB6925760839} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
83 | {C46F6932-AB4C-4A49-A3BA-1F9690015A48} = {BC6D364C-E228-46F3-B0DC-36E10395334B}
84 | {084BE120-923F-4517-850C-17D1D5590AC9} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
85 | {3C3FD86F-220D-418F-B964-3C4590824FCE} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
86 | {EEC9106E-6812-444B-9A5E-59CDF4022D4A} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
87 | {B9A8E446-DB9F-46E9-BFCD-916A3D8424AA} = {5256FABB-EEFB-4508-A51C-EAC828656DE7}
88 | EndGlobalSection
89 | EndGlobal
90 |
--------------------------------------------------------------------------------
/Odenwald/Type/Types.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using log4net;
15 | using System;
16 | using System.Collections.Generic;
17 | using System.IO;
18 | using System.Text;
19 | using System.Text.RegularExpressions;
20 |
21 | namespace Odenwald
22 | {
23 | public enum DsType
24 | {
25 | Absolute,
26 | Counter,
27 | Derive,
28 | Gauge
29 | };
30 |
31 | public enum Status
32 | {
33 | Success,
34 | Failure
35 | };
36 |
37 | public class DataSource
38 | {
39 | public DataSource(string name, DsType type, double min, double max)
40 | {
41 | Name = name;
42 | Type = type;
43 | Min = min;
44 | Max = max;
45 | }
46 |
47 | public string Name { get; set; }
48 | public DsType Type { get; set; }
49 | public double Min { get; set; }
50 | public double Max { get; set; }
51 | }
52 |
53 | internal class DataSetCollection
54 | {
55 | private static ILog m_logger = LogManager.GetLogger(typeof(DataSetCollection));
56 | private static volatile DataSetCollection _instance;
57 | private static readonly object SyncRoot = new Object();
58 |
59 | private readonly Dictionary> _dataSetMap;
60 | //
61 |
62 | private DataSetCollection()
63 | {
64 | _dataSetMap = new Dictionary>();
65 | }
66 |
67 | public static DataSetCollection Instance
68 | {
69 | get
70 | {
71 | if (_instance == null)
72 | {
73 | lock (SyncRoot)
74 | {
75 | if (_instance == null)
76 | {
77 | _instance = new DataSetCollection();
78 | _instance.Load();
79 | }
80 | }
81 | }
82 | return _instance;
83 | }
84 | }
85 |
86 | private static Status GetDouble(string dstr, out double val)
87 | {
88 | if (dstr == "u" || dstr == "U")
89 | {
90 | val = Double.NaN;
91 | return (Status.Success);
92 | }
93 | try
94 | {
95 | val = Double.Parse(dstr);
96 | }
97 | catch (Exception)
98 | {
99 | val = Double.NaN;
100 | return (Status.Failure);
101 | }
102 | return (Status.Success);
103 | }
104 |
105 | public void Print()
106 | {
107 | var sb = new StringBuilder();
108 | foreach (var entry in _dataSetMap)
109 | {
110 | sb.Append(string.Format("\n[{0}] ==>", entry.Key));
111 | foreach (DataSource ds in entry.Value)
112 | {
113 | sb.Append(string.Format(" [{0}:{1}:{2}:{3}]", ds.Name, ds.Type, ds.Min, ds.Max));
114 | }
115 | }
116 | Console.WriteLine(sb.ToString());
117 | }
118 |
119 | public void Load()
120 | {
121 | const string dataSetPattern = @"[\s\t]*(\w+)[\s\t]*(.*)$";
122 | const string dataSourcePattern = @"(\w+):(ABSOLUTE|COUNTER|DERIVE|GAUGE):([+-]?\w+):([+-]?\w+)[,]?\s*";
123 |
124 | var dataSetRegex = new Regex(dataSetPattern, RegexOptions.IgnoreCase);
125 | var dataSourceRegex = new Regex(dataSourcePattern, RegexOptions.IgnoreCase);
126 |
127 | string fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Type\types.db");
128 | string[] lines = File.ReadAllLines(fileName);
129 |
130 | foreach (string line in lines)
131 | {
132 | // skip comments and blank lines
133 | if (line.StartsWith("#") || line.Trim() == string.Empty)
134 | {
135 | continue;
136 | }
137 | Match match = dataSetRegex.Match(line);
138 | if (match.Groups.Count < 3)
139 | {
140 | m_logger.ErrorFormat("types.db: invalid data set [{0}]", line);
141 | continue;
142 | }
143 | string dataSetName = match.Groups[1].Value;
144 | MatchCollection matches = dataSourceRegex.Matches(line);
145 | if (matches.Count < 1)
146 | {
147 | m_logger.ErrorFormat("types.db: invalid data source [{0}]", line);
148 | continue;
149 | }
150 | var dataSourceList = new List();
151 | foreach (Match m in matches)
152 | {
153 | if (m.Groups.Count != 5)
154 | {
155 | m_logger.ErrorFormat("types.db: cannot parse data source [{0}]", line);
156 | dataSourceList.Clear();
157 | break;
158 | }
159 |
160 | string dsName = m.Groups[1].Value;
161 | var dstype = (DsType)Enum.Parse(typeof(DsType), m.Groups[2].Value, true);
162 |
163 | double min, max;
164 |
165 | if (GetDouble(m.Groups[3].Value, out min) != Status.Success)
166 | {
167 | m_logger.Error(string.Format("types.db: invalid Min value [{0}]", line));
168 | dataSourceList.Clear();
169 | break;
170 | }
171 |
172 | if (GetDouble(m.Groups[4].Value, out max) != Status.Success)
173 | {
174 | m_logger.Error(string.Format("types.db: invalid Max value [{0}]", line));
175 | dataSourceList.Clear();
176 | break;
177 | }
178 |
179 | var ds = new DataSource(dsName, dstype, min, max);
180 | dataSourceList.Add(ds);
181 | }
182 | if (dataSourceList.Count > 0)
183 | {
184 | _dataSetMap[dataSetName] = dataSourceList;
185 | }
186 | }
187 | }
188 |
189 | public IList GetDataSource(string dataSetName)
190 | {
191 | IList dataSourceList;
192 | return (_dataSetMap.TryGetValue(dataSetName, out dataSourceList) ? (dataSourceList) : (null));
193 | }
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/Odenwald/Aggregator.cs:
--------------------------------------------------------------------------------
1 |
2 | // ----------------------------------------------------------------------------
3 | // Copyright (C) 2017 Robinson.
4 | // https://github.com/robinson
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | using log4net;
15 | using Odenwald.Common;
16 | using System;
17 | using System.Collections.Generic;
18 | using System.Linq;
19 | using System.Text;
20 | using System.Threading.Tasks;
21 |
22 | namespace Odenwald
23 | {
24 | internal class CacheEntry
25 | {
26 | public MetricValue MetricRate;
27 | public double[] RawValues;
28 |
29 | public CacheEntry(MetricValue metricValue)
30 | {
31 | MetricRate = metricValue;
32 | RawValues = (double[])metricValue.Values.Clone();
33 | }
34 | }
35 | public class Aggregator
36 | {
37 | static ILog l_logger = LogManager.GetLogger(typeof(Aggregator));
38 | readonly Dictionary l_cache;
39 | readonly Object l_cacheLock;
40 | readonly bool l_storeRates;
41 | readonly int l_timeoutSeconds;
42 | public Aggregator(int timeoutSeconds, bool storeRates)
43 | {
44 | l_cache = new Dictionary();
45 | l_cacheLock = new object();
46 | l_timeoutSeconds = timeoutSeconds;
47 | l_storeRates = storeRates;
48 | }
49 |
50 |
51 |
52 |
53 | public void Aggregate(ref MetricValue metric)
54 | {
55 | // If rates are not stored then there is nothing to aggregate
56 | if (!l_storeRates)
57 | {
58 | return;
59 | }
60 | IList dsl = DataSetCollection.Instance.GetDataSource(metric.TypeName);
61 | if (dsl == null || metric.Values.Length != dsl.Count)
62 | {
63 | return;
64 | }
65 | double now = Util.GetNow();
66 | lock (l_cacheLock)
67 | {
68 | CacheEntry cEntry;
69 | string key = metric.Key;
70 |
71 | if (!(l_cache.TryGetValue(key, out cEntry)))
72 | {
73 | cEntry = new CacheEntry(metric.DeepCopy());
74 | for (int i = 0; i < metric.Values.Length; i++)
75 | {
76 | if (dsl[i].Type == DsType.Derive ||
77 | dsl[i].Type == DsType.Absolute ||
78 | dsl[i].Type == DsType.Counter)
79 | {
80 | metric.Values[i] = double.NaN;
81 | cEntry.MetricRate.Values[i] = double.NaN;
82 | }
83 | }
84 | l_cache[key] = cEntry;
85 | return;
86 | }
87 | for (int i = 0; i < metric.Values.Length; i++)
88 | {
89 | double rawValNew = metric.Values[i];
90 | double rawValOld = cEntry.RawValues[i];
91 | double rawValDiff = rawValNew - rawValOld;
92 | double timeDiff = cEntry.MetricRate.Epoch - DateTimeOffset.Now.ToUnixTimeSeconds();
93 |
94 | double rateNew = rawValDiff / timeDiff;
95 |
96 | switch (dsl[i].Type)
97 | {
98 | case DsType.Gauge:
99 | // no rates calculations are done, values are stored as-is for gauge
100 | cEntry.RawValues[i] = rawValNew;
101 | cEntry.MetricRate.Values[i] = rawValNew;
102 | break;
103 |
104 | case DsType.Absolute:
105 | // similar to gauge, except value will be divided by time diff
106 | cEntry.MetricRate.Values[i] = rawValNew / timeDiff;
107 | cEntry.RawValues[i] = rawValNew;
108 | metric.Values[i] = cEntry.MetricRate.Values[i];
109 | break;
110 |
111 | case DsType.Derive:
112 | cEntry.RawValues[i] = rawValNew;
113 | cEntry.MetricRate.Values[i] = rateNew;
114 | metric.Values[i] = rateNew;
115 |
116 | break;
117 |
118 | case DsType.Counter:
119 | // Counters are very simlar to derive except when counter wraps around
120 | if (rawValNew < rawValOld)
121 | {
122 | // counter has wrapped around
123 | cEntry.MetricRate.Values[i] = rawValNew / timeDiff;
124 | cEntry.RawValues[i] = rawValNew;
125 | metric.Values[i] = cEntry.MetricRate.Values[i];
126 | }
127 | else
128 | {
129 | cEntry.MetricRate.Values[i] = rateNew;
130 | cEntry.RawValues[i] = rawValNew;
131 | metric.Values[i] = rateNew;
132 | }
133 | break;
134 | }
135 | // range checks
136 | if (Convert.ToDouble(metric.Values[i]) < dsl[i].Min)
137 | {
138 | metric.Values[i] = dsl[i].Min;
139 | cEntry.RawValues[i] = metric.Values[i];
140 | }
141 | if (Convert.ToDouble(metric.Values[i]) > dsl[i].Max)
142 | {
143 | metric.Values[i] = dsl[i].Max;
144 | cEntry.RawValues[i] = metric.Values[i];
145 | }
146 | }
147 | }
148 | }
149 |
150 | public void RemoveExpiredEntries()
151 | {//TODO: consider about remove expired entries in the cache
152 | // If rates are not stored then there is nothing to remove
153 | if (!l_storeRates)
154 | {
155 | return;
156 | }
157 | double now = Util.GetNow();
158 | double expirationTime = now - l_timeoutSeconds;
159 | var removeList = new List();
160 |
161 | lock (l_cacheLock)
162 | {
163 | removeList.AddRange(from pair in l_cache
164 | let cEntry = pair.Value
165 | where cEntry.MetricRate.Epoch < expirationTime
166 | select pair.Key);
167 | if (removeList.Count > 0)
168 | l_logger.DebugFormat("Removing expired entries: {0}", removeList.Count);
169 | foreach (string key in removeList)
170 | {
171 | l_cache.Remove(key);
172 | }
173 | }
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/Odenwald.OpcDaPlugin/OpcDaPlugin.cs:
--------------------------------------------------------------------------------
1 | using log4net;
2 | using Odenwald.Common.Opc;
3 | using Opc;
4 | using System;
5 | using System.Collections.Concurrent;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 |
10 | using Factory = OpcCom.Factory;
11 | using OpcDa = Opc.Da;
12 |
13 | namespace Odenwald.OpcDaPlugin
14 | {
15 | public class OpcDaPlugin : IMetricsReadPlugin, IDisposable
16 | {
17 | #region attributes
18 | static ILog l_logger = LogManager.GetLogger(typeof(OpcDaPlugin));
19 | List PolledMeasurements;
20 | List MonitoredMeasurements;
21 | static Dictionary l_cache = new Dictionary();
22 | BlockingCollection l_metricCollection;
23 | OpcPluginConfig l_opcDaPluginConfig;
24 | OpcDa.Server l_server;
25 |
26 | #endregion
27 |
28 | #region IMetricsReadPlugin
29 | public void Configure()
30 | {
31 | l_opcDaPluginConfig = OpcPluginConfig.GetConfig("OpcDa");
32 | if (l_opcDaPluginConfig == null)
33 | {
34 | throw new Exception("Cannot get configuration section : OpcUa");
35 | }
36 |
37 | }
38 |
39 | public IList Read()
40 | {
41 | if (l_metricCollection.Count <= 0)
42 | return null;
43 | List metricList = new List();
44 |
45 | while (l_metricCollection.Count > 0)
46 | {
47 |
48 | OpcMetric data = null;
49 | try
50 | {
51 | data = l_metricCollection.Take();
52 | }
53 | catch (InvalidOperationException) { }
54 |
55 | if (data != null)
56 | {
57 | MetricValue metricValue = new MetricValue()
58 | {
59 | TypeName = "gauge",
60 | TypeInstanceName = "gauge",
61 | //Interval = data.Measurement.mo
62 | HostName = "localhost",
63 | PluginInstanceName = "OpcDaPluginInstance",
64 | PluginName = "OpcDaPlugin",
65 | Extension = data.JsonString()
66 | };
67 | metricList.Add(metricValue);
68 | }
69 | }
70 | l_logger.DebugFormat("Read {0} items.", metricList.Count);
71 | return metricList;
72 | }
73 |
74 | public void Start()
75 | {
76 | InitializeMeasurements();
77 | Uri serverUri = new Uri(l_opcDaPluginConfig.Settings.Url);
78 | var opcServerUrl = new URL(serverUri.ToString())
79 | {
80 | Scheme = serverUri.Scheme,
81 | HostName = serverUri.Host
82 | };
83 | l_server = new OpcDa.Server(new Factory(), opcServerUrl);
84 | l_server.Connect();
85 |
86 | l_metricCollection = new BlockingCollection();
87 | StartMonitoring();
88 | StartPolling();
89 | }
90 |
91 | public void Stop()
92 | {
93 | if (l_server != null)
94 | l_server.Dispose();
95 | }
96 | #endregion
97 |
98 | #region methods
99 | void InitializeMeasurements()
100 | {
101 | MonitoredMeasurements = new List();
102 | PolledMeasurements = new List();
103 | foreach (MeasurementConfig item in l_opcDaPluginConfig.Measurements)
104 | {
105 | Dictionary tags = null;
106 | if (!item.Tags.Equals(""))
107 | tags = item.Tags.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
108 | .Select(part => part.Split(':'))
109 | .ToDictionary(split => split[0], split => split[1]);
110 | switch (item.CollectionType)
111 | {
112 | case "monitored":
113 |
114 | var monitoredpoint = new MonitoredMeasurement()
115 | {
116 | Name = item.Name,
117 | Path = item.Path,
118 | MonitorResolution = item.MonitorResolution > 0 ? item.MonitorResolution : 0,
119 | DeadbandAbsolute = item.DeadbandAbsolute > 0 ? item.DeadbandAbsolute : 0,
120 | DeadbandRelative = item.DeadbandRelative > 0 ? item.DeadbandRelative : 0,
121 | DataType = item.DataType,
122 | Tags = tags
123 |
124 | };
125 |
126 | MonitoredMeasurements.Add(monitoredpoint);
127 | break;
128 | case "polled":
129 | var polledPoint = new PolledMeasurement()
130 | {
131 | Name = item.Name,
132 | Path = item.Path,
133 | DeadbandAbsolute = item.DeadbandAbsolute > 0 ? item.DeadbandAbsolute : 0,
134 | DeadbandRelative = item.DeadbandRelative > 0 ? item.DeadbandRelative : 0,
135 | PollInterval = item.PollInterval,
136 | DataType = item.DataType,
137 | Tags = tags
138 | };
139 |
140 | PolledMeasurements.Add(polledPoint);
141 |
142 | break;
143 | default:
144 | //no collection type, log
145 | l_logger.DebugFormat("no collection type at: {0}", item.Name);
146 | break;
147 | }
148 | }
149 |
150 | }
151 | void StartMonitoring()
152 | {
153 | foreach (var item in MonitoredMeasurements)
154 | {
155 | var subItem = new OpcDa.SubscriptionState
156 | {
157 | Name = item.Name,
158 | Active = true,
159 | UpdateRate = item.MonitorResolution
160 | };
161 | var sub = l_server.CreateSubscription(subItem);
162 | sub.DataChanged += (handle, requestHandle, values) =>
163 | {
164 | var p = values[0];
165 | MonitorData(item, p);
166 | };
167 | sub.AddItems(new[] { new OpcDa.Item { ItemName = item.Path } });
168 | sub.SetEnabled(true);
169 | }
170 | }
171 |
172 | private void MonitorData(MonitoredMeasurement measurement, OpcDa.ItemValueResult p)
173 | {
174 | OpcMetric metric = new OpcMetric()
175 | {
176 | Timestamp = p.Timestamp,
177 | OpcValue = p.Value,
178 | Opcstatus = p.ResultID.ToString(),
179 | Measurement = (MeasurementDto)measurement
180 | };
181 | l_metricCollection.Add(metric);
182 | }
183 |
184 | void StartPolling()
185 | {
186 | foreach (var item in PolledMeasurements)
187 | {
188 | var task = Task.Factory.StartNew((Func)(async () => // <- marked async
189 | {
190 | do
191 | {
192 | ReadMeasurement(item);
193 | await Task.Delay(TimeSpan.FromMilliseconds(item.PollInterval));
194 | } while (true);
195 | }));
196 | }
197 | }
198 | void ReadMeasurement(PolledMeasurement measurement)
199 | {
200 | var item = new OpcDa.Item { ItemName = measurement.Path };
201 | if (l_server == null || l_server.GetStatus().ServerState != OpcDa.serverState.running)
202 | {
203 | l_logger.ErrorFormat(string.Format("Server not connected. Cannot read path {0}.", measurement.Name));
204 | throw new Exception(string.Format("Server not connected. Cannot read path {0}.",measurement.Name));
205 | }
206 | var result = l_server.Read(new[] { item })[0];
207 | if (result == null)
208 | {
209 | l_logger.Error("the server replied with an empty response!!!");
210 | throw new Exception("the server replied with an empty response");//if any item cannot read, throw exeption
211 | }
212 | if (result.ResultID.ToString() != "S_OK")
213 | {
214 | l_logger.ErrorFormat(string.Format("Invalid response from the server. (Response Status: {0}, Opc Tag: {1})", result.ResultID, measurement.Path));
215 | throw new Exception(string.Format("Invalid response from the server. (Response Status: {0}, Opc Tag: {1})", result.ResultID, measurement.Path));
216 | }
217 |
218 | OpcMetric metric = new OpcMetric()
219 | {
220 | Measurement = measurement,
221 | Opcstatus = result.ResultID.ToString(),
222 | OpcValue = result.Value,
223 | Timestamp = result.Timestamp
224 |
225 | };
226 | if (OpcHelper.QualifyMetric(ref metric, l_cache))
227 | {
228 | l_cache[metric.Measurement.Name] = metric.OpcValue;
229 | l_metricCollection.Add(metric);
230 | }
231 | }
232 |
233 | public void Dispose()
234 | {
235 | if (l_server != null)
236 | l_server.Dispose();
237 | GC.SuppressFinalize(this);
238 | }
239 | #endregion
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/Odenwald.App/Odenwald.App.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AD130047-5631-4F12-B357-82B45E671C83}
8 | Exe
9 | Properties
10 | Odenwald.App
11 | Odenwald.App
12 | v4.6
13 | 512
14 | publish\
15 | true
16 | Disk
17 | false
18 | Foreground
19 | 7
20 | Days
21 | false
22 | false
23 | true
24 | 0
25 | 1.0.0.%2a
26 | false
27 | false
28 | true
29 |
30 |
31 | true
32 | full
33 | false
34 | bin\Debug\
35 | DEBUG;TRACE
36 | prompt
37 | 4
38 | false
39 |
40 |
41 | pdbonly
42 | true
43 | bin\Release\
44 | TRACE
45 | prompt
46 | 4
47 |
48 |
49 |
50 |
51 |
52 |
53 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
54 | True
55 |
56 |
57 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll
58 | True
59 |
60 |
61 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll
62 | True
63 |
64 |
65 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll
66 | True
67 |
68 |
69 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
70 | True
71 |
72 |
73 |
74 |
75 |
76 |
77 | ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
78 | True
79 |
80 |
81 | ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
82 | True
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Component
96 |
97 |
98 | OdenwaldService.cs
99 |
100 |
101 |
102 |
103 |
104 |
105 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
106 | Odenwald
107 |
108 |
109 |
110 |
111 | Designer
112 |
113 |
114 |
115 |
116 |
117 | False
118 | Microsoft .NET Framework 4.6 %28x86 and x64%29
119 | true
120 |
121 |
122 | False
123 | .NET Framework 3.5 SP1
124 | false
125 |
126 |
127 |
128 |
129 | xcopy "$(SolutionDir)Odenwald.ConsolePlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
130 | xcopy "$(SolutionDir)Odenwald.ConsolePlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
131 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
132 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
133 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
134 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
135 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
136 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
137 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
138 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
139 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
140 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
141 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
142 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
143 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
144 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
145 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
146 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
147 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
148 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
149 |
150 |
151 | del "$(SolutionDir)Odenwald.App\bin\*.*" /Q /F
152 |
153 |
154 |
155 |
156 |
157 |
158 |
165 |
--------------------------------------------------------------------------------
/Odenwald.Service/Odenwald.Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AD130047-5631-4F12-B357-82B45E671C83}
8 | Exe
9 | Properties
10 | Odenwald.Service
11 | Odenwald.Service
12 | v4.6
13 | 512
14 | publish\
15 | true
16 | Disk
17 | false
18 | Foreground
19 | 7
20 | Days
21 | false
22 | false
23 | true
24 | 0
25 | 1.0.0.%2a
26 | false
27 | false
28 | true
29 |
30 |
31 | true
32 | full
33 | false
34 | bin\Debug\
35 | DEBUG;TRACE
36 | prompt
37 | 4
38 | false
39 |
40 |
41 | pdbonly
42 | true
43 | bin\Release\
44 | TRACE
45 | prompt
46 | 4
47 |
48 |
49 |
50 |
51 |
52 |
53 | ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll
54 | True
55 |
56 |
57 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll
58 | True
59 |
60 |
61 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll
62 | True
63 |
64 |
65 | ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll
66 | True
67 |
68 |
69 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
70 | True
71 |
72 |
73 |
74 |
75 |
76 |
77 | ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
78 | True
79 |
80 |
81 | ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
82 | True
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Component
96 |
97 |
98 | OdenwaldService.cs
99 |
100 |
101 |
102 |
103 |
104 |
105 | {bb7a7712-cc11-4d95-83dc-a0ab28714860}
106 | Odenwald
107 |
108 |
109 |
110 |
111 | Designer
112 |
113 |
114 |
115 |
116 |
117 | False
118 | Microsoft .NET Framework 4.6 %28x86 and x64%29
119 | true
120 |
121 |
122 | False
123 | .NET Framework 3.5 SP1
124 | false
125 |
126 |
127 |
128 |
129 | xcopy "$(SolutionDir)Odenwald.ConsolePlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
130 | xcopy "$(SolutionDir)Odenwald.ConsolePlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
131 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
132 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
133 | xcopy "$(SolutionDir)Odenwald.WindowsPerformanceCounterPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
134 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
135 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
136 | xcopy "$(SolutionDir)Odenwald.OpcUaPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
137 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
138 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
139 | xcopy "$(SolutionDir)Odenwald.OpcDaPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
140 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
141 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
142 | xcopy "$(SolutionDir)Odenwald.InfluxDbPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
143 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
144 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
145 | xcopy "$(SolutionDir)Odenwald.KafkaProducerPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
146 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.dll" .\*.* /Y
147 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.pdb" .\*.* /Y
148 | xcopy "$(SolutionDir)Odenwald.KafkaConsumerPlugin\bin\$(ConfigurationName)\*.config" .\Config\*.* /Y
149 |
150 |
151 | del "$(SolutionDir)Odenwald.Service\bin\*.*" /Q /F
152 |
153 |
154 |
155 |
156 |
157 |
158 |
165 |
--------------------------------------------------------------------------------
/Odenwald/Type/types.db:
--------------------------------------------------------------------------------
1 | #
2 | # types.db - Data-set specifications for the system statistics collection daemon collectd
3 | # This file is a copy from following URL:
4 | # https://raw.githubusercontent.com/collectd/collectd/master/src/types.db
5 | #
6 | # The types.db file contains one line for each data-set specification. Each
7 | # line consists of two fields delimited by spaces and/or horizontal tabs.
8 | # The first field defines the name of the data-set, while the second field
9 | # defines a list of data-source specifications, delimited by spaces and,
10 | # optionally, a comma (",") right after each list-entry.
11 | #
12 | # The format of the data-source specification has been inspired by RRDtool's
13 | # data-source specification. Each data-source is defined by a quadruple made
14 | # up of the data-source name, type, minimal and maximal values, delimited by
15 | # colons (":"): ds-name:ds-type:min:max. ds-type may be either ABSOLUTE,
16 | # COUNTER, DERIVE, or GAUGE. min and max define the range of valid values for
17 | # data stored for this data-source. If U is specified for either the min or
18 | # max value, it will be set to unknown, meaning that no range checks will
19 | # happen. See rrdcreate(1) for more details.
20 | #
21 | #
22 | absolute value:ABSOLUTE:0:U
23 | apache_bytes value:DERIVE:0:U
24 | apache_connections value:GAUGE:0:65535
25 | apache_idle_workers value:GAUGE:0:65535
26 | apache_requests value:DERIVE:0:U
27 | apache_scoreboard value:GAUGE:0:65535
28 | ath_nodes value:GAUGE:0:65535
29 | ath_stat value:DERIVE:0:U
30 | backends value:GAUGE:0:65535
31 | bitrate value:GAUGE:0:4294967295
32 | blocked_clients value:GAUGE:0:U
33 | bytes value:GAUGE:0:U
34 | cache_eviction value:DERIVE:0:U
35 | cache_operation value:DERIVE:0:U
36 | cache_ratio value:GAUGE:0:100
37 | cache_result value:DERIVE:0:U
38 | cache_size value:GAUGE:0:U
39 | ceph_bytes value:GAUGE:U:U
40 | ceph_latency value:GAUGE:U:U
41 | ceph_rate value:DERIVE:0:U
42 | changes_since_last_save value:GAUGE:0:U
43 | charge value:GAUGE:0:U
44 | compression_ratio value:GAUGE:0:2
45 | compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
46 | connections value:DERIVE:0:U
47 | conntrack value:GAUGE:0:4294967295
48 | contextswitch value:DERIVE:0:U
49 | count value:GAUGE:0:U
50 | counter value:COUNTER:U:U
51 | cpufreq value:GAUGE:0:U
52 | cpu value:DERIVE:0:U
53 | current_connections value:GAUGE:0:U
54 | current_sessions value:GAUGE:0:U
55 | current value:GAUGE:U:U
56 | delay value:GAUGE:-1000000:1000000
57 | derive value:DERIVE:0:U
58 | df_complex value:GAUGE:0:U
59 | df_inodes value:GAUGE:0:U
60 | df used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
61 | disk_latency read:GAUGE:0:U, write:GAUGE:0:U
62 | disk_merged read:DERIVE:0:U, write:DERIVE:0:U
63 | disk_octets read:DERIVE:0:U, write:DERIVE:0:U
64 | disk_ops_complex value:DERIVE:0:U
65 | disk_ops read:DERIVE:0:U, write:DERIVE:0:U
66 | disk_time read:DERIVE:0:U, write:DERIVE:0:U
67 | disk_io_time io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
68 | dns_answer value:DERIVE:0:U
69 | dns_notify value:DERIVE:0:U
70 | dns_octets queries:DERIVE:0:U, responses:DERIVE:0:U
71 | dns_opcode value:DERIVE:0:U
72 | dns_qtype_cached value:GAUGE:0:4294967295
73 | dns_qtype value:DERIVE:0:U
74 | dns_query value:DERIVE:0:U
75 | dns_question value:DERIVE:0:U
76 | dns_rcode value:DERIVE:0:U
77 | dns_reject value:DERIVE:0:U
78 | dns_request value:DERIVE:0:U
79 | dns_resolver value:DERIVE:0:U
80 | dns_response value:DERIVE:0:U
81 | dns_transfer value:DERIVE:0:U
82 | dns_update value:DERIVE:0:U
83 | dns_zops value:DERIVE:0:U
84 | drbd_resource value:DERIVE:0:U
85 | duration seconds:GAUGE:0:U
86 | email_check value:GAUGE:0:U
87 | email_count value:GAUGE:0:U
88 | email_size value:GAUGE:0:U
89 | entropy value:GAUGE:0:4294967295
90 | expired_keys value:GAUGE:0:U
91 | fanspeed value:GAUGE:0:U
92 | file_size value:GAUGE:0:U
93 | files value:GAUGE:0:U
94 | flow value:GAUGE:0:U
95 | fork_rate value:DERIVE:0:U
96 | frequency_offset value:GAUGE:-1000000:1000000
97 | frequency value:GAUGE:0:U
98 | fscache_stat value:DERIVE:0:U
99 | gauge value:GAUGE:U:U
100 | hash_collisions value:DERIVE:0:U
101 | http_request_methods value:DERIVE:0:U
102 | http_requests value:DERIVE:0:U
103 | http_response_codes value:DERIVE:0:U
104 | humidity value:GAUGE:0:100
105 | if_collisions value:DERIVE:0:U
106 | if_dropped rx:DERIVE:0:U, tx:DERIVE:0:U
107 | if_errors rx:DERIVE:0:U, tx:DERIVE:0:U
108 | if_multicast value:DERIVE:0:U
109 | if_octets rx:DERIVE:0:U, tx:DERIVE:0:U
110 | if_packets rx:DERIVE:0:U, tx:DERIVE:0:U
111 | if_rx_errors value:DERIVE:0:U
112 | if_rx_octets value:DERIVE:0:U
113 | if_tx_errors value:DERIVE:0:U
114 | if_tx_octets value:DERIVE:0:U
115 | invocations value:DERIVE:0:U
116 | io_octets rx:DERIVE:0:U, tx:DERIVE:0:U
117 | io_packets rx:DERIVE:0:U, tx:DERIVE:0:U
118 | ipt_bytes value:DERIVE:0:U
119 | ipt_packets value:DERIVE:0:U
120 | irq value:DERIVE:0:U
121 | latency value:GAUGE:0:U
122 | links value:GAUGE:0:U
123 | load shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
124 | md_disks value:GAUGE:0:U
125 | memcached_command value:DERIVE:0:U
126 | memcached_connections value:GAUGE:0:U
127 | memcached_items value:GAUGE:0:U
128 | memcached_octets rx:DERIVE:0:U, tx:DERIVE:0:U
129 | memcached_ops value:DERIVE:0:U
130 | memory value:GAUGE:0:281474976710656
131 | memory_lua value:GAUGE:0:281474976710656
132 | multimeter value:GAUGE:U:U
133 | mutex_operations value:DERIVE:0:U
134 | mysql_commands value:DERIVE:0:U
135 | mysql_handler value:DERIVE:0:U
136 | mysql_locks value:DERIVE:0:U
137 | mysql_log_position value:DERIVE:0:U
138 | mysql_octets rx:DERIVE:0:U, tx:DERIVE:0:U
139 | mysql_bpool_pages value:GAUGE:0:U
140 | mysql_bpool_bytes value:GAUGE:0:U
141 | mysql_bpool_counters value:DERIVE:0:U
142 | mysql_innodb_data value:DERIVE:0:U
143 | mysql_innodb_dblwr value:DERIVE:0:U
144 | mysql_innodb_log value:DERIVE:0:U
145 | mysql_innodb_pages value:DERIVE:0:U
146 | mysql_innodb_row_lock value:DERIVE:0:U
147 | mysql_innodb_rows value:DERIVE:0:U
148 | mysql_select value:DERIVE:0:U
149 | mysql_sort value:DERIVE:0:U
150 | nfs_procedure value:DERIVE:0:U
151 | nginx_connections value:GAUGE:0:U
152 | nginx_requests value:DERIVE:0:U
153 | node_octets rx:DERIVE:0:U, tx:DERIVE:0:U
154 | node_rssi value:GAUGE:0:255
155 | node_stat value:DERIVE:0:U
156 | node_tx_rate value:GAUGE:0:127
157 | objects value:GAUGE:0:U
158 | operations value:DERIVE:0:U
159 | packets value:DERIVE:0:U
160 | pending_operations value:GAUGE:0:U
161 | percent value:GAUGE:0:100.1
162 | percent_bytes value:GAUGE:0:100.1
163 | percent_inodes value:GAUGE:0:100.1
164 | pf_counters value:DERIVE:0:U
165 | pf_limits value:DERIVE:0:U
166 | pf_source value:DERIVE:0:U
167 | pf_states value:GAUGE:0:U
168 | pf_state value:DERIVE:0:U
169 | pg_blks value:DERIVE:0:U
170 | pg_db_size value:GAUGE:0:U
171 | pg_n_tup_c value:DERIVE:0:U
172 | pg_n_tup_g value:GAUGE:0:U
173 | pg_numbackends value:GAUGE:0:U
174 | pg_scan value:DERIVE:0:U
175 | pg_xact value:DERIVE:0:U
176 | ping_droprate value:GAUGE:0:100
177 | ping_stddev value:GAUGE:0:65535
178 | ping value:GAUGE:0:65535
179 | players value:GAUGE:0:1000000
180 | power value:GAUGE:0:U
181 | pressure value:GAUGE:0:U
182 | protocol_counter value:DERIVE:0:U
183 | ps_code value:GAUGE:0:9223372036854775807
184 | ps_count processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
185 | ps_cputime user:DERIVE:0:U, syst:DERIVE:0:U
186 | ps_data value:GAUGE:0:9223372036854775807
187 | ps_disk_octets read:DERIVE:0:U, write:DERIVE:0:U
188 | ps_disk_ops read:DERIVE:0:U, write:DERIVE:0:U
189 | ps_pagefaults minflt:DERIVE:0:U, majflt:DERIVE:0:U
190 | ps_rss value:GAUGE:0:9223372036854775807
191 | ps_stacksize value:GAUGE:0:9223372036854775807
192 | ps_state value:GAUGE:0:65535
193 | ps_vm value:GAUGE:0:9223372036854775807
194 | pubsub value:GAUGE:0:U
195 | queue_length value:GAUGE:0:U
196 | records value:GAUGE:0:U
197 | requests value:GAUGE:0:U
198 | response_time value:GAUGE:0:U
199 | response_code value:GAUGE:0:U
200 | route_etx value:GAUGE:0:U
201 | route_metric value:GAUGE:0:U
202 | routes value:GAUGE:0:U
203 | segments value:GAUGE:0:65535
204 | serial_octets rx:DERIVE:0:U, tx:DERIVE:0:U
205 | signal_noise value:GAUGE:U:0
206 | signal_power value:GAUGE:U:0
207 | signal_quality value:GAUGE:0:U
208 | smart_poweron value:GAUGE:0:U
209 | smart_powercycles value:GAUGE:0:U
210 | smart_badsectors value:GAUGE:0:U
211 | smart_temperature value:GAUGE:-300:300
212 | smart_attribute current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
213 | snr value:GAUGE:0:U
214 | spam_check value:GAUGE:0:U
215 | spam_score value:GAUGE:U:U
216 | spl value:GAUGE:U:U
217 | swap_io value:DERIVE:0:U
218 | swap value:GAUGE:0:1099511627776
219 | tcp_connections value:GAUGE:0:4294967295
220 | temperature value:GAUGE:U:U
221 | threads value:GAUGE:0:U
222 | time_dispersion value:GAUGE:-1000000:1000000
223 | timeleft value:GAUGE:0:U
224 | time_offset value:GAUGE:-1000000:1000000
225 | total_bytes value:DERIVE:0:U
226 | total_connections value:DERIVE:0:U
227 | total_objects value:DERIVE:0:U
228 | total_operations value:DERIVE:0:U
229 | total_requests value:DERIVE:0:U
230 | total_sessions value:DERIVE:0:U
231 | total_threads value:DERIVE:0:U
232 | total_time_in_ms value:DERIVE:0:U
233 | total_values value:DERIVE:0:U
234 | uptime value:GAUGE:0:4294967295
235 | users value:GAUGE:0:65535
236 | vcl value:GAUGE:0:65535
237 | vcpu value:GAUGE:0:U
238 | virt_cpu_total value:DERIVE:0:U
239 | virt_vcpu value:DERIVE:0:U
240 | vmpage_action value:DERIVE:0:U
241 | vmpage_faults minflt:DERIVE:0:U, majflt:DERIVE:0:U
242 | vmpage_io in:DERIVE:0:U, out:DERIVE:0:U
243 | vmpage_number value:GAUGE:0:4294967295
244 | volatile_changes value:GAUGE:0:U
245 | voltage_threshold value:GAUGE:U:U, threshold:GAUGE:U:U
246 | voltage value:GAUGE:U:U
247 | vs_memory value:GAUGE:0:9223372036854775807
248 | vs_processes value:GAUGE:0:65535
249 | vs_threads value:GAUGE:0:65535
250 |
251 | #
252 | # Legacy types
253 | # (required for the v5 upgrade target)
254 | #
255 | arc_counts demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
256 | arc_l2_bytes read:COUNTER:0:U, write:COUNTER:0:U
257 | arc_l2_size value:GAUGE:0:U
258 | arc_ratio value:GAUGE:0:U
259 | arc_size current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
260 | mysql_qcache hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
261 | mysql_threads running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
262 |
--------------------------------------------------------------------------------