-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from AO-StreetArt/udpApi
Udp api
- Loading branch information
Showing
13 changed files
with
298 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# The basic CLyman Flow performs a series of basic checks on the CLyman API | ||
# It walks a single object through a full flow, step by step, and validates | ||
# all of the fields on the object at each step of the way. | ||
|
||
import logging | ||
import sys | ||
import json | ||
import copy | ||
import requests | ||
import socket | ||
import time | ||
|
||
# Basic Config | ||
aesel_addr = "http://127.0.0.1:5885" | ||
udp_ip = "127.0.0.1" | ||
udp_port = 5886 | ||
log_file = 'logs/udpTest.log' | ||
log_level = logging.DEBUG | ||
|
||
# Test Scene Data | ||
test_scene_data = { | ||
"key":"", | ||
"name":"basicFlowName", | ||
"latitude":124.0, | ||
"longitude":122.0, | ||
"distance":100.0, | ||
"region":"basicFlowRegion", | ||
"asset_ids":["basicAsset"], | ||
"tags":["basicTag"] | ||
} | ||
|
||
# The transforms we will track throughout the flow | ||
# These get calculated by hand, and validate the transformations applied | ||
# Current implementation applies LHS Matrix multiplication of translation, | ||
# then euler rotation, then scale, in that order. | ||
# Final Result can be found using http://matrix.reshish.com/multCalculation.php | ||
# Translation Matrix: | ||
# For a translation <x, y, z>, the corresponding matrix is: | ||
# [1.0, 0.0, 0.0, x.0, | ||
# 0.0, 1.0, 0.0, y.0, | ||
# 0.0, 0.0, 1.0, z.0, | ||
# 0.0, 0.0, 0.0, 1.0] | ||
# Rotation Matrix: | ||
# For a rotation of theta degrees about the vector <x, y, z>, the rotation | ||
# matrix can be found using https://www.andre-gaschler.com/rotationconverter/ | ||
# Scale Matrix: | ||
# For a scale <x, y, z>, the corresponding matrix is: | ||
# [x.0, 0.0, 0.0, 0.0, | ||
# 0.0, y.0, 0.0, 0.0, | ||
# 0.0, 0.0, z.0, 0.0, | ||
# 0.0, 0.0, 0.0, 1.0] | ||
test_transform = [1.0, 0.0, 0.0, 0.0, | ||
0.0, 1.0, 0.0, 0.0, | ||
0.0, 0.0, 1.0, 0.0, | ||
0.0, 0.0, 0.0, 1.0] | ||
|
||
updated_test_transform = [2.0, 0.0, 0.0, 2.0, | ||
0.0, 1.0806046, -1.682942, -0.6023374, | ||
0.0, 1.682942, 1.0806046, 2.7635466, | ||
0.0, 0.0, 0.0, 1.0] | ||
|
||
# Object data represented through each piece of the flow | ||
test_data = { | ||
"key": "", | ||
"name": "basicTestObject", | ||
"type": "basicTestType", | ||
"subtype": "basicTestSubtype", | ||
"owner": "basicTestOwner", | ||
"scene": "basicFlowName", | ||
"translation": [0.0, 0.0, 0.0], | ||
"euler_rotation": [0.0, 1.0, 0.0, 0.0], | ||
"scale": [1.0, 1.0, 1.0], | ||
"assets": ["basicTestAsset"] | ||
} | ||
|
||
updated_test_data = { | ||
"key": "", | ||
"name": "basicTestObject", | ||
"type": "Mesh", | ||
"subtype": "Cube", | ||
"owner": "Alex", | ||
"scene": "basicFlowName", | ||
"translation": [1.0, 1.0, 1.0], | ||
"euler_rotation": [1.0, 1.0, 0.0, 0.0], | ||
"scale": [2.0, 2.0, 2.0], | ||
"assets": ["anotherAsset"] | ||
} | ||
|
||
def execute_udp_flow(sock, udp_ip, udp_port, aesel_addr, test_data, | ||
test_transform, updated_test_data, updated_test_transform): | ||
# Send the UDP Message | ||
sock.sendto(json.dumps(updated_test_data), (udp_ip, udp_port)) | ||
time.sleep(1) | ||
# Validate that the update went through correctly | ||
r = requests.get(aesel_addr + '/v1/scene/' + test_scene_data['name'] + '/object/' + updated_test_data['name']) | ||
assert(r.status_code == requests.codes.ok) | ||
parsed_json = r.json() | ||
if parsed_json is not None: | ||
for i in range(0,16): | ||
logging.debug("Validating Transform element: %s" % i) | ||
assert(parsed_json["transform"][i] - updated_test_transform[i] < 0.01) | ||
|
||
|
||
# Execute the actual tests | ||
def execute_main(): | ||
# Grab the global pieces of data | ||
global test_data | ||
global test_transform | ||
global updated_test_data | ||
global updated_test_transform | ||
global log_file | ||
global log_level | ||
global udp_ip | ||
global udp_port | ||
global aesel_addr | ||
|
||
logging.basicConfig(filename=log_file, level=log_level) | ||
|
||
# Connect to UDP Socket | ||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||
logging.debug("Connected to UDP Socket") | ||
|
||
# Create a Scene and Object through the HTTP API | ||
r = requests.post(aesel_addr + '/v1/scene/' + test_scene_data['name'], json=test_scene_data) | ||
assert(r.status_code == requests.codes.ok) | ||
response_json = r.json() | ||
test_scene_data['key'] = response_json['key'] | ||
r = requests.post(aesel_addr + '/v1/scene/' + test_scene_data['name'] + "/object/" + test_data['name'], json=test_data) | ||
assert(r.status_code == requests.codes.ok) | ||
response_json = r.json() | ||
test_data['key'] = response_json['key'] | ||
updated_test_data['key'] = response_json['key'] | ||
|
||
# Execute each test with a deep copy of the data, so that it stays | ||
# independent through each test | ||
execute_udp_flow(sock, udp_ip, udp_port, aesel_addr, | ||
copy.deepcopy(test_data), | ||
copy.deepcopy(test_transform), | ||
copy.deepcopy(updated_test_data), | ||
copy.deepcopy(updated_test_transform)) | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) > 1: | ||
execute_main(sys.argv[1]) | ||
else: | ||
execute_main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
src/main/java/adrestia/controller/obj3/UdpController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
Apache2 License Notice | ||
Copyright 2017 Alex Barry | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package adrestia; | ||
|
||
import com.fasterxml.jackson.core.JsonGenerationException; | ||
import com.fasterxml.jackson.databind.JsonMappingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
import java.net.DatagramPacket; | ||
import java.net.DatagramSocket; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
|
||
import org.springframework.boot.ApplicationArguments; | ||
import org.springframework.boot.ApplicationRunner; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* A Service which exposes Object Overwrites on a UDP port. | ||
* Implements the Application Runner interface so that the port | ||
* gets opened after config values and beans have been autowired. | ||
*/ | ||
@Component | ||
public class UdpController implements ApplicationRunner { | ||
@Value("${server.udp.port}") | ||
private int port; | ||
private DatagramSocket socket; | ||
|
||
// Object Controller Logger | ||
private static final Logger logger = | ||
LogManager.getLogger("adrestia.UdpController"); | ||
|
||
// DAO Object allowing access to object data | ||
@Autowired | ||
ObjectDao objData; | ||
|
||
/** | ||
* Start listening on the UDP Socket. | ||
*/ | ||
@Override | ||
public void run(ApplicationArguments args) throws Exception { | ||
logger.info("Starting UDP API on port" + this.port); | ||
// Define our runnable to execute on the background thread | ||
int updPort = this.port; | ||
Runnable r = new Runnable() { | ||
@Override | ||
public void run() { | ||
try { | ||
socket = new DatagramSocket(updPort); | ||
} catch (Exception e) { | ||
logger.error("Error opening UDP Socket: ", e); | ||
return; | ||
} | ||
ObjectMapper mapper = new ObjectMapper(); | ||
while (true) { | ||
byte[] buf = new byte[512]; | ||
DatagramPacket packet = new DatagramPacket(buf, buf.length); | ||
try { | ||
socket.receive(packet); | ||
} catch (Exception e) { | ||
logger.error("Error reading data from UDP Socket: ", e); | ||
return; | ||
} | ||
String received | ||
= new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8); | ||
logger.info("Received UDP Request for Object Overwrite"); | ||
// Send the update | ||
ObjectDocument inpObject; | ||
try { | ||
inpObject = mapper.readValue(received, ObjectDocument.class); | ||
} catch (Exception e) { | ||
logger.error("Error parsing data from UDP Socket: ", e); | ||
return; | ||
} | ||
ObjectList clymanResponse = objData.overwrite(inpObject); | ||
// If we have a successful response, then we pull the first value | ||
if (clymanResponse.getNumRecords() <= 0 | ||
|| clymanResponse.getErrorCode() != 100) { | ||
logger.debug("Failure Registered. Clyman Response Error Code and Length:"); | ||
logger.debug(clymanResponse.getNumRecords()); | ||
logger.debug(clymanResponse.getErrorCode()); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
// Start the thread to listen on the socket | ||
new Thread(r).start(); | ||
} | ||
|
||
/** | ||
* Default empty UdpController constructor. | ||
*/ | ||
public UdpController() { | ||
super(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.