escalator 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +13 -1
- data/README.md +92 -2
- data/README_jp.md +102 -0
- data/lib/escalator/asm.rb +1 -1
- data/lib/escalator/cli.rb +8 -7
- data/lib/escalator/config.rb +84 -0
- data/lib/escalator/intel_hex.rb +43 -9
- data/lib/escalator/protocol/mitsubishi/mc_protocol.rb +228 -0
- data/lib/escalator/protocol/mitsubishi/mitsubishi.rb +36 -0
- data/lib/escalator/protocol/mitsubishi/qdevice.rb +114 -0
- data/lib/escalator/protocol/protocol.rb +78 -0
- data/lib/escalator/tasks/build.rb +20 -40
- data/lib/escalator/uploader.rb +114 -0
- data/lib/escalator/version.rb +1 -1
- data/lib/escalator.rb +6 -5
- data/plc/mitsubishi/iq-r/r08/LICENSE +21 -0
- data/plc/mitsubishi/iq-r/r08/r08.gx3 +0 -0
- data/template/escalator/config/plc.yml +7 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97963603ab6ca43c800f1457985665cde1595d64
|
4
|
+
data.tar.gz: 2655e9900ca290185648b1b5d5436a8eb2703c25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a023765c76d3fa85ccb6c4c399e3cf57b040d0c94e5bceb0c75890d0fb60b0531ba4d1b95b3732a739b3c098a18d30e0867e8bd42e41a609073a357b8a6fa4ab
|
7
|
+
data.tar.gz: 4f772215bb2dca5a8b63e8a18f030fd3e6347ef55f355b8923baea04a049a442838788cabe2bac686b23b86e3c2cc25516237159ca9c20e9f547e5bc9ae3e949
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,22 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
escalator (0.1.
|
4
|
+
escalator (0.1.2)
|
5
5
|
thor
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
+
activesupport (5.0.0.1)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (~> 0.7)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
concurrent-ruby (1.0.2)
|
16
|
+
i18n (0.7.0)
|
17
|
+
minitest (5.9.1)
|
10
18
|
power_assert (0.2.7)
|
11
19
|
rake (10.5.0)
|
12
20
|
test-unit (3.1.7)
|
13
21
|
power_assert
|
14
22
|
thor (0.19.1)
|
23
|
+
thread_safe (0.3.5)
|
24
|
+
tzinfo (1.2.2)
|
25
|
+
thread_safe (~> 0.1)
|
15
26
|
|
16
27
|
PLATFORMS
|
17
28
|
ruby
|
18
29
|
|
19
30
|
DEPENDENCIES
|
31
|
+
activesupport
|
20
32
|
bundler (~> 1.11)
|
21
33
|
escalator!
|
22
34
|
rake (~> 10.0)
|
data/README.md
CHANGED
@@ -2,9 +2,99 @@
|
|
2
2
|
|
3
3
|
The escalator is a simple abstract ladder for PLC (Programmable Logic Controller).
|
4
4
|
|
5
|
-
|
5
|
+
We aim to design runnable abstraction ladder which is running on any PLC with same ladder source or binary and prepare full stack tools.
|
6
|
+
|
7
|
+
# Getting started
|
8
|
+
|
9
|
+
It's required the Ruby environment.
|
10
|
+
To prepare Ruby environment, please find web sites.
|
11
|
+
|
12
|
+
Install Escalator at the command prompt.
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem install escalator
|
16
|
+
```
|
17
|
+
|
18
|
+
# Create an Escalator project
|
19
|
+
|
20
|
+
At the command prompt, create a new Escalator project.
|
21
|
+
|
22
|
+
```
|
23
|
+
$ escalator create my_project
|
24
|
+
$ cd my_project
|
25
|
+
```
|
26
|
+
|
27
|
+
Created files are consisted like below the tree.
|
28
|
+
|
29
|
+
```
|
30
|
+
.
|
31
|
+
├── Rakefile
|
32
|
+
├── asm
|
33
|
+
│ └── main.esc
|
34
|
+
├── config
|
35
|
+
│ └── plc.yml
|
36
|
+
└── plc
|
37
|
+
└── mitsubishi
|
38
|
+
└── iq-r
|
39
|
+
└── r08
|
40
|
+
├── LICENSE
|
41
|
+
└── r08.gx3
|
42
|
+
```
|
43
|
+
|
44
|
+
# Connection configuration
|
45
|
+
|
46
|
+
## PLC configuration
|
47
|
+
|
48
|
+
There is a plc project under the plc directory.
|
49
|
+
Launch the one of the plc project which you want to use.
|
50
|
+
(Currently we support MITSUBISHI iQ-R R08CUP only.)
|
51
|
+
|
52
|
+
Configure ethernet connection by the tool which is provided by plc maker.
|
53
|
+
Then upload settings and plc program to the plc.
|
54
|
+
|
55
|
+
## Escalator configuration
|
56
|
+
|
57
|
+
There is a configuration file at config/plc.yml.
|
58
|
+
Though currently we support MITSUBISHI iQ-R R08CUP only, you only change host to an ip address of your plc.
|
59
|
+
|
60
|
+
```
|
61
|
+
:plc:
|
62
|
+
:cpu: iq-r
|
63
|
+
:protocol: mc_protocol
|
64
|
+
:host: 192.168.0.1
|
65
|
+
:port: 5007
|
66
|
+
:program_area: d10000
|
67
|
+
:interaction_area: d9998
|
68
|
+
```
|
69
|
+
## Escalator programming
|
70
|
+
|
71
|
+
Escalator program file is located under the asm directory.
|
72
|
+
By default, use asm/main.esc.
|
73
|
+
Edit it and programming.
|
74
|
+
|
75
|
+
Refer [Wiki](https://github.com/ito-soft-design/escalator/wiki/mnemonic) to check mnemonic.
|
76
|
+
|
77
|
+
```
|
78
|
+
LD X0
|
79
|
+
OUT Y0
|
80
|
+
LD X1
|
81
|
+
OR M0
|
82
|
+
ANI X2
|
83
|
+
OUT M0
|
84
|
+
END
|
85
|
+
```
|
86
|
+
|
87
|
+
# Transfer the Escalator program
|
88
|
+
|
89
|
+
At the command prompt, use rake command to upload escalator program to the plc.
|
90
|
+
The Escalator program is running immediate after uploaded.
|
91
|
+
|
92
|
+
```
|
93
|
+
$ rake plc
|
94
|
+
```
|
95
|
+
|
96
|
+
|
6
97
|
|
7
98
|
## License
|
8
99
|
|
9
100
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
10
|
-
|
data/README_jp.md
CHANGED
@@ -5,6 +5,108 @@
|
|
5
5
|
|
6
6
|
まずはニーモニックレベルで実現し、その上に分かりやすい形のプログラミングツールを用意できればと考えています。
|
7
7
|
|
8
|
+
# 使い方
|
9
|
+
|
10
|
+
使用するにはRubyが実行できる環境が必要です。
|
11
|
+
Rubyの実行環境の構築はWebサイト等を検索して構築してください。
|
12
|
+
|
13
|
+
## インストール
|
14
|
+
|
15
|
+
gemでエスカレーターをインストールします。
|
16
|
+
|
17
|
+
```
|
18
|
+
$ gem install escalator
|
19
|
+
```
|
20
|
+
|
21
|
+
## プロジェクト作成
|
22
|
+
|
23
|
+
エスカレーターをインストールするとescalatorコマンドが使用できる様になります。
|
24
|
+
escalatorコマンドでラダーを構成するプロジェクトファイルを作ります。
|
25
|
+
|
26
|
+
```
|
27
|
+
$ escalator create my_project
|
28
|
+
$ cd my_project
|
29
|
+
```
|
30
|
+
|
31
|
+
ファイルの構成は下の様になっています。
|
32
|
+
plc以下にエスカレーターを実行するPLCプロジェクトの雛形があります。
|
33
|
+
現在は三菱電機のiQ-RシリーズR08CPUのみの対応となっています。
|
34
|
+
他メーカーや他の機種は今後追加する予定です。
|
35
|
+
|
36
|
+
|
37
|
+
```
|
38
|
+
.
|
39
|
+
├── Rakefile
|
40
|
+
├── asm
|
41
|
+
│ └── main.esc
|
42
|
+
├── config
|
43
|
+
│ └── plc.yml
|
44
|
+
└── plc
|
45
|
+
└── mitsubishi
|
46
|
+
└── iq-r
|
47
|
+
└── r08
|
48
|
+
├── LICENSE
|
49
|
+
└── r08.gx3
|
50
|
+
```
|
51
|
+
|
52
|
+
## 通信設定
|
53
|
+
|
54
|
+
### PLCの通信設定
|
55
|
+
|
56
|
+
plc以下のプロジェクトファイルを開いてIPアドレスなど変更します。
|
57
|
+
変更後PLCに設定とプログラムを書き込みます。
|
58
|
+
|
59
|
+
### エスカレーターの設定
|
60
|
+
|
61
|
+
config/plc.ymlファイルで設定します。
|
62
|
+
|
63
|
+
現在はiQ-Rのみの対応なので:host: 192.168.0.1の行でPLCに設定したIPアドレスを指定するのみで接続できます。
|
64
|
+
|
65
|
+
```
|
66
|
+
:plc:
|
67
|
+
:cpu: iq-r
|
68
|
+
:protocol: mc_protocol
|
69
|
+
:host: 192.168.0.1
|
70
|
+
:port: 5007
|
71
|
+
:program_area: d10000
|
72
|
+
:interaction_area: d9998
|
73
|
+
```
|
74
|
+
|
75
|
+
## エスカレータープログラム作成
|
76
|
+
|
77
|
+
エスカレーターのプログラムはasm以下にあります。
|
78
|
+
現在はmain.escファイルから生成します。
|
79
|
+
|
80
|
+
main.escを編集しプログラムを作成します。
|
81
|
+
PLC側の実装がまだ進んでいないので実行できるニーモニックはLD、OUT、AND、ORとその反転程度です。
|
82
|
+
|
83
|
+
ニーモニックについては[Wiki](https://github.com/ito-soft-design/escalator/wiki/mnemonic)の方を参照してください。
|
84
|
+
|
85
|
+
```
|
86
|
+
LD X0
|
87
|
+
OUT Y0
|
88
|
+
LD X1
|
89
|
+
OR M0
|
90
|
+
ANI X2
|
91
|
+
OUT M0
|
92
|
+
END
|
93
|
+
```
|
94
|
+
|
95
|
+
## プログラムの転送
|
96
|
+
|
97
|
+
エスカレータープログラムをplcに転送するはrakeコマンドを使用します。
|
98
|
+
転送後プログラムが実行されます。
|
99
|
+
|
100
|
+
```
|
101
|
+
$ rake plc
|
102
|
+
```
|
103
|
+
|
104
|
+
|
105
|
+
# エスカレーターに関する情報
|
106
|
+
|
107
|
+
- [一往確認日記 [escalator]](http://diary.itosoft.com/?category=escalator)
|
108
|
+
- [Wiki](https://github.com/ito-soft-design/escalator/wiki/)
|
109
|
+
|
8
110
|
# ライセンス
|
9
111
|
|
10
112
|
MIT
|
data/lib/escalator/asm.rb
CHANGED
data/lib/escalator/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# The MIT License (MIT)
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
@@ -9,10 +9,10 @@
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
11
11
|
# the following conditions:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# The above copyright notice and this permission notice shall be
|
14
14
|
# included in all copies or substantial portions of the Software.
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -28,13 +28,14 @@ include FileUtils
|
|
28
28
|
|
29
29
|
module Escalator
|
30
30
|
class CLI < Thor
|
31
|
-
|
31
|
+
|
32
32
|
desc "create", "Create a new project"
|
33
33
|
def create(name)
|
34
34
|
template_path = File.join(Escalator_root, "template", "escalator")
|
35
35
|
cp_r template_path, name
|
36
|
-
|
36
|
+
temlate_plc_path = File.join(Escalator_root, "plc")
|
37
|
+
cp_r temlate_plc_path, name
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
end
|
40
41
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'active_support/core_ext/string/inflections'
|
25
|
+
require "escalator/protocol/protocol"
|
26
|
+
require 'escalator/uploader'
|
27
|
+
require 'yaml'
|
28
|
+
|
29
|
+
include Escalator::Protocol::Mitsubishi
|
30
|
+
|
31
|
+
module Escalator
|
32
|
+
|
33
|
+
|
34
|
+
class EscalatorConfig
|
35
|
+
|
36
|
+
def self.default
|
37
|
+
@config ||= begin
|
38
|
+
config_path = File.join "config", "plc.yml"
|
39
|
+
h = YAML.load(File.read(config_path)) if File.exist?(config_path)
|
40
|
+
new h || {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize options={}
|
45
|
+
default = {input: "asm/main.asm", output: "build/main.hex"}
|
46
|
+
@config = options.merge default
|
47
|
+
end
|
48
|
+
|
49
|
+
def protocol
|
50
|
+
@protocol ||= begin
|
51
|
+
plc_info = @config[:plc]
|
52
|
+
p = eval("#{plc_info[:protocol].camelize}.new")
|
53
|
+
p.host = plc_info[:host] if plc_info[:host]
|
54
|
+
p.port = plc_info[:port] if plc_info[:port]
|
55
|
+
p.log_level = plc_info[:log_level] if plc_info[:log_level]
|
56
|
+
p
|
57
|
+
rescue
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def uploader
|
63
|
+
@uploader ||= begin
|
64
|
+
u = Uploader.new
|
65
|
+
u.protocol = self.protocol
|
66
|
+
u.program_area = u.protocol.device_by_name(@config[:plc][:program_area]) if @config[:plc] && @config[:plc][:program_area]
|
67
|
+
u.interaction_area = u.protocol.device_by_name(@config[:plc][:interaction_area]) if @config[:plc] && @config[:plc][:interaction_area]
|
68
|
+
u
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def method_missing(name, *args)
|
73
|
+
name = name.to_s unless name.is_a? String
|
74
|
+
case name.to_s
|
75
|
+
when /(.*)=$/
|
76
|
+
@config[$1.to_sym] = args.first
|
77
|
+
else
|
78
|
+
@config[name.to_sym]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/escalator/intel_hex.rb
CHANGED
@@ -1,14 +1,57 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
1
24
|
module Escalator
|
2
25
|
|
3
26
|
class IntelHex
|
4
27
|
|
5
28
|
attr_reader :offset, :codes
|
6
29
|
|
30
|
+
def self.load path
|
31
|
+
offset = 0
|
32
|
+
codes = []
|
33
|
+
File.read(path).lines.each do |l|
|
34
|
+
case l[7,2]
|
35
|
+
when "00"
|
36
|
+
address = l[3,4].to_i(16)
|
37
|
+
offset ||= address
|
38
|
+
l.chomp[9..-3].each_char.each_slice(2).each_with_index do |pair, i|
|
39
|
+
codes[address - offset + i] = pair.join("").to_i(16)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
new codes, offset
|
44
|
+
end
|
45
|
+
|
7
46
|
def initialize codes, offset = 0
|
8
47
|
@offset = offset
|
9
48
|
@codes = codes
|
10
49
|
end
|
11
50
|
|
51
|
+
def write_to path
|
52
|
+
File.write(path, dump)
|
53
|
+
end
|
54
|
+
|
12
55
|
def dump
|
13
56
|
addr = offset
|
14
57
|
lines = []
|
@@ -31,15 +74,6 @@ module Escalator
|
|
31
74
|
lines.join("\n")
|
32
75
|
end
|
33
76
|
|
34
|
-
def gxworks_memory_image
|
35
|
-
lines = []
|
36
|
-
@codes.each_slice(8) do |line_codes|
|
37
|
-
lines << line_codes.join("\t")
|
38
|
-
end
|
39
|
-
|
40
|
-
lines.join("\n")
|
41
|
-
end
|
42
|
-
|
43
77
|
end
|
44
78
|
|
45
79
|
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Escalator
|
25
|
+
module Protocol
|
26
|
+
module Mitsubishi
|
27
|
+
|
28
|
+
class McProtocol < Protocol
|
29
|
+
|
30
|
+
def initialize options={}
|
31
|
+
super
|
32
|
+
@host = options[:host] || "192.168.0.1"
|
33
|
+
@port = options[:port] || 5010
|
34
|
+
end
|
35
|
+
|
36
|
+
def open
|
37
|
+
@socket ||= TCPSocket.open(@host, @port)
|
38
|
+
end
|
39
|
+
|
40
|
+
def close
|
41
|
+
@socket.close if @socket
|
42
|
+
@socket = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_bit_from_device device
|
46
|
+
device = device_by_name device
|
47
|
+
get_bits_from_device(1, device).first
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_bits_from_device count, device
|
51
|
+
device = device_by_name device
|
52
|
+
packet = make_packet(body_for_get_bits_from_deivce(count, device))
|
53
|
+
@logger.debug("> #{dump_packet packet}")
|
54
|
+
open
|
55
|
+
@socket.write(packet.pack("c*"))
|
56
|
+
@socket.flush
|
57
|
+
res = receive
|
58
|
+
bits = []
|
59
|
+
count.times do |i|
|
60
|
+
v = res[11 + i / 2]
|
61
|
+
if i % 2 == 0
|
62
|
+
bits << ((v >> 4) != 0)
|
63
|
+
else
|
64
|
+
bits << ((v & 0xf) != 0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@logger.debug("get #{device.name} => #{bits}")
|
68
|
+
bits
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_bits_to_device bits, device
|
72
|
+
device = device_by_name device
|
73
|
+
packet = make_packet(body_for_set_bits_to_device(bits, device))
|
74
|
+
@logger.debug("> #{dump_packet packet}")
|
75
|
+
open
|
76
|
+
@socket.write(packet.pack("c*"))
|
77
|
+
@socket.flush
|
78
|
+
res = receive
|
79
|
+
@logger.debug("set #{bits} to:#{device.name}")
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def get_word_from_device device
|
84
|
+
device = device_by_name device
|
85
|
+
get_words_from_device(1, device).first
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_words_from_device(count, device)
|
89
|
+
device = device_by_name device
|
90
|
+
packet = make_packet(body_for_get_words_from_deivce(count, device))
|
91
|
+
@logger.debug("> #{dump_packet packet}")
|
92
|
+
open
|
93
|
+
@socket.write(packet.pack("c*"))
|
94
|
+
@socket.flush
|
95
|
+
res = receive
|
96
|
+
words = []
|
97
|
+
res[11, 2 * count].each_slice(2) do |pair|
|
98
|
+
words << pair.pack("c*").unpack("v").first
|
99
|
+
end
|
100
|
+
@logger.debug("get from: #{device.name} => #{words}")
|
101
|
+
words
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_words_to_device words, device
|
105
|
+
device = device_by_name device
|
106
|
+
packet = make_packet(body_for_set_words_to_device(words, device))
|
107
|
+
@logger.debug("> #{dump_packet packet}")
|
108
|
+
open
|
109
|
+
@socket.write(packet.pack("c*"))
|
110
|
+
@socket.flush
|
111
|
+
res = receive
|
112
|
+
@logger.debug("set #{words} to: #{device.name}")
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def device_by_name name
|
117
|
+
case name
|
118
|
+
when String
|
119
|
+
QDevice.new name
|
120
|
+
else
|
121
|
+
# it may be already QDevice
|
122
|
+
name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def receive
|
128
|
+
res = []
|
129
|
+
len = 0
|
130
|
+
begin
|
131
|
+
Timeout.timeout(0.1) do
|
132
|
+
while true
|
133
|
+
c = @socket.read(1)
|
134
|
+
next if c.nil? || c == ""
|
135
|
+
|
136
|
+
res << c.bytes.first
|
137
|
+
len = res[7] + res[8] << 8 if res.length >= 9
|
138
|
+
break if (len + 9 == res.length)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
rescue Timeout::Error
|
142
|
+
end
|
143
|
+
@logger.debug("< #{dump_packet res}")
|
144
|
+
res
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def make_packet body
|
150
|
+
header = [0x50, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00]
|
151
|
+
header[7..8] = data_for_short(body.length + 2)
|
152
|
+
header + body
|
153
|
+
end
|
154
|
+
|
155
|
+
def body_for_get_bit_from_deivce device
|
156
|
+
body_for_get_bits_from_deivce 1, device
|
157
|
+
end
|
158
|
+
|
159
|
+
def body_for_get_bits_from_deivce count, device
|
160
|
+
body_for_get_words_from_deivce count, device, false
|
161
|
+
end
|
162
|
+
|
163
|
+
def body_for_get_words_from_deivce count, device, word = true
|
164
|
+
body = [0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
165
|
+
body[2] = 1 unless word
|
166
|
+
body[4..7] = data_for_device(device)
|
167
|
+
body[8..9] = data_for_short count
|
168
|
+
body
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def body_for_set_bits_to_device bits, device
|
173
|
+
body = [0x01, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
174
|
+
d = device
|
175
|
+
bits = [bits] unless bits.is_a? Array
|
176
|
+
bits.each_slice(2) do |pair|
|
177
|
+
body << (pair.first ? 0x10 : 0x00)
|
178
|
+
body[-1] |= (pair.last ? 0x1 : 0x00) if pair.size == 2
|
179
|
+
d = d.next_device
|
180
|
+
end
|
181
|
+
body[4..7] = data_for_device(device)
|
182
|
+
body[8..9] = data_for_short bits.size
|
183
|
+
body
|
184
|
+
end
|
185
|
+
alias :body_for_set_bit_to_device :body_for_set_bits_to_device
|
186
|
+
|
187
|
+
def body_for_set_words_to_device words, device
|
188
|
+
body = [0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
189
|
+
d = device
|
190
|
+
words = [words] unless words.is_a? Array
|
191
|
+
words.each do |v|
|
192
|
+
body += data_for_short v
|
193
|
+
d = d.next_device
|
194
|
+
end
|
195
|
+
body[4..7] = data_for_device(device)
|
196
|
+
body[8..9] = data_for_short words.size
|
197
|
+
body
|
198
|
+
end
|
199
|
+
|
200
|
+
def data_for_device device
|
201
|
+
a = data_for_int device.number
|
202
|
+
a[3] = device.suffix_code
|
203
|
+
a
|
204
|
+
end
|
205
|
+
|
206
|
+
def data_for_short value
|
207
|
+
[value].pack("v").unpack("c*")
|
208
|
+
end
|
209
|
+
|
210
|
+
def data_for_int value
|
211
|
+
[value].pack("V").unpack("c*")
|
212
|
+
end
|
213
|
+
|
214
|
+
def dump_packet packet
|
215
|
+
a = []
|
216
|
+
len = packet.length
|
217
|
+
bytes = packet.dup
|
218
|
+
len.times do |i|
|
219
|
+
a << ("0" + bytes[i].to_s(16))[-2, 2]
|
220
|
+
end
|
221
|
+
"[" + a.join(", ") + "]"
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
$:.unshift File.dirname(__FILE__)
|
25
|
+
|
26
|
+
module Escalator
|
27
|
+
module Protocol
|
28
|
+
|
29
|
+
require 'socket'
|
30
|
+
require 'logger'
|
31
|
+
require 'timeout'
|
32
|
+
require 'qdevice'
|
33
|
+
require 'mc_protocol'
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Escalator
|
25
|
+
module Protocol
|
26
|
+
module Mitsubishi
|
27
|
+
|
28
|
+
class QDevice
|
29
|
+
|
30
|
+
attr_reader :suffix, :number
|
31
|
+
|
32
|
+
SUFFIXES = %w(SM SD X Y M L F V B D W TS TC TN SS SC SN CS CC CN SB SW S DX DY Z R ZR)
|
33
|
+
SUFFIX_CODES = [0x91, 0xa9, 0x9c, 0x9d, 0x90, 0x92, 0x93, 0x94, 0xa0, 0xa8, 0xb4, 0xc1, 0xc0, 0xc2, 0xc7, 0xc6, 0xc8, 0xc4, 0xc3, 0xc5, 0xa1, 0xb5, 0x98, 0xa2, 0xa3, 0xcc ,0xaf, 0xb0]
|
34
|
+
|
35
|
+
def initialize a, b = nil
|
36
|
+
case a
|
37
|
+
when Array
|
38
|
+
case a.size
|
39
|
+
when 4
|
40
|
+
@suffix = suffix_for_code(a[3])
|
41
|
+
@number = ((a[2] << 8 | a[1]) << 8) | a[0]
|
42
|
+
end
|
43
|
+
when String
|
44
|
+
if b
|
45
|
+
@suffix = a.upcase
|
46
|
+
@number = b
|
47
|
+
else
|
48
|
+
if a.length == 12
|
49
|
+
@suffix = [a[0,2].to_i(16), a[2,2].to_i(16)].pack "c*"
|
50
|
+
@suffix.strip!
|
51
|
+
@number = a[4,8].to_i(16)
|
52
|
+
elsif /(X|Y)(.+)/i =~ a
|
53
|
+
@suffix = $1.upcase
|
54
|
+
@number = $2.to_i(p_adic_number)
|
55
|
+
else
|
56
|
+
/(M|L|S|B|F|T|C|D|W|R)(.+)/i =~ a
|
57
|
+
@suffix = $1.upcase
|
58
|
+
@number = $2.to_i(p_adic_number)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def p_adic_number
|
65
|
+
case @suffix
|
66
|
+
when "X", "Y", "B", "W", "SB", "SW", "DX", "DY", "ZR"
|
67
|
+
16
|
68
|
+
else
|
69
|
+
10
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def name
|
74
|
+
@suffix + @number.to_s(p_adic_number).upcase
|
75
|
+
end
|
76
|
+
|
77
|
+
def next_device
|
78
|
+
d = self.class.new @suffix, @number + 1
|
79
|
+
d
|
80
|
+
end
|
81
|
+
|
82
|
+
def bit_device?
|
83
|
+
case @suffix
|
84
|
+
when "SM", "X", "Y", "M", "L", "F", "V", "B",
|
85
|
+
"TS", "TC", "SS", "SC","CS", "CC", "SB", "S", "DX", "DY"
|
86
|
+
true
|
87
|
+
else
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def suffix_for_code code
|
93
|
+
index = SUFFIX_CODES.index code
|
94
|
+
index ? SUFFIXES[index] : nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def suffix_code
|
98
|
+
index = SUFFIXES.index suffix
|
99
|
+
index ? SUFFIX_CODES[index] : 0
|
100
|
+
end
|
101
|
+
|
102
|
+
def + value
|
103
|
+
QDevice.new self.suffix, self.number + value
|
104
|
+
end
|
105
|
+
|
106
|
+
def - value
|
107
|
+
QDevice.new self.suffix, [self.number - value, 0].max
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
$:.unshift File.dirname(__FILE__)
|
25
|
+
|
26
|
+
module Escalator
|
27
|
+
module Protocol
|
28
|
+
|
29
|
+
class Protocol
|
30
|
+
|
31
|
+
attr_accessor :host, :port, :log_level
|
32
|
+
|
33
|
+
def initialize options={}
|
34
|
+
@logger = Logger.new(STDOUT)
|
35
|
+
@logger.level = options[:log_level] || Logger::INFO
|
36
|
+
end
|
37
|
+
|
38
|
+
def log_level= level
|
39
|
+
@log_level = level.is_a?(String) ? level.to_sym : level
|
40
|
+
case @log_level
|
41
|
+
when :debug
|
42
|
+
@logger.level = Logger::DEBUG
|
43
|
+
when :error
|
44
|
+
@logger.level = Logger::ERROR
|
45
|
+
when :fatal
|
46
|
+
@logger.level = Logger::FATAL
|
47
|
+
when :info
|
48
|
+
@logger.level = Logger::INFO
|
49
|
+
when :unknown
|
50
|
+
@logger.level = Logger::UNKNOWN
|
51
|
+
when :warn
|
52
|
+
@logger.level = Logger::WARN
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# abstract methods
|
57
|
+
|
58
|
+
def open; end
|
59
|
+
def close; end
|
60
|
+
|
61
|
+
def get_bit_from_device device; end
|
62
|
+
def get_bits_from_device count, device; end
|
63
|
+
def set_bits_to_device bits, device; end
|
64
|
+
def set_bit_to_device bit, device; set_bits_to_device bit, device; end
|
65
|
+
|
66
|
+
def get_word_from_device device; end
|
67
|
+
def get_words_from_device(count, device); end
|
68
|
+
def set_words_to_device words, device; end
|
69
|
+
def set_word_to_device word, device; set_words_to_device word, device; end
|
70
|
+
|
71
|
+
def device_by_name name; nil; end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
require 'mitsubishi/mitsubishi'
|
@@ -23,9 +23,11 @@
|
|
23
23
|
|
24
24
|
Escalator_root = File.expand_path(File.join(File.dirname(__FILE__), "../../../"))
|
25
25
|
|
26
|
+
require "escalator/config"
|
26
27
|
require 'escalator/asm'
|
27
28
|
require 'escalator/intel_hex'
|
28
29
|
require 'rake/loaders/makefile'
|
30
|
+
require 'fileutils'
|
29
31
|
|
30
32
|
#directory "build"
|
31
33
|
|
@@ -61,6 +63,7 @@ rule %r{^build/.+\.hex} => ['%{^build,asm}X.esc'] do |t|
|
|
61
63
|
$stderr = STDERR
|
62
64
|
end
|
63
65
|
stream = StringIO.new
|
66
|
+
puts "hex #{t.source}"
|
64
67
|
asm = Escalator::Asm.new File.read(t.source)
|
65
68
|
hex = Escalator::IntelHex.new asm.codes
|
66
69
|
File.write(t.name, hex.dump)
|
@@ -77,51 +80,28 @@ rule %r{^build/.+\.gxwm} => ['%{^build,asm}X.esc'] do |t|
|
|
77
80
|
$stderr = STDERR
|
78
81
|
end
|
79
82
|
stream = StringIO.new
|
83
|
+
puts "gxwm #{t.source}"
|
80
84
|
asm = Escalator::Asm.new File.read(t.source)
|
81
85
|
hex = Escalator::IntelHex.new asm.codes
|
82
86
|
File.write(t.name, hex.gxworks_memory_image)
|
83
87
|
end
|
84
88
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
# @refer: https://github.com/rsutphin/handbrake.rb/issues/1
|
89
|
-
begin
|
90
|
-
$stderr = File.open('hb.log', 'w')
|
91
|
-
$stdout = $stderr
|
92
|
-
mkdir_p "build"
|
93
|
-
ensure
|
94
|
-
$stdout = STDOUT
|
95
|
-
$stderr = STDERR
|
96
|
-
end
|
97
|
-
dir = "./asm"
|
98
|
-
stream = StringIO.new
|
99
|
-
sources = Dir.glob("asm/**/*.esc").each do |filename|
|
100
|
-
puts "asm #{filename}"
|
101
|
-
asm = Escalator::Asm.new File.read(filename)
|
102
|
-
dst = File.join("build", File.basename(filename, ".*") + ".lst")
|
103
|
-
File.write(dst, asm.dump_line)
|
104
|
-
end
|
89
|
+
desc "Clean all generated files."
|
90
|
+
task :clean do
|
91
|
+
FileUtils.rm_r "build"
|
105
92
|
end
|
106
93
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
$stdout = STDOUT
|
115
|
-
$stderr = STDERR
|
116
|
-
end
|
117
|
-
dir = "./asm"
|
118
|
-
stream = StringIO.new
|
119
|
-
sources = Dir.glob("asm/**/*.esc").each do |filename|
|
120
|
-
puts "hex #{filename}"
|
121
|
-
asm = Escalator::Asm.new File.read(filename)
|
122
|
-
dst = File.join("build", File.basename(filename, ".*") + ".hex")
|
123
|
-
hex = Escalator::IntelHex.new asm.codes
|
124
|
-
File.write(dst, hex.dump)
|
125
|
-
end
|
94
|
+
@config = Escalator::EscalatorConfig.default
|
95
|
+
|
96
|
+
task :upload => @config.output do
|
97
|
+
u = @config.uploader
|
98
|
+
u.source = @config.output
|
99
|
+
u.upload
|
100
|
+
puts "upload #{u.source}"
|
126
101
|
end
|
127
|
-
|
102
|
+
|
103
|
+
desc "Install program to PLCs."
|
104
|
+
task :plc => :upload do
|
105
|
+
end
|
106
|
+
|
107
|
+
task :default => %w(build/main.lst build/main.hex build/main.gxwm)
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Escalator
|
25
|
+
|
26
|
+
class Uploader
|
27
|
+
|
28
|
+
attr_accessor :protocol
|
29
|
+
attr_accessor :program_area, :interaction_area
|
30
|
+
attr_accessor :source
|
31
|
+
attr_accessor :data
|
32
|
+
|
33
|
+
def initialize options={}
|
34
|
+
@protocol = options[:protocol] if options[:protocol]
|
35
|
+
@program_area = options[:program_area] if options[:program_area]
|
36
|
+
@interaction_area = options[:interaction_area] if options[:interaction_area]
|
37
|
+
end
|
38
|
+
|
39
|
+
STOP_PLC_FLAG = 2 # bit 1
|
40
|
+
CLEAR_PROGRAM_FLAG = 4 # bit 2 require bit 1 on
|
41
|
+
|
42
|
+
CYCLE_RUN_FLAG = 2
|
43
|
+
|
44
|
+
|
45
|
+
def upload
|
46
|
+
# stop plc
|
47
|
+
stop_plc
|
48
|
+
clear_program
|
49
|
+
write_program
|
50
|
+
run_plc
|
51
|
+
end
|
52
|
+
|
53
|
+
def data
|
54
|
+
@data ||= begin
|
55
|
+
hex = IntelHex.load @source
|
56
|
+
hex.codes
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def word_data
|
61
|
+
data.each_slice(2).map do |pair|
|
62
|
+
pair.pack("c*").unpack("n*")
|
63
|
+
end.flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def to_plc_status
|
69
|
+
@to_plc_status ||= interaction_area
|
70
|
+
end
|
71
|
+
|
72
|
+
def from_plc_status
|
73
|
+
@from_plc_status ||= interaction_area.next_device
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def stop_plc
|
78
|
+
@protocol.set_word_to_device STOP_PLC_FLAG, to_plc_status
|
79
|
+
Timeout.timeout(5) do
|
80
|
+
v = @protocol.get_word_from_device from_plc_status
|
81
|
+
break if (v & STOP_PLC_FLAG) != 0
|
82
|
+
sleep 0.1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_program
|
87
|
+
@protocol.set_word_to_device STOP_PLC_FLAG | CLEAR_PROGRAM_FLAG, to_plc_status
|
88
|
+
Timeout.timeout(5) do
|
89
|
+
v = @protocol.get_word_from_device from_plc_status
|
90
|
+
break if (v & CLEAR_PROGRAM_FLAG) != 0
|
91
|
+
sleep 0.1
|
92
|
+
end
|
93
|
+
@protocol.set_word_to_device STOP_PLC_FLAG, to_plc_status
|
94
|
+
end
|
95
|
+
|
96
|
+
def run_plc
|
97
|
+
@protocol.set_word_to_device 0, to_plc_status
|
98
|
+
Timeout.timeout(5) do
|
99
|
+
v = @protocol.get_word_from_device from_plc_status
|
100
|
+
break if (v & CYCLE_RUN_FLAG) != 0
|
101
|
+
sleep 0.1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_program
|
106
|
+
word_data.each_slice(2*1024) do |chunk|
|
107
|
+
@protocol.set_words_to_device chunk, @program_area
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
end
|
data/lib/escalator/version.rb
CHANGED
data/lib/escalator.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# The MIT License (MIT)
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
@@ -9,10 +9,10 @@
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
11
11
|
# the following conditions:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# The above copyright notice and this permission notice shall be
|
14
14
|
# included in all copies or substantial portions of the Software.
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -25,6 +25,7 @@ require "escalator/version"
|
|
25
25
|
require "escalator/cli"
|
26
26
|
require "escalator/asm"
|
27
27
|
require "escalator/intel_hex"
|
28
|
+
require "escalator/config"
|
28
29
|
|
29
30
|
Escalator_root = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
30
31
|
|
@@ -32,4 +33,4 @@ module Escalator
|
|
32
33
|
end
|
33
34
|
|
34
35
|
|
35
|
-
Escalator::CLI.start
|
36
|
+
Escalator::CLI.start
|
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escalator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katsuyoshi Ito
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -76,14 +76,23 @@ files:
|
|
76
76
|
- lib/escalator.rb
|
77
77
|
- lib/escalator/asm.rb
|
78
78
|
- lib/escalator/cli.rb
|
79
|
+
- lib/escalator/config.rb
|
79
80
|
- lib/escalator/intel_hex.rb
|
81
|
+
- lib/escalator/protocol/mitsubishi/mc_protocol.rb
|
82
|
+
- lib/escalator/protocol/mitsubishi/mitsubishi.rb
|
83
|
+
- lib/escalator/protocol/mitsubishi/qdevice.rb
|
84
|
+
- lib/escalator/protocol/protocol.rb
|
80
85
|
- lib/escalator/tasks/build.rb
|
86
|
+
- lib/escalator/uploader.rb
|
81
87
|
- lib/escalator/version.rb
|
88
|
+
- plc/mitsubishi/iq-r/r08/LICENSE
|
89
|
+
- plc/mitsubishi/iq-r/r08/r08.gx3
|
82
90
|
- sample/escalator/sample1.esc
|
83
91
|
- sample/escalator/sample2.esc
|
84
92
|
- sample/escalator/sample2.png
|
85
93
|
- template/escalator/Rakefile
|
86
94
|
- template/escalator/asm/main.esc
|
95
|
+
- template/escalator/config/plc.yml
|
87
96
|
homepage: https://github.com/ito-soft-design/escalator/wiki
|
88
97
|
licenses:
|
89
98
|
- MIT
|