About me
home
Portfolio
home
👒

5 Historical data of Custom FIWARE 실습

이전 4번 FIWARE with Python까지 진행했고 충분히 이해를 하고있다면 한가지 이상한 점을 발견했을 것이다. 바로 데이터를 전송하는 endpoint가 QuantumLeap가 아니라는 점이다. 발견 못했어도 괜찮다. FIWARE는 어렵지 않지만 처음 개념을 이해하는게 중요하다. 차근차근 나아가는 것이니 지금까지 FIWARE 동작에 대해 이해했다면 복습과 같은 느낌으로, 어렵다고 생각한다면 조금 더 집중해서 진행해보자.
지금까지 전체적으로 FIWARE에 대한 이해에 집중했다면 이번 매뉴얼부터 데이터를 QuantumLeap로 보내 historical data에 대한 처리를 진행해보자.
사용 모듈을 다시 떠올려보자.
포트 정보
Orion_LD
1026
IOTA
IOTA_NORTH_PORT: 4041
IOTA_SOUTH_PORT: 7896
MongoDB
27017
QuantumLeap
8668
redis: 6379
crate: 4200(admin)
ld-context
3004→80
grafana
3003→3000
1.
로컬 서비스 프로비저닝
curl -iX POST 'http://localhost:4041/iot/services' \ -H 'fiware-service: youngCustomDevice' \ -H 'fiware-servicepath: /escTest' \ -H 'Content-Type: application/json' \ --data-raw '{ "services": [ { "apikey": "rtestaeyoungtest0818", "cbroker": "http://orion:1026", "entity_type": "Device", "timezone": "Asia/Seoul", "resource": "/iot/d", "attributes": [ { "object_id": "t", "type": "Property", "name": "acoustic", "metadata": { "unitCode": {"type": "Property", "value": "PER" }} }, { "object_id": "c1", "name": "class1", "type": "Float" }, { "object_id": "c2", "name": "class2", "type": "Float" }, { "object_id": "c3", "name": "class3", "type": "Float" }, { "object_id": "c4", "name": "class4", "type": "Float" }, { "object_id": "c5", "name": "class5", "type": "Float" }, { "object_id": "c6", "name": "class6", "type": "Float" }, { "object_id": "c7", "name": "class7", "type": "Float" }, { "object_id": "c8", "name": "class8", "type": "Float" }, { "object_id": "c9", "name": "class9", "type": "Float" }, { "object_id": "c10", "name": "class10", "type": "Float" }, { "object_id": "gps", "name": "location", "type": "geo:point" } ], "static_attributes": [ { "name": "category", "type": "Property", "value": "sensor" }, { "name": "supportedProtocol", "type": "Property", "value": "ul20" } ] } ] }'
JavaScript
복사
일단 서비스를 프로비져닝하고 확인한다.
curl -X GET \ 'http://localhost:4041/iot/services' \ -H 'fiware-service: youngCustomDevice' \ -H 'fiware-servicepath: /escTest' | python3 -m json.tool
JavaScript
복사
b.
Device 프로비져닝
Raspberry Pi에서 디바이스를 등록하자
<Raspberry Pi> 에서 전송 curl -L -X POST 'http://172.16.63.209:4041/iot/devices' \ -H 'fiware-service: youngcustomdevice' \ -H 'fiware-servicepath: /escTest' \ -H 'Content-Type: application/json' \ --data-raw '{ "devices": [ { "device_id": "acoustic01", "entity_name": "urn:ngsi-ld:Device:acoustic01", "entity_type": "Device", "timezone": "Asia/Seoul", "attributes": [ { "object_id": "t", "name": "acoustic", "type": "Property", "metadata": { "unitCode": { "type": "Property", "value": "PER" } } } ], "static_attributes": [ {"name": "category", "type":"Property", "value": ["sensor"]}, {"name": "supportedProtocol", "type": "Property", "value": ["ul20"]} ] } ] }'
JavaScript
복사
아래 코드를 서버에서 실행해 확인한다.
curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/?type=Device' \ -H 'NGSILD-Tenant: youngcustomdevice' \ -H 'NGSILD-Path: /escTest' \ -H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' | python3 -m json.tool
JavaScript
복사
c.
Setting up subscriptions
Subscription 등록한다.
curl -L -X POST 'http://localhost:1026/ngsi-ld/v1/subscriptions/' \ -H 'Content-Type: application/ld+json' \ -H 'NGSILD-Tenant: youngCustomDevice' \ --data-raw '{ "description": "Classification result from Pi", "type": "Subscription", "entities": [{"type": "Device"}], "watchedAttributes": ["class1", "class2", "class3", "class4", "class5", "class6", "class7", "class8", "class9", "class10"], "notification": { "attributes": ["class1", "class2", "class3", "class4", "class5", "class6", "class7", "class8", "class9", "class10"], "format": "normalized", "endpoint": { "uri": "http://quantumleap:8668/v2/notify", "accept": "application/json" } }, "@context": "http://context/ngsi-context.jsonld" }'
JavaScript
복사
정상 등록을 아래 코드로 확인하자.
curl -X GET \ 'http://localhost:1026/ngsi-ld/v1/subscriptions/' \ -H 'NGSILD-Tenant: youngCustomDevice' | python3 -m json.tool
JavaScript
복사
아래와 같은 결과가 나올것이다.
{ "id": "urn:ngsi-ld:Subscription:36ccb62c-1f61-11ed-87a7-0242ac120006", "type": "Subscription", "description": "Classification result from Pi", "entities": [ { "type": "Device" } ], "watchedAttributes": [ "class1", "class2", "class3", "class4", "class5", "class6", "class7", "class8", "class9", "class10" ], "status": "active", "isActive": true, "notification": { "attributes": [ "class1", "class2", "class3", "class4", "class5", "class6", "class7", "class8", "class9", "class10" ], "format": "normalized", "endpoint": { "uri": "http://quantumleap:8668/v2/notify", "accept": "application/json" }, "status": "ok" } }
JavaScript
복사
확인을 위해 일단 데이터를 추가하자. 아래 코드를 라즈베리파이에서 실행해 로컬 서버로 데이터를 전송하자. 물론 아래 예제에 나온 코드에서 ip주소는 자신이 구축한 서버의 주소로 설정해야한다.
이때 값을 여러개로 바꾸면서 서로 다른 데이터를 5번 정도 전송하자.
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0818&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.2|c2|0.4|c3|0.6|c4|0.8|c5|1.0|c6|1.2|c7|1.4|c8|1.6|c9|1.8|c10|2.0'
JavaScript
복사
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0818&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.3|c2|0.2|c3|0.5|c4|0.7|c5|0.8|c6|1.4|c7|1.2|c8|1.4|c9|1.4|c10|2.5'
JavaScript
복사
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0818&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.7|c2|0.5|c3|0.4|c4|0.5|c5|0.4|c6|1.6|c7|1.1|c8|1.0|c9|1.3|c10|2.0'
JavaScript
복사
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0818&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.8|c2|0.6|c3|0.3|c4|0.4|c5|0.5|c6|1.5|c7|1.0|c8|1.1|c9|1.1|c10|1.8'
JavaScript
복사
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0818&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.5|c2|0.8|c3|0.1|c4|0.5|c5|0.7|c6|1.0|c7|0.8|c8|1.2|c9|1.5|c10|1.5'
JavaScript
복사
이제 QuantumLeap에서 들어온 데이터가 정상적으로 crate db에 들어갔는지 확인해보자.
Crate DB 접근
Crate db 접근을 위해서는 localhost:4200 으로 들어간다.
이렇게 나오면 정상적으로 접근한 것이다.
여기서 메뉴에 들어가 Tables에 들어간다.
이렇게 우리가 원하는 class가 1부터 10까지 잘 들어가있음을 볼 수 있다.
구체적인 값을 확인해보자. Schema 위에 Query TABLE이란 버튼을 눌러 들어간다.
자동으로 쿼리문을 만들어준다. 원한다면 CRUD action들을 공부해 직접 쿼리를 진행해도 좋다. 기본으로 출력하면 엉망진창 순서다. 따라서 쿼리에 시간 기준 내림차순으로 출력하도록 하자. 이렇게 기본 쿼리에 추가를 원한다면 crate.io 에 방문해 Crate DB의 doc을 확인해서 추가하면 된다.
SELECT "entity_id","entity_type","time_index","fiware_servicepath","__original_ngsi_entity__","class1","class2","class3","class4","class5","class6","class7","class8","class9","class10" FROM "doc"."etdevice" ORDER BY "time_index" DESC LIMIT 100;
JavaScript
복사
위 쿼리문을 넣고 우측 아래 EXECUTE QUERY를 누르자.
먼저 우리가 등록한 Raspberry Pi device인 acoustic01이 entity id로 설정됨을 확인할 수 있다.
또한 등록한 시간도 함께 나온다(우측 시간은 Zulu time). Zulu time 기준으로 내림차순 정렬되어 나옴을 알 수 있다.
나는 테스트 과정에서 class{num} 별로 0.{num}, 0.{num}{num} 이런 식으로 5번을 넣었다.
입력한 value 역시 정상적으로 들어가 있음을 확인할 수 있다.

