apiotics 0.1.141 → 0.2.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.
- 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.
|