apiotics_factory 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,213 @@
1
+ require_relative "../../i2c"
2
+ require_relative "../../i2c/driver"
3
+ =begin
4
+ Generic software I2C Driver based on /sys/class/gpio.
5
+ THIS MODULE WORKS WITH VERY SLOW SPEED ABOUT JUST 1kHz (normaly 100kHz).
6
+ =end
7
+
8
+ class I2CDevice::Driver::GPIO < I2CDevice::Driver::Base
9
+ @@DEBUG = false
10
+
11
+ def self.export(pin) #:nodoc:
12
+ File.open("/sys/class/gpio/export", "w") do |f|
13
+ f.syswrite(pin)
14
+ end
15
+ end
16
+
17
+ def self.unexport(pin) #:nodoc:
18
+ File.open("/sys/class/gpio/unexport", "w") do |f|
19
+ f.syswrite(pin)
20
+ end
21
+ end
22
+
23
+ def self.direction(pin, direction) #:nodoc:
24
+ # [:in, :out, :high, :low].include?(direction) or raise "direction must be :in, :out, :high or :low"
25
+ File.open("/sys/class/gpio/gpio#{pin}/direction", "w") do |f|
26
+ f.syswrite(direction)
27
+ end
28
+ end
29
+
30
+ def self.read(pin) #:nodoc:
31
+ File.open("/sys/class/gpio/gpio#{pin}/value", "r") do |f|
32
+ f.sysread(1).to_i
33
+ end
34
+ end
35
+
36
+ def self.write(pin, val) #:nodoc:
37
+ File.open("/sys/class/gpio/gpio#{pin}/value", "w") do |f|
38
+ f.syswrite(val ? "1" : "0")
39
+ end
40
+ end
41
+
42
+ def self.finalizer(ports) #:nodoc:
43
+ proc do
44
+ ports.each do |pin|
45
+ GPIO.unexport(pin)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Pin-number of SDA
51
+ attr_reader :sda
52
+ # Pin-number of SCL
53
+ attr_reader :scl
54
+ # Clock speed in kHz
55
+ attr_reader :speed
56
+
57
+ # <tt>opts[:sda]</tt> :: [Integer] Pin-number of SDA
58
+ # <tt>opts[:scl]</tt> :: [Integer] Pin-number of SCL
59
+ # <tt>[ opts[:speed] = 1 ]</tt> :: [Integer] Clock speed in kHz
60
+ def initialize(opts={})
61
+ @sda = opts[:sda] or raise "opts[:sda] = [gpio pin number] is required"
62
+ @scl = opts[:scl] or raise "opts[:scl] = [gpio pin number] is required"
63
+ @speed = opts[:speed] || 1 # kHz but insane
64
+ @clock = 1.0 / (@speed * 1000)
65
+
66
+ begin
67
+ GPIO.export(@sda)
68
+ GPIO.export(@scl)
69
+ rescue Errno::EBUSY => e
70
+ end
71
+ ObjectSpace.define_finalizer(self, self.class.finalizer([@scl, @sda]))
72
+ begin
73
+ GPIO.direction(@sda, :high)
74
+ GPIO.direction(@scl, :high)
75
+ GPIO.direction(@sda, :in)
76
+ GPIO.direction(@scl, :in)
77
+ rescue Errno::EACCES => e # writing to gpio after export is failed in a while
78
+ retry
79
+ end
80
+ end
81
+
82
+ # Interface of I2CDevice::Driver
83
+ def i2cget(address, param, length=1)
84
+ ret = ""
85
+ start_condition
86
+ unless write( (address << 1) + 0)
87
+ raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})"
88
+ end
89
+ write(param)
90
+ stop_condition # AVR stucked with SCL low without this (Does not AVR support Sr condition?)
91
+ start_condition
92
+ unless write( (address << 1) + 1)
93
+ raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})"
94
+ end
95
+ length.times do |n|
96
+ ret << read(n != length - 1).chr
97
+ end
98
+ ret
99
+ ensure
100
+ stop_condition
101
+ end
102
+
103
+ # Interface of I2CDevice::Driver
104
+ def i2cset(address, *data)
105
+ sent = 0
106
+ start_condition
107
+ unless write( (address << 1) + 0)
108
+ raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})"
109
+ end
110
+ data.each do |c|
111
+ unless write(c)
112
+ break
113
+ end
114
+ sent += 1
115
+ end
116
+ sent
117
+ ensure
118
+ stop_condition
119
+ end
120
+
121
+ private
122
+
123
+ # Send start condition (or repeated start condition)
124
+ # raise I2CDevice::I2CBUSBusy if SCL line is low
125
+ def start_condition
126
+ p :start_condition if @@DEBUG
127
+ sleep @clock
128
+ GPIO.direction(@sda, :in)
129
+ GPIO.direction(@scl, :in)
130
+ if GPIO.read(@scl) == 0
131
+ raise I2CDevice::I2CBUSBusy, "BUS is busy"
132
+ end
133
+
134
+ sleep @clock / 2
135
+ GPIO.direction(@scl, :high)
136
+ sleep @clock / 2
137
+ GPIO.direction(@sda, :low)
138
+ sleep @clock
139
+ end
140
+
141
+ # Send stop condition.
142
+ def stop_condition
143
+ p :stop_condition if @@DEBUG
144
+ GPIO.direction(@scl, :low)
145
+ sleep @clock / 2
146
+ GPIO.direction(@sda, :low)
147
+ sleep @clock / 2
148
+ GPIO.direction(@scl, :in)
149
+ sleep @clock / 2
150
+ GPIO.direction(@sda, :in)
151
+ sleep @clock / 2
152
+ end
153
+
154
+ # Write one _byte_ to BUS.
155
+ def write(byte)
156
+ p [:write, byte] if @@DEBUG
157
+ GPIO.direction(@scl, :low)
158
+ sleep @clock
159
+
160
+ 7.downto(0) do |n|
161
+ GPIO.direction(@sda, byte[n] == 1 ? :high : :low)
162
+ GPIO.direction(@scl, :in)
163
+ until GPIO.read(@scl) == 1
164
+ # clock streching
165
+ sleep @clock
166
+ end
167
+ sleep @clock
168
+ GPIO.direction(@scl, :low)
169
+ GPIO.write(@sda, false)
170
+ sleep @clock
171
+ end
172
+
173
+ GPIO.direction(@sda, :in)
174
+ GPIO.direction(@scl, :in)
175
+ sleep @clock / 2
176
+ ack = GPIO.read(@sda) == 0
177
+ sleep @clock / 2
178
+ while GPIO.read(@scl) == 0
179
+ sleep @clock
180
+ end
181
+ GPIO.direction(@scl, :low)
182
+ ack
183
+ end
184
+
185
+ # Read one byte from BUS.
186
+ # <tt>ack</tt> :: [true|flase] Send ack for this read.
187
+ # Returns :: [Integer] Byte
188
+ def read(ack=true)
189
+ p [:read, ack] if @@DEBUG
190
+ ret = 0
191
+
192
+ GPIO.direction(@scl, :low)
193
+ sleep @clock
194
+ GPIO.direction(@sda, :in)
195
+
196
+ 8.times do
197
+ GPIO.direction(@scl, :in)
198
+ sleep @clock / 2
199
+ ret = (ret << 1) | GPIO.read(@sda)
200
+ sleep @clock / 2
201
+ GPIO.direction(@scl, :low)
202
+ sleep @clock
203
+ end
204
+
205
+ GPIO.direction(@sda, ack ? :low : :high)
206
+
207
+ GPIO.write(@scl, true)
208
+ sleep @clock
209
+ GPIO.write(@scl, false)
210
+ sleep @clock
211
+ ret
212
+ end
213
+ end
@@ -0,0 +1,60 @@
1
+ require_relative "../../i2c"
2
+ require_relative "../../i2c/driver"
3
+
4
+ class I2CDevice::Driver::I2CDev < I2CDevice::Driver::Base
5
+ # ioctl command
6
+ # Ref. https://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/include/linux/i2c.h
7
+ I2C_RETRIES = 0x0701
8
+ I2C_TIMEOUT = 0x0702
9
+ I2C_SLAVE = 0x0703
10
+ I2C_SLAVE_FORCE = 0x0706
11
+ I2C_TENBIT = 0x0704
12
+ I2C_FUNCS = 0x0705
13
+ I2C_RDWR = 0x0707
14
+ I2C_SMBUS = 0x0720
15
+ I2C_UDELAY = 0x0705
16
+ I2C_MDELAY = 0x0706
17
+
18
+ # This depends on /dev/i2c-* (i2c-dev) feature on Linux. You may load i2c-dev kernel module.
19
+ # <tt>path</tt> :: [String] Path to /dev/i2c-* file.
20
+ # <tt>force</tt> :: [Boolean] Force the driver to read or set values even if the device is in use.
21
+ # This is dangerous, as it can seriously confuse the kernel driver in question.
22
+ # It can also cause i2cget and i2cset to writ to the wrong register.
23
+ # Use at your own risk and only if you know what you're doing.
24
+ #
25
+ # If _path_ is not specified, this method use <tt>Dir.glob("/dev/i2c-*").last</tt> for _path_
26
+ def initialize(path=nil, force=false)
27
+ if path.nil?
28
+ path = Dir.glob("/dev/i2c-*").sort.last
29
+ end
30
+
31
+ unless File.exist?(path)
32
+ raise I2CDevice::I2CIOError, "/dev/i2c-0 is required"
33
+ end
34
+
35
+ @path = path
36
+ @slave_command = force ? I2C_SLAVE_FORCE : I2C_SLAVE
37
+ end
38
+
39
+ # Interface of I2CDevice::Driver
40
+ def i2cget(address, param, length)
41
+ i2c = File.open(@path, "r+")
42
+ i2c.ioctl(@slave_command, address)
43
+ i2c.syswrite(param.chr) unless param.nil?
44
+ ret = i2c.sysread(length)
45
+ i2c.close
46
+ ret
47
+ rescue Errno::EIO => e
48
+ raise I2CDevice::I2CIOError, e.message
49
+ end
50
+
51
+ # Interface of I2CDevice::Driver
52
+ def i2cset(address, *data)
53
+ i2c = File.open(@path, "r+")
54
+ i2c.ioctl(@slave_command, address)
55
+ i2c.syswrite(data.pack("C*"))
56
+ i2c.close
57
+ rescue Errno::EIO => e
58
+ raise I2CDevice::I2CIOError, e.message
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../i2c"
4
+
5
+ module I2CDevice::Driver
6
+ # Abstract class for I2CDevice::Driver
7
+ class Base
8
+ include I2CDevice::Driver
9
+ end
10
+
11
+ # Low-level method for i2cget
12
+ # Driver must implement this.
13
+ # <tt>address</tt> :: [Integer] 7-bit slave address without r/w bit. MSB is always 0.
14
+ # <tt>data</tt> :: [Array[Integer]] Writing bytes array.
15
+ # Returns :: [String] Wrote bytes
16
+ def i2cget(address, param, length=1)
17
+ raise NotImplementedError
18
+ end
19
+
20
+ # Low-level method for i2cset
21
+ # Driver must implement this.
22
+ # <tt>address</tt> :: [Integer] 7-bit slave address without r/w bit. MSB is always 0.
23
+ # <tt>data</tt> :: [Array[Integer]] Writing bytes array.
24
+ # Returns :: [String] Wrote bytes
25
+ def i2cset(address, *data)
26
+ raise NotImplementedError
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ # Generic abstract class for I2C manipulation.
2
+ class I2CDevice
3
+ VERSION = "0.0.6"
4
+
5
+ # Super class of all of this library.
6
+ class I2CException < Exception; end
7
+ class I2CIOError < I2CException; end
8
+ class I2CBUSBusy < I2CIOError; end
9
+
10
+ # Slave address
11
+ attr_accessor :address
12
+
13
+ # <tt>args[:address]</tt> :: [Integer] 7-bit slave address without r/w bit. MSB is always 0.
14
+ # <tt>args[:driver]</tt> :: [I2CDevice::Driver::I2CDev] Instance of driver class
15
+ def initialize(args={})
16
+ if args[:driver].nil?
17
+ require "i2c/driver/i2c-dev"
18
+ args[:driver] = I2CDevice::Driver::I2CDev.new
19
+ end
20
+
21
+ @driver = args[:driver]
22
+ @address = args[:address] or raise I2CException, "args[:address] required"
23
+ end
24
+
25
+ # This method read data from slave with following process:
26
+ #
27
+ # 1. Write `param` to slave
28
+ # 2. re-start
29
+ # 3. Read data until NACK or `length`
30
+ #
31
+ # <tt>param</tt> :: [Integer] First writing byte. Typically, this is slave memory address.
32
+ # <tt>length=1</tt> :: [Integer] Read bytes length
33
+ # Returns :: [String] Bytes
34
+ def i2cget(param, length=1)
35
+ @driver.i2cget(@address, param, length)
36
+ end
37
+
38
+ # Write _data_ to slave.
39
+ # <tt>data</tt> :: [Array[Integer]] Writing bytes array.
40
+ # Returns :: [String] Wrote bytes
41
+ def i2cset(*data)
42
+ @driver.i2cset(@address, *data)
43
+ end
44
+ end
45
+
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apiotics_factory
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Apiotics
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.20'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.20'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ description: A gem to quickly create stub drivers for Apiotics devices.
56
+ email: info@apiotics.com
57
+ executables:
58
+ - apiotics_factory
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - License
63
+ - bin/apiotics_factory
64
+ - lib/apiotics_factory.rb
65
+ - lib/apiotics_factory/clear_credentials.rb
66
+ - lib/apiotics_factory/configuration.rb
67
+ - lib/apiotics_factory/generator.rb
68
+ - lib/apiotics_factory/my_command.rb
69
+ - lib/apiotics_factory/portal.rb
70
+ - lib/apiotics_factory/publish.rb
71
+ - lib/apiotics_factory/underscore.rb
72
+ - lib/apiotics_factory/version.rb
73
+ - lib/templates/apiotics_driver.rb.erb
74
+ - lib/templates/apiotics_interfaces.rb.erb
75
+ - lib/templates/config.json.erb
76
+ - lib/templates/exec.rb.erb
77
+ - lib/templates/grove_pi/grove_pi.rb
78
+ - lib/templates/grove_pi/i2c/device/acm1602ni.rb
79
+ - lib/templates/grove_pi/i2c/device/adt7410.rb
80
+ - lib/templates/grove_pi/i2c/device/aqm0802.rb
81
+ - lib/templates/grove_pi/i2c/device/bmp180.rb
82
+ - lib/templates/grove_pi/i2c/device/d6t-44l.rb
83
+ - lib/templates/grove_pi/i2c/device/hd44780.rb
84
+ - lib/templates/grove_pi/i2c/device/hdc1000.rb
85
+ - lib/templates/grove_pi/i2c/device/mpl115a2.rb
86
+ - lib/templates/grove_pi/i2c/driver.rb
87
+ - lib/templates/grove_pi/i2c/driver/gpio.rb
88
+ - lib/templates/grove_pi/i2c/driver/i2c-dev.rb
89
+ - lib/templates/grove_pi/i2c/i2c.rb
90
+ homepage: https://www.apiotics.com
91
+ licenses:
92
+ - Apiotics Factory License
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: A Gem To Generate Apiotics Drivers
114
+ test_files: []