apiotics 0.1.141 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/apiotics.rb +1 -0
- data/lib/apiotics/configuration.rb +4 -1
- data/lib/apiotics/encrypt_decrypt.rb +19 -0
- data/lib/apiotics/extract.rb +1 -1
- data/lib/apiotics/hardware.rb +223 -5
- data/lib/apiotics/insert.rb +1 -1
- data/lib/apiotics/portal.rb +36 -3
- data/lib/apiotics/server.rb +221 -119
- data/lib/apiotics/version.rb +1 -1
- data/lib/generators/apiotics/controller/controller_generator.rb +1 -1
- data/lib/generators/apiotics/script/script_generator.rb +1 -0
- data/lib/generators/apiotics/script/templates/install_firmware.rake +2 -2
- data/lib/generators/apiotics/script/templates/set_wifi.rake +13 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 185f239908233c662b8a5abccb2ae33dedc35ccb
|
4
|
+
data.tar.gz: '08ffbf5c91966a2923a9d03bebf966b3c4fadbb8'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 656e760acebbc1ca43fd5c6b0e5f01c82815e4004a1dee246793a3ad0964fd4393a0465324075a573b489154350d8d50167a2beea7e816df9d140b7c3a9b04c2
|
7
|
+
data.tar.gz: cca8670e92c02c334c731b0a0babd0bc3037d494b6663777613b2c59ff8c231a24f1a5aa9a470eba36fd205385f978b399c339a76801dcaaa7f37cecbdf141ca
|
data/lib/apiotics.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Apiotics
|
2
2
|
class Configuration
|
3
3
|
|
4
|
-
attr_accessor :public_key, :private_key, :local_logging, :targets, :local_port, :server, :server_port, :portal, :push, :tls, :verify_peer, :handshake, :parents, :reduced_metadata, :redis_comms_connection, :interface_kinds, :max_missed_heartbeats, :heartbeat_interval, :heroku, :create_heartbeat_error
|
4
|
+
attr_accessor :public_key, :private_key, :local_logging, :targets, :local_port, :server, :server_port, :portal, :push, :tls, :verify_peer, :handshake, :parents, :reduced_metadata, :redis_comms_connection, :interface_kinds, :max_missed_heartbeats, :heartbeat_interval, :heroku, :server_type, :mqtt_port, :aws_endpoint, :create_heartbeat_error
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@public_key = nil
|
@@ -23,6 +23,9 @@ module Apiotics
|
|
23
23
|
@heartbeat_interval = 5
|
24
24
|
@create_heartbeat_error = false
|
25
25
|
@heroku = false
|
26
|
+
@server_type = nil
|
27
|
+
@mqtt_port = 8883
|
28
|
+
@aws_endpoint
|
26
29
|
@interface_kinds = {
|
27
30
|
"string" => "string",
|
28
31
|
"text" => "string",
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
class String
|
4
|
+
def apiotics_encrypt(key)
|
5
|
+
cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
|
6
|
+
cipher.key = Digest::SHA1.hexdigest key
|
7
|
+
s = cipher.update(self) + cipher.final
|
8
|
+
|
9
|
+
s.unpack('H*')[0].upcase
|
10
|
+
end
|
11
|
+
|
12
|
+
def apiotics_decrypt(key)
|
13
|
+
cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
|
14
|
+
cipher.key = Digest::SHA1.hexdigest key
|
15
|
+
s = [self].pack("H*").unpack("C*").pack("c*")
|
16
|
+
|
17
|
+
cipher.update(s) + cipher.final
|
18
|
+
end
|
19
|
+
end
|
data/lib/apiotics/extract.rb
CHANGED
data/lib/apiotics/hardware.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'os'
|
2
2
|
require 'etc'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module Apiotics
|
5
6
|
class Hardware
|
@@ -59,7 +60,7 @@ module Apiotics
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
|
-
def self.
|
63
|
+
def self.openocd_install_firmware(config_script, firmware_path, starting_address)
|
63
64
|
directory = Rails.root.join('lib', 'openocd', 'gnuarmeclipse')
|
64
65
|
unless Dir.exist?(directory)
|
65
66
|
self.save_openocd
|
@@ -74,19 +75,19 @@ module Apiotics
|
|
74
75
|
msg = system(string)
|
75
76
|
end
|
76
77
|
|
77
|
-
def self.openocd(worker_name, name)
|
78
|
+
def self.openocd(worker_name, name, config)
|
78
79
|
msg = ""
|
79
80
|
download_directory = Rails.root.join('lib', 'openocd')
|
80
81
|
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
81
82
|
download_directory = Rails.root.join('lib', 'openocd', 'downloads')
|
82
83
|
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
83
84
|
Dir.chdir download_directory
|
84
|
-
config = Apiotics::Portal.openocd_worker_config(worker_name)
|
85
|
-
config = JSON.parse(config)
|
86
85
|
unless config["openocd_config_file_name"] == nil || config["openocd_config_file_name"] == ""
|
87
86
|
path = Rails.root.join('lib', 'openocd', 'downloads', config["firmware_file_name"])
|
88
87
|
if File.exist?(path)
|
88
|
+
puts "Device firmware already cached at #{path}. Using cached version. To download a new copy of the device firmware, delete the file at #{path}.\n"
|
89
89
|
else
|
90
|
+
puts "Downloading device firmware...\n"
|
90
91
|
firmware_data = Apiotics::Portal.download_firmware(worker_name)
|
91
92
|
file = File.new(path, 'w')
|
92
93
|
file.write firmware_data["file"].force_encoding(Encoding::UTF_8)
|
@@ -114,7 +115,7 @@ module Apiotics
|
|
114
115
|
IO.write(data, clean_bits.force_encoding(Encoding::UTF_8), offset)
|
115
116
|
data.close
|
116
117
|
end
|
117
|
-
msg = self.
|
118
|
+
msg = self.openocd_install_firmware(config["openocd_config_file_name"], path, config["openocd_start_address"])
|
118
119
|
else
|
119
120
|
k = Apiotics.configuration.targets.keys
|
120
121
|
puts "Worker could not be found. The workers associated with your Hive are: #{k.join(',')}"
|
@@ -122,5 +123,222 @@ module Apiotics
|
|
122
123
|
return msg
|
123
124
|
end
|
124
125
|
|
126
|
+
def self.check_mac_uniflash_install
|
127
|
+
status = false
|
128
|
+
puts "Checking for Uniflash installation...\n"
|
129
|
+
path = "/Applications/ti/uniflash_4.3.0/dslite.sh"
|
130
|
+
if File.exist?(path)
|
131
|
+
puts "Uniflash installation found.\n"
|
132
|
+
status = true
|
133
|
+
else
|
134
|
+
puts "No Uniflash installation found.\n"
|
135
|
+
end
|
136
|
+
return status
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.check_linux_uniflash_install #need a Linux installation to check where UniFlash installs itself
|
140
|
+
status = false
|
141
|
+
puts "Checking for Uniflash installation...\n"
|
142
|
+
path = "#{Dir.home}/ti/uniflash_4.3.0/dslite.sh"
|
143
|
+
if File.exist?(path)
|
144
|
+
puts "Uniflash installation found.\n"
|
145
|
+
status = true
|
146
|
+
else
|
147
|
+
puts "No Uniflash installation found.\n"
|
148
|
+
end
|
149
|
+
return status
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.check_uniflash_install
|
153
|
+
status = false
|
154
|
+
if Hardware.mac == true
|
155
|
+
if Hardware.check_mac_uniflash_install == true
|
156
|
+
status = "/Applications/ti/uniflash_4.3.0/dslite.sh"
|
157
|
+
end
|
158
|
+
elsif Hardware.linux == true
|
159
|
+
if Hardware.check_linux_uniflash_install == true
|
160
|
+
status = "#{Dir.home}/ti/uniflash_4.3.0/dslite.sh"
|
161
|
+
end
|
162
|
+
else
|
163
|
+
puts "Your computer is not running a supported OS. Please use either Mac OS or Linux to install your firmware.\n"
|
164
|
+
end
|
165
|
+
return status
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.import_uniflash_image(uniflash_path, path, config)
|
169
|
+
project_path = "#{Dir.home}/.SLImageCreator/projects/#{config['firmware_file_name'].split(".")[0]}"
|
170
|
+
if Dir.exist?(project_path)
|
171
|
+
FileUtils.remove_dir(project_path)
|
172
|
+
end
|
173
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} project import --file #{path}"
|
174
|
+
puts "Creating uniflash project... \n"
|
175
|
+
msg = system(string)
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.find_uniflash_mac_address(uniflash_path, config)
|
179
|
+
mac_addr = nil
|
180
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} device info"
|
181
|
+
puts "Finding device MAC address... \n"
|
182
|
+
msg = `#{string}`
|
183
|
+
mac_addr_start = msg.rindex("MAC : ")
|
184
|
+
if mac_addr_start != nil
|
185
|
+
mac_addr_start = mac_addr_start + 15
|
186
|
+
mac_addr_end = msg.rindex("PROG MAC") - 1
|
187
|
+
mac_addr = msg[mac_addr_start..mac_addr_end].chomp
|
188
|
+
else
|
189
|
+
puts "Could not read MAC address. Please press the reset button on your board and try running rake firmware:install again.\n"
|
190
|
+
end
|
191
|
+
return mac_addr
|
192
|
+
end
|
193
|
+
|
194
|
+
def self.edit_json_config_mac_address(mac_address, config)
|
195
|
+
status = false
|
196
|
+
puts "Editing device configuration to assign device MAC address..."
|
197
|
+
path = "#{Dir.home}/.SLImageCreator/projects/#{config['firmware_file_name'].split(".")[0]}/#{config['firmware_file_name'].split(".")[0]}.json"
|
198
|
+
if File.exist?(path)
|
199
|
+
puts "json configuration file found...\n"
|
200
|
+
file = File.read(path)
|
201
|
+
puts "updating MAC address...\n"
|
202
|
+
json_config = JSON.parse(file)
|
203
|
+
json_config["header"]["DEV_MAC_ADDR"] = mac_address
|
204
|
+
json_config["systemFiles"]["CONFIG_TYPE_MAC"]["MAC_ADDR"] = mac_address
|
205
|
+
puts "writing updated json configuration file...\n"
|
206
|
+
File.write(path, json_config.to_json)
|
207
|
+
status = true
|
208
|
+
else
|
209
|
+
puts "Error: json configuration file could not be found at #{path}\n"
|
210
|
+
end
|
211
|
+
return status
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.create_uniflash_image(uniflash_path, config)
|
215
|
+
puts "Creating uniflash firmware image...\n"
|
216
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} project create_image --name #{config['firmware_file_name'].split(".")[0]} --sli_file #{config['firmware_file_name'].split(".")[0]}.sli"
|
217
|
+
msg = system(string)
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.brand_uniflash_image(uniflash_path, config)
|
221
|
+
puts "Adding Hive and Worker Type details to the firmware image...\n"
|
222
|
+
details_hash = {
|
223
|
+
"hive_public_key" => config["hive_public_key"],
|
224
|
+
"hive_private_key" => config["hive_private_key"],
|
225
|
+
"worker_type" => config["worker_type"]
|
226
|
+
}
|
227
|
+
path = Rails.root.join('lib', 'uniflash', 'downloads', 'branding.json')
|
228
|
+
File.write(path, details_hash.to_json)
|
229
|
+
target_path = "branding.json"
|
230
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} project add_file --name #{config["firmware_file_name"].split(".")[0]} --file #{path} --fs_path #{target_path} --overwrite --flags publicread"
|
231
|
+
msg = system(string)
|
232
|
+
File.delete(path)
|
233
|
+
wifi_path = Rails.root.join('lib', 'uniflash', 'downloads', 'wifi_settings')
|
234
|
+
if File.exist?(wifi_path)
|
235
|
+
Hardware.add_wifi_details(uniflash_path, config, wifi_path)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.add_wifi_details(uniflash_path, config, wifi_path)
|
240
|
+
pwd = ApioticsSetting.find_by(key: "wifi_key").value
|
241
|
+
|
242
|
+
encrypted = File.read(wifi_path)
|
243
|
+
|
244
|
+
decrypted = encrypted.apiotics_decrypt(pwd)
|
245
|
+
|
246
|
+
target_path = "wifi_settings.json"
|
247
|
+
path = Rails.root.join('lib', 'uniflash', 'downloads', 'wifi_settings.json')
|
248
|
+
File.write(path, decrypted)
|
249
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} project add_file --name #{config["firmware_file_name"].split(".")[0]} --file #{path} --fs_path #{target_path} --overwrite --flags publicread"
|
250
|
+
msg = system(string)
|
251
|
+
File.delete(path)
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.write_uniflash_image(uniflash_path, config)
|
255
|
+
puts "Writing uniflash firmware image...\n"
|
256
|
+
string = "#{uniflash_path} --mode #{config["openocd_config_file_name"]} image program --file #{config['firmware_file_name'].split(".")[0]}.sli"
|
257
|
+
msg = system(string)
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.uniflash(worker_name, name, config)
|
261
|
+
uniflash_path = Hardware.check_uniflash_install
|
262
|
+
if uniflash_path != false
|
263
|
+
download_directory = Rails.root.join('lib', 'uniflash')
|
264
|
+
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
265
|
+
download_directory = Rails.root.join('lib', 'uniflash', 'downloads')
|
266
|
+
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
267
|
+
Dir.chdir download_directory
|
268
|
+
unless config["openocd_config_file_name"] == nil || config["openocd_config_file_name"] == ""
|
269
|
+
path = Rails.root.join('lib', 'uniflash', 'downloads', config["firmware_file_name"])
|
270
|
+
if File.exist?(path)
|
271
|
+
puts "Device firmware already cached at #{path}. Using cached version. To download a new copy of the device firmware, delete the file at #{path}.\n"
|
272
|
+
else
|
273
|
+
puts "Downloading device firmware...\n"
|
274
|
+
firmware_data = Apiotics::Portal.download_firmware(worker_name)
|
275
|
+
file = File.new(path, 'w')
|
276
|
+
file.write firmware_data["file"].force_encoding(Encoding::UTF_8)
|
277
|
+
file.close
|
278
|
+
end
|
279
|
+
Hardware.import_uniflash_image(uniflash_path, path, config)
|
280
|
+
mac_address = Hardware.find_uniflash_mac_address(uniflash_path, config)
|
281
|
+
unless mac_address == nil
|
282
|
+
if Hardware.edit_json_config_mac_address(mac_address, config)
|
283
|
+
Hardware.brand_uniflash_image(uniflash_path, config)
|
284
|
+
Hardware.create_uniflash_image(uniflash_path, config)
|
285
|
+
Hardware.write_uniflash_image(uniflash_path, config)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
else
|
289
|
+
k = Apiotics.configuration.targets.keys
|
290
|
+
puts "Worker could not be found. The workers associated with your Hive are: #{k.join(',')}"
|
291
|
+
end
|
292
|
+
else
|
293
|
+
puts "Could not find Uniflash 4.3.0. If you need to install it, please visit http://processors.wiki.ti.com/index.php/Category:CCS_UniFlash and install version 4.3.0.\n"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def self.install(worker_name, name)
|
298
|
+
config = Apiotics::Portal.openocd_worker_config(worker_name)
|
299
|
+
config = JSON.parse(config)
|
300
|
+
if config["installer"] == "Open OCD 0.10"
|
301
|
+
Hardware.openocd(worker_name, name, config)
|
302
|
+
elsif config["installer"] == "Uniflash 4.3.0"
|
303
|
+
Hardware.uniflash(worker_name, name, config)
|
304
|
+
else
|
305
|
+
puts "Unknown installer for #{worker_name}. Please check the installer settings for the #{worker_name} device on the Apiotics portal.\n"
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def self.wifi(ssid, password, security_mode)
|
310
|
+
args = {
|
311
|
+
"ssid" => ssid,
|
312
|
+
"password" => password,
|
313
|
+
"security_mode" => security_mode
|
314
|
+
}
|
315
|
+
args.keys.each do |key|
|
316
|
+
if args[key] == nil
|
317
|
+
args[key] = ""
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
pwd = ApioticsSetting.find_by(key: "wifi_key")
|
322
|
+
if pwd == nil
|
323
|
+
s = ApioticsSetting.new
|
324
|
+
s.key = "wifi_key"
|
325
|
+
s.value = SecureRandom.hex
|
326
|
+
s.save
|
327
|
+
pwd = s.value
|
328
|
+
else
|
329
|
+
pwd = pwd.value
|
330
|
+
end
|
331
|
+
|
332
|
+
encrypted_wifi_config = args.to_json.apiotics_encrypt(pwd)
|
333
|
+
|
334
|
+
download_directory = Rails.root.join('lib', 'uniflash')
|
335
|
+
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
336
|
+
download_directory = Rails.root.join('lib', 'uniflash', 'downloads')
|
337
|
+
Dir.mkdir download_directory unless Dir.exist?(download_directory)
|
338
|
+
Dir.chdir download_directory
|
339
|
+
path = Rails.root.join('lib', 'uniflash', 'downloads', 'wifi_settings')
|
340
|
+
File.write(path, encrypted_wifi_config)
|
341
|
+
end
|
342
|
+
|
125
343
|
end
|
126
344
|
end
|
data/lib/apiotics/insert.rb
CHANGED
@@ -25,7 +25,7 @@ module Apiotics
|
|
25
25
|
find_record
|
26
26
|
@methods.each do |k,v|
|
27
27
|
@type = @record.class.columns_hash[k].type
|
28
|
-
|
28
|
+
change_value
|
29
29
|
@record.send("#{k}=".to_sym, v)
|
30
30
|
unless Apiotics.configuration.reduced_metadata == true
|
31
31
|
@record.send(("#{k}_action=").to_sym, @action)
|
data/lib/apiotics/portal.rb
CHANGED
@@ -62,6 +62,11 @@ module Apiotics
|
|
62
62
|
def self.retrieve_configuration
|
63
63
|
json = HTTParty.post("#{Apiotics.configuration.portal}api/hive", :query => {:public_key => Apiotics.configuration.public_key, :private_key => Apiotics.configuration.private_key}).body
|
64
64
|
hash = Apiotics::Parse.portal(json)
|
65
|
+
if Apiotics.configuration.server_type == nil
|
66
|
+
Apiotics.configuration.server_type = hash["server_version"]
|
67
|
+
Apiotics.configuration.aws_endpoint = hash["aws_endpoint"]
|
68
|
+
end
|
69
|
+
hash
|
65
70
|
end
|
66
71
|
|
67
72
|
def self.parse_all_interfaces
|
@@ -264,13 +269,41 @@ module Apiotics
|
|
264
269
|
if gem_setting == nil
|
265
270
|
gem_setting = ApioticsSetting.new
|
266
271
|
gem_setting.key = "gem_id"
|
267
|
-
gem_setting.value = hash["
|
272
|
+
gem_setting.value = hash["public_hash"]
|
268
273
|
gem_setting.save
|
269
274
|
else
|
270
|
-
gem_setting.value = hash["
|
275
|
+
gem_setting.value = hash["public_hash"]
|
271
276
|
gem_setting.save
|
272
277
|
end
|
273
|
-
|
278
|
+
s = ApioticsSetting.find_by(key: "private_gem_hash")
|
279
|
+
if s == nil
|
280
|
+
s = ApioticsSetting.new
|
281
|
+
s.key = "private_gem_hash"
|
282
|
+
s.value = hash["private_hash"]
|
283
|
+
s.save
|
284
|
+
end
|
285
|
+
s = ApioticsSetting.find_by(key: "public_key")
|
286
|
+
if s == nil
|
287
|
+
s = ApioticsSetting.new
|
288
|
+
s.key = "public_key"
|
289
|
+
s.value = hash["public"]
|
290
|
+
s.save
|
291
|
+
end
|
292
|
+
s = ApioticsSetting.find_by(key: "private_key")
|
293
|
+
if s == nil
|
294
|
+
s = ApioticsSetting.new
|
295
|
+
s.key = "private_key"
|
296
|
+
s.value = hash["private"]
|
297
|
+
s.save
|
298
|
+
end
|
299
|
+
s = ApioticsSetting.find_by(key: "cert")
|
300
|
+
if s == nil
|
301
|
+
s = ApioticsSetting.new
|
302
|
+
s.key = "cert"
|
303
|
+
s.value = hash["cert"]
|
304
|
+
s.save
|
305
|
+
end
|
306
|
+
hash["public_hash"]
|
274
307
|
end
|
275
308
|
|
276
309
|
end
|
data/lib/apiotics/server.rb
CHANGED
@@ -6,6 +6,7 @@ require "socket"
|
|
6
6
|
require 'openssl'
|
7
7
|
require 'json'
|
8
8
|
require "redis"
|
9
|
+
require 'aws_iot_device'
|
9
10
|
|
10
11
|
module Apiotics
|
11
12
|
class Server
|
@@ -16,93 +17,174 @@ module Apiotics
|
|
16
17
|
$redis = ::Redis.new
|
17
18
|
end
|
18
19
|
end
|
20
|
+
@localport = Apiotics.configuration.local_port
|
21
|
+
@error_msg = nil
|
19
22
|
Thread.abort_on_exception = true
|
20
23
|
hive_public_key = ApioticsSetting.find_by(key: "hive_public_key")
|
21
24
|
if hive_public_key == nil || hive_public_key.value != Apiotics.configuration.public_key
|
22
25
|
Server.clear_db_settings
|
23
26
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
if Apiotics::Server.server_type == "aws"
|
28
|
+
port = Apiotics.configuration.mqtt_port
|
29
|
+
key = Apiotics::Server.key
|
30
|
+
cert = Apiotics::Server.cert
|
31
|
+
ca_cert = Apiotics::Server.ca_cert
|
32
|
+
key_file = Tempfile.new
|
33
|
+
cert_file = Tempfile.new
|
34
|
+
ca_cert_file = Tempfile.new
|
35
|
+
key_file.write(key)
|
36
|
+
key_file.rewind
|
37
|
+
cert_file.write(cert)
|
38
|
+
cert_file.rewind
|
39
|
+
ca_cert_file.write(ca_cert)
|
40
|
+
ca_cert_file.rewind
|
41
|
+
aws_endpoint = Apiotics::Server.aws_endpoint
|
42
|
+
gem_id = Apiotics::Server.gem_id
|
43
|
+
Server.sync_devices(nil)
|
44
|
+
|
45
|
+
@server = AwsIotDevice::MqttShadowClient::MqttManager.new
|
46
|
+
@server.config_endpoint(aws_endpoint, port)
|
47
|
+
@server.config_ssl_context(ca_cert_file.path, key_file.path, cert_file.path)
|
48
|
+
#@server.persistent = true
|
49
|
+
@server.connect(aws_endpoint, port, true, true, false)
|
50
|
+
|
51
|
+
@server.on_message do |packet|
|
52
|
+
msg = packet.payload
|
53
|
+
puts "Message received: " + msg
|
54
|
+
Server.parse_message(msg)
|
42
55
|
end
|
56
|
+
|
57
|
+
PahoMqtt.logger = "/Users/mackie/.apiotics/paho.log"
|
58
|
+
|
59
|
+
@server.subscribe("topic/#{Apiotics.configuration.public_key}/setcomplete", 1)
|
60
|
+
@server.subscribe("topic/#{Apiotics.configuration.public_key}/setrequestack", 1)
|
61
|
+
@server.subscribe("topic/#{Apiotics.configuration.public_key}/getack", 1)
|
62
|
+
|
63
|
+
Server.ping(@server)
|
64
|
+
|
43
65
|
else
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
66
|
+
server_details = Server.lookup
|
67
|
+
rgs = ApioticsSetting.find_by(key: "server")
|
68
|
+
rgs_port = ApioticsSetting.find_by(key: "port")
|
69
|
+
if rgs == nil
|
70
|
+
if server_details["status"] == "ok"
|
71
|
+
rgs = server_details["ip"]
|
72
|
+
c = ApioticsSetting.new
|
73
|
+
c.key = "server"
|
74
|
+
c.value = rgs
|
75
|
+
c.save
|
76
|
+
rgs_port = server_details["port"]
|
77
|
+
c = ApioticsSetting.new
|
78
|
+
c.key = "port"
|
79
|
+
c.value = rgs_port
|
80
|
+
c.save
|
81
|
+
else
|
82
|
+
@error_msg = server_details["status_msg"]
|
83
|
+
end
|
51
84
|
else
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
ca_tempfile.write Server.ca_cert.to_pem
|
63
|
-
ca_tempfile.rewind
|
64
|
-
context.ca_file = ca_tempfile.path
|
65
|
-
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
85
|
+
if server_details["status"] == "ok"
|
86
|
+
rgs.value = server_details["ip"]
|
87
|
+
rgs.save
|
88
|
+
rgs = rgs.value
|
89
|
+
rgs_port.value = server_details["port"]
|
90
|
+
rgs_port.save
|
91
|
+
rgs_port = rgs_port.value
|
92
|
+
else
|
93
|
+
@error_msg = server_details["status_msg"]
|
94
|
+
end
|
66
95
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
96
|
+
if Apiotics.configuration.tls == true
|
97
|
+
socket = TCPSocket.new(rgs, rgs_port)
|
98
|
+
context = OpenSSL::SSL::SSLContext.new
|
99
|
+
context.key = Server.key
|
100
|
+
context.cert = Server.cert
|
101
|
+
if Apiotics.configuration.verify_peer == true
|
102
|
+
ca_tempfile = Tempfile.new
|
103
|
+
ca_tempfile.write Server.ca_cert.to_pem
|
104
|
+
ca_tempfile.rewind
|
105
|
+
context.ca_file = ca_tempfile.path
|
106
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
107
|
+
end
|
108
|
+
@server = OpenSSL::SSL::SSLSocket.new socket, context
|
109
|
+
@server.sync_close = true
|
110
|
+
@server.connect
|
111
|
+
if Apiotics.configuration.verify_peer == true
|
112
|
+
ca_tempfile.close(true)
|
113
|
+
end
|
114
|
+
else
|
115
|
+
@server = TCPSocket.open(rgs, rgs_port)
|
72
116
|
end
|
73
|
-
|
74
|
-
|
117
|
+
Server.sync_devices(nil)
|
118
|
+
|
119
|
+
listen_remote
|
120
|
+
@heartbeat_state = Hash.new
|
121
|
+
heartbeat = {
|
122
|
+
"action" => "heartbeat",
|
123
|
+
"hive_id" => Apiotics.configuration.public_key,
|
124
|
+
"instance_id" => "0000000000000000000000000000000000000000000000000000000000000000",
|
125
|
+
"driver" => "Core::Heartbeat",
|
126
|
+
"interface" => nil
|
127
|
+
}
|
128
|
+
send_heartbeat(heartbeat)
|
75
129
|
end
|
76
|
-
|
77
|
-
@localport = Apiotics.configuration.local_port
|
78
|
-
listen_remote
|
79
|
-
@heartbeat_state = Hash.new
|
80
|
-
heartbeat = {
|
81
|
-
"action" => "heartbeat",
|
82
|
-
"hive_id" => Apiotics.configuration.public_key,
|
83
|
-
"instance_id" => "0000000000000000000000000000000000000000000000000000000000000000",
|
84
|
-
"driver" => "Core::Heartbeat",
|
85
|
-
"interface" => nil
|
86
|
-
}
|
87
|
-
send_heartbeat(heartbeat)
|
130
|
+
puts "Starting local server..."
|
88
131
|
listen_local
|
89
132
|
rescue => e
|
90
|
-
|
91
|
-
@server.close
|
92
|
-
end
|
133
|
+
Server.close
|
93
134
|
puts e.message
|
94
135
|
puts e.backtrace.inspect
|
95
136
|
raise e
|
96
137
|
end
|
97
138
|
end
|
139
|
+
|
140
|
+
def self.ping(server)
|
141
|
+
Thread.abort_on_exception = true
|
142
|
+
Thread.new do
|
143
|
+
msg = {"p" => "p"}
|
144
|
+
loop do
|
145
|
+
server.publish("topic/ping", msg.to_json, false, 1)
|
146
|
+
sleep 30
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
98
150
|
|
99
151
|
def send(msg)
|
100
|
-
|
101
|
-
|
152
|
+
# need to check for which server.
|
153
|
+
if Apiotics.configuration.server_type == "aws"
|
154
|
+
msg = JSON.parse(msg)
|
155
|
+
if msg["action"] == "get"
|
156
|
+
msg["driver"] = msg["driver"].split("::")[1]
|
157
|
+
@server.publish("topic/#{Apiotics.configuration.public_key}/get", msg.to_json, false, 1)
|
158
|
+
else
|
159
|
+
#send_msg = {
|
160
|
+
# "state" => {
|
161
|
+
# "desired" => {
|
162
|
+
# msg["driver"].split("::")[1] => msg["interface"]
|
163
|
+
# }
|
164
|
+
# }
|
165
|
+
#}
|
166
|
+
#puts "Message sent: #{send_msg.to_json} to #{"$aws/things/#{msg["instance_id"]}/shadow/update"}"
|
167
|
+
#@server.publish("$aws/things/#{msg["instance_id"]}/shadow/update", send_msg.to_json, false, 1)
|
168
|
+
puts "Message sent: #{msg.to_json} to #{"topic/#{Apiotics.configuration.public_key}/setrequest"}"
|
169
|
+
@server.publish("topic/#{Apiotics.configuration.public_key}/setrequest", msg.to_json, false, 1)
|
170
|
+
end
|
171
|
+
else
|
172
|
+
puts "Message sent: #{msg}"
|
173
|
+
@server.puts( msg )
|
174
|
+
end
|
102
175
|
end
|
103
176
|
|
104
|
-
def close
|
105
|
-
|
177
|
+
def self.close
|
178
|
+
#need to check for which server.
|
179
|
+
if Apiotics.configuration.server_type == "aws"
|
180
|
+
if @server != nil
|
181
|
+
@server.disconnect
|
182
|
+
end
|
183
|
+
else
|
184
|
+
if @server != nil
|
185
|
+
@server.close
|
186
|
+
end
|
187
|
+
end
|
106
188
|
end
|
107
189
|
|
108
190
|
def listen_remote
|
@@ -112,19 +194,7 @@ module Apiotics
|
|
112
194
|
loop do
|
113
195
|
msg = @server.gets
|
114
196
|
puts "Message received: " + msg
|
115
|
-
msg_hash =
|
116
|
-
#puts "Driver: " + msg_hash["driver"]
|
117
|
-
unless msg_hash["driver"] == "Core::Heartbeat" || msg_hash["action"] == "sync" || msg_hash["error"] != nil
|
118
|
-
r = Apiotics::Insert.new(msg_hash)
|
119
|
-
if r.valid == true
|
120
|
-
if r.action == "set-request-ack" || r.action == "set-complete" || r.action == "get-ack"
|
121
|
-
r.save
|
122
|
-
unless Apiotics.configuration.local_logging == false
|
123
|
-
r.save_log
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
197
|
+
msg_hash = Server.parse_message(msg)
|
128
198
|
if msg_hash["driver"] == "Core::Heartbeat"
|
129
199
|
monitor_heartbeat(msg_hash)
|
130
200
|
elsif msg_hash["action"] == "sync"
|
@@ -151,10 +221,28 @@ module Apiotics
|
|
151
221
|
end
|
152
222
|
end
|
153
223
|
|
224
|
+
def self.parse_message(msg)
|
225
|
+
msg_hash = Apiotics::Parse.message(msg)
|
226
|
+
#puts "Driver: " + msg_hash["driver"]
|
227
|
+
unless msg_hash["driver"] == "Core::Heartbeat" || msg_hash["action"] == "sync" || msg_hash["error"] != nil
|
228
|
+
r = Apiotics::Insert.new(msg_hash)
|
229
|
+
if r.valid == true
|
230
|
+
if r.action == "set-request-ack" || r.action == "set-complete" || r.action == "get-ack"
|
231
|
+
r.save
|
232
|
+
unless Apiotics.configuration.local_logging == false
|
233
|
+
r.save_log
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
msg_hash
|
239
|
+
end
|
240
|
+
|
154
241
|
def listen_local
|
155
242
|
if Apiotics.configuration.redis_comms_connection == false
|
156
243
|
begin
|
157
244
|
@local_server = TCPServer.open(@localport)
|
245
|
+
puts "Local server started..."
|
158
246
|
loop do
|
159
247
|
Thread.abort_on_exception = true
|
160
248
|
Thread.fork(@local_server.accept) do |client|
|
@@ -163,7 +251,7 @@ module Apiotics
|
|
163
251
|
string = '{"error":"' + error_msg + '"}'
|
164
252
|
client.puts(string)
|
165
253
|
end
|
166
|
-
#puts s
|
254
|
+
#puts "Sending message to Server.send #{s}"
|
167
255
|
self.send(s)
|
168
256
|
end
|
169
257
|
end
|
@@ -188,12 +276,7 @@ module Apiotics
|
|
188
276
|
|
189
277
|
def send_heartbeat(heartbeat)
|
190
278
|
if Apiotics.configuration.handshake == true
|
191
|
-
gem_id =
|
192
|
-
if gem_id == nil
|
193
|
-
gem_id = Apiotics::Portal.register_client
|
194
|
-
else
|
195
|
-
gem_id = gem_id.value
|
196
|
-
end
|
279
|
+
gem_id = Server.gem_id
|
197
280
|
connect_msg = {
|
198
281
|
"action" => "connect",
|
199
282
|
"hive_id" => Apiotics.configuration.public_key,
|
@@ -284,28 +367,34 @@ module Apiotics
|
|
284
367
|
return hash
|
285
368
|
end
|
286
369
|
|
370
|
+
def self.gem_id
|
371
|
+
gem_id = ApioticsSetting.find_by(key: "gem_id")
|
372
|
+
if gem_id == nil
|
373
|
+
gem_id = Apiotics::Portal.register_client
|
374
|
+
else
|
375
|
+
gem_id = gem_id.value
|
376
|
+
end
|
377
|
+
gem_id
|
378
|
+
end
|
379
|
+
|
287
380
|
def self.key
|
288
|
-
key = ApioticsSetting.find_by(key: "
|
381
|
+
key = ApioticsSetting.find_by(key: "private_key")
|
289
382
|
if key == nil
|
290
|
-
|
383
|
+
Apiotics::Portal.register_client
|
384
|
+
key = ApioticsSetting.find_by(key: "private_key")
|
385
|
+
key = key.value
|
291
386
|
else
|
292
387
|
key = key.value
|
293
388
|
end
|
294
|
-
pass_phrase = ApioticsSetting.find_by(key: "key_pass_phrase").value
|
295
|
-
key = OpenSSL::PKey::RSA.new key, pass_phrase
|
296
389
|
return key
|
297
390
|
end
|
298
391
|
|
299
392
|
def self.cert
|
300
393
|
cert = ApioticsSetting.find_by(key: "cert")
|
301
394
|
if cert == nil
|
302
|
-
|
303
|
-
|
304
|
-
cert =
|
305
|
-
c = ApioticsSetting.new
|
306
|
-
c.key = "cert"
|
307
|
-
c.value = cert
|
308
|
-
c.save
|
395
|
+
Apiotics::Portal.register_client
|
396
|
+
cert = ApioticsSetting.find_by(key: "cert")
|
397
|
+
cert = cert.value
|
309
398
|
else
|
310
399
|
cert = cert.value
|
311
400
|
end
|
@@ -313,29 +402,6 @@ module Apiotics
|
|
313
402
|
return cert
|
314
403
|
end
|
315
404
|
|
316
|
-
def self.generate_key
|
317
|
-
key = OpenSSL::PKey::RSA.new 2048
|
318
|
-
pass_phrase = 'simbiotes'
|
319
|
-
cipher = OpenSSL::Cipher.new 'AES-128-CBC'
|
320
|
-
s = ApioticsSetting.new
|
321
|
-
s.key = "key_cipher"
|
322
|
-
s.value = "OpenSSL::Cipher.new 'AES-128-CBC'"
|
323
|
-
s.save
|
324
|
-
s = ApioticsSetting.new
|
325
|
-
s.key = "key_pass_phrase"
|
326
|
-
s.value = 'simbiotes'
|
327
|
-
s.save
|
328
|
-
s = ApioticsSetting.new
|
329
|
-
s.key = "public_key"
|
330
|
-
s.value = key.public_key.to_pem
|
331
|
-
s.save
|
332
|
-
s = ApioticsSetting.new
|
333
|
-
s.key = "key"
|
334
|
-
s.value = key.export(cipher, pass_phrase)
|
335
|
-
s.save
|
336
|
-
return s.value
|
337
|
-
end
|
338
|
-
|
339
405
|
def self.generate_cert(key, public_key)
|
340
406
|
csr = OpenSSL::X509::Request.new
|
341
407
|
csr.version = 0
|
@@ -369,6 +435,42 @@ module Apiotics
|
|
369
435
|
hive_public_key.save
|
370
436
|
end
|
371
437
|
|
438
|
+
def self.server_type
|
439
|
+
s = ApioticsSetting.find_by(key: "server_type")
|
440
|
+
if s == nil
|
441
|
+
if Apiotics.configuration.server_type == nil
|
442
|
+
hash = Apiotics::Portal.retrieve_configuration
|
443
|
+
Apiotics.configuration.server_type == hash["server_version"]
|
444
|
+
server_type = hash["server_version"]
|
445
|
+
else
|
446
|
+
server_type = Apiotics.configuration.server_type
|
447
|
+
end
|
448
|
+
s = ApioticsSetting.new
|
449
|
+
s.key = "server_type"
|
450
|
+
s.value = server_type
|
451
|
+
s.save
|
452
|
+
end
|
453
|
+
s.value
|
454
|
+
end
|
455
|
+
|
456
|
+
def self.aws_endpoint
|
457
|
+
s = ApioticsSetting.find_by(key: "aws_endpoint")
|
458
|
+
if s == nil
|
459
|
+
if Apiotics.configuration.aws_endpoint == nil
|
460
|
+
hash = Apiotics::Portal.retrieve_configuration
|
461
|
+
Apiotics.configuration.server_type == hash["aws_endpoint"]
|
462
|
+
aws_endpoint = hash["aws_endpoint"]
|
463
|
+
else
|
464
|
+
aws_endpoint = Apiotics.configuration.aws_endpoint
|
465
|
+
end
|
466
|
+
s = ApioticsSetting.new
|
467
|
+
s.key = "aws_endpoint"
|
468
|
+
s.value = aws_endpoint
|
469
|
+
s.save
|
470
|
+
end
|
471
|
+
s.value
|
472
|
+
end
|
473
|
+
|
372
474
|
def do_at_exit
|
373
475
|
end
|
374
476
|
|
data/lib/apiotics/version.rb
CHANGED
@@ -7,7 +7,7 @@ module Apiotics
|
|
7
7
|
@models = Apiotics.configuration.targets[module_name.to_s]
|
8
8
|
template "apiotics_scaffold.rb.erb", "app/controllers/#{module_file_name}/#{module_file_name.pluralize}_controller.rb"
|
9
9
|
generate "apiotics:view", "#{parent}"
|
10
|
-
route "scope module: :#{module_file_name} do \n\t\tresources :#{module_file_name}s\n\tend
|
10
|
+
route "scope module: :#{module_file_name} do \n\t\tresources :#{module_file_name}s\n\tend"
|
11
11
|
generate "simple_form:install"
|
12
12
|
end
|
13
13
|
|
@@ -21,6 +21,7 @@ module Apiotics
|
|
21
21
|
copy_file "dev_comm_server.rake", "lib/tasks/dev_comm_server.rake"
|
22
22
|
copy_file "publish_script.rake", "lib/tasks/publish_script.rake"
|
23
23
|
copy_file "install_firmware.rake", "lib/tasks/install_firmware.rake"
|
24
|
+
copy_file "set_wifi.rake", "lib/tasks/set_wifi.rake"
|
24
25
|
FileUtils.chmod 0775, "lib/scripts/server_control.rb"
|
25
26
|
FileUtils.chmod 0775, "lib/scripts/heroku_server_control.rb"
|
26
27
|
end
|
@@ -2,9 +2,9 @@ namespace :firmware do
|
|
2
2
|
desc "Install firmware on devices. Use rake firmware:install {worker_name} to install firmware on a device. Use rake firmware:install {worker_name} {instance_name} to install firmware and set a name for the device."
|
3
3
|
task :install, [:worker, :name] => [:environment] do |task, args|
|
4
4
|
if args[:name] == nil
|
5
|
-
Apiotics::Hardware.
|
5
|
+
Apiotics::Hardware.install(args[:worker], nil)
|
6
6
|
else
|
7
|
-
Apiotics::Hardware.
|
7
|
+
Apiotics::Hardware.install(args[:worker], args[:name])
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :firmware do
|
2
|
+
desc "Set Wifi details for a device (if applicable). Use rake firmware:wifi[ssid, password, security_mode] to set the wifi details for a device."
|
3
|
+
task :wifi, [:ssid, :password, :security_mode] => [:environment] do |task, args|
|
4
|
+
security_modes = ["WEP", "WPA", "WPA2"]
|
5
|
+
if args[:security_mode] != nil
|
6
|
+
unless security_modes.include?(args[:security_mode])
|
7
|
+
puts "#{args[:security_mode]} is not a supported WiFi security mode. The supported security modes are: #{security_modes.to_s}"
|
8
|
+
else
|
9
|
+
Apiotics::Hardware.wifi(args[:ssid], args[:password], args[:security_mode])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apiotics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MicroArx Corporation
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: apiotics-aws-iot-client
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: pg
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -163,6 +177,7 @@ files:
|
|
163
177
|
- lib/apiotics/client.rb
|
164
178
|
- lib/apiotics/configuration.rb
|
165
179
|
- lib/apiotics/connection_error.rb
|
180
|
+
- lib/apiotics/encrypt_decrypt.rb
|
166
181
|
- lib/apiotics/extract.rb
|
167
182
|
- lib/apiotics/hardware.rb
|
168
183
|
- lib/apiotics/insert.rb
|
@@ -220,6 +235,7 @@ files:
|
|
220
235
|
- lib/generators/apiotics/script/templates/script.rb.erb
|
221
236
|
- lib/generators/apiotics/script/templates/server.rb
|
222
237
|
- lib/generators/apiotics/script/templates/server_control.rb
|
238
|
+
- lib/generators/apiotics/script/templates/set_wifi.rake
|
223
239
|
- lib/generators/apiotics/script/templates/test_comm_server.rake
|
224
240
|
- lib/generators/apiotics/script/templates/test_server.rb
|
225
241
|
- lib/generators/apiotics/script/templates/test_server_control.rb
|
@@ -251,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
251
267
|
version: '0'
|
252
268
|
requirements: []
|
253
269
|
rubyforge_project:
|
254
|
-
rubygems_version: 2.
|
270
|
+
rubygems_version: 2.6.10
|
255
271
|
signing_key:
|
256
272
|
specification_version: 4
|
257
273
|
summary: IoT For Everybody.
|