ropc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db471e5edce66fb370612a4889ea5e281d3e7a36
4
+ data.tar.gz: 29a579ba8ebf66b889b047593ece02474aad37b6
5
+ SHA512:
6
+ metadata.gz: 1615ac3edfebd1c31746a71c899c00ee0ce074db8fc044c8c672b065a64f55f35384a745f66803afc6e1ee727b1a7c5a801636d3ab9e029bef2ef00b07dc5e4b
7
+ data.tar.gz: 24cdcad9e93a717de7d45f61ee54cc2ee44fc0caac6f4e66d9c158056ebc69d9cf0aa64f2b9a1eb4a9236522ca2167d6334bf1eea59fefbbba364d2099135418
@@ -0,0 +1,4 @@
1
+ require "ropc/client"
2
+
3
+ module ROPC
4
+ end
@@ -0,0 +1,158 @@
1
+ require 'win32ole'
2
+ require 'logger'
3
+
4
+ module ROPC
5
+
6
+ module OPCDataSource
7
+ OPCCache = 1
8
+ OPCDevice = 2
9
+ end
10
+
11
+ module OPCQuality
12
+ OPCQualityMask = 192
13
+ OPCQualityBad = 0
14
+ OPCQualityUncertain = 64
15
+ OPCQualityGood = 192
16
+ OPCQuality = {192 => "Good", 64 => "Uncertain", 0 => "Bad"}
17
+ end
18
+
19
+ class Client
20
+ def initialize(tags: [], server: nil, node: nil, logger: Logger.new(STDOUT), level: "WARN")
21
+ @tags = tags
22
+
23
+ @server = server
24
+ @server ||= ENV["ROPC_SERVER"]
25
+ fail "Environment variable ROPC_SERVER not set or not server given." if @server.nil?
26
+
27
+ @node = node
28
+ @node ||= ENV["ROPC_NODE"]
29
+ fail "Environment variable ROPC_NODE not set or not node given." if @node.nil?
30
+
31
+ @logger = logger
32
+ @logger.level = level
33
+
34
+ establish_connection
35
+ end
36
+
37
+ def establish_connection
38
+ begin
39
+ @opc_automation = WIN32OLE.new 'OPC.Automation.1'
40
+ @logger.info("OPC.Automation.1 created.")
41
+ rescue => err
42
+ @logger.fatal("Cannot create win32ole OPC Automation object")
43
+ @logger.fatal(err)
44
+ exit
45
+ end
46
+
47
+ begin
48
+ @opc_automation.Connect(@server,@node)
49
+ @logger.info("Connected to OPC Server.")
50
+ @logger.info("OPC Server StartTime: #{@opc_automation.invoke("StartTime")}") # returns Time Class
51
+ @logger.info("OPC Server CurrentTime: #{@opc_automation.invoke("CurrentTime")}") # returns Time Class
52
+ rescue => err
53
+ @logger.fatal("Cannot connect to OPC #{@server} on #{@node}")
54
+ @logger.fatal(err)
55
+ exit
56
+ end
57
+
58
+ begin
59
+ @opc_group = @opc_automation.OPCGroups.add "OPCGroup"
60
+ @opc_items = @opc_group.OPCItems
61
+ #opc_group.UpdateRate = 1000
62
+ @logger.info("Group UpdateRate: #{@opc_group.UpdateRate}")
63
+ @logger.info("OPC Group IsSubscribed: #{@opc_group.IsSubscribed}")
64
+ @logger.info("OPC Group IsActive: #{@opc_group.IsActive}")
65
+ rescue => err
66
+ @logger.fatal("Could not add OPCGroup")
67
+ @logger.fatal(err)
68
+ exit
69
+ end
70
+
71
+ @items = {}
72
+
73
+ if @tags.respond_to?("each")
74
+ @tags.each {|tag| self.add tag }
75
+ else
76
+ self.add @tags
77
+ end
78
+
79
+ @logger.info("Number of OPCGroup in OPCGroups: #{@opc_automation.OPCGroups.Count}")
80
+ @logger.info("Number of OPCItem in OPCitems: #{@opc_items.Count}")
81
+
82
+ end
83
+
84
+ def add(tag)
85
+ begin
86
+ @items[tag] = @opc_items.AddItem(tag, 1)
87
+ rescue
88
+ @logger.warn("Failed to add this tag: #{tag}")
89
+ end
90
+ end
91
+
92
+ def remove(tag)
93
+ @items.delete(tag) if @items.has_key?(tag)
94
+ end
95
+
96
+ def read_tag(tag)
97
+ if @items.has_key?(tag)
98
+ opcitem = @items[tag]
99
+ begin
100
+ opcitem.read OPCDataSource::OPCCache # 1: reading from cache, 2: reading from device
101
+ rescue
102
+ @logger.warn("Failed to read opc tag: #{tag}")
103
+ cleanup
104
+ establish_connection
105
+ return tags
106
+ end
107
+ ts = opcitem.TimeStamp + opcitem.TimeStamp.gmtoff
108
+ @logger.info("Read #{opcitem.ItemID} Value: #{extract_value(opcitem.Value)}, Quality: #{OPCQuality::OPCQuality[opcitem.Quality]}, Time: #{ts}")
109
+ return {tag: opcitem.ItemID, value: extract_value(opcitem.Value), quality: OPCQuality::OPCQuality[opcitem.Quality], timestamp: ts}
110
+ else
111
+ return {}
112
+ end
113
+ end
114
+
115
+ def read
116
+ read_all
117
+ end
118
+
119
+ def read_all
120
+ tags = []
121
+ @items.keys.each do |tag|
122
+ tags << read_tag(tag)
123
+ end
124
+ return tags
125
+ end
126
+
127
+ def cleanup
128
+ @opc_groups.RemoveAll if @opc_groups
129
+ @opc_automation.Disconnect if @opc_automation
130
+ end
131
+
132
+ def extract_value str
133
+ begin
134
+ if str.kind_of?(FalseClass)
135
+ return 0.0
136
+ elsif str.kind_of?(TrueClass)
137
+ return 1.0
138
+ elsif Float(str)
139
+ return str
140
+ elsif Int(str)
141
+ return str
142
+ end
143
+ rescue
144
+ @logger.warn("failed to extract value: #{str}; returning 0.0")
145
+ return 0.0
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ def self.read_tags(tags)
152
+ opc = ROPC::Client.new(tags: tags, level: "WARN")
153
+ ret = opc.read
154
+ opc.cleanup
155
+ ret
156
+ end
157
+
158
+ end
@@ -0,0 +1,3 @@
1
+ module ROPC
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ropc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Koni Marti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: win32ole-pp
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ description: Read the tags from an OPC server using Win32 OLE for monitoring and data
28
+ analysis.
29
+ email: ''
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/ropc.rb
35
+ - lib/ropc/client.rb
36
+ - lib/ropc/version.rb
37
+ homepage: https://github.com/konimarti
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.5.2
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Minimal, read-only OPC client
61
+ test_files: []