Class: DefaultHandlerWrapper

Inherits:
WEEL::HandlerWrapperBase
  • Object
show all
Defined in:
lib/cpee-handlerwrapper-opcua.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(arguments, position = nil, continue = nil) ⇒ DefaultHandlerWrapper

}}}



41
42
43
44
45
46
47
48
# File 'lib/cpee-handlerwrapper-opcua.rb', line 41

def initialize(arguments,position=nil,continue=nil) # {{{
  @controller = arguments[0]
  @handler_continue = continue
  @handler_position = position
  @handler_passthrough = nil
  @handler_returnValue = nil
  @label = ''
end

Class Method Details

.inform_handlerwrapper_error(arguments, err) ⇒ Object

}}}



28
29
30
31
# File 'lib/cpee-handlerwrapper-opcua.rb', line 28

def self::inform_handlerwrapper_error(arguments,err) # {{{
  controller = arguments[0]
  controller.notify("handlerwrapper/error", :instance => controller.instance, :instance_uuid => controller.uuid, :message => err.message, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
end

.inform_position_change(arguments, ipc = {}) ⇒ Object

}}}



32
33
34
35
36
37
38
39
# File 'lib/cpee-handlerwrapper-opcua.rb', line 32

def self::inform_position_change(arguments,ipc={}) # {{{
  controller = arguments[0]
  controller.serialize_positions!
  ipc[:instance] = controller.instance
  ipc[:instance_uuid] = controller.uuid
  ipc[:timestamp] = Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z")
  controller.notify("position/change", ipc)
end

.inform_state_change(arguments, newstate) ⇒ Object

