# # Copyright (c) 2018 ITO SOFT DESIGN Inc. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. <<-DOC Here is a sample configuration. Puts your configuration to config/plugins/slack.yml device_comments: - M0: エラー0 - M1: エラー1 - M2: エラー2 - M10: エラー10 events: - webhook_url: your_web_hook_url trigger: type: raise_and_fall value_type: bool format: raise: __device_comment__ が発生しました。 fall: __device_comment__ が解除になりました。 devices: M0-M2,M10 DOC require 'net/https' module LadderDrive module Emulator class SlackPlugin < Plugin def initialize plc super #plc return if disabled? @values = {} @times = {} @worker_queue = Queue.new # collect comments @comments = {} config[:device_comments].each do |k, v| d = plc.device_by_name(k) @comments[d.name] = v if d end if config[:device_comments] setup end def run_cycle plc return if disabled? return unless config[:events] config[:events].each do |event| next unless event[:devices] next unless event[:webhook_url] begin # gether values devices = event[:devices].split(",").map{|e| e.split("-")}.map do |devs| devs = devs.map{|d| plc.device_by_name d.strip} d1 = devs.first d2 = devs.last [d2.number - d1.number + 1, 1].max.times.inject([]){|a, i| a << d1; d1 += 1; a} end.flatten interval_triggered = false now = Time.now devices.each do |device| triggered = false v = nil case event[:trigger][:type] when "interval" t = @times[event.object_id] || now triggered = t <= now if triggered interval_triggered = true t += event[:trigger][:interval] || 300 @times[event.object_id] = t end v = device.send event[:value_type] || :value, event[:trigger][:text_length] || 8 else v = device.send event[:value_type] || :value, event[:text_length] || 8 unless @values[device.name] == v @values[device.name] = v case event[:trigger][:type] when "raise" triggered = !!v when "fall" triggered = !v else triggered = true end end end next unless triggered || interval_triggered @worker_queue.push event:event, device_name:device.name, value:v, time: now end rescue => e p e puts $! puts $@ end end end private def setup Thread.start { thread_proc } end def thread_proc while arg = @worker_queue.pop begin event = arg[:event] uri = URI.parse(event[:webhook_url]) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE req = Net::HTTP::Post.new(uri.path) req["Content-Type"] = "application/json" format = event[:format] || "__comment__ occured at __time__" case format when Hash case arg[:value] when false, nil, 0 format = format[:fall] else format = format[:interval] || format[:raise] end end device_name = arg[:device_name] comment = @comments[device_name] || device_name value = arg[:value].to_s time = arg[:time].iso8601 payload = {text:format.gsub(/__device_comment__/, comment).gsub(/__value__/, value).gsub(/__time__/, time).gsub(/__device_name__/, device_name) } req.body = payload.to_json http.request(req) rescue => e # TODO: Resend if it fails. p e end end end end end end def plugin_slack_init plc @slack_plugin = LadderDrive::Emulator::SlackPlugin.new plc end def plugin_slack_exec plc @slack_plugin.run_cycle plc end