vws 1.2.0 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +18 -18
- data/Gemfile +4 -4
- data/LICENSE.txt +22 -22
- data/README.md +153 -140
- data/Rakefile +2 -2
- data/lib/vws.rb +258 -257
- data/lib/vws/helpers.rb +2 -0
- data/lib/vws/version.rb +3 -3
- data/spec/vws_spec.rb +74 -96
- data/vws.gemspec +31 -31
- metadata +7 -6
- data/.travis.yml +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8e8f520b6858b811e7364870611efde7b48e9a2
|
4
|
+
data.tar.gz: 7cb620d7706e9fcd71457d2cda8d5837f8d26b7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f683f9a33a6f0afbd5c86b0898cb908076bed286a70addc77890ffa9a60d59f8bae121381e8f5450dd95f3deab68350e1e66f13756758dea34ffa40fd51ee706
|
7
|
+
data.tar.gz: 02ef649bca4db7f834021685ddf6fac5f232fa4feeca83de755c03c5ae100aeb7a36e8501fe2992a01cfdf15338601b5831d600e94deb52350a600c63e0b865f
|
data/.gitignore
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
.bundle
|
4
|
-
.config
|
5
|
-
.yardoc
|
6
|
-
Gemfile.lock
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
18
|
-
spec/local_env.yml
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
spec/local_env.yml
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in vws.gemspec
|
4
|
-
gemspec
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in vws.gemspec
|
4
|
+
gemspec
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
Copyright (c) 2013 Nikos Kokkos
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
Copyright (c) 2013 Nikos Kokkos
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,140 +1,153 @@
|
|
1
|
-
# Vws (Vuforia Web Services ruby gem for API access for target management)
|
2
|
-
|
3
|
-
This is a ruby gem to interact with Vuforia web services api for managing the targets:
|
4
|
-
https://developer.vuforia.com/
|
5
|
-
|
6
|
-
It uses the excellent rest-client (https://github.com/rest-client/rest-client) to handle the
|
7
|
-
HTTP/REST requests required by the Vuforia Web Services API.
|
8
|
-
|
9
|
-
## Installation from source:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
1
|
+
# Vws (Vuforia Web Services ruby gem for API access for target management)
|
2
|
+
|
3
|
+
This is a ruby gem to interact with Vuforia web services api for managing the targets:
|
4
|
+
https://developer.vuforia.com/library//articles/Solution/How-To-Use-the-Vuforia-Web-Services-API
|
5
|
+
|
6
|
+
It uses the excellent rest-client (https://github.com/rest-client/rest-client) to handle the
|
7
|
+
HTTP/REST requests required by the Vuforia Web Services API.
|
8
|
+
|
9
|
+
## Installation from source:
|
10
|
+
|
11
|
+
Clone this repo onto your hard drive and cd into the root folder.
|
12
|
+
|
13
|
+
First install bundler gem (if it is not installed) by issuing:
|
14
|
+
|
15
|
+
gem install bundler
|
16
|
+
|
17
|
+
Install the required gems by vws gem by:
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
Build the vws gem by:
|
22
|
+
|
23
|
+
rake build
|
24
|
+
|
25
|
+
This will build the vws.gem into the pkg folder.
|
26
|
+
|
27
|
+
Install the gem from the pkg folder by:
|
28
|
+
|
29
|
+
gem install vws.gem
|
30
|
+
|
31
|
+
|
32
|
+
## Basic Installation using rails Gemfile:
|
33
|
+
|
34
|
+
|
35
|
+
Add this line to your rails application's Gemfile:
|
36
|
+
|
37
|
+
gem 'vws'
|
38
|
+
|
39
|
+
And then execute:
|
40
|
+
|
41
|
+
bundle install
|
42
|
+
|
43
|
+
|
44
|
+
The gem has been uploaded to rubygems.org (http://rubygems.org/gems/vws), therefore you can simply issue:
|
45
|
+
|
46
|
+
gem install vws
|
47
|
+
|
48
|
+
and you'll be set.
|
49
|
+
|
50
|
+
|
51
|
+
## Usage:
|
52
|
+
|
53
|
+
Instantiate a connection to the api with:
|
54
|
+
|
55
|
+
connection = Vws::Api.new("your_server_vws_access_key", "your_server_vws_secret_key")
|
56
|
+
|
57
|
+
After a successful connection, you should have access to the vuforia api as shown here:
|
58
|
+
https://developer.vuforia.com/library/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API
|
59
|
+
|
60
|
+
So, if you want to get a summary of the cloud database, you issue:
|
61
|
+
|
62
|
+
connection.summary
|
63
|
+
|
64
|
+
For a list of targets in your database:
|
65
|
+
|
66
|
+
connection.list_targets
|
67
|
+
|
68
|
+
To retrieve a target's info:
|
69
|
+
|
70
|
+
connection.retrieve_target(target_id)
|
71
|
+
|
72
|
+
To activate or deactivate a target:
|
73
|
+
|
74
|
+
connection.set_active_flag(target_id, active_flag) where active_flag = true/false
|
75
|
+
|
76
|
+
To add a target to the database:
|
77
|
+
|
78
|
+
connection.add_target(target_name, file_path, width, active_flag, application_metadata)
|
79
|
+
You may set application_metadata = nil if you do not use this attribute
|
80
|
+
|
81
|
+
To delete a target:
|
82
|
+
|
83
|
+
connection.delete_target(target_id)
|
84
|
+
|
85
|
+
but before deleting a target, you have to set to inactive if it active and
|
86
|
+
wait for a while:
|
87
|
+
|
88
|
+
Change a target flag to inactive/active:
|
89
|
+
|
90
|
+
connection.set_active_flag(target_id, active_flag), where active_flag=true/false
|
91
|
+
|
92
|
+
List duplicates for target:
|
93
|
+
|
94
|
+
connection.list_duplicates(target_id)
|
95
|
+
|
96
|
+
|
97
|
+
## Parsing the output:
|
98
|
+
|
99
|
+
Response from the server is in JSON(text/string) format. So, you can easily parse the output and convert it to a Hash with keys. For example you may parse the output as such:
|
100
|
+
|
101
|
+
connection_hash = JSON.parse(connection)
|
102
|
+
|
103
|
+
Once you do that, you have access to the list of the hash's keys with
|
104
|
+
|
105
|
+
connection_hash.keys
|
106
|
+
|
107
|
+
Then, you can grab the information relating to a certain key with:
|
108
|
+
|
109
|
+
connection_hash["key"]
|
110
|
+
|
111
|
+
For example, here you can find the keys from the response after asking for the database summary:
|
112
|
+
https://developer.vuforia.com/library/articles/Solution/How-To-Get-a-Database-Summary-Report-Using-the-VWS-API.
|
113
|
+
From that you can extract the name of the database with:
|
114
|
+
|
115
|
+
connection_hash["name"]
|
116
|
+
|
117
|
+
|
118
|
+
## Attributes of the uploaded file:
|
119
|
+
Vuforia has a great article about what makes a target ideal:
|
120
|
+
https://developer.vuforia.com/library/articles/Best_Practices/Attributes-of-an-Ideal-Image-Target
|
121
|
+
Currently, this ruby gem does not check for file size or any other attributes addressed in the article above.
|
122
|
+
|
123
|
+
|
124
|
+
## Spec
|
125
|
+
|
126
|
+
Enter your server keys into vws_spec.rb file and run the specs at the root
|
127
|
+
of the folder by issuing:
|
128
|
+
|
129
|
+
rspec spec
|
130
|
+
|
131
|
+
|
132
|
+
##Caveats
|
133
|
+
|
134
|
+
Setting a target from on to off and vice versa takes some time. It may take up to
|
135
|
+
0-10 minutes and it's based on Vuforia's infrastucture. It is your responsibilty
|
136
|
+
to poll for the changes on the target since no such feature has been implemented
|
137
|
+
in this gem. More you can find here: https://developer.vuforia.com/library//articles/Best_Practices/Best-Practices-for-using-the-VWS-API
|
138
|
+
|
139
|
+
## Contributing
|
140
|
+
|
141
|
+
Please, if you use it, report back any bugs/problems.
|
142
|
+
|
143
|
+
1. Fork it
|
144
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
145
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
146
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
147
|
+
5. Create new Pull Request
|
148
|
+
|
149
|
+
## License
|
150
|
+
|
151
|
+
This software is licensed under the MIT License (MIT).
|
152
|
+
|
153
|
+
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.
|
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
data/lib/vws.rb
CHANGED
@@ -1,257 +1,258 @@
|
|
1
|
-
require "vws/version"
|
2
|
-
require 'rubygems'
|
3
|
-
require 'rest_client'
|
4
|
-
require 'digest/md5'
|
5
|
-
require 'time'
|
6
|
-
require 'openssl'
|
7
|
-
require 'base64'
|
8
|
-
require 'json'
|
9
|
-
|
10
|
-
|
11
|
-
module Vws
|
12
|
-
#constants for end point interface links
|
13
|
-
BASE_URL = "https://vws.vuforia.com"
|
14
|
-
TARGETS_URL = BASE_URL + "/targets"
|
15
|
-
SUMMARY_URL = BASE_URL + "/summary"
|
16
|
-
DUPLICATES_URL = BASE_URL + "/duplicates"
|
17
|
-
|
18
|
-
class Api
|
19
|
-
|
20
|
-
def initialize(accesskey=nil, secretkey=nil)
|
21
|
-
@accesskey = accesskey || ENV['VWS_ACCESSKEY']
|
22
|
-
@secretkey = secretkey || ENV['VWS_SECRETKEY']
|
23
|
-
end
|
24
|
-
|
25
|
-
def build_signature(request_path, body_hash, http_verb, timestamp)
|
26
|
-
# request_path signifies the suburi you call after you subtract the
|
27
|
-
# BASE_URL; that is, if you call https://vws/vuforia.com/targets,
|
28
|
-
# the request_path is '/targets'
|
29
|
-
|
30
|
-
contentType = ""
|
31
|
-
hexDigest = "d41d8cd98f00b204e9800998ecf8427e" # Hex digest of an empty
|
32
|
-
# string. We use it to
|
33
|
-
# signify empty body
|
34
|
-
|
35
|
-
if http_verb == "GET" || http_verb == "DELETE"
|
36
|
-
# Do nothing since we have already set contentType and hexDigest
|
37
|
-
elsif http_verb == "POST" || http_verb == "PUT"
|
38
|
-
contentType = "application/json";
|
39
|
-
# the request should have a request body, so create an md5 hash of that
|
40
|
-
# json body data
|
41
|
-
hexDigest = Digest::MD5.hexdigest(body_hash.to_json)
|
42
|
-
else
|
43
|
-
puts "Invalid request method for signature method: " + http_verb
|
44
|
-
return nil
|
45
|
-
end
|
46
|
-
|
47
|
-
toDigest = http_verb + "\n" +
|
48
|
-
hexDigest + "\n" +
|
49
|
-
contentType + "\n" +
|
50
|
-
timestamp + "\n" +
|
51
|
-
request_path
|
52
|
-
|
53
|
-
return Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new,
|
54
|
-
@secretkey, toDigest))
|
55
|
-
end
|
56
|
-
|
57
|
-
# Calls the api end point for the list of targets associated with
|
58
|
-
# server access key and cloud database
|
59
|
-
# https://developer.vuforia.com/library/articles/Solution/How-To-Get-a-Target-List-for-a-Cloud-Database-Using-the-VWS-API
|
60
|
-
def list_targets
|
61
|
-
#Date is the current date per RFC 2616, section 3.3.1,
|
62
|
-
#rfc1123-date format, e.g.: Sun, 22 Apr #2012 08:49:37 GMT.
|
63
|
-
date_timestamp = Time.now.httpdate #ruby provides this date format
|
64
|
-
#with httpdate method
|
65
|
-
signature = self.build_signature('/targets', nil, 'GET', date_timestamp)
|
66
|
-
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
67
|
-
|
68
|
-
authorization_header = "VWS " + @accesskey + ":" + signature
|
69
|
-
begin
|
70
|
-
RestClient.get(TARGETS_URL, :'Date' => date_timestamp,
|
71
|
-
:'Authorization' => authorization_header)
|
72
|
-
rescue => e
|
73
|
-
e.response
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def add_target(target_name, file_path, width, active_flag,
|
78
|
-
raise "file path is required" if file_path.nil?
|
79
|
-
raise "target name is required" if target_name.nil?
|
80
|
-
date_timestamp = Time.now.httpdate
|
81
|
-
#for file uploads, read file contents data and Base 64 encode it:
|
82
|
-
contents_encoded = Base64.encode64(
|
83
|
-
|
84
|
-
|
85
|
-
:
|
86
|
-
:
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
:
|
95
|
-
:
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
def update_target(target_id, target_name=nil, file_path=nil, width=nil, active_flag=nil)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
body_hash = { :name => target_name,
|
111
|
-
:width => width, #Width of the target in scene unit
|
112
|
-
:image => contents_encoded,
|
113
|
-
:active_flag => active_flag
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
:'
|
121
|
-
:
|
122
|
-
:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
#
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
:'
|
188
|
-
:
|
189
|
-
:
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
#
|
197
|
-
|
198
|
-
|
199
|
-
#
|
200
|
-
#
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
#
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
:'
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
end
|
1
|
+
require "vws/version"
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'time'
|
6
|
+
require 'openssl'
|
7
|
+
require 'base64'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
|
11
|
+
module Vws
|
12
|
+
#constants for end point interface links
|
13
|
+
BASE_URL = "https://vws.vuforia.com"
|
14
|
+
TARGETS_URL = BASE_URL + "/targets"
|
15
|
+
SUMMARY_URL = BASE_URL + "/summary"
|
16
|
+
DUPLICATES_URL = BASE_URL + "/duplicates"
|
17
|
+
|
18
|
+
class Api
|
19
|
+
|
20
|
+
def initialize(accesskey=nil, secretkey=nil)
|
21
|
+
@accesskey = accesskey || ENV['VWS_ACCESSKEY']
|
22
|
+
@secretkey = secretkey || ENV['VWS_SECRETKEY']
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_signature(request_path, body_hash, http_verb, timestamp)
|
26
|
+
# request_path signifies the suburi you call after you subtract the
|
27
|
+
# BASE_URL; that is, if you call https://vws/vuforia.com/targets,
|
28
|
+
# the request_path is '/targets'
|
29
|
+
|
30
|
+
contentType = ""
|
31
|
+
hexDigest = "d41d8cd98f00b204e9800998ecf8427e" # Hex digest of an empty
|
32
|
+
# string. We use it to
|
33
|
+
# signify empty body
|
34
|
+
|
35
|
+
if http_verb == "GET" || http_verb == "DELETE"
|
36
|
+
# Do nothing since we have already set contentType and hexDigest
|
37
|
+
elsif http_verb == "POST" || http_verb == "PUT"
|
38
|
+
contentType = "application/json";
|
39
|
+
# the request should have a request body, so create an md5 hash of that
|
40
|
+
# json body data
|
41
|
+
hexDigest = Digest::MD5.hexdigest(body_hash.to_json)
|
42
|
+
else
|
43
|
+
puts "Invalid request method for signature method: " + http_verb
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
toDigest = http_verb + "\n" +
|
48
|
+
hexDigest + "\n" +
|
49
|
+
contentType + "\n" +
|
50
|
+
timestamp + "\n" +
|
51
|
+
request_path
|
52
|
+
|
53
|
+
return Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new,
|
54
|
+
@secretkey, toDigest))
|
55
|
+
end
|
56
|
+
|
57
|
+
# Calls the api end point for the list of targets associated with
|
58
|
+
# server access key and cloud database
|
59
|
+
# https://developer.vuforia.com/library/articles/Solution/How-To-Get-a-Target-List-for-a-Cloud-Database-Using-the-VWS-API
|
60
|
+
def list_targets
|
61
|
+
#Date is the current date per RFC 2616, section 3.3.1,
|
62
|
+
#rfc1123-date format, e.g.: Sun, 22 Apr #2012 08:49:37 GMT.
|
63
|
+
date_timestamp = Time.now.httpdate #ruby provides this date format
|
64
|
+
#with httpdate method
|
65
|
+
signature = self.build_signature('/targets', nil, 'GET', date_timestamp)
|
66
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
67
|
+
|
68
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
69
|
+
begin
|
70
|
+
RestClient.get(TARGETS_URL, :'Date' => date_timestamp,
|
71
|
+
:'Authorization' => authorization_header)
|
72
|
+
rescue => e
|
73
|
+
e.response
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_target(target_name, file_path, width, active_flag, metadata=nil)
|
78
|
+
raise "file path is required" if file_path.nil?
|
79
|
+
raise "target name is required" if target_name.nil?
|
80
|
+
date_timestamp = Time.now.httpdate
|
81
|
+
#for file uploads, read file contents data and Base 64 encode it:
|
82
|
+
contents_encoded = Base64.encode64(open(file_path) { |io| io.read })
|
83
|
+
metadata_encoded = Base64.encode64(metadata.to_s)
|
84
|
+
body_hash = { :name => target_name,
|
85
|
+
:width => width, #width of the target in scene units
|
86
|
+
:image => contents_encoded,
|
87
|
+
:active_flag => active_flag,
|
88
|
+
:application_metadata => metadata_encoded }
|
89
|
+
signature = self.build_signature('/targets', body_hash, 'POST', date_timestamp)
|
90
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
91
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
92
|
+
begin
|
93
|
+
RestClient.post(TARGETS_URL, body_hash.to_json,
|
94
|
+
:'Date' => date_timestamp,
|
95
|
+
:'Authorization' => authorization_header,
|
96
|
+
:content_type => 'application/json',
|
97
|
+
:accept => :json)
|
98
|
+
rescue => e
|
99
|
+
e.response
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def update_target(target_id, target_name=nil, file_path=nil, width=nil, active_flag=nil, metadata=nil)
|
104
|
+
date_timestamp = Time.now.httpdate
|
105
|
+
target_id_url = TARGETS_URL + '/' + target_id
|
106
|
+
target_id_suburl = '/targets' + '/' + target_id
|
107
|
+
#for file uploads, read file contents data and Base 64 encode it:
|
108
|
+
contents_encoded = Base64.encode64(open(file_path) { |io| io.read })
|
109
|
+
metadata_encoded = Base64.encode64(metadata.to_s)
|
110
|
+
body_hash = { :name => target_name,
|
111
|
+
:width => width, #Width of the target in scene unit
|
112
|
+
:image => contents_encoded,
|
113
|
+
:active_flag => active_flag,
|
114
|
+
:application_metadata => metadata_encoded }
|
115
|
+
signature = self.build_signature(target_id_suburl, body_hash, 'PUT', date_timestamp)
|
116
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
117
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
118
|
+
begin
|
119
|
+
RestClient.put(target_id_url, body_hash.to_json,
|
120
|
+
:'Date' => date_timestamp,
|
121
|
+
:'Authorization' => authorization_header,
|
122
|
+
:content_type => 'application/json',
|
123
|
+
:accept => :json)
|
124
|
+
rescue => e
|
125
|
+
e.response
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Database Summary Report
|
130
|
+
# https://developer.vuforia.com/resources/dev-guide/database-summary-report
|
131
|
+
def summary
|
132
|
+
date_timestamp = Time.now.httpdate
|
133
|
+
signature = self.build_signature('/summary', nil, 'GET', date_timestamp)
|
134
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
135
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
136
|
+
begin
|
137
|
+
RestClient.get(SUMMARY_URL, :'Date' => date_timestamp,
|
138
|
+
:'Authorization' => authorization_header)
|
139
|
+
rescue => e
|
140
|
+
e.response
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Retrieve a target from the cloud database
|
145
|
+
# https://developer.vuforia.com/resources/dev-guide/retrieving-target-cloud-database
|
146
|
+
def retrieve_target(target_id)
|
147
|
+
date_timestamp = Time.now.httpdate
|
148
|
+
target_id_url = TARGETS_URL + '/' + target_id
|
149
|
+
target_id_suburl = '/targets' + '/' + target_id
|
150
|
+
signature = self.build_signature(target_id_suburl, nil, 'GET', date_timestamp)
|
151
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
152
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
153
|
+
begin
|
154
|
+
RestClient.get(target_id_url, :'Date' => date_timestamp,
|
155
|
+
:'Authorization' => authorization_header)
|
156
|
+
rescue => e
|
157
|
+
e.response
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Target Summary Report
|
162
|
+
# https://developer.vuforia.com/resources/dev-guide/target-summary-report
|
163
|
+
def target_summary(target_id)
|
164
|
+
date_timestamp = Time.now.httpdate
|
165
|
+
target_id_url = SUMMARY_URL + '/' + target_id
|
166
|
+
target_id_suburl = '/summary' + '/' + target_id
|
167
|
+
signature = self.build_signature(target_id_suburl, nil, 'GET', date_timestamp)
|
168
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
169
|
+
begin
|
170
|
+
RestClient.get(target_id_url, :'Date' => date_timestamp,
|
171
|
+
:'Authorization' => authorization_header)
|
172
|
+
rescue => e
|
173
|
+
e.response
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def set_active_flag(target_id, active_flag)
|
178
|
+
date_timestamp = Time.now.httpdate
|
179
|
+
target_id_url = TARGETS_URL + '/' + target_id
|
180
|
+
target_id_suburl = '/targets' + '/' + target_id
|
181
|
+
body_hash = {:active_flag => active_flag}
|
182
|
+
signature = self.build_signature(target_id_suburl, body_hash, 'PUT', date_timestamp)
|
183
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
184
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
185
|
+
begin
|
186
|
+
RestClient.put(target_id_url, body_hash.to_json,
|
187
|
+
:'Date' => date_timestamp,
|
188
|
+
:'Authorization' => authorization_header,
|
189
|
+
:content_type => 'application/json',
|
190
|
+
:accept => :json)
|
191
|
+
rescue => e
|
192
|
+
e.response
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Delete a target in a cloud database
|
197
|
+
# https://developer.vuforia.com/library/articles/Solution/How-To-Delete-a-Target-Using-the-VWS-API
|
198
|
+
def delete_target(target_id)
|
199
|
+
# In order to delete the target, we have to set it to non-active.
|
200
|
+
# Therefore,first retrieve target info and act accordingly to target info
|
201
|
+
# returned
|
202
|
+
target_data = JSON.parse(retrieve_target(target_id)) # have to JSON.parse
|
203
|
+
# retrieve_target's results since they're in string format
|
204
|
+
target_result_code = target_data["result_code"]
|
205
|
+
if target_result_code != "AuthenticationFailure"
|
206
|
+
if target_result_code != "UnknownTarget"
|
207
|
+
target_active_flag = target_data["target_record"]["active_flag"]
|
208
|
+
target_status = target_data["status"]
|
209
|
+
if target_result_code == "Success"
|
210
|
+
if target_active_flag == true && target_status == "success"
|
211
|
+
return {:result_code => "TargetActive"}.to_json
|
212
|
+
elsif target_active_flag == false && target_status == "success"
|
213
|
+
# if we reached this point, the target is fine, inactive and
|
214
|
+
# ready to be deleted
|
215
|
+
date_timestamp = Time.now.httpdate
|
216
|
+
target_id_url = TARGETS_URL + '/' + target_id
|
217
|
+
target_id_suburl = '/targets' + '/' + target_id
|
218
|
+
signature = self.build_signature(target_id_suburl, nil, 'DELETE', date_timestamp)
|
219
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
220
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
221
|
+
begin
|
222
|
+
RestClient.delete(target_id_url,
|
223
|
+
:'Date' => date_timestamp,
|
224
|
+
:'Authorization' => authorization_header)
|
225
|
+
rescue => e
|
226
|
+
e.response
|
227
|
+
end
|
228
|
+
else
|
229
|
+
return {:result_code => "#{target_status}"}.to_json
|
230
|
+
end
|
231
|
+
end
|
232
|
+
else
|
233
|
+
return {:result_code => "UnknownTarget"}.to_json
|
234
|
+
end
|
235
|
+
else
|
236
|
+
return {:result_code => "AuthenticationFailure"}.to_json
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def list_duplicates(target_id)
|
241
|
+
date_timestamp = Time.now.httpdate
|
242
|
+
|
243
|
+
target_id_url = DUPLICATES_URL + '/' + target_id
|
244
|
+
target_id_suburl = '/duplicates' + '/' + target_id
|
245
|
+
|
246
|
+
signature = self.build_signature(target_id_suburl, nil, 'GET', date_timestamp)
|
247
|
+
raise ArgumentError.new('Signature returned nil. Aborting...') if signature == nil
|
248
|
+
authorization_header = "VWS " + @accesskey + ":" + signature
|
249
|
+
begin
|
250
|
+
RestClient.get(target_id_url, :'Date' => date_timestamp,
|
251
|
+
:'Authorization' => authorization_header)
|
252
|
+
rescue => e
|
253
|
+
e.response
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
end
|