apiotics_factory 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57b5011c4903e6ef99d831b9ae85710287b6acc5
4
+ data.tar.gz: 25d2c749da32bdf104eada7bf53eb272fcaa8eb4
5
+ SHA512:
6
+ metadata.gz: 12b1eb3b83b55b53141a60a7b43515c57ef152530c532f67fdcacc6be0fff2bbfc6e8114dc929c53869004fa20e025f86a0c0fcc554f903f0796b8c4354a1fac
7
+ data.tar.gz: 5efec3d5df04768067213d6a421f7783846f3da221d5739e01aebc36f70f9fd9e3555df87e2de5721f2ba7925db0319e76cce2d65e082fb2d2be818d0fa33e7f
data/License ADDED
@@ -0,0 +1,9 @@
1
+ Copyright 2018 MicroArx Corporation
2
+
3
+ Permission is hereby granted to use the Apiotics_Factory Gem (the "Gem") to create driver software. Software created using the Gem or with its assistance may only be distributed using Apiotics websites such as portal.apiotics.com, and may only be installed on third party devices (devices other than those belonging to the developer of the driver software or to MicroArx Corporation) using Apiotics development tools such as the Apiotics Gem. Software created using this Gem or with the assistance of this Gem may only be installed on third party devices which are running operating system images or firmware provided by Apiotics or distributed via the Apiotics websites and installed with Apiotics development tools.
4
+
5
+ Permission is not granted to install or use this software to subvert the Apiotics website, development tools, operating system images or firmware with intent to install driver software on operating systems or firmware other than those provided by Apiotics and installed with Apiotics development tools, to use Apiotics software or development tools in any way without paying the subscription plan fees as published on portal.apiotics.com, or with any other intent or purpose.
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/apiotics_factory'
3
+ ApioticsFactory::MyCommand.start
@@ -0,0 +1,25 @@
1
+ require 'thor/group'
2
+
3
+ module ApioticsFactory
4
+ class ClearCredentials < Thor::Group
5
+
6
+ include Thor::Actions
7
+
8
+ desc "Deletes vendor and portal credentials."
9
+
10
+ def self.source_root
11
+ Dir.pwd
12
+ end
13
+
14
+ def delete_credentials
15
+ config_dir = File.dirname(__FILE__).chomp("/lib/apiotics_factory") + "/var"
16
+ #puts config_dir
17
+ if File.exist?(config_dir + "/config.json")
18
+ puts "Deleting config file #{config_dir}" + "/config.json"
19
+ File.delete(config_dir + "/config.json")
20
+ end
21
+ end
22
+
23
+
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ module ApioticsFactory
2
+ class Configuration
3
+
4
+ attr_accessor :public_key, :private_key, :portal, :interface_kinds
5
+
6
+ def initialize
7
+ @public_key = nil
8
+ @private_key = nil
9
+ @portal = "https://portal.apiotics.com/"
10
+ @interface_kinds = {
11
+ "string" => "string",
12
+ "text" => "string",
13
+ "smallint" => "integer",
14
+ "integer" => "integer",
15
+ "bigint" => "integer",
16
+ "float" => "float",
17
+ "boolean" => "boolean",
18
+ "enum" => "string",
19
+ "json" => "json",
20
+ "uint8_t" => "integer",
21
+ "uint16_t" => "integer",
22
+ "uint32_t" => "integer",
23
+ "int16_t" => "integer",
24
+ "int32_t" => "integer",
25
+ "int64_t" => "integer"
26
+ }
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,133 @@
1
+
2
+ require 'json'
3
+ require 'thor/group'
4
+ require 'apiotics_factory/underscore'
5
+
6
+ module ApioticsFactory
7
+ class Generator < Thor::Group
8
+
9
+ include Thor::Actions
10
+
11
+ argument :id
12
+ class_option :library, type: :string, default: "grove_pi"
13
+
14
+ desc "Generates an Apiotics driver. Requires the driver name and driver id (from the portal) as arguments."
15
+
16
+ def self.source_root
17
+ Dir.pwd
18
+ end
19
+
20
+ def fetch_info
21
+ config_dir = File.dirname(__FILE__).chomp("/lib/apiotics_factory") + "/var"
22
+ #puts config_dir
23
+ if File.exist?(config_dir + "/config.json")
24
+ puts "Found config file #{config_dir}" + "/config.json"
25
+ config = JSON.parse(File.read(config_dir + "/config.json"))
26
+ ApioticsFactory.configuration.public_key = config["public_key"]
27
+ ApioticsFactory.configuration.private_key = config["private_key"]
28
+ ApioticsFactory.configuration.portal = config["portal"]
29
+ else
30
+ say("Please enter your vendor public key from the Apiotics Portal.")
31
+ ApioticsFactory.configuration.public_key = ask("Vendor Public Key: ")
32
+ say("Please enter your vendor private key from the Apiotics Portal.")
33
+ ApioticsFactory.configuration.private_key = ask("Vendor Private Key: ")
34
+ say("Please confirm the Apiotics Portal web address.")
35
+ ApioticsFactory.configuration.portal = ask("Portal: ", default: "https://portal.apiotics.com/")
36
+ unless ApioticsFactory.configuration.portal[-1] == "/"
37
+ ApioticsFactory.configuration.portal = ApioticsFactory.configuration.portal + "/"
38
+ end
39
+ config = {
40
+ "public_key" => ApioticsFactory.configuration.public_key,
41
+ "private_key" => ApioticsFactory.configuration.private_key,
42
+ "portal" => ApioticsFactory.configuration.portal
43
+ }
44
+ #puts config
45
+ unless Dir.exist?(config_dir)
46
+ Dir.mkdir(config_dir)
47
+ end
48
+ File.write(config_dir + "/config.json", config.to_json)
49
+ end
50
+ puts "Fetching driver data from the portal..."
51
+ data = ApioticsFactory::Portal.driver(id)
52
+ #puts data
53
+ data = JSON.parse(data)
54
+ @driver_name = data["name"]
55
+ @status = true
56
+ unless data.keys.include?("errors")
57
+ @interfaces = data["interfaces"]# a hash with "read", "write" and "all". "read" is an array of read and read/write interfaces. "write" is an array of write and read/write interfaces. "all" is a hash with interface names as the keys.
58
+ # the value is a hash with an "accessor" key and a "type" key
59
+ @delay_default = data["delay_default"]
60
+ if @delay_default == nil
61
+ @delay_default = Hash.new
62
+ @interfaces["read"].each do |interface|
63
+ @delay_default[interface] = 1.0
64
+ end
65
+ end
66
+ else
67
+ @status = false
68
+ say("#{data['errors']['detail']}")
69
+ end
70
+ @template_path = File.dirname(__FILE__).chomp("/apiotics_factory") + "/templates"
71
+ end
72
+
73
+ #need to account for the case when the portal call fails.
74
+
75
+ def create_config_file
76
+ if @status == true
77
+ puts "Creating driver config file..."
78
+ template("#{@template_path}/config.json.erb", "#{@driver_name.downcase}/config.json")
79
+ end
80
+ end
81
+
82
+ def create_exec_file
83
+ if @status == true
84
+ puts "Creating driver executable..."
85
+ @exec_name = @driver_name
86
+ @exec_name = @exec_name.gsub(/::/, '/')
87
+ @exec_name = @exec_name.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
88
+ @exec_name = @exec_name.gsub(/([a-z\d])([A-Z])/,'\1_\2')
89
+ @exec_name = @exec_name.tr("-", "_")
90
+ @exec_name = @exec_name.downcase
91
+ template("#{@template_path}/exec.rb.erb", "#{@driver_name.downcase}/rootfs/#{@driver_name.downcase}")
92
+ chmod "#{@driver_name.downcase}/rootfs/#{@driver_name.downcase}", 0755
93
+ end
94
+ end
95
+
96
+ def create_apiotics_driver
97
+ if @status == true
98
+ puts "Creating apiotics_driver.rb"
99
+ template("#{@template_path}/apiotics_driver.rb.erb", "#{@driver_name.downcase}/rootfs/apiotics_driver.rb")
100
+ end
101
+ end
102
+
103
+ def create_interface_file
104
+ if @status == true
105
+ "Creating #{@exec_name}.rb"
106
+ template("#{@template_path}/apiotics_interfaces.rb.erb", "#{@driver_name.downcase}/rootfs/#{@exec_name}.rb")
107
+ end
108
+ end
109
+
110
+ def create_library
111
+ if @status == true
112
+ if options[:library] == "grove_pi"
113
+ puts "Adding GrovePi library..."
114
+ insert_into_file "#{@driver_name.downcase}/rootfs/#{@exec_name}.rb", "require_relative './grove_pi.rb'\n", :after => "require_relative './apiotics_driver'\n"
115
+ copy_file "#{@template_path}/grove_pi/grove_pi.rb", "#{@driver_name.downcase}/rootfs/grove_pi.rb"
116
+ copy_file "#{@template_path}/grove_pi/i2c/i2c.rb", "#{@driver_name.downcase}/rootfs/i2c.rb"
117
+ copy_file "#{@template_path}/grove_pi/i2c/driver.rb", "#{@driver_name.downcase}/rootfs/i2c/driver.rb"
118
+ copy_file "#{@template_path}/grove_pi/i2c/driver/i2c-dev.rb", "#{@driver_name.downcase}/rootfs/i2c/driver/i2c-dev.rb"
119
+ copy_file "#{@template_path}/grove_pi/i2c/driver/gpio.rb", "#{@driver_name.downcase}/rootfs/i2c/driver/gpio.rb"
120
+ directory "#{@template_path}/grove_pi/i2c/device", "#{@driver_name.downcase}/rootfs/i2c/device"
121
+ end
122
+ end
123
+ end
124
+
125
+ def create_vendor
126
+ if @status == true
127
+ puts "Creating vendor directory..."
128
+ empty_directory "#{@driver_name.downcase}/rootfs/vendor"
129
+ end
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,15 @@
1
+ require "thor"
2
+
3
+ module ApioticsFactory
4
+ class MyCommand < Thor
5
+ # register(class_name, subcommand_alias, usage_list_string, description_string)
6
+ register(ApioticsFactory::Generator, "generate", "generate <DriverId>", "Generate Apiotics Driver. You can find the Id for your driver on the portal. If your driver does not yet exist on the portal, create it there first.")
7
+
8
+ # register(class_name, subcommand_alias, usage_list_string, description_string)
9
+ register(ApioticsFactory::Publish, "publish", "publish <DriverId>", "Publish Apiotics Driver. You can find the Id for your driver on the portal. If your driver does not yet exist on the portal, create it there first.")
10
+
11
+ # register(class_name, subcommand_alias, usage_list_string, description_string)
12
+ register(ApioticsFactory::ClearCredentials, "clear_credentials", "clear_credentials", "Delete vendor and portal information from the Gem.")
13
+
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ require 'httparty'
2
+ require 'json'
3
+ require 'rest-client'
4
+ #require 'resolv-replace'
5
+
6
+ module ApioticsFactory
7
+ class Portal
8
+
9
+ def self.driver(driver)
10
+ puts "portal: #{ApioticsFactory.configuration.portal}"
11
+ puts "public_key: #{ApioticsFactory.configuration.public_key}"
12
+ puts "private_key: #{ApioticsFactory.configuration.private_key}"
13
+ puts "id: #{driver}"
14
+ json = HTTParty.post("#{ApioticsFactory.configuration.portal}api/driver", :query => {:public_key => ApioticsFactory.configuration.public_key, :private_key => ApioticsFactory.configuration.private_key, driver: driver}).body
15
+ end
16
+
17
+ def self.driver_version(driver)
18
+ json = HTTParty.post("#{ApioticsFactory.configuration.portal}api/driver_version", :query => {:public_key => ApioticsFactory.configuration.public_key, :private_key => ApioticsFactory.configuration.private_key, driver: driver}).body
19
+ end
20
+
21
+ def self.publish_driver(driver, path)
22
+ payload = {
23
+ :multipart => true,
24
+ :file => File.open(path, 'rb'),
25
+ :public_key => ApioticsFactory.configuration.public_key,
26
+ :private_key => ApioticsFactory.configuration.private_key,
27
+ :driver => driver
28
+ }
29
+ r = RestClient.post("#{ApioticsFactory.configuration.portal}api/upload_driver", payload)
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,83 @@
1
+
2
+ require 'json'
3
+ require 'thor/group'
4
+
5
+ module ApioticsFactory
6
+ class Publish < Thor::Group
7
+
8
+ include Thor::Actions
9
+
10
+ argument :id
11
+ class_option :path
12
+
13
+ desc "Publishes an Apiotics driver. Requires the driver name and driver id (from the portal) as arguments."
14
+
15
+ def self.source_root
16
+ if :path == nil
17
+ Dir.pwd
18
+ else
19
+ :path
20
+ end
21
+ end
22
+
23
+ def fetch_info
24
+ config_dir = File.dirname(__FILE__).chomp("/lib/apiotics_factory") + "/var"
25
+
26
+ if File.exist?(config_dir + "/config.json")
27
+ config = JSON.parse(File.read(config_dir + "/config.json"))
28
+ ApioticsFactory.configuration.public_key = config["public_key"]
29
+ ApioticsFactory.configuration.private_key = config["private_key"]
30
+ ApioticsFactory.configuration.portal = config["portal"]
31
+ else
32
+ say("Please enter your vendor public key from the Apiotics Portal.")
33
+ ApioticsFactory.configuration.public_key = ask("Vendor Public Key: ")
34
+ say("Please enter your vendor private key from the Apiotics Portal.")
35
+ ApioticsFactory.configuration.private_key = ask("Vendor Private Key: ")
36
+ say("Please confirm the Apiotics Portal web address.")
37
+ ApioticsFactory.configuration.portal = ask("Portal: ", default: "https://portal.apiotics.com/")
38
+ unless ApioticsFactory.configuration.portal[-1] == "/"
39
+ ApioticsFactory.configuration.portal = ApioticsFactory.configuration.portal + "/"
40
+ end
41
+ config = {
42
+ "public_key" => ApioticsFactory.configuration.public_key,
43
+ "private_key" => ApioticsFactory.configuration.private_key,
44
+ "portal" => ApioticsFactory.configuration.portal
45
+ }
46
+ unless Dir.exist?(config_dir)
47
+ Dir.mkdir(config_dir)
48
+ end
49
+ File.write(config_dir + "/config.json", config.to_json)
50
+ end
51
+ data = ApioticsFactory::Portal.driver_version(id)
52
+ #puts data
53
+ data = JSON.parse(data)
54
+ @driver_name = data["name"]
55
+ @status = true
56
+ unless data.keys.include?("errors")
57
+ @version = data["version"]
58
+ else
59
+ @status = false
60
+ say("#{data['errors']['detail']}")
61
+ end
62
+ end
63
+
64
+ #need to account for the case where the portal call fails.
65
+
66
+ def publish
67
+ if @status == true
68
+ run("tar -cvzf #{@driver_name.downcase}-#{@version}.tgz ./#{@driver_name.downcase}")
69
+ say("Uploading driver to the portal...")
70
+ path = Dir.pwd + "/#{@driver_name.downcase}-#{@version}.tgz"
71
+ response = ApioticsFactory::Portal.publish_driver(id, path)
72
+ say("Cleaning up...")
73
+ run("rm #{@driver_name.downcase}-#{@version}.tgz")
74
+ if response.code == 200
75
+ say("Upload successful")
76
+ else
77
+ say("Upload not successful")
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,11 @@
1
+ module ApioticsFactory
2
+ class String
3
+ def underscore
4
+ self.gsub(/::/, '/').
5
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
6
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
7
+ tr("-", "_").
8
+ downcase
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module ApioticsFactory
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ require "apiotics_factory/configuration"
2
+ require "apiotics_factory/version"
3
+ require "apiotics_factory/portal"
4
+ require "apiotics_factory/underscore"
5
+ require "apiotics_factory/generator"
6
+ require "apiotics_factory/publish"
7
+ require "apiotics_factory/clear_credentials"
8
+ require "apiotics_factory/my_command"
9
+
10
+ module ApioticsFactory
11
+
12
+ class << self
13
+ attr_accessor :configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ def self.reset
21
+ @configuration = Configuration.new
22
+ end
23
+
24
+ def self.configure
25
+ yield(configuration)
26
+ end
27
+
28
+ end
@@ -0,0 +1,244 @@
1
+ class ApioticsDriver
2
+ require 'socket'
3
+ require 'json'
4
+
5
+ attr_accessor :debug_enable
6
+
7
+ def initialize
8
+ if File.file?("driver_config.json")
9
+ @config = JSON.parse(File.read("driver_config.json"))
10
+ if @config.keys.include?("log_file")
11
+ $stdout = File.open( @config["log_file"], 'a' )
12
+ $stdout.sync = true
13
+ end
14
+ if @config.keys.include?("driver_name")
15
+ @driver_name = @config["driver_name"]
16
+ else
17
+ @driver_name = "Unspecified"
18
+ end
19
+ puts "initializing #{@driver_name}"
20
+ @socket_address = "localhost"
21
+ @socket_port = 8001
22
+ @debug_enable = false
23
+ @delay = <%= @delay_default %>
24
+ @threads = {}
25
+ @state = {}
26
+ @read_interfaces = <%= @interfaces["read"] %>
27
+ @write_interfaces = <%= @interfaces["write"] %>
28
+ @interfaces = <%= @interfaces["all"] %>
29
+ @interface_kinds = {
30
+ "string" => "string",
31
+ "text" => "string",
32
+ "smallint" => "integer",
33
+ "integer" => "integer",
34
+ "bigint" => "integer",
35
+ "float" => "float",
36
+ "boolean" => "boolean",
37
+ "enum" => "string",
38
+ "json" => "json",
39
+ "uint8_t" => "integer",
40
+ "uint16_t" => "integer",
41
+ "uint32_t" => "integer",
42
+ "int16_t" => "integer",
43
+ "int32_t" => "integer",
44
+ "int64_t" => "integer"
45
+ }
46
+ @connected = false
47
+ @msg_queue = []
48
+ @flush_active = false
49
+ end
50
+ end
51
+
52
+ def send_msg(value)
53
+ interface = caller_locations(1,1)[0].label
54
+ if interface[0..5] == "write_"
55
+ interface = interface[6..-1]
56
+ elsif interface[0..4] == "read_"
57
+ interface = interface[5..-1]
58
+ end
59
+ unless interface == "port"
60
+ @state[interface] = value
61
+ else
62
+ @state[interface] = Kernel.const_get(value)
63
+ end
64
+ msg = {
65
+ "action" => "set-complete",
66
+ "driver" => @driver_name,
67
+ "interface" => {
68
+ interface => value
69
+ }
70
+ }
71
+ self.deliver_msg(msg)
72
+ end
73
+
74
+ def send_msg2(interface, value)
75
+ if interface[0..5] == "write_"
76
+ interface = interface[6..-1]
77
+ elsif interface[0..4] == "read_"
78
+ interface = interface[5..-1]
79
+ end
80
+ unless interface == "port"
81
+ @state[interface] = value
82
+ else
83
+ @state[interface] = Kernel.const_get(value)
84
+ end
85
+ msg = {
86
+ "action" => "set-complete",
87
+ "driver" => @driver_name,
88
+ "interface" => {
89
+ interface => value
90
+ }
91
+ }
92
+ self.deliver_msg(msg)
93
+ end
94
+
95
+ def get_msg
96
+ puts "Starting get message..."
97
+ #begin
98
+ Thread::abort_on_exception = true
99
+ Thread.new do
100
+ if @connected == false
101
+ @socket = TCPSocket.open( @socket_address, @socket_port )
102
+ connect_msg = {
103
+ "action" => "connect",
104
+ "driver" => @driver_name
105
+ }
106
+ puts "Sending #{connect_msg.to_json}..."
107
+ @socket.puts connect_msg.to_json
108
+ @connected = true
109
+ end
110
+ while response = @socket.gets.chomp
111
+ if @debug_enable == true
112
+ puts "Received message #{response}..."
113
+ end
114
+ msg = JSON.parse(response)
115
+ msg = msg["interface"]
116
+ if msg != nil
117
+ msg.each do |k,v|
118
+ if k != "delay" && k != "port" && @write_interfaces.include?(k)
119
+ method = "write_#{k}"
120
+ v = self.type_cast(k,v)
121
+ if @interfaces.keys.include?("port")
122
+ unless @state["port"] == nil
123
+ self.send(method, v)
124
+ else
125
+ self.msg_queue(method, v)
126
+ end
127
+ else
128
+ self.send(method, v)
129
+ end
130
+ elsif k == "delay"
131
+ if v.is_a?(String)
132
+ v = JSON.parse(v)
133
+ end
134
+ v.each do |key, val|
135
+ @delay[key] = val.to_f
136
+ self.send_msg2(k,v)
137
+ end
138
+ else
139
+ self.send_msg2(k,v)
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ #rescue => e
146
+ # puts e.message
147
+ # puts e.backtrace
148
+ # get_msg
149
+ #end
150
+ end
151
+
152
+ def msg_queue(method, v)
153
+ array = [method, v]
154
+ @msg_queue << array
155
+ if @flush_active == false
156
+ self.flush_queue
157
+ end
158
+ end
159
+
160
+ def flush_queue
161
+ Thread::abort_on_exception = true
162
+ Thread.new do
163
+ @flush_active = true
164
+ while @msg_queue.length > 0
165
+ entry = @msg_queue[0]
166
+ if @state["port"] != nil
167
+ self.send(entry[0], entry[1])
168
+ @msg_queue = @msg_queue - [entry]
169
+ end
170
+ sleep 0.1
171
+ end
172
+ @flush_active = false
173
+ end
174
+ end
175
+
176
+ def read_msg
177
+ puts "starting read message"
178
+ @delay.each do |k,v|
179
+ unless @threads.keys.include?(k) || k == "port" || k == "delay"
180
+ #begin
181
+ Thread::abort_on_exception = true
182
+ t = Thread.new do
183
+ while true
184
+ unless @state["port"] == nil
185
+ read_function = "read_#{k}"
186
+ self.send(read_function)
187
+ sleep @delay[k]
188
+ end
189
+ end
190
+ end
191
+ #rescue => e
192
+ # if @debug_enable == true
193
+ # puts e.message
194
+ # puts e.backtrace
195
+ # end
196
+ # @threads.delete(k)
197
+ # read_msg
198
+ #end
199
+ @threads[k] = t
200
+ end
201
+ end
202
+ end
203
+
204
+
205
+ def close
206
+ msg = {
207
+ "action" => "disconnect"
208
+ }
209
+ msg = msg.to_json
210
+ self.deliver_msg(msg)
211
+ end
212
+
213
+ def type_cast(k, v)
214
+ if @interfaces[k]["type"] == "boolean"
215
+ if v.is_a?(String)
216
+ if v == "true"
217
+ v = true
218
+ elsif v == "false"
219
+ v = false
220
+ end
221
+ end
222
+ end
223
+ if @interfaces[k]["type"] == "float"
224
+ if v.is_a?(String)
225
+ v = v.to_f
226
+ end
227
+ end
228
+ if @interface_kinds[@interfaces[k]["type"]] == "integer"
229
+ if v.is_a?(String)
230
+ v = v.to_i
231
+ end
232
+ end
233
+ return v
234
+ end
235
+
236
+ def deliver_msg(msg)
237
+ if @debug_enable == true
238
+ puts "Sending Message: #{msg}\n"
239
+ end
240
+ jmsg = msg.to_json
241
+ @socket.puts(jmsg)
242
+ end
243
+
244
+ end
@@ -0,0 +1,33 @@
1
+ require_relative './apiotics_driver'
2
+ class <%= @driver_name %> < ApioticsDriver
3
+
4
+ def initialize
5
+ super
6
+ self.get_msg
7
+ sleep 5
8
+ self.read_msg
9
+ end
10
+
11
+ # the @state variable is available to you. For each interface you have, you can get it's current
12
+ # value by reading @state["interface_name"].
13
+ <% @interfaces["all"].each do |k, v|%>
14
+ <% unless k == "port" || k == "delay" %>
15
+ <% if v["accessor"] == "write only" || v["accessor"] == "read/write" %>
16
+ def <%= "write_#{k}(#{v["type"]})"%>
17
+
18
+ # Your hardware specific logic to set the state of your <%= k %> hardware goes here based on the value of the <%= v['type'] %> variable.
19
+
20
+ self.send_msg(<%= v["type"]%>) # This line sends a confirmation message back to the web application noting that the operation is complete.
21
+ end
22
+ <% end %>
23
+ <% if v["accessor"] == "read only" || v["accessor"] == "read/write" %>
24
+ def <%= "read_#{k}"%>
25
+
26
+ # Your hardware specific logic here should read a value from your <%= k %> hardware, and set the <%= v["type"] %> variable appropriately.
27
+
28
+ self.send_msg(<%= v["type"]%>) # This line sends the value in the <%= v["type"] %> variable to the web application.
29
+ end
30
+ <% end %>
31
+ <% end %>
32
+ <% end %>
33
+ end