simatic 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ require 'simatic/types/simatic_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Bool < SimaticType
6
+ LENGTH = 1
7
+
8
+ def self.parse_one raw_data
9
+ super
10
+ raw_data.unpack('b*').first.index('1') ? true : false
11
+ end
12
+
13
+ def self.serialize value
14
+ [value ? 1 : 0].pack('c')
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Byte < SimaticSimpleType
6
+ LENGTH = 1
7
+ PATTERN = 'C'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Char < SimaticSimpleType
6
+ LENGTH = 1
7
+ PATTERN = 'a'
8
+
9
+ def self.serialize value
10
+ raise "Value must be String class (value: #{value})" unless value.kind_of? String
11
+ [value].pack(self::PATTERN)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ require 'time'
2
+ require 'simatic/types/simatic_type'
3
+
4
+ module Simatic
5
+ module Types
6
+ class DateAndTime < SimaticType
7
+ LENGTH = 8
8
+ def self.parse_one raw_value
9
+ super
10
+ array = raw_value.unpack('H*').first
11
+
12
+ year = array[0,2].to_i + (array[0,2].to_i <= 89 ? 2000 : 1900)
13
+ month = array[2,2].to_i
14
+ day = array[4,2].to_i
15
+ hour = array[6,2].to_i
16
+ min = array[8,2].to_i
17
+ sec = array[10,2].to_i
18
+
19
+ microsecond = array[12,3].to_i * 1000
20
+
21
+ Time.utc(year, month, day, hour, min, sec, microsecond)
22
+ end
23
+
24
+ def self.serialize value
25
+ raise "Value must be Time class" unless value.kind_of? Time
26
+
27
+ hex_string =
28
+ '%02d' % (value.year - ((value.year >= 2000) ? 2000 : 1900)) +
29
+ '%02d' % value.month +
30
+ '%02d' % value.day +
31
+ '%02d' % value.hour +
32
+ '%02d' % value.min +
33
+ '%02d' % value.sec +
34
+ '%03d' % (value.usec/1000.0).to_i +
35
+ '%01d' % (value.wday+1)
36
+
37
+ # puts hex_string
38
+
39
+ [hex_string].pack('H*')
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Dint < SimaticSimpleType
6
+ LENGTH = 4
7
+ PATTERN = 'l>'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Dword < SimaticSimpleType
6
+ LENGTH = 4
7
+ PATTERN = 'L>'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ require 'date'
2
+ require 'simatic/types/word'
3
+
4
+ module Simatic
5
+ module Types
6
+ class IECDate < Word
7
+ LENGTH = 2
8
+ def self.parse_one raw_value
9
+ days = super # days since 1990-01-01
10
+ Date.new(1990,1,1)+days
11
+ end
12
+
13
+ def self.serialize value
14
+ raise "Value #{value} must be Date class instead of #{value.class}" unless value.kind_of? Date
15
+ days = value - Date.new(1990,01,01)
16
+ super days
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'simatic/types/dword'
2
+
3
+ module Simatic
4
+ module Types
5
+ class IECTime < Dword
6
+ def self.parse_one raw_value
7
+ super / 1000.0 # seconds
8
+ end
9
+
10
+ def self.serialize value
11
+ raise "Value must be numeric in seconds" unless value.kind_of? Numeric
12
+ super (value * 1000.0).to_i # convert to milliseconds and write
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Int < SimaticSimpleType
6
+ LENGTH = 2
7
+ PATTERN = 's>'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Real < SimaticSimpleType
6
+ LENGTH = 4
7
+ PATTERN = 'g'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,47 @@
1
+ require 'simatic/types/simatic_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class S5time < SimaticType
6
+ LENGTH = 2
7
+ def self.parse_one raw_value
8
+ super
9
+ hex_string = raw_value.unpack('h*').first
10
+ time_base = hex_string[0].to_i
11
+ time_value = hex_string[1,3].to_i
12
+ case time_base
13
+ when 0 # 10 ms
14
+ time_value * 100.0
15
+ when 1 # 100 ms
16
+ time_value * 10.0
17
+ when 2 # 1 s
18
+ time_value * 1.0
19
+ when 3 # 10 s
20
+ time_value / 10.0
21
+ end
22
+ end
23
+
24
+ def self.serialize value
25
+ raise "Value must be numeric in seconds" unless value.kind_of? Numeric
26
+
27
+ params = case value.round(2)
28
+ when 0.00...9.99
29
+ [0, 100.0]
30
+ when 9.99...99.9
31
+ [1, 10.0]
32
+ when 99.9...999.0
33
+ [2, 1.0]
34
+ when 999.0..9990.0
35
+ [3, 0.1]
36
+ else
37
+ raise "Value is to large"
38
+ end
39
+
40
+ time_base = params.first.to_s
41
+ time_value = (value*params.last).to_i.to_s
42
+
43
+ [time_base+time_value].pack('h*')
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ require 'simatic/types/simatic_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class S7String < SimaticType
6
+ def initialize value, size = nil
7
+ @size = size
8
+ @value = value
9
+ end
10
+
11
+ def self.serialize value, size
12
+ raise "Value must be String class" unless value.kind_of? String
13
+ size = size || value.length
14
+ [size, value.length, value].pack("CCa#{size}x")
15
+ end
16
+
17
+ def serialize
18
+ if @value.kind_of? Array
19
+ @value.map { |single_val| self.class.serialize single_val, @size }
20
+ else
21
+ self.class.serialize @value, @size
22
+ end
23
+ end
24
+
25
+ def self.parse_one raw_value
26
+ res = raw_value.unpack('CCa*')
27
+
28
+ buf_size = res[0]
29
+ string_size = res[1]
30
+ string = res[2]
31
+
32
+ raise "S7String is broken, cant parse" if buf_size.nil? || string_size.nil? || string.nil? || buf_size < string_size
33
+
34
+ string[0, string_size]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ require 'simatic/types/simatic_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class SimaticSimpleType < SimaticType
6
+ def self.parse_one raw_value
7
+ super
8
+ raw_value.unpack(self::PATTERN).first
9
+ end
10
+
11
+ def self.serialize value
12
+ raise "Value must be numeric (value: #{value} type: #{value.class})" unless value.kind_of? Numeric
13
+
14
+ # puts "class #{self::PATTERN}"
15
+ # puts " PATTERN #{self::PATTERN} LENGTH #{self::LENGTH}"
16
+ [value].pack(self::PATTERN)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ module Simatic
2
+ module Types
3
+ class SimaticType
4
+ def initialize value
5
+ @value = value
6
+ end
7
+
8
+ def self.parse raw_data
9
+ if raw_data.kind_of? Array
10
+ # puts "raw_data #{raw_data}"
11
+ raw_data.map { |raw_value| self.parse_one raw_value }
12
+ else
13
+ parse_one raw_data
14
+ end
15
+ end
16
+
17
+ def self.parse_one raw_value
18
+ raw_value_length = raw_value.length
19
+ if raw_value_length != self::LENGTH
20
+ raise "Cant parse, cause raw data length #{raw_value_length} (must be #{self::LENGTH})."
21
+ end
22
+ raw_value
23
+ end
24
+
25
+ def serialize
26
+ if @value.kind_of? Array
27
+ @value.map { |single_val| self.class.serialize single_val }
28
+ else
29
+ self.class.serialize @value
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ require 'simatic/types/iec_time'
2
+
3
+ module Simatic
4
+ module Types
5
+ class TimeOfDay < IECTime
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'simatic/types/simatic_simple_type'
2
+
3
+ module Simatic
4
+ module Types
5
+ class Word < SimaticSimpleType
6
+ LENGTH = 2
7
+ PATTERN = 'S>'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Simatic
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simatic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simatic"
8
+ spec.version = Simatic::VERSION
9
+ spec.authors = ["Konstantin Ryzhov"]
10
+ spec.email = ["konstantin.ryzhov@gmail.com"]
11
+
12
+ spec.summary = %q{Ruby library for Siemens Simatic S7-300 PLC data exchange.}
13
+ spec.description = %q{Ruby library for Siemens Simatic S7-300 PLC data exchange.}
14
+ spec.homepage = "https://github.com/konstantin-ryzhov/ruby_s7plc"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.executables = ['read']
19
+ spec.require_paths = ["lib"]
20
+
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
23
+ end
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.9"
26
+ # spec.add_development_dependency "rake", "~> 10.0"
27
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simatic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Konstantin Ryzhov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ description: Ruby library for Siemens Simatic S7-300 PLC data exchange.
28
+ email:
29
+ - konstantin.ryzhov@gmail.com
30
+ executables:
31
+ - read
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - Gemfile
37
+ - README.md
38
+ - Rakefile
39
+ - bin/read
40
+ - lib/simatic.rb
41
+ - lib/simatic/memory_mapper.rb
42
+ - lib/simatic/plc.rb
43
+ - lib/simatic/sessions.rb
44
+ - lib/simatic/sessions/exchange_session.rb
45
+ - lib/simatic/sessions/open_session.rb
46
+ - lib/simatic/sessions/read_session.rb
47
+ - lib/simatic/sessions/session.rb
48
+ - lib/simatic/sessions/setup_session.rb
49
+ - lib/simatic/sessions/write_session.rb
50
+ - lib/simatic/types.rb
51
+ - lib/simatic/types/bool.rb
52
+ - lib/simatic/types/byte.rb
53
+ - lib/simatic/types/char.rb
54
+ - lib/simatic/types/date_and_time.rb
55
+ - lib/simatic/types/dint.rb
56
+ - lib/simatic/types/dword.rb
57
+ - lib/simatic/types/iec_date.rb
58
+ - lib/simatic/types/iec_time.rb
59
+ - lib/simatic/types/int.rb
60
+ - lib/simatic/types/real.rb
61
+ - lib/simatic/types/s5_time.rb
62
+ - lib/simatic/types/s7_string.rb
63
+ - lib/simatic/types/simatic_simple_type.rb
64
+ - lib/simatic/types/simatic_type.rb
65
+ - lib/simatic/types/time_of_day.rb
66
+ - lib/simatic/types/word.rb
67
+ - lib/simatic/version.rb
68
+ - simatic.gemspec
69
+ homepage: https://github.com/konstantin-ryzhov/ruby_s7plc
70
+ licenses:
71
+ - MIT
72
+ metadata:
73
+ allowed_push_host: https://rubygems.org
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.2.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Ruby library for Siemens Simatic S7-300 PLC data exchange.
94
+ test_files: []