API 요청
PUT /devices/{deviceID}
payload
{
"tags" : [
{
"attrName": "temperature",
"attrValue": "27.0"
},
{
"attrName": "LED",
"attrValue": "OFF"
}
]
}
API 응답
생성된 UpdateDeviceLambdaJavaProject의 pom.xml 파일을 열고, <dependencies> 태그 안에 aws-java-sdk-iot에 대한 의존성을 추가한 후에, 파일을 저장합니다.
<dependencies>
...
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-iot</artifactId>
</dependency>
</dependencies>
Eclipse 프로젝트 탐색기를 사용하여 UpdateDeviceLambdaJavaProject 프로젝트에서 UpdateDeviceHandler.java를 열고, 다음 코드로 바꿉니다.
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.amazonaws.services.iotdata.AWSIotData;
import com.amazonaws.services.iotdata.AWSIotDataClientBuilder;
import com.amazonaws.services.iotdata.model.UpdateThingShadowRequest;
import com.amazonaws.services.iotdata.model.UpdateThingShadowResult;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.fasterxml.jackson.annotation.JsonCreator;
public class UpdateDeviceHandler implements RequestHandler<Event, String> {
@Override
public String handleRequest(Event event, Context context) {
context.getLogger().log("Input: " + event);
AWSIotData iotData = AWSIotDataClientBuilder.standard().build();
String payload = getPayload(event.tags);
UpdateThingShadowRequest updateThingShadowRequest =
new UpdateThingShadowRequest()
.withThingName(event.device)
.withPayload(ByteBuffer.wrap(payload.getBytes()));
UpdateThingShadowResult result = iotData.updateThingShadow(updateThingShadowRequest);
byte[] bytes = new byte[result.getPayload().remaining()];
result.getPayload().get(bytes);
String resultString = new String(bytes);
return resultString;
}
private String getPayload(ArrayList<Tag> tags) {
String tagstr = "";
for (int i=0; i < tags.size(); i++) {
if (i != 0) tagstr += ", ";
tagstr += String.format("\"%s\" : \"%s\"", tags.get(i).tagName, tags.get(i).tagValue);
}
return String.format("{ \"state\": { \"desired\": { %s } } }", tagstr);
}
}
class Event {
public String device;
public ArrayList<Tag> tags;
public Event() {
tags = new ArrayList<Tag>();
}
}
class Tag {
public String tagName;
public String tagValue;
@JsonCreator
public Tag() {
}
public Tag(String n, String v) {
tagName = n;
tagValue = v;
}
}
Lambda에 함수를 업로드하려면, Eclipse 코드 창에서 마우스 오른쪽 버튼을 클릭하고 [AWS Lambda]와 [Upload function to AWS Lambda]를 차례대로 선택합니다.
[Select Target Lambda Function] 페이지에서 사용할 AWS 리전을 선택합니다. 이 리전은 Amazon S3 버킷에 대해 선택한 리전과 동일해야 합니다.
새 Lambda 함수 생성을 선택하고 함수 이름(예: UpdateDeviceFunction)을 입력한 후, [Next]를 선택합니다.
함수 구성(Function Configuration 페이지에서 대상 Lambda 함수에 대한 설명을 입력하고 함수에서 사용할 IAM 역할 선택합니다.
Lambda 함수 코드를 저장할 S3 버킷을 선택합니다. 만약 새로운 Amazon S3 버킷을 생성하고 싶은 경우에는 생성 버튼을 클릭하고 버킷 생성 대화 상자에 버킷 이름을 입력합니다.
Finish를 선택하여 Lambda 함수를 AWS에 업로드합니다.
Lambda 함수를 실행하려면, Eclipse 코드 창에서 마우스 오른쪽 버튼을 클릭하고 AWS Lambda를 선택한 후 Run Function on AWS Lambda(AWS Lambda에서 함수 실행)를 선택합니다.
Enter the JSON input for your function이 선택된 상태에서 입력 창에 다음 입력 문자열을 입력한다.
tags 속성: 변경할 사물의 태그 객체 배열 (이름과 값으로 정의됨)
{
"device": "MyMKRWiFi1010",
"tags" : [
{
"tagName": "temperature",
"tagValue": "25.2"
},
{
"tagName": "LED",
"tagValue": "ON"
}
]
}
Invoke 버튼을 클릭한 후, Eclipse Console 창에 다음과 같은 결과가 출력되는 지 확인합니다.
Invoking function...
==================== FUNCTION OUTPUT ====================
"{\"state\":{\"desired\":{\"temperature\":\"25.2\",\"LED\":\"ON\"}},\"metadata\":{\"desired\":{\"temperature\":{\"timestamp\":1575212613},\"LED\":{\"timestamp\":1575212613}}},\"version\":4454,\"timestamp\":1575212613}"
==================== FUNCTION LOG OUTPUT ====================
START RequestId: ffbcd4f1-e3c5-483d-97a3-1c9b4685dd5a Version: $LATEST
Input: com.amazonaws.lambda.demo.Event@6e0e048aEND RequestId: ffbcd4f1-e3c5-483d-97a3-1c9b4685dd5a
REPORT RequestId: ffbcd4f1-e3c5-483d-97a3-1c9b4685dd5a Duration: 7266.17 ms Billed Duration: 7300 ms Memory Size: 512 MB Max Memory Used: 140 MB Init Duration: 382.85 ms
다음 단계는 API Gateway를 통해 들어오는 클라이언트의 입력을 Lambda 함수에 전달하기 위해서 클라이언트의 입력을 Lambda 함수의 입력으로 매핑하는 과정에 대해서 진행합니다.
모델을 정의하려면 API Gateway 기본 탐색 창에서 API 아래에 있는 모델을 선택한 다음 생성을 선택합니다.
다음 스키마 정의를 Model schema(모델 스키마) 편집기에 복사합니다.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "UpdateDeviceInput",
"type" : "object",
"properties" : {
"tags" : {
"type": "array",
"items": {
"type": "object",
"properties" : {
"tagName" : { "type" : "string"},
"tagValue" : { "type" : "string"}
}
}
}
}
}
모델 생성을 선택하여 입력 모델 정의를 완료합니다.
리소스를 선택하고 /{device} PUT 메서드를 선택하고 메서드 요청(Method Request)을 선택하고 요청 본문(Request body)을 확장합니다. 모델 추가를 선택합니다. 콘텐츠 유형에 application/json을 입력합니다. 모델 이름에서 UpdateDeviceInput을 선택합니다. 확인 표시 아이콘을 선택하여 설정을 저장합니다.
/{device} PUT 메서드를 선택하고 통합 요청(Integration Request)을 선택하여 본문 매핑 템플릿을 설정합니다.
매핑 템플릿(Mapping Templates) 섹션을 확장합니다. 매핑 템플릿 추가(Add mapping template)를 선택합니다. Content-Type에 application/json을 입력합니다. 확인 표시 아이콘을 선택하여 설정을 저장합니다.
요청 본문 패스스루(Request body passthrough)에 권장되는 정의된 템플릿이 없는 경우(권장)를 선택합니다.
템플릿 생성(Generate template)에서 UpdateDeviceInput을 선택하여 초기 매핑 템플릿을 생성합니다. 이 옵션은 처음부터 매핑 템플릿을 작성할 필요가 없는 모델 스키마를 정의했기 때문에 사용할 수 있습니다.
매핑 템플릿 편집기에 생성된 매핑 스크립트를 다음과 바꿉니다.
#set($inputRoot = $input.path('$'))
{
"device": "$input.params('device')",
"tags" : [
##TODO: Update this foreach loop to reference array from input json
#foreach($elem in $inputRoot.tags)
{
"tagName" : "$elem.tagName",
"tagValue" : "$elem.tagValue"
}
#if($foreach.hasNext),#end
#end
]
}
저장을 선택합니다.
/devices/{device} – PUT – 메소드 실행 창으로 이동하여, 클라이언트 부분의 테스트를 클릭합니다.
{device} 경로에 본인이 만든 사물 이름(예, MyMKRWiFi1010)을 입력합니다.
요청 본문에 아래와 같은 내용을 입력합니다.
{
"tags" : [
{
"tagName": "temperature",
"tagValue": "25.2"
},
{
"tagName": "LED",
"tagValue": "ON"
}
]
}
테스트버튼을 클릭하여 다음과 같은 결과가 나오는 지 확인합니다.
REST API 리소스에 대해 CORS 지원 활성화
2단계를 완료하면 API를 생성했지만 아직 실제로 사용할 수는 없습니다. 배포해야 하기 때문입니다.