ropc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []