apiotics_factory 1.0.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.
@@ -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: []