ladder_drive 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bd6ed103f79bb7083b861a6464f83c668dcbb5c14808d3e702cc5a4206c9c6b
4
- data.tar.gz: e7c1f12717307d569f203f8c054413cf97c69e66c832247846f675f0405b9d4f
3
+ metadata.gz: 89e93e6ad6630128bf1a0996dd9de4c399e246acbb1c92615eb92fc83f0ec206
4
+ data.tar.gz: 5cb779d24babb0d23284276765c79e6edb27bbf1901d946eceb1a88a7b1cca99
5
5
  SHA512:
6
- metadata.gz: f6b4b164bbeba262f1c57334955ea09e423662b6e63a1b502f953211df9640645731a3970316e376f4545f046a75db2c3c5a0d3705d16725dd033ce3156e3483
7
- data.tar.gz: a0525951ac3a7d82a1b767806a0b59e2c5a7f95b55621e7ab7fd456689659d3f537f5c90f2baa3cc5cd618c536c66510ccb97cc2bc29b751a5b74a0e2b314518
6
+ metadata.gz: ea1e43769ad3deb7845a208c501906b2db81f04c9223ce7152f35d663ff5529cb44f2f8ebd0920f37443cb963715280bf8a69ac7efab3319504d218adc721b23
7
+ data.tar.gz: 59dae9cd3d5080ee2d7ce616951d05e1cf387c2e7920b8f3a2a2ce0411492ed662ae5da91517c69f99c9969fd3f82256049839e89f135bc5de99a89e59647091
data/Gemfile.lock CHANGED
@@ -4,7 +4,7 @@ PATH
4
4
  ladder_drive (0.6.0)
5
5
  activesupport (~> 4.2, >= 4.2.7)
6
6
  ffi (~> 1.9.24, >= 1.9.24)
7
- pi_piper (>= 2.0.0)
7
+ pi_piper (~> 2.0, >= 2.0.0)
8
8
  thor (~> 0)
9
9
 
10
10
  GEM
@@ -110,16 +110,16 @@ PLATFORMS
110
110
  ruby
111
111
 
112
112
  DEPENDENCIES
113
- activesupport
113
+ activesupport (~> 4.2, >= 4.2.7)
114
114
  bundler (~> 1.11)
115
- ffi
115
+ ffi (~> 1.9.24)
116
116
  google_drive
117
117
  ladder_drive!
118
- pi_piper
118
+ pi_piper (>= 2.0.0)
119
119
  rake (~> 10.0)
120
120
  ruby-trello
121
121
  serialport
122
122
  test-unit
123
123
 
124
124
  BUNDLED WITH