Visualizing Crate DB with Grafana

마지막 작업이다.
Grafana의 주소는 다음과 같다. 들어가서 로그인하자. localhost:3003
default id, pw는 둘 다 admin이다.
로그인 후 Data source를 지정해줘야 한다. 좌측 configuration에서 data sources에 들어가서 새로 생성하자.
우리는 CrateDB 를 data source로 하니 아래 그림과 같이 설정하자.
꼭 위 그림처럼 Database Connection OK가 나와야 한다.
다음으로는 우리가 지정한 Crate DB에서 원하는 Table과 Column을 지정해서 가져와야 한다. 좌측 + 버튼을 누르고 dashboard를 누르자. 그리고 add query를 누르고 아래 그림처럼 설정하자.
우리의 table 이름은 etdevice 이니까(Crate io에서 확인 가능) doc.etdevice로 설정한다. time column은 time index, 나머지는 query와 동일하게 select해주면 된다. 내림차순 설정을 할 필요도 없이 시간은 자동으로 입력되니 걱정하지 말자.
이렇게 시간 순서로 우리가 입력한 값이 시각화됨을 알 수 있다.
class 별 입력 값을 이렇게 확인 가능하다.
최종적으로 할 일은 World map에서 우리가 설정한 값을 확인하는 것이다. 다만 현재 데이터를 입력하는 과정에서 location은 따로 설정하지 않았었다. 따라서 해당 과정은 이어서 새로 진행해보자.

전부 정상적으로 출력됨 (23.01.26 김영준)

POST 5번을 너무 빨리해버려서 간격이 촘촘하다