{{{



18
19
20
21
22
23
# File 'lib/cpee-handlerwrapper-opcua.rb', line 18

def self::inform_state_change(arguments,newstate) # {{{
  controller = arguments[0]
controller.serialize_state!
controller.notify("state/change", :instance => controller.instance, :instance_uuid => controller.uuid, :state => newstate, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
controller.finalize_if_finished
end

.inform_syntax_error(arguments, err, code) ⇒ Object

}}}



24
25
26
27
# File 'lib/cpee-handlerwrapper-opcua.rb', line 24

def self::inform_syntax_error(arguments,err,code)# {{{
  controller = arguments[0]
  controller.notify("description/error", :instance => controller.instance, :instance_uuid => controller.uuid, :message => err.message, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
end

Instance Method Details

#activity_handle(passthrough, parameters) ⇒ Object

{{{



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/cpee-handlerwrapper-opcua.rb', line 60

def activity_handle(passthrough, parameters) # {{{
  raise "Wrong endpoint" if @handler_endpoint.nil? || @handler_endpoint.empty?
  @label = parameters[:label]
  @sensors = parameters[:sensors]
  @aggregators = parameters[:aggregators]
  @costs = parameters[:costs]
  @controller.notify("activity/calling", :instance => @controller.instance, :instance_uuid => @controller.uuid, :label => @label, :instance_name => @controller.info, :activity => @handler_position, :passthrough => passthrough, :endpoint => @handler_endpoint, :parameters => parameters, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
  if passthrough.to_s.empty?
    if @handler_endpoint.start_with?('opc.tcp')
      if @handler_endpoint =~ /^opc\.tcp-read:\/\/([^\/]+)\/(\d+)\/(.+)/
        nid = $3 == $3.to_i.to_s ? $3.to_i : $3
        ns  = $2
        url = 'opc.tcp://' + $1
        client = OPCUA::Client.new(url)
        if (node = client.get ns.to_i, nid)
          result = node.value
        else
          raise 'invalid nodeid'
        end
        client.disconnect
        callback [Riddl::Parameter::Simple.new('value',result)], {}
      elsif @handler_endpoint =~ /^opc\.tcp-write:\/\/([^\/]+)\/(\d+)\/([^\?]+)(\?value=(.*))?/
        nid = $3 == $3.to_i.to_s ? $3.to_i : $3
        ns  = $2
        par = $5
        url = 'opc.tcp://' + $1
        client = OPCUA::Client.new(url)
        if (node = client.get ns.to_i, nid)
          (parameters[:arguments] || [(:name => 'value', :value => par)] || []).each do |ele|
            what = CPEE::ValueHelper::parse_extended(ele.value)
            node.value = what
            result = what
          end
        else
          raise 'invalid nodeid'
        end
        client.disconnect
        callback [Riddl::Parameter::Simple.new('value',result)], {}
      elsif @handler_endpoint =~ /^opc\.tcp-execute:\/\/([^\/]+)\/(\d+)\/([^\?]+)(\?value=(.*))?/
        nid = $3 == $3.to_i.to_s ? $3.to_i : $3
        ns  = $2
        par = $5
        url = 'opc.tcp://' + $1
        client = OPCUA::Client.new(url)
        if (node = client.get ns.to_i, nid)
          params = []
          (parameters[:arguments] || []).each do |ele|
            what = CPEE::ValueHelper::parse_extended(ele.value)
            params << what
          end
          result = node.call *params
        else
          raise 'invalid nodeid'
        end
        client.disconnect
        callback [Riddl::Parameter::Simple.new('value',result)], {}
      end
    else
      params = []
      callback = Digest::MD5.hexdigest(Kernel::rand().to_s)
      (parameters[:arguments] || []).each do |s|
        if s.respond_to?(:mimetype)
          params <<  Riddl::Parameter::Complex.new(s.name.to_s,v.mimetype,v.value)
        else
          if s.name.to_s =~ /__$/
            params <<  Riddl::Parameter::Simple.new(s.name.to_s.chop.chop,CPEE::ValueHelper::generate(s.value),:query)
          else
            params <<  Riddl::Parameter::Simple.new(s.name.to_s,CPEE::ValueHelper::generate(s.value))
          end
        end
      end

      params << Riddl::Header.new("CPEE-BASE",@controller.base_url)
      params << Riddl::Header.new("CPEE-INSTANCE",@controller.instance)
      params << Riddl::Header.new("CPEE-INSTANCE-URL",@controller.instance_url)
      params << Riddl::Header.new("CPEE-INSTANCE-UUID",@controller.uuid)
      params << Riddl::Header.new("CPEE-CALLBACK",@controller.instance_url + '/callbacks/' + callback)
      params << Riddl::Header.new("CPEE-CALLBACK-ID",callback)
      params << Riddl::Header.new("CPEE-ACTIVITY",@handler_position)
      params << Riddl::Header.new("CPEE-LABEL",parameters[:label]||'')
      @controller.attributes.each do |key,value|
        params << Riddl::Header.new("CPEE-ATTR-#{key.to_s.gsub(/_/,'-')}",value)
      end

      tendpoint = @handler_endpoint.sub(/^http(s)?-(get|put|post|delete):/,'http\\1:')
      type = $2 || parameters[:method] || 'post'

      client = Riddl::Client.new(tendpoint)

      @controller.callbacks[callback] = CPEE::Callback.new("callback activity: #{@handler_position}",self,:callback,nil,nil,:http)
      @handler_passthrough = callback

      status, result, headers = client.request type => params
      if status < 200 || status >= 300
        callback([ Riddl::Parameter::Complex.new('error','application/json',StringIO.new(JSON::generate({ 'status' => status, 'error' => result[0].value.read }))) ], 'CPEE_SALVAGE' => true)
      else
        if headers['CPEE_INSTANTIATION']
          @controller.notify("task/instantiation", :instance => @controller.instance, :label => @label, :instance_name => @controller.info, :instance_uuid => @controller.uuid, :activity => @handler_position, :endpoint => @handler_endpoint, :received => CPEE::ValueHelper.parse(headers['CPEE_INSTANTIATION']), :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
        end
        if headers['CPEE_CALLBACK'] && headers['CPEE_CALLBACK'] == 'true' && result.any?
          headers['CPEE_UPDATE'] = true
          callback result, headers
        elsif headers['CPEE_CALLBACK'] && headers['CPEE_CALLBACK'] == 'true' && result.empty?
          # do nothing, later on things will happend
        else
          callback result
        end
      end
    end
  else
    @controller.callbacks[passthrough] = CPEE::Callback.new("callback activity: #{@handler_position}",self,:callback,nil,nil,:http)
    @handler_passthrough = passthrough
  end
end

#activity_manipulate_handle(parameters) ⇒ Object

}}}



174
175
176
# File 'lib/cpee-handlerwrapper-opcua.rb', line 174

def activity_manipulate_handle(parameters) #{{{
  @label = parameters[:label]
end

#activity_no_longer_necessaryObject

}}}



191
192
193
# File 'lib/cpee-handlerwrapper-opcua.rb', line 191

def activity_no_longer_necessary # {{{
  true
end

#activity_passthrough_valueObject

}}}