125
- 1.16.6
125
+ 1.17.2
data/README_jp.md CHANGED
@@ -184,12 +184,6 @@ OUT M1
184
184
  <!-- [![](http://img.youtube.com/vi/qGbicGLB7Gs/0.jpg)](https://youtu.be/qGbicGLB7Gs) -->
185
185
 
186
186
 
187
- ```warning: constant ::Fixnum is deprecated``` の表示が出る場合は次の様にしてみてください。
188
-
189
- ```sh
190
- $ RUBYOPT="-W0" rake
191
- ```
192
-
193
187
  ## Raspberry Pi
194
188
 
195
189
  Raspberry Pi上で動作させることもできます。
data/ladder_drive.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.7'
19
19
  spec.add_runtime_dependency 'ffi', '~> 1.9.24', '>= 1.9.24'
20
20
  spec.add_runtime_dependency 'pi_piper', '~> 2.0', '>= 2.0.0'
21
+ spec.add_runtime_dependency 'serialport'
21
22
 
22
23
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
24
  spec.bindir = "exe"
@@ -33,7 +33,7 @@ module LadderDrive
33
33
  def create(name)
34
34
  if File.exist? name
35
35
  puts "ERROR: #{name} already exists."
36
- exit -1
36
+ exit(-1)
37
37
  end
38
38
 
39
39
  # copy from template file
@@ -58,7 +58,7 @@ module LadderDrive
58
58
  path = File.join(plugins_path, "#{name}_plugin.rb")
59
59
  if File.exist? path
60
60
  mkdir_p "plugins"
61
- cp path, "plugins/#{name}_plugins.rb"
61
+ cp path, "plugins/#{name}_plugin.rb"
62
62
  end
63
63
  end
64
64
 
@@ -30,7 +30,6 @@ module LadderDrive
30
30
  include Singleton
31
31
 
32
32
  def run
33
- l = true
34
33
  trap(:INT) { puts "\n> " }
35
34
 
36
35
  display_title
@@ -54,7 +54,7 @@ module LadderDrive
54
54
  @suffix = nil
55
55
  @value = 0
56
56
  case a
57
- when Fixnum
57
+ when Integer
58
58
  @suffix = ESC_SUFFIXES[a]
59
59
  @number = b
60
60
  when String, Symbol
@@ -127,7 +127,7 @@ module LadderDrive
127
127
 
128
128
  def bool
129
129
  case @value
130
- when Fixnum
130
+ when Integer
131
131
  @value != 0
132
132
  else
133
133
  !!@value
@@ -29,6 +29,7 @@ module Keyence
29
29
 
30
30
  def initialize options={}
31
31
  super
32
+ @socket = nil
32
33
  @host = options[:host] || "192.168.0.10"
33
34
  @port = options[:port] || 8501
34
35
  prepare_device_map
@@ -148,6 +149,7 @@ module Keyence
148
149
 
149
150
  def available_bits_range suffix=nil
150
151
  case suffix
152
+ # FIXME: duplicated
151
153
  when "TM"
152
154
  1..512
153
155
  when "TM"
@@ -167,13 +169,13 @@ module Keyence
167
169
 
168
170
  def available_words_range suffix=nil
169
171
  case suffix
172
+ # FIXME: duplicated
170
173
  when "TM"
171
174
  1..256
172
175
  when "TM"
173
176
  1..12
174
177
  when "T", "TC", "TS", "C", "CC", "CS"
175
178
  1..120
176
- 1..120
177
179
  when "CTH"
178
180
  1..2
179
181
  when "CTC"
@@ -51,6 +51,7 @@ module Mitsubishi
51
51
  @baudrate = 19200
52
52
  @station_no = 0
53
53
  @wait_time = 0
54
+ @comm = nil
54
55
  #prepare_device_map
55
56
  end
56
57
 
@@ -29,6 +29,7 @@ module Mitsubishi
29
29
 
30
30
  def initialize options={}
31
31
  super
32
+ @socket = nil
32
33
  @host = options[:host] || "192.168.0.10"
33
34
  @port = options[:port] || 5010
34
35
  prepare_device_map
@@ -29,13 +29,17 @@ module Protocol
29
29
 
30
30
  class Protocol
31
31
 
32
- attr_accessor :host, :port, :log_level
32
+ attr_accessor :host, :port
33
33
 
34
34
  def initialize options={}
35
35
  @logger = Logger.new(STDOUT)
36
36
  self.log_level = options[:log_level] || :info
37
37
  end
38
38
 
39
+ def log_level
40
+ @log_level
41
+ end
42
+
39
43
  def log_level= level
40
44
  @log_level = level.is_a?(String) ? level.to_sym : level
41
45
  case @log_level
@@ -31,7 +31,6 @@ module LadderDrive
31
31
 
32
32
  attr_accessor :protocol
33
33
  attr_accessor :source
34
- attr_accessor :data
35
34
 
36
35
  def initialize options={}
37
36
  @protocol = options[:protocol] if options[:protocol]
@@ -22,5 +22,5 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
24
  module LadderDrive
25
- VERSION = "0.6.0"
25
+ VERSION = "0.6.1"
26
26
  end
@@ -31,7 +31,7 @@ module Emulator
31
31
  class EmuDevice < PlcDevice
32
32
 
33
33
  attr_reader :in_value, :out_value
34
- attr_accessor :plc
34
+ attr_reader :plc
35
35
 
36
36
  def initialize a, b = nil
37
37
  super
@@ -63,6 +63,7 @@ module Emulator
63
63
  end
64
64
  @lock = Mutex.new
65
65
  @config = config
66
+ @pending_save = nil
66
67
  reset
67
68
  load_plugins
68
69
  end
@@ -341,12 +342,12 @@ module Emulator
341
342
  (SIZE_OF_BIT_STACK - 1).downto 0 do |i|
342
343
  values << stack_device(i).word
343
344
  end
344
- v = values.pop
345
+ value = values.pop
345
346
  values.each_with_index do |v, i|
346
347
  stack_device(i).word = v
347
348
  end
348
349
  stack_count_device.word -= 1
349
- v
350
+ value
350
351
  end
351
352
  # ----------------
352
353
 
@@ -85,11 +85,10 @@ class Plugin
85
85
  class << self
86
86
 
87
87
  def devices_with_plc_from_str plc, dev_str
88
- devices = dev_str.split(",").map{|e| e.split("-")}.map do |devs|
88
+ dev_str.split(",").map{|e| e.split("-")}.map do |devs|
89
89
  devs = devs.map{|d| plc.device_by_name d.strip}
90
90
  d1 = devs.first
91
91
  d2 = devs.last
92
- d = d1
93
92
  [d2.number - d1.number + 1, 1].max.times.inject([]){|a, i| a << d1; d1 += 1; a}
94
93
  end.flatten
95
94
  end
@@ -118,7 +117,7 @@ class Plugin
118
117
  end
119
118
 
120
119
  def disabled?
121
- config[:disable]
120
+ config.empty? || config[:disable]
122
121
  end
123
122
 
124
123
  def run_cycle plc
@@ -65,127 +65,154 @@ DOC
65
65
  require 'net/https'
66
66
  require 'google_drive'
67
67
 
68
- def plugin_google_drive_init plc
69
- @plugin_google_drive_config = load_plugin_config 'google_drive'
70
- return if @plugin_google_drive_config[:disable]
71
-
72
- @plugin_google_drive_values = {}
73
- @plugin_google_drive_times = {}
74
- @plugin_google_drive_worker_queue = Queue.new
75
-
76
- begin
77
- # generate config file for google drive session
78
- tmp_dir = File.expand_path "tmp"
79
- session_path = File.join(tmp_dir, "google_drive_session.json")
80
- unless File.exist? session_path
81
- mkdir_p tmp_dir
82
- conf =
83
- [:client_id, :client_secret, :refresh_token].inject({}) do |h, key|
84
- v = @plugin_google_drive_config[key]
85
- h[key] = v if v
86
- h
87
- end
88
- File.write session_path, JSON.generate(conf)
89
- end
68
+ module LadderDrive
69
+ module Emulator
90
70
 
91
- # create google drive session
92
- @plugin_google_drive_session = GoogleDrive::Session.from_config(session_path)
71
+ class GoogleDrivePlugin < Plugin
93
72
 
94
- # start worker thread
95
- Thread.start {
96
- plugin_google_drive_worker_loop
97
- }
98
- rescue => e
99
- p e
100
- @plugin_google_drive_session = nil
101
- end
102
- end
73
+ def initialize plc
74
+ super #plc
75
+ return if disabled?
103
76
 
104
- def plugin_google_drive_exec plc
105
- return if @plugin_google_drive_config[:disable]
106
- return unless @plugin_google_drive_session
77
+ @values = {}
78
+ @times = {}
79
+ @worker_queue = Queue.new
107
80
 
108
- @plugin_google_drive_config[:loggings].each do |logging|
109
81
  begin
110
- # check triggered or not
111
- triggered = false
112
- case logging[:trigger][:type]
113
- when "interval"
114
- now = Time.now
115
- t = @plugin_google_drive_times[logging.object_id] || now
116
- triggered = t <= now
117
- if triggered
118
- t += logging[:trigger][:interval] || 300
119
- @plugin_google_drive_times[logging.object_id] = t
120
- end
121
- else
122
- d = plc.device_by_name logging[:trigger][:device]
123
- v = d.send logging[:trigger][:value_type], logging[:trigger][:text_length] || 8
124
- unless @plugin_google_drive_values[logging.object_id] == v
125
- @plugin_google_drive_values[logging.object_id] = v
126
- case logging[:trigger][:type]
127
- when "raise"
128
- triggered = !!v
129
- when "fall"
130
- triggered = !v
131
- else
132
- triggered = true
82
+ # generate config file for google drive session
83
+ tmp_dir = File.expand_path "tmp"
84
+ session_path = File.join(tmp_dir, "google_drive_session.json")
85
+ unless File.exist? session_path
86
+ mkdir_p tmp_dir
87
+ conf =
88
+ [:client_id, :client_secret, :access_token, :refresh_token].inject({}) do |h, key|
89
+ v = config[key]
90
+ h[key] = v if v
91
+ h
133
92
  end
134
- end
93
+ File.write session_path, JSON.generate(conf)
135
94
  end
136
95
 
137
- next unless triggered
96
+ # create google drive session
97
+ @session = GoogleDrive::Session.from_config(session_path)
138
98
 
139
- # gether values
140
- values = logging[:devices].map do |config|
141
- d1, d2 = config[:device].split("-").map{|d| plc.device_by_name d}
142
- devices = [d1]
143
- if d2
144
- d = d1 + 1
145
- devices += [d2.number - d1.number, 0].max.times.inject([]){|a, i| a << d; d += 1; a}
146
- end
147
- devices.map{|d| d.send config[:type], config[:length] || 8}
148
- end.flatten
149
- @plugin_google_drive_worker_queue.push logging:logging, values:values, time:Time.now
99
+ # start worker thread
100
+ setup if @session
150
101
  rescue => e
151
102
  p e
103
+ @session = nil
104
+ exit(1)
152
105
  end
153
- end if @plugin_google_drive_config[:loggings]
154
- end
155
106
 
156
- def plugin_google_drive_worker_loop
157
- while arg = @plugin_google_drive_worker_queue.pop
158
- begin
159
- logging = arg[:logging]
160
- spread_sheet = @plugin_google_drive_session.spreadsheet_by_key(logging[:spread_sheet][:spread_sheet_key])
107
+ end
161
108
 
162
- # get worksheet
163
- worksheet = begin
164
- if logging[:spread_sheet][:sheet_name]
165
- spread_sheet.worksheet_by_title logging[:spread_sheet][:sheet_name]
109
+ def run_cycle plc
110
+ return if disabled?
111
+ return unless @session
112
+
113
+ config[:loggings].each do |logging|
114
+ begin
115
+ # check triggered or not
116
+ triggered = false
117
+ case logging[:trigger][:type]
118
+ when "interval"
119
+ now = Time.now
120
+ t = @times[logging.object_id] || now
121
+ triggered = t <= now
122
+ if triggered
123
+ t += logging[:trigger][:interval] || 300
124
+ @times[logging.object_id] = t
125
+ end
166
126
  else
167
- spread_sheet.worksheets[logging[:spread_sheet][:sheet_no] || 0]
127
+ d = plc.device_by_name logging[:trigger][:device]
128
+ v = d.send logging[:trigger][:value_type], logging[:trigger][:text_length] || 8
129
+ unless @values[logging.object_id] == v
130
+ @values[logging.object_id] = v
131
+ case logging[:trigger][:type]
132
+ when "raise"
133
+ triggered = !!v
134
+ when "fall"
135
+ triggered = !v
136
+ else
137
+ triggered = true
138
+ end
139
+ end
168
140
  end
141
+
142
+ next unless triggered
143
+
144
+ # gether values
145
+ values = logging[:devices].map do |config|
146
+ d1, d2 = config[:device].split("-").map{|d| plc.device_by_name d}
147
+ devices = [d1]
148
+ if d2
149
+ d3 = d1 + 1
150
+ devices += [d2.number - d1.number, 0].max.times.inject([]){|a, i| a << d3; d3 += 1; a}
151
+ end
152
+ devices.map{|d| d.send config[:type], config[:length] || 8}
153
+ end.flatten
154
+ @worker_queue.push logging:logging, values:values, time:Time.now
155
+ rescue => e
156
+ #p e, caller
169
157
  end
158
+ end if config[:loggings]
159
+ end
160
+
161
+ private
162
+
163
+ def setup
164
+ Thread.start {
165
+ thread_proc
166
+ }
167
+ end
168
+
169
+ def thread_proc
170
+ while arg = @worker_queue.pop
171
+ begin
172
+ logging = arg[:logging]
173
+ spread_sheet = @session.spreadsheet_by_key(logging[:spread_sheet][:spread_sheet_key])
174
+
175
+ # get worksheet
176
+ worksheet = begin
177
+ if logging[:spread_sheet][:sheet_name]
178
+ spread_sheet.worksheet_by_title logging[:spread_sheet][:sheet_name]
179
+ else
180
+ spread_sheet.worksheets[logging[:spread_sheet][:sheet_no] || 0]
181
+ end
182
+ end
183
+
184
+ # write columns if needs
185
+ if worksheet.num_rows == 0
186
+ worksheet[1, 1] = "Time"
187
+ logging[:columns].split(",").each_with_index do |t, i|
188
+ worksheet[1, i + 2] = t
189
+ end
190
+ end
170
191
 
171
- # write columns if needs
172
- if worksheet.num_rows == 0
173
- worksheet[1, 1] = "Time"
174
- logging[:columns].split(",").each_with_index do |t, i|
175
- worksheet[1, i + 2] = t
192
+ # write values
193
+ r = worksheet.num_rows + 1
194
+ worksheet[r, 1] = arg[:time]
195
+ arg[:values].each_with_index do |v, i|
196
+ worksheet[r, i + 2] = v
197
+ end if arg[:values]
198
+ worksheet.save
199
+ rescue => e
200
+ # TODO: Resend if it fails.
201
+ #p e, caller
176
202
  end
177
203
  end
178
-
179
- # write values
180
- r = worksheet.num_rows + 1
181
- worksheet[r, 1] = arg[:time]
182
- arg[:values].each_with_index do |v, i|
183
- worksheet[r, i + 2] = v
184
- end if arg[:values]
185
- worksheet.save
186
- rescue => e
187
- # TODO: Resend if it fails.
188
- p e
189
204
  end
190
- end
205
+
206
+ end
207
+
208
+ end
209
+ end
210
+
211
+
212
+ def plugin_google_drive_init plc
213
+ @google_drive_plugin = LadderDrive::Emulator::GoogleDrivePlugin.new plc
214
+ end
215
+
216
+ def plugin_google_drive_exec plc
217
+ @google_drive_plugin.run_cycle plc
191
218
  end
@@ -57,78 +57,111 @@ DOC
57
57
 
58
58
  require 'net/https'
59
59
 
60
- def plugin_ifttt_init plc
61
- @plugin_ifttt_config = load_plugin_config 'ifttt'
62
- return if @plugin_ifttt_config[:disable]
63
-
64
- @plugin_ifttt_values = {}
65
- @plugin_ifttt_times = {}
66
- @plugin_ifttt_worker_queue = Queue.new
67
- Thread.start {
68
- plugin_ifttt_worker_loop
69
- }
70
- end
60
+ module LadderDrive
61
+ module Emulator
71
62
 
72
- def plugin_ifttt_exec plc
73
- return if @plugin_ifttt_config[:disable]
74
- return unless @plugin_ifttt_config[:web_hook_key]
75
-
76
- @plugin_ifttt_config[:events].each do |event|
77
- begin
78
- triggered = false
79
- case event[:trigger][:type]
80
- when "interval"
81
- now = Time.now
82
- t = @plugin_ifttt_times[event.object_id] || now
83
- triggered = t <= now
84
- if triggered
85
- t += event[:trigger][:interval] || 300
86
- @plugin_ifttt_times[event.object_id] = t
87
- end
88
- else
89
- d = plc.device_by_name event[:trigger][:device]
90
- v = d.send event[:trigger][:value_type], event[:trigger][:text_length] || 8
91
- unless @plugin_ifttt_values[event.object_id] == v
92
- @plugin_ifttt_values[event.object_id] = v
93
- case event[:trigger][:type]
94
- when "raise"
95
- triggered = !!v
96
- when "fall"
97
- triggered = !v
98
- else
99
- triggered = true
63
+ class IftttPlugin < Plugin
64
+
65
+ def initialize plc
66
+ super #plc
67
+ return if disabled?
68
+
69
+ @values = {}
70
+ @times = {}
71
+ @worker_queue = Queue.new
72
+ setup
73
+ end
74
+
75
+ def run_cycle plc
76
+ return if disabled?
77
+ config[:events].each do |event|
78
+ begin
79
+ triggered = false
80
+ case event[:trigger][:type]
81
+ when "interval"
82
+ now = Time.now
83
+ t = @times[event.object_id] || now
84
+ triggered = t <= now
85
+ if triggered
86
+ t += event[:trigger][:interval] || 300
87
+ @times[event.object_id] = t
88
+ end
89
+ else
90
+ d = plc.device_by_name event[:trigger][:device]
91
+ v = d.send event[:trigger][:value_type], event[:trigger][:text_length] || 8
92
+ unless @values[event.object_id] == v
93
+ @values[event.object_id] = v
94
+ case event[:trigger][:type]
95
+ when "raise"
96
+ triggered = !!v
97
+ when "fall"
98
+ triggered = !v
99
+ else
100
+ triggered = true
101
+ end
100
102
  end
101
103
  end
104
+
105
+ next unless triggered
106
+
107
+ @worker_queue.push event:event[:name], payload:event[:params].dup || {}, value:v
108
+ rescue => e
109
+ p e
102
110
  end
111
+ end if config[:events]
112
+ end
113
+
114
+ def disabled?
115
+ return false unless super
116
+ unless config[:web_hook_key]
117
+ puts "ERROR: IftttPlugin requires web_hook_key."
118
+ false
119
+ else
120
+ super
121
+ end
122
+ end
103
123
 
104
- next unless triggered
105
124
 
106
- @plugin_ifttt_worker_queue.push event:event[:name], payload:event[:params].dup || {}, value:v
107
- rescue => e
108
- p e
125
+ private
126
+
127
+ def setup
128
+ Thread.start {
129
+ thread_proc
130
+ }
109
131
  end
110
- end if @plugin_ifttt_config[:events]
111
- end
112
132
 
113
- def plugin_ifttt_worker_loop
114
- while arg = @plugin_ifttt_worker_queue.pop
115
- begin
116
- uri = URI.parse("https://maker.ifttt.com/trigger/#{arg[:event]}/with/key/#{@plugin_ifttt_config[:web_hook_key]}")
117
- http = Net::HTTP.new(uri.host, uri.port)
118
- http.use_ssl = true
119
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
120
-
121
- req = Net::HTTP::Post.new(uri.path)
122
- payload = arg[:payload]
123
- payload.keys.each do |key|
124
- payload[key] = arg[:value] if payload[key] == "__value__"
125
- end
126
- req.set_form_data(payload)
133
+ def thread_proc
134
+ while arg = @worker_queue.pop
135
+ begin
136
+ uri = URI.parse("https://maker.ifttt.com/trigger/#{arg[:event]}/with/key/#{config[:web_hook_key]}")
137
+ http = Net::HTTP.new(uri.host, uri.port)
138
+ http.use_ssl = true
139
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
140
+
141
+ req = Net::HTTP::Post.new(uri.path)
142
+ payload = arg[:payload]
143
+ payload.keys.each do |key|
144
+ payload[key] = arg[:value] if payload[key] == "__value__"
145
+ end
146
+ req.set_form_data(payload)
127
147
 
128
- http.request(req)
129
- rescue => e
130
- # TODO: Resend if it fails.
131
- p e
148
+ http.request(req)
149
+ rescue => e
150
+ # TODO: Resend if it fails.
151
+ p e
152
+ end
153
+ end
132
154
  end
133
- end
155
+
156
+ end
157
+
158
+ end
159
+ end
160
+
161
+ def plugin_ifttt_init plc
162
+ @ifttt_plugin = LadderDrive::Emulator::IftttPlugin.new plc
163
+ end
164
+
165
+ def plugin_ifttt_exec plc
166
+ @ifttt_plugin.run_cycle plc
134
167
  end
@@ -54,13 +54,15 @@ class PlcMapperPlugin < Plugin
54
54
 
55
55
  def initialize plc
56
56
  super #plc
57
+ return if disabled?
57
58
  @lock = Mutex.new
58
59
  @values_for_reading = {}
59
60
  @values_for_writing = {}
60
- setup
61
+ setup unless config.empty? || config[:disable]
61
62
  end
62
63
 
63
64
  def run_cycle plc
65
+ return if disabled?
64
66
  return false unless super
65
67
  @lock.synchronize {
66
68
  # set values from plcs to ladder drive.
@@ -81,8 +83,8 @@ class PlcMapperPlugin < Plugin
81
83
 
82
84
  def setup
83
85
  config[:plcs].each do |plc_config|
84
- Thread.start(plc_config) {|plc_config|
85
- mapping_thread_proc plc_config
86
+ Thread.start(plc_config) {|config|
87
+ mapping_thread_proc config
86
88
  }
87
89
  end
88
90
  end
@@ -102,7 +104,9 @@ class PlcMapperPlugin < Plugin
102
104
  mappings.map do |h|
103
105
  a = []
104
106
  h.each do |k, v|
105
- devs = v.split("-").map{|d| protocol.device_by_name d.strip}
107
+ devs = v.split("-").map{|d|
108
+ protocol.device_by_name d.strip
109
+ }
106
110
  d1 = devs.first
107
111
  d2 = devs.last
108
112
  a << k
@@ -125,6 +129,7 @@ class PlcMapperPlugin < Plugin
125
129
  Time.at t
126
130
  end
127
131
 
132
+ alerted = false
128
133
  loop do
129
134
  begin
130
135
  now = Time.now
@@ -133,8 +138,10 @@ class PlcMapperPlugin < Plugin
133
138
  next_time += interval
134
139
  end
135
140
  sleep next_time - Time.now
136
- rescue => e
137
- puts e, caller
141
+ alerted = false
142
+ rescue
143
+ puts "#{config[:description]} is not reachable." unless alerted
144
+ alerted = true
138
145
  end
139
146
  end
140
147
  end
@@ -43,113 +43,139 @@ DOC
43
43
 
44
44
  require 'net/https'
45
45
 
46
- def plugin_slack_init plc
47
- @plugin_slack_config = load_plugin_config 'slack'
48
-
49
- @plugin_slack_values = {}
50
- @plugin_slack_times = {}
51
- @plugin_slack_worker_queue = Queue.new
52
-
53
- # collect comments
54
- @plugin_slack_comments = {}
55
- @plugin_slack_config[:device_comments].each do |k, v|
56
- d = plc.device_by_name(k)
57
- @plugin_slack_comments[d.name] = v if d
58
- end if @plugin_slack_config[:device_comments]
59
-
60
- Thread.start {
61
- plugin_slack_worker_loop
62
- }
63
- end
64
46
 
65
- def plugin_slack_exec plc
66
- return if @plugin_slack_config[:disable]
67
-
68
- @plugin_slack_config[:events].each do |event|
69
- next unless event[:devices]
70
- next unless event[:webhook_url]
71
- begin
72
-
73
- # gether values
74
- devices = event[:devices].split(",").map{|e| e.split("-")}.map do |devs|
75
- devs = devs.map{|d| plc.device_by_name d.strip}
76
- d1 = devs.first
77
- d2 = devs.last
78
- d = d1
79
- [d2.number - d1.number + 1, 1].max.times.inject([]){|a, i| a << d1; d1 += 1; a}
80
- end.flatten
81
-
82
- interval_triggered = false
83
- now = Time.now
84
- devices.each do |device|
85
- triggered = false
86
- v = nil
87
- case event[:trigger][:type]
88
- when "interval"
89
- t = @plugin_slack_times[event.object_id] || now
90
- triggered = t <= now
91
- if triggered
92
- interval_triggered = true
93
- t += event[:trigger][:interval] || 300
94
- @plugin_slack_times[event.object_id] = t
95
- end
96
- v = device.send event[:value_type], event[:trigger][:text_length] || 8
97
- else
98
- v = device.send event[:value_type], event[:text_length] || 8
99
- unless @plugin_slack_values[device.name] == v
100
- @plugin_slack_values[device.name] = v
101
- case event[:trigger][:type]
102
- when "raise"
103
- triggered = !!v
104
- when "fall"
105
- triggered = !v
106
- else
107
- triggered = true
47
+ module LadderDrive
48
+ module Emulator
49
+
50
+ class SlackPlugin < Plugin
51
+
52
+ def initialize plc
53
+ super #plc
54
+ return if disabled?
55
+
56
+ @values = {}
57
+ @times = {}
58
+ @worker_queue = Queue.new
59
+
60
+ # collect comments
61
+ @comments = {}
62
+ config[:device_comments].each do |k, v|
63
+ d = plc.device_by_name(k)
64
+ @comments[d.name] = v if d
65
+ end if config[:device_comments]
66
+ setup
67
+ end
68
+
69
+ def run_cycle plc
70
+ return if disabled?
71
+ return unless config[:events]
72
+
73
+ config[:events].each do |event|
74
+ next unless event[:devices]
75
+ next unless event[:webhook_url]
76
+ begin
77
+
78
+ # gether values
79
+ devices = event[:devices].split(",").map{|e| e.split("-")}.map do |devs|
80
+ devs = devs.map{|d| plc.device_by_name d.strip}
81
+ d1 = devs.first
82
+ d2 = devs.last
83
+ [d2.number - d1.number + 1, 1].max.times.inject([]){|a, i| a << d1; d1 += 1; a}
84
+ end.flatten
85
+
86
+ interval_triggered = false
87
+ now = Time.now
88
+ devices.each do |device|
89
+ triggered = false
90
+ v = nil
91
+ case event[:trigger][:type]
92
+ when "interval"
93
+ t = @times[event.object_id] || now
94
+ triggered = t <= now
95
+ if triggered
96
+ interval_triggered = true
97
+ t += event[:trigger][:interval] || 300
98
+ @times[event.object_id] = t
99
+ end
100
+ v = device.send event[:value_type], event[:trigger][:text_length] || 8
101
+ else
102
+ v = device.send event[:value_type], event[:text_length] || 8
103
+ unless @values[device.name] == v
104
+ @values[device.name] = v
105
+ case event[:trigger][:type]
106
+ when "raise"
107
+ triggered = !!v
108
+ when "fall"
109
+ triggered = !v
110
+ else
111
+ triggered = true
112
+ end
108
113
  end
109
114
  end
115
+
116
+ next unless triggered || interval_triggered
117
+
118
+ @worker_queue.push event:event,
119
+ device_name:device.name,
120
+ value:v,
121
+ time: now
110
122
  end
123
+ rescue => e
124
+ p e
125
+ end
126
+ end
127
+ end
128
+
129
+ private
111
130
 
112
- next unless triggered || interval_triggered
131
+ def setup
132
+ Thread.start {
133
+ thread_proc
134
+ }
135
+ end
113
136
 
114
- @plugin_slack_worker_queue.push event:event,
115
- device_name:device.name,
116
- value:v,
117
- time: now
137
+ def thread_proc
138
+ while arg = @worker_queue.pop
139
+ begin
140
+ event = arg[:event]
141
+ uri = URI.parse(event[:webhook_url])
142
+ http = Net::HTTP.new(uri.host, uri.port)
143
+ http.use_ssl = true
144
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
145
+
146
+ req = Net::HTTP::Post.new(uri.path)
147
+ req["Content-Type"] = "application/json"
148
+
149
+ format = event[:format] || "__comment__ occured at __time__"
150
+ format = arg[:value] ? format[:raise] : format[:fall] unless format.is_a? String
151
+
152
+ device_name = arg[:device_name]
153
+ comment = @comments[device_name] || device_name
154
+ value = arg[:value].to_s
155
+ time = arg[:time].iso8601
156
+
157
+ payload = {text:format.gsub(/__device_comment__/, comment).gsub(/__value__/, value).gsub(/__time__/, time).gsub(/__device_name__/, device_name)
158
+ }
159
+ req.body = payload.to_json
160
+
161
+ http.request(req)
162
+ rescue => e
163
+ # TODO: Resend if it fails.
164
+ p e
165
+ end
118
166
  end
119
- rescue => e
120
- p e
121
167
  end
122
- end if @plugin_slack_config[:events]
168
+
123
169
  end
124
170
 
125
- def plugin_slack_worker_loop
126
- while arg = @plugin_slack_worker_queue.pop
127
- begin
128
- event = arg[:event]
129
- uri = URI.parse(event[:webhook_url])
130
- http = Net::HTTP.new(uri.host, uri.port)
131
- http.use_ssl = true
132
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
133
-
134
- req = Net::HTTP::Post.new(uri.path)
135
- req["Content-Type"] = "application/json"
136
-
137
- format = event[:format] || "__comment__ occured at __time__"
138
- format = arg[:value] ? format[:raise] : format[:fall] unless format.is_a? String
139
-
140
- device_name = arg[:device_name]
141
- comment = @plugin_slack_comments[device_name] || device_name
142
- value = arg[:value].to_s
143
- time = arg[:time].iso8601
144
-
145
- payload = {text:format.gsub(/__device_comment__/, comment).gsub(/__value__/, value).gsub(/__time__/, time).gsub(/__device_name__/, device_name)
146
- }
147
- req.body = payload.to_json
148
-
149
- http.request(req)
150
- rescue => e
151
- # TODO: Resend if it fails.
152
- p e
153
- end
154
- end
171
+ end
172
+ end
173
+
174
+
175
+ def plugin_slack_init plc
176
+ @slack_plugin = LadderDrive::Emulator::SlackPlugin.new plc
177
+ end
178
+
179
+ def plugin_slack_exec plc
180
+ @slack_plugin.run_cycle plc
155
181
  end
@@ -52,105 +52,122 @@ require 'trello'
52
52
 
53
53
  # @see https://qiita.com/tbpgr/items/60fc13aca8afd153e37b
54
54
 
55
- =begin
56
- Dotenv.load
57
55
 
58
- b = Trello::Board.all.find{|b| b.name == "工程モニター"}
59
- pp b.lists.map{|l| {id:l.id, name:l.name, cards:l.cards.map{|c| {id:c.id, name:c.name}}}}
60
- =end
56
+ module LadderDrive
57
+ module Emulator
61
58
 
59
+ class TrelloPlugin < Plugin
62
60
 
63
- def plugin_trello_init plc
64
- @plugin_trello_config = load_plugin_config 'trello'
61
+ def initialize plc
62
+ super #plc
63
+ return if disabled?
65
64
 
66
- @plugin_trello_values = {}
67
- @plugin_trello_times = {}
68
- @plugin_trello_worker_queue = Queue.new
65
+ @values = {}
66
+ @times = {}
67
+ @worker_queue = Queue.new
69
68
 
70
- @plugin_trello_configured = Trello.configure do |config|
71
- config.consumer_key = @plugin_trello_config[:consumer_key]
72
- config.consumer_secret = @plugin_trello_config[:consumer_secret]
73
- config.oauth_token = @plugin_trello_config[:oauth_token]
69
+ @configured = Trello.configure do |config|
70
+ config.consumer_key = self.config[:consumer_key]
71
+ config.consumer_secret = self.config[:consumer_secret]
72
+ config.oauth_token = self.config[:oauth_token]
73
+ end
74
+ setup
74
75
  end
75
76
 
76
- Thread.start {
77
- plugin_trello_worker_loop
78
- }
79
- end
77
+ def run_cycle plc
78
+ return if disabled?
79
+ return if config[:events].nil?
80
80
 
81
- def plugin_trello_exec plc
82
- return if @plugin_trello_config[:disable]
83
- # return unless @plugin_trello_configured
84
-
85
- @plugin_trello_config[:events].each do |event|
86
- begin
87
-
88
- triggered = false
89
- now = Time.now
90
- device = nil
91
-
92
- case event[:trigger][:type]
93
- when "interval"
94
- t = @plugin_trello_times[event.object_id] || now
95
- triggered = t <= now
96
- if triggered
97
- interval_triggered = true
98
- t += event[:trigger][:interval] || 300
99
- @plugin_trello_times[event.object_id] = t
100
- end
101
- else
102
- device = plc.device_by_name event[:trigger][:device]
103
- v = device.send event[:trigger][:value_type], event[:trigger][:text_length] || 8
104
- unless @plugin_trello_values[device.name] == v
105
- @plugin_trello_values[device.name] = v
106
- case event[:trigger][:type]
107
- when "raise"
108
- triggered = !!v
109
- when "fall"
110
- triggered = !v
111
- else
81
+ @config[:events].each do |event|
82
+ begin
83
+
84
+ triggered = false
85
+ now = Time.now
86
+ device = nil
87
+
88
+ case event[:trigger][:type]
89
+ when "interval"
90
+ t = @times[event.object_id] || now
91
+ triggered = t <= now
92
+ if triggered
112
93
  triggered = true
94
+ t += event[:trigger][:interval] || 300
95
+ @times[event.object_id] = t
96
+ end
97
+ else
98
+ device = plc.device_by_name event[:trigger][:device]
99
+ v = device.send event[:trigger][:value_type], event[:trigger][:text_length] || 8
100
+ unless @values[device.name] == v
101
+ @values[device.name] = v
102
+ case event[:trigger][:type]
103
+ when "raise"
104
+ triggered = !!v
105
+ when "fall"
106
+ triggered = !v
107
+ else
108
+ triggered = true
109
+ end
113
110
  end
114
111
  end
115
- end
116
112
 
117
- next unless triggered
113
+ next unless triggered
118
114
 
119
- @plugin_trello_worker_queue.push event:event, device_name:device.name, value:v, time: now
115
+ @worker_queue.push event:event, device_name:device.name, value:v, time: now
120
116
 
121
- rescue => e
122
- p e
117
+ rescue => e
118
+ p e
119
+ end
123
120
  end
124
- end if @plugin_trello_config[:events]
125
- end
121
+ end
122
+
123
+ private
126
124
 
127
- def plugin_trello_worker_loop
128
- while arg = @plugin_trello_worker_queue.pop
129
- begin
130
- event = arg[:event]
125
+ def setup
126
+ Thread.start {
127
+ thread_proc
128
+ }
129
+ end
131
130
 
132
- board = Trello::Board.all.find{|b| b.name == event[:board_name]}
133
- next unless board
131
+ def thread_proc
132
+ while arg = @worker_queue.pop
133
+ begin
134
+ event = arg[:event]
134
135
 
135
- card_name = event[:card_name].dup || ""
136
- card_name.gsub!(/__value__/, arg[:value] || "")
137
- next if (card_name || "").empty?
136
+ board = Trello::Board.all.find{|b| b.name == event[:board_name]}
137
+ next unless board
138
138
 
139
- list_name = event[:list_name]
140
- next unless list_name
141
- list = board.lists.find{|l| l.name == list_name}
142
- next unless list
139
+ card_name = event[:card_name].dup || ""
140
+ card_name.gsub!(/__value__/, arg[:value] || "")
141
+ next if (card_name || "").empty?
143
142
 
144
- card = board.lists.map{|l| l.cards.map{|c| c}}.flatten.find{|c| c.name == card_name}
145
- if card
146
- card.move_to_list list
147
- else
148
- card = Trello::Card.create name:card_name, list_id:list.id
149
- end
143
+ list_name = event[:list_name]
144
+ next unless list_name
145
+ list = board.lists.find{|l| l.name == list_name}
146
+ next unless list
150
147
 
151
- rescue => e
152
- # TODO: Resend if it fails.
153
- p e
148
+ card = board.lists.map{|l| l.cards.map{|c| c}}.flatten.find{|c| c.name == card_name}
149
+ if card
150
+ card.move_to_list list
151
+ else
152
+ card = Trello::Card.create name:card_name, list_id:list.id
153
+ end
154
+
155
+ rescue => e
156
+ # TODO: Resend if it fails.
157
+ p e
158
+ end
159
+ end
154
160
  end
155
- end
161
+
162
+ end
163
+
164
+ end
165
+ end
166
+
167
+ def plugin_trello_init plc
168
+ @trello_plugin = LadderDrive::Emulator::TrelloPlugin.new plc
169
+ end
170
+
171
+ def plugin_trello_exec plc
172
+ @trello_plugin.run_cycle plc
156
173
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ladder_drive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuyoshi Ito
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-29 00:00:00.000000000 Z
11
+ date: 2019-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -48,42 +48,56 @@ dependencies:
48
48
  name: ffi
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.9.24
54
- - - ">="
54
+ - - "~>"
55
55
  - !ruby/object:Gem::Version
56
56
  version: 1.9.24
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - "~>"
61
+ - - ">="
62
62
  - !ruby/object:Gem::Version
63
63
  version: 1.9.24
64
- - - ">="
64
+ - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: 1.9.24
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: pi_piper
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - "~>"
72
- - !ruby/object:Gem::Version
73
- version: '2.0'
74
71
  - - ">="
75
72
  - !ruby/object:Gem::Version
76
73
  version: 2.0.0
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.0'
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 2.0.0
81
84
  - - "~>"
82
85
  - !ruby/object:Gem::Version
83
86
  version: '2.0'
87
+ - !ruby/object:Gem::Dependency
88
+ name: serialport
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
84
91
  - - ">="
85
92
  - !ruby/object:Gem::Version
86
- version: 2.0.0
93
+ version: '0'
94
+ type: :runtime
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
87
101
  - !ruby/object:Gem::Dependency
88
102
  name: bundler
89
103
  requirement: !ruby/object:Gem::Requirement
@@ -224,8 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
238
  - !ruby/object:Gem::Version
225
239
  version: '0'
226
240
  requirements: []
227
- rubyforge_project:
228
- rubygems_version: 2.7.7
241
+ rubygems_version: 3.0.1
229
242
  signing_key:
230
243
  specification_version: 4
231
244
  summary: The ladder_drive is a simple abstract ladder for PLC (Programmable Logic