187
188
189
# File 'lib/cpee-handlerwrapper-opcua.rb', line 187

def activity_passthrough_value # {{{
  @handler_passthrough
end

#activity_result_valueObject

}}}



178
179
180
# File 'lib/cpee-handlerwrapper-opcua.rb', line 178

def activity_result_value # {{{
  @handler_returnValue
end

#activity_stopObject

}}}



182
183
184
185
186
# File 'lib/cpee-handlerwrapper-opcua.rb', line 182

def activity_stop # {{{
  unless @handler_passthrough.nil?
    @controller.callbacks.delete(@handler_passthrough)
  end
end

#callback(result = nil, options = {}) ⇒ Object



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/cpee-handlerwrapper-opcua.rb', line 283

def callback(result=nil,options={})
  @controller.notify("activity/receiving", :instance => @controller.instance, :label => @label, :instance_name => @controller.info, :instance_uuid => @controller.uuid, :activity => @handler_position, :endpoint => @handler_endpoint, :received => structurize_result(result), :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated, :sensors => @sensors, :aggregators => @aggregators, :costs => @costs)
  result = simplify_result(result)
  if options['CPEE_UPDATE']
    @handler_returnValue = result
    if options['CPEE_UPDATE_STATUS']
      @controller.notify("activity/status", :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :endpoint => @handler_endpoint, :status => options['CPEE_UPDATE_STATUS'], :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
    end
    @handler_continue.continue WEEL::Signal::Again
  else
    @controller.callbacks.delete(@handler_passthrough)
    @handler_returnValue = result
    @handler_passthrough = nil
    if options['CPEE_SALVAGE']
      @handler_continue.continue WEEL::Signal::Salvage
    else
      @handler_continue.continue
    end
  end
end

#inform_activity_doneObject

}}}



195
196
197
# File 'lib/cpee-handlerwrapper-opcua.rb', line 195

def inform_activity_done # {{{
  @controller.notify("activity/done", :endpoint => @handler_endpoint, :instance => @controller.instance, :label => @label, :instance_name => @controller.info, :instance_uuid => @controller.uuid, :activity => @handler_position, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
end

#inform_activity_failed(err) ⇒ Object

}}}



201
202
203
204
205
# File 'lib/cpee-handlerwrapper-opcua.rb', line 201

def inform_activity_failed(err) # {{{
  puts err.message
  puts err.backtrace
  @controller.notify("activity/failed", :endpoint => @handler_endpoint, :label => @label, :instance_name => @controller.info, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :message => err.message, :line => err.backtrace[0].match(/(.*?):(\d+):/)[2], :where => err.backtrace[0].match(/(.*?):(\d+):/)[1], :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
end

#inform_activity_manipulateObject

}}}



198
199
200
# File 'lib/cpee-handlerwrapper-opcua.rb', line 198

def inform_activity_manipulate # {{{
  @controller.notify("activity/manipulating", :endpoint => @handler_endpoint, :instance => @controller.instance, :label => @label, :instance_name => @controller.info, :instance_uuid => @controller.uuid, :activity => @handler_position, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
end

#inform_manipulate_change(status, changed_dataelements, changed_endpoints, dataelements, endpoints) ⇒ Object

}}}



206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/cpee-handlerwrapper-opcua.rb', line 206

def inform_manipulate_change(status,changed_dataelements,changed_endpoints,dataelements,endpoints) # {{{
  unless status.nil?
    @controller.serialize_status!
    @controller.notify("status/change", :endpoint => @handler_endpoint, :label => @label, :instance_name => @controller.info, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :id => status.id, :message => status.message, :attributes => @controller.attributes_translated, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
  end
  unless changed_dataelements.nil?
    @controller.serialize_dataelements!
    @controller.notify("dataelements/change", :endpoint => @handler_endpoint, :label => @label, :instance_name => @controller.info, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :changed => changed_dataelements, :values => dataelements, :attributes => @controller.attributes_translated, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
  end
  unless changed_endpoints.nil?
    @controller.serialize_endpoints!
    @controller.notify("endpoints/change", :endpoint => @handler_endpoint, :label => @label, :instance_name => @controller.info, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :changed => changed_endpoints, :values => endpoints, :attributes => @controller.attributes_translated, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
  end
end

#prepare(readonly, endpoints, parameters) ⇒ Object

}}}



50
51
52
53
54
55
56
57
58
# File 'lib/cpee-handlerwrapper-opcua.rb', line 50

def prepare(readonly, endpoints, parameters)
  @handler_endpoint = endpoints.is_a?(Array) ? endpoints.map{ |ep| readonly.endpoints[ep] }.compact : readonly.endpoints[endpoints]
  parameters[:arguments]&.each do |ele|
    if ele.value.is_a?(Proc)
      ele.value = readonly.instance_exec &ele.value
    end
  end
  parameters
end

#simplify_result(result) ⇒ Object

}}}



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/cpee-handlerwrapper-opcua.rb', line 228

def simplify_result(result)
  if result.length == 1
    if result[0].is_a? Riddl::Parameter::Simple
      result = result[0].value
    elsif result[0].is_a? Riddl::Parameter::Complex
      if result[0].mimetype == 'application/json'
        result = JSON::parse(result[0].value.read) rescue nil
      elsif result[0].mimetype == 'application/xml' || result[0].mimetype == 'text/xml'
        result = XML::Smart::string(result[0].value.read) rescue nil
      elsif result[0].mimetype == 'text/plain'
        result = result[0].value.read
        if result.start_with?("<?xml version=")
          result = XML::Smart::string(result)
        else
          result = result.to_f if result == result.to_f.to_s
          result = result.to_i if result == result.to_i.to_s
        end
      elsif result[0].mimetype == 'text/html'
        result = result[0].value.read
        result = result.to_f if result == result.to_f.to_s
        result = result.to_i if result == result.to_i.to_s
      else
        result = result[0]
      end
    end
  end
  result
end

#simulate(type, nesting, tid, parent, parameters = {}) ⇒ Object

{{{



310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/cpee-handlerwrapper-opcua.rb', line 310

def simulate(type,nesting,tid,parent,parameters={}) #{{{
  pp "#{type} - #{nesting} - #{tid} - #{parent} - #{parameters.inspect}"

  @controller.call_vote("simulating/step",
    :endpoint => @handler_endpoint,
    :instance => @controller.instance,
    :instance_uuid => @controller.uuid,
    :activity => tid,
    :type => type,
    :nesting => nesting,
    :parent => parent,
    :parameters => parameters
  )
end

#structurize_result(result) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/cpee-handlerwrapper-opcua.rb', line 257

def structurize_result(result)
  result.map do |r|
    if r.is_a? Riddl::Parameter::Simple
      { 'name' => r.name, 'data' => r.value }
    elsif r.is_a? Riddl::Parameter::Complex
      res = if r.mimetype == 'application/json'
        JSON::parse(r.value.read) rescue nil
      elsif r.mimetype == 'text/plain' || r.mimetype == 'text/html'
        ttt = r.value.read
        ttt = ttt.to_f if ttt == ttt.to_f.to_s
        ttt = ttt.to_i if ttt == ttt.to_i.to_s
        ttt
      else
        r.value.read
      end
      tmp = {
        'name' => r.name == '' ? 'result' : r.name,
        'mimetype' => r.mimetype,
        'data' => res
      }
      r.value.rewind
      tmp
    end
  end
end

#test_condition(mr, code) ⇒ Object



304
305
306
307
308
# File 'lib/cpee-handlerwrapper-opcua.rb', line 304

def test_condition(mr,code)
  res = mr.instance_eval(code)
  @controller.notify("condition/eval", :instance => @controller.instance, :instance_uuid => @controller.uuid, :code => code, :condition => (res ? "true" : "false"), :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"), :attributes => @controller.attributes_translated)
  res
end

#vote_sync_afterObject

}}}



221
222
223
# File 'lib/cpee-handlerwrapper-opcua.rb', line 221

def vote_sync_after # {{{
  @controller.call_vote("activity/syncing_after", :endpoint => @handler_endpoint, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
end

#vote_sync_before(parameters = nil) ⇒ Object

}}}



224
225
226
# File 'lib/cpee-handlerwrapper-opcua.rb', line 224

def vote_sync_before(parameters=nil) # {{{
  @controller.call_vote("activity/syncing_before", :endpoint => @handler_endpoint, :instance => @controller.instance, :instance_uuid => @controller.uuid, :activity => @handler_position, :parameters => parameters, :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
end